def test_generate_moves_one_valid(self): config = board.GameConfiguration(6, 2) b = board.Board(config, [1, 2, 3]) got = list(b.generate_moves(board.Roll(dice=[5, 4], prob=0))) self.assertEqual(2, len(got)) self.assertIn([board.Move(2, 5), board.Move(2, 4)], got) self.assertIn([board.Move(2, 4), board.Move(2, 5)], got)
def test_generate_moves_unfinished(self): # This is where you don't have to use all the moves to finish config = board.GameConfiguration(2, 2) b = board.Board(config, [1, 0, 1]) got = list(b.generate_moves(board.Roll(dice=[5, 4], prob=0))) self.assertEqual(2, len(got)) self.assertIn([board.Move(2, 4)], got) self.assertIn([board.Move(2, 5)], got)
def test_generate_moves_valid_with_holes(self): config = board.GameConfiguration(3, 4) # Making sure we don't generate the move that is the 1 spot # going 4 spaces.` b = board.Board(config, [0, 1, 0, 2, 0]) got = list(b.generate_moves(board.Roll(dice=[4, 4], prob=0))) self.assertEqual(1, len(got)) self.assertIn([board.Move(3, 4), board.Move(3, 4)], got)
def test_generate_moves_opposite_order(self): # This is the case where you have to try applying the dice in the # opposite order in order to get a different board as outcome. config = board.GameConfiguration(2, 4) b = board.Board(config, [0, 0, 1, 0, 1]) got = list(b.generate_moves(board.Roll(dice=[4, 3], prob=0))) self.assertEqual(2, len(got)) self.assertIn([board.Move(4, 3), board.Move(2, 4)], got) self.assertIn([board.Move(4, 4), board.Move(2, 3)], got)
def test_apply_move(self): config = board.GameConfiguration(6, 2) b = board.Board(config, [1, 2, 3]) self.assertEqual(b.apply_move(board.Move(2, 6)), board.Board(config, [2, 2, 2])) self.assertEqual(b.apply_move(board.Move(2, 1)), board.Board(config, [1, 3, 2])) self.assertEqual(b.apply_move(board.Move(1, 1)), board.Board(config, [2, 1, 3]))
def test_four_moves(self): moves = [ board.Move(6, 1), board.Move(5, 1), board.Move(4, 1), board.Move(3, 1) ] encoded_str = board.encode_moves_string(moves) self.assertEqual("[[6, 1], [5, 1], [4, 1], [3, 1]]", encoded_str) decoded_moves = board.decode_moves_string(encoded_str) self.assertEqual(moves, decoded_moves)
def test_apply_move_errors(self): config = board.GameConfiguration(6, 2) b = board.Board(config, [1, 2, 3]) with self.assertRaisesRegex(ValueError, "Invalid spot"): b.apply_move(board.Move(0, 6)) b = board.Board(config, [3, 0, 3]) with self.assertRaisesRegex(ValueError, "No marker"): b.apply_move(board.Move(1, 1)) b = board.Board(config, [1, 2, 3]) with self.assertRaisesRegex(ValueError, "Overflow count"): b.apply_move(board.Move(1, 6))
def test_pretty_print_with_moves(self): config = board.GameConfiguration(6, 4) b = board.Board(config, [2, 1, 1, 1, 1]) m1 = board.Move(spot=3, count=2) m2 = board.Move(spot=3, count=3) m3 = board.Move(spot=3, count=6) m4 = board.Move(spot=4, count=1) self.assertEqual( b.pretty_string([m1, m2, m3, m4]), "0 2 oo x + \n" + "1 1 o x | | \n" + "2 1 o | | | \n" + "3 1 o 2 3 6 x \n" + "4 1 o 1 \n")
def main(): filename = "log" + raw_input("name and # try ") + ".txt" gameboard = board.BaseBoard() userinput = raw_input("Would you like to be WHITE or BLACK: ") while userinput.upper() != "WHITE" and userinput.upper() != "BLACK": userinput = raw_input("Would you like to be WHITE or BLACK: ") if userinput.upper() == "WHITE": user = 1 if userinput.upper() == "BLACK": user = -1 #Get difficulty userinput = int(raw_input("What difficulty would you like: 1, 2, 3? ")) if userinput == 1: dif = 1 elif userinput == 2: dif = 2 else: dif = 3 ai = AI.AI(dif, board=copy.deepcopy(gameboard)) while not gameboard.over: file = open(filename, "a") print(gameboard.__unicode__()) if gameboard.turn == user: #User's turn try: #Cause oh well I'm lazy row = int(raw_input("Please enter a row: ")) column = int(raw_input("Please enter a column: ")) newrow = int(raw_input(("Please enter a new row: "))) newcolumn = int(raw_input(("Please enter a new column: "))) usermove = board.Move(row, column, newrow, newcolumn) if gameboard.legalmove(usermove): gameboard.makemove(usermove) ai.makemove(usermove) except: print("Try again.") else: #Computer turn print("AI is thinking...") aimove = ai.alphabeta(dif) print("AI makes move.") print(aimove) gameboard.makemove(aimove) ai.makemove(aimove) file.write(ai.gameTree.__unicode__().encode("UTF-8")) file.close() print("Good Game!") print(gameboard) return None
def test_generate_moves_four_dice(self): config = board.GameConfiguration(9, 4) b = board.Board(config, [0, 0, 3, 3, 3]) got = list(b.generate_moves(board.Roll(dice=[2, 2, 2, 2], prob=0))) self.assertEqual(78, len(got)) # Since this generates an annoying large number of moves, # we're not going to test all of them, just a couple. self.assertIn([ board.Move(3, 2), board.Move(2, 2), board.Move(2, 2), board.Move(2, 2) ], got) self.assertIn([ board.Move(3, 2), board.Move(3, 2), board.Move(3, 2), board.Move(2, 2) ], got)
def main(): gameboard = board.BaseBoard() userinput = raw_input("Would you like to be WHITE or BLACK: ") while userinput.upper() != "WHITE" and userinput.upper() != "BLACK": userinput = raw_input("Would you like to be white or black: ") if userinput.upper() == "WHITE": user = 1 if userinput.upper() == "BLACK": user = -1 #Get difficulty userinput = int(raw_input("What difficulty would you like: 1, 2, 3? ")) if userinput == 1: dif = 2 elif userinput == 2: dif = 3 else: dif = 5 ai = AI.AI(dif, board=copy.deepcopy(gameboard)) while not gameboard.over: print(gameboard.__unicode__()) if gameboard.turn == user: #User's turn row = input("Please enter a row: ") column = input("Please enter a column: ") row1 = input("Please enter a new row: ") column1 = input("Please enter a new column: ") usermove = board.Move(row, column, row1, column1) if gameboard.legalmove(usermove): gameboard.makemove(usermove) ai.makemove(usermove) else: #Computer turn print("AI is thinking...") ai.bestmove() aimove = ai.bestmove() print("AI makes move.") print(aimove) print(ai.gameTree.__unicode__()) gameboard.makemove(aimove) ai.makemove(aimove) print("Good Game!") print(gameboard.__unicode__())
def flip_move(move): frm, to = move.frm, move.to return board.Move(119 - frm, 119 - to, move.is_capture, move.is_castle)
def generatePseudoMoves(state): """ Takes input of a board object and returns a list of potential moves """ moves = [] side = state.pieceBitBoards[ board. WHITE] if state.sideToMove == board.Side.W else state.pieceBitBoards[ board.BLACK] # King Moves kingIndex = util.lastSetBit(side & state.pieceBitBoards[board.KINGS]) kingMoves = util.getSetBits(kingAttacks[kingIndex] & ~side) kingMoves = map(lambda x: (util.asCoord(kingIndex), util.asCoord(x)), kingMoves) moves.extend(map(lambda x: board.Move(fromSqr=x[0], toSqr=x[1]), kingMoves)) # Castling Moves if state.canCastle(state.sideToMove, True): moves.append( board.Move(fromSqr=util.asCoord(kingIndex), toSqr=util.asCoord(kingIndex + 2))) if state.canCastle(state.sideToMove, False): moves.append( board.Move(fromSqr=util.asCoord(kingIndex), toSqr=util.asCoord(kingIndex - 2))) # Knight Moves knightSquares = util.getSetBits(side & state.pieceBitBoards[board.KNIGHTS]) for index in knightSquares: knightMoves = util.getSetBits(knightAttacks[index] & ~side) knightMoves = map(lambda x: (util.asCoord(index), util.asCoord(x)), knightMoves) moves.extend( map(lambda x: board.Move(fromSqr=x[0], toSqr=x[1]), knightMoves)) # Pawn Moves pawnSquares = util.getSetBits(side & state.pieceBitBoards[board.PAWNS]) for index in pawnSquares: pawnMoves = util.getSetBits( pawnPush(util.asBit(index), state.sideToMove, state)) pawnMoves.extend( util.getSetBits(pawnAttack(index, state.sideToMove, state))) pawnMoves = map(lambda x: (util.asCoord(index), util.asCoord(x)), pawnMoves) for x in pawnMoves: if x[1][1] != 0 and x[1][1] != 7: moves.append(board.Move(fromSqr=x[0], toSqr=x[1])) else: moves.append( board.Move(fromSqr=x[0], toSqr=x[1], promotion='q')) moves.append( board.Move(fromSqr=x[0], toSqr=x[1], promotion='n')) moves.append( board.Move(fromSqr=x[0], toSqr=x[1], promotion='r')) moves.append( board.Move(fromSqr=x[0], toSqr=x[1], promotion='b')) # Rook Moves rookSquares = util.getSetBits(side & state.pieceBitBoards[board.ROOKS]) for index in rookSquares: rookMoves = util.getSetBits(rookAttacks(index, state) & ~side) rookMoves = map(lambda x: (util.asCoord(index), util.asCoord(x)), rookMoves) moves.extend( map(lambda x: board.Move(fromSqr=x[0], toSqr=x[1]), rookMoves)) # Bishop Moves bishopSquares = util.getSetBits(side & state.pieceBitBoards[board.BISHOPS]) for index in bishopSquares: bishopMoves = util.getSetBits(bishopAttacks(index, state) & ~side) bishopMoves = map(lambda x: (util.asCoord(index), util.asCoord(x)), bishopMoves) moves.extend( map(lambda x: board.Move(fromSqr=x[0], toSqr=x[1]), bishopMoves)) # Queen Moves queenSquares = util.getSetBits(side & state.pieceBitBoards[board.QUEENS]) for index in queenSquares: queenMoves = util.getSetBits((bishopAttacks(index, state) | rookAttacks(index, state)) & ~side) queenMoves = map(lambda x: (util.asCoord(index), util.asCoord(x)), queenMoves) moves.extend( map(lambda x: board.Move(fromSqr=x[0], toSqr=x[1]), queenMoves)) return moves
def run(self): running = True while running: self.x, self.y = pygame.mouse.get_pos() # Check if engine's turn to make a move. Hacky way for now - white_to_move variable is changed when in hist if self.state == PLAYING and ( (self.user_is_white and len(self.hist) % 2 == 0) or (not self.user_is_white and len(self.hist) % 2 == 1)): print("Engine is calculating...") move, score = self.engine.search(self.board) # Bring to present position internally (not visually, since we are not updating) while self.hist_ind < len(self.hist) - 1: self.make_move() vis_move = move if ( not self.is_flipped and self.white_to_move) or ( not self.white_to_move and self.is_flipped) else tools.flip_move(move) self.animate_move(tools.int_to_vis(vis_move.frm), tools.int_to_vis(vis_move.to)) self.make_move(move) print("Checks: ", self.board.checks) print("Pins: ", self.board.pins) print("Score: ", -score if self.user_is_white else score) print("-----------------") # Check for human moves for event in pygame.event.get(): if event.type == pygame.MOUSEBUTTONDOWN: if self.state == MENU: if self.analysis_button.collidepoint((self.x, self.y)): self.user_is_white = True self.is_flipped = False self.state = ANALYSIS print("Analysis mode!") elif self.white_button.collidepoint((self.x, self.y)): self.user_is_white = True self.is_flipped = False self.state = PLAYING pygame.mixer.Sound.play(self.start_game_fx) print("Playing as white!") elif self.rand_button.collidepoint((self.x, self.y)): rand = random.uniform(0, 1) print(rand) if rand < 0.5: self.user_is_white = True self.is_flipped = False print("Playing as white!") else: self.user_is_white = False self.is_flipped = True print("Playing as black!") self.state = PLAYING pygame.mixer.Sound.play(self.start_game_fx) elif self.black_button.collidepoint((self.x, self.y)): self.user_is_white = False self.is_flipped = True self.state = PLAYING pygame.mixer.Sound.play(self.start_game_fx) print("Playing as black!") if self.state in OVER: if self.play_again_button.collidepoint( (self.x, self.y)): self.init_game_state() elif self.state in (PLAYING, ANALYSIS): if self.flip_button.collidepoint((self.x, self.y)): self.is_flipped = not self.is_flipped print("Flipped board!") if self.state == PLAYING and self.resign_button.collidepoint( (self.x, self.y)): print("Resigned!") self.state = RESIGN # Game is at current position in history, and click within board bounds elif self.hist_ind == len( self.hist ) - 1 and MARGIN <= self.x <= BD_WIDTH + MARGIN and MARGIN <= self.y <= BD_HEIGHT + MARGIN: #print("Clicked inside board!") # Coordinates of square clicked sq_x = (self.x - MARGIN) // SQ_SIZE sq_y = (self.y - MARGIN) // SQ_SIZE from_sq = (sq_x, sq_y) # Check if clicked square is part of any valid move pos = tools.vis_to_int(from_sq) if (self.is_flipped or not self.white_to_move ) and (self.white_to_move or not self.is_flipped): pos = 119 - pos valid_selection = False for move in self.board.gen_legal_moves(): if move.frm == pos: valid_selection = True # If not currently selecting and square is not part of any valid move, we are in selecting mode if not self.selecting and valid_selection: self.from_sq = from_sq self.selecting = True self.dragging = True #print("Selecting") # If we are in selecting mode, the square we are over is the to_square for the move elif self.selecting: #print("Choosing square to move to!") self.to_sq = (sq_x, sq_y) x, y = tools.vis_to_int( self.from_sq), tools.vis_to_int(self.to_sq) # This capture detection needs to be optimized capture = self.board.pos[y].islower() or ( self.board.pos[x] == 'P' and y - x in (board.U + board.L, board.U + board.R)) castle = self.board.pos[x] == 'K' and abs( y - x) == 2 move = board.Move(x, y, capture, castle) move = move if (not self.is_flipped and self.white_to_move) or ( not self.white_to_move and self.is_flipped ) else tools.flip_move(move) #print("Proposed move: ", self.from_sq, self.to_sq) if move in self.board.gen_legal_moves(): print("Valid move!") self.animate_move(self.from_sq, self.to_sq) self.make_move(move) print("Checks: ", self.board.checks) print("Pins: ", self.board.pins) print( "Score: ", eval.evaluate(self.board) if self.white_to_move else -eval.evaluate(self.board)) print("-----------------") self.dragging = False else: #print("Invalid move chosen while selecting. Deselecting if released incorrectly.") self.deselect_next = True self.dragging = True elif event.type == pygame.MOUSEBUTTONUP: self.dragging = False if self.state in ( PLAYING, ANALYSIS) and self.hist_ind == len(self.hist) - 1: if self.from_sq and MARGIN <= self.x <= BD_WIDTH + MARGIN and MARGIN <= self.y <= BD_HEIGHT + MARGIN: #print("Released inside board!") # Coordinates of square clicked sq_x = (self.x - MARGIN) // SQ_SIZE sq_y = (self.y - MARGIN) // SQ_SIZE self.to_sq = (sq_x, sq_y) x, y = tools.vis_to_int( self.from_sq), tools.vis_to_int(self.to_sq) capture = self.board.pos[y].islower() or ( self.board.pos[x] == 'P' and y - x in (board.U + board.L, board.U + board.R)) castle = self.board.pos[x] == 'K' and abs(y - x) == 2 move = board.Move(x, y, capture, castle) move = move if ( not self.is_flipped and self.white_to_move ) or (not self.white_to_move and self.is_flipped) else tools.flip_move(move) #print("Proposed move: ", self.from_sq, self.to_sq) if move in self.board.gen_legal_moves(): print("Valid move!") self.make_move(move) print("Checks: ", self.board.checks) print("Pins: ", self.board.pins) print( "Score: ", eval.evaluate(self.board) if self.white_to_move else -eval.evaluate(self.board)) print("-----------------") else: print("Invalid move!") if self.deselect_next: #print("Deselecting") self.selecting = False self.from_sq = None self.deselect_next = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: self.unmake_move() if event.key == pygame.K_RIGHT: self.make_move() elif event.type == pygame.QUIT: running = False # Draw screen self.draw() # Delay self.clock.tick(FPS) pygame.quit()
def test_two_moves(self): moves = [board.Move(6, 2), board.Move(5, 3)] encoded_str = board.encode_moves_string(moves) self.assertEqual("[[6, 2], [5, 3]]", encoded_str) decoded_moves = board.decode_moves_string(encoded_str) self.assertEqual(moves, decoded_moves)
def test_generate_moves_second_dependent(self): config = board.GameConfiguration(2, 4) b = board.Board(config, [0, 0, 1, 0, 1]) got = list(b.generate_moves(board.Roll(dice=[4, 4], prob=0))) self.assertEqual(1, len(got)) self.assertIn([board.Move(4, 4), board.Move(2, 4)], got)