summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjake <jake@jakes-mail.top>2023-02-24 20:38:00 -0500
committerjake <jake@jakes-mail.top>2023-02-24 20:38:00 -0500
commitfb3f5d13949b174f9381247e5e440a4fa819b6bf (patch)
tree6e21f70847e8eed2488ebb612483cb0c877bcf88
parent265b50e1de0345c88612a0a623954c00077cc592 (diff)
add ai movement based on 'points' gained/lostHEADmaster
-rw-r--r--Main.gd158
-rw-r--r--project.godot8
2 files changed, 139 insertions, 27 deletions
diff --git a/Main.gd b/Main.gd
index 636f9f9..5b4bd89 100644
--- a/Main.gd
+++ b/Main.gd
@@ -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]:
diff --git a/project.godot b/project.godot
index 91e12b7..af74602 100644
--- a/project.godot
+++ b/project.godot
@@ -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