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/src/game/game_why.c 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;
}