def test_no_errors_when_playing_and_printing_games(): for i in range(100): player1 = RandomPlayer() player2 = RandomPlayer() observers = [GameStatePrinter(show_action_history=True)] game = TwoPlayerGame(State.empty(), player1, player2, observers) game.play()
def test_random_player_generate_move() -> None: """ Test the RandomPlayer class' generate_move method. """ goal = BlobGoal((0, 0, 0)) player1 = RandomPlayer(1, goal) player1._proceed = True b1 = Block((0, 0), 1000, (0, 0, 0), 0, 2) move1 = player1.generate_move(b1) assert isinstance(move1, tuple) and isinstance(move1[0], str) and \ (isinstance(move1[1], int) or move1[1] is None) and \ isinstance(move1[2], Block) if move1[0:2] == ('rotate', 1): assert move1[2].rotate(1) elif move1[0:2] == ('rotate', 3): assert move1[2].rotate(3) elif move1[0:2] == ('swap', 0): assert move1[2].swap(0) elif move1[0:2] == ('swap', 1): assert move1[2].swap(1) elif move1[0:2] == ('smash', None): assert move1[2].smash() elif move1[0:2] == ('paint', None): assert move1[2].paint(self.goal.colour) elif move1[0:2] == ('combine', None): assert move1[2].combine() else: assert False
def setUp(self): player_X = RandomPlayer('X') player_O = RandomPlayer('O') players = [player_X, player_O] self.tictactoe_state = TicTacToeState(players) return
def test_random_player(): wheel = create_wheel() rng = NonRandomOutcomeChoice(wheel) expected_outcomes = [wheel.get_outcome(n) for n in ["Black", "Low", "00"]] rng.set_outcomes(expected_outcomes) table = Table(wheel) random_player = RandomPlayer(table, rng=rng) bets = [random_player.next_bet() for i in range(3)] actual_outcomes = [b.outcome for b in bets] assert actual_outcomes == expected_outcomes
def test_smart_player(self, board_16x16) -> None: goal_smart = PerimeterGoal(COLOUR_LIST[1]) player_smart = SmartPlayer(1, goal_smart, 1) print(player_smart.difficulty) goal_random = PerimeterGoal(COLOUR_LIST[0]) player_random = RandomPlayer(10, goal_random) random_move = player_random.generate_move(board_16x16) #player_smart._proceed = True #x = player_smart.generate_move(board_16x16) assert 1
def test_player(game_board2): random.seed(1) goal = BlobGoal(COLOUR_LIST[1]) player = RandomPlayer(1, goal) player._proceed = True move = player.generate_move(game_board2) print(move) player2 = SmartPlayer(1, goal, 100) player2._proceed = True move2 = player2.generate_move(game_board2) print(move2)
def __init__(self, max_depth: int, num_human: int, random_players: int, smart_players: List[int]) -> None: """Initialize this game, as described in the Assignment 2 handout. Precondition: 2 <= max_depth <= 5 """ self.board = random_init(0, max_depth) self.board.update_block_locations((0, 0), BOARD_WIDTH) num_players = num_human + random_players + len(smart_players) self.renderer = Renderer(num_players) self.players = [] if random.random() < 0.5: for i in range(num_human): target = \ COLOUR_LIST[int(random.random() * len(COLOUR_LIST))] self.players.append(HumanPlayer(self.renderer, \ len(self.players), \ BlobGoal(target))) for i in range(random_players): target = \ COLOUR_LIST[int(random.random() * len(COLOUR_LIST))] self.players.append(RandomPlayer(self.renderer, \ len(self.players), \ BlobGoal(target))) for i in smart_players: target = \ COLOUR_LIST[int(random.random() * len(COLOUR_LIST))] self.players.append(SmartPlayer(self.renderer, \ len(self.players), \ BlobGoal(target), \ i)) else: for i in range(num_human): target = \ COLOUR_LIST[int(random.random() * len(COLOUR_LIST))] self.players.append(HumanPlayer(self.renderer, \ len(self.players), \ PerimeterGoal(target))) for i in range(random_players): target = \ COLOUR_LIST[int(random.random() * len(COLOUR_LIST))] self.players.append(RandomPlayer(self.renderer, \ len(self.players), \ PerimeterGoal(target))) for i in smart_players: target = \ COLOUR_LIST[int(random.random() * len(COLOUR_LIST))] self.players.append(SmartPlayer(self.renderer, \ len(self.players), \ PerimeterGoal(target), \ i)) self.renderer.draw(self.board, 0)
def test_unit_board(): random.seed(1) board = generate_board(1, BOARD_SIZE) goal = BlobGoal(COLOUR_LIST[1]) player = RandomPlayer(1, goal) player._proceed = True move = player.generate_move(board) print(move) player2 = SmartPlayer(1, goal, 1) player2._proceed = True move2 = player2.generate_move(board) print(move2)
def test_game(): state = State.empty() player1 = RandomPlayer('player 1') player2 = RandomPlayer('player 2') game = TwoPlayerGame(state, player1, player2) game._turn() game._turn() number_of_stones = sum((stone is not Color.NONE for stone in game.current_state.stones.values())) assert 2 == number_of_stones
def __init__(self, max_depth: int, num_human: int, random_players: int, smart_players: List[int]) -> None: """Initialize this game, as described in the Assignment 2 handout. Each player has a random target colour, and all players share the same goal(Players might have same target colour.) Precondition: 2 <= max_depth <= 5 """ self.board = random_init(0, max_depth) self.board.update_block_locations((0, 0), BOARD_WIDTH) num_player = num_human + random_players + len(smart_players) self.renderer = Renderer(num_player) self.players = [] random_num = random.randint(0, 1) for i in range(num_player): if random_num == 0: goal = BlobGoal(COLOUR_LIST[random.randint(0, 3)]) else: goal = PerimeterGoal(COLOUR_LIST[random.randint(0, 3)]) if i < num_human: self.players.append(HumanPlayer(self.renderer, i, goal)) elif num_human <= i < num_human + random_players: self.players.append(RandomPlayer(self.renderer, i, goal)) else: self.players.append( SmartPlayer( self.renderer, i, goal, smart_players[i - (num_human + random_players)])) # Display each player's goal before starting game. for i in range(num_player): self.renderer.display_goal(self.players[i])
def _generate_players(self, num_players: int, player_type: str, goal_type: str, start_id: int) -> List[Player]: """Generate a list of players with the given number of players, of the given type, with the given <goal_type>, with ids incrementing from <start_id>. Preconditions: player_type == 'human', 'random', or 'smart' goal_type == 'blob', or 'perimeter' """ player_list = [] player_count = 0 id_count = start_id while player_count < num_players: # Generate a blob goal or a perimeter goal with a random colour if goal_type == 'blob': goal = BlobGoal(COLOUR_LIST[random.randint(0, 3)]) else: goal = PerimeterGoal(COLOUR_LIST[random.randint(0, 3)]) # Generate a player of the given type, using goal if player_type == 'human': player = HumanPlayer(self.renderer, id_count, goal) elif player_type == 'random': player = RandomPlayer(self.renderer, id_count, goal) else: player = SmartPlayer(self.renderer, id_count, goal) # Add player to the player list, iterate counts by one player_list.append(player) player_count += 1 id_count += 1 return player_list
def main(num_trial): logging.basicConfig(level=logging.ERROR) g = MontyHallGame() p = RandomPlayer('Elle') switch_result = [0., 0] noswitch_result = [0., 0] start = time.time() for trial in xrange(num_trial): result = g.play(p) if p.switched: switch_result[1] += 1 switch_result[0] += result else: noswitch_result[1] += 1 noswitch_result[0] += result time_taken = time.time() - start print """ # of trials: {} Time taken: {} Approximated win rate: Switch: {} Not switch: {} """.format(num_trial, time_taken, switch_result[0]/switch_result[1], noswitch_result[0] / noswitch_result[1])
def set_players(self, num_human, random_players, smart_players): """Generate a common goal with different target colours for each players Each player gets player_id from 0 to total number of players. Add all of players to self.players """ rand_goal, num = random.randint(0, 1), 0 for _ in range(num_human): if rand_goal == 1: goal = BlobGoal(COLOUR_LIST[random.randint(0, 3)]) else: goal = PerimeterGoal(COLOUR_LIST[random.randint(0, 3)]) new_player = HumanPlayer(self.renderer, num, goal) self.renderer.display_goal(new_player) self.players.append(new_player) num += 1 for _ in range(random_players): if rand_goal == 1: goal = BlobGoal(COLOUR_LIST[random.randint(0, 3)]) else: goal = PerimeterGoal(COLOUR_LIST[random.randint(0, 3)]) self.players.append(RandomPlayer(self.renderer, num, goal)) num += 1 for i in range(len(smart_players)): if rand_goal == 1: goal = BlobGoal(COLOUR_LIST[random.randint(0, 3)]) else: goal = PerimeterGoal(COLOUR_LIST[random.randint(0, 3)]) self.players.append( SmartPlayer(self.renderer, num, goal, smart_players[i])) num += 1
def compareToRandom(self, games=500): """ Plays the current generation against the validation set for a given number of games and returns the results Output [ [wins_going_first, ties_going_first, losses_going_first], [wins_not_firsst, ties_not_first, losses_not_first] ] """ random_player = RandomPlayer(self.ruleset) wins = np.full((2, 3), 0) for i in range(games): player = random.choice(self.players) game = Game(self.ruleset, [player, random_player]) results = game.play() # If first wins_i = 0 if results[2] == 0 else 1 wins_i_i = None # win if results[0] == 0: wins_i_i = 0 if results[0] == None: # tie wins_i_i = 1 if results[0] == 1: # loss wins_i_i = 2 wins[wins_i][wins_i_i] += 1 return wins
def run_game(self, num_h, num_r, num_s): t = 0 l = [] for i in range(num_h): l.append(HumanPlayer(self.b)) t += 2 for i in range(num_r): l.append(RandomPlayer(self.b)) t += 2 for i in range(num_s): l.append(SmartPlayer(self.b, -1 + t)) t += 2 while not self.game_over(): for playr in l: self.draw_board() plm = playr.move() self.make_move(plm[0], plm[1]) print( '\n' + str(playr) + ' ' + str(l.index(playr)) + ' made move (' + str(plm[0]) + ', ' + str(plm[1]) + ')\n\n---------------------------------------------------\n' ) if self.game_over(): print('\n\n' + str(playr) + ' ' + str(l.index(playr)) + ' Lost') return l.index(playr)
def measure_train_sets_generation(player_a, player_b, n_games): def _measure_for_train_set(tra, trb, train_only=False, do_partial_fit=False, train_set_games=1000): if not train_only: print("Train set: {} vs {}. Number of games in set: {}".format( tra, trb, train_set_games)) train = prepare_supervised_train_set(tra, tra, 3, n_games=train_set_games) X, Y = train if hasattr(player_a, "classifier"): if do_partial_fit: if hasattr(player_a.classifier, "partial_fit"): player_a.classifier.partial_fit(X, Y) else: return else: player_a.classifier.fit(X, Y) if hasattr(player_b, "classifier"): if do_partial_fit: if hasattr(player_b.classifier, "partial_fit"): player_b.classifier.partial_fit(X, Y) else: return else: player_b.classifier.fit(X, Y) if not train_only: test(player_a, player_b, ui=False, n_games=n_games) print("Measuring for {} and {}, number of games: {}".format( player_a, player_b, n_games)) print("Now measuring train set sizes:") for i in [2, 10, 100, 500, 1000, 5000, 10000]: _measure_for_train_set(RandomPlayer("RandomPlayer"), RandomPlayer("RandomPlayer"), train_set_games=i) print("Now measuring different train sets:") _measure_for_train_set(RandomPlayer("RandomPlayer"), RandomPlayer("RandomPlayer")) _measure_for_train_set(player_a, player_b) _measure_for_train_set(RandomPlayer("RandomPlayer"), RandomPlayer("RandomPlayer"), train_only=True) _measure_for_train_set(player_a, player_a) _measure_for_train_set(RandomPlayer("RandomPlayer"), RandomPlayer("RandomPlayer"), train_only=True) _measure_for_train_set(player_b, player_b)
def __init__(self, players={ 'mikko': HumanPlayer(), 'beta-ai': RandomPlayer() }): self.players = players player_names = list(players.keys()) shuffle(player_names) self.game_state = dominion.GameState(player_names)
def test_greedy_is_better_than_random(): state = State.empty() player1 = RandomPlayer('player 1') player2 = GreedyPlayer('player 2') game = TwoPlayerGame(state, player1, player2) game.play() assert Color.BROWN == game.current_state.winner
def __init__(self, table_size=100): self.table_size = table_size self.table = Table(table_size) self.players = [ RandomPlayer(self.table, 'Player one random'), MemoryPlayer(1, self.table, 'Player two memory'), MemoryPlayer(1, self.table, 'Player three memory'), ] self.counter = 1 self.mongodb = MongoClient().pexes
def test_random_player__init__() -> None: """ Test the __init__ method of the RandomPlayer class. """ goal = BlobGoal((0, 0, 0)) player = RandomPlayer(1, goal) assert player.id == 1 assert player.goal is goal assert not player._proceed
def test_depth_5_board(renderer): random.seed(1002) board = generate_board(5, BOARD_SIZE) renderer.draw_board(_block_to_squares(board)) renderer.save_to_file('board_5_ref.png') renderer.clear() goal1 = BlobGoal(COLOUR_LIST[0]) # blue goal2 = BlobGoal(COLOUR_LIST[1]) # red player1 = RandomPlayer(1, goal1) player2 = RandomPlayer(2, goal2) player1._proceed = True move1 = player1.generate_move(board) move1_block = move1[2] to_do = _get_block(board, move1_block.position, move1_block.level) assert move1[0] == "swap" and move1[1] == 0 assert to_do.swap(0) renderer.draw_board(_block_to_squares(board)) renderer.save_to_file('board_5_move1.png') renderer.clear() afterfirst1 = goal1.score(board) afterfirst2 = goal2.score(board) player2._proceed = True move2 = player2.generate_move(board) move2_block = move2[2] to_do_2 = _get_block(board, move2_block.position, move2_block.level) assert move2[0] == "smash" assert to_do_2.smash() renderer.draw_board(_block_to_squares(board)) renderer.save_to_file('board_5_move2.png') renderer.clear() aftersecond1 = goal1.score(board) aftersecond2 = goal2.score(board) player1._proceed = True move3 = player1.generate_move(board) move3_block = move3[2] to_do_3 = _get_block(board, move3_block.position, move3_block.level) assert move3[0] == "rotate" and move3[1] == 3 assert to_do_3.rotate(3) renderer.draw_board(_block_to_squares(board)) renderer.save_to_file('board_5_move3.png') renderer.clear() afterthird1 = goal1.score(board) afterthird2 = goal2.score(board)
def train_q_player(board_size, train_set_size): random = RandomPlayer("Random") q_player = QPlayer("QPlayer", 0.5, 0.1) game_executor = GameExecutor(q_player, random) game_executor.train_q_player(board_size=board_size, q_player=q_player, starting_player=PLAYER_X, n_games=train_set_size, with_ui=False) return q_player
def __init__(self, max_depth: int, num_human: int, random_players: int, smart_players: List[int]) -> None: """Initialize this game, as described in the Assignment 2 handout. Precondition: 2 <= max_depth <= 5 """ self.max_depth = max_depth self.num_human = num_human self.random_players = random_players self.smart_players = smart_players self.num_players = num_human + random_players + len(smart_players) # 1 create a Renderer for this game self.renderer = Renderer(self.num_players) # 2 Generate a random goal typr, for all players to share potential_goal = [ BlobGoal(COLOUR_LIST[0]), PerimeterGoal(COLOUR_LIST[0]) ] self.goal = potential_goal[random.randint(0, 1)] # 3 Generate a random board, with the given maximum depth self.board = random_init(0, max_depth) self.board.update_block_locations((0, 0), 750) # 4 Generate the right number of human players, random players, # and smart players self.players = [] for human_id in range(num_human): self.players.append(HumanPlayer(self.renderer, human_id, self.goal)) for ran_id in range(num_human, num_human + random_players): self.players.append(RandomPlayer(self.renderer, ran_id, self.goal)) for smart_id in range(num_human + random_players, self.num_players): difficulty_level = smart_players[smart_id - num_human - random_players] self.players.append( SmartPlayer(self.renderer, smart_id, self.goal, difficulty_level)) for player in self.players: player.goal.colour = COLOUR_LIST[random.randint(0, 3)] if isinstance(self.goal, BlobGoal): player.goal = BlobGoal(player.goal.colour) else: player.goal = PerimeterGoal(player.goal.colour) if isinstance(player, HumanPlayer): self.renderer.display_goal(player) # 5 before returning, draw the board for player_id in range(len(self.players)): self.renderer.draw(self.board, player_id)
def __init__(self, max_depth: int, num_human: int, random_players: int, smart_players: List[int]) -> None: """Initialize this game, as described in the Assignment 2 handout. Precondition: 2 <= max_depth <= 5 """ # Create the board self.board = random_init(0, max_depth) self.board.update_block_locations((0, 0), BOARD_WIDTH) # Generate a goal goals = [BlobGoal, PerimeterGoal] index = random.randrange(0, 2) goal = goals[index] # Create render num_players = num_human + random_players + len(smart_players) self.renderer = Renderer(num_players) # Create players self.players = [] val = 0 for id_ in range(num_human): # Create a colour for this player index = random.randrange(0, 4) colour = COLOUR_LIST[index] self.players.append(HumanPlayer(self.renderer, id_, goal(colour))) val += 1 for id_ in range(random_players): # Create a colour for this player index = random.randrange(0, 4) colour = COLOUR_LIST[index] self.players.append(RandomPlayer(self.renderer, val, goal(colour))) val += 1 # A SmartPlayer has a difficulty level if len(smart_players) > 0: for id_ in range(len(smart_players)): # Create a colour for this player index = random.randrange(0, 4) colour = COLOUR_LIST[index] self.players.append(SmartPlayer(self.renderer, val, goal(colour), smart_players[id_])) val += 1 # Display the goal and draw the board for i in self.players: self.renderer.display_goal(i) self.renderer.draw(self.board, i.id)
def run(): parse = argparse.ArgumentParser(description="gomoku program") parse.add_argument("player1", type=int, choices=[1, 2, 3, 4], help="1.Human; 2.MCTS; 3.Random; 4.Expert") parse.add_argument("player2", type=int, choices=[1, 2, 3, 4], help="1.Human; 2.MCTS; 3.Random; 4.Expert") parse.add_argument("--size", type=int, default=8, help="The Board size,default is 8*8 ") parse.add_argument("--simulate_time", type=int, default=2, help="The MCTS playout simulation time,default is 2s ") args = parse.parse_args() chess = Gomoku(board_size=args.size) p1 = { 1: HumanPlayer(chess), 2: MCTSPlayer(chess, simulate_time=args.simulate_time), 3: RandomPlayer(chess), 4: ExpertPlayer(chess) } p2 = { 1: HumanPlayer(chess), 2: MCTSPlayer(chess, simulate_time=args.simulate_time), 3: RandomPlayer(chess), 4: ExpertPlayer(chess) } chess.play(p1[args.player1], p2[args.player2], isShow=True)
def __init__(self, max_depth: int, num_human: int, random_players: int, smart_players: List[int]) -> None: """Initialize this game, as described in the Assignment 2 handout. Precondition: 2 <= max_depth <= 5 """ game_goal = [] self.players = [] num_players = num_human + random_players + len(smart_players) self.renderer = Renderer(num_players) # rand_num = random.randint(0, 1) # for i in range(num_players): # game_goal.append([ # PerimeterGoal( # COLOUR_LIST[random.randint(0, 3)] # ), # BlobGoal( # COLOUR_LIST[random.randint(0, 3)] # ) # ][rand_num] # ) if random.randint(0, 1) == 0: for i in range(num_players): game_goal.append( PerimeterGoal(COLOUR_LIST[random.randint(0, 3)])) else: for i in range(num_players): game_goal.append(BlobGoal(COLOUR_LIST[random.randint(0, 3)])) self.board = random_init(0, max_depth) self.board.update_block_locations((0, 0), BOARD_WIDTH) for i in range(num_players): if i < num_human: self.players.append(HumanPlayer(self.renderer, i, game_goal[i])) elif i < random_players + num_human: self.players.append( RandomPlayer(self.renderer, i, game_goal[i])) else: self.players.append( SmartPlayer(self.renderer, i, game_goal[i], smart_players[i - random_players - num_human])) for player in self.players: self.renderer.display_goal(player) # self.renderer.draw(self.board, 0) for i in range(num_players): self.renderer.draw(self.board, i)
def text_get_rules(default=0): size = -1 while size < 1: try: if not default: size = int(input('Board size: ')) else: size = DEFAULTS[default]['size'] except ValueError: pass swap = False while swap not in ('y', 'n'): if not default: swap = input('allow swap rule? (y/n): ') else: swap = DEFAULTS[default]['swap'] swap = (swap == 'y') if not default: player = [None] * 3 else: player = DEFAULTS[default]['players'] for i in (1, -1): if player[i] is not None: continue player_type = -1 while not (0 <= player_type <= 5): try: player_type = int(input( '0 - Text\n1 - Gui\n2 - Random (AI)\n3 - Alpha-Beta Search (AI)\n' '4 - Monte-Carlo Search (AI)\n5 - Charge Heuristic (AI)\nplayer %d type?: ' % ( i % 3))) except ValueError: pass if player_type == 0: player[i] = TextPlayer(i) elif player_type == 1: player[i] = GuiPlayer(i) elif player_type == 2: player[i] = RandomPlayer(i) elif player_type == 3: player[i] = build_alpha_beta_player(i, size) elif player_type == 4: player[i] = build_monte_carlo_player(i, size) elif player_type == 5: player[i] = ChargeHeuristicPlayer(i, size) board = HexBoard(size, swap) return board, player
def __init__(self, max_depth: int, num_human: int, random_players: int, smart_players: List[int]) -> None: """Initialize this game, as described in the Assignment 2 handout. Precondition: 2 <= max_depth <= 5 """ self.players = [] num_players = num_human + random_players + len(smart_players) self.renderer = Renderer(num_players) decider = random.randint(0, 1) # the random value ( 0 or 1 ) which we use it to # determine the goal of the game for i in range(num_players): c = COLOUR_LIST[random.randint(0, len(COLOUR_LIST) - 1)] # creating the random colour to assign to the player if decider == 0: # determining the random goal to the game goal = BlobGoal(c) else: goal = PerimeterGoal(c) if i < num_human: # first adding the human players self.players.append(HumanPlayer(self.renderer, i, goal)) self.renderer.display_goal(self.players[i]) # shows the goal of the player to him/her elif i < num_human + random_players: # adding the random players self.players.append(RandomPlayer(self.renderer, i, goal)) self.renderer.display_goal(self.players[i]) # shows the goal of the player else: level = smart_players[i - (num_human + random_players)] # it determines the difficulty level of the smartplayer which # is actualy the value of the smartplayer[index] # adding the smart players self.players.append(SmartPlayer(self.renderer, i, goal, level)) self.renderer.display_goal(self.players[i]) # shows the goal of the player self.board = random_init(0, max_depth) # make the board game with the given max_depth self.board.update_block_locations((0, 0), BOARD_WIDTH)
def main(p1, p2, stones_per_turn): players = [] if p1 == 'human' or p1 == 'h': players.append(HumanPlayer()) elif p1 == 'random' or p1 == 'r': players.append(RandomPlayer()) else: raise Exception("Unkown player 1 type.") if p2 == 'human' or p2 == 'h': players.append(HumanPlayer()) elif p2 == 'random' or p2 == 'r': players.append(RandomPlayer()) else: raise Exception("Unkown player 2 type.") GS = GameState(stones_per_turn, players) while not GS.game_is_over(): GS.play() return
def _create_player(self, num_human: int, random_players: int, smart_players: List[int]) -> None: """Generate a random goal type, for all players to share. Generate the right number of human players, random players, and smart players (with the given difficulty levels), in that order. Give the players consecutive player numbers, starting at 0. Assign each of them a random target colour and display their goal to them. """ # Create a list of goal for use in randomizing goals goal = [BlobGoal, PerimeterGoal] # Generate a random goal for all player to share rand_goal = random.choice(goal) self.players = [] # Store the current player id player_id = 0 # Generate HumanPLayer(s) and add it to the list of players for _ in range(num_human): # Randomize the target colours rand_num = random.randint(0, 3) human = HumanPlayer(self.renderer, player_id, rand_goal(COLOUR_LIST[rand_num])) self.players.append(human) self.renderer.display_goal(human) player_id += 1 # Generate RandomPlayer(s) and add it to the list of players for _ in range(random_players): # Randomize the target colours rand_num = random.randint(0, 3) rand_player = RandomPlayer(self.renderer, player_id, rand_goal(COLOUR_LIST[rand_num])) self.players.append(rand_player) self.renderer.display_goal(rand_player) player_id += 1 # Generate SmartPlayer(s) and add it to the list of players for difficulty in smart_players: # Randomize the target colours rand_num = random.randint(0, 3) smart_player = SmartPlayer(self.renderer, player_id, rand_goal(COLOUR_LIST[rand_num]), difficulty) self.players.append(smart_player) self.renderer.display_goal(smart_player) player_id += 1