Show
Ignore:
Timestamp:
04/15/08 07:32:45 (7 months ago)
Author:
bct
Message:

check tic-tac-toe win conditions, slimmed down _messageCB some more

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • branches/session_centric/src/tictactoe.py

    r9459 r9465  
    1010# implements <http://pidgin-games.sourceforge.net/xep/tictactoe.html#invite> 
    1111 
     12games_ns = 'http://jabber.org/protocol/games' 
     13 
    1214class InvalidMove(Exception): 
    1315        pass 
     
    2527                        self.role_o = 'x' 
    2628 
     29                self.send_invitation() 
     30 
     31                self.next_move_id = 1 
     32                self.received = self.wait_for_invite_response 
     33 
     34        def send_invitation(self): 
    2735                msg = xmpp.Message() 
    2836 
    2937                invite = msg.NT.invite 
    30                 invite.setNamespace('http://jabber.org/protocol/games') 
     38                invite.setNamespace(games_ns) 
    3139 
    3240                game = invite.NT.game 
    33                 game.setAttr('var', 'http://jabber.org/protocol/games/tictactoe') 
     41                game.setAttr('var', games_ns + '/tictactoe') 
    3442 
    3543                x = xmpp.DataForm(typ='submit') 
     
    3947                self.send(msg) 
    4048 
    41                 self.next_move_id = 1 
    42                 self.state = 'sent_invite' 
     49        def read_invitation(self, msg): 
     50                invite = msg.getTag('invite', namespace=games_ns) 
     51                game = invite.getTag('game') 
     52                x = game.getTag('x', namespace='jabber:x:data') 
     53 
     54                form = xmpp.DataForm(node=x) 
     55 
     56                if form.getField('role'): 
     57                        self.role_o = form.getField('role').getValues()[0] 
     58                else: 
     59                        self.role_o = 'x' 
     60 
     61                if form.getField('rows'): 
     62                        self.rows = int(form.getField('rows').getValues()[0]) 
     63                else: 
     64                        self.rows = 3 
     65 
     66                if form.getField('cols'): 
     67                        self.cols = int(form.getField('cols').getValues()[0]) 
     68                else: 
     69                        self.cols = 3 
     70 
     71                if form.getField('strike'): 
     72                        self.strike = int(form.getField('strike').getValues()[0]) 
     73                else: 
     74                        self.strike = 3 
    4375 
    4476        # received an invitation 
    4577        def invited(self, msg): 
    46                 invite = msg.getTag('invite', namespace='http://jabber.org/protocol/games') 
    47                 game = invite.getTag('game') 
    48                 x = game.getTag('x', namespace='jabber:x:data') 
    49  
    50                 form = xmpp.DataForm(node=x) 
    51  
    52                 if form.getField('role'): 
    53                         self.role_o = form.getField('role').getValues()[0] 
    54  
    55                 if form.getField('rows'): 
    56                         self.rows = int(form.getField('rows').getValues()[0]) 
    57  
    58                 if form.getField('cols'): 
    59                         self.cols = int(form.getField('cols').getValues()[0]) 
    60  
    61                 # XXX 'strike' 
    62  
    63                 if not hasattr(self, 'rows'): 
    64                         self.rows = 3 
    65  
    66                 if not hasattr(self, 'cols'): 
    67                         self.cols = 3 
     78                self.read_invitation(msg) 
     79 
     80                # XXX prompt user 
     81                #   "accept, reject, ignore" 
    6882 
    6983                # the number of the move about to be made 
    7084                self.next_move_id = 1 
    7185 
     86                # display the board 
    7287                self.board = TicTacToeBoard(self, self.rows, self.cols) 
    7388 
     
    7691 
    7792                join = response.NT.join 
    78                 join.setNamespace('http://jabber.org/protocol/games') 
     93                join.setNamespace(games_ns) 
    7994 
    8095                self.send(response) 
    8196 
    82                 if not hasattr(self, 'role_o') or self.role_o == 'x': 
     97                if self.role_o == 'x': 
    8398                        self.role_s = 'o' 
    84                         self.role_o = 'x' 
    8599 
    86100                        self.their_turn() 
     
    92106 
    93107        def is_my_turn(self): 
    94                 return self.state == 'get_input' 
    95  
    96         def received(self, msg): 
    97                 # just sent an invitation, expecting a reply 
    98                 if self.state == 'sent_invite': 
    99                         if msg.getTag('join', namespace='http://jabber.org/protocol/games'): 
    100                                 self.board = TicTacToeBoard(self, self.rows, self.cols) 
    101  
    102                                 if self.role_s == 'x': 
    103                                         self.our_turn() 
    104                                 else: 
    105                                         self.their_turn() 
    106  
    107                         return 
    108  
    109                 # ignore messages unless we're expecting a move 
    110                 if self.state != 'waiting': 
    111                         return 
    112  
    113                 turn = msg.getTag('turn', namespace='http://jabber.org/protocol/games') 
    114  
     108                # XXX not great semantics 
     109                return self.received == self.ignore 
     110 
     111        # just sent an invitation, expecting a reply 
     112        def wait_for_invite_response(self, msg): 
     113                if msg.getTag('join', namespace=games_ns): 
     114                        self.board = TicTacToeBoard(self, self.rows, self.cols) 
     115 
     116                        if self.role_s == 'x': 
     117                                self.our_turn() 
     118                        else: 
     119                                self.their_turn() 
     120 
     121                elif msg.getTag('decline', namespace=games_ns): 
     122                        self.XXX() 
     123 
     124        # silently ignores any received messages 
     125        def ignore(self, msg): 
     126                pass 
     127 
     128        def wait_for_move(self, msg): 
     129                turn = msg.getTag('turn', namespace=games_ns) 
    115130                move = turn.getTag('move', namespace='http://jabber.org/protocol/games/tictactoe') 
    116131 
     
    129144                        return 
    130145 
    131                 # XXX check win conditions 
    132  
    133                 self.next_move_id += 1 
    134  
    135                 self.our_turn() 
     146                # check win conditions 
     147                if self.board.check_for_strike(self.role_o, row, col, self.strike): 
     148                        self.lost() 
     149                elif self.board.full(): 
     150                        self.drawn() 
     151                else: 
     152                        self.next_move_id += 1 
     153 
     154                        self.our_turn() 
    136155 
    137156        def our_turn(self): 
    138                 self.state = 'get_input' 
     157                # ignore messages until we've made our move 
     158                self.received = self.ignore 
    139159                self.board.win.set_title(self.board.title + ': your turn') 
    140160 
    141161        def their_turn(self): 
    142                 self.state = 'waiting' 
     162                self.received = self.wait_for_move 
    143163                self.board.win.set_title(self.board.title + ': their turn') 
    144164 
    145165        # called when the board receives input 
    146         def move(self, row, column): 
     166        def move(self, row, col): 
    147167                try: 
    148                         self.board.mark(row, column, self.role_s) 
     168                        self.board.mark(row, col, self.role_s) 
    149169                except InvalidMove, e: 
    150                         print 'invalid move' 
     170                        print 'you made an invalid move' 
    151171                        return 
    152172 
    153                 self.send_move(row, column) 
    154  
    155                 # XXX check win conditions 
     173                self.send_move(row, col) 
     174 
     175                # check win conditions 
     176                if self.board.check_for_strike(self.role_s, row, col,self.strike): 
     177                        self.won() 
     178                elif self.board.full(): 
     179                        self.drawn() 
     180                else: 
     181                        self.next_move_id += 1 
     182 
     183                        self.their_turn() 
    156184 
    157185        def send_move(self, row, column): 
    158186                msg = xmpp.Message() 
     187                msg.setType('chat') 
    159188 
    160189                turn = msg.NT.turn 
    161                 turn.setNamespace('http://jabber.org/protocol/games') 
     190                turn.setNamespace(games_ns) 
    162191 
    163192                move = turn.NT.move 
    164                 move.setNamespace('http://jabber.org/protocol/games/tictactoe') 
     193                move.setNamespace(games_ns+'/tictactoe') 
    165194 
    166195                move.setAttr('row', str(row)) 
     
    170199                self.send(msg) 
    171200 
    172                 self.next_move_id += 1 
    173  
    174                 self.their_turn() 
    175  
    176201class TicTacToeBoard: 
     202        def check_for_strike(self, p, r, c, strike): 
     203                # up and down, left and right 
     204                tallyI = 0 
     205                tally_ = 0 
     206 
     207                # right triangles: L\ , F/ 
     208                tallyL = 0 
     209                tallyF = 0 
     210 
     211                # convert real columns to internal columns 
     212                r -= 1 
     213                c -= 1 
     214 
     215                for d in xrange(-strike, strike): 
     216                        # vertical check 
     217                        try: 
     218                                tallyI = tallyI + 1 if self.board[r+d][c] == p else 0 
     219                        except IndexError: 
     220                                pass 
     221 
     222                        # horizontal check 
     223                        try: 
     224                                tally_ = tally_ + 1 if self.board[r][c+d] == p else 0 
     225                        except IndexError: 
     226                                pass 
     227 
     228                        # diagonal checks 
     229                        try: 
     230                                tallyL = tallyL + 1 if self.board[r+d][c+d] == p else 0 
     231                        except IndexError: 
     232                                pass 
     233 
     234                        try: 
     235                                tallyF = tallyF + 1 if self.board[r+d][c-d] == p else 0 
     236                        except IndexError: 
     237                                pass 
     238 
     239                        if any([t == strike for t in (tallyL, tallyF, tallyI, tally_)]): 
     240                                return True 
     241 
     242                return False 
     243 
    177244        def __init__(self, session, rows, cols): 
    178245                self.session = session 
     
    184251 
    185252                self.setup_window() 
     253 
     254        # is the board full? 
     255        def full(self): 
     256                for r in xrange(self.rows): 
     257                        for c in xrange(self.cols): 
     258                                if self.board[r][c] == None: 
     259                                        return False 
     260 
     261                return True 
    186262 
    187263        def setup_window(self): 
     
    215291                self.session.move(row, column) 
    216292 
     293        # this actually draws the board 
    217294        def expose(self, widget, event): 
    218295                win = widget.window