chessgame/Main.gd

461 lines
16 KiB
GDScript3
Raw Normal View History

2023-02-17 11:37:23 -08:00
extends Node
export (PackedScene) var piece_scene
export (PackedScene) var movetile_scene
var board = new_board2()
var board_cell = 128
const BOARD_WIDTH = 7 # starting at 0..7
const BOARD_HEIGHT = 7
var movement_layer = false
var movement_layer_piece = null
2023-02-18 13:41:27 -08:00
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
2023-02-17 11:37:23 -08:00
var safely_handle_movement = false
var team1 = 1
var team2 = 2
func _ready():
make_player1("green")
make_player2("red")
2023-02-18 13:41:27 -08:00
#spawn_piece('pawn', 'teal', 1, 6, team1)
#spawn_piece('pawn', 'orange', 2, 4, team2)
#team2_king = spawn_piece('king', 'teal', 4, 0, team2)
#spawn_piece('rook', 'teal', 7, 0, team2)
#spawn_piece('rook', 'teal', 0, 0, team2)
OS.set_window_size(Vector2(700,700))
OS.set_window_always_on_top(true)
2023-02-17 11:37:23 -08:00
# horrifying discovery: this occurs after the signal capturing functions
func _process(delta):
safely_handle_movement = false
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()
2023-02-18 13:41:27 -08:00
#rint("You clicked on a %s, team %s" % [piece_name, piece.get_team()])
2023-02-17 11:37:23 -08:00
var location = click_spot()
2023-02-18 13:41:27 -08:00
#rint("Spot: %s " % location)
2023-02-17 11:37:23 -08:00
var pattern = get_move_pattern(piece, location)
if can_chess_move(pattern, location):
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)
2023-02-18 13:41:27 -08:00
team2_king = spawn_piece('king', color, 4, 0, team2)
2023-02-17 11:37:23 -08:00
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)
2023-02-18 13:41:27 -08:00
team1_king = spawn_piece('king', color, 4, 7, team1)
2023-02-17 11:37:23 -08:00
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):
2023-02-18 13:41:27 -08:00
#rint(vect2)
2023-02-17 11:37:23 -08:00
vect2.x = ceil(vect2.x / board_cell)
2023-02-18 13:41:27 -08:00
#rint(vect2.x)
2023-02-17 11:37:23 -08:00
vect2.x *= board_cell
vect2.x += board_cell / 2
vect2.y = ceil(vect2.y / board_cell)
2023-02-18 13:41:27 -08:00
#rint(vect2.y)
2023-02-17 11:37:23 -08:00
vect2.y *= board_cell
vect2.y += board_cell / 2
2023-02-18 13:41:27 -08:00
#rint(vect2)
2023-02-17 11:37:23 -08:00
return vect2
func new_board2():
# x →
# y
# ↓
# [0][0] = top left, [0][7] = bottom left, [7][0] = top right, [7][7] = bottom right
var board = []
for i in BOARD_HEIGHT + 1:
board.append([])
board[i].resize(BOARD_WIDTH + 1)
for j in BOARD_WIDTH + 1:
board[i][j] = 0
return board
func new_board():
return [[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]]
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,
2023-02-18 13:41:27 -08:00
en_passent_nw,
en_passent_ne,
2023-02-17 11:37:23 -08:00
move_2_down_pawn,
move_1_down_pawn,
attack_1_sw,
attack_1_se,
2023-02-18 13:41:27 -08:00
en_passent_sw,
en_passent_se,
2023-02-17 11:37:23 -08:00
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,
2023-02-18 13:41:27 -08:00
castling,
2023-02-17 11:37:23 -08:00
move_nw_inf,
move_ne_inf,
move_sw_inf,
move_se_inf,
knight,
}
func get_move_pattern(piece, coords):
var piece_name = piece.get_piece()
match (piece_name):
"pawn":
if piece.get_team() == team1:
if coords[1] == 6:
2023-02-18 13:41:27 -08:00
return [attack_1_nw, move_2_up_pawn, attack_1_ne, en_passent_ne, en_passent_nw]
2023-02-17 11:37:23 -08:00
else:
2023-02-18 13:41:27 -08:00
return [attack_1_nw, move_1_up_pawn, attack_1_ne, en_passent_ne, en_passent_nw]
2023-02-17 11:37:23 -08:00
else:
if coords[1] == 1:
2023-02-18 13:41:27 -08:00
return [attack_1_sw, move_2_down_pawn, attack_1_se, en_passent_se, en_passent_sw]
2023-02-17 11:37:23 -08:00
else:
2023-02-18 13:41:27 -08:00
return [attack_1_sw, move_1_down_pawn, attack_1_se, en_passent_se, en_passent_sw]
2023-02-17 11:37:23 -08:00
"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":
2023-02-18 13:41:27 -08:00
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]
2023-02-17 11:37:23 -08:00
_:
2023-02-18 13:41:27 -08:00
#rint("no pattern for this one")
return []
2023-02-17 11:37:23 -08:00
func can_chess_move(pattern, coords):
var can_move = false
2023-02-18 13:41:27 -08:00
var curr_piece = board[coords[0]][coords[1]]
var curr_team = curr_piece.get_team()
2023-02-17 11:37:23 -08:00
for e in pattern:
match (e):
move_1_down_pawn:
if make_tiles(coords, [0,1], 1, true, curr_team): can_move = true
move_2_down_pawn:
2023-02-18 13:41:27 -08:00
if make_tiles(coords, [0,1], 1, true, curr_team):
can_move = true
make_tiles(coords, [0,2], 1, true, curr_team, {'tile_is_en_passant': true})
2023-02-17 11:37:23 -08:00
attack_1_sw:
2023-02-18 13:41:27 -08:00
if make_tiles(coords, [-1,1], 1, false, curr_team, {"must_attack": true}): can_move = true
2023-02-17 11:37:23 -08:00
attack_1_se:
2023-02-18 13:41:27 -08:00
if make_tiles(coords, [1,1], 1, false, curr_team, {"must_attack": true}): can_move = true
en_passent_sw:
var pawn_maybe = board[coords[0]-1][coords[1]]
if pawn_maybe and pawn_maybe.get_piece() == "pawn" and pawn_maybe == en_passant_pawn and pawn_maybe.get_team() != curr_team:
if make_tiles(coords, [-1,1], 1, true, curr_team, {"en_passant_pawn": pawn_maybe}): can_move = true
en_passent_se:
if ! coords[0] + 1 > BOARD_WIDTH:
var pawn_maybe = board[coords[0]+1][coords[1]]
if pawn_maybe and pawn_maybe.get_piece() == "pawn" and pawn_maybe == en_passant_pawn and pawn_maybe.get_team() != curr_team:
if make_tiles(coords, [1,1], 1, true, curr_team, {"en_passant_pawn": pawn_maybe}): can_move = true
2023-02-17 11:37:23 -08:00
move_1_up_pawn:
if make_tiles(coords, [0,-1], 1, true, curr_team): can_move = true
move_2_up_pawn:
2023-02-18 13:41:27 -08:00
if make_tiles(coords, [0,-1], 1, true, curr_team):
can_move = true
make_tiles(coords, [0,-2], 1, true, curr_team, {'tile_is_en_passant': true})
2023-02-17 11:37:23 -08:00
attack_1_nw:
2023-02-18 13:41:27 -08:00
if make_tiles(coords, [-1,-1], 1, false, curr_team, {"must_attack": true}): can_move = true
2023-02-17 11:37:23 -08:00
attack_1_ne:
2023-02-18 13:41:27 -08:00
if make_tiles(coords, [1,-1], 1, false, curr_team, {"must_attack": true}): can_move = true
en_passent_nw:
var pawn_maybe = board[coords[0]-1][coords[1]]
if pawn_maybe and pawn_maybe.get_piece() == "pawn" and pawn_maybe == en_passant_pawn and pawn_maybe.get_team() != curr_team:
if make_tiles(coords, [-1,-1], 1, true, curr_team, {"en_passant_pawn": pawn_maybe}): can_move = true
en_passent_ne:
if ! coords[0] + 1 > BOARD_WIDTH:
var pawn_maybe = board[coords[0]+1][coords[1]]
if pawn_maybe and pawn_maybe.get_piece() == "pawn" and pawn_maybe == en_passant_pawn and pawn_maybe.get_team() != curr_team:
if make_tiles(coords, [1,-1], 1, true, curr_team, {"en_passant_pawn": pawn_maybe}): can_move = true
2023-02-17 11:37:23 -08:00
move_up_inf:
if make_tiles(coords, [0,-1], BOARD_HEIGHT, false, curr_team): can_move =true
move_down_inf:
if make_tiles(coords, [0,1], BOARD_HEIGHT, false, curr_team): can_move = true
move_left_inf:
if make_tiles(coords, [-1,0], BOARD_WIDTH, false, curr_team): can_move = true
move_right_inf:
if make_tiles(coords, [1,0], BOARD_WIDTH, false, curr_team): can_move = true
2023-02-18 13:41:27 -08:00
castling:
if ! curr_piece.has_moved and ! curr_piece.in_check:
var y = coords[1]
var king_x = coords[0]
var pieces = get_tree().get_nodes_in_group("piece")
for ele in pieces:
if ele.get_team() == curr_team and ele.get_piece() == "rook" and ! ele.has_moved and position_to_board_cell(ele.position)[1] == y:
print(ele)
var rook_x = position_to_board_cell(ele.position)[0]
# king side
if rook_x > king_x:
var blocked = false
pass
var diff = rook_x - king_x
for i in range(1, diff):
#rint(board[king_x + i][y])
if board[king_x + i][y]:
blocked = true
#rint("There is something at (%s,%s) %s" % [king_x + i,y, board[king_x + i][y].get_piece() ])
if ! blocked:
if make_tiles(coords, [2,0], 1, false, curr_team, {"castling_rook": ele}): can_move = true
else:
var blocked = false
pass
var diff = king_x - rook_x
for i in range(1, diff):
print(board[rook_x + i][y])
if board[rook_x + i][y]:
blocked = true
#rint("There is something at (%s,%s) %s" % [rook_x + i, y, board[rook_x + i][y].get_piece()])
if ! blocked:
if make_tiles(coords, [-2,0], 1, false, curr_team, {"castling_rook": ele}): can_move = true
2023-02-17 11:37:23 -08:00
move_ne_inf:
if make_tiles(coords, [1,-1], 8, false, curr_team): can_move = true
move_nw_inf:
if make_tiles(coords, [-1,-1], 8, false, curr_team): can_move = true
move_sw_inf:
if make_tiles(coords, [-1,1], 8, false, curr_team): can_move = true
move_se_inf:
if make_tiles(coords, [1,1], 8, false, curr_team): can_move = true
knight:
if make_tiles(coords, [1,2], 1, false, curr_team): can_move = true
if make_tiles(coords, [1,-2], 1, false, curr_team): can_move = true
if make_tiles(coords, [-1,-2], 1, false, curr_team): can_move = true
if make_tiles(coords, [-1,2], 1, false, curr_team): can_move = true
if make_tiles(coords, [2,1], 1, false, curr_team): can_move = true
if make_tiles(coords, [2,-1], 1, false, curr_team): can_move = true
if make_tiles(coords, [-2,-1], 1, false, curr_team): can_move = true
if make_tiles(coords, [-2,1], 1, false, curr_team): can_move = true
move_1_down:
if make_tiles(coords, [0,1], 1, false, curr_team): can_move = true
move_1_up:
if make_tiles(coords, [0,-1], 1, false, curr_team): can_move = true
move_1_right:
if make_tiles(coords, [1,0], 1, false, curr_team): can_move = true
move_1_left:
if make_tiles(coords, [-1,0], 1, false, curr_team): can_move = true
move_1_ne:
if make_tiles(coords, [1,-1], 1, false, curr_team): can_move = true
move_1_nw:
if make_tiles(coords, [-1,-1], 1, false, curr_team): can_move = true
move_1_se:
if make_tiles(coords, [1,1], 1, false, curr_team): can_move = true
move_1_sw:
if make_tiles(coords, [-1,1], 1, false, curr_team): can_move = true
return can_move
2023-02-18 13:41:27 -08:00
func position_to_board_cell(vect2):
var x = floor(vect2.x / board_cell)
var y = floor(vect2.y / board_cell)
return [x,y]
2023-02-17 11:37:23 -08:00
func movetile_clicked(move_tile):
2023-02-18 13:41:27 -08:00
#rint("Yep, I was clicked")
2023-02-17 11:37:23 -08:00
var location = click_spot()
var check = board[location[0]][location[1]]
2023-02-18 13:41:27 -08:00
var curr_piece = board[movement_layer_piece[0]][movement_layer_piece[1]]
2023-02-17 11:37:23 -08:00
if ! check:
pass
else:
check.kill()
2023-02-18 13:41:27 -08:00
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:
var rook_location = position_to_board_cell(move_tile.castling_rook.position)
# king
if 7 == rook_location[0]:
move_tile.castling_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
else:
move_tile.castling_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))
2023-02-17 11:37:23 -08:00
board[movement_layer_piece[0]][movement_layer_piece[1]] = 0
remove_movement_layer()
safely_handle_movement = true
2023-02-18 13:41:27 -08:00
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
2023-02-17 11:37:23 -08:00
2023-02-18 13:41:27 -08:00
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()
2023-02-17 11:37:23 -08:00
2023-02-18 13:41:27 -08:00
func spawn_move_tile(coords, en_passant_tile=false, en_passant_kill_tile=null, castling_rook=null):
2023-02-17 11:37:23 -08:00
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))
2023-02-18 13:41:27 -08:00
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)
2023-02-17 11:37:23 -08:00
2023-02-18 13:41:27 -08:00
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
}):
2023-02-17 11:37:23 -08:00
var x = coords[0]
var y = coords[1]
var pattern0 = pattern[0]
var pattern1 = pattern[1]
var a = 0
var b = 0
var board_size_x = 7 # starting at 0
var board_size_y = 7
var made_tile = false
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_size_x and (y + b) <= board_size_y and (x + a) >= 0 and (y + b) >= 0 :
var check = board[x + a][y + b]
2023-02-18 13:41:27 -08:00
if ! check and ! dict.get("must_attack"):
spawn_move_tile([x + a, y + b], dict.get("tile_is_en_passant"), dict.get("en_passant_pawn"), dict.get("castling_rook"))
2023-02-17 11:37:23 -08:00
made_tile = true
2023-02-18 13:54:16 -08:00
elif dict.get("must_attack"):
2023-02-17 11:37:23 -08:00
if ! check:
pass
elif check.get_team() != curr_team:
spawn_move_tile([x + a, y + b])
made_tile = true
elif ! cant_attack and check.get_team() != curr_team:
2023-02-18 13:54:16 -08:00
spawn_move_tile([x + a, y + b], dict.get("tile_is_en_passant"), dict.get("en_passant_pawn"))
2023-02-17 11:37:23 -08:00
made_tile = true
break # rules of chess say pieces cant go past another
else:
break
return made_tile
2023-02-18 13:41:27 -08:00
# 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