Ejemplo n.º 1
0
 def move(self, move, board):
     capture = True
     if board.fields[move.toField] is None:
         capture = False
     
     explosionMoves = super(AtomicGame, self).move(move, board)
     
     if not capture:
         return explosionMoves
     
     # create explosion moves
     target = move.toField
     for x in [-1, 0, 1]:
         for y in [-1, 0, 1]:
             # piece itself
             #if x == 0 and y == 0:
             #    continue
             # fields around it
             explosionTarget = board.moveByDirection(target, x, y)
             if explosionTarget is None:
                 continue
             if board.fields[explosionTarget] is None:
                 continue 
             if board.fields[explosionTarget].shortName in self.PAWN_PIECE_TYPES:
                 continue 
             move = Move(explosionTarget, explosionTarget)
             move.toPiece = '' # indicates that field will be cleared
             move.silent = True
             # execute on board
             board.move(move) 
             explosionMoves.append(move)
              
     return explosionMoves
Ejemplo n.º 2
0
    def handle_input(self, message, gameConnection):
        #print message
        if message is None:
            return
        
        params = message.split("/")
        #print params
        if len(params) > 1:
            mq = mqPool.get(params[1])
        print params
        
        if mq is None:
            print 'Access to non-existing message queue: %s' % params[1]; 
            return ''
            
        # make sure this socket is tied to the message queue?
        mq.socket = gameConnection
            
        if (params[0] == 'post' and params[2] == 'move'):
            # record time (when jazzy is calculating, nobody's clock should be active...)
            input_time = datetime.datetime.now()
                        
            # filter watchers attempting to post stuff
            if mq.watching or mq.game.finished == True:
                return
            # only allow current player to post his move
            if mq.game.getCurrentPlayer().mq != mq:
                mq.send(Message('alert', {'msg': 'Not your turn.'}).data)
                return
            
            game = mq.game
            
            # find board
            originalFrom = params[3]
            originalTo = params[4]
            shortFrom = originalFrom.replace('board_', '').replace('_field', '_');
            shortTo = originalTo.replace('board_', '').replace('_field', '_');
            boardId = shortFrom.split('_')[0]
            targetBoard = mq.game.getBoard(boardId)
            
            # create move
            if  shortFrom.split('_')[1] == 'SHORTCASTLING' or  shortFrom.split('_')[1] == 'LONGCASTLING':
                # castling
                postedMove = Move(None, None)
                postedMove.annotation = shortFrom.split('_')[1]
            else:
                # standard move
                fromField = shortFrom.split('_')[1]
                toField = int(shortTo.split('_')[1])
                postedMove = Move(fromField, toField)
                # do we have a promotion option set?
                if len(params) > 5:
                    postedMove.toPiece = game.getPieceByString(params[5], game.board) 

            
            # check move for correctness
            isLegalMove = game.isLegalMove(postedMove, targetBoard)
            # parse move
            postedMove.simpleParse(targetBoard)
            postedMove.fullParse(targetBoard)
                            
            # put the message to all players
            if isLegalMove:
                # do we have to ask for promotion piece?
                if game.moveNeedsPromotion(postedMove, targetBoard):
                    msg = Message('promote', {'from': originalFrom, 'to': originalTo})
                    # add options
                    msg.data['options'] = game.getPromotionOptions(postedMove.fromPiece.color)
                    mq.send(msg.data)
                else:
                    moves = game.move(postedMove, targetBoard, realMove = True, input_time = input_time)
                    
                    # analyze if game is over
                    result = game.getGameOverMessage()
                    if not(result is None):
                        game.finish()                        
    
                    # post all the moves the particular game created
                    for move in moves:                    
                        if isinstance(move, NullMove):
                            data = {'from':-1, 'to':-1}
                            data['silent'] = True
                        else:
                            # normal move
                            #move.simpleParse(mq.game.board)
                            if move.board is None:
                                data = {'from': move.fromField, 'to': move.toField}
                            else:
                                data = {'from': str(move.board.id) + '_' + str(move.fromField), 'to': str(move.board.id) + '_' + str(move.toField)}
                                
                            if move.silent:
                                data['silent'] = True
                            if not(move.toPiece is None):
                                if move.toPiece == '':
                                    data['toPiece'] = ''
                                else:
                                    data['toPiece'] = move.toPiece.getShortName()
                        if not(game.getCurrentPlayer(game.board) is None) and not(game.finished):
                            data['currP'] = game.getCurrentPlayer(game.board).mq.shortenedId
                        mq.metagame.broadcastSocket(Message('move', data).data)
                        
                    mq.metagame.broadcastSocket(Message('movehist', {'user': mq.subject.name, 'str': postedMove.str}).data)
                    
                    # debug position
                    logger.debug(str(game.board))
                    
                    # resend parts of the board that have changed (not forced)
                    for player in mq.metagame.players:
                        sitMsg = mq.metagame.getSituationMessage(mq, player=player)
                        if not(sitMsg is None):
                            player.mq.send(sitMsg.data)
                    # clear board
                    mq.game.board.resend = False # TODO generalize
                    
                    # distribute the game over message if there was one
                    if not(result is None):
                        mq.metagame.broadcastSocket(result.data)
                    
            else: 
                # not legal move
                msg = Message('alert', {'msg': 'Illegal move.'})
                mq.send(msg.data)
                if game.DEBUG_LEGAL_MOVES_ON_ILLEGAL_MOVE:
                    msg = Message('srvmsg', {'msg': 'Possible moves are: ' + str(sorted(mq.game.possibleMoves, key=lambda move: [str(move.fromField), move.toField]))})
                    mq.send(msg.data)
        
        elif (params[0] == 'getsit'):
            return mq.metagame.getSituationMessage(mq, force=True, init=True).data
        
        # draw claims
        elif params[0] == 'claim':
            # filter watchers attempting to post stuff
            if mq.watching:
                return
                
            if params[2] == 'repetition':                    
                if mq.game.isRepetitionDraw():
                    mq.metagame.broadcastSocket(mq.game._generateGameOverMessage('Draw by repetition upon player\'s request', '0.5-0.5', None).data)
                    mq.game.finish()   
                else:
                    mq.send(Message('alert', {'msg': 'No draw by repetition. This position has been on board {0} times.'.format(mq.game.getRepetitionCount())}).data) 
                    
            if params[2] == 'xmoverule':
                if mq.game.isXMoveDraw():
                    mq.metagame.broadcastSocket(mq.game._generateGameOverMessage('Draw by {0} move rule upon player\'s request'.format(mq.game.DRAW_X_MOVES_VALUE), '0.5-0.5').data)
                    mq.game.finish()   
                else:
                    mq.send(Message('alert', {'msg': 'No draw by {0} move rule. Counter is at {1}.'.format(mq.game.DRAW_X_MOVES_VALUE, mq.game.board.drawXMoveCounter)}).data)
            
            # clock
            if params[2] == 'clock':
                clockExpirationPlayer = None
                for player in mq.game.players:
                    if player.mq.clock.isExpired():
                        if clockExpirationPlayer is None:
                            clockExpirationPlayer = player
                        else:
                            # more than 1 clock expired -> draw
                            mq.game.broadcastSocket(mq.game._valueResult(None, 'Both players\' time\'s up!').data)
                            mq.game.finish()   
                            return
                        
                # anounce winner        
                if not(clockExpirationPlayer is None):
                    mq.game.broadcastSocket(mq.game._valueResult(clockExpirationPlayer, 'Time\'s up!').data)
                    mq.game.finish()   
                else:
                    mq.send(Message('alert', {'msg': 'No time trouble detected.'}).data)
                    
                    
        # messages about game end (resigning, draws) 
        elif (params[0] == 'end'):
            # only players please!
            if not mq.watching:
                # player resigned
                if (params[2] == 'resign'):
                    result = '0-1' if mq.subject.color == 'white' else '1-0' 
                    winner = mq.game.getNextCurrentPlayer() if mq.game.getCurrentPlayer() == mq.subject else mq.game.getCurrentPlayer()
                    mq.metagame.broadcastSocket(mq.game._generateGameOverMessage('Player resigned.', result, winner).data)
                    mq.game.finish()   
                # player is offering draw
                elif (params[2] == 'draw-offer'):
                    agreeingPlayers = []
                    for player in mq.game.players:
                        if player.offeringDraw:
                            agreeingPlayers.append(player)
                    
                    # rule: you may not offer a draw when you are on the move!
                    if not(mq.subject.offeringDraw) and (len(agreeingPlayers) > 0 or mq.subject != mq.game.getCurrentPlayer()):
                        # keep the player's decision
                        mq.subject.offeringDraw = True
                        
                        # do all players agree?
                        agreeingPlayers = []
                        for player in mq.game.players:
                            if player.offeringDraw:
                                agreeingPlayers.append(player)
                                
                        if len(agreeingPlayers) == len(mq.game.players):
                            # finish the game
                            mq.metagame.broadcastSocket(mq.game._generateGameOverMessage('Players agreed.', '0.5-0.5', None).data)
                            mq.game.finish()   
                        else:
                            # ask the other players
                            mq.metagame.broadcastSocket(Message('draw-offer', {}).data, agreeingPlayers)
                    
            
        # transfer chat message     
        elif (params[0] == 'post' and params[2] == 'chat'):            
            # filter watchers attempting to post stuff
            if mq.watching:
                return
            
            # sanitize
            msg = params[3]
            msg = GenericHandler.sanitizeHTML(msg)
                        
            mq.metagame.broadcastSocket(Message('chat', {'user': mq.subject.name, 'msg': msg}).data, [mq.subject])