templates.tictactoeFactory

  1# TicTacToe Factory - Example for illustrative purposes only.
  2
  3import smartpy as sp
  4
  5
  6@sp.module
  7def main():
  8    class TicTacToe(sp.Contract):
  9        def __init__(self, admin):
 10            self.data.admin = admin
 11            self.data.paused = False
 12            self.data.boards = sp.big_map()
 13            self.data.metaData = {}
 14
 15        @sp.entrypoint
 16        def build(self, params):
 17            sp.cast(params.game, sp.string)
 18            assert not self.data.paused or sp.sender == self.data.admin
 19            assert not self.data.boards.contains(params.game)
 20            self.data.boards[params.game] = sp.record(
 21                player1=params.player1,
 22                player2=params.player2,
 23                nbMoves=0,
 24                winner=0,
 25                draw=False,
 26                deck={
 27                    0: {0: 0, 1: 0, 2: 0},
 28                    1: {0: 0, 1: 0, 2: 0},
 29                    2: {0: 0, 1: 0, 2: 0},
 30                },
 31                nextPlayer=1,
 32                metaData={},
 33            )
 34
 35        @sp.entrypoint
 36        def deleteGame(self, params):
 37            assert sp.sender == self.data.admin
 38            del self.data.boards[params.game]
 39
 40        @sp.entrypoint
 41        def setPause(self, params):
 42            assert sp.sender == self.data.admin
 43            self.data.paused = params
 44
 45        @sp.entrypoint
 46        def setMetaData(self, params):
 47            assert sp.sender == self.data.admin
 48            sp.cast(params.name, sp.string)
 49            sp.cast(params.value, sp.string)
 50            self.data.metaData[params.name] = params.value
 51
 52        @sp.entrypoint
 53        def setGameMetaData(self, params):
 54            game = self.data.boards[params.game]
 55            assert sp.sender == self.data.admin or sp.sender == game.player1
 56            sp.cast(params.name, sp.string)
 57            sp.cast(params.value, sp.string)
 58            game.metaData[params.name] = params.value
 59
 60        @sp.entrypoint
 61        def play(self, params):
 62            assert not self.data.paused
 63            game = self.data.boards[params.game]
 64            assert game.winner == 0 and not game.draw
 65            assert params.i >= 0 and params.i < 3
 66            assert params.j >= 0 and params.j < 3
 67            assert params.move == game.nextPlayer
 68            assert game.deck[params.i][params.j] == 0
 69            if params.move == 1:
 70                assert sp.sender == game.player1
 71            else:
 72                assert sp.sender == game.player2
 73            game.nextPlayer = 3 - game.nextPlayer
 74            game.deck[params.i][params.j] = params.move
 75            game.nbMoves += 1
 76            game.winner = self.checkLine(
 77                sp.record(winner=game.winner, line=game.deck[params.i])
 78            )
 79            game.winner = self.checkLine(
 80                sp.record(
 81                    winner=game.winner,
 82                    line={
 83                        0: game.deck[0][params.j],
 84                        1: game.deck[1][params.j],
 85                        2: game.deck[2][params.j],
 86                    },
 87                )
 88            )
 89            game.winner = self.checkLine(
 90                sp.record(
 91                    winner=game.winner,
 92                    line={0: game.deck[0][0], 1: game.deck[1][1], 2: game.deck[2][2]},
 93                )
 94            )
 95            game.winner = self.checkLine(
 96                sp.record(
 97                    winner=game.winner,
 98                    line={0: game.deck[0][2], 1: game.deck[1][1], 2: game.deck[2][0]},
 99                )
100            )
101            if game.nbMoves == 9 and game.winner == 0:
102                game.draw = True
103            self.data.boards[params.game] = game
104
105        @sp.private()
106        def checkLine(self, winner, line):
107            winner_ = winner
108            if line[0] != 0 and line[0] == line[1] and line[0] == line[2]:
109                winner_ = line[0]
110            return winner_
111
112
113# Tests
114if "main" in __name__:
115
116    @sp.add_test()
117    def test():
118        # define a contract
119        admin = sp.test_account("Admin")
120        alice = sp.test_account("Alice")
121        bob = sp.test_account("Robert")
122
123        scenario = sp.test_scenario("TicTacToeFactory", main)
124        c1 = main.TicTacToe(admin.address)
125
126        scenario.h1("Tic-Tac-Toe Games")
127        # show its representation
128        scenario.h2("A sequence of interactions with a winner")
129        scenario += c1
130        scenario.h2("Message execution")
131        scenario.h3("Building a contract")
132
133        g1 = "game 1"
134        c1.build(game=g1, player1=alice.address, player2=bob.address)
135
136        scenario.h3("A first move in the center")
137        c1.play(game=g1, i=1, j=1, move=1, _sender=alice)
138
139        g2 = "game 2"
140        c1.build(game=g2, player1=alice.address, player2=bob.address)
141        c1.deleteGame(game=g2, _sender=admin)
142
143        c1.setMetaData(name="toto", value="titi", _sender=admin)
144
145        c1.setGameMetaData(game=g1, name="toto", value="titi", _sender=alice)
146        c1.setGameMetaData(game=g1, name="toto2", value="titi2", _sender=admin)