Add talk circles with TopicDef, staff/phone chat, and opinion outcomes.
This commit is contained in:
+38
-16
@@ -41,7 +41,8 @@ public readonly record struct ActorState(
|
||||
IReadOnlyDictionary<string, float> Needs,
|
||||
Intent Intent,
|
||||
bool LunchWindowOpen = false,
|
||||
ApparelActor Apparel = default);
|
||||
ApparelActor Apparel = default,
|
||||
TalkPlannerContext Talk = default);
|
||||
|
||||
/// <summary>
|
||||
/// Picks a goal by weight and plans walk-then-do. No world, no clock — a table of inputs to an
|
||||
@@ -254,6 +255,16 @@ public static class DecisionPlanner
|
||||
return Intent.None;
|
||||
}
|
||||
|
||||
if (state.BoundToLesson && TalkCircles.BlocksOnLesson(action.DefName))
|
||||
{
|
||||
return Intent.None;
|
||||
}
|
||||
|
||||
if (action.DefName.Equals(TalkActions.PhoneChat, StringComparison.Ordinal) && !state.Talk.HasPhone)
|
||||
{
|
||||
return Intent.None;
|
||||
}
|
||||
|
||||
if (RoomFor(catalog, map, walks, state, occupied, action) is null)
|
||||
{
|
||||
return Intent.None;
|
||||
@@ -396,8 +407,9 @@ public static class DecisionPlanner
|
||||
}
|
||||
|
||||
string? best = null;
|
||||
var bestCost = float.PositiveInfinity;
|
||||
var bestScore = float.NegativeInfinity;
|
||||
var from = state.NodeId ?? walks.TerritoryId;
|
||||
var candidates = new List<string>();
|
||||
foreach (var room in map.Rooms)
|
||||
{
|
||||
if (!action.Room.Equals(room.Def, StringComparison.Ordinal))
|
||||
@@ -410,27 +422,37 @@ public static class DecisionPlanner
|
||||
continue;
|
||||
}
|
||||
|
||||
var cost = walks.Minutes(from, room.Id);
|
||||
if (float.IsInfinity(cost) || cost > bestCost)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cost < bestCost || best is null || string.CompareOrdinal(room.Id, best) < 0)
|
||||
{
|
||||
best = room.Id;
|
||||
bestCost = cost;
|
||||
}
|
||||
candidates.Add(room.Id);
|
||||
}
|
||||
|
||||
if (map.Territory is { } territory
|
||||
&& action.Room.Equals(territory.Def, StringComparison.Ordinal)
|
||||
&& HasSlot(catalog, map, occupied, territory.Id, action.Thing))
|
||||
{
|
||||
var cost = walks.Minutes(from, territory.Id);
|
||||
if (!float.IsInfinity(cost) && (best is null || cost < bestCost || (cost == bestCost && string.CompareOrdinal(territory.Id, best) < 0)))
|
||||
candidates.Add(territory.Id);
|
||||
}
|
||||
|
||||
var hasAlternative = candidates.Count > 1;
|
||||
foreach (var nodeId in candidates)
|
||||
{
|
||||
if (action.Lunch
|
||||
&& TalkCircles.LunchNodeBlockedByEnemy(nodeId, state.Talk.SelfId ?? "", state.Talk, hasAlternative))
|
||||
{
|
||||
best = territory.Id;
|
||||
continue;
|
||||
}
|
||||
|
||||
var cost = walks.Minutes(from, nodeId);
|
||||
if (float.IsInfinity(cost))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var score = -cost + TalkCircles.NodeFriendScore(nodeId, state.Talk.SelfId ?? "", state.Talk);
|
||||
if (score > bestScore
|
||||
|| (score == bestScore && (best is null || string.CompareOrdinal(nodeId, best) < 0)))
|
||||
{
|
||||
best = nodeId;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user