rename gauntlet→candy_survival + rewrite Candy Survival per boss design
- Rename enum GAUNTLET→CANDY_SURVIVAL, all gauntlet_*→candy_survival_* - Rename files: gauntlet_manager→candy_survival_manager, candy_cannon→candy_survival_npc, gauntlet.tscn→candy_survival.tscn - Rewrite candy_survival_manager.gd: blueprints, candy stack, Mekton delivery, Sugar Rush, knock/ghost charges, sticky-as-wall - Update player_movement_manager.gd: smack→knock system, ghost integration - All Candy Survival issues (#54-57, #65-70) retitled per boss design - Shared managers (goals_cycle, goal, player_race, playerboard, turn) untouched
This commit is contained in:
@@ -8,38 +8,38 @@ class_name BotStrategicPlanner
|
||||
|
||||
var actor: Node3D
|
||||
var enhanced_gridmap: Node
|
||||
# Optional explicit gauntlet_manager binding (set by tests to avoid scene-tree
|
||||
# traversal collisions; production code uses _get_gauntlet_manager() instead).
|
||||
var gauntlet_manager_override: Node = null
|
||||
# Optional explicit candy_survival_manager binding (set by tests to avoid scene-tree
|
||||
# traversal collisions; production code uses _get_candy_survival_manager() instead).
|
||||
var candy_survival_manager_override: Node = null
|
||||
|
||||
# Tile type constants
|
||||
const GOAL_TILES = [7, 8, 9, 10] # Heart, Diamond, Star, Coin
|
||||
const HOLO_TILES = [11, 12, 13, 14] # Power-up holo tiles
|
||||
|
||||
# Gauntlet overlay layer (v2 ground-growth model — sticky/telegraph on layer 2).
|
||||
# Candy Survival overlay layer (v2 ground-growth model — sticky/telegraph on layer 2).
|
||||
# Bots must avoid these cells or use Ghost mode to cross.
|
||||
const GAUNTLET_OVERLAY_LAYER: int = 2
|
||||
const CANDY_SURVIVAL_OVERLAY_LAYER: int = 2
|
||||
const TILE_STICKY: int = 17
|
||||
const TILE_TELEGRAPH: int = 18
|
||||
|
||||
# =============================================================================
|
||||
# Gauntlet mode helpers (#075 — Bot AI: Sticky Avoidance & Pathfinding)
|
||||
# Candy Survival mode helpers (#075 — Bot AI: Sticky Avoidance & Pathfinding)
|
||||
# =============================================================================
|
||||
|
||||
func is_gauntlet_mode() -> bool:
|
||||
return LobbyManager and LobbyManager.is_game_mode(GameMode.Mode.GAUNTLET)
|
||||
func is_candy_survival_mode() -> bool:
|
||||
return LobbyManager and LobbyManager.is_game_mode(GameMode.Mode.CANDY_SURVIVAL)
|
||||
|
||||
func _get_gauntlet_manager() -> Node:
|
||||
"""Resolve the active GauntletManager.
|
||||
func _get_candy_survival_manager() -> Node:
|
||||
"""Resolve the active CandySurvivalManager.
|
||||
|
||||
Order of resolution:
|
||||
1. Explicit `gauntlet_manager_override` (used by tests).
|
||||
2. Walk actor's ancestors for any node containing a GauntletManager child
|
||||
1. Explicit `candy_survival_manager_override` (used by tests).
|
||||
2. Walk actor's ancestors for any node containing a CandySurvivalManager child
|
||||
(production path — robust to non-standard scene trees).
|
||||
3. Fallback: scan /root children for a GauntletManager.
|
||||
3. Fallback: scan /root children for a CandySurvivalManager.
|
||||
"""
|
||||
if gauntlet_manager_override and is_instance_valid(gauntlet_manager_override):
|
||||
return gauntlet_manager_override
|
||||
if candy_survival_manager_override and is_instance_valid(candy_survival_manager_override):
|
||||
return candy_survival_manager_override
|
||||
var root: Node = null
|
||||
if actor and actor.is_inside_tree():
|
||||
root = actor.get_tree().get_root()
|
||||
@@ -47,7 +47,7 @@ func _get_gauntlet_manager() -> Node:
|
||||
# nested under Main → Arena → Player).
|
||||
var n: Node = actor.get_parent()
|
||||
while n:
|
||||
var gm = n.get_node_or_null("GauntletManager")
|
||||
var gm = n.get_node_or_null("CandySurvivalManager")
|
||||
if gm:
|
||||
return gm
|
||||
n = n.get_parent()
|
||||
@@ -56,7 +56,7 @@ func _get_gauntlet_manager() -> Node:
|
||||
# Last-resort scan of root children (helps in unusual scene trees).
|
||||
for child in root.get_children():
|
||||
if child.name.begins_with("Main") or child.name.begins_with("BotTestMain"):
|
||||
var gm2 = child.get_node_or_null("GauntletManager")
|
||||
var gm2 = child.get_node_or_null("CandySurvivalManager")
|
||||
if gm2:
|
||||
return gm2
|
||||
return null
|
||||
@@ -76,17 +76,17 @@ func _is_overlay_unsafe(pos: Vector2i) -> bool:
|
||||
"""True if the cell carries a sticky or telegraphed overlay on layer 2."""
|
||||
if not enhanced_gridmap:
|
||||
return false
|
||||
var item = enhanced_gridmap.get_cell_item(Vector3i(pos.x, GAUNTLET_OVERLAY_LAYER, pos.y))
|
||||
var item = enhanced_gridmap.get_cell_item(Vector3i(pos.x, CANDY_SURVIVAL_OVERLAY_LAYER, pos.y))
|
||||
return item == TILE_STICKY or item == TILE_TELEGRAPH
|
||||
|
||||
func _is_cell_unsafe_in_gauntlet(pos: Vector2i) -> bool:
|
||||
"""Cell is unsafe in Gauntlet if it's sticky/telegraphed — unless the bot's
|
||||
func _is_cell_unsafe_in_candy_survival(pos: Vector2i) -> bool:
|
||||
"""Cell is unsafe in Candy Survival if it's sticky/telegraphed — unless the bot's
|
||||
Ghost mode is active (grants sticky bypass)."""
|
||||
if not is_gauntlet_mode():
|
||||
if not is_candy_survival_mode():
|
||||
return false
|
||||
if _is_bot_ghost_active():
|
||||
return false
|
||||
var gm = _get_gauntlet_manager()
|
||||
var gm = _get_candy_survival_manager()
|
||||
if gm and gm.has_method("is_sticky_cell") and gm.is_sticky_cell(pos):
|
||||
return true
|
||||
return _is_overlay_unsafe(pos)
|
||||
@@ -101,7 +101,7 @@ func _count_unsafe_neighbors(pos: Vector2i) -> int:
|
||||
|
||||
func should_activate_ghost_now() -> bool:
|
||||
"""True if the bot is boxed in / about to be sealed and should use Ghost powerup."""
|
||||
if not is_gauntlet_mode():
|
||||
if not is_candy_survival_mode():
|
||||
return false
|
||||
if not _bot_has_ghost_powerup():
|
||||
return false
|
||||
@@ -613,12 +613,12 @@ func _is_valid_move_target(pos: Vector2i, ignore_players: bool = false) -> bool:
|
||||
if not ignore_players and actor.is_position_occupied(pos):
|
||||
return false
|
||||
|
||||
# Gauntlet mode (#075): reject cells that are sticky or telegraphed —
|
||||
# Candy Survival mode (#075): reject cells that are sticky or telegraphed —
|
||||
# stepping onto them either traps the bot or strands it within 1s.
|
||||
# Safety applies even when ignore_players is true (a sticky cell is unsafe
|
||||
# regardless of whether another player is on it). Ghost-active bots are
|
||||
# exempt via the helper.
|
||||
if _is_cell_unsafe_in_gauntlet(pos):
|
||||
if _is_cell_unsafe_in_candy_survival(pos):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user