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)