Nimbin[12]?Games / Entropie / commits / 25ca081

Entropie git · main

Entropie festival game; first steps

sdl c game entropie cmake · first commit 2026-10-10 · last commit 2026-11-02 (17 hours ago) · synced 8 hours ago

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.gz

entropie 2.10.0: skirt when sitting, rain in tents

Christian Immanuel · 2026-10-20 15:19 · 25ca081ae2a1abdbc5eb24dd3045db706a1f20d7

- A skirt or dress lies over the lap when sitting (knees and shins show),
  instead of a ball round the thighs
- Rain: the friends shelter in their own tent at night or when it's nearer
  than the garage kitchen; they doze and come out when it stops
- Kurti no longer wanders with the chainsaw (checked in the NPC audit)
 build.sh                            |  2 +-
 commit_message.txt                  | 14 ++++++--------
 entropie/Makefile                   |  2 +-
 entropie/README.md                  |  3 ++-
 entropie/STATE.md                   | 10 +++++++---
 entropie/assets/shaders/figure.frag | 19 ++++++++++++++++---
 entropie/src/people/ai.c            | 15 +++++++++++++--
 entropie/src/people/condition.c     |  2 +-
 entropie/src/world/object.h         |  1 +
 entropie/src/world/tent.c           |  6 ++++++
 10 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/build.sh b/build.sh
index c062845..3bb2829 100644
--- a/build.sh
+++ b/build.sh
@@ -1 +1 @@
-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
+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
diff --git a/commit_message.txt b/commit_message.txt
index cc6fd6e..327e736 100644
--- a/commit_message.txt
+++ b/commit_message.txt
@@ -1,9 +1,7 @@
-entropie 2.9.0: rain, soda and Mate crates, dev menu time/weather
+entropie 2.10.0: skirt when sitting, rain in tents
 
-- Weather: dry spells and showers; drops round the camera, grey sky,
-  wetter look, real water on the ground, fires burn down faster
-- People shelter: Kurti and sons into the house, the others into the
-  garage kitchen; rain makes you colder
-- Two more crates in the boot: soda (cola and orange) and Mate (wakes you up)
-- No job offers until the tents stand and everything is unloaded
-- Dev menu: time of day, game speed, weather, skip the start
+- A skirt or dress lies over the lap when sitting (knees and shins show),
+  instead of a ball round the thighs
+- Rain: the friends shelter in their own tent at night or when it's nearer
+  than the garage kitchen; they doze and come out when it stops
+- Kurti no longer wanders with the chainsaw (checked in the NPC audit)
diff --git a/entropie/Makefile b/entropie/Makefile
index 93ca4b0..c5c4d9a 100644
--- a/entropie/Makefile
+++ b/entropie/Makefile
@@ -1,5 +1,5 @@
 APP       := entropie
-VERSION   := 2.9.0
+VERSION   := 2.10.0
 
 PREFIX    ?= /usr
 BINDIR    ?= $(PREFIX)/bin
diff --git a/entropie/README.md b/entropie/README.md
index 67bb8ef..6849ced 100644
--- a/entropie/README.md
+++ b/entropie/README.md
@@ -50,7 +50,8 @@ Painted in the rotoscope style of *Waking Life* (2001):
 - Rain falls round you, the sky greys over, everything looks wetter; the
   ground gets real water (puddles, mud), a fire burns down faster
 - People get out of it: Kurti and his sons into the house, the others into
-  your garages' kitchen; out again when it stops
+  their tent (at night, or when it's nearer) or your garages' kitchen; out
+  again when it stops
 - Out in the rain you get cold sooner (pullover)
 
 ## Tents
diff --git a/entropie/STATE.md b/entropie/STATE.md
index 774138f..b10b338 100644
--- a/entropie/STATE.md
+++ b/entropie/STATE.md
@@ -215,6 +215,11 @@ Round 2.9:
 - Weather (`world/weather.c`): `world.rain` eases (RAIN_EASE 150 s) to `rain_goal`: dry FIRST_DRY 3 h, then dry spells 2-8 h and showers 12-52 min (0.25..1). `world.wet` soaks in 25 min of hard rain, dries in 3 h (3x at night). 7 mm an hour poured onto the ground within 16 m (`Wetness_pour`, 8 splashes a frame, not under a roof: `Weather_covered`, a ray up 14 m). Fires lose 0.004 kg wood a second x rain. Drops (1400 x rain) within 9 m of the camera, 8.5 m/s, a little wind; `Shapes_rain` two crossed two-sided streaks each; none under a roof. Light (`game.c` rainLight): sun x (1 - 0.45 rain), the sky to grey, shadows x (1 - 0.85 rain); `rainWet` in scene.frag: the ground damper, the rest darker.
 - Shelter (`ai.c` shelter, from rain 0.3, out in it: `rain_out` in world.c): crates and gear down, Kurti and his sons into the house (`indoors`, kept while rain > 0.1), the others into your garages' kitchen (at `Site_drinksSpot`). Rain makes you colder outside; a hint the first time.
 
+Round 2.10:
+- Sitting in a skirt or dress (`figure.frag`): the thighs out forward (`sit` from the thighs against the spine), it lies over each thigh (two parts that melt into one lap, r 0.112 .. 0.098) and its hem falls a little in front of the knees (a flat part, 9 cm) - the cone from the waist to the knees made a ball round the lap. MAX_PARTS 38.
+- Rain, into the tent (`ai.c` shelter): the friends go into their own tent (up) at night (21-7) or when it's nearer than the kitchen; in, they doze (`rain_nap`: not woken by being rested, `condition.c`); `tent.c` Tent_update gets them up once the rain is under RAIN_NAP_END 0.15 (sleepy, over 0.6: they sleep on).
+- Kurti and the chainsaw: gone with "no helping" (2.8) - NPC audit: Kurti 33 joint pops (was 300-900), no tools in hand in 10 min.
+
 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).
@@ -347,7 +352,6 @@ Most important first.
 **Bugs**
 - Joint jumps left in the audit: jog+stop 171, sprint 297 (worst 26 cm) - running into things: a hurried catch step swings through in a few frames (step 0.07 -> 0.34, the ankle up 20 cm). Capping the swing speed helped sprint (278) but made jumps, drunk walk and the NPCs worse - tried and reverted in 1.83; ladder 45: toes on the sloping roof (a landing step's toes snap onto the slope, 16 cm; blending them in made all walking worse), toes turning onto the rungs getting on from the top (14 cm)
 
-- NPC audit: Kurti walks about with the chainsaw (putting it away?) and jitters at the garage gates and in the tool room (300-900 joint jumps a run)
 
 **Body and moving**
 - Obstacle approach, still to do: thin round logs (under 0.2 m) are still stepped over; a step in between on top of something unstable (if clumsy); NPCs: pull up on their own for their own reasons (now only following a leader), jumping onto things
@@ -363,7 +367,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); the pullover over a railing NPCs never do on their own
 - Tents, still to do: taking them down again; wind blowing an unpegged one about; people busy (work) when sleepy go to bed late
-- Rain, still to do: people sheltering in their tents; thunder; wet clothes
+- Rain, still to do: thunder; wet clothes
 - Main building: "the left building's roof peak is too far left" - to be clarified
 
 **Tools for us**
@@ -373,4 +377,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.9.0 (build 56bba45)`
+State of `entropie 2.10.0 (build 4d58e30)`
diff --git a/entropie/assets/shaders/figure.frag b/entropie/assets/shaders/figure.frag
index 413c0ef..e1813f6 100644
--- a/entropie/assets/shaders/figure.frag
+++ b/entropie/assets/shaders/figure.frag
@@ -71,7 +71,7 @@ const float SELF_SHADOW_SKIP  = 0.10; // meters
 
 // ---------- Body parts ----------
 
-const int MAX_PARTS = 36; // (a person with everything: a skirt, a jacket tied round, a cigarette, a Urinella, a stream)
+const int MAX_PARTS = 38; // (a person with everything: a skirt, a jacket tied round, a cigarette, a Urinella, a stream)
 vec3  partA[MAX_PARTS], partB[MAX_PARTS];
 float partR1[MAX_PARTS], partR2[MAX_PARTS];
 float partBlend[MAX_PARTS];   // smooth-union radius with the rest of the body
@@ -175,8 +175,21 @@ void buildBody() {
         float lift = max(-undress, 0.0); // (standing: gathered up in front, held at the hips)
         vec3 hem = mix(knees + vec3(0.0, -0.06, 0.0), waistline, 0.6 * max(undress, 0.0) + 0.72 * lift)
                  + chestForward * 0.09 * lift;
-        float wide = (0.5 * length(joints[J_KNEE_L] - joints[J_KNEE_R]) + 0.08) * (1.0 - 0.3 * lift);
-        addPart(waistline, hem, 0.165, max(wide, 0.165), 0.03, 0.8, lower); // (over the hips and thighs, wider as the knees part)
+        float apart = 0.5 * length(joints[J_KNEE_L] - joints[J_KNEE_R]);
+        float wide = (apart + 0.08) * (1.0 - 0.3 * lift);
+        // sitting (the thighs out forward): laid over each thigh (the two melt into one
+        // lap), the hem falling a little in front of the knees - not a sack round them
+        float sit = clamp((0.8 - dot(normalize(knees - pelvis), -spineDir)) / 0.6, 0.0, 1.0);
+        if (sit < 0.5 || lift > 0.0 || undress > 0.0) {
+            addPart(waistline, hem, 0.165, max(wide, 0.165), 0.03, 0.8, lower); // (over the hips and thighs, wider as the knees part)
+        } else {
+            for (int s = 0; s < 2; s++) {
+                vec3 hip = joints[J_HIP_L + s * 4] + spineDir * 0.04, knee = joints[J_KNEE_L + s * 4];
+                addPart(hip, knee + normalize(knee - hip) * 0.02, 0.112, 0.098, 0.06, 1.0, lower);
+            }
+            vec3 front = knees + chestForward * 0.04;
+            addPart(front, front + vec3(0.0, -0.09, 0.0), apart + 0.03, apart + 0.045, 0.04, 0.3, lower);
+        }
     }
 
     // Legs and feet
diff --git a/entropie/src/people/ai.c b/entropie/src/people/ai.c
index 27b06ca..1753c8d 100644
--- a/entropie/src/people/ai.c
+++ b/entropie/src/people/ai.c
@@ -1927,14 +1927,25 @@ static bool shelter(Object *self, Object *const *objects, int count, float dt) {
     if (!ai->sheltering) {
         if (!self->rain_out) return false;
         ai->sheltering = true;
-        if (random01(ai) < 0.6f) Ai_say(self, random01(ai) < 0.5f ? "It's pouring - inside, quick!" : self->lives_here ? "Rain! Into the house." : "Rain! Into the garages.");
+        if (random01(ai) < 0.6f) Ai_say(self, random01(ai) < 0.5f ? "It's pouring - inside, quick!" : self->lives_here ? "Rain! Into the house." : "Rain! I'm off under a roof.");
         for (int h = 0; h < 2; h++) { /* (crates and gear down where they are; tools along) */
             const Object *it = self->hands.item[h];
             if (it && (it->type == OBJ_CRATE || it->type == OBJ_GEAR)) Hands_drop(self, h);
         }
     }
     if (self->sitting) self->sitting = false;
-    if (!self->lives_here) { /* (the house is Kurti's: you lot wait it out in your garages' kitchen) */
+    if (!self->lives_here) { /* (the house is Kurti's: you lot wait it out in your tent, or in your garages' kitchen) */
+        Object *tent = Tent_of(objects, count, self);
+        bool night = g_world->hour >= 21.0f || g_world->hour < 7.0f;
+        if (tent && tent->tent_stage >= TENT_UP && self->body.pose == POSE_UP
+            && (night || flatDistance(tent->position, self->position) < flatDistance(Site_drinksSpot(), self->position))) {
+            if (!goToPoint(self, Tent_door(tent), 0.4f, objects, count, dt)) return true;
+            freeHands(self, NULL);
+            Tent_crawlIn(tent, self);
+            self->rain_nap = true;
+            rest(ai, 2.0f, 3.0f);
+            return true;
+        }
         Vec3 spot = vec3_add(Site_drinksSpot(), vec3(0.7f * ai->side, 0.0f, 0.7f * ai->side));
         if (goToPoint(self, spot, 0.7f, objects, count, dt)) rest(ai, 3.0f, 6.0f);
         return true;
diff --git a/entropie/src/people/condition.c b/entropie/src/people/condition.c
index 5e00c08..de65705 100644
--- a/entropie/src/people/condition.c
+++ b/entropie/src/people/condition.c
@@ -145,7 +145,7 @@ static void needs(Object *self, float dt, float game_dt) {
     if (n->sleepiness >= 1.0f && !b->asleep && settled) Body_lieDown(b);
     /* Slept enough (and sober enough): get up. Passed out drunk: up once sober enough. */
     float rested = self->passed_out ? 0.7f : 0.05f;
-    if (b->asleep && n->sleepiness < rested && self->drunk < WAKE_UP) Body_getUp(b);
+    if (b->asleep && n->sleepiness < rested && self->drunk < WAKE_UP && !self->rain_nap) Body_getUp(b);
     if (!b->asleep) self->passed_out = false;
     /* Can't hold it any more */
     if (n->bladder >= 1.0f && b->pose == POSE_UP && b->pee <= 0.0f) Body_pee(b, Object_peeTime(self));
diff --git a/entropie/src/world/object.h b/entropie/src/world/object.h
index 6da5790..7491639 100644
--- a/entropie/src/world/object.h
+++ b/entropie/src/world/object.h
@@ -173,6 +173,7 @@ typedef struct Object {
     float      tent_idle;     /* ... seconds since anybody worked on it */
     int        tent_beds;     /* ... sleeping bags (bit 0 owner, 2 owner2) and mats (1, 3) put in */
     struct Object *in_tent;   /* characters: sleeping in this tent (no collisions with it) */
+    bool          rain_nap;  /* in their tent out of the rain, dozing: not woken by being rested, up when it stops */
     struct Object *riding;    /* characters: sitting in this car (hidden, no physics, no AI: see car.c) ... */
     int        ride_seat;     /* ... on this seat (0 the driver) */
     int        branches;      /* trees: branches left on the crown */
diff --git a/entropie/src/world/tent.c b/entropie/src/world/tent.c
index 8664d47..ae10995 100644
--- a/entropie/src/world/tent.c
+++ b/entropie/src/world/tent.c
@@ -188,10 +188,16 @@ void Tent_crawlOut(Object *who) {
     Object_syncColliders(who);
 }
 
+#define RAIN_NAP_END 0.15f /* rain: under this, out of the tent again */
+
 void Tent_update(World *world, float dt) {
     for (int i = 0; i < world->count; i++) {
         Object *o = world->objects[i];
         if (o->type == OBJ_TENT) { o->tent_idle += dt; continue; }
+        if (o->rain_nap && (!o->body.asleep || world->rain < RAIN_NAP_END)) { /* in out of the rain: up when it stops */
+            o->rain_nap = false;
+            if (o->body.asleep && o->needs.sleepiness < 0.6f) Body_getUp(&o->body);
+        }
         if (o->is_character && o->in_tent && !o->body.asleep && o->body.pose == POSE_UP) { Tent_crawlOut(o); continue; }
         /* a sleeping bag or a mat put down at the door of its owner's tent: in it goes */
         if (o->type != OBJ_GEAR || o->variant > GEAR_MAT || o->is_held || o->broken || !o->owner) continue;