add weighted movement for ai, so it'll intentionally capture things

This commit is contained in:
jake 2023-02-21 20:16:17 -05:00
parent da75e49e23
commit 43faa277bb

172
Main.gd
View file

@ -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)