Nimbin[12]?Games / Entropie / entropie/src/game/game_why.c

Entropie git · main

Entropie festival game; first steps

sdl c game entropie cmake · first commit 2026-10-10 · last commit 2026-11-02 (18 hours ago) · synced 10 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/src/game/game_why.c 5.9 KB · 128 lines raw
/*
 * The why questions coming up on the ground: you see something that makes you
 * wonder - a woman peeing standing up with a Urinella, somebody down drunk
 * that nobody noticed, a guy working shirtless - and it goes into your
 * notebook (J) with who could tell you why. Asked (talk.c, about the
 * festival), it's understood; the Herberge decides (game_meeting.c).
 *
 * The notebook: the festival (its name, who leads what, the cash box, what
 * this weekend is for) and the why questions, as far as each has got.
 */

#include <math.h>

#include "game/game_internal.h"
#include "world/cast.h"
#include "world/why.h"

#define WHY_CHECK  1.0f  /* s between looks round */
#define SEE_NEAR   25.0f /* m: what you notice */
#define WHY_SHOWN  7.0f  /* s it stays on screen */

static bool near(const Game *game, const Object *o) {
    return hypotf(o->position.x - game->player->position.x, o->position.z - game->player->position.z) < SEE_NEAR;
}

static void comeUp(Game *game, int k, const char *what) {
    game->world.why[k] = WHY_RAISED;
    snprintf(game->story_line, sizeof game->story_line, "%s (J: your notebook)", what);
    say(game, game->story_line);
    game->message_time = WHY_SHOWN;
}

void game_why(Game *game, float dt) {
    if ((game->why_check -= dt) > 0.0f || Game_inBerlin(game->player)) return;
    game->why_check = WHY_CHECK;
    World *w = &game->world;
    char what[128];
    for (int i = 0; i < w->count; i++) {
        const Object *o = w->objects[i];
        if (o->type != OBJ_HUMAN || !near(game, o)) continue;
        if (w->why[WHY_URINELLA] == WHY_UNKNOWN && o->female && o->urinella && o->urinellas > 0 && o->ai.mode == AI_PEE && Body_isBusy(&o->body)) {
            snprintf(what, sizeof what, "%s pees standing up with a Urinella. Why would a festival hand those out?", o->name);
            comeUp(game, WHY_URINELLA, what);
            return;
        }
        if (w->why[WHY_AWARENESS] == WHY_UNKNOWN && Body_isDown(&o->body) && (o->passed_out || o->drunk > 0.7f)) {
            snprintf(what, sizeof what, "%s is down, out cold - and nobody noticed. Who looks out for people at a festival?", o->name);
            comeUp(game, WHY_AWARENESS, what);
            return;
        }
        if (w->why[WHY_SHIRT] == WHY_UNKNOWN && !o->female && o->look.top == TOP_BARE) {
            snprintf(what, sizeof what, "%s works shirtless. Festival bars that say \"no shirt, no service\" - why?", o->name);
            comeUp(game, WHY_SHIRT, what);
            return;
        }
    }
}

/* ---------- The notebook (J) ---------- */

/* A long text into lines of at most `width` characters (at spaces); returns how many. */
static int wrap(const char *text, const char *indent, char lines[][128], int max, int width) {
    int n = 0;
    const char *p = text;
    while (*p && n < max) {
        int len = (int)strlen(p), take = len;
        if (take > width) {
            take = width;
            while (take > 0 && p[take] != ' ') take--;
            if (take == 0) take = width;
        }
        snprintf(lines[n++], 128, "%s%.*s", indent, take, p);
        p += take;
        while (*p == ' ') p++;
    }
    return n;
}

int Game_notesLines(const Game *game, char lines[][128], int max, const char **title) {
    static char head[128];
    const World *w = &game->world;
    int n = 0;
    snprintf(head, sizeof head, "Your notebook - %s   (J: close)", Game_festivalName(game));
    *title = head;
    /* who leads the floors */
    static const int FLOORS[] = { PROJECT_OBSTWIESE, PROJECT_HOFBUEHNE, PROJECT_KARTOFFELACKER, PROJECT_HIDDEN };
    char who[128] = "Leading the floors:";
    size_t len = strlen(who);
    for (int k = 0; k < 4 && len < sizeof who - 30; k++) {
        const Object *lead = Cast_leadOf(w->objects, w->count, (Project)FLOORS[k]);
        if (game->player->leads == FLOORS[k]) lead = game->player;
        static const char *const SHORT[] = { "Obstwiese", "Hofbuehne", "Kartoffelacker", "techno" };
        snprintf(who + len, sizeof who - len, "%s %s %s", k ? "," : "", SHORT[k], lead ? (lead == game->player ? "you" : lead->name) : "nobody");
        len = strlen(who);
    }
    if (n < max) snprintf(lines[n++], 128, "%s", who);
    static const char *const FOCUS[] = { "-", "the floors", "the side jobs", "a party" };
    if (n < max) snprintf(lines[n++], 128, "Cash box: %d EUR   Weekend %d, for: %s", (int)w->cash, game->weekend, FOCUS[(unsigned)game->focus < 4 ? game->focus : 0]);
    if (n < max && (w->bigtree.step > BT_STANDING || Cast_leadOf(w->objects, w->count, PROJECT_BIG_TREE)))
        snprintf(lines[n++], 128, "The big old tree (Enrico): %s", game_bigTreeStatus(game));
    if (n < max) snprintf(lines[n++], 128, " ");
    if (n < max) snprintf(lines[n++], 128, "Why do festivals do that?");
    for (int k = 0; k < WHY_COUNT && n < max; k++) {
        const WhyInfo *q = Why_get(k);
        switch (w->why[k]) {
        case WHY_UNKNOWN: snprintf(lines[n++], 128, "-  ? (hasn't come up yet)"); break;
        case WHY_RAISED:
            snprintf(lines[n++], 128, "-  %s", q->ask);
            if (n < max) {
                char heard[128];
                snprintf(heard, sizeof heard, "%s asked it at the Herberge: \"%s\"", q->raiser, q->raise);
                n += wrap(w->why_heard & (1 << k) ? heard : q->seen, "      ", lines + n, max - n, 100);
            }
            if (n < max) snprintf(lines[n++], 128, "      Ask %s, %s, %s or %s (X, 4, then 5)", q->knowers[0], q->knowers[1], q->knowers[2], q->knowers[3]);
            break;
        case WHY_UNDERSTOOD:
            snprintf(lines[n++], 128, "-  %s", q->ask);
            if (n < max) n += wrap(q->because, "      ", lines + n, max - n, 100);
            if (n < max) snprintf(lines[n++], 128, "      Decided at the next Herberge");
            break;
        default:
            snprintf(lines[n++], 128, "-  %s: %s", q->title, w->why[k] == WHY_YES ? "yes - we do it" : "not this year");
            break;
        }
    }
    n += game_festivalNotes(game, lines + n, max - n);
    return n;
}