853 lines
30 KiB
GDScript
853 lines
30 KiB
GDScript
extends Node
|
|
|
|
export (PackedScene) var piece_scene
|
|
export (PackedScene) var movetile_scene
|
|
|
|
var board = new_board()
|
|
var board_cell = 128
|
|
const BOARD_WIDTH = 7 # starting at 0..7
|
|
const BOARD_HEIGHT = 7
|
|
|
|
var history = []
|
|
|
|
var team1_capture = new_board()
|
|
var team2_capture = new_board()
|
|
|
|
var game_over = false
|
|
|
|
var movement_layer = false
|
|
var movement_layer_piece = null
|
|
|
|
var en_passant_pawn = null
|
|
var en_passant_wait = 0 # how many times any piece on the board must move before en_passant_pawn gets set to null
|
|
|
|
var team1_king = null
|
|
var team2_king = null
|
|
|
|
# hack to prevent 'clicking' on a killed piece
|
|
var safely_handle_movement = false
|
|
|
|
var turn = 0
|
|
|
|
var team1 = 1
|
|
var team2 = 2
|
|
|
|
func _ready():
|
|
make_player1("green")
|
|
make_player2("red")
|
|
|
|
#checkmatet1()
|
|
#checkmatet2()
|
|
var captures = update_capture_tables(board_to_text_board(board))
|
|
team1_capture = captures[0]
|
|
team2_capture = captures[1]
|
|
save_turn()
|
|
OS.set_window_size(Vector2(700,700))
|
|
randomize()
|
|
#OS.set_window_always_on_top(true)
|
|
|
|
|
|
func checkmatet1():
|
|
team1_king = spawn_piece('king', 'orange', 4, 7, team1)
|
|
spawn_piece('bishop', 'orange', 3, 7, team1)
|
|
spawn_piece('pawn', 'orange', 5, 6, team1)
|
|
spawn_piece('pawn', 'orange', 3, 6, team1)
|
|
spawn_piece('pawn', 'orange', 4, 6, team1)
|
|
spawn_piece('rook', 'teal', 7, 3, team2)
|
|
|
|
func checkmatet2():
|
|
team2_king = spawn_piece('king', 'teal', 4, 0, team2)
|
|
spawn_piece('bishop', 'teal', 3, 0, team2)
|
|
spawn_piece('pawn', 'teal', 5, 1, team2)
|
|
spawn_piece('pawn', 'teal', 3, 1, team2)
|
|
spawn_piece('pawn', 'teal', 4, 1, team2)
|
|
spawn_piece('rook', 'orange', 7, 2, team1)
|
|
|
|
func _process(_delta):
|
|
safely_handle_movement = false
|
|
if Input.is_action_just_pressed("mouse2"):
|
|
if click_spot() == Vector2(0,0):
|
|
print(history)
|
|
if click_spot() == Vector2(1,0):
|
|
#print(team2_every_legal_move(board_to_text_board(board)))
|
|
print("whoops")
|
|
if click_spot() == Vector2(2,0):
|
|
print(board_to_text_board(board))
|
|
if click_spot() == Vector2(4,0):
|
|
color_tiles(team2_capture, "red")
|
|
if click_spot() == Vector2(5,0):
|
|
color_tiles(team1_capture, "green")
|
|
if click_spot() == Vector2(7,0):
|
|
ai_move(team2, board_to_text_board(board))
|
|
if click_spot() == Vector2(7,1):
|
|
ai_move(team1, board_to_text_board(board))
|
|
|
|
enum ai_modes {
|
|
purely_random,
|
|
}
|
|
|
|
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
|
|
new_turn()
|
|
|
|
func new_turn():
|
|
check_for_promotion()
|
|
var text_board = board_to_text_board(board)
|
|
var captures = update_capture_tables(text_board)
|
|
team1_capture = captures[0]
|
|
team2_capture = captures[1]
|
|
#print(captures)
|
|
is_king_team1_checked(text_board, true, team2_capture)
|
|
is_king_team2_checked(text_board, true, team1_capture)
|
|
|
|
turn += 1
|
|
print("Turn: %s" % turn)
|
|
save_turn()
|
|
print("-------------------")
|
|
|
|
func save_turn():
|
|
var text_board = board_to_text_board(board)
|
|
history.append(text_board)
|
|
|
|
enum piece_names {
|
|
pawn,
|
|
rook,
|
|
knight,
|
|
bishop,
|
|
king,
|
|
queen
|
|
}
|
|
|
|
func board_to_text_board(boarde):
|
|
var text_board = new_board()
|
|
for i in 8:
|
|
for k in 8:
|
|
if boarde[i][k] is Object:
|
|
var curr_piece = boarde[i][k]
|
|
var piece_name = curr_piece.get_piece()
|
|
var piece_enum = piece_names.get(piece_name)
|
|
var team = curr_piece.get_team()
|
|
var has_moved = curr_piece.has_moved
|
|
var in_check = curr_piece.in_check
|
|
var en_passant = null
|
|
if curr_piece == en_passant_pawn: en_passant = 1
|
|
#var color = curr_piece.get_piece_color_by_region()
|
|
text_board[i][k] = [piece_enum, team, en_passant, has_moved, in_check]
|
|
else:
|
|
text_board[i][k] = 0
|
|
return text_board
|
|
|
|
enum movement_condition {
|
|
not_attacking,
|
|
must_attack,
|
|
en_passant_kill,
|
|
king_side_castling,
|
|
queen_side_castling,
|
|
}
|
|
|
|
func update_capture_tables(text_board, setting=tile_setting.hide_tiles_and_cover_allies):
|
|
var t1_capture = new_board()
|
|
var t2_capture = new_board()
|
|
var pieces = get_pieces(text_board)
|
|
for e in pieces:
|
|
var coords = e[chess_enum.pos]
|
|
if e[chess_enum.team] == team1:
|
|
t1_capture[coords[0]][coords[1]] = 2
|
|
else: # team2
|
|
t2_capture[coords[0]][coords[1]] = 2
|
|
for e in pieces:
|
|
var coords = e[chess_enum.pos]
|
|
var pattern = get_move_pattern(e, coords)
|
|
var captured = can_chess_move(pattern, coords, text_board, setting)
|
|
if e[chess_enum.team] == team1:
|
|
for c in captured:
|
|
if c.size() == 3:
|
|
if c[2] == movement_condition.not_attacking:
|
|
continue
|
|
t1_capture[c[0]][c[1]] = 1
|
|
else: # team2
|
|
for c in captured:
|
|
if c.size() == 3:
|
|
if c[2] == movement_condition.not_attacking:
|
|
continue
|
|
t2_capture[c[0]][c[1]] = 1
|
|
#print(team1_capture)
|
|
#print(team2_capture)
|
|
#color_tiles(t2_capture, "red")
|
|
#color_tiles(t1_capture, "green")
|
|
return [t1_capture, t2_capture]
|
|
|
|
func color_tiles(capture, color):
|
|
for i in 8:
|
|
for k in 8:
|
|
if capture[i][k] == 1:
|
|
var move_tile = movetile_scene.instance()
|
|
add_child(move_tile)
|
|
move_tile.set_color(color)
|
|
move_tile.position = in_square(Vector2(i * board_cell, k * board_cell))
|
|
|
|
func check_for_promotion():
|
|
var pieces = get_tree().get_nodes_in_group("piece")
|
|
for e in pieces:
|
|
if e.get_piece() == "pawn":
|
|
var y = position_to_board_cell(e.position)[1]
|
|
if y == 0 or y == 7:
|
|
print("pawn is elligable for promotion")
|
|
# TODO: player option
|
|
e.set_piece("queen", e.get_piece_color_by_region())
|
|
|
|
func is_king_team2_checked(text_board, enumerate=true, capture_table=[]):
|
|
if team2_king:
|
|
for i in 8:
|
|
for k in 8:
|
|
if text_board[i][k] and text_board[i][k][chess_enum.piece_enum] == piece_names["king"] and text_board[i][k][chess_enum.team] == team2:
|
|
if capture_table[i][k] >= 1:
|
|
if enumerate:
|
|
print("Aye, team2 in check.")
|
|
team2_king.in_check = true
|
|
if enumerate_checkmate(text_board, 2):
|
|
print("Game over: Checkmate! Team 1 wins!")
|
|
game_over = true
|
|
return true
|
|
else:
|
|
team2_king.in_check = false
|
|
return false
|
|
|
|
func is_king_team1_checked(text_board, enumerate=true, capture_table=[]):
|
|
if team1_king:
|
|
for i in 8:
|
|
for k in 8:
|
|
if text_board[i][k] and text_board[i][k][chess_enum.piece_enum] == piece_names["king"] and text_board[i][k][chess_enum.team] == team1:
|
|
if capture_table[i][k] >= 1:
|
|
if enumerate:
|
|
print("Aye, team1 in check.")
|
|
team1_king.in_check = true
|
|
if enumerate_checkmate(text_board, 1):
|
|
print("Game over: Checkmate! Team 2 wins!")
|
|
game_over = true
|
|
return true
|
|
else:
|
|
team1_king.in_check = false
|
|
return false
|
|
|
|
func enumerate_checkmate(text_board, which_king=1):
|
|
var checkmate = true
|
|
var legal_every_move = team_every_legal_move(text_board, which_king)
|
|
for every_move in legal_every_move:
|
|
var piece = every_move[0]
|
|
#rint("piece at (%s,%s)" % [piece[0],piece[1]])
|
|
for move in every_move[1]:
|
|
#print("can move to: (%s,%s)" % [move[0],move[1]])
|
|
var fake_board = pretend_text_board_movement(text_board.duplicate(true), piece, move)
|
|
#print(text_board)
|
|
#print(fake_board)
|
|
var fake_captures = update_capture_tables(fake_board.duplicate(true))
|
|
var t1_captures = fake_captures[0]
|
|
var t2_captures = fake_captures[1]
|
|
if which_king == 1:
|
|
if is_king_team1_checked(fake_board, false, t2_captures):
|
|
pass
|
|
else:
|
|
checkmate = false
|
|
else: # team2
|
|
if is_king_team2_checked(fake_board, false, t1_captures):
|
|
pass
|
|
else:
|
|
checkmate = false
|
|
return checkmate
|
|
|
|
func get_pieces(text_board):
|
|
var pieces = []
|
|
var deepcopy = text_board.duplicate(true)
|
|
for i in 8:
|
|
for k in 8:
|
|
if deepcopy[i][k] is Array:
|
|
deepcopy[i][k].append([i,k])
|
|
pieces.append(deepcopy[i][k]) # 6
|
|
return pieces
|
|
|
|
func team_every_legal_move(text_board, team):
|
|
var every_legal_move = []
|
|
for i in 8:
|
|
for k in 8:
|
|
if text_board[i][k] is Array and text_board[i][k][chess_enum.team] == team:
|
|
var piece_name = text_board[i][k][chess_enum.piece_enum]
|
|
var coords = [i,k]
|
|
var move_pattern
|
|
#var name_of_this = match_piece_names_enums(piece_name)
|
|
move_pattern = get_move_pattern([piece_name, team], coords)
|
|
every_legal_move.append([[i,k], can_chess_move(move_pattern, coords, text_board, tile_setting.hide_tiles_no_cover_allies)])
|
|
#rint(every_legal_move)
|
|
return every_legal_move
|
|
|
|
func match_piece_names_enums(piece_name):
|
|
if piece_names["pawn"] == piece_name:
|
|
return "pawn"
|
|
elif piece_names["rook"] == piece_name:
|
|
return "rook"
|
|
elif piece_names["knight"] == piece_name:
|
|
return "knight"
|
|
elif piece_names["bishop"] == piece_name:
|
|
return "bishop"
|
|
elif piece_names["queen"] == piece_name:
|
|
return "queen"
|
|
elif piece_names["king"] == piece_name:
|
|
return "king"
|
|
else:
|
|
print("unknown piece: %s" % piece_name)
|
|
|
|
func pretend_text_board_movement(text_board, old_coords, new_coords):
|
|
#print("old coords: (%s , %s)" % old_coords)
|
|
#print("new coords: (%s , %s)" % [new_coords[0], new_coords[1]])
|
|
#print(text_board)
|
|
var new_text_board = text_board.duplicate(true)
|
|
new_text_board[new_coords[0]][new_coords[1]] = new_text_board[old_coords[0]][old_coords[1]]
|
|
new_text_board[old_coords[0]][old_coords[1]] = 0
|
|
#print(new_text_board)
|
|
return new_text_board
|
|
|
|
func remove_movement_layer():
|
|
movement_layer = false
|
|
movement_layer_piece = null
|
|
var movement_tiles = get_tree().get_nodes_in_group("tile")
|
|
for e in movement_tiles:
|
|
e.queue_free()
|
|
|
|
func piece_clicked(piece):
|
|
if movement_layer:
|
|
print("I was clicked on, but the movement layer is toggled")
|
|
if movement_layer_piece == click_spot():
|
|
remove_movement_layer()
|
|
else:
|
|
if ! safely_handle_movement:
|
|
#var piece_name = piece.get_piece()
|
|
#rint("You clicked on a %s, team %s" % [piece_name, piece.get_team()])
|
|
var location = click_spot()
|
|
#rint("Spot: %s " % location)
|
|
var pattern = get_move_pattern(piece, location)
|
|
if can_chess_move(pattern, location, board_to_text_board(board)):
|
|
movement_layer = true
|
|
movement_layer_piece = location
|
|
|
|
func click_spot():
|
|
var square = get_viewport().get_mouse_position()
|
|
square[0] = floor(square[0] / board_cell)
|
|
square[1] = floor(square[1] / board_cell)
|
|
return square
|
|
|
|
func make_player2(color):
|
|
spawn_piece('rook', color, 0, 0, team2)
|
|
spawn_piece('knight', color, 1, 0, team2)
|
|
spawn_piece('bishop', color, 2, 0, team2)
|
|
spawn_piece('queen', color, 3, 0, team2)
|
|
team2_king = spawn_piece('king', color, 4, 0, team2)
|
|
spawn_piece('bishop', color, 5, 0, team2)
|
|
spawn_piece('knight', color, 6, 0, team2)
|
|
spawn_piece('rook', color, 7, 0, team2)
|
|
for i in BOARD_WIDTH + 1:
|
|
spawn_piece('pawn', color, i , 1, team2)
|
|
|
|
func make_player1(color):
|
|
spawn_piece('rook', color, 0, 7, team1)
|
|
spawn_piece('knight', color, 1, 7, team1)
|
|
spawn_piece('bishop', color, 2, 7, team1)
|
|
spawn_piece('queen', color, 3, 7, team1)
|
|
team1_king = spawn_piece('king', color, 4, 7, team1)
|
|
spawn_piece('bishop', color, 5, 7, team1)
|
|
spawn_piece('knight', color, 6, 7, team1)
|
|
spawn_piece('rook', color, 7, 7, team1)
|
|
for i in BOARD_WIDTH + 1:
|
|
spawn_piece('pawn', color, i , 6, team1)
|
|
|
|
func spawn_piece(piece_name, color, x=0, y=0, team=0):
|
|
var piece = piece_scene.instance()
|
|
piece.init(piece.piece_map.get(piece_name), piece.piece_color.get(color), team)
|
|
add_child(piece)
|
|
piece.connect("clicked", self, "piece_clicked", [piece])
|
|
board_add_piece(piece, x, y)
|
|
piece.position = in_square(Vector2(x * board_cell, y * board_cell))
|
|
return piece
|
|
|
|
func rand_pos():
|
|
return Vector2(rand_range(0, get_viewport().size.x),rand_range(0, get_viewport().size.y))
|
|
|
|
# needs to be Vector2 as that is what object.position takes
|
|
func in_square(vect2):
|
|
#rint(vect2)
|
|
vect2.x = ceil(vect2.x / board_cell)
|
|
#rint(vect2.x)
|
|
vect2.x *= board_cell
|
|
vect2.x += board_cell / 2
|
|
|
|
vect2.y = ceil(vect2.y / board_cell)
|
|
#rint(vect2.y)
|
|
vect2.y *= board_cell
|
|
vect2.y += board_cell / 2
|
|
|
|
#rint(vect2)
|
|
return vect2
|
|
|
|
func new_board():
|
|
# x →
|
|
# y
|
|
# ↓
|
|
# [0][0] = top left, [0][7] = bottom left, [7][0] = top right, [7][7] = bottom right
|
|
var new_board = []
|
|
for i in BOARD_HEIGHT + 1:
|
|
new_board.append([])
|
|
new_board[i].resize(BOARD_WIDTH + 1)
|
|
for j in BOARD_WIDTH + 1:
|
|
new_board[i][j] = 0
|
|
return new_board
|
|
|
|
func board_add_piece(piece, x, y):
|
|
board[x][y] = piece
|
|
|
|
enum {
|
|
move_2_up_pawn,
|
|
move_1_up_pawn,
|
|
attack_1_nw,
|
|
attack_1_ne,
|
|
en_passant_nw,
|
|
en_passant_ne,
|
|
|
|
move_2_down_pawn,
|
|
move_1_down_pawn,
|
|
attack_1_sw,
|
|
attack_1_se,
|
|
en_passant_sw,
|
|
en_passant_se,
|
|
|
|
move_1_up,
|
|
move_1_down,
|
|
move_1_left,
|
|
move_1_right,
|
|
move_1_nw,
|
|
move_1_ne,
|
|
move_1_sw,
|
|
move_1_se,
|
|
|
|
move_up_inf,
|
|
move_down_inf,
|
|
move_left_inf,
|
|
move_right_inf,
|
|
castling,
|
|
|
|
move_nw_inf,
|
|
move_ne_inf,
|
|
move_sw_inf,
|
|
move_se_inf,
|
|
|
|
knight,
|
|
}
|
|
|
|
func get_move_pattern(piece, coords):
|
|
var piece_name
|
|
var team
|
|
if piece is Object:
|
|
piece_name = piece.get_piece()
|
|
team = piece.get_team()
|
|
else:
|
|
piece_name = match_piece_names_enums(piece[chess_enum.piece_enum])
|
|
#print(piece_name)
|
|
team = piece[1]
|
|
#rint("Array: %s, %s" % [piece_name, team])
|
|
|
|
match (piece_name):
|
|
"pawn":
|
|
if team == team1:
|
|
if coords[1] == 6:
|
|
return [attack_1_nw, move_2_up_pawn, attack_1_ne, en_passant_ne, en_passant_nw]
|
|
else:
|
|
return [attack_1_nw, move_1_up_pawn, attack_1_ne, en_passant_ne, en_passant_nw]
|
|
else:
|
|
if coords[1] == 1:
|
|
return [attack_1_sw, move_2_down_pawn, attack_1_se, en_passant_se, en_passant_sw]
|
|
else:
|
|
return [attack_1_sw, move_1_down_pawn, attack_1_se, en_passant_se, en_passant_sw]
|
|
"rook":
|
|
return [move_up_inf, move_left_inf, move_right_inf, move_down_inf]
|
|
"knight":
|
|
return [knight]
|
|
"bishop":
|
|
return [move_ne_inf, move_nw_inf, move_sw_inf, move_se_inf]
|
|
"queen":
|
|
return [move_up_inf, move_down_inf, move_left_inf, move_right_inf, move_ne_inf, move_nw_inf, move_sw_inf, move_se_inf]
|
|
"king":
|
|
return [move_1_down, move_1_left, move_1_right, move_1_up, move_1_ne, move_1_nw, move_1_se, move_1_sw, castling]
|
|
_:
|
|
return []
|
|
|
|
enum chess_enum {
|
|
piece_enum = 0,
|
|
team = 1,
|
|
en_passant = 2,
|
|
has_moved = 3,
|
|
in_check = 4,
|
|
pos = 5
|
|
}
|
|
|
|
enum tile_setting {
|
|
hide_tiles_and_cover_allies = 0
|
|
show_tiles = 1
|
|
hide_tiles_no_cover_allies = 2
|
|
}
|
|
|
|
func can_chess_move(pattern, coords, text_board, create_tiles=tile_setting.show_tiles):
|
|
var can_move = []
|
|
#rint(text_board[coords[0]][coords[1]])
|
|
var curr_piece = text_board[coords[0]][coords[1]]
|
|
var curr_team = curr_piece[chess_enum.team]
|
|
for e in pattern:
|
|
match (e):
|
|
move_1_down_pawn:
|
|
var test = make_tiles(coords, [0,1], 1, true, curr_team, {}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.not_attacking)
|
|
can_move.append_array(test)
|
|
move_2_down_pawn:
|
|
var test = make_tiles(coords, [0,1], 1, true, curr_team, {}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.not_attacking)
|
|
can_move.append_array(test)
|
|
var test2 = make_tiles(coords, [0,2], 1, true, curr_team, {'tile_is_en_passant': true}, create_tiles, text_board)
|
|
if test2:
|
|
test2[0].push_back(movement_condition.not_attacking)
|
|
can_move.append_array(test2)
|
|
attack_1_sw:
|
|
var test = make_tiles(coords, [-1,1], 1, false, curr_team, {"must_attack": true}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.must_attack)
|
|
can_move.append_array(test)
|
|
attack_1_se:
|
|
var test = make_tiles(coords, [1,1], 1, false, curr_team, {"must_attack": true}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.must_attack)
|
|
can_move.append_array(test)
|
|
en_passant_sw:
|
|
var pawn_maybe = text_board[coords[0]-1][coords[1]]
|
|
if pawn_maybe and pawn_maybe[chess_enum.piece_enum] == piece_names["pawn"] and pawn_maybe[chess_enum.en_passant] == 1 and pawn_maybe[chess_enum.team] != curr_team:
|
|
var test = make_tiles(coords, [-1,1], 1, true, curr_team, {"en_passant_pawn": pawn_maybe}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.en_passant_kill)
|
|
can_move.append_array(test)
|
|
en_passant_se:
|
|
if ! coords[0] + 1 > BOARD_WIDTH:
|
|
var pawn_maybe = text_board[coords[0]+1][coords[1]]
|
|
if pawn_maybe and pawn_maybe[chess_enum.piece_enum] == piece_names["pawn"] and pawn_maybe[chess_enum.en_passant] == 1 and pawn_maybe[chess_enum.team] != curr_team:
|
|
var test = make_tiles(coords, [1,1], 1, true, curr_team, {"en_passant_pawn": pawn_maybe}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.en_passant_kill)
|
|
can_move.append_array(test)
|
|
|
|
move_1_up_pawn:
|
|
var test = make_tiles(coords, [0,-1], 1, true, curr_team, {}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.not_attacking)
|
|
can_move.append_array(test)
|
|
move_2_up_pawn:
|
|
var test = make_tiles(coords, [0,-1], 1, true, curr_team, {}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.not_attacking)
|
|
can_move.append_array(test)
|
|
var test2 = make_tiles(coords, [0,-2], 1, true, curr_team, {'tile_is_en_passant': true}, create_tiles, text_board)
|
|
if test2:
|
|
test2[0].push_back(movement_condition.not_attacking)
|
|
can_move.append_array(test2)
|
|
attack_1_nw:
|
|
var test = make_tiles(coords, [-1,-1], 1, false, curr_team, {"must_attack": true}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.must_attack)
|
|
can_move.append_array(test)
|
|
attack_1_ne:
|
|
var test = make_tiles(coords, [1,-1], 1, false, curr_team, {"must_attack": true}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.must_attack)
|
|
can_move.append_array(test)
|
|
en_passant_nw:
|
|
var pawn_maybe = text_board[coords[0]-1][coords[1]]
|
|
if pawn_maybe and pawn_maybe[chess_enum.piece_enum] == piece_names["pawn"] and pawn_maybe[chess_enum.en_passant] == 1 and pawn_maybe[chess_enum.team] != curr_team:
|
|
var test = make_tiles(coords, [-1,-1], 1, true, curr_team, {"en_passant_pawn": pawn_maybe}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.en_passant_kill)
|
|
can_move.append_array(test)
|
|
en_passant_ne:
|
|
if ! coords[0] + 1 > BOARD_WIDTH:
|
|
var pawn_maybe = text_board[coords[0]+1][coords[1]]
|
|
if pawn_maybe and pawn_maybe[chess_enum.piece_enum] == piece_names["pawn"] and pawn_maybe[chess_enum.en_passant] == 1 and pawn_maybe[chess_enum.team] != curr_team:
|
|
var test = make_tiles(coords, [1,-1], 1, true, curr_team, {"en_passant_pawn": pawn_maybe}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.en_passant_kill)
|
|
can_move.append_array(test)
|
|
|
|
move_up_inf:
|
|
can_move.append_array(make_tiles(coords, [0,-1], BOARD_HEIGHT, false, curr_team, {}, create_tiles, text_board))
|
|
move_down_inf:
|
|
can_move.append_array(make_tiles(coords, [0,1], BOARD_HEIGHT, false, curr_team, {}, create_tiles, text_board))
|
|
move_left_inf:
|
|
can_move.append_array(make_tiles(coords, [-1,0], BOARD_WIDTH, false, curr_team, {}, create_tiles, text_board))
|
|
move_right_inf:
|
|
can_move.append_array(make_tiles(coords, [1,0], BOARD_WIDTH, false, curr_team, {}, create_tiles, text_board))
|
|
castling:
|
|
if ! curr_piece[chess_enum.has_moved] and ! curr_piece[chess_enum.in_check]:
|
|
var y = coords[1]
|
|
var king_x = coords[0]
|
|
#var pieces = get_tree().get_nodes_in_group("piece")
|
|
var pieces = get_pieces(text_board)
|
|
for ele in pieces:
|
|
if ele[chess_enum.team] == curr_team and ele[chess_enum.piece_enum] == piece_names["rook"] and ! ele[chess_enum.has_moved] and ele[chess_enum.pos][1] == y:
|
|
#rint(ele)
|
|
var rook_x = ele[chess_enum.pos][0]
|
|
# king side
|
|
if rook_x > king_x:
|
|
var blocked = false
|
|
var diff = rook_x - king_x
|
|
for i in range(1, diff):
|
|
if board[king_x + i][y]:
|
|
blocked = true
|
|
# cannot castle through or to a tile that is attacked
|
|
if curr_team == team1:
|
|
if team2_capture[king_x + i][y] == 1:
|
|
blocked = true
|
|
else: # team2
|
|
if team1_capture[king_x + i][y] == 1:
|
|
blocked = true
|
|
|
|
#rint("There is something at (%s,%s) %s" % [king_x + i,y, board[king_x + i][y].get_piece() ])
|
|
if ! blocked:
|
|
var test = make_tiles(coords, [2,0], 1, false, curr_team, {"castling_rook": ele}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.king_side_castling)
|
|
can_move.append_array(test)
|
|
else:
|
|
var blocked = false
|
|
var diff = king_x - rook_x
|
|
for i in range(1, diff):
|
|
#rint(board[rook_x + i][y])
|
|
if board[rook_x + i][y]:
|
|
blocked = true
|
|
if i != 1: # on queenside, that first square doesn't really matter if it is attacked
|
|
if curr_team == team1:
|
|
if team2_capture[rook_x + i][y] == 1:
|
|
blocked = true
|
|
else: # team2
|
|
if team1_capture[rook_x + i][y] == 1:
|
|
blocked = true
|
|
#rint("There is something at (%s,%s) %s" % [rook_x + i, y, board[rook_x + i][y].get_piece()])
|
|
if ! blocked:
|
|
var test = make_tiles(coords, [-2,0], 1, false, curr_team, {"castling_rook": ele}, create_tiles, text_board)
|
|
if test:
|
|
test[0].push_back(movement_condition.queen_side_castling)
|
|
can_move.append_array(test)
|
|
|
|
move_ne_inf:
|
|
can_move.append_array(make_tiles(coords, [1,-1], 8, false, curr_team, {}, create_tiles, text_board))
|
|
move_nw_inf:
|
|
can_move.append_array(make_tiles(coords, [-1,-1], 8, false, curr_team, {}, create_tiles, text_board))
|
|
move_sw_inf:
|
|
can_move.append_array(make_tiles(coords, [-1,1], 8, false, curr_team, {}, create_tiles, text_board))
|
|
move_se_inf:
|
|
can_move.append_array(make_tiles(coords, [1,1], 8, false, curr_team, {}, create_tiles, text_board))
|
|
|
|
knight:
|
|
can_move.append_array(make_tiles(coords, [1,2], 1, false, curr_team, {}, create_tiles, text_board))
|
|
can_move.append_array(make_tiles(coords, [1,-2], 1, false, curr_team, {}, create_tiles, text_board))
|
|
can_move.append_array(make_tiles(coords, [-1,-2], 1, false, curr_team, {}, create_tiles, text_board))
|
|
can_move.append_array(make_tiles(coords, [-1,2], 1, false, curr_team, {}, create_tiles, text_board))
|
|
can_move.append_array(make_tiles(coords, [2,1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
can_move.append_array(make_tiles(coords, [2,-1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
can_move.append_array(make_tiles(coords, [-2,-1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
can_move.append_array(make_tiles(coords, [-2,1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
|
|
move_1_down:
|
|
can_move.append_array(make_tiles(coords, [0,1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
move_1_up:
|
|
can_move.append_array(make_tiles(coords, [0,-1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
move_1_right:
|
|
can_move.append_array(make_tiles(coords, [1,0], 1, false, curr_team, {}, create_tiles, text_board))
|
|
move_1_left:
|
|
can_move.append_array(make_tiles(coords, [-1,0], 1, false, curr_team, {}, create_tiles, text_board))
|
|
move_1_ne:
|
|
can_move.append_array(make_tiles(coords, [1,-1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
move_1_nw:
|
|
can_move.append_array(make_tiles(coords, [-1,-1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
move_1_se:
|
|
can_move.append_array(make_tiles(coords, [1,1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
move_1_sw:
|
|
can_move.append_array(make_tiles(coords, [-1,1], 1, false, curr_team, {}, create_tiles, text_board))
|
|
return can_move
|
|
|
|
func position_to_board_cell(vect2):
|
|
var x = floor(vect2.x / board_cell)
|
|
var y = floor(vect2.y / board_cell)
|
|
return [x,y]
|
|
|
|
func movetile_clicked(move_tile):
|
|
#rint("Yep, I was clicked")
|
|
var location = click_spot()
|
|
var check = board[location[0]][location[1]]
|
|
var curr_piece = board[movement_layer_piece[0]][movement_layer_piece[1]]
|
|
if ! check:
|
|
pass
|
|
else:
|
|
check.kill()
|
|
|
|
board[location[0]][location[1]] = curr_piece
|
|
if move_tile.en_passant_tile:
|
|
#rint("toggling en passant able...")
|
|
en_passant_pawn = curr_piece
|
|
en_passant_wait = 2 # gets -1 in this script later
|
|
if move_tile.castling_rook:
|
|
# move_tile.castling_rook actually an array (created by get_pieces() rather than an object)
|
|
var rook_location = move_tile.castling_rook[chess_enum["pos"]]
|
|
# need to take that pos and figure out which rook object refers to
|
|
var pos = position_to_board_cell(Vector2(rook_location[0] * board_cell, rook_location[1] * board_cell))
|
|
var rook = board[pos[0]][pos[1]]
|
|
# king side
|
|
if 7 == rook_location[0]:
|
|
rook.position = in_square(Vector2(5 * board_cell, rook_location[1] * board_cell))
|
|
board[5][rook_location[1]] = board[7][rook_location[1]]
|
|
board[7][rook_location[1]] = 0
|
|
# queen side
|
|
else:
|
|
rook.position = in_square(Vector2(3 * board_cell, rook_location[1] * board_cell))
|
|
board[3][rook_location[1]] = board[0][rook_location[1]]
|
|
board[0][rook_location[1]] = 0
|
|
|
|
curr_piece.position = in_square(Vector2(location[0] * board_cell, location[1] * board_cell))
|
|
board[movement_layer_piece[0]][movement_layer_piece[1]] = 0
|
|
remove_movement_layer()
|
|
safely_handle_movement = true
|
|
|
|
curr_piece.has_moved = true
|
|
|
|
if move_tile.en_passant_kill_tile:
|
|
kill_en_passant_pawn(location)
|
|
|
|
if en_passant_wait >= 1:
|
|
en_passant_wait -= 1
|
|
if en_passant_wait == 0:
|
|
en_passant_pawn = null
|
|
|
|
new_turn()
|
|
|
|
func kill_en_passant_pawn(location):
|
|
if board[location[0]+1][location[1]] is Object and board[location[0]+1][location[1]] == en_passant_pawn:
|
|
board[location[0]+1][location[1]] = 0
|
|
if board[location[0]-1][location[1]] is Object and board[location[0]-1][location[1]] == en_passant_pawn:
|
|
board[location[0]-1][location[1]] = 0
|
|
if board[location[0]][location[1]+1] is Object and board[location[0]][location[1]+1] == en_passant_pawn:
|
|
board[location[0]][location[1]+1] = 0
|
|
if board[location[0]][location[1]-1] is Object and board[location[0]][location[1]-1] == en_passant_pawn:
|
|
board[location[0]][location[1]-1] = 0
|
|
en_passant_pawn.kill()
|
|
|
|
func spawn_move_tile(coords, en_passant_tile=false, en_passant_kill_tile=null, castling_rook=null):
|
|
var move_tile = movetile_scene.instance()
|
|
add_child(move_tile)
|
|
move_tile.connect("move_clicked", self, "movetile_clicked", [move_tile])
|
|
move_tile.position = in_square(Vector2(coords[0] * board_cell, coords[1] * board_cell))
|
|
if en_passant_tile: move_tile.en_passant_tile = true
|
|
if en_passant_kill_tile: move_tile.en_passant_kill_tile = true
|
|
if castling_rook: move_tile.castling_rook = castling_rook
|
|
#rint(move_tile.position)
|
|
|
|
func make_tiles(coords, pattern, go_range, cant_attack, curr_team,
|
|
dict = {
|
|
"must_attack": false,
|
|
'tile_is_en_passant': false,
|
|
'en_passant_pawn': null,
|
|
'castling_rook': null
|
|
}, create_tiles = tile_setting.show_tiles, text_board=[]):
|
|
var x = coords[0]
|
|
var y = coords[1]
|
|
var pattern0 = pattern[0]
|
|
var pattern1 = pattern[1]
|
|
var a = 0
|
|
var b = 0
|
|
|
|
var made_tile = []
|
|
|
|
for _i in range(1,go_range+1):
|
|
a += pattern0
|
|
b += pattern1
|
|
# dont go out of bounds: not bigger than board size but not smaller than 0
|
|
if (x + a) <= BOARD_WIDTH and (y + b) <= BOARD_HEIGHT and (x + a) >= 0 and (y + b) >= 0 :
|
|
var check = text_board[x + a][y + b]
|
|
if ! check and ! dict.get("must_attack"):
|
|
if create_tiles == tile_setting.show_tiles:
|
|
spawn_move_tile([x + a, y + b], dict.get("tile_is_en_passant"), dict.get("en_passant_pawn"), dict.get("castling_rook"))
|
|
made_tile.push_back([x + a, y + b])
|
|
elif dict.get("must_attack"): # pawn setting
|
|
if check and check[chess_enum.team] != curr_team:
|
|
if create_tiles == tile_setting.show_tiles:
|
|
spawn_move_tile([x + a, y + b])
|
|
made_tile.push_back([x + a, y + b])
|
|
elif create_tiles == 0:
|
|
made_tile.push_back([x + a, y + b])
|
|
elif ! cant_attack and check[chess_enum.team] != curr_team:
|
|
if create_tiles == tile_setting.show_tiles:
|
|
spawn_move_tile([x + a, y + b], dict.get("tile_is_en_passant"), dict.get("en_passant_pawn"))
|
|
made_tile.push_back([x + a, y + b])
|
|
break # rules of chess say pieces cant go past another
|
|
elif create_tiles == tile_setting.hide_tiles_and_cover_allies and ! cant_attack and check[chess_enum.team] == curr_team :
|
|
# ^ in otherwords: we won't mark it on map but will 'mark' it for non-maps (like capture board)
|
|
made_tile.push_back([x + a, y + b])
|
|
break # but still can't go past teammate
|
|
else:
|
|
break
|
|
return made_tile
|
|
|
|
# option (used when we KNOW it is an array)
|
|
# "object" -> sprite object
|
|
# "tile" -> return info about the tile
|
|
func array_piece(coords, option=null):
|
|
var element = board[coords[0]][coords[1]]
|
|
#rint(element)
|
|
if element is Array:
|
|
if option == "object":
|
|
return element[0]
|
|
elif option == "tile":
|
|
return element[1]
|
|
return element
|