templates.nim

 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)