519 lines
19 KiB
GDScript
519 lines
19 KiB
GDScript
extends GutTest
|
|
|
|
const VillageOpportunitySystemScript := preload(
|
|
"res://simulation/opportunities/VillageOpportunitySystem.gd"
|
|
)
|
|
const RelationshipSystemScript := preload("res://simulation/relationships/RelationshipSystem.gd")
|
|
|
|
|
|
func test_opening_requires_current_knowledge_and_care() -> void:
|
|
var system := VillageOpportunitySystemScript.new()
|
|
var pantry := _empty_pantry()
|
|
var npc := _npc(0, 90.0)
|
|
var npcs: Array[SimNPC] = [npc]
|
|
var knowledge := EventKnowledgeSystem.new()
|
|
var trigger := _withdrawal_event(4, 8, npc.id)
|
|
|
|
assert_null(system.consider_event(trigger, 8, pantry, npcs, knowledge, {}))
|
|
_remember(knowledge, npc.id, 4, 8)
|
|
npc.hunger = VillageOpportunitySystem.CARE_HUNGER_THRESHOLD - 0.01
|
|
assert_null(system.consider_event(trigger, 8, pantry, npcs, knowledge, {}))
|
|
assert_true(system.get_all_sorted().is_empty())
|
|
assert_eq(system.next_opportunity_id, 0)
|
|
|
|
|
|
func test_highest_hunger_then_lowest_id_deterministically_owns_the_opportunity() -> void:
|
|
var system := VillageOpportunitySystemScript.new()
|
|
var pantry := _empty_pantry()
|
|
var lower_hunger := _npc(1, 85.0)
|
|
var high_id := _npc(5, 92.0)
|
|
var low_id := _npc(2, 92.0)
|
|
var npcs: Array[SimNPC] = [high_id, lower_hunger, low_id]
|
|
var knowledge := EventKnowledgeSystem.new()
|
|
var trigger := _withdrawal_event(7, 10, lower_hunger.id)
|
|
for npc in npcs:
|
|
_remember(knowledge, npc.id, 7, 10)
|
|
var pantry_before := pantry.to_dictionary()
|
|
var tasks_before: Array[StringName] = []
|
|
for npc in npcs:
|
|
tasks_before.append(npc.current_task)
|
|
|
|
var opened: OpportunityStateRecord = system.consider_event(
|
|
trigger, 10, pantry, npcs, knowledge, {}
|
|
)
|
|
|
|
assert_not_null(opened)
|
|
assert_eq(opened.get_opportunity_id(), 0)
|
|
assert_eq(opened.get_interested_npc_id(), low_id.id)
|
|
assert_eq(opened.get_trigger_event_id(), 7)
|
|
assert_eq(opened.get_created_tick(), 10)
|
|
assert_eq(opened.get_opportunity_type(), SimulationIds.OPPORTUNITY_RESTOCK_EMPTY_PANTRY)
|
|
assert_eq(opened.get_status(), OpportunityStateRecord.STATUS_OPEN)
|
|
assert_eq(opened.get_target_id(), SimulationIds.STORAGE_VILLAGE_PANTRY)
|
|
assert_eq(opened.get_resource_id(), SimulationIds.RESOURCE_FOOD)
|
|
assert_eq(opened.get_target_amount(), 1.0)
|
|
assert_eq(pantry.to_dictionary(), pantry_before)
|
|
for index in npcs.size():
|
|
assert_eq(npcs[index].current_task, tasks_before[index])
|
|
assert_eq(system.next_opportunity_id, 1)
|
|
|
|
|
|
func test_near_equal_hunger_still_uses_the_exact_highest_value() -> void:
|
|
var system := VillageOpportunitySystemScript.new()
|
|
var pantry := _empty_pantry()
|
|
var lower_id := _npc(1, 92.0)
|
|
var slightly_hungrier := _npc(9, 92.000001)
|
|
var npcs: Array[SimNPC] = [lower_id, slightly_hungrier]
|
|
var knowledge := EventKnowledgeSystem.new()
|
|
var trigger := _withdrawal_event(8, 10, lower_id.id)
|
|
for npc in npcs:
|
|
_remember(knowledge, npc.id, 8, 10)
|
|
|
|
var opened: OpportunityStateRecord = system.consider_event(
|
|
trigger, 10, pantry, npcs, knowledge, {}
|
|
)
|
|
|
|
assert_not_null(opened)
|
|
assert_eq(opened.get_interested_npc_id(), slightly_hungrier.id)
|
|
|
|
|
|
func test_late_knowledge_can_open_old_event_and_open_opportunity_dedupes() -> void:
|
|
var system := VillageOpportunitySystemScript.new()
|
|
var pantry := _empty_pantry()
|
|
var npc := _npc(3, 88.0)
|
|
var npcs: Array[SimNPC] = [npc]
|
|
var knowledge := EventKnowledgeSystem.new()
|
|
var original_trigger := _withdrawal_event(10, 4, npc.id)
|
|
|
|
assert_null(system.consider_event(original_trigger, 4, pantry, npcs, knowledge, {}))
|
|
_remember(knowledge, npc.id, 10, 12)
|
|
var opened: OpportunityStateRecord = system.consider_event(
|
|
original_trigger, 12, pantry, npcs, knowledge, {}
|
|
)
|
|
assert_not_null(opened)
|
|
assert_eq(opened.get_created_tick(), 12)
|
|
|
|
var duplicate_trigger := _withdrawal_event(11, 13, npc.id)
|
|
_remember(knowledge, npc.id, 11, 13)
|
|
assert_null(system.consider_event(duplicate_trigger, 13, pantry, npcs, knowledge, {}))
|
|
assert_eq(system.get_all_sorted().size(), 1)
|
|
assert_eq(system.next_opportunity_id, 1)
|
|
|
|
|
|
func test_only_strict_later_npc_deposit_resolves_without_mutating_supply() -> void:
|
|
var fixture := _open_fixture()
|
|
var system: VillageOpportunitySystem = fixture["system"]
|
|
var pantry: StorageStateRecord = fixture["pantry"]
|
|
var npcs: Array[SimNPC] = fixture["npcs"]
|
|
var knowledge: EventKnowledgeSystem = fixture["knowledge"]
|
|
pantry.deposit(SimulationIds.RESOURCE_FOOD, 1.0)
|
|
var food_before := pantry.get_amount(SimulationIds.RESOURCE_FOOD)
|
|
|
|
var invalid_events: Array[EconomicEventRecord] = [
|
|
_supply_event(20, 11, SimulationIds.EVENT_RESOURCE_EXTRACTED, 0),
|
|
_supply_event(21, 11, SimulationIds.EVENT_STORAGE_DEPOSITED, -1),
|
|
EconomicEventRecord.create(
|
|
25,
|
|
SimulationIds.EVENT_STORAGE_DEPOSITED,
|
|
11,
|
|
0,
|
|
&"not_the_actor_inventory",
|
|
SimulationIds.STORAGE_VILLAGE_PANTRY,
|
|
SimulationIds.RESOURCE_FOOD,
|
|
1.0
|
|
),
|
|
EconomicEventRecord.create(
|
|
22,
|
|
SimulationIds.EVENT_STORAGE_DEPOSITED,
|
|
11,
|
|
0,
|
|
SimulationIds.npc_inventory_id(0),
|
|
SimulationIds.STORAGE_VILLAGE_WOODPILE,
|
|
SimulationIds.RESOURCE_FOOD,
|
|
1.0
|
|
),
|
|
EconomicEventRecord.create(
|
|
23,
|
|
SimulationIds.EVENT_STORAGE_DEPOSITED,
|
|
11,
|
|
0,
|
|
SimulationIds.npc_inventory_id(0),
|
|
SimulationIds.STORAGE_VILLAGE_PANTRY,
|
|
SimulationIds.RESOURCE_FOOD,
|
|
0.0
|
|
),
|
|
]
|
|
for event in invalid_events:
|
|
assert_null(system.consider_event(event, 11, pantry, npcs, knowledge, {}))
|
|
assert_eq(pantry.get_amount(SimulationIds.RESOURCE_FOOD), food_before)
|
|
assert_eq(system.get_open_opportunity().get_status(), OpportunityStateRecord.STATUS_OPEN)
|
|
|
|
var valid_supply := _supply_event(24, 12, SimulationIds.EVENT_STORAGE_DEPOSITED, 0)
|
|
var resolved: OpportunityStateRecord = system.consider_event(
|
|
valid_supply, 12, pantry, npcs, knowledge, {}
|
|
)
|
|
assert_not_null(resolved)
|
|
assert_eq(resolved.get_status(), OpportunityStateRecord.STATUS_RESOLVED)
|
|
assert_eq(resolved.get_resolution_event_id(), 24)
|
|
assert_eq(resolved.get_resolved_tick(), 12)
|
|
assert_null(system.get_open_opportunity())
|
|
assert_eq(pantry.get_amount(SimulationIds.RESOURCE_FOOD), food_before)
|
|
|
|
|
|
func test_player_extraction_into_pantry_is_the_other_valid_resolution() -> void:
|
|
var fixture := _open_fixture()
|
|
var system: VillageOpportunitySystem = fixture["system"]
|
|
var pantry: StorageStateRecord = fixture["pantry"]
|
|
var npcs: Array[SimNPC] = fixture["npcs"]
|
|
var knowledge: EventKnowledgeSystem = fixture["knowledge"]
|
|
pantry.deposit(SimulationIds.RESOURCE_FOOD, 1.0)
|
|
var player_supply := _supply_event(30, 14, SimulationIds.EVENT_RESOURCE_EXTRACTED, -1)
|
|
assert_null(system.consider_event(player_supply, 14, pantry, npcs, knowledge, {}))
|
|
assert_not_null(system.get_open_opportunity())
|
|
|
|
var resolved: OpportunityStateRecord = system.consider_event(
|
|
player_supply, 14, pantry, npcs, knowledge, _player_resource_states()
|
|
)
|
|
|
|
assert_not_null(resolved)
|
|
assert_eq(resolved.get_resolution_event_id(), 30)
|
|
assert_eq(resolved.get_status(), OpportunityStateRecord.STATUS_RESOLVED)
|
|
|
|
|
|
func test_missing_wood_maintenance_does_not_change_the_existing_food_lifecycle() -> void:
|
|
var fixture := _open_fixture()
|
|
var system: VillageOpportunitySystem = fixture["system"]
|
|
var pantry: StorageStateRecord = fixture["pantry"]
|
|
var npcs: Array[SimNPC] = fixture["npcs"]
|
|
var food_need: OpportunityStateRecord = system.get_open_opportunity()
|
|
npcs[0].is_dead = true
|
|
|
|
assert_null(system.maintain_open_opportunity(1000, 10, npcs, pantry, null))
|
|
assert_eq(food_need.get_status(), OpportunityStateRecord.STATUS_OPEN)
|
|
assert_eq(food_need.get_closed_tick(), -1)
|
|
|
|
|
|
func test_capable_helper_requires_exact_knowledge_trust_and_a_real_supply_route() -> void:
|
|
var fixture := _open_fixture()
|
|
var system: VillageOpportunitySystem = fixture["system"]
|
|
var pantry: StorageStateRecord = fixture["pantry"]
|
|
var knowledge: EventKnowledgeSystem = fixture["knowledge"]
|
|
var interested: SimNPC = fixture["npcs"][0]
|
|
var helper := _npc(1, 20.0)
|
|
var npcs: Array[SimNPC] = [interested, helper]
|
|
var relationships := RelationshipSystemScript.new()
|
|
var trusted := RelationshipStateRecord.create(helper.id, interested.id, 0.8, 0.7)
|
|
relationships.restore([trusted])
|
|
var source := _resource_state(
|
|
&"orchard_berries", SimulationIds.ACTION_GATHER_FOOD, SimulationIds.RESOURCE_FOOD, 2.0, 3.0
|
|
)
|
|
var resource_states := {source.get_node_id(): source}
|
|
var opportunity: OpportunityStateRecord = system.get_open_opportunity()
|
|
|
|
assert_null(
|
|
system.find_capable_helper(
|
|
opportunity, pantry, npcs, knowledge, relationships, resource_states
|
|
)
|
|
)
|
|
_remember(knowledge, helper.id, opportunity.get_trigger_event_id(), 10)
|
|
relationships.restore([RelationshipStateRecord.create(helper.id, interested.id, 0.8, 0.59)])
|
|
assert_null(
|
|
system.find_capable_helper(
|
|
opportunity, pantry, npcs, knowledge, relationships, resource_states
|
|
)
|
|
)
|
|
relationships.restore([trusted])
|
|
var opportunity_before := opportunity.to_dictionary()
|
|
var source_before := source.to_dictionary()
|
|
var helper_inventory_before := helper.inventory.duplicate(true)
|
|
var result: OpportunityHelperResult = system.find_capable_helper(
|
|
opportunity, pantry, npcs, knowledge, relationships, resource_states
|
|
)
|
|
|
|
assert_not_null(result)
|
|
assert_eq(result.opportunity_id, opportunity.get_opportunity_id())
|
|
assert_eq(result.helper_npc_id, helper.id)
|
|
assert_eq(result.action_id, SimulationIds.ACTION_GATHER_FOOD)
|
|
assert_true(result.source_id.is_empty())
|
|
assert_eq(result.available_source_count, 1)
|
|
assert_eq(result.resource_id, SimulationIds.RESOURCE_FOOD)
|
|
assert_eq(result.trigger_event_id, opportunity.get_trigger_event_id())
|
|
assert_eq(result.trust, 0.7)
|
|
assert_true(result.profession_match)
|
|
assert_false(result.uses_inventory)
|
|
assert_string_contains(result.reason, "Knows the need")
|
|
assert_eq(opportunity.to_dictionary(), opportunity_before)
|
|
assert_eq(source.to_dictionary(), source_before)
|
|
assert_eq(helper.inventory, helper_inventory_before)
|
|
|
|
|
|
func test_ready_inventory_then_trust_and_stable_id_rank_helpers_deterministically() -> void:
|
|
var fixture := _open_fixture()
|
|
var system: VillageOpportunitySystem = fixture["system"]
|
|
var pantry: StorageStateRecord = fixture["pantry"]
|
|
var knowledge: EventKnowledgeSystem = fixture["knowledge"]
|
|
var interested: SimNPC = fixture["npcs"][0]
|
|
var trusted_gatherer := _npc(1, 20.0)
|
|
var lower_id_carrier := _npc(2, 20.0)
|
|
var stronger_carrier := _npc(5, 20.0)
|
|
lower_id_carrier.profession = SimulationIds.PROFESSION_GUARD
|
|
stronger_carrier.profession = SimulationIds.PROFESSION_GUARD
|
|
lower_id_carrier.add_inventory(SimulationIds.RESOURCE_FOOD, 1.0)
|
|
stronger_carrier.add_inventory(SimulationIds.RESOURCE_FOOD, 1.0)
|
|
var npcs: Array[SimNPC] = [interested, trusted_gatherer, lower_id_carrier, stronger_carrier]
|
|
var opportunity: OpportunityStateRecord = system.get_open_opportunity()
|
|
for helper in [trusted_gatherer, lower_id_carrier, stronger_carrier]:
|
|
_remember(knowledge, helper.id, opportunity.get_trigger_event_id(), 10)
|
|
var relationships := RelationshipSystemScript.new()
|
|
(
|
|
relationships
|
|
. restore(
|
|
[
|
|
RelationshipStateRecord.create(trusted_gatherer.id, interested.id, 0.9, 0.95),
|
|
RelationshipStateRecord.create(lower_id_carrier.id, interested.id, 0.7, 0.7),
|
|
RelationshipStateRecord.create(stronger_carrier.id, interested.id, 0.7, 0.8),
|
|
]
|
|
)
|
|
)
|
|
var source := _resource_state(
|
|
&"berry_source", SimulationIds.ACTION_GATHER_FOOD, SimulationIds.RESOURCE_FOOD, 2.0
|
|
)
|
|
var result: OpportunityHelperResult = system.find_capable_helper(
|
|
opportunity, pantry, npcs, knowledge, relationships, {source.get_node_id(): source}
|
|
)
|
|
|
|
assert_eq(result.helper_npc_id, stronger_carrier.id)
|
|
assert_eq(result.action_id, SimulationIds.ACTION_DEPOSIT_FOOD)
|
|
assert_eq(result.source_id, SimulationIds.npc_inventory_id(stronger_carrier.id))
|
|
assert_true(result.uses_inventory)
|
|
assert_eq(result.available_source_count, 0)
|
|
assert_false(result.profession_match)
|
|
assert_eq(result.trust, 0.8)
|
|
|
|
(
|
|
relationships
|
|
. restore(
|
|
[
|
|
RelationshipStateRecord.create(trusted_gatherer.id, interested.id, 0.9, 0.95),
|
|
RelationshipStateRecord.create(lower_id_carrier.id, interested.id, 0.7, 0.8),
|
|
RelationshipStateRecord.create(stronger_carrier.id, interested.id, 0.7, 0.8),
|
|
]
|
|
)
|
|
)
|
|
result = system.find_capable_helper(
|
|
opportunity, pantry, npcs, knowledge, relationships, {source.get_node_id(): source}
|
|
)
|
|
assert_eq(result.helper_npc_id, lower_id_carrier.id)
|
|
|
|
|
|
func test_wood_helper_uses_available_finite_source_and_respects_reservations() -> void:
|
|
var system := VillageOpportunitySystemScript.new()
|
|
var interested := _npc(0, 20.0)
|
|
var helper := _npc(1, 20.0)
|
|
helper.profession = SimulationIds.PROFESSION_WOODCUTTER
|
|
var npcs: Array[SimNPC] = [interested, helper]
|
|
var knowledge := EventKnowledgeSystem.new()
|
|
var opportunity := OpportunityStateRecord.create(
|
|
0,
|
|
10,
|
|
4,
|
|
interested.id,
|
|
1.0,
|
|
SimulationIds.OPPORTUNITY_SUPPLY_MISSING_WOOD,
|
|
SimulationIds.STORAGE_VILLAGE_WOODPILE,
|
|
SimulationIds.RESOURCE_WOOD
|
|
)
|
|
system.restore([opportunity], 1)
|
|
_remember(knowledge, helper.id, opportunity.get_trigger_event_id(), 10)
|
|
var relationships := RelationshipSystemScript.new()
|
|
relationships.restore([RelationshipStateRecord.create(helper.id, interested.id, 0.7, 0.7)])
|
|
var preferred_source := _resource_state(
|
|
&"safe_grove", SimulationIds.ACTION_GATHER_WOOD, SimulationIds.RESOURCE_WOOD, 2.0, 5.0, 0.1
|
|
)
|
|
var fallback_source := _resource_state(
|
|
&"rough_grove", SimulationIds.ACTION_GATHER_WOOD, SimulationIds.RESOURCE_WOOD, 2.0, 1.0, 0.8
|
|
)
|
|
var sources := {
|
|
fallback_source.get_node_id(): fallback_source,
|
|
preferred_source.get_node_id(): preferred_source,
|
|
}
|
|
var woodpile := StorageStateRecord.create(
|
|
SimulationIds.STORAGE_VILLAGE_WOODPILE, {String(SimulationIds.RESOURCE_WOOD): 0.0}
|
|
)
|
|
var result: OpportunityHelperResult = system.find_capable_helper(
|
|
opportunity, woodpile, npcs, knowledge, relationships, sources
|
|
)
|
|
|
|
assert_eq(result.helper_npc_id, helper.id)
|
|
assert_eq(result.action_id, SimulationIds.ACTION_GATHER_WOOD)
|
|
assert_true(result.source_id.is_empty())
|
|
assert_eq(result.available_source_count, 2)
|
|
assert_true(result.profession_match)
|
|
assert_true(preferred_source.reserve(99))
|
|
result = system.find_capable_helper(
|
|
opportunity, woodpile, npcs, knowledge, relationships, sources
|
|
)
|
|
assert_eq(result.available_source_count, 1)
|
|
assert_true(fallback_source.reserve(99))
|
|
assert_null(
|
|
system.find_capable_helper(opportunity, woodpile, npcs, knowledge, relationships, sources)
|
|
)
|
|
|
|
|
|
func test_restore_preserves_ids_sorted_queries_and_resolves_only_oldest_open() -> void:
|
|
var older := OpportunityStateRecord.create(2, 5, 4, 7)
|
|
var newer := OpportunityStateRecord.create(5, 8, 7, 9)
|
|
var restored_records: Array[OpportunityStateRecord] = [newer, older]
|
|
var system := VillageOpportunitySystemScript.new()
|
|
system.restore(restored_records, 6)
|
|
|
|
assert_eq(system.next_opportunity_id, 6)
|
|
assert_eq(system.get_all_sorted().map(_opportunity_id), [2, 5])
|
|
assert_eq(system.get_open_opportunity(), older)
|
|
assert_eq(system.get_latest_for_npc(9), newer)
|
|
assert_null(system.get_latest_for_npc(100))
|
|
|
|
var pantry := _empty_pantry()
|
|
pantry.deposit(SimulationIds.RESOURCE_FOOD, 1.0)
|
|
var npcs: Array[SimNPC] = [_npc(0, 10.0)]
|
|
var supply := _supply_event(40, 10, SimulationIds.EVENT_STORAGE_DEPOSITED, 0)
|
|
var resolved: OpportunityStateRecord = system.consider_event(
|
|
supply, 10, pantry, npcs, EventKnowledgeSystem.new(), {}
|
|
)
|
|
assert_eq(resolved, older)
|
|
assert_eq(older.get_status(), OpportunityStateRecord.STATUS_RESOLVED)
|
|
assert_eq(newer.get_status(), OpportunityStateRecord.STATUS_OPEN)
|
|
assert_eq(system.get_open_opportunity(), newer)
|
|
|
|
|
|
func test_record_parser_rejects_malformed_state_combinations() -> void:
|
|
var valid := OpportunityStateRecord.create(3, 10, 8, 2)
|
|
assert_not_null(OpportunityStateRecord.from_dictionary(valid.to_dictionary()))
|
|
|
|
var invalid_open := valid.to_dictionary()
|
|
invalid_open["resolution_event_id"] = 9
|
|
assert_null(OpportunityStateRecord.from_dictionary(invalid_open))
|
|
var invalid_type := valid.to_dictionary()
|
|
invalid_type["opportunity_type"] = "generic_quest"
|
|
assert_null(OpportunityStateRecord.from_dictionary(invalid_type))
|
|
var invalid_target := valid.to_dictionary()
|
|
invalid_target["target_amount"] = 2.0
|
|
assert_null(OpportunityStateRecord.from_dictionary(invalid_target))
|
|
var invalid_resolved := valid.to_dictionary()
|
|
invalid_resolved["status"] = String(OpportunityStateRecord.STATUS_RESOLVED)
|
|
invalid_resolved["resolution_event_id"] = 12
|
|
invalid_resolved["resolved_tick"] = 9
|
|
assert_null(OpportunityStateRecord.from_dictionary(invalid_resolved))
|
|
invalid_resolved["resolved_tick"] = 10
|
|
invalid_resolved["resolution_event_id"] = valid.get_trigger_event_id()
|
|
assert_null(OpportunityStateRecord.from_dictionary(invalid_resolved))
|
|
|
|
|
|
func _open_fixture() -> Dictionary:
|
|
var system := VillageOpportunitySystemScript.new()
|
|
var pantry := _empty_pantry()
|
|
var npc := _npc(0, 90.0)
|
|
var npcs: Array[SimNPC] = [npc]
|
|
var knowledge := EventKnowledgeSystem.new()
|
|
var trigger := _withdrawal_event(1, 10, npc.id)
|
|
_remember(knowledge, npc.id, 1, 10)
|
|
assert_not_null(system.consider_event(trigger, 10, pantry, npcs, knowledge, {}))
|
|
return {"system": system, "pantry": pantry, "npcs": npcs, "knowledge": knowledge}
|
|
|
|
|
|
func _empty_pantry() -> StorageStateRecord:
|
|
return StorageStateRecord.create(
|
|
SimulationIds.STORAGE_VILLAGE_PANTRY, {String(SimulationIds.RESOURCE_FOOD): 0.0}
|
|
)
|
|
|
|
|
|
func _npc(npc_id: int, hunger: float) -> SimNPC:
|
|
var npc := SimNPC.new(npc_id, "NPC %d" % npc_id, SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
|
|
npc.hunger = hunger
|
|
npc.is_dead = false
|
|
return npc
|
|
|
|
|
|
func _withdrawal_event(event_id: int, tick: int, actor_id: int) -> EconomicEventRecord:
|
|
return EconomicEventRecord.create(
|
|
event_id,
|
|
SimulationIds.EVENT_STORAGE_WITHDRAWN,
|
|
tick,
|
|
actor_id,
|
|
SimulationIds.STORAGE_VILLAGE_PANTRY,
|
|
SimulationIds.npc_inventory_id(actor_id),
|
|
SimulationIds.RESOURCE_FOOD,
|
|
1.0
|
|
)
|
|
|
|
|
|
func _supply_event(
|
|
event_id: int, tick: int, event_type: StringName, actor_id: int
|
|
) -> EconomicEventRecord:
|
|
var source_id := &"player_resource"
|
|
if event_type == SimulationIds.EVENT_STORAGE_DEPOSITED and actor_id >= 0:
|
|
source_id = SimulationIds.npc_inventory_id(actor_id)
|
|
return EconomicEventRecord.create(
|
|
event_id,
|
|
event_type,
|
|
tick,
|
|
actor_id,
|
|
source_id,
|
|
SimulationIds.STORAGE_VILLAGE_PANTRY,
|
|
SimulationIds.RESOURCE_FOOD,
|
|
1.0
|
|
)
|
|
|
|
|
|
func _player_resource_states() -> Dictionary:
|
|
var resource_node := ResourceNode.new()
|
|
resource_node.node_id = &"player_resource"
|
|
resource_node.action_id = SimulationIds.ACTION_GATHER_FOOD
|
|
resource_node.resource_id = SimulationIds.RESOURCE_FOOD
|
|
resource_node.can_player_use = true
|
|
var resource_state := ResourceStateRecord.create_from_node(resource_node)
|
|
var result := {resource_node.node_id: resource_state}
|
|
resource_node.free()
|
|
return result
|
|
|
|
|
|
func _resource_state(
|
|
node_id: StringName,
|
|
action_id: StringName,
|
|
resource_id: StringName,
|
|
amount: float,
|
|
discovery_priority: float = 0.0,
|
|
safety_risk: float = 0.0
|
|
) -> ResourceStateRecord:
|
|
var node := ResourceNode.new()
|
|
node.node_id = node_id
|
|
node.action_id = action_id
|
|
node.resource_id = resource_id
|
|
node.initial_amount = amount
|
|
node.yield_per_action = 1.0
|
|
node.discovery_priority = discovery_priority
|
|
node.safety_risk = safety_risk
|
|
var state := ResourceStateRecord.create_from_node(node)
|
|
node.free()
|
|
return state
|
|
|
|
|
|
func _remember(
|
|
knowledge: EventKnowledgeSystem, knower_id: int, event_id: int, acquired_tick: int
|
|
) -> void:
|
|
var records := knowledge.get_all_sorted()
|
|
records.append(
|
|
KnownEventStateRecord.create(
|
|
knower_id,
|
|
event_id,
|
|
SimulationIds.KNOWLEDGE_ACQUISITION_PERFORMED,
|
|
KnownEventStateRecord.NO_SOURCE_NPC_ID,
|
|
acquired_tick
|
|
)
|
|
)
|
|
knowledge.restore(records)
|
|
|
|
|
|
func _opportunity_id(opportunity: OpportunityStateRecord) -> int:
|
|
return opportunity.get_opportunity_id()
|