From 4b9191e4819a79636ba4a68b7dd9850e622ed40f Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 18 Feb 2023 16:41:27 -0500 Subject: [PATCH] Add en passant and castling --- Main.gd | 206 +++++++++++++++++++++++++++++++++++++++++++--------- Main.tscn | 3 + MoveTile.gd | 4 + Piece.tscn | 4 +- Sprite.gd | 3 + 5 files changed, 183 insertions(+), 37 deletions(-) diff --git a/Main.gd b/Main.gd index 72cbacb..059e2d3 100644 --- a/Main.gd +++ b/Main.gd @@ -11,6 +11,13 @@ 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 @@ -19,11 +26,17 @@ var team2 = 2 func _ready(): make_player1("green") make_player2("red") - print(OS.set_window_size(Vector2(700,700))) + #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): - # hack to prevent 'clicking' on a killed piece safely_handle_movement = false func remove_movement_layer(): @@ -41,9 +54,9 @@ func piece_clicked(piece): else: if ! safely_handle_movement: var piece_name = piece.get_piece() - print("You clicked on a %s, team %s" % [piece_name, piece.get_team()]) + #rint("You clicked on a %s, team %s" % [piece_name, piece.get_team()]) var location = click_spot() - print("Spot: %s " % location) + #rint("Spot: %s " % location) var pattern = get_move_pattern(piece, location) if can_chess_move(pattern, location): movement_layer = true @@ -60,7 +73,7 @@ func make_player2(color): spawn_piece('knight', color, 1, 0, team2) spawn_piece('bishop', color, 2, 0, team2) spawn_piece('queen', color, 3, 0, team2) - spawn_piece('king', color, 4, 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) @@ -72,7 +85,7 @@ func make_player1(color): spawn_piece('knight', color, 1, 7, team1) spawn_piece('bishop', color, 2, 7, team1) spawn_piece('queen', color, 3, 7, team1) - spawn_piece('king', color, 4, 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) @@ -93,18 +106,18 @@ func rand_pos(): # needs to be Vector2 as that is what object.position takes func in_square(vect2): - #print(vect2) + #rint(vect2) vect2.x = ceil(vect2.x / board_cell) - #print(vect2.x) + #rint(vect2.x) vect2.x *= board_cell vect2.x += board_cell / 2 vect2.y = ceil(vect2.y / board_cell) - #print(vect2.y) + #rint(vect2.y) vect2.y *= board_cell vect2.y += board_cell / 2 - #print(vect2) + #rint(vect2) return vect2 func new_board2(): @@ -138,11 +151,15 @@ enum { 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, @@ -157,6 +174,7 @@ enum { move_down_inf, move_left_inf, move_right_inf, + castling, move_nw_inf, move_ne_inf, @@ -172,16 +190,14 @@ func get_move_pattern(piece, coords): "pawn": if piece.get_team() == team1: if coords[1] == 6: - print("This pawn piece hasn't moved!") - return [attack_1_nw, move_2_up_pawn, attack_1_ne] + return [attack_1_nw, move_2_up_pawn, attack_1_ne, en_passent_ne, en_passent_nw] else: - print("This pawn piece has moved and that is hecking brave!") - return [attack_1_nw, move_1_up_pawn, attack_1_ne] + 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] + 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] + 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": @@ -191,32 +207,54 @@ func get_move_pattern(piece, coords): "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] + 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] _: - print("no pattern for this one") + #rint("no pattern for this one") + return [] func can_chess_move(pattern, coords): var can_move = false - var curr_team = board[coords[0]][coords[1]].get_team() + 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], 2, true, curr_team): can_move = true + 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, true): can_move = true + 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, true): can_move = true + 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: + 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], 2, true, curr_team): can_move = true + 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, true): can_move = true + 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, true): can_move = true + 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: + 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 @@ -226,6 +264,38 @@ func can_chess_move(pattern, coords): 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 @@ -264,31 +334,82 @@ func can_chess_move(pattern, coords): 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): - print("Yep, I was clicked") + #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]] = board[movement_layer_piece[0]][movement_layer_piece[1]] - board[movement_layer_piece[0]][movement_layer_piece[1]].position = \ - in_square(Vector2(location[0] * board_cell, location[1] * board_cell)) + 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): +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)) - print(move_tile.position) + 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, must_attack = false): +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] @@ -306,19 +427,32 @@ func make_tiles(coords, pattern, go_range, cant_attack, curr_team, must_attack = # 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] - if ! check and ! must_attack: - spawn_move_tile([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 must_attack: + elif dict.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]) + spawn_move_tile([x + a, y + b], dict.tile_is_en_passant, dict.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 diff --git a/Main.tscn b/Main.tscn index c7d81bc..6c71b06 100644 --- a/Main.tscn +++ b/Main.tscn @@ -46,3 +46,6 @@ tile_set = SubResource( 1 ) cell_size = Vector2( 128, 128 ) format = 1 tile_data = PoolIntArray( 0, 1, 0, 1, 0, 0, 2, 1, 0, 3, 0, 0, 4, 1, 0, 5, 0, 0, 6, 1, 0, 7, 0, 0, 65536, 0, 0, 65537, 1, 0, 65538, 0, 0, 65539, 1, 0, 65540, 0, 0, 65541, 1, 0, 65542, 0, 0, 65543, 1, 0, 131072, 1, 0, 131073, 0, 0, 131074, 1, 0, 131075, 0, 0, 131076, 1, 0, 131077, 0, 0, 131078, 1, 0, 131079, 0, 0, 196608, 0, 0, 196609, 1, 0, 196610, 0, 0, 196611, 1, 0, 196612, 0, 0, 196613, 1, 0, 196614, 0, 0, 196615, 1, 0, 262144, 1, 0, 262145, 0, 0, 262146, 1, 0, 262147, 0, 0, 262148, 1, 0, 262149, 0, 0, 262150, 1, 0, 262151, 0, 0, 327680, 0, 0, 327681, 1, 0, 327682, 0, 0, 327683, 1, 0, 327684, 0, 0, 327685, 1, 0, 327686, 0, 0, 327687, 1, 0, 393216, 1, 0, 393217, 0, 0, 393218, 1, 0, 393219, 0, 0, 393220, 1, 0, 393221, 0, 0, 393222, 1, 0, 393223, 0, 0, 458752, 0, 0, 458753, 1, 0, 458754, 0, 0, 458755, 1, 0, 458756, 0, 0, 458757, 1, 0, 458758, 0, 0, 458759, 1, 0 ) +__meta__ = { +"_editor_description_": "" +} diff --git a/MoveTile.gd b/MoveTile.gd index 5ae65b5..8bc8ca4 100644 --- a/MoveTile.gd +++ b/MoveTile.gd @@ -5,6 +5,10 @@ signal move_clicked const blue = Color(0.30, 0.71, 0.96, 0.54) const red = Color(1.00, 0.00, 0.00, 0.54) +export var en_passant_tile = false +export var en_passant_kill_tile = false +export var castling_rook = "" + func _on_Area2D_input_event(viewport, event, shape_idx): if event.is_action_pressed("mouse1"): emit_signal("move_clicked") diff --git a/Piece.tscn b/Piece.tscn index 8361904..435ab11 100644 --- a/Piece.tscn +++ b/Piece.tscn @@ -11,7 +11,9 @@ region = Rect2( 0, 0, 128, 128 ) [sub_resource type="RectangleShape2D" id=2] -[node name="Piece" type="Sprite"] +[node name="Piece" type="Sprite" groups=[ +"piece", +]] texture = SubResource( 1 ) script = ExtResource( 2 ) diff --git a/Sprite.gd b/Sprite.gd index 61ccf06..5e3802a 100644 --- a/Sprite.gd +++ b/Sprite.gd @@ -8,6 +8,9 @@ var CELL_H = 128 export var piece = 'pawn' export var team = 0 +export var has_moved = false +export var in_check = false + const move_patterns = { pawn = [[0,0,0],[2,0,0],[0,0,0]] }