Created
July 13, 2023 05:33
-
-
Save octalmage/0dbc9bd7a99d17b9bad57e555820f750 to your computer and use it in GitHub Desktop.
War for JAX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class WarContract { | |
init({ rng }) { | |
storage.put("rng", rng); | |
storage.put("id", 1); | |
} | |
can_update() { | |
return blockchain.requireAuth(blockchain.contractAdmin()); | |
} | |
startGame() { | |
blockchain.deposit(1000000); | |
const game = { | |
player1: tx.publisher, | |
player1Deck: [], | |
player2: null, | |
player2Deck: [], | |
inProgress: true, | |
commit: "", | |
}; | |
const id = storage.get("id"); | |
storage.mapPut("games", id, JSON.stringify(game)); | |
storage.put("id", BigNumber(id).plus(1)); | |
return id; | |
} | |
joinGame({ id }) { | |
const from = tx.publisher; | |
const gameStr = storage.mapGet("games", id); | |
if (!gameStr) { | |
throw new Error("No such game exists"); | |
} | |
const game = JSON.parse(gameStr); | |
if (game.player2 !== null) { | |
throw new Error("Game already has two players"); | |
} | |
const commit = blockchain.call(storage.get("rng"), "commit"); | |
game.commit = commit; | |
blockchain.deposit(1000000); // Accept 1000000 tokens | |
game.player2 = from; | |
storage.mapPut("games", id, JSON.stringify(game)); | |
} | |
deal({ id }) { | |
const gameStr = storage.mapGet("games", id); | |
if (!gameStr) { | |
throw new Error("No such game exists"); | |
} | |
const game = JSON.parse(gameStr); | |
if (game.player2 === null) { | |
throw new Error("A second player is needed to play"); | |
} | |
if (game.player1Deck.length !== 0) { | |
throw new Error("Cards have already been dealt"); | |
} | |
const randomNumber = blockchain.call(storage.get("rng"), "reveal", { | |
id: game.commit, | |
range: 0, | |
}); | |
const deck = this._shuffle(randomNumber); | |
game.player2Deck = deck.slice(deck.length / 2); | |
game.player1Deck = deck.slice(0, deck.length / 2); | |
storage.mapPut("games", id, JSON.stringify(game)); | |
} | |
play({ id }) { | |
const gameStr = storage.mapGet("games", id); | |
if (!gameStr) { | |
throw new Error("You must join a game before playing a turn"); | |
} | |
const game = JSON.parse(gameStr); | |
if (!game.inProgress) { | |
throw new Error("Game complete"); | |
} | |
let result; | |
while (game.inProgress) { | |
let playerDeck, opponentDeck; | |
if (game.player1 === tx.publisher) { | |
playerDeck = game.player1Deck; | |
opponentDeck = game.player2Deck; | |
} else if (game.player2 === tx.publisher) { | |
playerDeck = game.player2Deck; | |
opponentDeck = game.player1Deck; | |
} else { | |
throw new Error("You're not part of this game"); | |
} | |
const playerCard = playerDeck.shift(); | |
const opponentCard = opponentDeck.shift(); | |
if (playerCard > opponentCard) { | |
playerDeck.push(playerCard, opponentCard); | |
} else if (opponentCard > playerCard) { | |
opponentDeck.push(opponentCard, playerCard); | |
} | |
if (playerDeck.length === 0 || opponentDeck.length === 0) { | |
game.inProgress = false; | |
const winner = playerDeck.length === 0 ? game.player2 : game.player1; | |
// Payout 2000000 tokens to the game winner | |
blockchain.withdraw(winner, 2000000); | |
result = playerDeck.length === 0 ? "You lose the game!" : "You win the game!"; | |
} | |
} | |
storage.mapPut("games", id, JSON.stringify(game)); | |
return result; | |
} | |
_shuffle(entropy) { | |
let deck = []; | |
// Generate deck array using a loop | |
for (let i = 0; i < 52; i++) { | |
deck[i] = i + 1; | |
} | |
// Expand randomSeed into 52 random numbers out of 100. | |
const randomSeed = BigNumber(entropy, 16); | |
const expandedValues = []; | |
for (let i = 0; i < deck.length; i++) { | |
const hash = crypto.sha256(randomSeed.plus(i).toString(16)); | |
expandedValues[i] = BigNumber(hash, 16).mod(100).toNumber(); | |
} | |
// Sort the cards based on the 52 random numbers. | |
deck.sort((a, b) => { | |
const aIndex = expandedValues[a - 1]; | |
const bIndex = expandedValues[b - 1]; | |
if (aIndex < bIndex) { | |
return -1; | |
} | |
if (aIndex > bIndex) { | |
return 1; | |
} | |
return 0; | |
}); | |
return deck; | |
} | |
} | |
module.exports = WarContract; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment