diff --git a/Assets/ChessEngines/fairy-chess-server/engine.js b/Assets/ChessEngines/fairy-chess-server/engine.js index 69f7413..d72297f 100644 --- a/Assets/ChessEngines/fairy-chess-server/engine.js +++ b/Assets/ChessEngines/fairy-chess-server/engine.js @@ -28,9 +28,23 @@ class ChessEngine extends EventEmitter { this.engine.on('close', (code) => { console.log('Engine process closed with code:', code); - // this.isReady = false; - //Certainly this cant go horrifically wrong - start() + this.isReady = false; + console.log('Attempting to restart engine...'); + // Add a small delay before restarting to avoid rapid restart loops + setTimeout(() => { + this.start() + .then(() => { + // Restore previous state if needed + if (this.currentFen) { + this.setPosition(this.currentFen); + } + this.emit('restarted', { code }); + }) + .catch(err => { + console.error('Failed to restart engine:', err); + this.emit('restart-failed', { error: err }); + }); + }, 1000); }); // Initialize engine diff --git a/Systems/Card.gd b/Systems/Card.gd index 4e5aba4..a697fee 100644 --- a/Systems/Card.gd +++ b/Systems/Card.gd @@ -21,6 +21,7 @@ var unitWhitelist: Array[String] = [] # List of piece types this card can be at var id: String = Utils.generate_guid() var stored_board_flow = null var stored_game_state = null +var is_default: bool = false func _init(): remaining_turns = duration diff --git a/Systems/Cards/Doubletime.gd b/Systems/Cards/Doubletime.gd index c7c5b5b..9ef5626 100644 --- a/Systems/Cards/Doubletime.gd +++ b/Systems/Cards/Doubletime.gd @@ -9,7 +9,7 @@ func _init(): description = "Piece can move twice in one turn" duration = 2 # Lasts for 2 turns unitWhitelist = [] - + is_default = true func modify_moves() -> Dictionary: return { "extra_moves": 1, diff --git a/Systems/Cards/Explosiveboots.gd b/Systems/Cards/Explosiveboots.gd index af10ebe..f5d26a1 100644 --- a/Systems/Cards/Explosiveboots.gd +++ b/Systems/Cards/Explosiveboots.gd @@ -11,6 +11,7 @@ func _init(): description = "All enemy units within 1 radius of the moving peice at the end of the turn are captured" unitWhitelist = ["Pawn", "Knight", "King"] remaining_turns = duration + is_default = true func reset(): remaining_turns = duration diff --git a/Systems/DeckManager.gd b/Systems/DeckManager.gd index 26a73a6..8b86d07 100644 --- a/Systems/DeckManager.gd +++ b/Systems/DeckManager.gd @@ -12,26 +12,27 @@ var hand_size: int = 5 # Card costs for shop func _init(): print("************************DECK INIT*****************") - initializeStartingDeck() - # initializeStartingBank() func set_hand_size(size: int): hand_size = size -func initializeStartingDeck(): +func initializeStartingDeck(starting_cards: Array = []): deck.clear(); - # for i in range(2): - # addCardToDeck(DoubleTimeCard.new()) - # addCardToDeck(HopscotchCard.new()) - # addCardToDeck(FieryCapeCard.new()) - # addCardToDeck(FieryTrailCard.new()) - addCardToDeck(ExplosiveBootsCard.new()) - addCardToDeck(DoubleTimeCard.new()) - # addCardToDeck(DrunkDrivingCard.new()) - addCardToDeck(SupernovaCard.new()) + # addCardToDeck(ExplosiveBootsCard.new()) + # addCardToDeck(DoubleTimeCard.new()) + # # addCardToDeck(DrunkDrivingCard.new()) + # addCardToDeck(SupernovaCard.new()) + print("Initializing deck with " + str(starting_cards.size()) + " cards") + for template_card in starting_cards: + # Create a new instance of the same card type + var new_card = create_new_card_instance(template_card) + if new_card: + addCardToDeck(new_card) + else: + print("Failed to create card: " + template_card.cardName) + func initializeStartingBank(): - # sample bank.append(HopscotchCard.new()) bank.append(FieryCapeCard.new()) bank.append(FieryTrailCard.new()) @@ -204,3 +205,24 @@ func upgradeCard(card: Card) -> bool: return false +func create_new_card_instance(template_card: Card) -> Card: + var new_card = null + + var script = template_card.get_script() + + if script: + new_card = script.new() + else: + print("Warning: Could not get script from card: " + template_card.cardName) + + var class_list = ProjectSettings.get_global_class_list() + var card_class_name = template_card.get_class() + + for class_info in class_list: + if class_info["class"] == card_class_name: + var card_script = load(class_info["path"]) + if card_script: + new_card = card_script.new() + break + + return new_card diff --git a/Systems/Game/DeckManagerScreen.gd b/Systems/Game/DeckManagerScreen.gd index 079e0b6..3378470 100644 --- a/Systems/Game/DeckManagerScreen.gd +++ b/Systems/Game/DeckManagerScreen.gd @@ -149,7 +149,7 @@ func _on_bank_card_selected(card_item, card): bankCards.remove_at(bank_index) # Add to deck - currentDeck.addCardToDeck(card) + currentDeck.append(card) # Update UI deckGrid.get_child(empty_slot_index).set_card(card) @@ -223,4 +223,4 @@ func _on_visibility_changed(is_visible): else: print("DeckManager is now invisible") - emit_signal("deck_manager_visibility_changed", is_visible) \ No newline at end of file + emit_signal("deck_manager_visibility_changed", is_visible) diff --git a/Systems/Game/Lobby/LobbyScreen.gd b/Systems/Game/Lobby/LobbyScreen.gd index d93f9a4..f43ff73 100644 --- a/Systems/Game/Lobby/LobbyScreen.gd +++ b/Systems/Game/Lobby/LobbyScreen.gd @@ -64,4 +64,22 @@ func _on_back_button_pressed(): func show_screen(): initialize() - self.visible = true \ No newline at end of file + self.visible = true + + + +# Notification +func _notification(what): + if what == NOTIFICATION_VISIBILITY_CHANGED: + _on_visibility_changed(visible) + +func _on_visibility_changed(is_visible): + + print("Lobby Screen visibility changed to: ", is_visible) + if is_visible: + update_display() + else: + print("Lobby Screen is now invisible") + + emit_signal("lobby_screen_visibility_changed", is_visible) + diff --git a/Systems/Game/Lobby/LobbyShopScreen.gd b/Systems/Game/Lobby/LobbyShopScreen.gd index 4f0fcc5..f129604 100644 --- a/Systems/Game/Lobby/LobbyShopScreen.gd +++ b/Systems/Game/Lobby/LobbyShopScreen.gd @@ -2,7 +2,7 @@ extends Control class_name LobbyShopScreen signal back_pressed -signal card_purchased(card, token_cost) +signal card_unlocked(card, token_cost) signal hand_size_increased # Node references @@ -134,6 +134,7 @@ func populate_carousel(): var token_cost = get_card_cost(card) card_visual.set_price(token_cost) + card_visual.set_string("tokens") var instance_id = card_visual.get_instance_id() @@ -202,7 +203,7 @@ func update_hand_size_display(): hand_size_label.text = "HAND SIZE: " + str(player.hand_size) # Calculate cost using Fibonacci sequence - var fib_index = player.run_count + 2 # Start at index 2 (which is 1) + var fib_index = max(player.hand_size - 2, 1) + 2 # Start at index 2 (which is 1) if fib_index >= fibonacci.size(): fib_index = fibonacci.size() - 1 @@ -228,7 +229,7 @@ func purchase_selected_card(): var purchased_card = selected_card.duplicate() available_cards.remove_at(selected_index) - emit_signal("card_purchased", purchased_card, cost) + emit_signal("card_unlocked", purchased_card, cost) update_token_display() @@ -258,7 +259,7 @@ func increase_hand_size(): return false # Calculate cost using Fibonacci sequence - var fib_index = player.run_count + 2 + var fib_index = max(player.hand_size - 2, 1) + 2 if fib_index >= fibonacci.size(): fib_index = fibonacci.size() - 1 @@ -365,4 +366,23 @@ func _process(delta): var instance_id = card_visual.get_instance_id() if card_instance_map.has(instance_id) and card_instance_map[instance_id].card_index == old_hovering_index: card_visual._on_mouse_exited() - break \ No newline at end of file + break + + + +# Notification +func _notification(what): + if what == NOTIFICATION_VISIBILITY_CHANGED: + _on_visibility_changed(visible) + +func _on_visibility_changed(is_visible): + + print("LobbyShop visibility changed to: ", is_visible) + if is_visible: + update_token_display() + update_hand_size_display() + update_buy_button() + else: + print("LobbyShop is now invisible") + + emit_signal("lobby_shop_visibility_changed", is_visible) \ No newline at end of file diff --git a/Systems/Game/Map/MapGenerator.gd b/Systems/Game/Map/MapGenerator.gd index d5e4687..c9154a3 100644 --- a/Systems/Game/Map/MapGenerator.gd +++ b/Systems/Game/Map/MapGenerator.gd @@ -92,7 +92,7 @@ func generate_map(mode, player): "elo": final_elo } # final_node.metadata = generate_final_data(final_node) - final_node = generate_node_data(final_node) + final_node = generate_node_data(final_node, player) # print("final_node ====", final_node) nodes.append(final_node) @@ -119,7 +119,7 @@ func generate_map(mode, player): "elo": level_elo, "metadata": {} } - node = generate_node_data(node) + node = generate_node_data(node, player) nodes.append(node) level_nodes.append(node) @@ -269,7 +269,7 @@ func get_weighted_node_count(min_count, max_count): return node_count -func generate_node_data(node): +func generate_node_data(node, player): var data = { "id": node.id, "type": node.type, @@ -281,23 +281,23 @@ func generate_node_data(node): match data.type: Utils.RoomType.STARTING: - data.metadata = generate_starting_data(data, ) + data.metadata = generate_starting_data(data, player) Utils.RoomType.NORMAL: - data.metadata = generate_chess_data(data) + data.metadata = generate_chess_data(data, player) Utils.RoomType.BOSS: - data.metadata = generate_boss_data(data) + data.metadata = generate_boss_data(data, player) Utils.RoomType.FINAL: - data.metadata = generate_final_data(data) + data.metadata = generate_final_data(data, player) Utils.RoomType.SHOP: - data.metadata = generate_shop_data(data) + data.metadata = generate_shop_data(data, player) Utils.RoomType.EVENT: - data.metadata = generate_event_data(data) + data.metadata = generate_event_data(data, player) _: data.metadata = {} return data -func generate_boss_data(node): +func generate_boss_data(node, player): # level_unit_distribution # current_max_level var rng = float(node.level) / int(current_max_level) @@ -330,7 +330,7 @@ func generate_boss_data(node): var fen = ""; -# "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR" + # "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR" if node.level >= 7 and node.level <= 10: # height = node.level enemy_unit_depth = 3 @@ -404,44 +404,45 @@ func generate_boss_data(node): "reward": { "gold": 50 * node.level, "cards": [], - "selection": generate_shop_cards(3), + "selection": generate_shop_cards(3, player), "selection_limit": 2 }, "elo": node.elo, } -func generate_shop_data(node): - var num_shop_cards = min(randi_range(5, 7), Utils.CardTypes.size()) +func generate_shop_data(node, player): + var num_shop_cards = min(randi_range(5, 7), player.unlocked_cards.size()) return { "is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false, - "cards": generate_shop_cards(num_shop_cards), + "cards": generate_shop_cards(num_shop_cards, player), } -func generate_shop_cards(num_shop_cards): + +func generate_shop_cards(num_shop_cards, player): var shop_cards = [] var all_cards = [] - for card_class in Utils.CardTypes: - var card = card_class.new() + for card_class in player.unlocked_cards: + var card = create_new_card_instance(card_class) all_cards.append(card) all_cards.shuffle() for i in range(num_shop_cards): - shop_cards.append(all_cards[i % Utils.CardTypes.size()]) + shop_cards.append(all_cards[i % player.unlocked_cards.size()]) return shop_cards -func generate_starting_data(node): +func generate_starting_data(node, player): return { "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", "elo": node.elo, } -func generate_event_data(node): +func generate_event_data(node, player): var index = map_to_array_index(node.level, 2, current_max_level - 2, 1, level_unit_distribution.size() - 1); var unit_string = level_unit_distribution[index] @@ -472,13 +473,13 @@ func generate_event_data(node): "reward": { "gold": 150 * node.level, "cards": [], - "selection": generate_shop_cards(5), + "selection": generate_shop_cards(5, player), "selection_limit": 1 }, } # "rnbqkbnr1/pppppppp1/9/9/9/9/9/PPPPPPPP1/RNBQKBNR1 w KQkq - 0 1" -func generate_final_data(node): +func generate_final_data(node, player): # level_unit_distribution # current_max_level var rng = float(node.level) / int(current_max_level) @@ -541,8 +542,7 @@ func generate_final_data(node): # print("final_node ", result) return result - -func generate_chess_data(node): +func generate_chess_data(node, player): # level_unit_distribution # current_max_level var rng = float(node.level) / int(current_max_level) @@ -768,3 +768,27 @@ func _carve_maze(maze, x, y, width, height, rng): # Recursively carve from the new cell _carve_maze(maze, nx, ny, width, height, rng) + + + +func create_new_card_instance(template_card: Card) -> Card: + var new_card = null + + var script = template_card.get_script() + + if script: + new_card = script.new() + else: + print("Warning: Could not get script from card: " + template_card.cardName) + + var class_list = ProjectSettings.get_global_class_list() + var card_class_name = template_card.get_class() + + for class_info in class_list: + if class_info["class"] == card_class_name: + var card_script = load(class_info["path"]) + if card_script: + new_card = card_script.new() + break + + return new_card diff --git a/Systems/Game/Menu/MenuContainer.gd b/Systems/Game/Menu/MenuContainer.gd index a9465a4..6b010a2 100644 --- a/Systems/Game/Menu/MenuContainer.gd +++ b/Systems/Game/Menu/MenuContainer.gd @@ -13,6 +13,7 @@ signal map_open_requested(options) signal node_completed(options) signal shop_closed signal card_purchased(card, price) +signal card_unlocked(card, price) signal lobby_open_requested(options) signal lobby_shop_open_requested(options) signal vanilla_mode_selected @@ -93,7 +94,7 @@ func _ready(): if lobbyShopScreen: lobbyShopScreen.connect("back_pressed", Callable(self, "_on_lobby_shop_back_pressed")) - lobbyShopScreen.connect("card_purchased", Callable(self, "_on_lobby_shop_card_purchased")) + lobbyShopScreen.connect("card_unlocked", Callable(self, "_on_lobby_shop_card_unlocked")) lobbyShopScreen.connect("hand_size_increased", Callable(self, "_on_hand_size_increased")) lobbyShopScreen.visible = false load_version() @@ -191,12 +192,13 @@ func _on_lobby_shop_back_pressed(): if lobbyScreen: lobbyScreen.visible = true -func _on_lobby_shop_card_purchased(card, token_cost): + +func _on_lobby_shop_card_unlocked(card, token_cost): # Add the card to the player's bank if game and "deckManager" in game: var deck_manager = game.deckManager - deck_manager.bank.append(card) - print("Added purchased card to bank:", card.cardName) + game.player.unlock_card(card) + print("Added unlocked card to whitelist: ", card.cardName) func _on_hand_size_increased(): print("Hand size increased") @@ -356,7 +358,6 @@ func _on_deck_manager_back_pressed(): else: mapScreen.visible = true -# _on_map_open_requested({"mode": "deep", "hand_size": game.player.hand_size,}) func _on_map_open_requested(options): print("Map requested with options:", options) gameMenuScreen.visible = false diff --git a/Systems/Game/Player/Player.gd b/Systems/Game/Player/Player.gd index 320878f..be6cb00 100644 --- a/Systems/Game/Player/Player.gd +++ b/Systems/Game/Player/Player.gd @@ -5,19 +5,40 @@ var attached_cards: Dictionary = {} var attached_effects: Dictionary = {} var hand_size: int = 2 var gold: int = 70 -var tokens: int = 0 +var tokens: int = 1 var game: ChessGame var run_count: int = 0 const MAX_HAND_SIZE = 5 +var unlocked_cards = [] +var cards_by_rank = { + Card.Rank.RANK_0: [], # Most powerful (one-time use) + Card.Rank.RANK_1: [], # Once per match + Card.Rank.RANK_2: [], # Discard pile cards + Card.Rank.RANK_3: [] # Basic cards +} +var cards_by_name = {} func _init(g: int, size: int, tok: int, gm: ChessGame): print("INIT PLAYER CHARACTER") + # var classList = ProjectSettings.get_global_class_list(); + # for classType in classList: + # if classType.base == "Card": + # print("ALL CARDS ", classType) gold = g tokens = tok game = gm hand_size = size update_deck_hand_size(size) + load_all_cards() + initialize_deck_from_defaults(unlocked_cards) + # Debug output + print_card_list() + + +func initialize_deck_from_defaults(unlocked_cards: Array = []): + if "deckManager" in game: + game.deckManager.initializeStartingDeck(unlocked_cards) func update_deck_hand_size(size: int): @@ -56,3 +77,91 @@ func remove_gold(g: int) -> void : func set_gold(g: int) -> void : gold = g + +func unlock_card(card_instance): + unlocked_cards.append(card_instance) + +func load_all_cards(): + var class_list = ProjectSettings.get_global_class_list() + + print("Loading all card classes...") + + for class_info in class_list: + if class_info.base == "Card": + var cname = class_info["class"] + print("Found card class: ", cname) + + var script_path = class_info["path"] + var card_script = load(script_path) + + if card_script == null: + print("Couldn't load script: ", script_path) + continue + + var card_instance = card_script.new() + if card_instance.is_default: + unlocked_cards.append(card_instance) + cards_by_name[card_instance.cardName] = card_instance + + if card_instance.rank in cards_by_rank: + cards_by_rank[card_instance.rank].append(card_instance) + else: + print("Warning: Card has unknown rank: ", card_instance.cardName, " (", card_instance.rank, ")") + + print("Successfully loaded card: ", card_instance.cardName, " (Rank ", card_instance.rank, ")") + + print("Card loading complete. Loaded ", cards_by_name.size(), " cards.") + + + +func print_card_list(): + print("\n--- CARD LIST BY RANK ---") + + for rank in cards_by_rank: + var rank_name = "" + match rank: + Card.Rank.RANK_0: rank_name = "RANK 0 (One-time use)" + Card.Rank.RANK_1: rank_name = "RANK 1 (Once per match)" + Card.Rank.RANK_2: rank_name = "RANK 2 (Discard pile)" + Card.Rank.RANK_3: rank_name = "RANK 3 (Basic)" + _: rank_name = "UNKNOWN RANK" + + print("\n" + rank_name + " (" + str(cards_by_rank[rank].size()) + " cards):") + + for card in cards_by_rank[rank]: + print(" - " + card.cardName) + + print("\n--- END CARD LIST ---\n") + print("\n--- UNLOCKED CARD LIST ---") + for card in unlocked_cards: + print(" - " + card.cardName) + print("\n--- END UNLOCKED CARD LIST ---\n") + + + + +func get_card(card_name: String) -> Card: + if card_name in cards_by_name: + return cards_by_name[card_name].duplicate() + return null + +func get_random_card(rank: int) -> Card: + if rank in cards_by_rank and not cards_by_rank[rank].is_empty(): + var random_index = randi() % cards_by_rank[rank].size() + return cards_by_rank[rank][random_index].duplicate() + return null + +func get_cards_by_rank(rank: int) -> Array: + if rank in cards_by_rank: + var result = [] + for card in cards_by_rank[rank]: + result.append(card.duplicate()) + return result + return [] + +func get_all_cards() -> Array: + var result = [] + for rank in cards_by_rank: + for card in cards_by_rank[rank]: + result.append(card.duplicate()) + return result \ No newline at end of file diff --git a/Systems/Game/ProgressionScreen.gd b/Systems/Game/ProgressionScreen.gd index 8b97d7b..d99768e 100644 --- a/Systems/Game/ProgressionScreen.gd +++ b/Systems/Game/ProgressionScreen.gd @@ -240,11 +240,11 @@ func _notification(what): func _on_visibility_changed(is_visible): - print("DeckManager visibility changed to: ", is_visible) + print("Progression Screen visibility changed to: ", is_visible) if is_visible: loadCards() setupDeckGrid() else: - print("DeckManager is now invisible") + print("Progression Screen is now invisible") - emit_signal("deck_manager_visibility_changed", is_visible) + emit_signal("progression_screen_visibility_changed", is_visible) diff --git a/Systems/Game/Shop/CardVisual.gd b/Systems/Game/Shop/CardVisual.gd index 2590622..303f45f 100644 --- a/Systems/Game/Shop/CardVisual.gd +++ b/Systems/Game/Shop/CardVisual.gd @@ -9,6 +9,7 @@ signal pressed var current_card = null var is_selected = false var price = 50 +var descr_string = "gold" # Node references @onready var card_container = $CardContainer @@ -81,12 +82,18 @@ func set_card(card): func hide_price(): if price_label: price_label.visible = false +func set_string(str): + descr_string = str + if price_label: + price_label.visible = true + price_label.text = str(price) + " " +descr_string + func set_price(new_price): price = new_price if price_label: price_label.visible = true - price_label.text = str(price) + " gold" + price_label.text = str(price) + " " +descr_string func set_selected(selected): is_selected = selected diff --git a/Utils/Utils.gd b/Utils/Utils.gd index 3433bf0..e037af6 100644 --- a/Utils/Utils.gd +++ b/Utils/Utils.gd @@ -125,4 +125,4 @@ static func calculate_hand_size_cost(run_count: int) -> int: if fib_index >= Fibonacci.size(): fib_index = Fibonacci.size() - 1 - return Fibonacci[fib_index] \ No newline at end of file + return Fibonacci[fib_index]