#include #include "mon.h" #include "vars.h" #include "dice.h" #include "pline.h" #include "fuses.h" #include "effect.h" #include "structs.h" #include "sleep.h" typedef struct sleepeffect SLEEPEFFECT; struct sleepeffect { SLEEPEFFECT *flink; SLEEPEFFECT *blink; MONST *m; EFFECT *eff; TIME start; TIME expires; int expfuse; } ; static SLEEPEFFECT *allsleep = 0; static void destroy_sleepeffect(SLEEPEFFECT *e) { if (e->flink) e->flink->blink = e->blink; if (e->blink) e->blink->flink = e->flink; else allsleep = e->flink; free(e); } static void apply_sleep(MONST *m, void *ev __attribute__((__unused__))) { m->effflags |= MEF_SLEEP; } static void death_sleep(MONST *m __attribute__((__unused__)), void *ev) { cancelfuse(((SLEEPEFFECT *)ev)->expfuse); destroy_sleepeffect(ev); } static EFFECTOPS effops_sleep = EFFECTOPS_INIT(sleep); static void sleep_expire(long int liarg __attribute__((__unused__)), void *ev) { SLEEPEFFECT *e; e = ev; effect_remove(e->m,e->eff); if (! (e->m->effflags & MEF_SLEEP)) { if (e->m == you) { // XXX change this depending on wakeup reason pline("You wake up! Now %016llx",(unsigned long long int)curtime); } else if (monst_cansee_monst(you,e->m)) { pline("%s wakes up!",(*e->m->ops->Name)(e->m)); } } destroy_sleepeffect(ev); } static void sleep_end(SLEEPEFFECT *e) { cancelfuse(e->expfuse); sleep_expire(0,e); } void begin_sleep(MONST *m, TIME dur) { SLEEPEFFECT *e; if (m == you) { pline("You fall asleep! Now %016llx dur %g",(unsigned long long int)curtime,dur/(double)TIMESCALE); } else if (monst_cansee_monst(you,m)) { pline("%s falls asleep!",(*m->ops->Name)(m)); } e = malloc(sizeof(SLEEPEFFECT)); e->m = m; e->start = curtime; e->expires = curtime + (dur * TIMESCALE); e->expfuse = addfuse_abs(&sleep_expire,0,e,e->expires); e->flink = allsleep; e->blink = 0; if (allsleep) allsleep->blink = e; allsleep = e; e->eff = 0; e->eff = effect_add(m,e,&effops_sleep); } void sleep_awaken(MONST *m) { SLEEPEFFECT *e; SLEEPEFFECT *e2; TIME d; TIME f; for (e=allsleep;e;e=e2) { e2 = e->flink; if (e->m == m) { /* * 0% chance of waking at beginning, up to 100% at or after 2/3 * of the way through the duration. */ d = e->expires - e->start; f = curtime - e->start; // if frnd() > f / (d * 2/3) if (frnd()*2*d > 3*f) sleep_end(e); } } }