Entropie git · main
Entropie festival game; first steps
C 88.5% Markdown 9.1% GLSL 2.3%git clone https://git.christianimmanuel.de/games/Entropie.gitwget https://git.christianimmanuel.de/games/Entropie/archive/Entropie.tar.gzentropie 2.24.0: gone with the wind
- A strong gust can tear paper or a pullover out of a hand (two hands hold it safe); the others run after theirs and pick it up, or give up
build.sh | 7 +++++-- commit_message.txt | 6 +++--- entropie/Makefile | 2 +- entropie/README.md | 2 ++ entropie/STATE.md | 7 +++++-- entropie/commit_message.txt | 6 +++--- entropie/src/people/ai.c | 31 +++++++++++++++++++++++++++++++ entropie/src/people/ai.h | 2 ++ entropie/src/world/world.c | 34 +++++++++++++++++++++++++++++++++- 9 files changed, 85 insertions(+), 12 deletions(-) diff --git a/build.sh b/build.sh index 8c57d4f..597e4e0 100644 --- a/build.sh +++ b/build.sh @@ -1,3 +1,6 @@ -[ -f /home/Shared/Claude/entropie/commit_message.txt ] || exit -cd .. && rm -rf entropie; mv $SHARED_CLAUDE/entropie/commit_message.txt . && tar -xvf $SHARED_CLAUDE/entropie/entropie.tar.gz && echo "$(git add . && git commit -m "$(cat commit_message.txt)")" && cd entropie && make clean && make && cat ../commit_message.txt +if [ -f /home/Shared/Claude/entropie/commit_message.txt ]; then + cd .. && rm -rf entropie; mv $SHARED_CLAUDE/entropie/commit_message.txt . && tar -xvf $SHARED_CLAUDE/entropie/entropie.tar.gz && echo "$(git add . && git commit -m "$(cat commit_message.txt)")" && cd entropie && make clean && make && cat ../commit_message.txt +else + echo "Missing file: /home/Shared/Claude/entropie/commit_message.txt" +fi diff --git a/commit_message.txt b/commit_message.txt index e0d62fe..6463217 100644 --- a/commit_message.txt +++ b/commit_message.txt @@ -1,4 +1,4 @@ -entropie 2.23.0: belly first +entropie 2.24.0: gone with the wind -- Chest high ledges: the less sporty (or drunk) push up onto the belly, lie - over the edge, bring a knee up and stand up +- A strong gust can tear paper or a pullover out of a hand (two hands hold + it safe); the others run after theirs and pick it up, or give up diff --git a/entropie/Makefile b/entropie/Makefile index 4ecbe6e..ea56756 100644 --- a/entropie/Makefile +++ b/entropie/Makefile @@ -1,5 +1,5 @@ APP := entropie -VERSION := 2.23.0 +VERSION := 2.24.0 PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin diff --git a/entropie/README.md b/entropie/README.md index 382a0a9..29a30a4 100644 --- a/entropie/README.md +++ b/entropie/README.md @@ -63,6 +63,8 @@ Painted in the rotoscope style of *Waking Life* (2001): - A tent not pegged down (under half its pegs) blows about in strong wind until it snags on something or somebody works on it; its owner comes running - Trees and bushes sway; paper, plastic and a pullover lying about get blown along +- A strong gust can tear paper or a pullover out of a hand (hold it with two + hands to be safe); the others run after theirs ## Tents diff --git a/entropie/STATE.md b/entropie/STATE.md index bdaedcc..7a3ef30 100644 --- a/entropie/STATE.md +++ b/entropie/STATE.md @@ -293,6 +293,9 @@ Round 2.22: Round 2.23: - The belly way up (`climb.c`, `ClimbMove.belly_way` / `belly`): something BELLY_LOW 1.0 .. BELLY_HIGH 1.55 m high (scaled), both hands free, standing, for the less sporty (fitness under BELLY_FIT 0.45) or drunk (over 0.4): hands on the edge, a push up till the hips are just over it (feet BELLY_DROP 0.9 below the top), the upper body lies flat over it (forearms on top; `Body.belly_over`, BELLY_PITCH 1.0 rad added to the bend in `body_pose.c`), wriggling on a little, a knee up, standing up. BELLY_TIME 2.6 s fresh. Checked on a 1.3 m wall. +Round 2.24: +- Blown out of the hand (`world.c` windSnatches): paper (as `paperLike`, the trash that blows about) held in one hand from SNATCH_PAPER 8 m/s wind, a pullover from SNATCH_CLOTH 11.5, only in a gust over SNATCH_GUST 0.3; chance SNATCH_RATE 0.35 / s per 4 m/s over it x gust x (0.5 + drunk + 0.5 careless). Dropped, thrown up and off with the wind, a line said. Two hands on it: never. NPCs go after it (`ai.c` fetchBlown, `ai.blown` / `blown_t`): picked up again, given up after BLOWN_GIVE_UP 25 s or BLOWN_FAR 30 m (in a storm paper outruns them). Not saved (fresh after a load). + Unfinished building (Shell_build, at SHELL_AT in the frame's frame): brick shell 6.4 x 4.7, walls 2.9, open front (2 m) to the frame (now only the front half: pillars at z -13.8 / -9.2), window holes, bare floor, tiled roof with slabs. Barn: brick courses on BUILDING_BRICK walls (`addBrickCourses`: mortar a shade lighter, so the ink doesn't trace it), ivy (`Shapes_ivy`, OBJ_STRUCTUREs) on both long sides; the woodpile (OBJ_WOODPILE "Woodpile", WOODPILE_A/B) left of the toilet, everybody's woodpile from the start (`scene.c` Scene_finish). Fireplace tripod: wooden poles, feet TRIPOD_OUT 0.9 m outside the stones, TRIPOD_PAST 0.4 m past the top, a lashing; each pole an OBJ_WALL along it ("Tripod pole"). Gates (FURN_GATE, green boards): in your garages' doorways (GATES: hinge, end), `gate_open` / `gate_t`, `hinge`, `gate_shut` / `gate_out`; Object_swingGate (1.2 s), driven by showProps; a click within 1.2 m opens / shuts both leaves. Props that show (1.89, `world.c` showProps every frame): the tin's mesh is built again when its butts change (`Shapes_ashtray`: up to 12 show, the ash rises, a heap from 14; `shown` = what's built). @@ -440,7 +443,7 @@ Most important first. - "No shirt no service" policy (decision open) - Clothing, still to do: more outfits for extra people (only the performance test has any: they all wear trousers) - Tents, still to do: NPCs taking theirs down on their own (leaving) -- Weather, still to do: a sound for thunder, wind and rain (no sound in the game yet); a hat or anything held blown out of the hands +- Weather, still to do: a sound for thunder, wind and rain (no sound in the game yet); hats (nobody wears one yet) blown off **Saves, still to do** - Things being done (a job half way, a ladder being climbed, carrying something together) come back fresh, not as they were @@ -452,4 +455,4 @@ Most important first. - Drawing many figures on a real graphics card: not measured (software GL: 300 people cost 3x the rest of the scene) --- -State of `entropie 2.23.0 (build 43b0331)` +State of `entropie 2.24.0 (build d783eec)` diff --git a/entropie/commit_message.txt b/entropie/commit_message.txt index e0d62fe..6463217 100644 --- a/entropie/commit_message.txt +++ b/entropie/commit_message.txt @@ -1,4 +1,4 @@ -entropie 2.23.0: belly first +entropie 2.24.0: gone with the wind -- Chest high ledges: the less sporty (or drunk) push up onto the belly, lie - over the edge, bring a knee up and stand up +- A strong gust can tear paper or a pullover out of a hand (two hands hold + it safe); the others run after theirs and pick it up, or give up diff --git a/entropie/src/people/ai.c b/entropie/src/people/ai.c index cad732e..1b229a4 100644 --- a/entropie/src/people/ai.c +++ b/entropie/src/people/ai.c @@ -1916,6 +1916,34 @@ static bool chaseTent(Object *self, Object *const *objects, int count, float dt) return true; } +/* The wind took something out of their hand: after it and pick it up (not + for ever: gone too far, or somebody else has it, never mind). */ +#define BLOWN_GIVE_UP 25.0f /* s */ +#define BLOWN_FAR 30.0f /* m */ +static bool fetchBlown(Object *self, Object *const *objects, int count, float dt) { + Ai *ai = &self->ai; + Object *it = ai->blown; + if (!it) return false; + ai->blown_t += dt; + if (it->is_held || it->broken || ai->blown_t > BLOWN_GIVE_UP || flatDistance(it->position, self->position) > BLOWN_FAR || + self->body.asleep || self->in_tent || self->indoors > 0.0f || self->riding) { + if (!it->is_held && ai->blown_t > BLOWN_GIVE_UP && ai->speech_time <= 0.0f) Ai_say(self, "Oh, forget it."); + ai->blown = NULL; + return false; + } + if (self->sitting) self->sitting = false; + int hand = Hands_freeHand(self); + if (hand < 0) { ai->blown = NULL; return false; } + if (it->is_grounded && Hands_gapFrom(self->position, self->look.height, it) < PICKUP_REACH) { + stand(self); + turnTowards(self, vec3_sub(it->position, self->position), 1.0f); + if (Hands_pickUpObject(self, hand, it)) ai->blown = NULL; + return true; + } + goToPoint(self, it->position, 0.3f, objects, count, dt); + return true; +} + static bool pitchTents(Object *self, Object *const *objects, int count, float dt) { Ai *ai = &self->ai; if (ai->unload || self->body.asleep || self->in_tent) return false; @@ -2252,6 +2280,9 @@ void Ai_update(Object *self, Object *const *objects, int count, float dt) { /* Their tent blowing away: after it */ if ((ai->mode == AI_IDLE || ai->mode == AI_WANDER || ai->mode == AI_TABLE || ai->mode == AI_WORK || ai->mode == AI_FETCH) && chaseTent(self, objects, count, dt)) return; + /* The wind took something out of their hand: after it */ + if ((ai->mode == AI_IDLE || ai->mode == AI_WANDER || ai->mode == AI_TABLE || ai->mode == AI_WORK || ai->mode == AI_FETCH) && + fetchBlown(self, objects, count, dt)) return; /* Rain: inside */ if ((ai->mode == AI_IDLE || ai->mode == AI_WANDER || ai->mode == AI_TABLE || ai->mode == AI_WORK || ai->mode == AI_FETCH) && shelter(self, objects, count, dt)) return; diff --git a/entropie/src/people/ai.h b/entropie/src/people/ai.h index 50d3789..6700097 100644 --- a/entropie/src/people/ai.h +++ b/entropie/src/people/ai.h @@ -183,6 +183,8 @@ typedef struct { 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 *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) */ diff --git a/entropie/src/world/world.c b/entropie/src/world/world.c index c8635ec..29d4284 100644 --- a/entropie/src/world/world.c +++ b/entropie/src/world/world.c @@ -1263,9 +1263,13 @@ static void emptyTray(World *world, Object *o) { #define BLOW_CLOTH 9.0f /* ... a pullover from this */ #define BLOW_SHOVE 0.9f /* m/s^2 for each m/s over it (against the ground's grip) */ +static bool paperLike(const Object *o) { + return o->type == OBJ_TRASH && o->size.x > 0.0f && ((o->variant & 3) == PALETTE_WARM || (o->variant & 3) == PALETTE_STANDARD); +} + static void windBlows(World *world, Object *o, float dt) { if (o->is_static || o->is_held || o->broken || !o->is_grounded || o->lifted) return; - bool paper = o->type == OBJ_TRASH && o->size.x > 0.0f && ((o->variant & 3) == PALETTE_WARM || (o->variant & 3) == PALETTE_STANDARD); + bool paper = paperLike(o); bool cloth = o->type == OBJ_CLOTHES; if (!paper && !cloth) return; float speed = hypotf(world->wind.x, world->wind.z), from = paper ? BLOW_PAPER : BLOW_CLOTH; @@ -1276,6 +1280,33 @@ static void windBlows(World *world, Object *o, float dt) { if (paper) o->angular_velocity.y += (sinf(o->position.x * 3.1f) > 0.0f ? 1.0f : -1.0f) * 2.0f * shove * speed; } +/* A gust tears paper or a pullover held in one hand out of it (the drunk and + careless let go sooner); it flies off with the wind. */ +#define SNATCH_PAPER 8.0f /* m/s: paper from this wind ... */ +#define SNATCH_CLOTH 11.5f /* ... a pullover from this */ +#define SNATCH_GUST 0.3f /* ... only in a gust this strong (0..1) */ +#define SNATCH_RATE 0.35f /* chance a second for every 4 m/s over it, in a full gust */ +static void windSnatches(World *world, Object *o, float dt) { + if (!o->is_character || o->indoors > 0.0f || o->in_tent || o->riding || world->gust < SNATCH_GUST) return; + float speed = hypotf(world->wind.x, world->wind.z); + if (speed < SNATCH_PAPER) return; + for (int h = 0; h < 2; h++) { + Object *it = o->hands.item[h]; + if (!it || o->hands.state[h] != HAND_HOLDING || o->hands.item[1 - h] == it) continue; /* (two hands on it: held tight) */ + bool cloth = it->type == OBJ_CLOTHES; + if (!cloth && !paperLike(it)) continue; + float over = speed - (cloth ? SNATCH_CLOTH : SNATCH_PAPER); + if (over <= 0.0f) continue; + float rate = SNATCH_RATE * over / 4.0f * world->gust * (0.5f + fminf(o->drunk, 1.0f) + 0.5f * (1.0f - Object_caution(o))); + if (dice(world) >= rate * dt) continue; + Hands_drop(o, h); + it->velocity = vec3(world->wind.x * 0.5f, 1.6f, world->wind.z * 0.5f); /* (up and away with it) */ + it->is_grounded = false; + if (o->type != OBJ_PLAYER) { o->ai.blown = it; o->ai.blown_t = 0.0f; } + Ai_say(o, cloth ? "Hey - my pullover!" : "Whoops - gone with the wind!"); + } +} + void World_update(World *world, float dt, float game_dt) { Object_indexKinds(world->objects, world->count); world->dt_props = dt; @@ -1332,6 +1363,7 @@ void World_update(World *world, float dt, float game_dt) { for (int i = 0; i < world->count; i++) { Object *o = world->objects[i]; windBlows(world, o, dt); + windSnatches(world, o, dt); Physics_step(o, world->objects, world->count, &world->terrain, dt); landThrown(o); }