1# Nim Game, https://en.wikipedia.org/wiki/Nim - Example for illustrative purposes only.
2
3import smartpy as sp
4
5
6@sp.module
7def main():
8 def vector(xs):
9 m = {}
10 k = 0
11 for v in xs:
12 m[k] = v
13 k += 1
14 return m
15
16 class NimGame(sp.Contract):
17 def __init__(self, size, bound, winnerIsLast):
18 self.private.bound = bound
19 self.private.winnerIsLast = winnerIsLast
20 self.data.deck = vector(range(1, size + 1))
21 self.data.size = size
22 self.data.nextPlayer = 1
23 self.data.claimed = False
24 self.data.winner = 0
25
26 @sp.entrypoint
27 def remove(self, params):
28 assert params.cell >= 0
29 assert params.cell < self.data.size
30 assert params.k >= 1
31 with sp.match(self.private.bound):
32 with sp.case.Some as bound:
33 assert params.k <= bound
34 assert params.k <= self.data.deck[params.cell]
35 self.data.deck[params.cell] = self.data.deck[params.cell] - params.k
36 self.data.nextPlayer = 3 - self.data.nextPlayer
37
38 @sp.entrypoint
39 def claim(self, params):
40 assert sum(self.data.deck.values()) == 0
41 assert not self.data.claimed
42 self.data.claimed = True
43 if self.private.winnerIsLast:
44 self.data.winner = 3 - self.data.nextPlayer
45 else:
46 self.data.winner = self.data.nextPlayer
47 assert params.winner == self.data.winner
48
49
50# Tests
51if "main" in __name__:
52
53 @sp.add_test()
54 def test():
55 scenario = sp.test_scenario("Nim", main)
56 scenario.h1("Nim game")
57 # define a contract
58 c1 = main.NimGame(size=5, bound=sp.Some(2), winnerIsLast=False)
59 # show its representation
60 scenario.h2("Contract")
61 scenario += c1
62 scenario.h2("Message execution")
63 scenario.h3("A first move")
64 c1.remove(cell=2, k=1)
65 scenario.h3("A second move")
66 c1.remove(cell=2, k=2)
67 scenario.h3("An illegal move")
68 c1.remove(cell=2, k=1, _valid=False)
69 scenario.h3("Another illegal move")
70
71 c1.claim(winner=1, _valid=False)
72 scenario.h3("A third move")
73 c1.remove(cell=1, k=2)
74 scenario.h3("More moves")
75 c1.remove(cell=0, k=1)
76 c1.remove(cell=3, k=1)
77 c1.remove(cell=3, k=1)
78 c1.remove(cell=3, k=2)
79 c1.remove(cell=4, k=1)
80 c1.remove(cell=4, k=2)
81 scenario.h3("A failed attempt to claim")
82 c1.claim(winner=1, _valid=False)
83 scenario.h3("A last removal")
84 c1.remove(cell=4, k=2)
85 scenario.h3("And a final claim")
86 c1.claim(winner=1)
87 scenario.p("The winner is").show(c1.data.winner)