def test_drop_piece(): """ Adds a new piece to the board & returns True. False if new piece can't be added to that column. """ test_board = c4.create_board() c4.drop_piece(1, c4.HUMAN, test_board) assert test_board[-1][1] == c4.HUMAN c4.drop_piece(2, c4.AI, test_board) assert test_board[-1][2] == c4.AI c4.drop_piece(1, c4.HUMAN, test_board) assert test_board[-2][1] == c4.HUMAN for i in range(6): c4.drop_piece(6, c4.HUMAN, test_board) assert c4.drop_piece(6, c4.AI, test_board) == False
def alphabeta(board, turn, depth, a, b): possible_moves = get_possible_moves(board) #TERMINAL CASES #Case 1: board is a winning state for human if winning_board(board, 1): return MoveInfo(-1) #Case 2: board is a winning state for ai elif winning_board(board, 2): return MoveInfo(1) #Case 3: tie elif possible_moves == [] or depth == 0: return MoveInfo(board_evaluation(board, possible_moves, turn)) #search for move best_move = None value = -INFINITY if turn == 1 else INFINITY for move in possible_moves: piece_type = turn + 1 new_board = copy.deepcopy(board) row = connect4.get_next_open_row(new_board, move) connect4.drop_piece(new_board, row, move, piece_type) child = alphabeta(new_board, (turn + 1) % 2, depth - 1, a, b) if (child.score > value and turn == 1) or (child.score < value and turn != 1): best_move = move value = child.score if turn == 1: a = max(a, value) if turn != 1: b = min(b, value) if a >= b: break return MoveInfo(value, best_move)
def main(): board = c4.create_board() game_over = False is_human = True while not game_over: c4.print_board(board) player = c4.HUMAN if is_human else c4.AI if is_human: print("Your turn") selection = c4.make_selection(c4.HUMAN) if selection is None: continue else: print("AI turn") time.sleep(1) selection = select_column(board) d = c4.drop_piece(selection, player, board) if not d: continue if c4.is_winning_move(board): c4.print_board(board) print(f"-----------\nPLAYER {player} IS THE WINNER!") game_over = True is_human = not is_human
if currentplayer == 1 and human > 0: open_columns = connect4.open_columns() print "Open columns: " + str(open_columns) column = input("Player " + str(currentplayer) + " choose an open column to drop your piece in: \n") while column not in open_columns: print "ERROR: " + str(column) + " is not a valid open column" print "Open columns: " + str(open_columns) column = input("Player " + str(currentplayer) + " choose an open column to drop your piece in: \n") winner = connect4.drop_piece(column, currentplayer) #ai player 1 move elif currentplayer == 1: column = ai1.analyze_choices(4, 1, -sys.maxint, sys.maxint)[1] print "DROP AT: " + str(column) winner = connect4.drop_piece(column, currentplayer) #ai player 2 move else: column = ai2.analyze_choices(4, 2, -sys.maxint, sys.maxint)[1] print "DROP AT: " + str(column) winner = connect4.drop_piece(column, currentplayer) #if no winner, switch players if winner != True: if currentplayer == 1:
def analyze_choices(self, depth, player, alpha, beta): if depth == 0: return [self.evaluate(), -1] elif player == self.ai: v = -sys.maxint maxcolumn = -1 columns = connect4.open_columns() if len(columns) == 0: return [self.TIE_SCORE, -1] for column in columns: win = connect4.drop_piece(column, player) if win == True: connect4.undo_piece(column) return [self.FOUR_SCORE * self.SELF_SCORE, column] score = self.analyze_choices(depth-1,self.opponent, alpha, beta)[0] connect4.undo_piece(column) if score > v: v = score maxcolumn = column if v > alpha: alpha = v if beta <= alpha: break return [v, maxcolumn] else: v = sys.maxint mincolumn = -1 columns = connect4.open_columns() if len(columns) == 0: return [self.TIE_SCORE, -1] for column in columns: win = connect4.drop_piece(column, player) if win == True: connect4.undo_piece(column) return [self.FOUR_SCORE * self.OPPONENT_SCORE * -1, column] score = self.analyze_choices(depth-1,self.ai, alpha, beta)[0] connect4.undo_piece(column) if score < v: v = score mincolumn = column if v < beta: beta = v if beta <= alpha: break return [v, mincolumn]
if event.type == QUIT: pygame.quit() sys.exit() if computers == 2: if winner != True: print ai1 column = ai1.analyze_choices(ai1.MAX_DEPTH, 1, -sys.maxint, sys.maxint)[1] for i in range(6): if connect4.board[i][column] != 0: row = i - 1 break elif i == 5: row = i break dropped = connect4.drop_piece(column, 1) print pygame.time.get_ticks() - lastmove lastmove = pygame.time.get_ticks() if dropped == True: font = pygame.font.Font(None, 75) text = "Player 1 Wins!" end = font.render("Player 1 Wins!", 0, (255, 0, 0), None) DISPLAYSURF.blit(end, (0, 0)) winner = True tile = pygame.image.load("redtile.png") board_display[row][column] = tile DISPLAYSURF.blit(board_display[row][column], (column * 52, row * 52)) pygame.display.update() if winner != True: print ai2
def minimax(board, turn, depth): """performs minimax algorithm on board bounded by [depth] value given """ possible_moves = get_possible_moves(board) #Case 1: board is a winning state for human if winning_board(board, 1): return MoveInfo(-1) #Case 2: board is a winning state for ai elif winning_board(board, 2): return MoveInfo(1) #Case 3: tie elif possible_moves == []: return MoveInfo(0) elif depth == 0: return MoveInfo(board_evaluation(board, possible_moves, turn)) move_information = [] #keeps track of minimax values for moves for move in possible_moves: #get board generated by playing move if turn == 0: piece_type = 1 else: piece_type = 2 new_board = copy.deepcopy(board) row = connect4.get_next_open_row(new_board, move) connect4.drop_piece(new_board, row, move, piece_type) #minimax on board move_info = minimax(new_board, (turn + 1) % 2, depth - 1) move_info.move = move #track move information move_information.append(move_info) #maximize score for ai if turn == 1: bestScore = -10000 curr_idx = 0 best_idx = 0 while curr_idx < len(move_information): #print(turn) #print(move_information[curr_idx]) if move_information[curr_idx].score > bestScore: bestScore = move_information[curr_idx].score best_idx = curr_idx elif move_information[curr_idx].score == bestScore: new_best = random.randint(0, 1) if (new_best == 1): best_idx = curr_idx curr_idx += 1 return move_information[best_idx] #minimize score for human bestScore = 10000 curr_idx = 0 best_idx = 0 while curr_idx < len(move_information): #print(turn) #print(move_information[curr_idx]) if move_information[curr_idx].score < bestScore: bestScore = move_information[curr_idx].score best_idx = curr_idx elif move_information[curr_idx].score == bestScore: new_best = random.randint(0, 1) if (new_best == 1): best_idx = curr_idx curr_idx += 1 return move_information[best_idx]