Nimbin[12]?Games / Entropie / commits / 31b963f

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.98.0: people step up onto blocks and crates

Christian Immanuel · 2026-10-19 17:32 · 31b963f14f43f98962460b39ba21b1a2f27c1bde

- People step up onto a long block, crate or log in their way instead of
  always walking round: the sporty and fresh up to about hip height, the
  unfit, worn out or drunk only about knee high
- Stepping over or onto something long at a slant starts at its face, not
  a metre early in mid-air (for you too)
 entropie/Makefile            |  2 +-
 entropie/README.md           |  6 ++++--
 entropie/STATE.md            |  8 ++++++--
 entropie/commit_message.txt  | 12 ++++++------
 entropie/src/people/ai.c     | 24 ++++++++++++++++--------
 entropie/src/world/object.c  |  7 +++++++
 entropie/src/world/object.h  |  3 +++
 entropie/src/world/physics.c | 14 +++++++++++++-
 8 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/entropie/Makefile b/entropie/Makefile
index 549e3b1..c9c7b4b 100644
--- a/entropie/Makefile
+++ b/entropie/Makefile
@@ -1,5 +1,5 @@
 APP       := entropie
-VERSION   := 1.97.0
+VERSION   := 1.98.0
 
 PREFIX    ?= /usr
 BINDIR    ?= $(PREFIX)/bin
diff --git a/entropie/README.md b/entropie/README.md
index 15dad1c..e68e1ac 100644
--- a/entropie/README.md
+++ b/entropie/README.md
@@ -187,8 +187,10 @@ and satellite pictures (about 340 x 340 m).
   clumsy, drunk or hurrying), slower steps - and now and then a step off
 - Something you can't step over or onto (a tree, a post, a high crate, a
   wall's corner) that you'd only just catch: your body drifts past it to the side
-- The others do it too: a long log across the way they step onto and walk on
-  (and wobble), shorter things they walk round
+- The others do it too: a long log or block across the way they step onto and
+  walk on (and wobble), shorter things they walk round. How high they step up
+  is their own: the sporty and fresh up to about hip height, the unfit, worn
+  out or drunk only knee high - higher than that they go round
 - Off the edge of something you go once your middle is past it - no standing
   on air beside it; slopes (a roof, the ramp) no longer show invisible steps
 - The sporty fit their steps to what's coming, so a foot lands at a good
diff --git a/entropie/STATE.md b/entropie/STATE.md
index a194c05..47de684 100644
--- a/entropie/STATE.md
+++ b/entropie/STATE.md
@@ -138,6 +138,10 @@ Round 1.97:
 - Jacket off and with them (`jacket_hung` false, top not TOP_JACKET): `FigureLook.jacket_tied` (set in `world.c` dressForNight) -> `jacketTied` in figure.frag: a band over the hips, a knot in front with the two sleeve ends hanging (over a skirt's top), the rest hanging flat down the back. MAX_PARTS 31 -> 35 (and addPart stops at it).
 - Back on the rack (`ai.c` hangJacket): idle or wandering, warm (chill under 0.05), the rack within RACK_WALK 60 m: RACK_CHANCE 0.004/s x tidiness (0.5 + liking for clearing up - 0.4 drunk); there (`goTo` 0.6 m) a hand to it, `jacket_hung`. Gives up after JACKET_GIVE_UP or when getting cold again.
 
+Round 1.98:
+- NPCs step up onto higher things (`object.c` Object_stepUpMost: (0.38 + 0.37 fitness) x (0.75 + 0.25 vigor) - 0.25 drunk, 0.25-0.75 m scaled; the player 0.75). `ai.c` longToStepOnto: static things too (not a building's parts), 1.5 m long or more; up to ONTO_HIGH 0.55 anything, higher up to their own most if at least ONTO_DEEP 0.5 m deep. `physics.c` startStepOver: the "higher" step up for NPCs as high as Object_stepUpMost (it was the player only).
+- Step over / onto: where the way meets the thing's near and far face from a ray (`Collider_ray`) instead of its projected radius - at a slant a long thing's corner made the step start 1 m early and land in the air before it.
+
 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); the coat rack (FURN_COATRACK, in your kitchen by the doors, garage coords 20.6 / 2.4) shows the jackets hanging on it (`Shapes_coatRack`, up to 6, a bitmask of whose in `shown`). `jacket_hung` (characters, true at the start): cold (chill 0.6+) and the jacket with them: on it goes (as before); hanging: NPCs `ai.want_jacket` -> `ai.c` fetchJacket (idle / wander: goTo the rack, on with it, "Ah, better."; gives up after 90 s or warm again); you are told once ("your jacket hangs on the rack in your garage") and click the rack (`game_actions.c` coatRack: on, or back onto it). Warm again: it comes off and stays with them.
@@ -270,7 +274,7 @@ Most important first.
 - 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)
 
 **Body and moving**
-- Obstacle approach, still to do: NPCs stepping up onto higher things (now only what they'd stride over anyway); 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
+- 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
 - 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, still to do: gesture variants; stepping over and climbing their own way; sporty ones more elegant (walking styles are in)
@@ -290,4 +294,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.97.0 (build 51512aa)`
+State of `entropie 1.98.0 (build f761dd4)`
diff --git a/entropie/commit_message.txt b/entropie/commit_message.txt
index 5433932..35ae27f 100644
--- a/entropie/commit_message.txt
+++ b/entropie/commit_message.txt
@@ -1,7 +1,7 @@
-entropie 1.97.0: jackets tied round the waist, back onto the rack
+entropie 1.98.0: people step up onto blocks and crates
 
-- A jacket taken off (by the fire, in the morning) is tied round the waist
-  by its sleeves: a band over the hips, the knot in front, the rest hanging
-  down the back
-- Warm again, people take it back to the coat rack sooner or later (the
-  tidy sooner, the drunk later)
+- People step up onto a long block, crate or log in their way instead of
+  always walking round: the sporty and fresh up to about hip height, the
+  unfit, worn out or drunk only about knee high
+- Stepping over or onto something long at a slant starts at its face, not
+  a metre early in mid-air (for you too)
diff --git a/entropie/src/people/ai.c b/entropie/src/people/ai.c
index a365285..d844454 100644
--- a/entropie/src/people/ai.c
+++ b/entropie/src/people/ai.c
@@ -93,21 +93,29 @@ void Ai_useGrid(struct Grid *grid) { g_grid = grid; }
 struct World *g_world;
 void Ai_useWorld(struct World *world) { g_world = world; }
 
-/* Something solid lying across the way, long (going round is a detour) and low
-   enough to step onto: people step up onto it and on (see physics: startStepOver). */
+/* Something solid in the way, long (going round is a detour) and low enough to
+   step onto: people step up onto it and on (see physics: startStepOver). Up to
+   ONTO_HIGH anything (they'd stride over it anyway); higher, as high as they go
+   up (Object_stepUpMost), if it's deep enough to land on (ONTO_DEEP). */
 #define ONTO_LONG  1.5f  /* m along at least */
-#define ONTO_HIGH  0.55f /* m above the feet at most (what they would stride over anyway) */
+#define ONTO_HIGH  0.55f /* m above the feet: what they would stride over anyway */
+#define ONTO_DEEP  0.5f  /* m across at least, to step up onto it when higher */
 
 static bool longToStepOnto(const Object *self, const Object *o) {
-    if (o->is_static || o->is_held || o->is_character || o->collider_count == 0 || !Physics_standsOn(o)) return false;
+    if (o->type == OBJ_WALL || o->is_held || o->is_character || o->collider_count == 0 || !Physics_standsOn(o)) return false; /* (a building's steps: see the stairs) */
     const Collider *c = &o->colliders[0];
-    float top = Object_colliderCenter(o, 0).y, longest = 0.0f;
+    float top = Object_colliderCenter(o, 0).y, longest = 0.0f, shortest = 1e9f;
     const float half[3] = { c->half_extents.x, c->half_extents.y, c->half_extents.z };
     for (int k = 0; k < 3; k++) {
         top += fabsf(c->axes[k].y) * half[k];
-        longest = fmaxf(longest, 2.0f * half[k] * sqrtf(c->axes[k].x * c->axes[k].x + c->axes[k].z * c->axes[k].z));
-    }
-    return longest >= ONTO_LONG && top - self->position.y <= ONTO_HIGH;
+        if (fabsf(c->axes[k].y) > 0.95f) continue; /* (the upright one) */
+        float flat = 2.0f * half[k] * sqrtf(c->axes[k].x * c->axes[k].x + c->axes[k].z * c->axes[k].z);
+        longest = fmaxf(longest, flat);
+        shortest = fminf(shortest, flat);
+    }
+    float high = top - self->position.y;
+    if (longest < ONTO_LONG) return false;
+    return high <= ONTO_HIGH || (high <= Object_stepUpMost(self) && shortest >= ONTO_DEEP * self->look.height / 1.75f);
 }
 
 #define WALL_RADIUS 0.24f /* m kept from a building's walls (a doorway 0.9 m wide leaves 0.4 m to aim through) */
diff --git a/entropie/src/world/object.c b/entropie/src/world/object.c
index 40a3b07..f7019fc 100644
--- a/entropie/src/world/object.c
+++ b/entropie/src/world/object.c
@@ -584,6 +584,13 @@ float Object_vigor(const Object *obj) {
     return (0.5f + 0.5f * fminf(obj->needs.stamina / 0.3f, 1.0f)) * (1.0f - 0.25f * Object_tiredness(obj));
 }
 
+float Object_stepUpMost(const Object *obj) {
+    const float s = obj->look.height / 1.75f;
+    if (obj->type == OBJ_PLAYER) return 0.75f * s; /* (you decide yourself: as high as anyone, see physics.c STEP_UP_MOST) */
+    float most = (0.38f + 0.37f * obj->fitness) * (0.75f + 0.25f * Object_vigor(obj)) - 0.25f * fminf(obj->drunk, 1.0f);
+    return clampf(most, 0.25f, 0.75f) * s;
+}
+
 float Object_topSpeed(const Object *obj) {
     return obj->top_speed * Object_vigor(obj) * (1.0f - 0.35f * fminf(obj->drunk, 1.0f));
 }
diff --git a/entropie/src/world/object.h b/entropie/src/world/object.h
index 1384d44..d60bf79 100644
--- a/entropie/src/world/object.h
+++ b/entropie/src/world/object.h
@@ -367,6 +367,9 @@ float   Object_caution(const Object *obj);
 
 /* Characters: 1 when fresh, down to 0.5 when exhausted (speed, strength, work). */
 float   Object_vigor(const Object *obj);
+/* How high (m) someone walks up onto something solid (a block, a crate): the sporty
+   and fresh higher, the unfit, worn out or drunk lower; higher than that they go round. */
+float   Object_stepUpMost(const Object *obj);
 /* Worn down by the day (sleepiness, felt by personality, fitness and drink): 0 fresh .. 1 done in. */
 float   Object_tiredness(const Object *obj);
 /* Characters: how fast they can sprint and jump right now (tired or drunk: less). */
diff --git a/entropie/src/world/physics.c b/entropie/src/world/physics.c
index 6c26d60..b15effe 100644
--- a/entropie/src/world/physics.c
+++ b/entropie/src/world/physics.c
@@ -921,11 +921,23 @@ static bool startStepOver(Object *obj, Object *const *objects, int count, const
         float ahead = vec3_dot(rel, dir), beside = fabsf(rel.x * -dir.z + rel.z * dir.x);
         float top = Object_colliderCenter(o, 0).y + projectRadius(c, WORLD_UP) - obj->position.y;
         float near = ahead - reach, far = ahead + reach;
+        { /* (straight at a long thing at a slant: its faces where the way goes in and out, not its corners) */
+            Vec3 from = vec3(obj->position.x, obj->position.y + fminf(0.5f * top, 0.2f * s), obj->position.z), center = Object_colliderCenter(o, 0);
+            float in = Collider_ray(c, center, from, dir, NULL);
+            if (in >= 0.0f) {
+                float back = Collider_ray(c, center, vec3_add(from, vec3_scale(dir, in + 20.0f)), vec3_scale(dir, -1.0f), NULL);
+                if (back >= 0.0f) {
+                    near = in;
+                    far = in + 20.0f - back;
+                    reach = 0.5f * (far - near);
+                }
+            }
+        }
         /* up onto it: higher than a stride over, or something solid you can just as well stand on (a log, a crate) -
            no straddling then, you stand up there and walk on (nobody walks up onto tables) */
         const bool you = obj->type == OBJ_PLAYER, person = you || obj->type == OBJ_HUMAN;
         bool up = person && standsOn(o) && top <= STEP_UP_MOST * s && side >= 0.12f * s && /* (a log end-on: a narrow step) */
-                  ((you && !over && top > STEP_OVER_HEIGHT * s && 2.0f * reach >= STEP_UP_ROOM * s) || /* (higher: only you - the others walk round) */
+                  (((you || top <= Object_stepUpMost(obj)) && !over && top > STEP_OVER_HEIGHT * s && 2.0f * reach >= STEP_UP_ROOM * s) || /* (higher: as high as they go up; else they walk round) */
                    (top >= STAND_LOWEST * s && 2.0f * reach >= STAND_ROOM * s && (you || top <= STEP_OVER_HEIGHT * 1.15f * s)));
         if (up) over = false;
         if (!over && !up) continue;