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 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 team1 = 1 var team2 = 2 func _ready(): make_player1("green") make_player2("red") #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) # 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() #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): 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_passent_nw, en_passent_ne, move_2_down_pawn, move_1_down_pawn, attack_1_sw, attack_1_se, en_passent_sw, en_passent_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 = piece.get_piece() match (piece_name): "pawn": if piece.get_team() == team1: if coords[1] == 6: return [attack_1_nw, move_2_up_pawn, attack_1_ne, en_passent_ne, en_passent_nw] else: return [attack_1_nw, move_1_up_pawn, attack_1_ne, en_passent_ne, en_passent_nw] else: if coords[1] == 1: return [attack_1_sw, move_2_down_pawn, attack_1_se, en_passent_se, en_passent_sw] else: return [attack_1_sw, move_1_down_pawn, attack_1_se, en_passent_se, en_passent_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] _: #rint("no pattern for this one") return [] func can_chess_move(pattern, coords): var can_move = false var curr_piece = board[coords[0]][coords[1]] var curr_team = curr_piece.get_team() 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: 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}) attack_1_sw: if make_tiles(coords, [-1,1], 1, false, curr_team, {"must_attack": true}): can_move = true attack_1_se: 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 move_1_up_pawn: if make_tiles(coords, [0,-1], 1, true, curr_team): can_move = true move_2_up_pawn: 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}) attack_1_nw: if make_tiles(coords, [-1,-1], 1, false, curr_team, {"must_attack": true}): can_move = true attack_1_ne: 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 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 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 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 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: 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)) 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 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 }): 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 = 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_WIDTH and (y + b) <= BOARD_HEIGHT and (x + a) >= 0 and (y + b) >= 0 : var check = board[x + a][y + b] 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")) made_tile = true elif dict.get("must_attack"): 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: spawn_move_tile([x + a, y + b], dict.get("tile_is_en_passant"), dict.get("en_passant_pawn")) made_tile = true break # rules of chess say pieces cant go past another 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