diff --git a/.gitignore b/.gitignore index 488f0d9..e25202a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # Chess engine binaries and their subdirectories Assets/ChessEngines/stockfish/* Assets/ChessEngines/Fairy-Stockfish/* +Assets/ChessEngines/quack/* # Assets/ChessEngines/stockfish/** # Assets/ChessEngines/Fairy-Stockfish/** diff --git a/Systems/Game/ChessGame.gd b/Systems/Game/ChessGame.gd index be222b8..7ef5351 100644 --- a/Systems/Game/ChessGame.gd +++ b/Systems/Game/ChessGame.gd @@ -640,10 +640,14 @@ func is_tile_reached(location: String, piece_name: String = "") -> bool: func resolveMoveEffects() -> void: # Resolve effects after a move is made - print("resolveMoveEffects", currentlyMovingPiece) + print("resolveMoveEffects ",) + # print("togglePieceChessEffect ", currentlyMovingPiece) togglePieceChessEffect() + # print("togglePieceChessEffect Done ",) selectedNode = "" + # print("resetHighlights ",) resetHighlights() + # print("resetHighlights Done ",) currentlyMovingPiece = null func endTurn() -> void: diff --git a/Systems/Game/HandPreloadScreen.gd b/Systems/Game/HandPreloadScreen.gd index f90ae99..7404491 100644 --- a/Systems/Game/HandPreloadScreen.gd +++ b/Systems/Game/HandPreloadScreen.gd @@ -162,7 +162,7 @@ func _on_bank_card_selected(card_item, card): print("_on_bank_card_selected ", card.id) # Find first empty slot in deck var empty_slot_index = -1 - if card and (card.rank == Card.Rank.RANK_2 || card.rank == Card.Rank.RANK_3): + if card and (Utils.HandRankWhiteList.has(card.rank)): for i in range(deckGrid.get_child_count()): var slot = deckGrid.get_child(i) if !slot.has_card(): diff --git a/Systems/Game/Map/MapGenerator.gd b/Systems/Game/Map/MapGenerator.gd index c9154a3..9384062 100644 --- a/Systems/Game/Map/MapGenerator.gd +++ b/Systems/Game/Map/MapGenerator.gd @@ -551,11 +551,12 @@ func generate_chess_data(node, player): # print("generate_chess_data ", index) var unit_string = level_unit_distribution[index] var pawn_string = "" - + var height = 6; + unit_string = level_unit_distribution[level_unit_distribution.size() - 1] + height = 8 for x in unit_string.length(): pawn_string += "p" - var height = 6; # "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR" var fen = ""; if node.level > 8 and node.level <= 10: diff --git a/Systems/StateMachine/GameStates/Movement.gd b/Systems/StateMachine/GameStates/Movement.gd index ad54de5..8459d60 100644 --- a/Systems/StateMachine/GameStates/Movement.gd +++ b/Systems/StateMachine/GameStates/Movement.gd @@ -184,7 +184,7 @@ func handleMovement(location: String, generated: bool = false) -> void: game.selectedNode = location game.getMovableAreas() return - print("Movemnet ", moves) + # print("Movemnet ", moves) if isCastlingMove(node, location): handleCastling(node, generated) finished.emit(Constants.POST_MOVE) @@ -208,7 +208,7 @@ func handleMovement(location: String, generated: bool = false) -> void: else: if game.isValidMove(location) || generated: # executeMove(location) - + # print("handleRegularMove Start") handleRegularMove(node, consumeMove, generated) if consumeMove: multiMoving = "" @@ -347,18 +347,21 @@ func handleCaptureMovement(node: PieceContainer) -> void: func handleRegularMove(node: PieceContainer, consume: bool, generated: bool = false) -> void: - print("handleRegularMove", node, game.selectedNode) + # print("handleRegularMove", node, game.selectedNode) if generated: moveAndConsume(node, consume) return for i in game.areas: if i == node.name: + # print("handleRegularMove move Consume", ) moveAndConsume(node, consume) - + break + # print("handleRegularMove Done", ) +# func moveAndConsume(node: PieceContainer, consume: bool) -> void: var sourceContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer + # print("Removing Piece 1 ") var piece = sourceContainer.get_piece() - # print("Removing Piece 1") node.animate_movement(sourceContainer, piece); game.currentlyMovingPiece = piece if consume: diff --git a/Utils/Utils.gd b/Utils/Utils.gd index e037af6..095e4c4 100644 --- a/Utils/Utils.gd +++ b/Utils/Utils.gd @@ -110,6 +110,8 @@ static var CardPrices = { Card.Rank.RANK_3: 25 # Common (Rank 3) } +static var HandRankWhiteList = [Card.Rank.RANK_2, Card.Rank.RANK_3] + static var TokenCosts = { Card.Rank.RANK_0: 15, # Most expensive (one-time use) Card.Rank.RANK_1: 10, # Expensive (once per match) diff --git a/addons/Chess/Scripts/Bishop.gd b/addons/Chess/Scripts/Bishop.gd index 649b0ea..7bca576 100644 --- a/addons/Chess/Scripts/Bishop.gd +++ b/addons/Chess/Scripts/Bishop.gd @@ -5,6 +5,8 @@ class_name Bishop func _ready(): self.texture = load("res://addons/Chess/Textures/WBishop.svg") Points = 3 + original_movement_string = "B" + current_movement_string = original_movement_string func _process(_delta): if Item_Color != Temp_Color: @@ -15,35 +17,35 @@ func _process(_delta): self.texture = load("res://addons/Chess/Textures/BBishop.svg") -func getValidMoves(board_flow, current_location: String) -> Dictionary: - var moves = { - "regular_moves": [], - "special_moves": [] - } +# func getValidMoves(board_flow, current_location: String) -> Dictionary: +# var moves = { +# "regular_moves": [], +# "special_moves": [] +# } - var loc = current_location.split("-") - var x = int(loc[0]) - var y = int(loc[1]) +# var loc = current_location.split("-") +# var x = int(loc[0]) +# var y = int(loc[1]) - # Bishop moves diagonally - var diagonal_dirs = [[1,1], [1,-1], [-1,1], [-1,-1]] - for dir in diagonal_dirs: - var curr_x = x - var curr_y = y - while true: - curr_x += dir[0] - curr_y += dir[1] - var new_loc = str(curr_x) + "-" + str(curr_y) +# # Bishop moves diagonally +# var diagonal_dirs = [[1,1], [1,-1], [-1,1], [-1,-1]] +# for dir in diagonal_dirs: +# var curr_x = x +# var curr_y = y +# while true: +# curr_x += dir[0] +# curr_y += dir[1] +# var new_loc = str(curr_x) + "-" + str(curr_y) - if !is_valid_cell(board_flow, new_loc): - break +# if !is_valid_cell(board_flow, new_loc): +# break - if can_move_to_cell(board_flow, new_loc): - moves.regular_moves.append(new_loc) - elif can_move_to_cell(board_flow, new_loc, true): - moves.regular_moves.append(new_loc) - break - else: - break +# if can_move_to_cell(board_flow, new_loc): +# moves.regular_moves.append(new_loc) +# elif can_move_to_cell(board_flow, new_loc, true): +# moves.regular_moves.append(new_loc) +# break +# else: +# break - return moves +# return moves diff --git a/addons/Chess/Scripts/King.gd b/addons/Chess/Scripts/King.gd index 6845980..7c0dcff 100644 --- a/addons/Chess/Scripts/King.gd +++ b/addons/Chess/Scripts/King.gd @@ -4,9 +4,12 @@ class_name King var Castling = true + func _ready(): self.texture = load("res://addons/Chess/Textures/WKing.svg") Points = 10 + original_movement_string = "WF" + current_movement_string = original_movement_string func _process(_delta): if Item_Color != Temp_Color: @@ -17,43 +20,43 @@ func _process(_delta): self.texture = load("res://addons/Chess/Textures/BKing.svg") # King.gd -func getValidMoves(board_flow, current_location: String) -> Dictionary: - var moves = { - "regular_moves": [], - "special_moves": [] - } +# func getValidMoves(board_flow, current_location: String) -> Dictionary: +# var moves = { +# "regular_moves": [], +# "special_moves": [] +# } - var loc = current_location.split("-") - var x = int(loc[0]) - var y = int(loc[1]) +# var loc = current_location.split("-") +# var x = int(loc[0]) +# var y = int(loc[1]) - # Regular king moves (unchanged) - var king_dirs = [[0,1], [0,-1], [1,0], [-1,0], [1,1], [1,-1], [-1,1], [-1,-1]] - for dir in king_dirs: - var new_loc = str(x + dir[0]) + "-" + str(y + dir[1]) - if is_valid_cell(board_flow, new_loc): - if can_move_to_cell(board_flow, new_loc) || can_move_to_cell(board_flow, new_loc, true): - moves.regular_moves.append(new_loc) +# # Regular king moves (unchanged) +# var king_dirs = [[0,1], [0,-1], [1,0], [-1,0], [1,1], [1,-1], [-1,1], [-1,-1]] +# for dir in king_dirs: +# var new_loc = str(x + dir[0]) + "-" + str(y + dir[1]) +# if is_valid_cell(board_flow, new_loc): +# if can_move_to_cell(board_flow, new_loc) || can_move_to_cell(board_flow, new_loc, true): +# moves.regular_moves.append(new_loc) - # Castling logic - if Castling: - # Kingside castling (right side) - if check_kingside_castle(board_flow, x, y): - # Add rook's current position to regular moves - moves.regular_moves.append(str(x + 3) + "-" + str(y)) - # Add king and rook destinations to special moves as individual items - moves.special_moves.append(str(x + 1) + "-" + str(y)) # Rook's destination - moves.special_moves.append(str(x + 2) + "-" + str(y)) # King's destination +# # Castling logic +# if Castling: +# # Kingside castling (right side) +# if check_kingside_castle(board_flow, x, y): +# # Add rook's current position to regular moves +# moves.regular_moves.append(str(x + 3) + "-" + str(y)) +# # Add king and rook destinations to special moves as individual items +# moves.special_moves.append(str(x + 1) + "-" + str(y)) # Rook's destination +# moves.special_moves.append(str(x + 2) + "-" + str(y)) # King's destination - # Queenside castling (left side) - if check_queenside_castle(board_flow, x, y): - # Add rook's current position to regular moves - moves.regular_moves.append(str(x - 4) + "-" + str(y)) - # Add king and rook destinations to special moves as individual items - moves.special_moves.append(str(x - 1) + "-" + str(y)) # Rook's destination - moves.special_moves.append(str(x - 2) + "-" + str(y)) # King's destination +# # Queenside castling (left side) +# if check_queenside_castle(board_flow, x, y): +# # Add rook's current position to regular moves +# moves.regular_moves.append(str(x - 4) + "-" + str(y)) +# # Add king and rook destinations to special moves as individual items +# moves.special_moves.append(str(x - 1) + "-" + str(y)) # Rook's destination +# moves.special_moves.append(str(x - 2) + "-" + str(y)) # King's destination - return moves +# return moves func check_kingside_castle(board_flow, x: int, y: int) -> bool: # Check if path is clear diff --git a/addons/Chess/Scripts/Knight.gd b/addons/Chess/Scripts/Knight.gd index ab62d52..400823c 100644 --- a/addons/Chess/Scripts/Knight.gd +++ b/addons/Chess/Scripts/Knight.gd @@ -1,9 +1,12 @@ @tool extends Pawn class_name Knight + func _ready(): self.texture = load("res://addons/Chess/Textures/WKnight.svg") Points = 3 + original_movement_string = "N" + current_movement_string = original_movement_string func _process(_delta): if Item_Color != Temp_Color: @@ -13,75 +16,75 @@ func _process(_delta): elif Item_Color == 1: self.texture = load("res://addons/Chess/Textures/BKnight.svg") -func getValidMoves(board_flow, current_location: String) -> Dictionary: - var moves = { - "regular_moves": [], - "special_moves": [] - } +# func getValidMoves(board_flow, current_location: String) -> Dictionary: +# var moves = { +# "regular_moves": [], +# "special_moves": [] +# } - var loc = current_location.split("-") - var x = int(loc[0]) - var y = int(loc[1]) - game = board_flow.get_parent() as ChessGame +# var loc = current_location.split("-") +# var x = int(loc[0]) +# var y = int(loc[1]) +# game = board_flow.get_parent() as ChessGame - # All possible L-shaped moves - var knight_moves = [ - [-2, -1], [-2, 1], - [-1, -2], [-1, 2], - [1, -2], [1, 2], - [2, -1], [2, 1] - ] +# # All possible L-shaped moves +# var knight_moves = [ +# [-2, -1], [-2, 1], +# [-1, -2], [-1, 2], +# [1, -2], [1, 2], +# [2, -1], [2, 1] +# ] - for move in knight_moves: - var target_x = x + move[0] - var target_y = y + move[1] - var new_loc = str(target_x) + "-" + str(target_y) +# for move in knight_moves: +# var target_x = x + move[0] +# var target_y = y + move[1] +# var new_loc = str(target_x) + "-" + str(target_y) - if is_valid_cell(board_flow, new_loc): - # Check both possible paths to the target - var horizontal_first_clear = true - var vertical_first_clear = true +# if is_valid_cell(board_flow, new_loc): +# # Check both possible paths to the target +# var horizontal_first_clear = true +# var vertical_first_clear = true - # Path 1: Check horizontal first, then vertical - # Check horizontal movement - var step_x = sign(move[0]) - for i in range(1, abs(move[0]) + 1): - var path_tile_loc = str(x + (i * step_x)) + "-" + str(y) - var tile = game.tileManager.get_tile(path_tile_loc) - if tile && !tile.jumpable: - horizontal_first_clear = false - break +# # Path 1: Check horizontal first, then vertical +# # Check horizontal movement +# var step_x = sign(move[0]) +# for i in range(1, abs(move[0]) + 1): +# var path_tile_loc = str(x + (i * step_x)) + "-" + str(y) +# var tile = game.tileManager.get_tile(path_tile_loc) +# if tile && !tile.jumpable: +# horizontal_first_clear = false +# break - # Check vertical movement if horizontal was clear - if horizontal_first_clear: - var step_y = sign(move[1]) - var path_tile_loc = str(target_x) + "-" + str(y + step_y) - var tile = game.tileManager.get_tile(path_tile_loc) - if tile && !tile.jumpable: - horizontal_first_clear = false +# # Check vertical movement if horizontal was clear +# if horizontal_first_clear: +# var step_y = sign(move[1]) +# var path_tile_loc = str(target_x) + "-" + str(y + step_y) +# var tile = game.tileManager.get_tile(path_tile_loc) +# if tile && !tile.jumpable: +# horizontal_first_clear = false - # Path 2: Check vertical first, then horizontal - # Check vertical movement - var step_y = sign(move[1]) - for i in range(1, abs(move[1]) + 1): - var path_tile_loc = str(x) + "-" + str(y + (i * step_y)) - var tile = game.tileManager.get_tile(path_tile_loc) - if tile && !tile.jumpable: - vertical_first_clear = false - break +# # Path 2: Check vertical first, then horizontal +# # Check vertical movement +# var step_y = sign(move[1]) +# for i in range(1, abs(move[1]) + 1): +# var path_tile_loc = str(x) + "-" + str(y + (i * step_y)) +# var tile = game.tileManager.get_tile(path_tile_loc) +# if tile && !tile.jumpable: +# vertical_first_clear = false +# break - # Check horizontal movement if vertical was clear - if vertical_first_clear: - var path_tile_loc = str(x + step_x) + "-" + str(target_y) - var tile = game.tileManager.get_tile(path_tile_loc) - if tile && !tile.jumpable: - vertical_first_clear = false +# # Check horizontal movement if vertical was clear +# if vertical_first_clear: +# var path_tile_loc = str(x + step_x) + "-" + str(target_y) +# var tile = game.tileManager.get_tile(path_tile_loc) +# if tile && !tile.jumpable: +# vertical_first_clear = false - # Move is valid if EITHER path is clear - if (horizontal_first_clear || vertical_first_clear) && (can_move_to_cell(board_flow, new_loc) || can_move_to_cell(board_flow, new_loc, true)): - moves.regular_moves.append(new_loc) +# # Move is valid if EITHER path is clear +# if (horizontal_first_clear || vertical_first_clear) && (can_move_to_cell(board_flow, new_loc) || can_move_to_cell(board_flow, new_loc, true)): +# moves.regular_moves.append(new_loc) - return moves +# return moves # func animate_movement(target_position: Vector2, duration: float = 0.5) -> void: diff --git a/addons/Chess/Scripts/Pawn.gd b/addons/Chess/Scripts/Pawn.gd index fef61b4..b702ab3 100644 --- a/addons/Chess/Scripts/Pawn.gd +++ b/addons/Chess/Scripts/Pawn.gd @@ -11,6 +11,7 @@ class_name Pawn @export var Points = 1 + var game: ChessGame = null var duration_label: Label var Temp_Color = 0 @@ -20,153 +21,376 @@ const BASE_SIZE = Vector2(40, 40) const CARD_TINT_COLOR = Color(0.3, 0.8, 0.3, 0.5) # Green tint for card effects const EFFECT_TINT_COLOR = Color(0.8, 0.2, 0.2, 0.5) var id: String = Utils.generate_guid() +var original_movement_string: String = "mfWcfF" +var current_movement_string: String = original_movement_string + +const DIRECTIONS = { + "b": [0, 1], # backward + "f": [0, -1], # forward + "l": [-1, 0], # right + "r": [1, 0], # left + "bl": [-1, 1], # forward-right + "br": [1, 1], # forward-left + "fl": [-1, -1], # backward-right + "fr": [1, -1] # backward-left +} func _ready(): - modulate = Color.WHITE if Item_Color == 0 else Color.BLACK + modulate = Color.WHITE if Item_Color == 0 else Color.BLACK func _init(chess: ChessGame) -> void: - game = chess - self.texture = load("res://addons/Chess/Textures/WPawn.svg") - var background_style = StyleBoxFlat.new() - background_style.bg_color = Color.WHITE - background_style.corner_radius_top_left = 2 - background_style.corner_radius_top_right = 2 - background_style.corner_radius_bottom_left = 2 - background_style.corner_radius_bottom_right = 2 - background_style.content_margin_left = 2 - background_style.content_margin_right = 2 - background_style.content_margin_top = 1 - background_style.content_margin_bottom = 1 - duration_label = Label.new() - duration_label.add_theme_stylebox_override("normal", background_style) - duration_label.add_theme_color_override("font_color", Color.BLACK) - duration_label.position = Vector2(-20, -20) # Position above the piece - add_child(duration_label) - duration_label.hide() + game = chess + self.texture = load("res://addons/Chess/Textures/WPawn.svg") + var background_style = StyleBoxFlat.new() + background_style.bg_color = Color.WHITE + background_style.corner_radius_top_left = 2 + background_style.corner_radius_top_right = 2 + background_style.corner_radius_bottom_left = 2 + background_style.corner_radius_bottom_right = 2 + background_style.content_margin_left = 2 + background_style.content_margin_right = 2 + background_style.content_margin_top = 1 + background_style.content_margin_bottom = 1 + duration_label = Label.new() + duration_label.add_theme_stylebox_override("normal", background_style) + duration_label.add_theme_color_override("font_color", Color.BLACK) + duration_label.position = Vector2(-20, -20) # Position above the piece + add_child(duration_label) + duration_label.hide() func update_appearance() -> void: - # print("update_appearance") - var chess_game = game - if !is_instance_valid(get_tree()) || !chess_game: - return - - if !chess_game.deckManager: - return - - var deck_manager = chess_game.deckManager - var has_card = deck_manager.attached_cards.has(get_instance_id()) - var has_effect = deck_manager.attached_effects.has(get_instance_id()) - var base_color = Color.WHITE if Item_Color == 0 else Color.BLACK + # print("update_appearance") + var chess_game = game + if !is_instance_valid(get_tree()) || !chess_game: + return + + if !chess_game.deckManager: + return + + var deck_manager = chess_game.deckManager + var has_card = deck_manager.attached_cards.has(get_instance_id()) + var has_effect = deck_manager.attached_effects.has(get_instance_id()) + var base_color = Color.WHITE if Item_Color == 0 else Color.BLACK - if has_effect and deck_manager.attached_effects[get_instance_id()].size() > 0: - modulate = base_color * ( EFFECT_TINT_COLOR) - if has_card: - # Apply tint while keeping the piece color - modulate = base_color * CARD_TINT_COLOR - - - # Update duration display - var card = deck_manager.attached_cards[get_instance_id()] - if is_instance_valid(duration_label): - duration_label.text = str(card.remaining_turns) - duration_label.show() - else: - # Reset to normal color - modulate = Color.WHITE if Item_Color == 0 else Color.BLACK - if is_instance_valid(duration_label): - duration_label.hide() + if has_effect and deck_manager.attached_effects[get_instance_id()].size() > 0: + modulate = base_color * ( EFFECT_TINT_COLOR) + if has_card: + # Apply tint while keeping the piece color + modulate = base_color * CARD_TINT_COLOR + + + # Update duration display + var card = deck_manager.attached_cards[get_instance_id()] + if is_instance_valid(duration_label): + duration_label.text = str(card.remaining_turns) + duration_label.show() + else: + # Reset to normal color + modulate = Color.WHITE if Item_Color == 0 else Color.BLACK + if is_instance_valid(duration_label): + duration_label.hide() func on_card_effect_changed() -> void: - update_appearance() + update_appearance() # Movement interface method that all pieces will implement -# In Pawn.gd func getValidMoves(board_flow, current_location: String) -> Dictionary: - var moves = { - "regular_moves": [], - "special_moves": [] - } - - var loc = current_location.split("-") - var x = int(loc[0]) - var y = int(loc[1]) - - # Movement direction based on color - var direction = -1 if Item_Color == 0 else 1 - - # Forward movement - var forward = str(x) + "-" + str(y + direction) - if is_valid_cell(board_flow, forward) && can_move_to_cell(board_flow, forward): - moves.regular_moves.append(forward) - - # Double move on first turn - var double_forward = str(x) + "-" + str(y + (direction * 2)) - if Double_Start && is_valid_cell(board_flow, double_forward) && can_move_to_cell(board_flow, double_forward): - moves.regular_moves.append(double_forward) - - # Diagonal captures - for dx in [-1, 1]: - var capture = str(x + dx) + "-" + str(y + direction) - if is_valid_cell(board_flow, capture) && can_move_to_cell(board_flow, capture, true): - moves.regular_moves.append(capture) - - # En Passant - var adjacent = str(x + dx) + "-" + str(y) - if is_valid_cell(board_flow, adjacent) && is_valid_cell(board_flow, capture): - var adjacent_cell = board_flow.get_node(adjacent) as PieceContainer - if adjacent_cell.get_piece() != null: - var adjacent_piece = adjacent_cell.get_piece() - if adjacent_piece.name == "Pawn" && adjacent_piece.En_Passant && adjacent_piece.Item_Color != self.Item_Color: - moves.special_moves.append([adjacent, capture]) - - return moves + var moves = { + "regular_moves": [], + "special_moves": [] + } + + var loc = current_location.split("-") + var x = int(loc[0]) + var y = int(loc[1]) + + # Invert directions if black + var direction_multiplier = 1 if Item_Color == 1 else -1 + + # Parse the Betza notation + var atoms = parseBetzaNotation(current_movement_string) + + # Process each atom + for atom in atoms: + var can_move = "m" in atom.modifiers || (!("m" in atom.modifiers) && !("c" in atom.modifiers)) + var can_capture = "c" in atom.modifiers || (!("m" in atom.modifiers) && !("c" in atom.modifiers)) + + # Get directions for this atom + var directions = getDirectionsForAtom(atom) + + # Process each direction + for dir in directions: + var dir_vector = DIRECTIONS[dir].duplicate() + + # Adjust direction based on color + if Item_Color == 1: # If black + if "f" in dir: + dir_vector[1] *= -1 + if "b" in dir: + dir_vector[1] *= -1 + if "l" in dir: + dir_vector[0] *= -1 + if "r" in dir: + dir_vector[0] *= -1 + + # Handle different atom types + match atom.type: + "W": # Wazir (orthogonal step) + processStep(board_flow, moves, x, y, dir_vector, can_move, can_capture) + "F": # Ferz (diagonal step) + processStep(board_flow, moves, x, y, dir_vector, can_move, can_capture) + "R": # Rook (orthogonal slider) + processSlider(board_flow, moves, x, y, dir_vector, can_move, can_capture, atom.range) + "B": # Bishop (diagonal slider) + processSlider(board_flow, moves, x, y, dir_vector, can_move, can_capture, atom.range) + "N": # Knight + processKnightMove(board_flow, moves, x, y, dir_vector, can_move, can_capture) + + # Add special pawn moves if this is a pawn + if original_movement_string == "mfWcfF": + addSpecialPawnMoves(board_flow, moves, x, y) + + return moves # Helper method for all pieces func is_valid_cell(board_flow, location: String) -> bool: - var node = board_flow.get_node_or_null(location) - return node != null + var node = board_flow.get_node_or_null(location) + return node != null # Helper for checking if cell is empty or contains enemy func can_move_to_cell(board_flow, location: String, is_capture: bool = false) -> bool: - var container = board_flow.get_node(location) as PieceContainer - var game = board_flow.get_parent() as ChessGame - var tile = game.tileManager.get_tile(location) - if tile && !tile.passable: - return false - if is_capture: - var piece = container.get_piece() - return piece != null && piece.Item_Color != self.Item_Color - return !container.has_piece() + var container = board_flow.get_node(location) as PieceContainer + var game = board_flow.get_parent() as ChessGame + var tile = game.tileManager.get_tile(location) + if tile && !tile.passable: + return false + if is_capture: + var piece = container.get_piece() + return piece != null && piece.Item_Color != self.Item_Color + return !container.has_piece() + +func set_current_movement_string(mvmnt: String): + current_movement_string = mvmnt + +func get_current_movement_string() -> String: + return current_movement_string + +func get_original_movement_string() -> String: + return original_movement_string func animate_movement(target_position: Vector2, duration: float = 0.5) -> void: - # print("--------------STARTING ANIM--------------", position, " ", target_position) - z_index = 1 - var tween = create_tween() - # Make sure the tween is configured properly - tween.set_trans(Tween.TRANS_LINEAR) # or TRANS_CUBIC for smoother movement - tween.set_ease(Tween.EASE_IN_OUT) + # print("--------------STARTING ANIM--------------", position, " ", target_position) + z_index = 1 + var tween = create_tween() + # Make sure the tween is configured properly + tween.set_trans(Tween.TRANS_LINEAR) # or TRANS_CUBIC for smoother movement + tween.set_ease(Tween.EASE_IN_OUT) - var start_pos = position - tween.tween_property(self, "global_position", target_position, duration) - #.from(start_pos) + var start_pos = position + tween.tween_property(self, "global_position", target_position, duration) + #.from(start_pos) - # Wait for animation to complete - await tween.finished - # print("--------------FINISHED ANIM--------------") + # Wait for animation to complete + await tween.finished + # print("--------------FINISHED ANIM--------------") func animate_capture(duration: float = 0.5) -> void: - z_index = 1 # Ensure piece is visible above others during animation - var tween = create_tween() - tween.set_trans(Tween.TRANS_LINEAR) - tween.set_ease(Tween.EASE_IN_OUT) + z_index = 1 # Ensure piece is visible above others during animation + var tween = create_tween() + tween.set_trans(Tween.TRANS_LINEAR) + tween.set_ease(Tween.EASE_IN_OUT) - # First turn red - tween.tween_property(self, "modulate", Color.RED, duration/2) - # Then shrink to nothing - tween.tween_property(self, "scale", Vector2.ZERO, duration/2) - # Finally remove the piece - tween.tween_callback(queue_free) + # First turn red + tween.tween_property(self, "modulate", Color.RED, duration/2) + # Then shrink to nothing + tween.tween_property(self, "scale", Vector2.ZERO, duration/2) + # Finally remove the piece + tween.tween_callback(queue_free) - await tween.finished \ No newline at end of file + await tween.finished + + +# ========================BETZA NOTATION================ + +# Parse the Betza notation string into a list of atoms +func parseBetzaNotation(notation: String) -> Array: + var atoms = [] + var i = 0 + + while i < notation.length(): + var atom = { + "type": "", + "modifiers": [], + "range": -1 # -1 unlimited + } + + # Collect modifiers before the atom type + while i < notation.length() && ["m", "c"].has(notation[i]): + atom.modifiers.append(notation[i]) + i += 1 + + # direction modifiers + var directions = "" + while i < notation.length() && ["f", "b", "l", "r"].has(notation[i]): + directions += notation[i] + i += 1 + + if directions: + atom.modifiers.append(directions) + + # atom type + if i < notation.length(): + atom.type = notation[i] + i += 1 + + # range specification + var range_str = "" + while i < notation.length() && notation[i].is_valid_int(): + range_str += notation[i] + i += 1 + + if range_str: + atom.range = int(range_str) + + atoms.append(atom) + + return atoms + +# Directions for an atom based on its modifiers +func getDirectionsForAtom(atom) -> Array: + var base_directions = [] + var direction_modifiers = [] + + # Extract direction modifiers + for modifier in atom.modifiers: + if modifier.length() > 1 || ["f", "b", "l", "r"].has(modifier): + for char in modifier: + if ["f", "b", "l", "r"].has(char): + direction_modifiers.append(char) + + # Set base directions based on atom type + match atom.type: + "W": # Wazir + base_directions = ["f", "b", "l", "r"] + "F": # Ferz + base_directions = ["fl", "fr", "bl", "br"] + "R": # Rook + base_directions = ["f", "b", "l", "r"] + "B": # Bishop + base_directions = ["fl", "fr", "bl", "br"] + "Q": # Queen + base_directions = ["f", "b", "l", "r", "fl", "fr", "bl", "br"] + "K": # King + base_directions = ["f", "b", "l", "r", "fl", "fr", "bl", "br"] + "N": # Knight - directions handled specially + base_directions = ["f", "b", "l", "r"] + + # Filter directions based on modifiers - NEW LOGIC HERE + if direction_modifiers: + var filtered_directions = [] + + for dir in base_directions: + # For each direction, check if it CONTAINS any of the modifiers + # (doesn't need to match all characters) + var contains_modifier = false + for mod in direction_modifiers: + if dir.contains(mod): + contains_modifier = true + break + + if contains_modifier: + filtered_directions.append(dir) + + return filtered_directions + + return base_directions + +# Process a single step move +func processStep(board_flow, moves, x, y, dir_vector, can_move, can_capture): + var new_x = x + dir_vector[0] + var new_y = y + dir_vector[1] + var target = str(new_x) + "-" + str(new_y) + print("processStep " + target ) + + if is_valid_cell(board_flow, target): + if can_move && can_move_to_cell(board_flow, target, false): + if !moves.regular_moves.has(target): + moves.regular_moves.append(target) + elif can_capture && can_move_to_cell(board_flow, target, true): + if !moves.regular_moves.has(target): + moves.regular_moves.append(target) + +# Process a slider move (rook, bishop, queen) +func processSlider(board_flow, moves, x, y, dir_vector, can_move, can_capture, max_range): + var step = 1 + var blocked = false + + while !blocked && (max_range == -1 || step <= max_range): + var new_x = x + (dir_vector[0] * step) + var new_y = y + (dir_vector[1] * step) + var target = str(new_x) + "-" + str(new_y) + + if !is_valid_cell(board_flow, target): + blocked = true + continue + + var target_cell = board_flow.get_node(target) as PieceContainer + if target_cell.get_piece() == null: + if can_move: + if !moves.regular_moves.has(target): + moves.regular_moves.append(target) + else: + if can_capture && target_cell.get_piece().Item_Color != self.Item_Color: + if !moves.regular_moves.has(target): + moves.regular_moves.append(target) + blocked = true + + step += 1 + +# Process knight move +func processKnightMove(board_flow, moves, x, y, dir_vector, can_move, can_capture): + # Knight directions regardless of the dir_vector + var knight_offsets = [ + [1, 2], [2, 1], [2, -1], [1, -2], + [-1, -2], [-2, -1], [-2, 1], [-1, 2] + ] + + for offset in knight_offsets: + var new_x = x + offset[0] + var new_y = y + offset[1] + var target = str(new_x) + "-" + str(new_y) + + if is_valid_cell(board_flow, target): + var has_piece = board_flow.get_node(target).get_piece() != null + var enemy_piece = has_piece && board_flow.get_node(target).get_piece().Item_Color != self.Item_Color + + if ((can_move && !has_piece) || (can_capture && enemy_piece)): + if !moves.regular_moves.has(target): + moves.regular_moves.append(target) + +# Add special pawn moves (double move, en passant) +func addSpecialPawnMoves(board_flow, moves, x, y): + var direction = 1 if Item_Color == 1 else -1 + + # Double move on first turn + if Double_Start: + var single_forward = str(x) + "-" + str(y + direction) + var double_forward = str(x) + "-" + str(y + (direction * 2)) + + if is_valid_cell(board_flow, single_forward) and is_valid_cell(board_flow, double_forward) and can_move_to_cell(board_flow, single_forward) and can_move_to_cell(board_flow, double_forward): + if !moves.regular_moves.has(double_forward): + moves.regular_moves.append(double_forward) + + # En Passant + for dx in [-1, 1]: + var adjacent = str(x + dx) + "-" + str(y) + var capture = str(x + dx) + "-" + str(y + direction) + + if is_valid_cell(board_flow, adjacent) and is_valid_cell(board_flow, capture): + var adjacent_cell = board_flow.get_node(adjacent) as PieceContainer + if adjacent_cell.get_piece() != null: + var adjacent_piece = adjacent_cell.get_piece() + if adjacent_piece.name == "Pawn" and adjacent_piece.En_Passant and adjacent_piece.Item_Color != self.Item_Color: + moves.special_moves.append([adjacent, capture]) diff --git a/addons/Chess/Scripts/Queen.gd b/addons/Chess/Scripts/Queen.gd index 60a1dfb..e0d36dc 100644 --- a/addons/Chess/Scripts/Queen.gd +++ b/addons/Chess/Scripts/Queen.gd @@ -5,6 +5,8 @@ class_name Queen func _ready(): self.texture = load("res://addons/Chess/Textures/WQueen.svg") Points = 9 + original_movement_string = "RB" + current_movement_string = original_movement_string func _process(_delta): if Item_Color != Temp_Color: Temp_Color = Item_Color @@ -13,57 +15,57 @@ func _process(_delta): elif Item_Color == 1: self.texture = load("res://addons/Chess/Textures/BQueen.svg") -func getValidMoves(board_flow, current_location: String) -> Dictionary: - var moves = { - "regular_moves": [], - "special_moves": [] - } +# func getValidMoves(board_flow, current_location: String) -> Dictionary: +# var moves = { +# "regular_moves": [], +# "special_moves": [] +# } - var loc = current_location.split("-") - var x = int(loc[0]) - var y = int(loc[1]) +# var loc = current_location.split("-") +# var x = int(loc[0]) +# var y = int(loc[1]) - # Queen combines rook (straight) and bishop (diagonal) movements - # Straight movements - var straight_dirs = [[0,1], [0,-1], [1,0], [-1,0]] - for dir in straight_dirs: - var curr_x = x - var curr_y = y - while true: - curr_x += dir[0] - curr_y += dir[1] - var new_loc = str(curr_x) + "-" + str(curr_y) +# # Queen combines rook (straight) and bishop (diagonal) movements +# # Straight movements +# var straight_dirs = [[0,1], [0,-1], [1,0], [-1,0]] +# for dir in straight_dirs: +# var curr_x = x +# var curr_y = y +# while true: +# curr_x += dir[0] +# curr_y += dir[1] +# var new_loc = str(curr_x) + "-" + str(curr_y) - if !is_valid_cell(board_flow, new_loc): - break +# if !is_valid_cell(board_flow, new_loc): +# break - if can_move_to_cell(board_flow, new_loc): - moves.regular_moves.append(new_loc) - elif can_move_to_cell(board_flow, new_loc, true): - moves.regular_moves.append(new_loc) - break - else: - break +# if can_move_to_cell(board_flow, new_loc): +# moves.regular_moves.append(new_loc) +# elif can_move_to_cell(board_flow, new_loc, true): +# moves.regular_moves.append(new_loc) +# break +# else: +# break - # Diagonal movements - var diagonal_dirs = [[1,1], [1,-1], [-1,1], [-1,-1]] - for dir in diagonal_dirs: - var curr_x = x - var curr_y = y - while true: - curr_x += dir[0] - curr_y += dir[1] - var new_loc = str(curr_x) + "-" + str(curr_y) +# # Diagonal movements +# var diagonal_dirs = [[1,1], [1,-1], [-1,1], [-1,-1]] +# for dir in diagonal_dirs: +# var curr_x = x +# var curr_y = y +# while true: +# curr_x += dir[0] +# curr_y += dir[1] +# var new_loc = str(curr_x) + "-" + str(curr_y) - if !is_valid_cell(board_flow, new_loc): - break +# if !is_valid_cell(board_flow, new_loc): +# break - if can_move_to_cell(board_flow, new_loc): - moves.regular_moves.append(new_loc) - elif can_move_to_cell(board_flow, new_loc, true): - moves.regular_moves.append(new_loc) - break - else: - break +# if can_move_to_cell(board_flow, new_loc): +# moves.regular_moves.append(new_loc) +# elif can_move_to_cell(board_flow, new_loc, true): +# moves.regular_moves.append(new_loc) +# break +# else: +# break - return moves +# return moves diff --git a/addons/Chess/Scripts/Rook.gd b/addons/Chess/Scripts/Rook.gd index 66fb2f1..2a2dd22 100644 --- a/addons/Chess/Scripts/Rook.gd +++ b/addons/Chess/Scripts/Rook.gd @@ -4,9 +4,12 @@ class_name Rook var Castling = true + func _ready(): self.texture = load("res://addons/Chess/Textures/WRook.svg") Points = 5 + original_movement_string = "R" + current_movement_string = original_movement_string func _process(_delta): if Item_Color != Temp_Color: @@ -16,45 +19,45 @@ func _process(_delta): elif Item_Color == 1: self.texture = load("res://addons/Chess/Textures/BRook.svg") -func getValidMoves(board_flow, current_location: String) -> Dictionary: - var moves = { - "regular_moves": [], - "special_moves": [] - } +# func getValidMoves(board_flow, current_location: String) -> Dictionary: +# var moves = { +# "regular_moves": [], +# "special_moves": [] +# } - var loc = current_location.split("-") - var x = int(loc[0]) - var y = int(loc[1]) +# var loc = current_location.split("-") +# var x = int(loc[0]) +# var y = int(loc[1]) - # Check all four directions - var directions = [[0,1], [0,-1], [1,0], [-1,0]] +# # Check all four directions +# var directions = [[0,1], [0,-1], [1,0], [-1,0]] - for dir in directions: - var curr_x = x - var curr_y = y - while true: - curr_x += dir[0] - curr_y += dir[1] - var new_loc = str(curr_x) + "-" + str(curr_y) - if !is_valid_cell(board_flow, new_loc): - break - if can_move_to_cell(board_flow, new_loc): - moves.regular_moves.append(new_loc) - elif can_move_to_cell(board_flow, new_loc, true): - moves.regular_moves.append(new_loc) - break - else: - break +# for dir in directions: +# var curr_x = x +# var curr_y = y +# while true: +# curr_x += dir[0] +# curr_y += dir[1] +# var new_loc = str(curr_x) + "-" + str(curr_y) +# if !is_valid_cell(board_flow, new_loc): +# break +# if can_move_to_cell(board_flow, new_loc): +# moves.regular_moves.append(new_loc) +# elif can_move_to_cell(board_flow, new_loc, true): +# moves.regular_moves.append(new_loc) +# break +# else: +# break - if Castling: - # Check if there's a king that can castle - for direction in [-4, 3]: # Check both sides for king - var king_pos = str(x + direction) + "-" + str(y) - if is_valid_cell(board_flow, king_pos): - var king_container = board_flow.get_node(king_pos) as PieceContainer - var piece = king_container.get_piece() - if piece != null && piece.name == "King" && piece.Castling && piece.Item_Color == self.Item_Color: - moves.special_moves.append([king_pos, current_location]) +# if Castling: +# # Check if there's a king that can castle +# for direction in [-4, 3]: # Check both sides for king +# var king_pos = str(x + direction) + "-" + str(y) +# if is_valid_cell(board_flow, king_pos): +# var king_container = board_flow.get_node(king_pos) as PieceContainer +# var piece = king_container.get_piece() +# if piece != null && piece.name == "King" && piece.Castling && piece.Item_Color == self.Item_Color: +# moves.special_moves.append([king_pos, current_location]) - return moves +# return moves