Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/dominoplayer.py
blob: 9d05c64f4c3ba5a9d720c137a317bdd5976f81a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
import logging
from gettext import gettext as _

from dominoview import Tile
from dominopiece import DominoPiece


class DominoPlayer:

    """
    Jugadores (automaticos o humanos) del domino
    """

    def __init__(self, game, number):
        self.number = number
        self.name = _('Player ')+str(self.number)
        self.game = game
        self._pieces = []
        self.order_piece_selected = 0
        self.playing = False
        self.color = None
        # se usa para saber si este usuario paso la ultima vuelta
        self.has_passed = False
        # where are displayed the pieces for this player
        self.pieces_y_position = self.game.table.bottom_limit

    def set_pieces(self, pieces):
        self._pieces = pieces
        for piece in self._pieces:
            piece.player = self
            piece.state = DominoPiece.PIECE_PLAYER
        self.order_piece_selected = 0

    def get_pieces(self):
        return self._pieces

    def play(self):
        # "Play player",self.number
        self.playing = True
        # "Cant piezas",len(self._pieces)
        if self == self.game.ui_player:
            # "Abilitando botones"
            self.game.game_state = self.game.GAME_STATE_SELECT_PIECE
            if len(self.game.pieces) > 0:
                # si hay piezas puede pedir pero no pasar
                self.game.btnNew.props.sensitive = True
                self.game.btnPass.props.sensitive = False
            else:
                # si no hay piezas no puede pedir pero si pasar
                self.game.btnNew.props.sensitive = False
                self.game.btnPass.props.sensitive = True

    def end_play(self):
        if self == self.game.ui_player:
            # "Deshabilitando botones"
            self.game.btnPass.props.sensitive = False
            self.game.btnNew.props.sensitive = False
        # "End player",self.number
        self.playing = False

        self.game.next_player(self.number).play()

    def remove_piece(self, piece):
        cantPieces = len(self._pieces)
        # TODO: there are a better way?
        for n in range(0, len(self._pieces)):
            p = self._pieces[n]
            if piece == p:
                self._pieces[n] = cantPieces
                self._pieces.remove(cantPieces)
                return

    def get_status(self):
        if (len(self._pieces) > 0):
            return self.name + ' - ' + str(len(self._pieces)) + \
                ' ' + _('pieces') + '.    '
        else:
            return self.name + ' -  ' + _('WIN') + '!!!!.    '

    def test_good_position(self, tile, piece):
        n, p = tile.n, tile.p
        logging.error('tile value %s direction %s piece a %s piece b %s',
                      tile.value, tile.direction, piece.a, piece.b)
        # check using the tile direction if the next 3 spaces are free
        # (2 for the piece, and 1 more)
        ok = True
        for i in range(0, 3):
            n = n + tile.direction[0]
            p = p + tile.direction[1]
            if not self.game.test_free_position(n, p):
                ok = False
                break

        if ok:
            logging.error('3 spaces free')
            # define piece position
            # substract one to n, p. (we added 3 to have one more free
            n = n - tile.direction[0]
            p = p - tile.direction[1]
            logging.error('piece position n %s, p %s', n, p)
            # get the minimal between the original tile + 1 and
            # the final n, p values calculated
            ori_n = tile.n + tile.direction[0]
            ori_p = tile.p + tile.direction[1]
            min_n, min_p = min(n, ori_n), min(p, ori_p)
            logging.error('piece position n %s, p %s', min_n, min_p)

            logging.error('tile.value %s piece a %s b %s direction %s',
                          tile.value, piece.a, piece.b, tile.direction)
            # define piece orientation
            if tile.value == piece.b:
                if tile.direction in (Tile.RIGHT, Tile.DOWN):
                    piece.reversed = True
                new_value = piece.a
            elif tile.value == piece.a:
                if tile.direction in (Tile.LEFT, Tile.UP):
                    piece.reversed = True
                new_value = piece.b
            piece.vertical = tile.direction in (Tile.DOWN, Tile.UP)
            logging.error('test_good_position vertical %s reversed %s',
                          piece.vertical, piece.reversed)
            return new_value, tile.direction, piece, min_n, min_p
        else:
            # rotate the tile direction
            if tile.direction == Tile.LEFT:
                tile.direction = Tile.UP
            elif tile.direction == Tile.UP:
                tile.direction = Tile.RIGHT
            elif tile.direction == Tile.RIGHT:
                tile.direction = Tile.DOWN
            elif tile.direction == Tile.DOWN:
                tile.direction = Tile.LEFT
            return self.test_good_position(tile, piece)

    def place_piece(self, piece):
        if piece.a == self.game.start.value or \
                piece.b == self.game.start.value:
            # try with start tile
            new_tile_value, direction, piece, piece_n, piece_p = \
                self.test_good_position(self.game.start, piece)
            self.game.put_piece(self, piece, piece_n, piece_p)
            self.game.start.value = new_tile_value
            self.game.start.n += direction[0] * 2
            self.game.start.p += direction[1] * 2
            self.game.start.direction = direction

        elif piece.a == self.game.end.value or \
                piece.b == self.game.end.value:
            # try with end
            new_tile_value, direction, piece, piece_n, piece_p = \
                self.test_good_position(self.game.end, piece)
            self.game.put_piece(self, piece, piece_n, piece_p)
            self.game.end.value = new_tile_value
            self.game.end.n += direction[0] * 2
            self.game.end.p += direction[1] * 2
            self.game.end.direction = direction
        else:
            return False

        self.game.show_pieces_player(self)
        return True


class SimpleAutoPlayer(DominoPlayer):

    """
    Jugador automatico simple
    Busca la primera ficha que pueda ubicarse en alguna de las posiciones
    si no encuentra una pide
    NO TIENE NINGUNA ESTRATEGIA
    """

    def __init__(self, game, number):
        DominoPlayer.__init__(self, game, number)
        self.pieces_y_position = 0

    def play(self):
        # "Jugando automatico"
        if self.game.start is None:
            # si no hay ninguna pieza en el tablero ponemos la primera
            piece = self._pieces[0]
            n, p = self.game.cantX / 2 - 1, self.game.cantY / 2
            self.game.put_piece(self, piece, n, p)

            # seteamos comienzo y fin del domino
            startTile = Tile(n, p)
            startTile.value = piece.a
            startTile.direction = Tile.LEFT
            self.game.start = startTile

            endTile = Tile(n + 1, p)
            endTile.value = piece.b
            endTile.direction = Tile.RIGHT
            self.game.end = endTile
            self.game.show_pieces_player(self)

        else:
            # "automatica siguiente"
            # buscamos si tenemos alguna ficha que corresponda
            # en el comienzo
            ok = self.check_put_piece()

            if not ok:
                # pido una hasta que sea valida o no hayan mas disponibles
                # si no encontramos pedimos hasta que alguna sirva
                while not ok:
                    # "Pido pieza"
                    pieces = self.game.take_pieces(1)
                    if len(pieces) > 0:
                        piece = pieces[0]
                        piece.player = self
                        self.get_pieces().append(piece)
                        ok = self.check_put_piece()
                    else:
                        ok = True  # No hay mas piezas
                        self.has_passed = True
            if not ok:
                self.has_passed = True

        # juega el siguiente jugador
        self.end_play()

    def check_put_piece(self):
        for tile in (self.game.start, self.game.end):
            # look for a piece with the value
            piece = self._get_piece_with_value(tile.value)
            if piece is not None:
                self.place_piece(piece)
                return True
        return False

    # elige una pieza que tenga un valor
    def _get_piece_with_value(self, value):
        for piece in self._pieces:
            if piece.player == self:
                # "get_piece_with_value",piece.a, piece.b
                if (piece.a == value) or (piece.b == value):
                    return piece
        return None