diff --git a/simulation/SimulationManager.gd b/simulation/SimulationManager.gd index aa64c07..21ba046 100644 --- a/simulation/SimulationManager.gd +++ b/simulation/SimulationManager.gd @@ -127,7 +127,7 @@ func simulate_tick() -> void: and old_state in [SimNPC.TASK_STATE_IDLE, SimNPC.TASK_STATE_COMPLETE] and npc.task_state in [SimNPC.TASK_STATE_IDLE, SimNPC.TASK_STATE_COMPLETE] ): - var selection := action_selector.select_action(npc, village, clock.time_of_day()) + var selection := action_selector.select_action(npc, village, clock.time_of_day(), npcs) if selection != null: latest_decisions[npc.id] = selection npc_decision_recorded.emit(npc, selection) @@ -360,6 +360,23 @@ func notify_npc_arrived(npc_id: int) -> void: npc.has_travel_target = false npc.start_working() + if npc.target_id != &"": + for other in npcs: + if other.id == npc.id or other.is_dead: + continue + if ( + other.target_id == npc.target_id + and other.task_state in [ + SimNPC.TASK_STATE_TRAVELING, SimNPC.TASK_STATE_WORKING + ] + ): + npc.familiarity[other.id] = minf( + float(npc.familiarity.get(other.id, 0.0)) + 0.1, 1.0 + ) + other.familiarity[npc.id] = minf( + float(other.familiarity.get(npc.id, 0.0)) + 0.1, 1.0 + ) + if debug_logs: print( "[SimulationManager] ", diff --git a/simulation/actions/ActionSelectionSystem.gd b/simulation/actions/ActionSelectionSystem.gd index 564c292..3d77c80 100644 --- a/simulation/actions/ActionSelectionSystem.gd +++ b/simulation/actions/ActionSelectionSystem.gd @@ -18,7 +18,7 @@ const WORK_BEGIN := 0.28 const WORK_END := 0.85 -func select_action(npc: SimNPC, village: SimVillage, time_of_day: float = 0.5) -> ActionSelectionResult: +func select_action(npc: SimNPC, village: SimVillage, time_of_day: float = 0.5, all_npcs: Array = []) -> ActionSelectionResult: if npc.is_dead: return null @@ -120,10 +120,10 @@ func select_action(npc: SimNPC, village: SimVillage, time_of_day: float = 0.5) - SimulationIds.ACTION_WANDER, -1.0, "Discretionary wander" ) - return _choose_best_work_action(npc, village) + return _choose_best_work_action(npc, village, all_npcs) -func _choose_best_work_action(npc: SimNPC, village: SimVillage) -> ActionSelectionResult: +func _choose_best_work_action(npc: SimNPC, village: SimVillage, all_npcs: Array) -> ActionSelectionResult: var scores := { SimulationIds.ACTION_GATHER_FOOD: _calculate_score( @@ -170,6 +170,16 @@ func _choose_best_work_action(npc: SimNPC, village: SimVillage) -> ActionSelecti 0.75 ) } + for familiar_id in npc.familiarity: + if not familiar_id is int: + continue + var other_task: StringName + for other in all_npcs: + if other.id == familiar_id and not other.is_dead: + other_task = other.current_task + break + if other_task in scores: + scores[other_task] = float(scores[other_task]) + 0.3 var best_action := SimulationIds.ACTION_GATHER_FOOD var best_score: float = scores[best_action] for action_id in [ diff --git a/world/ui/ui.gd b/world/ui/ui.gd index 515281e..62a9f14 100644 --- a/world/ui/ui.gd +++ b/world/ui/ui.gd @@ -132,12 +132,14 @@ func _refresh_npc_inspector() -> void: if not score_rows.is_empty(): score_text = "\n\nUtility\n" + "\n".join(score_rows) var event_text := _build_event_history(npc) + var housemate_text := _build_housemate_display(npc) npc_inspector_label.text = ( "%s ยท %s\n" + "Task: %s (%s)\n" + "Destination: %s\n" + "Hunger: %.0f Energy: %.0f\n" - + "Carrying food: %.0f wood: %.0f\n\n" + + "Carrying food: %.0f wood: %.0f\n" + + "%s\n" + "Why\n%s%s\n\n" + "Recent\n%s\n\n" + "[Tab] Next villager [F10] Cinematic/debug [F12] Demo reset" @@ -151,6 +153,7 @@ func _refresh_npc_inspector() -> void: npc.energy, npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD), npc.get_inventory_amount(SimulationIds.RESOURCE_WOOD), + housemate_text, reason_text, score_text, event_text @@ -188,3 +191,24 @@ func _build_event_history(npc: SimNPC) -> String: for event in events: lines.append(event.description(name_map)) return "\n".join(lines) + + +func _build_housemate_display(npc: SimNPC) -> String: + if npc.familiarity.is_empty(): + return "" + var highest_id: int = -1 + var highest_score := -1.0 + for key in npc.familiarity: + var other_id: int = int(key) + var score: float = float(npc.familiarity[key]) + if score > highest_score: + highest_score = score + highest_id = other_id + if highest_id < 0: + return "" + var other_name := "Someone" + for other_npc in simulation_manager.npcs: + if other_npc.id == highest_id: + other_name = other_npc.npc_name + break + return "Familiar: %s (%.0f%%)" % [other_name, highest_score * 100.0]