five-on-it / packages/ai/src/crowd
packages/ai/src/crowd
The crowd (GAME_DESIGN §5.6): pedestrians with roles kept around the players (or the AI's stand-ins while nobody is in the room: traffic.ts' viewersOf), a number the server sets (setCrowd), the way the traffic keeps its cars. Who is out is decided here; how each walks (its role on the pavements, fleeing gunfire, a shopkeeper ducking inside) is the simulation's pedestrian system.
- Spawned near the players: on a node of the level's pavements (
@foi/world'spavementsOf) between CrowdOptions.spawnMin andspawnMaxmetres of the nearest player, never on a scrap of pavement too small to walk, never on top of somebody; at most one a tick, with a role drawn from ROLE_MIX, or from the roles the level's district there suggests (LevelData.districts[].pedestrians: a tech campus's commuters and joggers, an old town's shopkeepers). A shopkeeper takes a door nobody keeps (in range, not just left) and stands at it. - Despawned far away: a pedestrian farther than
despawnfrom every player goes, and with nobody on the server they all do. A shopkeeper who went inside (gunfire) goes too, and its door stays empty for CROWD'sdoorAwaybefore another takes it. - A level without pavements (no roads) gets its crowd in the open cross around the centre instead, wandering as pedestrians did before the pavements.
- By the hour (the room clock, GAME_DESIGN §5.6): fewer people at night (CROWD_HOURS' shares: while more are out than the hour wants, one a tick who is out of every player's near sight, beyond
spawnMin, goes home); joggers only mornings and evenings; shopkeepers only in shop hours, and in at their doors at closing; commuters thick at the rush hours, the morning's walking to work (a building's door, where they go in) and the evening's out of a door and home (a pavement away, where they go in too). - The city's routines: ROUTINE_SHARE of the newcomers come out for a routine instead (ROUTINE_MIX, by the hour of CROWD_HOURS; a district's mix that names routines gets those): a dog walker, a street sweeper (at dawn), an officer on its beat anywhere on the pavements; a smoker beside a door nobody keeps (out of its way); a vendor beside a kiosk's or a stall's counter nobody serves, in shop hours; a queuer at the end of a bus stop's line (four at most), while the buses run; a sitter on its way to a bench nobody sits on or makes for (
@foi/world's spots). A routine with no free place is no routine: the newcomer comes from the ordinary mix. - The dogs (the simulation's
dogs.tsruns them: NPCs of their own): a dog comes out with every dog walker, on its lead beside it, and where there are pavements a few strays are kept around the players as the people are (CROWD'sstrays, one for everystrayPerpeople the hour wants). They are no people: kept in a list of their own (listCrowdDogs), outside the number the server sets and the people's readout. A dog goes with its walker when that is taken off the street (near it or on its lead; one that ran off is freed, a stray from then on); far from every player it goes like anybody; a dead one lies until no player is withinspawnMinof it, then its body is taken away (a dog never comes back at a post). The people are put out as if the dogs were not there (no dog keeps a spot from a person, and the strays are drawn on a stream of their own), so the same people come out with the dogs as without them.
Everything runs on the crowd's own random streams (the people's, and the strays'), in a fixed order (the people by entity id), so two worlds fed the same inputs keep the same crowd, which hashCrowd feeds into hashAiState.