Reconcile radio-delivered body and status casualties by original roster identity
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
// Delivered initial-roster slot identities only. No native actor/position access.
|
||||
// One instance belongs to one immutable formation SourceId in the watch roster.
|
||||
class ERR_HQDeliveredCasualties
|
||||
{
|
||||
protected int m_Strength;
|
||||
protected ref array<int> m_StatusSlots = {};
|
||||
protected ref array<int> m_KnownSlots = {};
|
||||
bool Bind(int strength)
|
||||
{
|
||||
if (strength < 1 || strength > 32) return false;
|
||||
if (m_Strength != 0) return m_Strength == strength;
|
||||
m_Strength = strength;
|
||||
return true;
|
||||
}
|
||||
int Count() { return m_KnownSlots.Count(); }
|
||||
int StatusCount() { return m_StatusSlots.Count(); }
|
||||
bool Closed() { return m_Strength > 0 && Count() == m_Strength; }
|
||||
bool Known(int slot) { return m_KnownSlots.Contains(slot); }
|
||||
protected bool ValidSlot(int slot) { return m_Strength > 0 && slot >= 0 && slot < m_Strength; }
|
||||
bool AcceptBody(int slot)
|
||||
{
|
||||
if (!ValidSlot(slot)) return false;
|
||||
if (!m_KnownSlots.Contains(slot)) m_KnownSlots.Insert(slot);
|
||||
return true; // A repeated valid report is idempotent, including a status-known casualty.
|
||||
}
|
||||
bool AcceptStatus(array<int> slots, int reportedLosses, int reportedLiving)
|
||||
{
|
||||
if (m_Strength <= 0 || !slots || reportedLosses < 0 || reportedLosses > m_Strength
|
||||
|| reportedLiving < 0 || reportedLiving > m_Strength - reportedLosses || slots.Count() != reportedLosses)
|
||||
return false;
|
||||
array<int> unique = {};
|
||||
foreach (int slot : slots)
|
||||
{
|
||||
if (!ValidSlot(slot) || unique.Contains(slot)) return false;
|
||||
unique.Insert(slot);
|
||||
}
|
||||
// A later local cumulative status cannot resurrect a previously status-confirmed member.
|
||||
// Body-only knowledge is intentionally not required in an uninformed caller's status.
|
||||
foreach (int previous : m_StatusSlots) if (!unique.Contains(previous)) return false;
|
||||
m_StatusSlots.Clear();
|
||||
foreach (int slot : unique)
|
||||
{
|
||||
m_StatusSlots.Insert(slot);
|
||||
if (!m_KnownSlots.Contains(slot)) m_KnownSlots.Insert(slot);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int LivingUpperBound(int lastReportedLiving)
|
||||
{
|
||||
if (Closed()) return 0;
|
||||
if (lastReportedLiving < 0 || lastReportedLiving > m_Strength) return -1;
|
||||
return Math.Min(lastReportedLiving, m_Strength - Count());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user