Nimbin[12]?Games / Entropie / entropie/src/people/pockets.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/people/pockets.c 5.5 KB · 159 lines raw
#include "people/pockets.h"

#include <math.h>

bool Pockets_light(Object *who) {
    if (!who->lighter || who->lighter_uses <= 0) return false;
    who->lighter_uses--;
    return true;
}

Object *Pockets_lighterNear(Object *who, Object *const *objects, int count, float range) {
    Object *best = NULL;
    for (int i = 0; i < count; i++) {
        Object *o = objects[i];
        if (o == who || !o->is_character || o->type == OBJ_DOG || !o->lighter || o->lighter_uses <= 0) continue;
        float d = hypotf(o->position.x - who->position.x, o->position.z - who->position.z);
        if (d < range) { range = d; best = o; }
    }
    return best;
}

void Pockets_passLighter(Object *from, Object *to) {
    if (!from->lighter || to->lighter) return;
    to->lighter = true;
    to->lighter_uses = from->lighter_uses;
    to->lighter_of = from->lighter_of == to ? NULL : from->lighter_of ? from->lighter_of : from; /* (back home: their own again) */
    from->lighter = false;
    from->lighter_of = NULL;
    from->lighter_uses = 0;
}

bool Pockets_giveBack(Object *who) {
    Object *owner = who->lighter_of;
    if (!who->lighter || !owner || owner->lighter) return false;
    Pockets_passLighter(who, owner);
    return true;
}

int Pockets_refill(Object *who) {
    int got = POCKET_URINELLAS - who->urinellas;
    if (got < 0) got = 0;
    who->urinellas = POCKET_URINELLAS;
    return got;
}

static bool canRoll(const Object *who) { return who->tobacco > 0 && who->papers > 0; }

bool Pockets_hasSmoke(const Object *who) {
    return who->cigarettes > 0 || canRoll(who);
}

bool Pockets_takeSmoke(Object *who, bool can_roll, bool *rolled) {
    if (canRoll(who) && (can_roll || who->cigarettes <= 0)) {
        if (!can_roll) return false; /* (only the makings, and no hands for rolling) */
        who->tobacco--;
        who->papers--;
        if (who->filters > 0) who->filters--; /* (with a filter if there's one) */
        *rolled = true;
        return true;
    }
    if (who->cigarettes <= 0) return false;
    who->cigarettes--;
    *rolled = false;
    return true;
}

Object *Pockets_smokesNear(Object *who, Object *const *objects, int count, float range) {
    Object *best = NULL;
    for (int i = 0; i < count; i++) {
        Object *o = objects[i];
        if (o == who || !o->is_character || o->type == OBJ_DOG || !Pockets_hasSmoke(o)) continue;
        float d = hypotf(o->position.x - who->position.x, o->position.z - who->position.z);
        if (d < range) { range = d; best = o; }
    }
    return best;
}

bool Pockets_giveSmoke(Object *from, Object *to) {
    if (from->cigarettes > 0) from->cigarettes--;
    else if (canRoll(from)) { from->tobacco--; from->papers--; if (from->filters > 0) from->filters--; } /* (rolls them one) */
    else return false;
    to->cigarettes++;
    return true;
}

PocketNeed Pockets_need(const Object *who) {
    if (who->cigarettes > 0 || (who->tobacco <= 0 && who->papers <= 0)) return POCKET_NOTHING;
    if (who->papers <= 0) return POCKET_PAPERS;
    if (who->tobacco <= 0) return POCKET_TOBACCO;
    if (who->filter_habit && who->filters <= 0) return POCKET_FILTERS;
    return POCKET_NOTHING;
}

static int spare(const Object *o, PocketNeed what) {
    switch (what) {
    case POCKET_PAPERS:  return o->papers;
    case POCKET_FILTERS: return o->filters;
    case POCKET_TOBACCO: return o->tobacco;
    case POCKET_ASHTRAY: return o->pocket_tray ? 2 : 0;
    case POCKET_NOTHING: break;
    }
    return 0;
}

Object *Pockets_hasNear(Object *who, PocketNeed what, Object *const *objects, int count, float range) {
    Object *best = NULL;
    for (int i = 0; i < count; i++) {
        Object *o = objects[i];
        if (o == who || !o->is_character || o->type == OBJ_DOG || spare(o, what) <= 1) continue;
        float d = hypotf(o->position.x - who->position.x, o->position.z - who->position.z);
        if (d < range) { range = d; best = o; }
    }
    return best;
}

int Pockets_give(Object *from, Object *to, PocketNeed what) {
    static const int SOME[] = { [POCKET_NOTHING] = 0, [POCKET_PAPERS] = 3, [POCKET_FILTERS] = 5, [POCKET_TOBACCO] = 2, [POCKET_ASHTRAY] = 1 };
    int n = spare(from, what);
    if (n > SOME[what]) n = SOME[what];
    if (n <= 0) return 0;
    switch (what) {
    case POCKET_PAPERS:  from->papers -= n;  to->papers += n;  break;
    case POCKET_FILTERS: from->filters -= n; to->filters += n; break;
    case POCKET_TOBACCO: from->tobacco -= n; to->tobacco += n; break;
    case POCKET_ASHTRAY: if (!to->butt_held) return 0; to->butt_held = false; from->pocket_butts++; break;
    case POCKET_NOTHING: break;
    }
    return n;
}

const char *Pockets_needName(PocketNeed what) {
    switch (what) {
    case POCKET_PAPERS:  return "a paper";
    case POCKET_FILTERS: return "a filter";
    case POCKET_TOBACCO: return "a bit of tobacco";
    case POCKET_ASHTRAY: return "your pocket ashtray";
    case POCKET_NOTHING: break;
    }
    return "something";
}

int Pockets_slots(const Object *who) {
    switch (who->look.garment) {
    case GARMENT_TROUSERS: return who->work_trousers ? 8 : 4; /* (work trousers: thigh and leg pockets too) */
    case GARMENT_SHORTS:   return 4;
    case GARMENT_SKIRT:    return 2;
    default:               return 1; /* (a dress: one small one) */
    }
}

int Pockets_used(const Object *who) {
    return (who->cigarettes > 0) + (who->tobacco > 0) + (who->papers > 0) + (who->filters > 0) +
           (who->lighter ? 1 : 0) + (who->keys ? 1 : 0) + (who->urinellas > 0) + (who->pocket_tray || who->pocket_butts > 0);
}

void Pockets_keepButt(Object *who) {
    who->pocket_butts++;
    who->butt_held = false;
}