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
def move(self, move, board): coin_pos = board.findPieces('c', None).pop() # there only is one ;-) coin_target = coin_pos + (move.toField - move.fromField) coin_move = Move(coin_pos, coin_target) coin_move.silent = True board.move(coin_move) # normal stuff return [coin_move] + super(CoinGame, self).move(move, board)
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])
def parseCastling(self, moveSet, board, player): if True in board.castlingsPossible[player.color]: # has the king moved already? kingPiece = board.fields[self.castlingPositions[player.color][0]] if not(kingPiece is None) and kingPiece.moveCount > 0 and not self.CASTLING_IF_KING_HAS_MOVED: # destroys both castling possibilities! board.castlingsPossible[player.color] = [False, False] return moveSet # short / long for cType in [0, 1]: if board.castlingsPossible[player.color][cType]: good = True # has the rook moved already? rookPiece = board.fields[self.castlingPositions[player.color][1 + cType]] if not(rookPiece is None) and rookPiece.moveCount > 0 and not self.CASTLING_IF_ROOK_HAS_MOVED: # destroys this castling possibility! board.castlingsPossible[player.color][cType] = False good = False # any relevant field non-empty? if good: # relevant fields are any between rook's and king's start and target fields leftPos = min(self.castlingPositions[player.color][0], self.castlingPositions[player.color][1 + cType], self.castlingTargetPositions[player.color][2 * cType], self.castlingTargetPositions[player.color][2 * cType + 1]) rightPos = max(self.castlingPositions[player.color][0], self.castlingPositions[player.color][1 + cType], self.castlingTargetPositions[player.color][2 * cType], self.castlingTargetPositions[player.color][2 * cType + 1]) # check them for emptiness (moving rook being there is okay [Chess960!]) for pos in range(leftPos, rightPos + 1): if not (board.fields[pos] is None) and pos != self.castlingPositions[player.color][0] and pos != self.castlingPositions[player.color][1 + cType]: # empty, king, rook good = False break # fields for king checked? if good and True: # get all attacked fields opponentMoves = self.getPossibleMoves(board, False, self.getNextPlayer(board, player), noCastlingMoves=True, noDropMoves=True) opponentAttackedFields = set() for oMove in opponentMoves: opponentAttackedFields.add(oMove.toField) # get fields king will cross (including start and end) kingPos = self.castlingPositions[player.color][0] kingTargetPos = self.castlingTargetPositions[player.color][2 * cType] leftPos = min(kingPos, kingTargetPos) rightPos = max(kingPos, kingTargetPos) # compare for pos in range(leftPos, rightPos + 1): if pos in opponentAttackedFields: # test which type of check has happened and obey settings if pos == kingPos and not self.CASTLING_FROM_CHECK: good = False break elif pos == kingTargetPos and not self.CASTLING_TO_CHECK: good = False break elif not self.CASTLING_THROUGH_CHECK: good = False break # good! if good: move = Move(None, None) move.annotation = 'SHORTCASTLING' if cType == 0 else 'LONGCASTLING' moveSet.add(move) return moveSet