def test_end_tie(self): game = Kalah(6, 4) game.set_status( {'f': 2, 'e': 2, 'd': 0, 'c': 0, 'b': 8, 'a': 8, 'bank_player_one': 2, 'F': 0, 'E': 0, 'D': 0, 'C': 2, 'B': 0, 'A': 0, 'bank_player_tow': 24}) self.assertEqual(game.play('f'), 'tie')
def simulate_game(holes, seeds, steps): result = [] game = Kalah(holes, seeds) for step in steps: result.append((game.play(step), game.status())) return result
def test_render(self): game = Kalah(6, 4) a = ' **** ' b = '* *' c = '=' * 7 w1 = a + ' ' + c * game.holes + ' ' + a + "\n" w2 = '* *' + ' ' + '| ' * game.holes + '|' + ' ' + '* *\n' w3 = b + ' ' for k, v in game.board.items(): if k == 'bank_player_one' or k == 'bank_player_one': break else: w3 += f"| {v}{' ' if v<10 else ''} " w3 += '| ' + b + "\n" w = f"* {game.board['bank_player_tow']}{' ' if game.board['bank_player_tow'] < 10 else ''} * {c * game.holes} *{' ' if game.board['bank_player_one'] < 10 else ''}{game.board['bank_player_one']} *\n" w5 = b + ' ' flag = 0 for k, v in game.board.items(): if k == 'bank_player_one': flag = 1 if not flag: w5 += f"| {v}{' ' if v<10 else ''} " w5 += '| ' + b + "\n" s = w1 + w2 + w3 + w2 + w + w2 + w5 + w2 + w1 self.assertEqual(game.__str__(), s)
def render_game(holes, seeds, steps): game = Kalah(holes, seeds) for i in range(0, len(steps)): if steps[i] > holes - 1: steps[i] -= holes print(game.play(steps[i])) print(game)
def simulate_game(holes, seeds, steps): game = Kalah(holes, seeds) for i in range(0, len(steps)): if steps[i] > holes - 1: steps[i] -= holes msg = game.play(steps[i]) status = game.status() l = {msg: status} return l
def __init__(self): self.game = Kalah(5, 5) self.maxSeeds = 50 self.maxDigits = 2 self.padding = ' ' * 12 self.player1string = ' Player 1 ' self.player2string = ' Player 2 ' self.canContinue = True
def test_4_holes_4_seeds(self): print(self.game.render()) self.game = Kalah(4, 4) self.game.set_status([0, 0, 0, 0, 17, 4, 2, 6, 2, 1]) self.assertEqual(self.game.play(2), "Player 1 wins.") self.game.set_status([1, 2, 6, 2, 4, 0, 0, 0, 0, 17]) self.game.set_player(1) self.assertEqual(self.game.play(8), "Player 2 wins.") self.game.set_status([0, 0, 0, 0, 16, 3, 2, 6, 3, 2]) self.assertEqual(self.game.play(2), "Tie")
def main(*args, **kwargs): parser = argparse.ArgumentParser() parser.add_argument('-pl1', '-PL1', '--player1', type=str, default='') parser.add_argument('-pl2', '-PL2', '--player2', type=str, default='') parser.add_argument('-n', '-N', '--network', help='play networked', action='store_true') parser.add_argument('-s', '-S', '--server', type=str, default='localhost', help='Server name') parser.add_argument('-p', '-P', '--port', type=int, default=31425, help='Server port < default is >') args = parser.parse_args() print(args) player1 = Player if args.player1 == '' else HumanPlayer player2 = Player if args.player2 == '' else HumanPlayer if not args.network: game = Kalah(player1, player2) else: game = KalahNetwork(player1) game.start() game.match() game.end()
def move(self, position, board, is_my_move=True): ''' returns the board after given movement. you can get either your's or opponent's movement with the parameter "is_my_move" ''' board = copy.deepcopy(board) prediction = Kalah(board) if not is_my_move: prediction.board = reverse_board(board) _, free_turn = prediction.move(position) board = prediction.board if not is_my_move: board = reverse_board(board) return board, prediction.is_game_over(), free_turn
def test_game(count, depth, p_random, p1_h, n): ''' Tests a search strategy through a series of complete games of Kalah. The test passes if the search wins at least the given percentage of games and calls its heuristic function at most the given proportion of times relative to Minimax. Writes the winning percentage of the second strategy to standard output. count -- a positive integer depth -- the depth to search to p_random -- the probability of making a random move instead of the suggested move win_cutoff -- the proportion of games won needed to pass test_strategy -- a function that takes a depth and heuristic and returns a function that takes a position and returns the move suggested by a search to the given depth p1_h -- a heuristic function that takes a game position and returns an integer heuristic value, positive for positions where P1 has an advantage and negative where P2 has an advantage n -- a positive integer ''' board = Kalah(6) h1 = minimax.Heuristic(p1_h) p1_strategy_fxn = minimax.minimax_strategy p2_strategy_fxn = mcts.mcts_strategy win_pct = compare_strategies(board, lambda: p1_strategy_fxn(depth, h1), lambda: p2_strategy_fxn(n), count, 1.0 - p_random) print(1.0 - win_pct)
def test_capture_player_2(self): game = Kalah(6, 4) game.set_status( {'f': 4, 'e': 4, 'd': 4, 'c': 8, 'b': 8, 'a': 8, 'bank_player_one': 1, 'F': 0, 'E': 0, 'D': 0, 'C': 0, 'B': 0, 'A': 9, 'bank_player_tow': 2}) game.turn = [0, 1] game.play('A') self.assertEqual(game.status(), (5, 5, 5, 9, 0, 9, 1, 1, 0, 0, 0, 0, 0, 13))
def test_non_capture(self): game = Kalah(6, 4) game.turn = [0, 1] game.set_status( {'f': 4, 'e': 4, 'd': 4, 'c': 8, 'b': 0, 'a': 8, 'bank_player_one': 1, 'F': 1, 'E': 0, 'D': 0, 'C': 0, 'B': 0, 'A': 5, 'bank_player_tow': 13}) game.play('F') self.assertEqual(game.status(), (4, 4, 4, 8, 0, 8, 1, 0, 1, 0, 0, 0, 5, 13))
def test_player_2_crosses(self): game = Kalah(6, 4) game.play('e') game.play('E') game.play('a') game.play('A') self.assertEqual(game.status(), (5, 1, 6, 6, 5, 0, 1, 5, 1, 6, 6, 5, 0, 1))
def test_move(pos_list, turn, depth, test_strategy, h): ''' Prints the move suggested by the given strategy.. pos_list -- a list of nonnegative integers giving the number of seeds in each pit in Kalah turn -- 0 or 1 to indicate which player is to make the next move depth -- a positive integer giving the depth to search to test_strategy -- a function that takes a depth and heuristic and returns a function that takes a position and returns the move suggested by a search to the given depth h -- a heuristic function that takes a game position and returns an integer heuristic value, positive for positions where P1 has an advantage and negative where P2 has an advantage ''' board = Kalah(len(pos_list) // 2 - 1) pos = Kalah.Position(board, pos_list, turn) h = minimax.Heuristic(h) strategy = test_strategy(depth, h) print(strategy(pos))
def test_end_game_player_2_win(self): game = Kalah(6, 4) game.turn = [0, 1] game.set_status( {'f': 0, 'e': 0, 'd': 0, 'c': 2, 'b': 0, 'a': 0, 'bank_player_one': 10, 'F': 2, 'E': 3, 'D': 0, 'C': 0, 'B': 8, 'A': 8, 'bank_player_tow': 15}) self.assertEqual(game.play('F'), 'Player 2 wins')
def test_game(count, depth, p_random, win_cutoff, size_cutoff, test_strategy, p1_h, p2_h): ''' Tests a search strategy through a series of complete games of Kalah. The test passes if the search wins at least the given percentage of games and calls its heuristic function at most the given proportion of times relative to Minimax. count -- a positive integer depth -- the depth to search to p_random -- the probability of making a random move instead of the suggested move win_cutoff -- the proportion of games won needed to pass size_cutoff -- the proportion of calls to the heurustic to allow compared to minimax test_strategy -- a function that takes a depth and heuristic and returns a function that takes a position and returns the move suggested by a search to the given depth p1_h -- a heuristic function that takes a game position and returns an integer heuristic value, positive for positions where P1 has an advantage and negative where P2 has an advantage p2_h -- a heuristic function that takes a game position and returns an integer heuristic value, positive for positions where P1 has an advantage and negative where P2 has an advantage ''' board = Kalah(6) h1 = minimax.Heuristic(p1_h) h2 = minimax.Heuristic(p2_h) p1_strategy = minimax.minimax_strategy(depth, h1) p2_strategy = test_strategy(depth, h2) win_pct = compare_strategies(board, p1_strategy, p2_strategy, count, 1.0 - p_random) if win_pct <= 1.0 - win_cutoff and h2.count_calls( ) < h1.count_calls() * size_cutoff: print("PASS") else: print("FAIL") print(1.0 - win_pct) print(h1.count_calls()) print(h2.count_calls())
def test_two_simple_moves(self): game = Kalah(6, 4) game.play('e') game.play('E') self.assertEqual(game.status(), (4, 0, 5, 5, 5, 5, 0, 4, 0, 5, 5, 5, 5, 0))
class KalahTestCase(unittest.TestCase): def setUp(self): self.game = Kalah(6, 4) def test_init_status(self): assert self.game.status() == (4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0) def test_init_play(self): assert self.game.play(1) == "Player 2 plays next" assert self.game.play(1) == "Player 1 plays next" self.assertRaises(ValueError, self.game.play, -2) self.assertRaises(ValueError, self.game.play, 7) self.assertRaises(ValueError, self.game.play, self.game.holes) def test_init_done(self): assert self.game.game_over == False def test_init_score(self): assert self.game.score() == (0, 0) def test_simple_move(self): self.game.play(2) assert self.game.status() == (4, 4, 0, 5, 5, 5, 1, 4, 4, 4, 4, 4, 4, 0) def test_few_moves(self): self.game.play(2) assert self.game.status() == (4, 4, 0, 5, 5, 5, 1, 4, 4, 4, 4, 4, 4, 0) self.game.play(3) assert self.game.status() == (4, 4, 0, 0, 6, 6, 2, 5, 5, 4, 4, 4, 4, 0) self.game.play(4) assert self.game.status() == (5, 5, 0, 0, 6, 6, 2, 5, 5, 4, 4, 0, 5, 1) self.game.play(0) assert self.game.status() == (0, 6, 1, 1, 7, 7, 2, 5, 5, 4, 4, 0, 5, 1) self.assertRaises(ValueError, self.game.play, 4) self.game.play(0) assert self.game.status() == (0, 6, 1, 1, 7, 7, 2, 0, 6, 5, 5, 1, 6, 1) def test_captures(self): self.game.set_board([0, 0, 4, 4, 4, 9, 5, 5, 5, 4, 4, 4]) self.game.play(5) assert self.game.status() == (1, 0, 4, 4, 4, 0, 7, 6, 6, 6, 5, 0, 5, 0) self.game.set_board([4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 8]) self.game.play(5) assert self.game.status() == (5, 5, 5, 5, 5, 0, 7, 0, 4, 4, 4, 4, 0, 7) self.game.set_board([1, 0, 4, 5, 4, 5, 7, 7, 6, 6, 0, 3]) self.game.set_bank([0, 0]) self.game.play(0) assert self.game.status() == (0, 1, 4, 5, 4, 5, 0, 7, 7, 6, 6, 0, 3, 0) def test_f_play_win(self): self.game.set_board([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1]) self.game.set_bank([5, 1]) assert self.game.play(5) == "Player 1 wins" def test_s_play_win(self): self.game.set_board([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) self.game.set_bank([0, 1]) self.game.play(1) assert self.game.play(5) == "Player 2 wins" def test_tie(self): self.game.set_board([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) self.game.set_bank([0, 0]) self.game.play(1) assert self.game.play(5) == "Tie" def test_repr(self): assert repr( Kalah(6, 4) ) == "Kalah(4, 6, status=(4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0), player=0)"
def run_game(self, tree_visualization=True): for i in range(self.num_of_games): if self.am_i_minmax is True: self.user = Minimax() else: module, name = self.user_path.rsplit('.', 1) self.user = getattr(importlib.import_module(module), name)(number_of_simulation=500, simulation_depth=6) if self.is_user_defined_opponent: module, name = self.opponent_path.rsplit('.', 1) self.opponent = getattr(importlib.import_module(module), name)(number_of_simulation=1000) else: self.opponent = Minimax() print("New game!") print("Initial board >>") # initialization: initial_board = [4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0] new_game = Kalah(initial_board) if i % 2 == 1: new_game.player = False new_game.show_board() if not self.am_i_minmax: self.user.initial_root(initial_board) if self.is_user_defined_opponent: self.opponent.initial_root(initial_board) turn = 0 while not new_game.is_game_over(): turn += 1 # pick a hole: if new_game.player: start_time = time.time() next_position = self.user.search( copy.deepcopy(new_game.get_board())) end_time = time.time() print('measured time: ', end_time - start_time) self.is_time_out(start_time, end_time) else: next_position = self.opponent.search( copy.deepcopy(new_game.get_board())) # update: tmp_score, free_turn = new_game.move(next_position) # print: if not self.am_i_minmax: print("winning rate:", self.user.print_winning_rate(next_position)) if tree_visualization: show_image(self.user.g.render(view=False), auto_close=False) if not self.am_i_minmax: self.user.update_root(next_position, copy.deepcopy(new_game.get_board()), copy.deepcopy(new_game.player)) if self.is_user_defined_opponent: self.opponent.update_root( next_position, copy.deepcopy(new_game.get_board()), copy.deepcopy(not new_game.player)) # end of a game, print result: new_game.show_board() turn = 0 self.score_board(i, new_game.result()) del self.user del self.opponent
def test_capture_player_1(self): game = Kalah(6, 4) game.play('f') game.play('F') game.play('b') game.play('F') game.play('c') game.play('F') game.play('d') game.play('F') game.play('b') game.play('a') self.assertEqual(game.status(), (0, 5, 0, 1, 0, 0, 11, 1, 11, 7, 6, 6, 0, 0))
def setUp(self): self.game = Kalah(6, 4)
def test_initial_Status(self): game = Kalah(6, 4) self.assertEqual(game.status(), (4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0))
def test_bonus_move_player_2(self): game = Kalah(6, 4) game.play('f') self.assertEqual(game.play('D'), 'Player 2 plays next')
def test_empty_hole(self): game = Kalah(6, 4) game.play('e') game.play('A') game.play('f') self.assertRaises(ValueError, game.play, 'A')
def test_bonus_move_player_1(self): game = Kalah(6, 4) self.assertEqual(game.play('d'), 'Player 1 plays next')
def test_crossing_other_bank(self): game = Kalah(6, 4) game.play('e') game.play('E') game.play('d') game.play('D') game.play('c') game.play('C') game.play('b') game.play('B') game.play('a') game.play('A') self.assertEqual(game.status(), (9, 4, 3, 2, 2, 1, 4, 9, 4, 3, 2, 1, 0, 4))
def test_illegal_hole(self): game = Kalah(6, 4) self.assertRaises(IndexError, game.play, 'A')
def test_repr(self): assert repr(Kalah(6, 4)) == "Kalah(4, 6, status=(4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0), player=0)"
def test_crossing_move(self): game = Kalah(6, 4) game.play('a') self.assertEqual(game.status(), (4, 4, 4, 4, 4, 0, 1, 5, 5, 5, 4, 4, 4, 0))
def test_simple_move(self): game = Kalah(6, 4) game.play('f') self.assertEqual(game.status(), (0, 5, 5, 5, 5, 4, 0, 4, 4, 4, 4, 4, 4, 0))