diff --git a/Main.gd b/Main.gd index 82146c8..ea47a80 100644 --- a/Main.gd +++ b/Main.gd @@ -81,56 +81,148 @@ func _process(_delta): ai_move(team2, board_to_text_board(board)) if click_spot() == Vector2(7,1): ai_move(team1, board_to_text_board(board)) + if click_spot() == Vector2(6,0): + ai_move(team2, board_to_text_board(board), ai_modes.weighted_random) + if click_spot() == Vector2(6,1): + ai_move(team1, board_to_text_board(board), ai_modes.weighted_random) enum ai_modes { purely_random, + weighted_random, + minimax_depth_2, +} + +var ai_weights = { + pawn = 10, + knight = 30, + bishop = 30, + rook = 50, + queen = 80, + king = 1000, } func ai_move(team, text_board, ai_mode=ai_modes.purely_random): var legal_every_move = team_every_legal_move(text_board, team) - legal_every_move.shuffle() if ai_mode == ai_modes.purely_random: - while 1: - var piece_and_moves = legal_every_move.pop_back() - if piece_and_moves: - pass - else: - break # AI literally cannot move this turn, game should be offically over before this occurs - var piece = piece_and_moves[0] - var moves = piece_and_moves[1] - if moves: - print(moves) - moves.shuffle() - var move = moves.pop_back() - var pos = position_to_board_cell(Vector2(piece[0] * board_cell, piece[1] * board_cell)) - var board_piece = board[pos[0]][pos[1]] - board_piece.position = in_square(Vector2(move[0] * board_cell, move[1] * board_cell)) - if board[move[0]][move[1]]: - board[move[0]][move[1]].kill() - board[move[0]][move[1]] = board_piece - board[pos[0]][pos[1]] = 0 - - if move.size() == 3: - if move[2] == movement_condition.en_passant_kill: - kill_en_passant_pawn([move[0], move[1]]) - elif move[2] == movement_condition.king_side_castling: - # TODO hard coding rook positions like this seems bad - var rook = board[7][pos[1]] - rook.position = in_square(Vector2(5 * board_cell, pos[1] * board_cell)) - board[5][pos[1]] = board[7][pos[1]] - board[7][pos[1]] = 0 - elif move[2] == movement_condition.queen_side_castling: - # TODO hard coding rook positions like this seems bad - var rook = board[0][pos[1]] - rook.position = in_square(Vector2(3 * board_cell, pos[1] * board_cell)) - board[3][pos[1]] = board[0][pos[1]] - board[0][pos[1]] = 0 - #print("piece at (%s,%s), to (%s,%s)" % [ piece[0], piece[1], move[0], move[1] ]) - break - else: - continue + ai_random_move(legal_every_move) + elif ai_mode == ai_modes.weighted_random: + ai_weighted_random(team, text_board, legal_every_move) new_turn() +func ai_make_move(piece, move): + var pos = position_to_board_cell(Vector2(piece[0] * board_cell, piece[1] * board_cell)) + var board_piece = board[pos[0]][pos[1]] + board_piece.position = in_square(Vector2(move[0] * board_cell, move[1] * board_cell)) + if board[move[0]][move[1]]: + board[move[0]][move[1]].kill() + board[move[0]][move[1]] = board_piece + board[pos[0]][pos[1]] = 0 + + if move.size() == 3: + if move[2] == movement_condition.en_passant_kill: + kill_en_passant_pawn([move[0], move[1]]) + elif move[2] == movement_condition.king_side_castling: + # TODO hard coding rook positions like this seems bad + var rook = board[7][pos[1]] + rook.position = in_square(Vector2(5 * board_cell, pos[1] * board_cell)) + board[5][pos[1]] = board[7][pos[1]] + board[7][pos[1]] = 0 + elif move[2] == movement_condition.queen_side_castling: + # TODO hard coding rook positions like this seems bad + var rook = board[0][pos[1]] + rook.position = in_square(Vector2(3 * board_cell, pos[1] * board_cell)) + board[3][pos[1]] = board[0][pos[1]] + board[0][pos[1]] = 0 + +func ai_random_move(legal_every_move): + legal_every_move.shuffle() + while 1: + var piece_and_moves = legal_every_move.pop_back() + if ! piece_and_moves: + if ! legal_every_move: + break # AI literally cannot move this turn, game should be offically over before this occurs + var piece = piece_and_moves[0] + var moves = piece_and_moves[1] + if moves: + #rint(moves) + moves.shuffle() + var move = moves.pop_back() + ai_make_move(piece, move) + return + else: + continue + +func ai_weighted_random(team, text_board, legal_every_move): + # generate a board with 'points' on it. + # if move[x],move[y] corrispond over some points keep the move in memory. then, sort move by smallest to greatest points + # pop_back() to get 'best move'. if there are no moves, just do random movement. + var p_board = generate_points_board(team, text_board) + var saved_moves = [] + for every_move in legal_every_move: + var piece = every_move[0] + var moves = every_move[1] + if moves: + for move in moves: + if p_board[move[0]][move[1]] > 0: + saved_moves.append([p_board[move[0]][move[1]], piece, move]) + else: + continue + if saved_moves.size() > 0: + saved_moves.shuffle() + #rint(saved_moves) + saved_moves.sort_custom(self, "sort_ascending") # sort, by smallest to greatest, then pop_back() + print(saved_moves) + var the_move = saved_moves.pop_back() + ai_make_move(the_move[1], the_move[2]) + else: + ai_random_move(legal_every_move) + +func sort_ascending(a, b): + if a[0] < b[0]: + return true + return false + +func generate_points_board(team, text_board): + var p_board = new_board() + for i in 8: + for k in 8: + var piece = text_board[i][k] + if piece: + match piece[0]: + piece_names.pawn: + if piece[1] == team: + p_board[i][k] = -1 * ai_weights.pawn + else: + p_board[i][k] = ai_weights.pawn + piece_names.rook: + if piece[1] == team: + p_board[i][k] = -1 * ai_weights.rook + else: + p_board[i][k] = ai_weights.rook + piece_names.knight: + if piece[1] == team: + p_board[i][k] = -1 * ai_weights.knight + else: + p_board[i][k] = ai_weights.knight + piece_names.bishop: + if piece[1] == team: + p_board[i][k] = -1 * ai_weights.bishop + else: + p_board[i][k] = ai_weights.bishop + piece_names.queen: + if piece[1] == team: + p_board[i][k] = -1 * ai_weights.queen + else: + p_board[i][k] = ai_weights.queen + piece_names.king: + if piece[1] == team: + p_board[i][k] = -1 * ai_weights.king + else: + p_board[i][k] = ai_weights.king + else: + p_board[i][k] = 0 + return p_board + func new_turn(): check_for_promotion() var text_board = board_to_text_board(board)