Nimbin[12]?Games / Entropie / commits / 99cdee7

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 1.70.0: more gestures, everyone with their own habits

Christian Immanuel · 2026-10-15 06:24 · 99cdee764547c2ab7972bc96528443c3645db3c4

- New idle gestures: rubbing the neck or the nose, at the earlobe, a hand
  back through the hair, thumb in the belt, hand on the chest, shading
  the eyes (with hip, head, chin and pocket: eleven)
- Mood picks them (proud, shy, nervous, tired, lively), and everyone has
  two habits they make most

Includes 1.69.0 (if not committed separately):
- Faster with a crowd: 750 people 22 -> 14 ms a frame (kind index, cell
  grid for company, no foot checks far from you)

Includes 1.68.0 (if not committed separately):
- The walking map is updated in place when fixed things change
  (0.3 ms instead of 10 ms)

Includes 1.67.0 (if not committed separately):
- Pour your drink on the fire (C): a small fire goes out, a big one
  hisses, vodka flares up

Includes 1.66.0 (if not committed separately):
- Careful people sort the woodpile by length (front even) and put the
  branches lying about onto a heap at the end of the woodpile

Includes 1.65.0 (if not committed separately):
- Smooth off the ladder (a step back, one foot after the other) and
  taking it down (the hand reaches for the rail at chest height)

Includes 1.64.0 (if not committed separately):
- Smooth ladder and climbs: getting on, over the edge at the top, feet
  from where they are; the easy 1 m climb no longer drops you off again

Includes 1.63.0 (if not committed separately):
- The hose melts in the fire (leaks, burns through); duct tape and the
  shears mend it

Includes 1.62.0 (if not committed separately):
- Smooth pull-ups: no hop at the end, feet and knees ease over the edge,
  elbows and hands taking hold blend in (audit walk: joint jumps 161 -> 58)

Includes 1.61.0 (if not committed separately):
- A step ladder in the tool room: stands on its own, at a wall with its
  back to it; climb onto the wall from its top

Includes 1.60.0 (if not committed separately):
- A folding ladder (two 2.5 m halves on a hinge, 5 m open) beside the
  telescopic one; one click at a wall unfolds it and leans it there

Includes 1.59.0 (if not committed separately):
- Stepping up onto blocks above knee high; set moves and jumps only for
  things standing on the ground in front of you

Includes 1.58.0 (if not committed separately):
- Walking over knee-high things is one smooth set move that always
  finishes; at a run: jump up onto blocks, catch climbable edges
 entropie/Makefile                   |  2 +-
 entropie/README.md                  |  5 +++++
 entropie/STATE.md                   |  6 +++---
 entropie/commit_message.txt         | 15 ++++++++++-----
 entropie/src/people/body.c          | 33 ++++++++++++++++++++++++++++-----
 entropie/src/people/body.h          |  1 +
 entropie/src/people/body_internal.h | 10 +++++++++-
 entropie/src/people/body_pose.c     | 35 +++++++++++++++++++++++++++++++++++
 8 files changed, 92 insertions(+), 15 deletions(-)

diff --git a/entropie/Makefile b/entropie/Makefile
index 27c20b9..4989f8c 100644
--- a/entropie/Makefile
+++ b/entropie/Makefile
@@ -1,5 +1,5 @@
 APP       := entropie
-VERSION   := 1.69.0
+VERSION   := 1.70.0
 
 PREFIX    ?= /usr
 BINDIR    ?= $(PREFIX)/bin
diff --git a/entropie/README.md b/entropie/README.md
index cb2def2..966f44a 100644
--- a/entropie/README.md
+++ b/entropie/README.md
@@ -237,6 +237,11 @@ and satellite pictures (about 340 x 340 m).
   feet settle into another stance, the body sways a little and breathes.
   Now and then someone shakes a leg loose, rocks on the toes, stretches,
   rolls the shoulders, stretches the neck, folds the arms or taps a foot
+- One hand now and then: on the hip, scratching the head, at the chin, in the
+  pocket, rubbing the neck or the nose, at the ear, back through the hair,
+  thumb in the belt, on the chest, shading the eyes. How someone feels
+  picks it (proud, shy, nervous, tired, lively), and everyone has two of
+  their own they make most
 - Arms keep out of walls, tables and what you climb (they move back and out of the way)
 - Movement is smooth and anatomically sound: feet lift off and set down
   gently (heel first, then the toes), hips and hands move on springs,
diff --git a/entropie/STATE.md b/entropie/STATE.md
index 31a6063..9788424 100644
--- a/entropie/STATE.md
+++ b/entropie/STATE.md
@@ -66,7 +66,7 @@ Talk topics: offer, ask, suggest, where (new woodpile spot), ask for a hand, ask
 
 - **Poses**: up, falling, lying down to sleep, down, getting up; sitting on a seat or cross-legged on the ground. Lying down (or falling) before ever having faced anywhere (asleep or passed out right where they stood): back, as usual (it collapsed into a heap "sitting over the floor")
 - **Fidgets** (standing about): shake a leg, rock on the toes, stretch, roll shoulders, stretch the neck, fold arms, tap a foot
-- **Gestures**: hand on the hip, at the head, at the chin, in a pocket
+- **Gestures** (one hand, idle; `body.c` picks, `body_pose.c` gesturePalm): hip, scratching the head, chin, pocket, rubbing the neck, rubbing the nose, earlobe, back through the hair, thumb in the belt, hand on the chest, shading the eyes. Weighted by mood: proud (hip, hair, thumb), shy (pocket, neck, ear, chest), nervous (head, chin, nose, ear), tired (neck), lively (hair, shading). Everyone has two habits of their own (`habit`, x3 and x2)
 - **Face**: mouth, eyelids, brows, smile, gaze; drunk, tired, shy, proud show in it
 - **Falls**: straight over, knees first, twisting, diving forward; reeling back first; stumbles over the foot that caught
 - **Where a fall lands**: the way it was going if there's room, else turned aside or shorter (crumpling at the foot of a wall); lies across things up to 0.5 m high, never into or over higher ones; no part of the body goes into what it comes down on (lifted onto it, limbs refitted); sitting, the legs rest on what lies in front; the lift eases in and out (5 m/s), no jumps
@@ -146,7 +146,7 @@ Most important first.
 - Climbing rework: hands first (one reaches first, shoulder ahead), a knee up, the other foot next to it; or sit on it and lift the legs; or belly first and roll; by height, surface and person
 - Balance: hips over the feet, look for stable footing, play with balance
 - Personal movement styles: gesture variants, each person a bit their own; stepping over and climbing their own way; sporty ones more elegant
-- More gestures and feelings to pick personalities from (a list to choose from)
+- More gestures (two hands: rubbing them, hands behind the head, arms akimbo) and feelings to pick personalities from: the list in Body / Gestures can grow
 
 **People**
 - Peeing properly: open the fly; women crouch and pull down / lift the skirt or dress; Urinella (some don't like it; mishaps; tidy, careless or high disposal)
@@ -159,4 +159,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 1.69.0 (build 97ae07e)`
+State of `entropie 1.70.0 (build b080bd1)`
diff --git a/entropie/commit_message.txt b/entropie/commit_message.txt
index 0e61efe..85b6983 100644
--- a/entropie/commit_message.txt
+++ b/entropie/commit_message.txt
@@ -1,9 +1,14 @@
-entropie 1.69.0: faster with a crowd (750 people: 22 -> 14 ms a frame)
+entropie 1.70.0: more gestures, everyone with their own habits
 
-- The scans everybody does each frame (fire near, stink, sleepers, who's
-  around) look only at people, fireplaces or stink, or ask the cell grid
-- People more than 30 m from you don't check their feet and hands against
-  things (nobody sees that far)
+- New idle gestures: rubbing the neck or the nose, at the earlobe, a hand
+  back through the hair, thumb in the belt, hand on the chest, shading
+  the eyes (with hip, head, chin and pocket: eleven)
+- Mood picks them (proud, shy, nervous, tired, lively), and everyone has
+  two habits they make most
+
+Includes 1.69.0 (if not committed separately):
+- Faster with a crowd: 750 people 22 -> 14 ms a frame (kind index, cell
+  grid for company, no foot checks far from you)
 
 Includes 1.68.0 (if not committed separately):
 - The walking map is updated in place when fixed things change
diff --git a/entropie/src/people/body.c b/entropie/src/people/body.c
index fd810c1..c56977f 100644
--- a/entropie/src/people/body.c
+++ b/entropie/src/people/body.c
@@ -620,11 +620,32 @@ static void updateExpression(Body *b, const BodyFrame *f, float speed) {
         b->gesture_timer = (5.0f + 9.0f * random01(b)) * (1.0f - 0.5f * b->shown.nerves);
         int side = random01(b) < 0.5f + 0.3f * b->quirk[0] ? 1 : 0;
         if (speed < 0.15f && b->pose == POSE_UP && !b->hand_active[side]) {
-            float r = random01(b);
-            int g = 1 + (int)(random01(b) * (float)(GESTURE_COUNT - 1));
-            if (proudness(b) > 0.3f && r < 0.5f) g = GESTURE_HIP;
-            if (b->shown.nerves > 0.3f && r < 0.5f) g = random01(b) < 0.5f ? GESTURE_HEAD : GESTURE_CHIN;
-            if (g >= GESTURE_COUNT) g = GESTURE_POCKET;
+            /* which one: how they feel, and their own habits (each person has two they make most) */
+            const float nerves = b->shown.nerves, tired = fmaxf(-b->shown.energy, 0.0f), lively = fmaxf(b->shown.energy, 0.0f);
+            const float proud = proudness(b), shy = shyness(b);
+            float weight[GESTURE_COUNT] = {
+                [GESTURE_HIP]    = 0.6f + 1.5f * proud,
+                [GESTURE_HEAD]   = 0.6f + 0.8f * nerves,
+                [GESTURE_CHIN]   = 0.6f + 0.6f * nerves,
+                [GESTURE_POCKET] = 0.8f + 0.6f * shy,
+                [GESTURE_NECK]   = 0.3f + 1.2f * tired + 0.6f * shy,
+                [GESTURE_NOSE]   = 0.3f + 1.2f * nerves,
+                [GESTURE_EAR]    = 0.2f + 1.0f * nerves + 0.5f * shy,
+                [GESTURE_HAIR]   = 0.3f + 1.0f * proud + 0.4f * lively,
+                [GESTURE_THUMB]  = 0.3f + 1.0f * proud,
+                [GESTURE_CHEST]  = 0.2f + 0.8f * shy,
+                [GESTURE_SHADE]  = 0.2f + 0.4f * lively,
+            };
+            weight[b->habit[0]] *= 3.0f;
+            weight[b->habit[1]] *= 2.0f;
+            float total = 0.0f;
+            for (int k = 1; k < GESTURE_COUNT; k++) total += fmaxf(weight[k], 0.0f);
+            float r = random01(b) * total;
+            int g = GESTURE_POCKET;
+            for (int k = 1; k < GESTURE_COUNT; k++) {
+                r -= fmaxf(weight[k], 0.0f);
+                if (r <= 0.0f) { g = k; break; }
+            }
             b->gesture = g;
             b->gesture_side = side;
             b->gesture_len = b->gesture_time = 2.5f + 3.0f * random01(b);
@@ -780,6 +801,8 @@ void Body_update(Body *b, const BodyFrame *f) {
         b->rng = 0x9E3779B9u ^ (unsigned)(int)(f->position.x * 7919.0f) ^ ((unsigned)(int)(f->position.z * 104729.0f) << 7);
         if (b->rng == 0) b->rng = 1;
         for (int k = 0; k < 4; k++) b->quirk[k] = random01(b) * 2.0f - 1.0f;
+        b->habit[0] = (unsigned char)(1 + (int)(random01(b) * (float)(GESTURE_COUNT - 1)) % (GESTURE_COUNT - 1));
+        b->habit[1] = (unsigned char)(1 + ((int)b->habit[0] + (int)(random01(b) * (float)(GESTURE_COUNT - 2))) % (GESTURE_COUNT - 1));
         b->gesture_timer = 3.0f + 6.0f * random01(b);
         b->last_position = f->position;
         b->last_facing = f->facing;
diff --git a/entropie/src/people/body.h b/entropie/src/people/body.h
index 83bf9f3..b5d05e1 100644
--- a/entropie/src/people/body.h
+++ b/entropie/src/people/body.h
@@ -190,6 +190,7 @@ typedef struct {
     float fore[2], fore_vel[2]; /* elbow bend */
     float weight_shift, weight_goal, weight_timer; /* idle: standing on one leg more */
     float quirk[4];          /* per person: lopsided arm swing, shoulders, head tilt, elbows (-1..1) */
+    unsigned char habit[2];  /* per person: two gestures they make more than others */
     int   gesture;           /* idle: one hand on the hip, at the head, at the chin, ... */
     int   gesture_side;
     float gesture_time;      /* > 0 while gesturing (seconds left) */
diff --git a/entropie/src/people/body_internal.h b/entropie/src/people/body_internal.h
index e823975..5bfd26b 100644
--- a/entropie/src/people/body_internal.h
+++ b/entropie/src/people/body_internal.h
@@ -109,7 +109,15 @@ enum { FALL_PLANK, FALL_CRUMPLE, FALL_TWIST, FALL_DIVE };
 #define TRAIL_LAND_DELAY  0.09f  /* running jump: the trailing foot comes down after the leading one */
 
 /* Idle gestures with one hand */
-enum { GESTURE_NONE, GESTURE_HIP, GESTURE_HEAD, GESTURE_CHIN, GESTURE_POCKET, GESTURE_COUNT };
+enum { GESTURE_NONE, GESTURE_HIP, GESTURE_HEAD, GESTURE_CHIN, GESTURE_POCKET,
+       GESTURE_NECK,   /* rubbing the back of the neck (tired, shy) */
+       GESTURE_NOSE,   /* rubbing the nose (nervous) */
+       GESTURE_EAR,    /* at the earlobe (nervous, shy) */
+       GESTURE_HAIR,   /* a hand back through the hair (proud, lively) */
+       GESTURE_THUMB,  /* thumb hooked in the belt (proud, at ease) */
+       GESTURE_CHEST,  /* hand on the chest (shy) */
+       GESTURE_SHADE,  /* shading the eyes, looking out (lively) */
+       GESTURE_COUNT };
 #define GESTURE_FADE      0.4f
 
 /* Standing about, the whole body: nobody stands quite still for long */
diff --git a/entropie/src/people/body_pose.c b/entropie/src/people/body_pose.c
index 43611d8..05a2a8f 100644
--- a/entropie/src/people/body_pose.c
+++ b/entropie/src/people/body_pose.c
@@ -245,6 +245,41 @@ static void gesturePalm(const Body *b, const Vec3 *j, const Skeleton *sk, float
         *palm = vec3_add(head, vec3_add(vec3_scale(fwd, 0.14f), vec3_add(vec3_scale(up, -0.10f), vec3_scale(side, sign * 0.02f))));
         *pole = vec3(sign * 0.4f, -1.0f, 0.2f);
         break;
+    case GESTURE_NECK: { /* rubbing the back of the neck, elbow up and forward */
+        float rub = 0.015f * sinf(b->clock * 9.0f);
+        *palm = vec3_add(head, vec3_add(vec3_scale(fwd, -0.10f), vec3_add(vec3_scale(up, -0.09f), vec3_scale(side, sign * (0.05f + rub)))));
+        *pole = vec3(sign * 0.6f, 0.6f, 0.6f);
+        break;
+    }
+    case GESTURE_NOSE: { /* rubbing the nose with a finger */
+        float rub = 0.008f * sinf(b->clock * 12.0f);
+        *palm = vec3_add(head, vec3_add(vec3_scale(fwd, 0.15f), vec3_add(vec3_scale(up, -0.03f + rub), vec3_scale(side, sign * 0.01f))));
+        *pole = vec3(sign * 0.4f, -1.0f, 0.2f);
+        break;
+    }
+    case GESTURE_EAR:    /* fingers at the earlobe */
+        *palm = vec3_add(head, vec3_add(vec3_scale(fwd, 0.01f), vec3_add(vec3_scale(up, -0.03f), vec3_scale(side, sign * 0.12f))));
+        *pole = vec3(sign, -0.6f, 0.2f);
+        break;
+    case GESTURE_HAIR: { /* from the forehead back over the top, then held there a moment */
+        float u = b->gesture_len > 0.0f ? 1.0f - b->gesture_time / b->gesture_len : 1.0f;
+        float back = smoothstepf(0.15f, 0.55f, u);
+        *palm = vec3_add(head, vec3_add(vec3_scale(fwd, lerpf(0.11f, -0.05f, back)), vec3_add(vec3_scale(up, lerpf(0.09f, 0.13f, back)), vec3_scale(side, sign * 0.04f))));
+        *pole = vec3(sign, 0.8f, 0.3f);
+        break;
+    }
+    case GESTURE_THUMB:  /* thumb hooked in the belt at the front */
+        *palm = vec3_add(j[JOINT_PELVIS], vec3(sign * 0.10f, 0.01f, 0.12f));
+        *pole = vec3(sign * 0.8f, -0.3f, -0.5f);
+        break;
+    case GESTURE_CHEST:  /* hand flat on the chest */
+        *palm = vec3_add(j[JOINT_CHEST], vec3(sign * 0.04f, 0.02f, 0.14f));
+        *pole = vec3(sign * 0.8f, -0.6f, -0.2f);
+        break;
+    case GESTURE_SHADE:  /* hand flat over the brow, looking out */
+        *palm = vec3_add(head, vec3_add(vec3_scale(fwd, 0.15f), vec3_add(vec3_scale(up, 0.12f), vec3_scale(side, sign * 0.06f))));
+        *pole = vec3(sign, 0.5f, -0.2f); /* (the elbow up and out to the side: the face stays free) */
+        break;
     default:             /* hand in the trouser pocket */
         *palm = vec3_add(j[JOINT_PELVIS], vec3(sign * 0.15f, -0.13f, 0.05f));
         *pole = vec3(sign * 0.6f, -0.2f, -1.0f);