From 086b1148538652c4fdded4be40ec3ab7f9846496 Mon Sep 17 00:00:00 2001 From: 2ManyProjects Date: Tue, 11 Feb 2025 16:22:40 -0600 Subject: [PATCH] INTEGRADED AI --- .gitignore | 2 + Diagrams/Game Machine.mmd | 6 +- Systems/FairyStockfish/Stockfish.gd | 181 +++++++++++++++++ Systems/Game/ChessGame.gd | 159 ++++++++++++++- Systems/PieceContainer.gd | 3 +- .../GameStates/ApplyTileEffects.gd | 2 +- Systems/StateMachine/GameStates/BlackTurn.gd | 27 ++- Systems/StateMachine/GameStates/Movement.gd | 190 ++++++++++++------ .../StateMachine/GameStates/PostMovePhase.gd | 2 +- .../GameStates/ResolvePersistentEffects.gd | 2 +- board.tscn | 7 - project.godot | 2 +- 12 files changed, 502 insertions(+), 81 deletions(-) create mode 100644 Systems/FairyStockfish/Stockfish.gd diff --git a/.gitignore b/.gitignore index 0af181c..a2218df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ # Godot 4+ specific ignores .godot/ /android/ +stockfish +Assets/ChessEngines diff --git a/Diagrams/Game Machine.mmd b/Diagrams/Game Machine.mmd index 8071ab6..15148b8 100644 --- a/Diagrams/Game Machine.mmd +++ b/Diagrams/Game Machine.mmd @@ -12,15 +12,15 @@ stateDiagram HandSetup --> DrawPhase DrawPhase --> ResolvePersistentEffects : Draw/Discard - ResolvePersistentEffects --> ApplyTileEffects : Update Durations - ApplyTileEffects --> PreMovePhase + ResolvePersistentEffects --> PreMovePhase : Update Durations PreMovePhase --> AttachCards : Play Cards AttachCards --> ApplyCardEffects ApplyCardEffects --> Movement Movement --> PostMovePhase - PostMovePhase --> EvaluatePosition : Resolve Move Effects + PostMovePhase --> ApplyTileEffects : Resolve Move Effects + ApplyTileEffects --> EvaluatePosition state EvaluatePosition { [*] --> CheckStatus diff --git a/Systems/FairyStockfish/Stockfish.gd b/Systems/FairyStockfish/Stockfish.gd new file mode 100644 index 0000000..164ca72 --- /dev/null +++ b/Systems/FairyStockfish/Stockfish.gd @@ -0,0 +1,181 @@ +# Stockfish.gd +extends Node + +# References to game objects +var board: Array +var game: ChessGame + +# Engine state +var engine_path: String = "" +var mutex: Mutex +var running := false + +# Game state +var moves: Array = [] +var move_time: int = 1000 # in ms +var generated_move: Dictionary = {} # Stores the last generated move + +# Piece type mapping +var symbol_from_piece_type := { + "PAWN": "p", "KNIGHT": "n", "BISHOP": "b", + "ROOK": "r", "QUEEN": "q", "KING": "k" +} + +var piece_type_from_symbol := { + "p": "PAWN", "n": "KNIGHT", "b": "BISHOP", + "r": "ROOK", "q": "QUEEN", "k": "KING" +} + +func _init(boardRef: Array): + board = boardRef + mutex = Mutex.new() + +func _ready(): + game = get_parent() as ChessGame + +func _exit_tree(): + disconnect_engine() + +func connect_to_engine(path: String) -> bool: + if running: + return false + + engine_path = path + + # Test if we can execute stockfish + var output = [] + var exit_code = OS.execute(engine_path, ["uci"], output, true) + print("Exit code: ", exit_code) + print("Output: ", output) + if exit_code != OK: + printerr("Failed to start Stockfish engine: ", exit_code) + return false + + running = true + print("Connected to engine: ", engine_path) + + # Initialize with current game state + load_fen(game.getCurrentFen()) + return true + +func disconnect_engine(): + if running: + mutex.lock() + var output = [] + OS.execute(engine_path, ["quit"], output, true) + mutex.unlock() + running = false + engine_path = "" + print("Disconnected from engine") + +func limit_strength_to(elo_value: int): + mutex.lock() + if elo_value != -1: # Using -1 instead of int.MaxValue + _send_command("setoption name UCI_LimitStrength value true") + _send_command("setoption name UCI_Elo value " + str(elo_value)) + else: + _send_command("setoption name UCI_LimitStrength value false") + mutex.unlock() + +func stop_calculating(): + mutex.lock() + _send_command("stop") + mutex.unlock() + +func load_fen(fen: String): + moves.clear() + update_position(fen) + +func update_position(fen: String): + mutex.lock() + _send_command("position fen " + fen) + mutex.unlock() + +func generateMove(think_time_ms: int = 1000) -> void: + if not running: + return + + move_time = think_time_ms + + # Update position first + mutex.lock() + var command = "position fen " + game.getCurrentFen() + if moves.size() > 0: + command += " moves " + " ".join(moves) + print(command) + var output = _send_command(command) + + # Then get move + output = _send_command("go movetime " + str(move_time)) + if output.size() == 0: + return + print(type_string(typeof(output[0]))) + var lines = output[0].split("\n") + mutex.unlock() + # Parse the output + for line in lines: + # print("-") + # print(line) + # print("-") + if line.begins_with("bestmove"): + var parts = line.split(" ") + print( parts) + if parts.size() >= 2: + generated_move = { + "move": parts[1], + "ponder": parts[3] + } + print("Generated move: ", generated_move) + return + + generated_move = {} + +func getGeneratedMove() -> Dictionary: + var move = generated_move.duplicate() + generated_move.clear() # Clear after retrieving + return move + +func from_move_to_string(move_data: Dictionary) -> String: + var board_size = len(board) + + # Get source and target squares + var source_i = move_data.source % board_size + var source_j = move_data.source / board_size + var target_i = move_data.target % board_size + var target_j = move_data.target / board_size + + # Convert to algebraic notation + var letters = "abcdefghijklmnopqrstuvwxyz".substr(0, board_size) + var str_move = "%s%d%s%d" % [ + letters[source_i], + board_size - source_j, + letters[target_i], + board_size - target_j + ] + + # Add promotion piece if needed + if move_data.get("flags", "") == "PROMOTION": + str_move += symbol_from_piece_type[move_data.promotion_piece] + + return str_move + +func send_move(move_data: Dictionary): + var str_move = from_move_to_string(move_data) + moves.append(str_move) + print("move: ", str_move) + + # Update engine with the new move + mutex.lock() + var command = "position fen " + game.getCurrentFen() + if moves.size() > 0: + command += " moves " + " ".join(moves) + _send_command(command) + mutex.unlock() + +func _send_command(command: String) -> Array: + if not running: + return [] + + var output = [] + OS.execute(engine_path, [command], output, true) + return output \ No newline at end of file diff --git a/Systems/Game/ChessGame.gd b/Systems/Game/ChessGame.gd index 6f4acc4..8133fd7 100644 --- a/Systems/Game/ChessGame.gd +++ b/Systems/Game/ChessGame.gd @@ -8,6 +8,11 @@ signal send_location(location: String) signal turn_changed var currentPlayer: String = WHITE var board: Array +var isWhiteToMove: bool = true +var castlingRights: String = "KQkq" +var enPassantTarget: String = "-" +var halfMoveClock: int = 0 +var moveCount: int = 1 var currentHand: Array var selectedNode: String = "" var locationX: String = "" @@ -21,7 +26,9 @@ var currentlyMovingPiece = null var p1Points: int = 0 var p2Points: int = 0 var Turn: int = 0 - +const StockfishController = preload("res://Systems/FairyStockfish/Stockfish.gd") +var stockfishController: StockfishController +var stockfishPath = "res://Assets/ChessEngines/stockfish/stockfish.exe" @onready var turnIndicator: ColorRect = $TurnIndicator @onready var p1String: RichTextLabel = $Player1Points @onready var p2String: RichTextLabel = $Player2Points @@ -41,18 +48,31 @@ var Turn: int = 0 @onready var boardContainer: FlowContainer = $Flow @onready var stateMachine: StateMachine = $StateMachine +var currentFen = "" var lightStyle = null var darkStyle = null var highlightStyle = null +var cpuElo = 1500 func _ready() -> void: + if OS.get_name() == "Windows": + stockfishPath = "res://Assets/ChessEngines/stockfish/stockfish.exe" + else: + stockfishPath = ProjectSettings.globalize_path("res://Assets/ChessEngines/Fairy-Stockfish/src/stockfish") add_to_group("ChessGame") + currentFen = FEN DisplayServer.window_set_size(Vector2i(windowXSize, windowYSize)) initializeGame() initializeTiles() stateMachine.transitionToNextState(Constants.WHITE_TURN) - + stockfishController = StockfishController.new(board) + add_child(stockfishController) + if stockfishController.connect_to_engine(stockfishPath): + stockfishController.limit_strength_to(cpuElo) + +func _exit_tree(): + stockfishController.disconnect_engine() func initializeTiles() -> void: tileManager = TileManager.new($Flow, self) @@ -83,6 +103,45 @@ func initializeCardPreview() -> void: +func getCurrentFen() -> String: + var fen = "" + + # For a standard chess board, we want to generate FEN from top (black side, rank 8) + # to bottom (white side, rank 1) + for y in range(boardYSize): + var emptySquares = 0 + for x in range(boardXSize): + # print("CHECKING ", str(x) + "-" + str(y)) + var container = boardContainer.get_node(str(x) + "-" + str(y)) as PieceContainer + var piece = container.get_piece() + if piece == null: + emptySquares += 1 + else: + if emptySquares > 0: + fen += str(emptySquares) + emptySquares = 0 + # Convert piece to FEN notation + var fenChar = getPieceFenChar(piece) + fen += fenChar + + # Add any remaining empty squares at the end of the rank + if emptySquares > 0: + fen += str(emptySquares) + + # Add rank separator (except for the last rank) + if y < boardYSize - 1: + fen += "/" + + # Add the rest of the FEN string components + fen += " %s %s %s %d %d" % [ + "w" if isWhiteToMove else "b", + castlingRights, + enPassantTarget, + halfMoveClock, + moveCount + ] + + return fen func initializeBoard() -> void: # Parse FEN to get board dimensions # rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 @@ -485,3 +544,99 @@ func cleanupPhase() -> void: func isNull(location: String) -> bool: return get_node_or_null("Flow/" + location) == null + + +func getPieceFenChar(piece: Pawn) -> String: + if piece == null: + return "" + var fenChar = "" + match piece.name: + "Pawn": fenChar = "p" + "Knight": fenChar = "n" + "Bishop": fenChar = "b" + "Rook": fenChar = "r" + "Queen": fenChar = "q" + "King": fenChar = "k" + + # In our system, Item_Color == 1 is white, 0 is black + return fenChar.to_upper() if piece.Item_Color == 0 else fenChar + +func updateStateFromMove(fromIdx: int, toIdx: int) -> void: + # Update game state based on the move + isWhiteToMove = !isWhiteToMove + if isWhiteToMove: + moveCount += 1 + + # Update castling rights if needed + updateCastlingRights(fromIdx, toIdx) + + # Update en passant target + updateEnPassantTarget(fromIdx, toIdx) + + # Update halfmove clock + updateHalfMoveClock(fromIdx, toIdx) + +func updateCastlingRights(fromIdx: int, toIdx: int) -> void: + var piece = board[fromIdx] + if piece == null: + return + + # Remove castling rights when king or rook moves + match piece.type: + "king": + if piece.isWhite: + castlingRights = castlingRights.replace("K", "").replace("Q", "") + else: + castlingRights = castlingRights.replace("k", "").replace("q", "") + "rook": + var startRank = 7 if piece.isWhite else 0 + if fromIdx == startRank * 8: # Queen-side rook + castlingRights = castlingRights.replace("Q" if piece.isWhite else "q", "") + elif fromIdx == startRank * 8 + 7: # King-side rook + castlingRights = castlingRights.replace("K" if piece.isWhite else "k", "") + + if castlingRights == "": + castlingRights = "-" + +func updateEnPassantTarget(fromIdx: int, toIdx: int) -> void: + var piece = board[fromIdx] + if piece == null or piece.type != "pawn": + enPassantTarget = "-" + return + + # Check for double pawn move + var fromRank = fromIdx / 8 + var toRank = toIdx / 8 + if abs(fromRank - toRank) == 2: + var file = fromIdx % 8 + var targetRank = (fromRank + toRank) / 2 + enPassantTarget = "%s%d" % [char(97 + file), 8 - targetRank] + else: + enPassantTarget = "-" + +func updateHalfMoveClock(fromIdx: int, toIdx: int) -> void: + var piece = board[fromIdx] + if piece == null: + return + + # Reset on pawn move or capture + if piece.type == "pawn" or board[toIdx] != null: + halfMoveClock = 0 + else: + halfMoveClock += 1 + + +func _on_ai_move_generated(move: String) -> void: + if Turn == 1: # Only process AI moves during black's turn + # The move will be automatically handled by the Movement state + # which is listening for the moveGenerated signal + pass + +func executeAiMove(fromLocation: String, toLocation: String) -> void: + selectedNode = fromLocation + executeMove(toLocation) + +func convertNotationToLocation(notation: String) -> String: + var file = notation[0].unicode_at(0) - 'a'.unicode_at(0) + var rank = 8 - int(notation[1]) + return str(file) + "-" + str(rank) diff --git a/Systems/PieceContainer.gd b/Systems/PieceContainer.gd index 0cf609f..1362204 100644 --- a/Systems/PieceContainer.gd +++ b/Systems/PieceContainer.gd @@ -78,4 +78,5 @@ func get_overlay(overlay_name: String) -> Node: return null func has_piece() -> bool: - return piece != null \ No newline at end of file + return piece != null + diff --git a/Systems/StateMachine/GameStates/ApplyTileEffects.gd b/Systems/StateMachine/GameStates/ApplyTileEffects.gd index 60284f5..b01f5db 100644 --- a/Systems/StateMachine/GameStates/ApplyTileEffects.gd +++ b/Systems/StateMachine/GameStates/ApplyTileEffects.gd @@ -3,4 +3,4 @@ extends "res://Systems/StateMachine/ChessGameState.gd" func enter(_previous: String, _data := {}) -> void: print("ENTERING STATE ", Constants.TILE_EFFECTS) game.applyTileEffects() - finished.emit(Constants.PRE_MOVE) \ No newline at end of file + finished.emit(Constants.EVALUATE_POSITION) \ No newline at end of file diff --git a/Systems/StateMachine/GameStates/BlackTurn.gd b/Systems/StateMachine/GameStates/BlackTurn.gd index 27e11c2..4bf21fe 100644 --- a/Systems/StateMachine/GameStates/BlackTurn.gd +++ b/Systems/StateMachine/GameStates/BlackTurn.gd @@ -1,6 +1,31 @@ extends "res://Systems/StateMachine/ChessGameState.gd" + +var moveTimer: Timer + +func _ready() -> void: + moveTimer = Timer.new() + moveTimer.one_shot = true # Timer only fires once + moveTimer.connect("timeout", _on_move_timer_timeout) + add_child(moveTimer) + func enter(_previous: String, _data := {}) -> void: print("ENTERING STATE ", Constants.BLACK_TURN) game.currentPlayer = game.BLACK - finished.emit(Constants.HAND_SETUP) \ No newline at end of file + + # Delay to avoid duplication during animation + if game.stockfishController: + moveTimer.start(2) + +func _on_move_timer_timeout() -> void: + # Generate AI move after delay + print("------------------GENERATING MOVE --------------------") + if game.stockfishController: + print("------------------STARTING GENERATING MOVE --------------------") + game.stockfishController.generateMove(1000) # 1 second think time + finished.emit(Constants.HAND_SETUP) + +func exit() -> void: + moveTimer.stop() + + diff --git a/Systems/StateMachine/GameStates/Movement.gd b/Systems/StateMachine/GameStates/Movement.gd index b6fce12..220905a 100644 --- a/Systems/StateMachine/GameStates/Movement.gd +++ b/Systems/StateMachine/GameStates/Movement.gd @@ -6,8 +6,19 @@ var multiMoving = "" func _ready() -> void: print("Movement state ready") +func _setup_movement_modifiers() -> void: + for piece_id in game.deckManager.attached_cards: + var card = game.deckManager.attached_cards[piece_id] + if card.effectType == Card.EffectType.MOVEMENT_MODIFIER: + var effects = card.modify_moves() + moves_remaining[piece_id] = effects.get("extra_moves", 0) + 1 + + func enter(_previous: String, _data := {}) -> void: - print("ENTERING STATE ", Constants.MOVEMENT) + print("ENTERING STATE ", Constants.MOVEMENT, " ", game.currentPlayer) + + + _setup_movement_modifiers() if !game.boardContainer.is_connected("tile_pressed", handleMovement): game.boardContainer.connect("tile_pressed", handleMovement) if game.selectedNode != "": @@ -31,16 +42,49 @@ func enter(_previous: String, _data := {}) -> void: moves_remaining[piece_id] += effects.get("extra_moves", 0) else: moves_remaining[piece_id] = effects.get("extra_moves", 0) + 1 + + if game.currentPlayer == game.BLACK and game.stockfishController: + var move = game.stockfishController.getGeneratedMove() + print("GENERATED MOVE ", move) + if move: + var move_str = move.move # e.g., "e2e4" + var source_square = move_str.substr(0, 2) # "e2" + var target_square = move_str.substr(2, 2) # "e4" + + # First select the piece + var source_location = convert_algebraic_to_location(source_square) + game.selectedNode = source_location + print("source_location ", source_location) + + # Then make the move + var target_location = convert_algebraic_to_location(target_square) + print("target_location ", target_location) + handleMovement(target_location, true) + return func exit() -> void: if game.boardContainer.is_connected("tile_pressed", handleMovement): game.boardContainer.disconnect("tile_pressed", handleMovement) -func handleMovement(location: String) -> void: + +func convert_algebraic_to_location(square: String) -> String: + var file = square[0] # letter (a-h) + var rank = int(square[1]) # number (1-8) + + # Convert file letter to number (a=0, b=1, etc) + var file_num = file.unicode_at(0) - 'a'.unicode_at(0) + + # Convert rank to 0-based index from bottom + var rank_num = rank - 1 + + # Return location in your game's format + return "%d-%d" % [file_num, rank_num] + +func handleMovement(location: String, generated: bool = false) -> void: # we need to prevent swapping of focus between peices after the double move process has started # maybe once u start nmoving a peice global stat var is set # and any moving peice needs ot match that - # print("HANDLING MOVEMENT ", location, " | ", multiMoving, " | ", game.selectedNode) + print("HANDLING MOVEMENT ", location, " | ", multiMoving, " | ", game.selectedNode) var node = game.get_node("Flow/" + location) as PieceContainer # Only try to get piece if we have a selected node @@ -89,17 +133,16 @@ func handleMovement(location: String) -> void: if piece_id in moves_remaining: moves_remaining.erase(piece_id) # finished.emit(Constants.POST_MOVE) - if game.selectedNode == location: if !is_multi_moving and multiMoving == "": print("CLEAR SELECTION*************") game.clearSelection() elif isCastlingMove(node, location): - handleCastling(node) + handleCastling(node, generated) finished.emit(Constants.POST_MOVE) # En Passant elif isEnPassantMove(node, location): - handleEnPassant(node) + handleEnPassant(node, generated) # Reselect piece elif isReselectMove(node): if !is_multi_moving and multiMoving == "": @@ -108,17 +151,17 @@ func handleMovement(location: String) -> void: game.getMovableAreas() # Capture piece elif isCaptureMove(node): - handleCapture(node) + handleCapture(node, generated) finished.emit(Constants.POST_MOVE) # Regular move # elif isRegularMove(node): # handleRegularMove(node) # finished.emit(Constants.POST_MOVE) else: - if game.isValidMove(location): + if game.isValidMove(location) || generated: # executeMove(location) - handleRegularMove(node, consumeMove) + handleRegularMove(node, consumeMove, generated) if consumeMove: multiMoving = "" game.clearSelection() @@ -167,86 +210,107 @@ func isCaptureMove(node: PieceContainer) -> bool: func isRegularMove(node: PieceContainer) -> bool: return game.selectedNode != "" && node.get_piece() != null -func handleCastling(node: PieceContainer) -> void: +func handleCastling(node: PieceContainer, generated: bool = false) -> void: print("handleCastling") + if generated: + castleMovement(node) + return for i in game.areas: if i == node.name: - var kingContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer - var rookContainer = node as PieceContainer - var kingTargetContainer = game.get_node("Flow/" + game.specialArea[1]) as PieceContainer - var rookTargetContainer = game.get_node("Flow/" + game.specialArea[0]) as PieceContainer + castleMovement(node) +func castleMovement(node: PieceContainer) -> void: + var kingContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer + var rookContainer = node as PieceContainer + var kingTargetContainer = game.get_node("Flow/" + game.specialArea[1]) as PieceContainer + var rookTargetContainer = game.get_node("Flow/" + game.specialArea[0]) as PieceContainer - var king = kingContainer.get_piece() - var rook = rookContainer.get_piece() + var king = kingContainer.get_piece() + var rook = rookContainer.get_piece() - # kingContainer.remove_piece(true) - # rookContainer.remove_piece(true) - # kingTargetContainer.set_piece(king) - # rookTargetContainer.set_piece(rook) + # kingContainer.remove_piece(true) + # rookContainer.remove_piece(true) + # kingTargetContainer.set_piece(king) + # rookTargetContainer.set_piece(rook) - kingTargetContainer.animate_movement(kingContainer, king); + kingTargetContainer.animate_movement(kingContainer, king); - rookTargetContainer.animate_movement(rookContainer, rook); + rookTargetContainer.animate_movement(rookContainer, rook); - game.currentlyMovingPiece = king - game.resolveMoveEffects() + game.currentlyMovingPiece = king + game.resolveMoveEffects() -func handleEnPassant(node: PieceContainer) -> void: +func handleEnPassant(node: PieceContainer, generated: bool = false) -> void: print("handleEnPassant") - for i in game.specialArea: + if generated: + handleEnPassantMovement(node) + return + for i in game.areas: if i == node.name: - var targetContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer - var pawn = (game.get_node("Flow/" + game.selectedNode) as PieceContainer).get_piece() - # node.remove_piece() - # targetContainer.set_piece(pawn) - game.currentlyMovingPiece = pawn + handleEnPassantMovement(node) - targetContainer.animate_movement(node, pawn); - game.resolveMoveEffects() +func handleEnPassantMovement(node: PieceContainer) -> void: + var targetContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer + var pawn = (game.get_node("Flow/" + game.selectedNode) as PieceContainer).get_piece() + # node.remove_piece() + # targetContainer.set_piece(pawn) + game.currentlyMovingPiece = pawn -func handleCapture(node: PieceContainer) -> void: + + targetContainer.animate_movement(node, pawn); + game.resolveMoveEffects() + +func handleCapture(node: PieceContainer, generated: bool = false) -> void: print("handleCapture") + if generated: + handleCaptureMovement(node) + return for i in game.areas: if i == node.name: - - - var source_container = game.get_node("Flow/" + game.selectedNode) as PieceContainer - - - var moving_piece = source_container.get_piece() - var captured_piece = node.get_piece() - - if moving_piece && captured_piece: - await game.animatePieceCapture(captured_piece) - game.updatePointsAndCapture(captured_piece, false) - node.animate_movement(source_container, moving_piece); - var tile = game.tileManager.get_tile(node.name) - if tile: - tile.apply_effect(moving_piece) + handleCaptureMovement(node) - game.currentlyMovingPiece = moving_piece - game.resolveMoveEffects() +func handleCaptureMovement(node: PieceContainer) -> void: + var source_container = game.get_node("Flow/" + game.selectedNode) as PieceContainer + + + var moving_piece = source_container.get_piece() + var captured_piece = node.get_piece() + + if moving_piece && captured_piece: + await game.animatePieceCapture(captured_piece) + game.updatePointsAndCapture(captured_piece, false) + node.animate_movement(source_container, moving_piece); + var tile = game.tileManager.get_tile(node.name) + if tile: + tile.apply_effect(moving_piece) -func handleRegularMove(node: PieceContainer, consume: bool) -> void: + + game.currentlyMovingPiece = moving_piece + game.resolveMoveEffects() + + +func handleRegularMove(node: PieceContainer, consume: bool, generated: bool = false) -> void: print("handleRegularMove", node, game.selectedNode) + if generated: + moveAndConsume(node, consume) + return for i in game.areas: if i == node.name: - print(i) - var sourceContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer - var piece = sourceContainer.get_piece() - print("Removing Piece 1") - node.animate_movement(sourceContainer, piece); - game.currentlyMovingPiece = piece - if consume: - game.resolveMoveEffects() - else: - game.togglePieceChessEffect() - + moveAndConsume(node, consume) +func moveAndConsume(node: PieceContainer, consume: bool) -> void: + var sourceContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer + var piece = sourceContainer.get_piece() + print("Removing Piece 1") + node.animate_movement(sourceContainer, piece); + game.currentlyMovingPiece = piece + if consume: + game.resolveMoveEffects() + else: + game.togglePieceChessEffect() func executeMove(targetLocation: String) -> void: diff --git a/Systems/StateMachine/GameStates/PostMovePhase.gd b/Systems/StateMachine/GameStates/PostMovePhase.gd index 82c2411..1999f4c 100644 --- a/Systems/StateMachine/GameStates/PostMovePhase.gd +++ b/Systems/StateMachine/GameStates/PostMovePhase.gd @@ -8,4 +8,4 @@ func enter(_previous: String, _data := {}) -> void: game.updateEffectDurations() # if (game.isPlayerTurn()): # game.deckManager.updateCardDurations() - finished.emit(Constants.EVALUATE_POSITION) + finished.emit(Constants.TILE_EFFECTS) diff --git a/Systems/StateMachine/GameStates/ResolvePersistentEffects.gd b/Systems/StateMachine/GameStates/ResolvePersistentEffects.gd index 8eb2be5..3ccf976 100644 --- a/Systems/StateMachine/GameStates/ResolvePersistentEffects.gd +++ b/Systems/StateMachine/GameStates/ResolvePersistentEffects.gd @@ -3,4 +3,4 @@ extends "res://Systems/StateMachine/ChessGameState.gd" func enter(_previous: String, _data := {}) -> void: print("ENTERING STATE ", Constants.PERSISTENT_EFFECTS) - finished.emit(Constants.TILE_EFFECTS) + finished.emit(Constants.PRE_MOVE) diff --git a/board.tscn b/board.tscn index ec5da14..30ec2ba 100644 --- a/board.tscn +++ b/board.tscn @@ -27,13 +27,6 @@ offset_bottom = -5.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_fkb2r") -boardXSize = null -boardYSize = null -tileXSize = null -tileYSize = null -windowXSize = null -windowYSize = null -FEN = null [node name="Flow" type="FlowContainer" parent="."] layout_mode = 1 diff --git a/project.godot b/project.godot index 1f76a23..6f12b78 100644 --- a/project.godot +++ b/project.godot @@ -33,4 +33,4 @@ import/blender/enabled=false [rendering] -renderer/rendering_method="gl_compatibility" +renderer/rendering_method="mobile"