Add person-to-person disease contagion with outbreak notices.

Node/class contact rolls use pair+day seeds; vanilla respiratory diseases spread, and a threshold raises an info toast instead of per-sneeze noise.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-21 13:55:24 +03:00
co-authored by Cursor
parent a369308116
commit 4a52107bd2
19 changed files with 648 additions and 15 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ namespace HSchool.People;
/// <summary>
/// Reads DiseaseDef stages for lesson gain, stay-home rolls and warmth decay.
/// Contagion between people is phase 79.
/// Contagion rolls live in DiseaseSystem; this type only answers stage questions.
/// </summary>
public static class DiseaseEffects
{
+14
View File
@@ -26,6 +26,7 @@ public static class Seed
public const int MeetingSalt = 18;
public const int MeetingAttendSalt = 19;
public const int DiseaseSalt = 20;
public const int ContagionSalt = 21;
/// <summary>A stream that belongs to the school rather than to one family.</summary>
public static int ForSchool(int schoolSeed, int salt) => Mix(schoolSeed, familyIndex: -1, salt);
@@ -49,6 +50,19 @@ public static class Seed
return (int)z;
}
/// <summary>
/// Contact roll for an ordered person pair on one day (contagion). Ids are sorted so
/// A→B and B→A share the stream; channel salt separates node vs class.
/// </summary>
public static int MixPair(int schoolSeed, string personA, string personB, int dayNumber, int salt)
{
ArgumentNullException.ThrowIfNull(personA);
ArgumentNullException.ThrowIfNull(personB);
var first = string.CompareOrdinal(personA, personB) <= 0 ? personA : personB;
var second = string.CompareOrdinal(personA, personB) <= 0 ? personB : personA;
return Mix(schoolSeed, first + "\u001f" + second, dayNumber, salt);
}
private static uint Stable(string value)
{
ulong z = 0;