#ifndef PEOPLE_AI_H #define PEOPLE_AI_H /* * Behaviour of the other people in the world. * * idle : stands around, turns towards the player when near * wander : strolls to a random spot around home, avoiding obstacles * help : walks beside a leader; when the leader grabs something it finds * a free spot at the object, grabs too and pushes / pulls along * fetch : walks to a beer bottle and picks it up * drink : takes a sip or two, then puts the bottle down * wake : someone passed out drunk for a while: goes over and shakes them awake * needs : sleeps when tired, eats and drinks (lying food and bottles, or * at the apple crate and water barrel), walks off for a pee * tidy : people who like things clean pick up trash they pass and drop * it in the container when they're not busy * help : (also) when it's not clear what to do: takes something like what * the leader carries, walks along with it and does the same with it * (puts it down next to theirs, into the fire, into the bin) * help : (also) understands the leader's wood work and carries it on: * fells with them, takes the branches off, cuts and splits what * lies around; fetches fitting tools; rests when worn out * work : an order of their own: makes firewood of the wood around a * place (and fells more trees if asked), then stacks it on the * woodpile they were shown; collects the trash with a garbage * bag and takes it to the container; looks after the fire (keeps * wood in it, lights it when it gets dark, sits by it) * person : everyone has their own character: jobs they like or hate (they * are quicker at what they like), how willing they are to do what * they're asked, and a few words about themselves. Tired or drunk, * they say no more often. They suggest jobs that need doing * pace : and their own way of working: quick or slow, thinking things * over before starting on them or getting right to it, and breaks * now and then (none, sitting down, a little walk, a chat) * follow : being shown something: how to make firewood (watches until * they get it) or where the woodpile goes (follows you there) * talk : walks up to the player to offer help, ask what to do, or ask * where the firewood should go; how chatty depends on temperament. * Out of work only because the player has the axe: the bold ask * for it, the others wait for it to be put down * * Steering looks ahead along a few directions and takes the first free one, * so people walk around boxes, trees and each other instead of into them. */ #include #include "math/linalg.h" struct Object; typedef enum { AI_IDLE, AI_WANDER, AI_HELP, AI_FETCH, AI_DRINK, AI_WAKE, /* goes over to someone asleep and shakes them awake */ AI_SUPPLY, /* eats or drinks at the apple crate / water barrel */ AI_PEE, /* walks off a bit for a pee */ AI_WORK, /* on an order: firewood (and more trees) on their own */ AI_FOLLOW, /* being shown something by the player */ AI_APPROACH, /* walks up to the player to say something */ AI_TABLE, /* over to a free chair at a table: sits a while, eats or drinks what they have there */ } AiMode; typedef enum { ORDER_NONE, ORDER_FIREWOOD, ORDER_TREES, ORDER_TRASH, ORDER_FIRE, ORDER_COUNT } Order; /* How someone takes a break from work */ typedef enum { BREAK_NONE, BREAK_SIT, BREAK_WALK, BREAK_CHAT, BREAK_COFFEE } BreakKind; /* Who someone is */ typedef struct { float likes[ORDER_COUNT]; /* -1 hates the job .. 1 loves it */ float willing; /* 0 = only what they fancy .. 1 = whatever they're asked */ float skill[ORDER_COUNT]; /* how good they are at it to begin with (0..1) */ const char *about; /* a few words about themselves */ /* How they work */ float tempo; /* 1 = normal; quicker strokes and steps above, slower below */ float ponder; /* seconds they think it over before starting on something */ BreakKind break_kind; /* what they do for a break ... */ float break_every; /* ... after about this many seconds of work ... */ float break_length; /* ... for about this long */ } Character; /* What someone walks up to the player to talk about */ typedef enum { TOPIC_NONE, TOPIC_OFFER, TOPIC_ASK, TOPIC_SUGGEST, TOPIC_WHERE, TOPIC_ASK_HAND, TOPIC_TOOL } Topic; typedef enum { SHOW_NONE, SHOW_HOW, SHOW_PLACE } Showing; #define AI_SPEECH_MAX 80 #define AI_SKIPS 4 /* things they remember they couldn't get at */ #define AI_PATH_MAX 24 /* waypoints (see world/nav.h) */ typedef struct { bool ready; AiMode mode; struct Object *leader; /* AI_HELP */ struct Object *target; /* AI_FETCH / AI_DRINK: the bottle, AI_WAKE: the sleeper */ bool pushing; /* AI_HELP: holding the leader's object */ float settled; /* AI_HELP / AI_FOLLOW: arrived (or blocked close by): off again once the spot is further than this; 0 = not there */ Vec3 home; Vec3 goal; /* where we are walking to */ float timer; /* pause left / time in this mode */ float side; /* AI_HELP: -1 left of the leader, +1 right */ float detour; /* side we last walked around something (-1 / 1) */ Vec3 steer_dir; /* the way round an obstacle we're taking ... */ float steer_hold; /* ... for this much longer */ float boxed; /* no way through just now: wait this long before trying again (no dithering) */ Vec3 walk_dir; /* the way they walk (turns smoothly) */ const struct Object *steer_target; /* what we're walking up to ... */ float steer_best, steer_stall; /* ... closest so far, seconds without getting closer */ Vec3 path[AI_PATH_MAX]; /* a way round fixed things (when walking straight leads into a corner) */ int path_len, path_at; Vec3 path_goal; /* ... where it leads */ float path_none; /* no way there: don't look again for this long */ float watch_time; /* watchdog: seconds without anything happening ... */ Vec3 watch_pos; /* ... since here ... */ int watch_mode; /* ... in this mode / order / with this target and these things in hand */ const struct Object *watch_target, *watch_items[2]; int watch_count; float watch_job; /* job_time last frame (working on something counts as something happening) */ int watch_strikes; /* stuck again without anything happening in between */ float stuck; /* seconds without getting closer to the goal */ float closest; int sips_left; /* AI_DRINK: sips still wanted */ float table_stay; /* AI_TABLE: seconds they sit there ... */ float table_pause; /* ... till the next bite or sip ... */ float table_chat; /* ... and the next word with the others there */ bool resting; /* AI_HELP: worn out, catching breath */ struct Object *tool; /* AI_HELP: tool we are going to fetch for the leader's job */ struct Object *copied; /* AI_HELP: the leader's item we copy (got one like it, do the same with it) */ int copy_sort; /* ... what sort of thing it is */ int copy_step; /* ... 0 = carrying along, then putting it down / in the fire / in the bin */ Vec3 copy_put; /* ... where ours goes */ unsigned rng; /* Work orders and what this person knows */ Order order; /* AI_WORK */ Order pending; /* asked for, but first they need to be shown how */ Vec3 work_area; bool knows_wood; /* knows how to make firewood */ struct Object *woodpile; /* the woodpile they were shown (NULL = don't know one) */ bool no_pile; /* told to leave the firewood where it is */ Showing showing; /* AI_FOLLOW */ int seen_jobs; /* the player's finished jobs when the showing began */ struct Object *job_target; /* wood being worked on */ float job_time; struct Object *skip[AI_SKIPS]; /* didn't work out: leave these a while ... */ float skip_time[AI_SKIPS]; /* ... this much longer each */ float retry; /* lost the grip: wait a moment before trying again */ float jam_time; /* AI_HELP: the load doesn't move and we stand where it wants to go (seconds) */ float clear_time; /* ... so we keep off that side a while */ Vec3 clear_dir; /* ... (the way the load wants to go) */ Vec3 jam_from; /* (where the load was when we started to wonder) */ float shove_time; /* a pushed load has been shoving us this long (negative: a while not minding it) */ float dodge; /* stepping out of its way (seconds left) ... */ Vec3 dodge_dir; /* ... this way */ /* Talking */ Topic topic; /* AI_APPROACH: what they want to talk about */ bool ready_to_talk; bool talking; /* in a conversation: stands still and listens */ float talk_cooldown; char speech[AI_SPEECH_MAX]; Character character; Order suggested; /* TOPIC_SUGGEST: the job they suggest */ Vec3 pee_cover; /* AI_PEE: what they pee behind (face it, or squat with the back to it) ... */ bool pee_hidden; /* ... if there is something */ float annoyed; /* 0..1: left waiting for an answer, ignored; eases off over minutes */ bool wants_bag; /* at the garbage bags: the world hands them one */ struct Object *empty_tray; /* at a full ashtray: the world tips it out into their hand */ bool tool_asked; /* asked the player for their axe (once per order) */ float tidy_pause; /* bending down for trash on the way (seconds left) */ float tray_time; /* on the way to empty the ashtray this long */ struct Object *sort_from; /* sorting the crates (ai_help.c sortCrates): to this one for a bottle that doesn't belong ... */ struct Object *sort_bottle; /* ... carrying this one over to its own crate ... */ float sort_time; /* ... this long already ... */ float sort_look; /* ... and looking again for one in this long */ bool want_jacket; /* cold, the pullover put down somewhere: off to get it */ bool want_smokes; /* out of cigarettes, nobody gives one: off to the machine */ float smokes_time; /* ... on the way this long */ bool asked_you; /* asked the player for one (nothing came of it: the machine next time) */ struct Object *take_from; /* a bottle from this crate, or the next thing out of this car's boot: please (see car.c Car_serve) */ bool sheltering; /* in out of the rain (ai.c shelter) */ bool rain_seated; /* ... sat down to wait it out (the garages' kitchen, the shelter) ... */ int rain_place; /* ... which of those (Site_rainPlaces), + 1 (0: not chosen yet) */ bool greet; /* just arrived: over to the fire, saying hello, sitting there till the work starts ... */ bool greet_stand; /* ... no room on the benches: standing with the others here instead ... */ Vec3 greet_at; bool greet_asked; /* ... asked those on a bench to move up */ bool drying; /* wet through after the rain: sitting by the fire till dry */ bool timber; /* felling: waiting for somebody to get out from where it'll come down */ Vec3 dodge_to; /* warned off (a tree coming down): out to here ... */ float dodge_t; /* ... for this long */ struct Object *umbrella; /* rain: off to get this umbrella instead of going under a roof (ai.c shelter) */ float greet_left; /* just turned up: this long at the fire, then on with the day (0: till told otherwise) */ bool on_project; /* at work on their floor's stage (ai_project.c) ... */ float shift; /* ... game s into this go at it (then a break) ... */ float project_off; /* ... game s till they go back to it ... */ float held_up; /* ... game s it's been held up (material missing) ... */ struct Object *fetch; /* ... material they're bringing over to it (this long so far) */ float fetch_time; bool errand; /* off somewhere on purpose: errand_to (a shopping run: the car's driver door; showing the way: the spot) ... */ bool errand_there; /* ... and there */ Vec3 errand_to; struct Object *errand_with; /* ... showing whoever this is the way: waiting for them when they fall behind */ bool meeting; /* in Berlin: at a meeting (or there between weekends) - sitting, listening, nothing else */ float remark; /* ... real s till the next remark about it */ float praised; /* game s till a "great work" counts again */ struct Object *share; /* rain: walking under this one's umbrella, at their side ... */ float share_time; /* ... this long so far */ struct Object *blown; /* the wind took this out of their hand: after it (ai.c fetchBlown) ... */ float blown_t; /* ... this long already */ struct Object *hang_on; /* warm, the pullover round the waist: over this (a railing, a chair) it goes ... */ float hang_wait; /* ... and not thought of again for this long */ bool going_in; /* a resident on the way into the house (ai.c goInside) */ struct Object *tent_job; /* lending a hand with this tent (ai.c pitchTents) ... */ float tent_time; /* ... this long */ bool tent_said; /* ... said so */ bool unload; /* unloading the car (ai.c unloadCar) ... */ bool unload_rest; /* ... put it down for a breather */ struct Object *unload_car; float unload_time; /* ... on this trip this long */ float butt_time; /* holding a finished cigarette (Object.butt_held) this long ... */ bool butt_asked; /* ... and asked somebody for their pocket ashtray already */ int asking_you; /* asked the player for this (PocketNeed: a paper, a filter, tobacco), 0: nothing */ bool filter_asked; /* asked for a filter this time already (none: rolls one without) */ float jacket_time; /* ... on the way this long */ bool tool_waiting; /* waiting for the player to put the axe down */ unsigned char banned; /* tools (1 << ToolKind) they were told to leave alone ... */ unsigned char defies; /* ... and those they use anyway ("I know what I'm doing") */ unsigned char warned; /* tools they already said something about (using one they shouldn't) */ float risky; /* seconds until the next close call with a tool they shouldn't use */ float speech_time; float lighter_time; /* until they next think about lighters (give one back, ask for theirs) */ float lighter_ask; /* until they ask anybody for a lighter again */ struct Object *set_aside[2]; /* put down to pee: picked up again after */ /* Getting the work place ready (ai_work.c prepareSpot) */ struct Object *prep_for; /* the piece it was looked at for ... */ int prep_stage; /* ... PREP_* */ Vec3 prep_spot; /* ... where the work goes (moving it) */ struct Object *prep_item; /* ... what's being cleared away */ struct Object *prep_helper; /* ... who was called over to help move it */ float prep_time; bool chat_near; /* on a chat break: close enough (left again only well beyond) */ float hold_idle; bool hold_there; /* ... at the spot (stands there till pushed well off it) */ float ladder_dir; /* on a ladder: +1 going up, -1 down */ float ladder_seek; /* until they look for a way up / down again */ Order paused_order; /* called away from this job (to help): back to it after, or when reminded ... */ Vec3 paused_area; /* ... there */ float high_time; /* seconds up high (a roof) ... */ bool high_said; /* ... said something about it */ bool heights_said; /* told they won't go up there (once each time they're asked) */ float ladder_climb_t; /* seconds up a ladder that leads nowhere */ /* holding a ladder nobody is on: seconds of that (then they let go) */ float sun_heat; /* seconds of hard work in the midday sun (the shirt comes off) */ float sniff_cooldown; /* until the next remark about a smell */ AiMode before; /* mode to go back to after being shown something */ /* Their way of working */ const struct Object *task_seen; /* the last thing they thought over before starting on it */ float ponder; /* thinking it over (seconds left) */ float streak; /* seconds worked since the last break */ float on_break; /* on a break (seconds left) */ Vec3 break_from; /* BREAK_WALK: where they set out from (and come back to) */ bool break_back; /* ... on the way back */ BreakKind break_now; /* this break: mostly their own kind, now and then another */ struct Object *break_at; /* BREAK_COFFEE: the stove (a coffee there) */ float break_sip; /* ... until the next sip */ struct Object *chat_with; /* BREAK_CHAT: who they're chatting with */ float chat_line; /* ... until the next thing said */ int chat_said; /* The festival (ai_fest.c) */ int fest_floor; /* dancing at this floor (+1; 0 none) ... */ Vec3 fest_spot; /* ... their place on it ... */ float fest_time; /* ... real s at it so far (negative: till they feel like dancing again) */ struct Object *fest_who; /* the storm: off to warn this one; the awareness team: off to see to this one */ float fest_walk; /* ... on the way this long */ /* People and people (ai_touch.c) */ struct Object *step_in; /* off to tell this one to stop (they bothered step_for) ... */ struct Object *step_for; float step_t; /* ... on the way this long */ struct Object *harass; /* a drunk guest after this one (the festival) ... */ float harass_walk; /* ... on the way this long */ } Ai; /* Starts helping the leader; drops a bottle if needed. */ void Ai_help(struct Object *self, struct Object *leader); void Ai_stopHelping(struct Object *self); bool Ai_isHelping(const struct Object *self); /* Called away from a job and didn't go back to it on their own: back to it now (reminded). False: no such job. */ bool Ai_resumePaused(struct Object *self); /* Says something (a speech bubble for a few seconds). */ void Ai_say(struct Object *self, const char *text); /* Starts working on an order around area (they must know how). */ void Ai_order(struct Object *self, Order order, Vec3 area); /* A tree felled falling that way: the first thing it would come down on (a house, a car, a tent ...), or NULL. */ const struct Object *Ai_fallsOnto(const struct Object *tree, Vec3 dir); /* Somebody where it'll come down (falling that way): told to get out (they step aside). True if anybody is there. */ bool Ai_warnFellingRoom(struct Object *feller, struct Object *const *objects, int count, struct Object *tree, Vec3 dir); void Ai_stopWork(struct Object *self); /* Follows the player to be shown how to do the pending order, or where the woodpile goes. */ void Ai_show(struct Object *self, Showing what, const struct Object *player); void Ai_stopShowing(struct Object *self); /* Now knows this woodpile and stacks firewood there. */ void Ai_setWoodpile(struct Object *self, struct Object *woodpile); /* In a conversation or not; done = it ended (no new chat for a while). */ void Ai_setTalking(struct Object *self, bool talking); /* Tools: a tool someone shouldn't use (the chainsaw unpractised, the axe or the saw drunk) they use anyway, unless told not to - and the ignorant don't listen. tool: a ToolKind. Ai_banTool: true = they'll leave it. */ bool Ai_shouldntUse(const struct Object *self, int tool); bool Ai_banTool(struct Object *self, int tool, bool ban); bool Ai_mayUse(const struct Object *self, int tool); /* Time of day (hours) for everybody's plans. */ void Ai_setHour(float hour); /* Does this job need doing right now (not much firewood, trash lying around, dark and no fire)? */ bool Ai_needed(const struct Object *self, struct Object *const *objects, int count, Order order); /* Asked to do a job: yes or no, and what they say. their_idea: they asked for something to do. */ bool Ai_willDo(struct Object *self, struct Object *const *objects, int count, Order order, bool their_idea, const char **reply); /* How fast their work goes compared to normal: liking the job, condition, drink. */ float Ai_workRate(const struct Object *self); /* The job someone is doing right now (ORDER_NONE: nothing). */ Order Ai_job(const struct Object *self); /* Doing a job makes you better at it. */ void Ai_practice(struct Object *self, Order job, float amount); /* The player calls out to them: they come over (or say why not). False if they didn't hear. */ bool Ai_call(struct Object *self, const struct Object *player); /* Where things are (the world's cell grid): steering only looks at what's near. NULL: everything. */ struct Grid; struct World; void Ai_useGrid(struct Grid *grid); /* The world (for climbing: ladders, edges). */ void Ai_useWorld(struct World *world); /* Settled in (the car empty, the tents up): from now on they come to you with jobs (firewood, trees...). */ void Ai_setSettled(bool settled); /* Before physics: chooses what to do and sets movement and facing. */ void Ai_update(struct Object *self, struct Object *const *objects, int count, float dt); #endif /* PEOPLE_AI_H */