add ai movement based on 'points' gained/lost
This commit is contained in:
parent
265b50e1de
commit
fb3f5d1394
2 changed files with 139 additions and 27 deletions
156
Main.gd
156
Main.gd
|
@ -34,13 +34,18 @@ var team2 = 2
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
make_player1("green")
|
make_player1("green")
|
||||||
make_player2("red")
|
#make_player2("red")
|
||||||
|
|
||||||
#checkmatet1()
|
#checkmatet1()
|
||||||
#checkmatet2()
|
#checkmatet2()
|
||||||
#spawn_piece("pawn", "teal", 2, 6, team1)
|
#spawn_piece("pawn", "teal", 2, 6, team1)
|
||||||
#spawn_piece("pawn", "red", 3, 4, team2)
|
#spawn_piece("pawn", "teal", 2, 1, team1)
|
||||||
#spawn_piece("rook", "red", 0, 5, team2)
|
#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))
|
var captures = update_capture_tables(board_to_text_board(board))
|
||||||
team1_capture = captures[0]
|
team1_capture = captures[0]
|
||||||
|
@ -73,10 +78,18 @@ func _process(_delta):
|
||||||
if click_spot() == Vector2(0,0):
|
if click_spot() == Vector2(0,0):
|
||||||
print(history)
|
print(history)
|
||||||
if click_spot() == Vector2(1,0):
|
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(team2_every_legal_move(board_to_text_board(board)))
|
||||||
print("whoops")
|
print("Queuing for team1...")
|
||||||
if click_spot() == Vector2(2,0):
|
ai_move(team1, board_to_text_board(board), ai_modes.points, 1)
|
||||||
print(board_to_text_board(board))
|
#print("Killing queen: %s" % evaluate_move([2,6], [3,5], board_to_text_board(board), team1, 1))
|
||||||
if click_spot() == Vector2(4,0):
|
if click_spot() == Vector2(4,0):
|
||||||
color_tiles(team2_capture, "red")
|
color_tiles(team2_capture, "red")
|
||||||
if click_spot() == Vector2(5,0):
|
if click_spot() == Vector2(5,0):
|
||||||
|
@ -93,7 +106,7 @@ func _process(_delta):
|
||||||
enum ai_modes {
|
enum ai_modes {
|
||||||
purely_random,
|
purely_random,
|
||||||
weighted_random,
|
weighted_random,
|
||||||
minimax_depth_2,
|
points,
|
||||||
}
|
}
|
||||||
|
|
||||||
var ai_weights = {
|
var ai_weights = {
|
||||||
|
@ -101,30 +114,110 @@ var ai_weights = {
|
||||||
knight = 30,
|
knight = 30,
|
||||||
bishop = 30,
|
bishop = 30,
|
||||||
rook = 50,
|
rook = 50,
|
||||||
queen = 80,
|
queen = 500,
|
||||||
king = 1000,
|
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 legal_every_move = team_every_legal_move(text_board, team)
|
||||||
|
var the_move
|
||||||
if ai_mode == ai_modes.purely_random:
|
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:
|
elif ai_mode == ai_modes.weighted_random:
|
||||||
ai_weighted_random(team, text_board, legal_every_move)
|
the_move = ai_weighted_random(team, text_board, legal_every_move)
|
||||||
elif ai_mode == ai_modes.minimax_depth_2:
|
elif ai_mode == ai_modes.points:
|
||||||
ai_minimax_depth_2(team, text_board, legal_every_move)
|
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()
|
new_turn()
|
||||||
|
|
||||||
func ai_minimax_depth_2(team, text_board, legal_every_move):
|
func ai_points_system(team, legal_moves, text_board, depth=2):
|
||||||
pass
|
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):
|
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 pos = position_to_board_cell(Vector2(piece[0] * board_cell, piece[1] * board_cell))
|
||||||
var board_piece = board[pos[0]][pos[1]]
|
var board_piece = board[pos[0]][pos[1]]
|
||||||
board_piece.position = in_square(Vector2(move[0] * board_cell, move[1] * board_cell))
|
board_piece.position = in_square(Vector2(move[0] * board_cell, move[1] * board_cell))
|
||||||
if board[move[0]][move[1]]:
|
if board[move[0]][move[1]]:
|
||||||
board[move[0]][move[1]].kill()
|
board[move[0]][move[1]].kill()
|
||||||
board[move[0]][move[1]] = board_piece
|
board[move[0]][move[1]] = board_piece
|
||||||
|
board[move[0]][move[1]].has_moved = true
|
||||||
board[pos[0]][pos[1]] = 0
|
board[pos[0]][pos[1]] = 0
|
||||||
|
|
||||||
if move.size() == 3:
|
if move.size() == 3:
|
||||||
|
@ -143,7 +236,7 @@ func ai_make_move(piece, move):
|
||||||
board[3][pos[1]] = board[0][pos[1]]
|
board[3][pos[1]] = board[0][pos[1]]
|
||||||
board[0][pos[1]] = 0
|
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()
|
legal_every_move.shuffle()
|
||||||
while 1:
|
while 1:
|
||||||
var piece_and_moves = legal_every_move.pop_back()
|
var piece_and_moves = legal_every_move.pop_back()
|
||||||
|
@ -156,16 +249,14 @@ func ai_random_move(legal_every_move):
|
||||||
#rint(moves)
|
#rint(moves)
|
||||||
moves.shuffle()
|
moves.shuffle()
|
||||||
var move = moves.pop_back()
|
var move = moves.pop_back()
|
||||||
ai_make_move(piece, move)
|
#rint( ai_text_board_move(board_to_text_board(board), piece, move) )
|
||||||
return
|
#ai_make_move(piece, move)
|
||||||
|
var p_board = generate_points_board(team, text_board)
|
||||||
|
return [p_board[move[0]][move[1]], piece, move]
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
func ai_weighted_random(team, text_board, legal_every_move):
|
func get_moves_with_points(p_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 = []
|
var saved_moves = []
|
||||||
for every_move in legal_every_move:
|
for every_move in legal_every_move:
|
||||||
var piece = every_move[0]
|
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])
|
saved_moves.append([p_board[move[0]][move[1]], piece, move])
|
||||||
else:
|
else:
|
||||||
continue
|
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:
|
if saved_moves.size() > 0:
|
||||||
|
if ! dict.get("no_shuffle"):
|
||||||
saved_moves.shuffle()
|
saved_moves.shuffle()
|
||||||
#rint(saved_moves)
|
#rint(saved_moves)
|
||||||
saved_moves.sort_custom(self, "sort_ascending") # sort, by smallest to greatest, then pop_back()
|
saved_moves.sort_custom(self, "sort_ascending") # sort, by smallest to greatest, then pop_back()
|
||||||
print(saved_moves)
|
print(saved_moves)
|
||||||
var the_move = saved_moves.pop_back()
|
var the_move
|
||||||
ai_make_move(the_move[1], the_move[2])
|
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:
|
else:
|
||||||
ai_random_move(legal_every_move)
|
return ai_random_move(team, text_board, legal_every_move)
|
||||||
|
|
||||||
func sort_ascending(a, b):
|
func sort_ascending(a, b):
|
||||||
if a[0] < b[0]:
|
if a[0] < b[0]:
|
||||||
|
|
|
@ -34,6 +34,10 @@ window/stretch/aspect="expand"
|
||||||
|
|
||||||
singletons=[ "res://addons/godot-git-plugin/git_api.gdnlib" ]
|
singletons=[ "res://addons/godot-git-plugin/git_api.gdnlib" ]
|
||||||
|
|
||||||
|
[global]
|
||||||
|
|
||||||
|
limit=false
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
mouse1={
|
mouse1={
|
||||||
|
@ -47,6 +51,10 @@ mouse2={
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[network]
|
||||||
|
|
||||||
|
limits/debugger_stdout/max_chars_per_second=9999999999
|
||||||
|
|
||||||
[physics]
|
[physics]
|
||||||
|
|
||||||
common/enable_pause_aware_picking=true
|
common/enable_pause_aware_picking=true
|
||||||
|
|
Loading…
Reference in a new issue