Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md). All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
namespace Theriapolis.Core.Rules.Reputation;
|
||||
|
||||
/// <summary>
|
||||
/// Phase 6 M2 — append-only event log surfaced by the reputation screen
|
||||
/// ("why does so-and-so hate me?"). Bounded to a reasonable tail so the
|
||||
/// save file stays small even after a 100-hour playthrough.
|
||||
///
|
||||
/// Phase 6 M5 layers propagation on top: each entry will be re-walked
|
||||
/// per game-day to fan out into other settlements with distance/time
|
||||
/// decay.
|
||||
/// </summary>
|
||||
public sealed class RepLedger
|
||||
{
|
||||
public const int MaxEntries = 256;
|
||||
|
||||
private readonly List<RepEvent> _entries = new();
|
||||
private int _nextSeq = 1;
|
||||
|
||||
public IReadOnlyList<RepEvent> Entries => _entries;
|
||||
public int Count => _entries.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Append <paramref name="ev"/> to the ledger. If <see cref="RepEvent.SequenceId"/>
|
||||
/// is 0, a fresh monotone id is assigned; otherwise the supplied id
|
||||
/// is preserved (used by the save-restore path).
|
||||
/// </summary>
|
||||
public RepEvent Append(RepEvent ev)
|
||||
{
|
||||
if (ev.SequenceId == 0)
|
||||
ev = ev with { SequenceId = _nextSeq++ };
|
||||
else if (ev.SequenceId >= _nextSeq)
|
||||
_nextSeq = ev.SequenceId + 1;
|
||||
_entries.Add(ev);
|
||||
if (_entries.Count > MaxEntries) _entries.RemoveAt(0);
|
||||
return ev;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_entries.Clear();
|
||||
_nextSeq = 1;
|
||||
}
|
||||
|
||||
/// <summary>Largest <see cref="RepEvent.SequenceId"/> issued so far. 0 = empty ledger.</summary>
|
||||
public int HighestSequenceId => _nextSeq - 1;
|
||||
|
||||
/// <summary>Most recent N events affecting <paramref name="factionId"/>.</summary>
|
||||
public IEnumerable<RepEvent> ForFaction(string factionId, int count = 8)
|
||||
{
|
||||
int yielded = 0;
|
||||
for (int i = _entries.Count - 1; i >= 0 && yielded < count; i--)
|
||||
{
|
||||
if (string.Equals(_entries[i].FactionId, factionId, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
yielded++;
|
||||
yield return _entries[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Most recent N events affecting <paramref name="roleTag"/>.</summary>
|
||||
public IEnumerable<RepEvent> ForRole(string roleTag, int count = 8)
|
||||
{
|
||||
int yielded = 0;
|
||||
for (int i = _entries.Count - 1; i >= 0 && yielded < count; i--)
|
||||
{
|
||||
if (string.Equals(_entries[i].RoleTag, roleTag, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
yielded++;
|
||||
yield return _entries[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user