templates.nimLift

  1# Multiple Nim Games - Example for illustrative purposes only.
  2
  3# Instead of defining a single NimGame per contract,
  4# we define a contract for multiple games.
  5
  6import smartpy as sp
  7
  8
  9@sp.module
 10def main():
 11    def rangeMap(params):
 12        (a, b) = params
 13        r = {}
 14        for i in range(a, b):
 15            r[i - a] = i
 16        return r
 17
 18    class NimMultipleGame(sp.Contract):
 19        def __init__(self):
 20            self.data.games = {}
 21            self.data.nbGames = 0
 22
 23        @sp.entrypoint
 24        def build(self, params):
 25            size = params.size
 26            bound = params.bound
 27            lastWins = False
 28            game = sp.record(
 29                deck=rangeMap((1, size + 1)),
 30                size=size,
 31                nextPlayer=1,
 32                claimed=False,
 33                winner=0,
 34                bound=bound,
 35                lastWins=lastWins,
 36            )
 37            self.data.games[self.data.nbGames] = game
 38            self.data.nbGames += 1
 39
 40        @sp.entrypoint
 41        def remove(self, params):
 42            gameId = params.gameId
 43            game = self.data.games[gameId]
 44            cell = params.cell
 45            k = params.k
 46            assert 0 <= cell
 47            assert cell < game.size
 48            assert 1 <= k
 49            assert k <= game.bound
 50            assert k <= game.deck[cell]
 51            game.deck[cell] = game.deck[cell] - k
 52            game.nextPlayer = 3 - game.nextPlayer
 53            self.data.games[gameId] = game
 54
 55        @sp.entrypoint
 56        def claim(self, params):
 57            gameId = params.gameId
 58            game = self.data.games[gameId]
 59            assert sum(game.deck.values()) == 0
 60            game.claimed = True
 61            if game.lastWins:
 62                game.winner = 3 - game.nextPlayer
 63            else:
 64                game.winner = game.nextPlayer
 65            self.data.games[gameId] = game
 66
 67
 68# Tests
 69@sp.add_test()
 70def test():
 71    scenario = sp.test_scenario("NimGames", main)
 72    # define a contract
 73    c1 = main.NimMultipleGame()
 74    # show its representation
 75    scenario.h1("Nim games")
 76    scenario.h2("Contract")
 77    scenario += c1
 78    scenario.h2("First: define a few games with build")
 79    for size in range(5, 8):
 80        c1.build(size=size, bound=2)
 81    scenario.h2("Message execution")
 82    scenario.h3("A first move")
 83    c1.remove(gameId=0, cell=2, k=1)
 84    scenario.h3("A second move")
 85    c1.remove(gameId=0, cell=2, k=2)
 86    scenario.h3("An illegal move")
 87    c1.remove(gameId=0, cell=2, k=1, _valid=False)
 88    scenario.h3("Another illegal move")
 89    c1.claim(gameId=1, _valid=False)
 90    scenario.h3("A third move")
 91    c1.remove(gameId=0, cell=1, k=2)
 92    scenario.h3("More moves")
 93    c1.remove(gameId=0, cell=0, k=1)
 94    c1.remove(gameId=0, cell=3, k=1)
 95    c1.remove(gameId=0, cell=3, k=1)
 96    c1.remove(gameId=0, cell=3, k=2)
 97    c1.remove(gameId=0, cell=4, k=1)
 98    c1.remove(gameId=0, cell=4, k=2)
 99    scenario.h3("A failed attempt to claim")
100    c1.claim(gameId=0, _valid=False)
101    scenario.h3("A last removal")
102    c1.remove(gameId=0, cell=4, k=2)
103    scenario.h3("And a final claim")
104    c1.claim(gameId=0)