add ai movement based on 'points' gained/lost

This commit is contained in:
jake 2023-02-24 20:38:00 -05:00
parent 265b50e1de
commit fb3f5d1394
2 changed files with 139 additions and 27 deletions

158
Main.gd
View file

@ -34,13 +34,18 @@ var team2 = 2
func _ready():
make_player1("green")
make_player2("red")
#make_player2("red")
#checkmatet1()
#checkmatet2()
#spawn_piece("pawn", "teal", 2, 6, team1)
#spawn_piece("pawn", "red", 3, 4, team2)
#spawn_piece("rook", "red", 0, 5, team2)
#spawn_piece("pawn", "teal", 2, 1, team1)
#spawn_piece("knight", "teal", 4, 6, team1)
#spawn_piece("knight", "teal", 5, 4, team1)
#spawn_piece("rook", "teal", 7, 6, team1)
#spawn_piece("queen", "red", 3, 5, team2)
#spawn_piece("pawn", "red", 7, 1, team2)
var captures = update_capture_tables(board_to_text_board(board))
team1_capture = captures[0]
@ -73,10 +78,18 @@ func _process(_delta):
if click_spot() == Vector2(0,0):
print(history)
if click_spot() == Vector2(1,0):
print("Queuing for team2...")
ai_move(team2, board_to_text_board(board), ai_modes.points, 1)
if click_spot() == Vector2(1,1):
print("Killing pawn: %s" % [evaluate_move([3,5], [2,6], board_to_text_board(board), team2, 1)])
print("Killing knight: %s" % [evaluate_move([3,5], [4,6], board_to_text_board(board), team2, 1)])
print("Going to (3,1): %s" % [evaluate_move([3,5], [3,1], board_to_text_board(board), team2, 1)])
print("Going to (3,4) (enemy controlled): %s" % [evaluate_move([3,5], [3,4], board_to_text_board(board), team2, 1)])
if click_spot() == Vector2(1,2):
#print(team2_every_legal_move(board_to_text_board(board)))
print("whoops")
if click_spot() == Vector2(2,0):
print(board_to_text_board(board))
print("Queuing for team1...")
ai_move(team1, board_to_text_board(board), ai_modes.points, 1)
#print("Killing queen: %s" % evaluate_move([2,6], [3,5], board_to_text_board(board), team1, 1))
if click_spot() == Vector2(4,0):
color_tiles(team2_capture, "red")
if click_spot() == Vector2(5,0):
@ -93,7 +106,7 @@ func _process(_delta):
enum ai_modes {
purely_random,
weighted_random,
minimax_depth_2,
points,
}
var ai_weights = {
@ -101,30 +114,110 @@ var ai_weights = {
knight = 30,
bishop = 30,
rook = 50,
queen = 80,
queen = 500,
king = 1000,
}
func ai_move(team, text_board, ai_mode=ai_modes.purely_random):
func ai_move(team, text_board, ai_mode=ai_modes.purely_random, depth=1):
var legal_every_move = team_every_legal_move(text_board, team)
var the_move
if ai_mode == ai_modes.purely_random:
ai_random_move(legal_every_move)
the_move = ai_random_move(team, text_board, legal_every_move)
elif ai_mode == ai_modes.weighted_random:
ai_weighted_random(team, text_board, legal_every_move)
elif ai_mode == ai_modes.minimax_depth_2:
ai_minimax_depth_2(team, text_board, legal_every_move)
the_move = ai_weighted_random(team, text_board, legal_every_move)
elif ai_mode == ai_modes.points:
the_move = ai_points_system(team, legal_every_move, text_board, depth)
#print(the_move)
if the_move:
if the_move[1]:
ai_make_move(the_move[1], the_move[2])
new_turn()
func ai_minimax_depth_2(team, text_board, legal_every_move):
pass
func ai_points_system(team, legal_moves, text_board, depth=2):
var best = [-INF, null]
var alpha = -INF
var beta = -INF
legal_moves.shuffle()
for every_moves in legal_moves:
var piece = every_moves[0]
var moves = every_moves[1]
for move in moves:
var eval = evaluate_move(piece, move, text_board, team, depth)
#var eval = eval_move2(piece, move, text_board, team, depth)
if eval > best[0]:
best = [eval, piece, move]
print("This move is worth: %s" % best[0])
return best
func evaluate_move(piece, move, text_board, team, depth, add_points=false):
var p_board = generate_points_board(team, text_board)
var points = p_board[move[0]][move[1]]
if depth == 0 or depth <= 0:
return points
# evaluate opposing team now
var eval_board
eval_board = ai_text_board_move(text_board.duplicate(true), piece, move)
var legal_moves
if team == team1:
legal_moves = team_every_legal_move(eval_board, team2)
else: # team2
legal_moves = team_every_legal_move(eval_board, team1)
var highest_opposing_points = 0
for every_moves in legal_moves:
var this_piece = every_moves[0]
for this_move in every_moves[1]:
var eval
if team == team1:
eval = evaluate_move(this_piece, this_move, eval_board.duplicate(true), team2, depth-1, !add_points)
else: # team2
eval = evaluate_move(this_piece, this_move, eval_board.duplicate(true), team1, depth-1, !add_points)
if eval > highest_opposing_points:
#rint("Piece at (%s) moves to (%s), gaining %s points" % [this_piece, this_move, eval])
highest_opposing_points = eval
if add_points:
points += highest_opposing_points
else:
points -= highest_opposing_points
return points
func ai_text_board_move(text_board, piece, move):
var new_board = text_board.duplicate(true)
var pos = new_board[piece[0]][piece[1]]
pos[text_board_ele.has_moved] = true
new_board[move[0]][move[1]] = pos
new_board[piece[0]][piece[1]] = 0
if move.size() == 3:
#rint(new_board[move[0]][move[1] - 1])
if move[2] == movement_condition.en_passant_kill:
if move[1] + 1 < 8 and new_board[move[0]][move[1] + 1] is Array and new_board[move[0]][move[1] + 1][text_board_ele.en_passant]:
new_board[ move[0] ][(move[1] + 1)] = 0
elif move[1] - 1 > 0 and new_board[move[0]][(move[1] - 1)] is Array and new_board[move[0]][move[1] - 1][text_board_ele.en_passant]:
new_board [move[0] ][(move[1] - 1)] = 0
elif move[2] == movement_condition.king_side_castling:
# TODO hard coding rook positions like this seems bad
var rook = new_board[7][pos[1]]
new_board[5][pos[1]] = rook
new_board[7][pos[1]] = 0
elif move[2] == movement_condition.queen_side_castling:
# TODO hard coding rook positions like this seems bad
var rook = new_board[0][pos[1]]
new_board[3][pos[1]] = rook
new_board[0][pos[1]] = 0
return new_board
func ai_make_move(piece, move):
#rint(piece)
#rint(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[move[0]][move[1]].has_moved = true
board[pos[0]][pos[1]] = 0
if move.size() == 3:
@ -143,7 +236,7 @@ func ai_make_move(piece, move):
board[3][pos[1]] = board[0][pos[1]]
board[0][pos[1]] = 0
func ai_random_move(legal_every_move):
func ai_random_move(team, text_board, legal_every_move):
legal_every_move.shuffle()
while 1:
var piece_and_moves = legal_every_move.pop_back()
@ -156,16 +249,14 @@ func ai_random_move(legal_every_move):
#rint(moves)
moves.shuffle()
var move = moves.pop_back()
ai_make_move(piece, move)
return
#rint( ai_text_board_move(board_to_text_board(board), piece, move) )
#ai_make_move(piece, move)
var p_board = generate_points_board(team, text_board)
return [p_board[move[0]][move[1]], piece, move]
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)
func get_moves_with_points(p_board, legal_every_move):
var saved_moves = []
for every_move in legal_every_move:
var piece = every_move[0]
@ -180,15 +271,28 @@ func ai_weighted_random(team, text_board, legal_every_move):
saved_moves.append([p_board[move[0]][move[1]], piece, move])
else:
continue
return saved_moves
func ai_weighted_random(team, text_board, legal_every_move, dict = {"no_shuffle":false, "skip_amount":0}):
# 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 = get_moves_with_points(p_board, legal_every_move)
if saved_moves.size() > 0:
saved_moves.shuffle()
if ! dict.get("no_shuffle"):
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])
var the_move
the_move = saved_moves.pop_back()
for i in dict.get("skip_amount"):
the_move = saved_moves.pop_back()
#ai_make_move(the_move[1], the_move[2])
return the_move
else:
ai_random_move(legal_every_move)
return ai_random_move(team, text_board, legal_every_move)
func sort_ascending(a, b):
if a[0] < b[0]:

View file

@ -34,6 +34,10 @@ window/stretch/aspect="expand"
singletons=[ "res://addons/godot-git-plugin/git_api.gdnlib" ]
[global]
limit=false
[input]
mouse1={
@ -47,6 +51,10 @@ mouse2={
]
}
[network]
limits/debugger_stdout/max_chars_per_second=9999999999
[physics]
common/enable_pause_aware_picking=true