feat: surface player routes for village needs

This commit is contained in:
Rijad Zuzo
2026-07-16 12:36:50 +02:00
parent d6e6a63048
commit 4f88d15e12
15 changed files with 417 additions and 47 deletions
+59 -1
View File
@@ -306,6 +306,60 @@ func test_ready_inventory_then_trust_and_stable_id_rank_helpers_deterministicall
assert_eq(result.helper_npc_id, lower_id_carrier.id)
func test_player_response_requires_no_helper_and_a_real_player_supply_route() -> void:
var fixture := _open_fixture()
var system: VillageOpportunitySystem = fixture["system"]
var pantry: StorageStateRecord = fixture["pantry"]
var opportunity: OpportunityStateRecord = system.get_open_opportunity()
var player_source := _resource_state(
&"player_berries", SimulationIds.ACTION_GATHER_FOOD, SimulationIds.RESOURCE_FOOD, 1.0
)
var npc_only_source := _resource_state(
&"npc_berries",
SimulationIds.ACTION_GATHER_FOOD,
SimulationIds.RESOURCE_FOOD,
2.0,
0.0,
0.0,
false
)
var resource_states := {
player_source.get_node_id(): player_source,
npc_only_source.get_node_id(): npc_only_source,
}
assert_true(player_source.reserve(99))
var opportunity_before := opportunity.to_dictionary()
var pantry_before := pantry.to_dictionary()
var source_before := player_source.to_dictionary()
var response: OpportunityPlayerResponseResult = system.find_player_response(
opportunity, pantry, resource_states, false
)
assert_not_null(response)
assert_eq(response.opportunity_id, opportunity.get_opportunity_id())
assert_eq(response.trigger_event_id, opportunity.get_trigger_event_id())
assert_eq(response.action_id, SimulationIds.ACTION_GATHER_FOOD)
assert_eq(response.resource_id, SimulationIds.RESOURCE_FOOD)
assert_eq(response.target_id, SimulationIds.STORAGE_VILLAGE_PANTRY)
assert_eq(response.available_source_count, 1)
assert_string_contains(response.reason, "No capable helper")
assert_string_contains(response.reason, "player-usable finite Food source")
assert_eq(opportunity.to_dictionary(), opportunity_before)
assert_eq(pantry.to_dictionary(), pantry_before)
assert_eq(player_source.to_dictionary(), source_before)
assert_null(system.find_player_response(opportunity, pantry, resource_states, true))
player_source.set_enabled(false)
assert_null(system.find_player_response(opportunity, pantry, resource_states, false))
var full_pantry := StorageStateRecord.create(
SimulationIds.STORAGE_VILLAGE_PANTRY, {String(SimulationIds.RESOURCE_WOOD): 1.0}, 1.0
)
player_source.set_enabled(true)
assert_null(system.find_player_response(opportunity, full_pantry, resource_states, false))
var wrong_target := StorageStateRecord.create(&"not_the_pantry", {}, 1.0)
assert_null(system.find_player_response(opportunity, wrong_target, resource_states, false))
func test_wood_helper_uses_available_finite_source_and_respects_reservations() -> void:
var system := VillageOpportunitySystemScript.new()
var interested := _npc(0, 20.0)
@@ -483,7 +537,9 @@ func _resource_state(
resource_id: StringName,
amount: float,
discovery_priority: float = 0.0,
safety_risk: float = 0.0
safety_risk: float = 0.0,
can_player_use: bool = true,
can_npcs_use: bool = true
) -> ResourceStateRecord:
var node := ResourceNode.new()
node.node_id = node_id
@@ -493,6 +549,8 @@ func _resource_state(
node.yield_per_action = 1.0
node.discovery_priority = discovery_priority
node.safety_risk = safety_risk
node.can_player_use = can_player_use
node.can_npcs_use = can_npcs_use
var state := ResourceStateRecord.create_from_node(node)
node.free()
return state