feat: introduce identity-backed goat
This commit is contained in:
@@ -2,6 +2,7 @@ extends Node
|
||||
|
||||
const SimulationEventLogScript := preload("res://simulation/events/SimulationEventLog.gd")
|
||||
const VillageEconomyScript := preload("res://simulation/economy/VillageEconomy.gd")
|
||||
const AnimalCareSystemScript := preload("res://simulation/animals/AnimalCareSystem.gd")
|
||||
const RelationshipSystemScript := preload("res://simulation/relationships/RelationshipSystem.gd")
|
||||
const EventKnowledgeSystemScript := preload("res://simulation/knowledge/EventKnowledgeSystem.gd")
|
||||
|
||||
@@ -38,6 +39,7 @@ var wander_random_sources := {}
|
||||
var resource_states: Dictionary = {}
|
||||
var event_log := SimulationEventLogScript.new()
|
||||
var economy := VillageEconomyScript.new()
|
||||
var animal_care := AnimalCareSystemScript.new()
|
||||
var relationship_system := RelationshipSystemScript.new()
|
||||
var event_knowledge_system := EventKnowledgeSystemScript.new()
|
||||
var opportunity_system := VillageOpportunitySystem.new()
|
||||
@@ -71,6 +73,8 @@ func _ready() -> void:
|
||||
economy.inventory_changed.connect(_on_economy_inventory_changed)
|
||||
economy.economic_event_requested.connect(_record_economic_event)
|
||||
economy.narrative_event_requested.connect(record_narrative_event)
|
||||
animal_care.economic_event_requested.connect(_record_economic_event_at)
|
||||
animal_care.narrative_event_requested.connect(record_narrative_event)
|
||||
action_selector.relationship_system = relationship_system
|
||||
var definition_errors := SimulationDefinitions.validate()
|
||||
if not definition_errors.is_empty():
|
||||
@@ -83,12 +87,14 @@ func _ready() -> void:
|
||||
clock.elapsed_ticks = int(0.25 * cycle_duration_seconds / tick_interval)
|
||||
village.debug_logs = debug_logs
|
||||
economy.configure(village, debug_logs)
|
||||
animal_care.configure(economy, active_world_adapter)
|
||||
economy.initialize_storage()
|
||||
village.update_modifiers()
|
||||
village.update_priorities()
|
||||
generate_npcs()
|
||||
relationship_system.initialize_households(npcs)
|
||||
call_deferred("register_loaded_resource_nodes")
|
||||
animal_care.call_deferred("register_loaded_nodes")
|
||||
call_deferred("register_loaded_storage_nodes")
|
||||
if debug_logs:
|
||||
print("--- Simulation started ---")
|
||||
@@ -156,6 +162,7 @@ func simulate_tick() -> void:
|
||||
tick_count += 1
|
||||
if debug_logs:
|
||||
print("--- Tick ", tick_count, " ---")
|
||||
animal_care.advance()
|
||||
var village_was_changed := false
|
||||
_population_view.rebuild(npcs)
|
||||
for npc in npcs:
|
||||
@@ -210,8 +217,9 @@ func _select_action_if_idle(npc: SimNPC, previous_state: StringName) -> void:
|
||||
if npc.task_state not in [SimNPC.TASK_STATE_IDLE, SimNPC.TASK_STATE_COMPLETE]:
|
||||
return
|
||||
var helper := get_active_opportunity_helper()
|
||||
var animal_feed_name := animal_care.get_available_feed_name(npc.id)
|
||||
var selection := action_selector.select_action(
|
||||
npc, village, clock.time_of_day(), npcs, helper, _population_view
|
||||
npc, village, clock.time_of_day(), npcs, helper, _population_view, animal_feed_name
|
||||
)
|
||||
if selection == null:
|
||||
return
|
||||
@@ -239,7 +247,12 @@ func _handle_npc_death(npc: SimNPC, previous_task: StringName, previous_target:
|
||||
func _complete_current_action(npc: SimNPC) -> void:
|
||||
var completed_task := npc.current_task
|
||||
var definition := SimulationDefinitions.get_action(completed_task)
|
||||
if economy.consume_completion_cost(npc, definition):
|
||||
var completion_succeeded := false
|
||||
if completed_task == SimulationIds.ACTION_FEED_ANIMAL:
|
||||
completion_succeeded = feed_animal(npc.target_id, npc.id)
|
||||
else:
|
||||
completion_succeeded = economy.consume_completion_cost(npc, definition)
|
||||
if completion_succeeded:
|
||||
_apply_action_completion(npc, completed_task, definition)
|
||||
elif not npc.target_id.is_empty():
|
||||
release_npc_reservation(npc.id)
|
||||
@@ -272,6 +285,8 @@ func _apply_action_completion(
|
||||
npc.energy = minf(npc.energy + 40.0, 100.0)
|
||||
npc.position = npc.home_position
|
||||
record_narrative_event(SimulationIds.EVENT_NPC_SLEPT, npc.id)
|
||||
SimulationIds.ACTION_FEED_ANIMAL:
|
||||
pass
|
||||
SimulationIds.ACTION_PATROL, SimulationIds.ACTION_STUDY, SimulationIds.ACTION_REST, SimulationIds.ACTION_WANDER:
|
||||
village.apply_npc_task(npc)
|
||||
if debug_logs and completed_task == SimulationIds.ACTION_SLEEP:
|
||||
@@ -364,6 +379,9 @@ func release_npc_reservation(npc_id: int) -> void:
|
||||
var resource_state := get_resource_state(npc.target_id)
|
||||
if resource_state != null:
|
||||
resource_state.release(npc.id)
|
||||
var animal_state := animal_care.get_state(npc.target_id)
|
||||
if animal_state != null:
|
||||
animal_state.release(npc.id)
|
||||
npc.target_id = &""
|
||||
return
|
||||
|
||||
@@ -397,6 +415,22 @@ func notify_npc_arrived(npc_id: int) -> void:
|
||||
)
|
||||
notify_npc_navigation_failed(npc.id)
|
||||
return
|
||||
if (
|
||||
npc.target_id != &""
|
||||
and definition != null
|
||||
and definition.target_type == SimulationIds.TARGET_ANIMAL
|
||||
):
|
||||
if not animal_care.can_complete_feed(npc.target_id, npc.id):
|
||||
if debug_logs:
|
||||
print(
|
||||
"[SimulationManager] ",
|
||||
npc.npc_name,
|
||||
" arrived but animal ",
|
||||
npc.target_id,
|
||||
" no longer needs feeding, replanning"
|
||||
)
|
||||
notify_npc_navigation_failed(npc.id)
|
||||
return
|
||||
|
||||
npc.has_travel_target = false
|
||||
npc.start_working()
|
||||
@@ -903,6 +937,13 @@ func _on_economy_inventory_changed(npc: SimNPC, item_id: StringName, amount: flo
|
||||
npc_inventory_changed.emit(npc, item_id, amount)
|
||||
|
||||
|
||||
func feed_animal(animal_id: StringName, actor_id: int = -1) -> bool:
|
||||
var succeeded := animal_care.feed(animal_id, actor_id, npcs, tick_count)
|
||||
if succeeded:
|
||||
village_changed.emit(village)
|
||||
return succeeded
|
||||
|
||||
|
||||
func register_loaded_resource_nodes() -> void:
|
||||
for node in ResourceNode.get_all():
|
||||
register_resource_node(node)
|
||||
@@ -1051,50 +1092,6 @@ func get_starving_count() -> int:
|
||||
return _population_view.starving_count()
|
||||
|
||||
|
||||
func get_state_snapshot() -> Dictionary:
|
||||
var npc_snapshots: Array[Dictionary] = []
|
||||
for npc in npcs:
|
||||
npc_snapshots.append(
|
||||
{
|
||||
"id": npc.id,
|
||||
"name": npc.npc_name,
|
||||
"profession": npc.profession,
|
||||
"hunger": npc.hunger,
|
||||
"energy": npc.energy,
|
||||
"strength": npc.strength,
|
||||
"intelligence": npc.intelligence,
|
||||
"task": npc.current_task,
|
||||
"task_state": npc.task_state,
|
||||
"task_duration": npc.task_duration,
|
||||
"task_progress": npc.task_progress,
|
||||
"target_id": String(npc.target_id),
|
||||
"position": [npc.position.x, npc.position.y, npc.position.z],
|
||||
"travel_target_position":
|
||||
[
|
||||
npc.travel_target_position.x,
|
||||
npc.travel_target_position.y,
|
||||
npc.travel_target_position.z
|
||||
],
|
||||
"has_travel_target": npc.has_travel_target,
|
||||
"starvation_ticks": npc.starvation_ticks,
|
||||
"is_dead": npc.is_dead
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
"seed": simulation_seed,
|
||||
"tick_count": tick_count,
|
||||
"village":
|
||||
{
|
||||
"food": village.food,
|
||||
"wood": village.wood,
|
||||
"safety": village.safety,
|
||||
"knowledge": village.knowledge
|
||||
},
|
||||
"npcs": npc_snapshots
|
||||
}
|
||||
|
||||
|
||||
func get_state_checksum() -> String:
|
||||
return create_state_record().to_json().sha256_text()
|
||||
|
||||
@@ -1127,6 +1124,7 @@ func create_state_record() -> SimulationStateRecord:
|
||||
record.village = VillageStateRecord.capture(village)
|
||||
for npc in npcs:
|
||||
record.npcs.append(NPCStateRecord.capture(npc))
|
||||
animal_care.append_state_records(record)
|
||||
var sorted_resource_ids: Array = resource_states.keys()
|
||||
sorted_resource_ids.sort()
|
||||
for resource_id in sorted_resource_ids:
|
||||
@@ -1194,6 +1192,7 @@ func restore_state(record: SimulationStateRecord) -> bool:
|
||||
for resource_record in record.resources:
|
||||
resource_states[resource_record.get_node_id()] = resource_record
|
||||
register_loaded_resource_nodes()
|
||||
animal_care.restore_state_records(record.animals)
|
||||
village_changed.emit(village)
|
||||
state_restored.emit()
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user