Reguły symulacji
Dokumentacja wszystkich reguł zachowania mieszkańców.
1. Architektura — DES (Discrete Event Simulation)
Symulator nie iteruje po sekundach, lecz przeskakuje do momentów gdy „coś się dzieje". Dzięki temu na nowoczesnym sprzęcie jest w stanie symulować aktywność nawet dziesiątek milionów osób.
- Każda osoba ma w schedulerze dokładnie 1 oczekujące zdarzenie w formie: _„O czasie T osoba P zaczyna aktywność A"_.
- Gdy zdarzenie odpala się (
T ≤ sim_time):
1. oblicz czas trwania A → czas_końca = T + duration(A) 2. oblicz następną aktywność B = next_activity(A) 3. zapisz do logu: {T, czas_końca, osoba, A, origin, dest} 4. zaktualizuj stan osoby 5. wstaw do schedulera: "O czas_końca osoba zaczyna B"
- Łańcuch jest samo-zasilający się i nigdy się nie urywa.
1a. Dni tygodnia — weekendy
day_of_week(d) zwraca 0=pon … 5=sob, 6=ndz na podstawie wzoru (d/86400 + 3) % 7.
W soboty i niedziele aktywny jest oddzielny harmonogram weekendowy (patrz sekcja 15). Godziny pobudki i śniadania są takie same jak w dni robocze.
2. Deterministyczna pseudolosowość
prand(person_id, day_epoch, salt)
Zwraca uint32_t z dobrym rozkładem. Algorytm: XOR-Shift Hash z mnożeniem przez stałe Knutha.
- Nie ma globalnego stanu → bezpieczne wątkowo.
- Ta sama kombinacja
(person_id, day_epoch, salt)zawsze daje ten sam wynik → powtarzalność dla tego samego seeda. day_epoch= timestamp początku dnia (00:00:00 UTC), różnicuje tę samą osobę w różnych dniach.saltrozróżnia różne zastosowania tej samej osoby tego samego dnia (np.salt=0: godzina wstania,salt=2: czas śniadania).
variance(person_id, day, salt, range)
Zwraca losowe odchylenie z przedziału [-range, +range] sekund. Używane wszędzie tam, gdzie do czasu bazowego dodawana jest wariacja.
3. Godziny wstania
| Status osoby | Bazowa godzina wstania | Wariacja |
|---|---|---|
Pracujący (STATUS_EMPLOYED) | 6:30 | ±30 min |
Uczeń (STATUS_STUDENT) | 7:00 | ±30 min |
Student wyższej uczelni (STATUS_HIGHER_EDU) | 7:00 | ±30 min |
Dziecko (STATUS_CHILD) | 7:30 | ±30 min |
Bezrobotny (STATUS_UNEMPLOYED) | 8:00 | ±30 min |
Emeryt (STATUS_RETIRED) | 8:00 | ±30 min |
Wariacja używa salt=0. Wynik to sekundy od północy — może przekroczyć 24h, co jest obsługiwane w activity_duration(EVT_SLEEP).
4. Maszyna stanów — harmonogram dnia
4.1 Rytm poranny (wszyscy)
SLEEP → [MORNING_SEX →] WAKEUP → BREAKFAST → (patrz 4.2–4.4)
MORNING_SEX jest opcjonalnym krokiem przed WAKEUP. Warunki wystąpienia:
- Para kohabitująca (partner w tym samym lokalu,
home_unit_ididentyczne) - Wiek mężczyzny: 20–35 lat
- Oboje należą do tej samej grupy godzin wstania (patrz tabela poniżej)
- Prawdopodobieństwo: 15% dziennie
Grupy godzin wstania (same_wakeup_group):
| Grupa | Statusy | Godzina bazowa |
|---|---|---|
| 0 | EMPLOYED | 6:30 |
| 1 | STUDENT, HIGHER_EDU | 7:00 |
| 2 | CHILD | 7:30 |
| 3 | UNEMPLOYED, RETIRED | 8:00 |
Symetria: decyzja opiera się na shared_id = min(A.id, B.id) i salt 77 — oboje obliczają identyczną wartość prand(), więc albo oboje wchodzą w zdarzenie, albo żadne.
Czas trwania: 5–15 minut (M(5) + prand(id, dzien, 78) % (M(10)+1)). Lokalizacja: home_unit_id (własny lokal). Następna aktywność: EVT_WAKEUP.
4.2 Ścieżka pracującego
BREAKFAST → COMMUTE_TO_WORK → WORK_* → WORK_BREAK → WORK_* → COMMUTE_FROM_WORK
→ (80%) HOME_REST / (20%) GROCERY_SHOPPING → HOME_REST → ...
- Po przyjeździe do pracy typ aktywności zależy od typu organizacji pracodawcy:
| Typ budynku pracodawcy | Aktywność |
|---|---|
BTYPE_INDUSTRIAL | EVT_WORK_FACTORY |
BTYPE_SHOP_GROCERY, BTYPE_SHOP_OTHER | EVT_WORK_SHOP |
BTYPE_SERVICE, BTYPE_MEDICAL | EVT_WORK_SERVICE |
| Pozostałe | EVT_WORK_OFFICE |
- Pierwszy blok pracy kończy się przed 12:00 → następuje przerwa (
EVT_WORK_BREAK). - Drugi blok pracy kończy się po 12:00 → następuje powrót do domu (
EVT_COMMUTE_FROM_WORK). - Po powrocie z pracy: 20% szans na zakupy (
EVT_GROCERY_SHOPPING), reszta →EVT_HOME_REST. Decydujeprand(id, dzien, salt=20) % 5 == 0.
4.3 Ścieżka ucznia / studenta
BREAKFAST → COMMUTE_TO_SCHOOL → SCHOOL_CLASS/UNIVERSITY_CLASS
→ SCHOOL_BREAK → SCHOOL_CLASS → COMMUTE_FROM_SCHOOL → HOME_LEARNING → HOME_REST → ...
- Student wyższej uczelni (
STATUS_HIGHER_EDU) →EVT_UNIVERSITY_CLASSzamiastEVT_SCHOOL_CLASS. - Przerwa szkolna odpala się przed 11:00 (dla uczniów) lub przed 12:00 (dla studentów).
- Po powrocie ze szkoły: zawsze
EVT_HOME_LEARNING(odrabianie lekcji) → potemEVT_HOME_REST.
4.4 Ścieżka dzieci, bezrobotnych, emerytów
BREAKFAST → HOME_REST → (wieczorem) DINNER → WATCH_TV (em./bezr.) lub HOME_REST → FALLING_ASLEEP → SLEEP
4.5 Wieczorny rytm (wszyscy)
HOME_REST → DINNER → HOME_REST (lub WATCH_TV) → FALLING_ASLEEP → SLEEP
- Emeryci i bezrobotni: zawsze
EVT_WATCH_TV. Pozostali (pracujący, studenci, dzieci w wieku ≥ 12 lat): 65% →EVT_WATCH_TV, 35% →EVT_HOME_REST(salt=79). EVT_FALLING_ASLEEPtrwa stałe 20 minut, potemEVT_SLEEP.
5. Czasy trwania aktywności
| Aktywność | Czas bazowy | Wariacja | Salt |
|---|---|---|---|
EVT_WAKEUP | 15 min | ±5 min | 1 |
EVT_BREAKFAST | 30 min | ±10 min | 2 |
EVT_WORK_OFFICE/FACTORY/SHOP/SERVICE | 4 h | ±20 min | 4 |
EVT_WORK_BREAK | 45 min | ±10 min | 5 |
EVT_SCHOOL_CLASS | 2 h 30 min | ±15 min | 6 |
EVT_SCHOOL_BREAK | 15 min | — | — |
EVT_UNIVERSITY_CLASS | 2 h | ±15 min | 7 |
EVT_HOME_LEARNING | 2 h | ±30 min | 8 |
EVT_GROCERY_SHOPPING | 30 min | ±10 min | 9 |
EVT_DINNER | 45 min | ±10 min | 10 |
EVT_FALLING_ASLEEP | 20 min | — | — |
Dojazdy
Czas dojazdu oblicza travel_time(miasto, unit_A, unit_B) — na podstawie odległości euklidesowej między lokalami. Minimum: 3 min, maksimum: 60 min.
Sen (EVT_SLEEP)
Trwa od t do następnej godziny wstania:
- Jeśli godzina wstania jest jeszcze dziś →
czas_wstania_dzis - t. - Jeśli godzina wstania już minęła →
czas_wstania_jutro - t.
HOME_REST
Czas do najwcześniejszego z:
- godziny kolacji:
18:00 ± 30 min(salt=11) - godziny snu:
22:30 ± 30 min(salt=12) - jeśli obie minęły: 5 minut
Jeśli osoba ma zaplanowane spotkanie (plans[id].meet_time > 0):
- PLAN_COHABIT / PLAN_HOST: czekamy do
meet_time(skrócenie jeśli krótsze od normalnego). - PLAN_GUEST: wychodzimy wcześniej o czas dojazdu do lokalu partnera.
WATCH_TV
Trwa do godziny snu (22:30 ± 30 min, salt=13). Jeśli poza planem snu → 5 minut. Skracane do meet_time jeśli jest plan spotkania.
6. Seks — czas trwania
Czas trwania zależy od wieku i charakteru relacji.
| Wiek | Z partnerem / kochanką | Z małżonkiem (REL_SPOUSE) |
|---|---|---|
| < 30 lat | 30–45 min | 25–40 min |
| 30–39 lat | 25–35 min | 20–30 min |
| 40–49 lat | 20–30 min | 15–25 min |
| 50–59 lat | 15–25 min | 10–20 min |
| ≥ 60 lat | 10–20 min | 5–15 min |
Reguły kwalifikacji:
EVT_SEX_HOME+rel_type == REL_SPOUSE→ czas z małżonkiem.EVT_SEX_AWAY→ zawsze czas z partnerem / kochanką (niezależnie od rel_type).EVT_SEX_HOME+ inne rel_type → czas z partnerem.
Salty: 30 (SEX_HOME), 31 (SEX_AWAY), 32 (SEX_HOST), 33 (SEX_GUEST). EVT_SEX_HOST i EVT_SEX_GUEST używają tych samych przedziałów co SEX_HOME/AWAY.
7. Planowanie dziennych spotkań (plan_daily_meeting)
Wywoływane przy EVT_WAKEUP. Planuje spotkanie seksualne na dany dzień.
7.1 Wybór partnera
- Romans (
affair_partner_id != 0) ma priorytet przed stałym partnerem. - Fallback: stały partner (
partner_id). - Brak partnera → brak planu.
7.2 Rola: COHABIT / HOST / GUEST / AWAY
- COHABIT: oboje mieszkają pod tym samym adresem (
home_unit_ididentyczne) i brak romansu. - HOST / GUEST (inny dom lub romans):
- Jeśli kobieta jest uczennicą/studentką → mężczyzna zawsze gospodarzem (
PLAN_HOST). - W pozostałych przypadkach: losowo wg
prand(min(A.id, B.id), d, salt=43) % 2. - AWAY (hotel/klub) — nadpisuje HOST/GUEST w dwóch scenariuszach (patrz 7.6).
7.3 Wspólny seed
Oboje partnerzy niezależnie obliczają plan. Używają shared_id = min(osoba->id, partner->id), dzięki czemu wyliczają identyczny meet_time i meet_loc bez żadnej komunikacji.
7.4 Czas spotkania — reguły wg statusu mężczyzny w parze
| Warunek | Przedział czasu |
|---|---|
| Mężczyzna: uczeń/student < 24 lat | 11:00–17:00 |
| Mężczyzna: uczeń/student ≥ 24 lat | 14:00–22:00 |
Romans + mężczyzna żonaty (REL_SPOUSE) | 17:00–22:00 |
| Mężczyzna żonaty (spotkanie z żoną) | 20:00–23:00 |
| Pozostałe | 19:00–22:00 |
Czas dokładny: d + meet_start + prand(shared_id, d, salt=44) % meet_range.
7.5 Lokal spotkania
- COHABIT: własny dom (
home_unit_idinicjatora). - HOST: własny dom gospodarza.
- GUEST: dom gospodarza (
meet_loc = gospodarz->home_unit_id). - AWAY:
meet_loc = 0(placeholder; docelowo id hotelu/klubu).
7.6 Seks w hotelu/klubie (PLAN_AWAY / EVT_SEX_AWAY)
Oboje partnerzy wyjeżdżają do miejsca neutralnego i wracają zaraz po seksie (nigdy nie nocują).
Scenariusz A — romans między małżonkami: romans (is_affair == 1), oboje mają współmałżonka i z nim mieszkają (rel_type == REL_SPOUSE + home_unit_id == partner_home). Dom żadnej ze stron nie jest dostępny → hotel obowiązkowy.
Scenariusz B — casual dating młodych: brak romansu, oboje < 26 lat, rel_type == REL_NONE u obojga. Prawdopodobieństwo hotelu: 25% pn–pt, 50% sob–ndz (prand(shared_id, d, salt=62) % 100). Jeśli nie wylosowano hotelu → standardowy HOST/GUEST.
Łańcuch stanów dla każdej strony:
HOME_REST → EVT_TRAVEL_TO_PARTNER → EVT_SEX_AWAY → EVT_MORNING_RETURN → EVT_HOME_REST
Czas trwania EVT_TRAVEL_TO_PARTNER: travel_time(home, meet_loc=0) = MIN_TRAVEL_SECS = 3 min (placeholder).
8. Synchronizacja COHABIT (force_cohabit_sex)
Gdy osoba A z rolą PLAN_COHABIT wchodzi w EVT_SEX_HOME, partner B może być jeszcze w innej aktywności. Zamiast czekać aż B sam dojdzie do meet_time, wymuszamy B natychmiast.
Mechanizm stale event:
- Inkrementujemy
partner->sched_gen. - Stare zdarzenie B w schedulerze (z poprzednim
gen) zostanie pominięte. - Wstawiamy nowe
EVT_HOME_RESTdla B zczas_koncaidentycznym jak A.
Dzięki temu oboje kończą seks jednocześnie → act_count[EVT_SEX_HOME] jest zawsze parzyste.
Wyjątek: jeśli B jest aktualnie w EVT_SEX_HOST, EVT_SEX_GUEST lub EVT_WAIT_FOR_PARTNER (romansuje) → nie przerywamy.
9. Stale event detection
Każda osoba ma pole sched_gen (licznik generacji). Każde zdarzenie w schedulerze niesie ze sobą gen wstawionego zdarzenia.
W sim_process_event(): jeśli item->gen != osoba->sched_gen → zdarzenie jest stale i jest pomijane.
Używane wyłącznie przez force_cohabit_sex() do unieważnienia starych zdarzeń partnera.
10. Zakończenie seksu jako gość
Po EVT_SEX_GUEST (seks u partnera w jego domu):
- 80%:
EVT_STAY_OVERNIGHT→ nocuje → ranoEVT_MORNING_RETURN→EVT_HOME_REST. - 20%:
EVT_MORNING_RETURNod razu →EVT_HOME_REST.
Decyduje prand(id, dzien, salt=50) % 5 < 4.
11. Ochrona przed romansem partnera (sprawdzenie planu)
W next_activity(EVT_HOME_REST) i next_activity(EVT_WATCH_TV) dla PLAN_COHABIT, przed wejściem w EVT_SEX_HOME sprawdzamy:
- Czy partner jest aktualnie w aktywności seksualnej (
EVT_SEX_HOST,EVT_SEX_GUEST,EVT_WAIT_FOR_PARTNER) → pomiń. - Czy partner ma romans zaplanowany na dziś (
plans[partner.id].role == PLAN_HOSTlubPLAN_GUESTzmeet_time > 0) → pomiń.
Cel: uniknięcie sytuacji gdy A wchodzi w SEX_HOME z B, a B zaraz wejdzie w SEX z kimś trzecim (romans).
12. Czyszczenie planu po spotkaniu
Plan (plans[osoba->id].meet_time) jest zerowany gdy:
EVT_SEX_HOSTodpala się (gospodarz zakończył seks),EVT_SEX_HOMEodpala się (współmieszkańcy zakończyli seks),EVT_MORNING_RETURNodpala się (gość wrócił do domu).
13. Lokalizacja osoby podczas aktywności (LOC_STREET vs LOC_UNIT)
Osoba jest LOC_STREET (w drodze) podczas:
EVT_COMMUTE_TO_WORKEVT_COMMUTE_FROM_WORKEVT_COMMUTE_TO_SCHOOLEVT_COMMUTE_FROM_SCHOOLEVT_TRAVEL_TO_PARTNEREVT_MORNING_RETURN
We wszystkich pozostałych aktywnościach: LOC_UNIT (w konkretnym lokalu).
14. Inicjalizacja (sim_init_all)
Na starcie dla każdej osoby:
- Stan: śpi (
EVT_SLEEP), jest w domu (LOC_UNIT,home_unit_id). - Obliczana jest godzina wstania na bieżący dzień.
- Jeśli godzina wstania już minęła → planowane na jutro (
+86400s). - Do schedulera wstawiane jest
EVT_WAKEUP.
15. Harmonogram weekendowy
15.1 Obiad (sobota i niedziela)
- Dotyczy par współmieszkających (
home_unit_ididentyczne,partner_id > 0). - Czas: losowo 13:00–15:00, synchronizowany przez
shared_id = min(A.id, B.id)→ oboje mają identyczny czas. - Salt=45. Aktywność:
EVT_LUNCH(≈60 min ± 15 min, salt=14). - Dzieci nie dostają własnego zdarzenia obiadu — są w domu podczas
HOME_REST.
15.2 Zakupy sobotnie
- Dotyczy: kobiet (
GENDER_FEMALE) powyżej 18 lat. - Prawdopodobieństwo: 70% (
prand(id, d, 46) % 10 < 7). - Czas: losowo 9:00–13:00 (salt=47). Aktywność:
EVT_GROCERY_SHOPPING.
15.3 Nauka domowa — niedziela
- Dotyczy: dzieci i uczniów (
STATUS_CHILD,STATUS_STUDENT). - Prawdopodobieństwo: 70% (salt=55).
- Czas: losowo 10:00–12:00 (salt=56). Aktywność:
EVT_HOME_LEARNING.
15.4 Seks sobotni (pary COHABIT)
Romanse (affair_partner_id > 0) mają priorytet i działają wg reguł weekday (HOST/GUEST), nie weekendowych.
| Typ pary | Prawdopob. | Slot | Czas |
|---|---|---|---|
Bez dzieci (children_count == 0) | 90% (salt=48) | Rano lub wieczór (50/50, salt=57) | Rano: wakeup + 60–120 min; Wieczór: 16–23 (po kolacji) |
| Z dziećmi | 70% (salt=48) | Tylko wieczór | 16–23 (po kolacji) |
Rano: czas = wakeup_tod + M(60) + prand(58) % M(60), cappowany do shopping_time - M(30) (jeśli kobieta ma zakupy) lub do 12:00.
Wieczór: surowy czas 16:00–23:00 (salt=49) podnoszony do pora_kolacji + M(60), żeby kolacja zawsze była przed seksem. Max 22:30.
Flaga sat_sex_morning = 1 oznacza poranny slot.
15.5 Seks niedzielny (pary COHABIT)
- Dotyczy: osoby ≥ 19 lat, które nie miały seksu w sobotę (
sat_had_sex[id] == 0). - Prawdopodobieństwo: 80% (salt=59).
- Czas: 16:00–23:00 (po kolacji, ta sama logika przesunięcia co sobota).
Flaga sat_had_sex[id]:
- Reset przy
EVT_WAKEUPw sobotę. - Set = 1 przy
EVT_SEX_HOMEw sobotę. - Czytana przy planowaniu niedzielnym.
15.6 Przepływ stanów weekendowych
WAKEUP → BREAKFAST →
[sob, kobieta >18, 70%] → HOME_REST → GROCERY_SHOPPING →
[sob/ndz, para] → HOME_REST → LUNCH →
HOME_REST →
[sob/ndz, seks wieczorny] → SEX_HOME →
HOME_REST → DINNER → FALLING_ASLEEP → SLEEP
[sob, para bez dzieci, seks rano] → HOME_REST → SEX_HOME →
HOME_REST → (powyżej od GROCERY_SHOPPING)
[ndz, dzieci, 70%] → HOME_REST → HOME_LEARNING →
HOME_REST → LUNCH → ...
[sob/ndz, single 18–40, klub] → HOME_REST → CLUB_NIGHT →
[15%] → SEX_AWAY → HOME_REST → FALLING_ASLEEP
[85%] → HOME_REST → FALLING_ASLEEP
15.7 Klub nocny — szukanie przygodnego seksu (EVT_CLUB_NIGHT = 410)
Modeluje sobotnie i niedzielne wyjścia singli do klubów nocnych w poszukiwaniu jednorazowego kontaktu seksualnego.
Podstawa empiryczna (Gorzów Wlkp.): Miasto ma ~5 aktywnych klubów nocnych (Klub Studio, Pub Wesele, Viva Disco, Ósemka, MIXcoolTURA). Klub Studio opisywany jako odwiedzany przez „setki osób co tydzień"; pojemność większych lokali do ~500 os. Łączna frekwencja w sobotni wieczór: szacunkowo 1 500–2 500 os. Z tego ~20–30% aktywnie szuka przygody seksualnej. Źródło: [baza.mgbi.pl](https://baza.mgbi.pl/katalog/baza/baza-firm-gorzow-wielkopolski) + lokalne materiały prasowe (marzec 2026).
Kto uczestniczy:
- Status: dowolny (poza dziećmi — wiek ≥ 18)
- Wiek: 18–40 lat
- Relacja: brak stałego partnera (
partner_id == 0) i brak romansu (affair_partner_id == 0) - Dotyczy soboty i niedzieli
Prawdopodobieństwo wyjścia:
| Dzień | Prawdopob. | Salt |
|---|---|---|
| Sobota | 8% | 64 |
| Niedziela | 3% | 64 |
Godzina wyjścia:
- Sobota: losowo 20:00–23:00 (salt=65)
- Niedziela: losowo 20:00–22:00 (salt=65)
Zapisywane jako plan->meet_time, plan->role = PLAN_AWAY, plan->partner_id = 0, plan->meet_loc = 0. W next_home(): gdy plan->role == PLAN_AWAY && plan->partner_id == 0 → EVT_CLUB_NIGHT (zamiast EVT_TRAVEL_TO_PARTNER).
Czas trwania aktywności EVT_CLUB_NIGHT:
1h ± 30 min (salt=63). Osoba jest „w mieście" bez konkretnego lokalu (activity_unit = 0).
Wynik po wyjściu z klubu:
| Wynik | Prawdopob. | Następna aktywność | Salt |
|---|---|---|---|
| Znaleziono partnera | 15% | EVT_SEX_AWAY | 66 |
| Nic się nie wydarzyło | 85% | EVT_HOME_REST | 66 |
Seks przygodny (EVT_SEX_AWAY po EVT_CLUB_NIGHT):
- Czas trwania: jak standardowy
EVT_SEX_AWAY(tabela czas×wiek, salt=31, brak małżeństwa). - Lokalizacja:
meet_loc = 0(brak konkretnego lokalu). - Po seksie: bezpośrednio
EVT_HOME_REST(boplan->partner_id == 0; brakEVT_MORNING_RETURN). - Flaga
sat_had_sex: nie ustawiana (osoba jest singlem, nie wpływa na plan niedzielny).
Skala dla Gorzowa przy ~12 000 eligible singli:
| Miara | Sobota | Niedziela |
|---|---|---|
| Planuje wyjście | ~960 os. | ~360 os. |
W EVT_CLUB_NIGHT jednocześnie (21–01) | ~500–800 os. | ~180–300 os. |
W EVT_SEX_AWAY (przygodny) | ~140 os. | ~54 os. |
16. Poznanie na zakupach (try_shop_flirt)
Wywoływana przy EVT_GROCERY_SHOPPING. Modeluje przypadkowe poznanie się w sklepie spożywczym.
16.1 Warunki wstępne
- Osoba jest singlem (
partner_id == 0) - Wiek: 18–50 lat
- 5% szans na „spotkanie" kogoś w sklepie (salt=83,
prand % 100 < 5)
16.2 Wybór kandydata
Deterministyczny punkt startowy (salt=84), przeszukiwanie do 10 kolejnych osób po id. Kandydat musi spełniać:
- aktualnie w
EVT_GROCERY_SHOPPING - singiel (
partner_id == 0) - płeć przeciwna
- różnica wieku ≤ 12 lat
16.3 Nowy związek
- Kanoniczny inicjator: niższe
id - 10% szans na nowy związek (salt=85,
prand % 100 < 10)
Efekt: analogicznie do try_work_encounter — REL_PARTNER, rel_since_year, EVT_FIRST_MEETING.
17. Podryw w pracy (try_work_encounter)
Wywoływana przy EVT_WORK_BREAK. Modeluje rozmowę i ewentualne poznanie się dwóch współpracowników na przerwie.
17.1 Warunki wstępne
- Osoba jest singlem (
partner_id == 0) - Wiek: 18–55 lat
- Organizacja (
work_org_id) istnieje i ma ≥ 2 pracowników - 30% szans na zainicjowanie rozmowy (salt=79,
prand % 100 < 30)
17.2 Wybór kandydata
Deterministycznie wybierany z listy pracowników tej samej organizacji (salt=82). Przeszukiwanie do 5 kolejnych pozycji licząc od punktu startowego; kandydat musi aktualnie być w EVT_WORK_BREAK.
17.3 Kanoniczny inicjator i EVT_WORK_CHAT
Tylko osoba z niższym id loguje zdarzenie. Obie strony widzą to samo zdarzenie EVT_WORK_CHAT (od t_start do t_end przerwy).
17.4 Podryw i nowy związek
Warunki podrywu (wszystkie muszą być spełnione):
- różna płeć
- kandydat jest singlem (
partner_id == 0) - różnica wieku ≤ 10 lat
Dwa niezależne rzuty:
- 15% szans na podryw (salt=80,
prand % 100 < 15) - 8% szans że podryw kończy się związkiem (salt=81,
prand % 100 < 8)
Efekt: nowy REL_PARTNER — oboje otrzymują wzajemne partner_id, rel_type = REL_PARTNER, rel_since_year = rok bieżący. Logowany EVT_FIRST_MEETING.
Oczekiwana częstość: łącznie ~0.36% sesji EVT_WORK_BREAK zaowocuje związkiem.
18. Romanse w pracy (try_affair_start)
Wywoływana przy EVT_WORK_BREAK, po try_work_encounter(). Modeluje powstawanie nowych romansów pozamałżeńskich w miejscu pracy.
18.1 Warunki wstępne — mężczyzna
REL_SPOUSE(żonaty), wiek ≤ 32 lataffair_partner_id == 0(brak aktywnego romansu)- Pracuje w organizacji z ≥ 2 pracownikami
- 5% szans na próbę (salt=93,
prand % 100 < 5)
18.2 Wybór kandydatki
Deterministyczny punkt startowy (salt=94), przeszukiwanie do 10 kolejnych pozycji z listy pracowników org. Kandydatka musi spełniać:
- Kobieta, wiek ≤ 29 lat
partner_id == 0(singielka)affair_partner_id == 0(wolna)- Aktualnie w
EVT_WORK_BREAK(ta sama org, ta sama przerwa) - Różnica wieku: mężczyzna starszy o 1–3 lata (dokładnie)
kandydatka.education <= mężczyzna.education— mężczyźni romansują z kobietami o równym lub niższym wykształceniu; kobiety nie idą z mężczyznami o niższym
18.3 Start romansu
- 10% szans że romans faktycznie się zaczyna (salt=95,
prand % 100 < 10) - Skutek:
affair_partner_idustawiany obustronnie (mężczyzna ↔ kandydatka) - Logowany
EVT_AFFAIR_START = 508(P1=mężczyzna, P2=kochanka)
EVT_AFFAIR_END = 509 jest logowany w try_breakup w momencie konwersji kochanki na stały związek (P6).
19. Rozstania i rozwody (try_breakup)
Wywoływana przy EVT_WAKEUP gdy osoba ma partnera. Kanoniczny inicjator: niższe id (dzięki temu każda para sprawdzana raz).
18.1 Kwalifikacja do rozstania
Trzy ścieżki kwalifikacyjne (pierwsza pasująca wygrywa):
| Scenariusz | Warunek | Prawdopobieństwo/dzień | Salt |
|---|---|---|---|
| Romans | mężczyzna ma kochankę bez innego partnera | 0.3% (% 1000 < 3) | 86 |
| Kohabitacja | razem ≥ 7 lat I (brak dzieci LUB najmłodsze ≥ 17 lat) | 0.05% (% 2000 < 1) | 87 |
| Osobne domy | 5–8 lat stażu I oboje bezdzietni | 0.1% (% 1000 < 1) | 87 |
18.2 Fallback — szukanie lokalu (P4)
Tylko dla kohabitacji bez romansu: przed rozstaniem szukamy wolnego lokalu mieszkalnego dla mężczyzny (30 losowych prób, salt=88). Brak wolnego lokalu → rozstanie nie zachodzi.
18.3 Skutki rozstania
- Zerowanie pól związku:
partner_id = 0,rel_type = REL_NONE,rel_since_year = 0u obojga. - Logowany
EVT_DIVORCE(byli małżonkowie,REL_SPOUSE) lubEVT_BREAKUP(partnerzy,REL_PARTNER). - Mężczyzna przy kohabitacji bez romansu przenosi się do znalezionego lokalu;
sched_gen++.
18.4 Konwersja romansu w związek (P6)
Gdy rozstanie spowodowane romansem:
- romans → nowy
REL_PARTNER(wzajemnepartner_id,rel_since_year = rok bieżący) - mężczyzna przenosi się do domu kochanki (jeśli wcześniej kohabitował)
- stare zdarzenie mężczyzny unieważnione:
sched_gen++ - logowany
EVT_PARTNER_MOVES_IN
18.5 Opieka nad dziećmi po rozstaniu (P5)
Każde dziecko pary (z obu tablic children[]) jest rozpatrywane niezależnie:
- 5% szans z ojcem (
prand(child_id, dzien, 88) % 100 < 5) - 95%: dziecko zostaje z matką (
home_unit_idbez zmian)
19. Ślub (try_marry)
Wywoływana przy EVT_WAKEUP. Sprawdza czy para REL_PARTNER powinna wziąć ślub. Kanoniczny inicjator: niższe id.
19.1 Prawdopodobieństwo ślubu
Zależy od stażu (rel_since_year → rok bieżący):
| Staż | Próg | Prawdopobieństwo/dzień | Skumulowane |
|---|---|---|---|
| < 2 lata | % 14000 < 1 | ~0.007% | ~5% w 2 latach |
| 2–5 lat | % 578 < 1 | ~0.17% | ~85% w tym przedziale |
| 5–7 lat | % 664 < 1 | ~0.15% | ~66% z pozostałych |
| ≥ 7 lat | % 50 < 1 | 2% | domknięcie 100% |
Salt: 89.
19.2 Skutki ślubu
rel_type = REL_SPOUSEu obojgamarriage_day = day_since_1960(t)u obojga (dni od 1960-01-01)- Logowany
EVT_WEDDING
20. Przeprowadzka po ślubie (try_move_in_after_wedding)
Wywoływana przy EVT_WAKEUP. Mężczyzna wprowadza się do domu kobiety. Kanoniczny inicjator: niższe id.
Warunki: REL_SPOUSE, marriage_day > 0, oboje żyją osobno (home_unit_id != partner->home_unit_id).
20.1 Harmonogram przeprowadzki
| Dzień od ślubu | Prawdopobieństwo | Wzór |
|---|---|---|
| 1 | 30% | prand % 10 < 3 |
| 2 | ~14% | prand % 7 < 1 |
| 3 | ~17% | prand % 6 < 1 |
| 4 | 20% | prand % 5 < 1 |
| 5 | 25% | prand % 4 < 1 |
| 6 | ~33% | prand % 3 < 1 |
| 7 | 50% | prand % 2 < 1 |
| ≥ 8 | 100% | zawsze |
Salt: 90.
20.2 Skutki przeprowadzki
- Mężczyzna:
home_unit_id = kobiety->home_unit_id - Zaktualizowane
occupant_countobu lokali (stary -1, nowy +1) - Jeśli mężczyzna był aktualnie w starym domu:
current_unit_idzaktualizowane - Jeśli mężczyzna ma wyższe
idniż inicjator:sched_gen+++EVT_HOME_RESTod razu - Logowany
EVT_PARTNER_MOVES_IN
21. Narodziny dziecka (try_birth)
Wywoływana przy EVT_WAKEUP (dla kobiet zamężnych kohabitujących). Zwraca czas końca porodu lub 0.
21.1 Warunki
GENDER_FEMALEREL_SPOUSE+partner_id != 0marriage_day > 0- Para kohabituje (
home_unit_id == partner->home_unit_id) children_count < 6
21.2 Okno porodu
| Numer dziecka | Okno | Przybliżenie |
|---|---|---|
Pierwsze (last_birth_day == 0) | marriage_day + 300 … marriage_day + 912 | 10 mies.–2,5 roku po ślubie |
| Kolejne | last_birth_day + 450 … last_birth_day + 1642 | 15–54 mies. po poprzednim |
Salt: 91. Poza oknem → brak rzutu.
21.3 Prawdopodobieństwo
prand(osoba->id, dzien, 91) % 1250 == 0 → ~0.08%/dzień w oknie.
21.4 Czas trwania porodu
| Godzina rozpoczęcia | Czas końca (birth_end) | Efekt |
|---|---|---|
| Przed 10:30 | Następny dzień 09:00 | Kobieta pomija EVT_WAKEUP dnia+1 → pełny dzień odpoczynku |
| Po/o 10:30 | Następny dzień losowo 14:00–17:00 (salt=92) | Wstaje późno, do końca dnia HOME_REST |
Mechanizm: try_birth zwraca birth_end != 0 → wywołujący (sim_process_event, blok EVT_WAKEUP) nadpisuje nastepna_aktywnosc = EVT_HOME_REST i czas_konca = birth_end.
21.5 Skutki narodzin
children_count++u obojga (matka i ojciec)last_birth_day = day_since_1960(t)u obojga- Logowany
EVT_BIRTH(czas odtdobirth_end)
22. Kalendarz szkolny (sim_calendar)
Moduł src/sim_calendar.c (nagłówek include/sim_calendar.h) dostarcza funkcje klasyfikujące dzień jako szkolny lub wolny. Wywoływane z EVT_BREAKFAST w sim_schedule.c.
22.1 Polskie święta stałe
| Data | Święto |
|---|---|
| 1 stycznia | Nowy Rok |
| 6 stycznia | Trzech Króli |
| 1 maja | Święto Pracy |
| 3 maja | Święto Konstytucji |
| 15 sierpnia | Wniebowzięcie NMP |
| 1 listopada | Wszystkich Świętych |
| 11 listopada | Niepodległość |
| 24 grudnia | Wigilia (od 2025 roku) |
| 25 grudnia | Boże Narodzenie |
| 26 grudnia | Drugi dzień BN |
Wielkanoc pominięte (ruchome, uproszczenie modelu).
22.2 Przerwa świąteczna (Boże Narodzenie)
- Zaczyna się w sobotę poprzedzającą 24 grudnia (poprzez wyznaczenie dnia tygodnia 23 grudnia).
- Kończy się 31 grudnia (włącznie).
22.3 Przerwa zimowa (ferie)
Algorytm: spośród kandydatów (poniedziałki od 7 stycznia do 1 marca) szukamy 14-dniowego okna z największą liczbą dni roboczych (Pn–Pt, bez świąt) przypadających w lutym. Przy remisie preferowany jest późniejszy start. Wynik jest cachowany per rok.
22.4 Rok szkolny — start
1 września, chyba że wypada w weekend lub jest świętem — wtedy następny dzień roboczy.
22.5 Wakacje letnie — koniec roku szkolnego
| Typ szkoły | Klasa | Koniec zajęć |
|---|---|---|
Liceum (BTYPE_SCHOOL_SECONDARY=4) | Klasa 4 (matura) | Ostatni piątek roboczy kwietnia |
Technikum (BTYPE_SCHOOL_TECHNIKUM=14) | Klasa 5 (matura) | Ostatni piątek roboczy kwietnia |
| Wszystkie pozostałe | — | Pierwszy piątek ≥ 21 czerwca |
Klasa 8 szkoły podstawowej nie ma odrębnej daty końca roku — kończy zajęcia razem z pozostałymi klasami podstawówki. Historyczna zasada kończenia w środę (sprzed 2001 r.) nie jest modelowana.
Wakacje trwają od pierwszego dnia po ostatnich zajęciach do dnia przed startem nowego roku szkolnego.
22.6 Studenci uczelni wyższych
| Tryb | Dni zajęć | Rok akademicki |
|---|---|---|
Dzienne (cal_uni_fulltime_day) | Pn–Pt (bez świąt) | 1 październik – koniec czerwca |
Zaoczne (cal_uni_parttime_day) | Sb–Nd (bez świąt) | od soboty przed pierwszym roboczym poniedziałkiem października |
Ustalanie trybu (bez nowego pola w strukturze):
EDU_HIGHER_MED→ zawsze dzienneage > 28→ zawsze zaoczne- Pozostali → dzienne
Tryb dzienny/zaoczny oblicza stu_is_parttime(age, education) z sim_student.c. Rok akademicki przechowywany w tablicy cal_table[] inicjalizowanej przy starcie demona.
22.7 Przedszkola i zerówka
cal_preschool_day(t, age):
- Przedszkola czynne w dni robocze (Pn–Pt), bez świąt, cały rok (brak ferii zimowych).
- Wyjątek: dzieci w wieku 6 lat (zerówka) mają wakacje letnie identyczne z klasą 1 szkoły podstawowej (pierwszy piątek ≥ 21 czerwca → wrzesień).
22.8 Typy szkół
| Stała | Wartość | Opis |
|---|---|---|
BTYPE_SCHOOL_PRIMARY | 3 | Szkoła podstawowa, klasy 1–8 |
BTYPE_SCHOOL_SECONDARY | 4 | Liceum ogólnokształcące, klasy 1–4 |
BTYPE_SCHOOL_TECHNIKUM | 14 | Technikum, klasy 1–5 |
BTYPE_SCHOOL_ZSZ | 18 | Zasadnicza szkoła zawodowa / branżowa I st., klasy 1–3 (wiek 15–17) |
BTYPE_SCHOOL_POSTSECONDARY | 19 | Szkoła policealna, grupy 1–2 (wiek 20–21, po maturze) |
BTYPE_UNIVERSITY | 5 | Uczelnia wyższa |
BTYPE_PRESCHOOL | 12 | Przedszkole (STATUS_PRESCHOOL, wiek 3–5) |
BTYPE_NURSERY | 13 | Żłobek (STATUS_CHILD z class_id > 0, wiek 0–2) |
W generatorze: wiek 15–18 → 50% liceum / 50% technikum; wiek 19 → wyłącznie technikum (klasa 5).
Żłobki uczęszczają tylko niemowlęta spełniające trzy kryteria: (1) wiek 0–2, (2) oboje rodzice STATUS_EMPLOYED, (3) oboje rodzice EDU_SECONDARY lub EDU_HIGHER (nie EDU_HIGHER_MED). Harmonogram żłobkowy identyczny jak przedszkolny (EVT_PRESCHOOL, cal_preschool_day()). Rodzice obsługiwani przez city_has_young_child() — analogicznie jak rodzice przedszkolaków.
