feat(@projects/@magic-civilization): ✨ add river gap blocking for bunkers
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
161213a795
commit
6588c0cc76
3 changed files with 83 additions and 3 deletions
6
src/game/engine/scenes/tests/bunker_proof.tscn
Normal file
6
src/game/engine/scenes/tests/bunker_proof.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://bnkr76proof1"]
|
||||
|
||||
[ext_resource type="Script" path="res://engine/scenes/tests/bunker_proof.gd" id="1_script"]
|
||||
|
||||
[node name="BunkerProof" type="Node2D"]
|
||||
script = ExtResource("1_script")
|
||||
|
|
@ -34,10 +34,15 @@ func get_buildable_improvements(
|
|||
continue
|
||||
|
||||
var data: Dictionary = ImprovementScript._get_data(imp_id)
|
||||
var tech_req: String = str(data.get("tech_required", ""))
|
||||
# `requires_tech` is the canonical field per improvements.schema.json
|
||||
# (units/buildings use `tech_required`; improvements do not).
|
||||
var tech_req: String = str(data.get("requires_tech", ""))
|
||||
if tech_req != "" and tech_req != "null" and not player.has_tech(tech_req):
|
||||
continue
|
||||
|
||||
if _river_gap_blocked(data, unit.position):
|
||||
continue
|
||||
|
||||
result.append({
|
||||
"id": imp_id,
|
||||
"name": data.get("name", imp_id),
|
||||
|
|
@ -47,6 +52,20 @@ func get_buildable_improvements(
|
|||
return result
|
||||
|
||||
|
||||
func _river_gap_blocked(data: Dictionary, tile_pos: Vector2i) -> bool:
|
||||
## Deposit-destroying improvements (bunker) cannot be sited on a
|
||||
## river-course tile until p2-78 lands the windowed hydrology re-solve.
|
||||
## The verdict comes from Rust (`GdGameState.bunker_river_gap_blocked`);
|
||||
## this is only the build-validity consultation.
|
||||
var effects: Dictionary = data.get("effects", {}) as Dictionary
|
||||
if not bool(effects.get("destroys_deposit", false)):
|
||||
return false
|
||||
var gd_state: RefCounted = GameState.get_gd_state()
|
||||
if gd_state == null:
|
||||
return false
|
||||
return bool(gd_state.call("bunker_river_gap_blocked", tile_pos.x, tile_pos.y))
|
||||
|
||||
|
||||
func _can_unit_build_at(
|
||||
unit: RefCounted, game_map: RefCounted, player: RefCounted
|
||||
) -> bool:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
extends GutTest
|
||||
## p0-16 acceptance test: when an improvement declares `tech_required`, the
|
||||
## p0-16 acceptance test: when an improvement declares `requires_tech`, the
|
||||
## worker's candidate list MUST exclude it for a player that lacks the tech.
|
||||
##
|
||||
## ImprovementManager.get_buildable_improvements applies the tech gate via
|
||||
|
|
@ -40,7 +40,7 @@ func before_all() -> void:
|
|||
"valid_terrain": ["grassland", "plains"],
|
||||
"yields": {"food": 1, "production": 1},
|
||||
"effects": {},
|
||||
"tech_required": FIXTURE_TECH_ID,
|
||||
"requires_tech": FIXTURE_TECH_ID,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -116,3 +116,58 @@ func test_worker_with_required_tech_includes_gated_improvement() -> void:
|
|||
("worker WITH '%s' tech must be offered '%s'; candidate list "
|
||||
+ "was %s") % [FIXTURE_TECH_ID, FIXTURE_IMP_ID, str(ids)],
|
||||
)
|
||||
|
||||
|
||||
func test_bunker_gated_by_terrain_and_pneumatic_construction() -> void:
|
||||
## p2-76 acceptance: the SHIPPING bunker is offered only on hills/mountains
|
||||
## AND only with `pneumatic_construction` (both gates read from bunker.json).
|
||||
var bunker_data: Dictionary = DataLoader.get_improvement("bunker")
|
||||
assert_false(bunker_data.is_empty(), "bunker.json must be loaded by the pack")
|
||||
|
||||
var mgr: RefCounted = ImprovementManagerScript.new()
|
||||
var game_map: RefCounted = GameMapScript.new()
|
||||
game_map.initialize(4, 4, 0)
|
||||
var tile: Resource = TileScript.new()
|
||||
tile.biome_id = "hills"
|
||||
tile.owner = 0
|
||||
tile.improvement = ""
|
||||
tile.position = Vector2i(0, 0)
|
||||
game_map.set_tile(Vector2i(0, 0), tile)
|
||||
|
||||
var player: RefCounted = PlayerScript.new()
|
||||
player.index = 0
|
||||
player.researched_techs.clear()
|
||||
|
||||
var worker: RefCounted = UnitScript.new("worker", 0, Vector2i(0, 0))
|
||||
worker.can_build_improvements = true
|
||||
worker.movement_remaining = 1
|
||||
|
||||
var without_tech: Array = mgr.get_buildable_improvements(worker, game_map, player)
|
||||
var ids_without: Array[String] = []
|
||||
for entry: Dictionary in without_tech:
|
||||
ids_without.append(str(entry.get("id", "")))
|
||||
assert_false(
|
||||
"bunker" in ids_without,
|
||||
"bunker must NOT be offered without pneumatic_construction; got %s" % str(ids_without),
|
||||
)
|
||||
|
||||
player.researched_techs.append("pneumatic_construction")
|
||||
var with_tech: Array = mgr.get_buildable_improvements(worker, game_map, player)
|
||||
var ids_with: Array[String] = []
|
||||
for entry: Dictionary in with_tech:
|
||||
ids_with.append(str(entry.get("id", "")))
|
||||
assert_true(
|
||||
"bunker" in ids_with,
|
||||
"bunker MUST be offered on hills with pneumatic_construction; got %s" % str(ids_with),
|
||||
)
|
||||
|
||||
# Terrain gate: same teched player on grassland must not see the bunker.
|
||||
tile.biome_id = "grassland"
|
||||
var on_grass: Array = mgr.get_buildable_improvements(worker, game_map, player)
|
||||
var ids_grass: Array[String] = []
|
||||
for entry: Dictionary in on_grass:
|
||||
ids_grass.append(str(entry.get("id", "")))
|
||||
assert_false(
|
||||
"bunker" in ids_grass,
|
||||
"bunker must NOT be offered on grassland; got %s" % str(ids_grass),
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue