#include // debugging output #include #include "dice.h" #include "pline.h" #include "stdio-util.h" // debugging output #include "damage.h" static DMGELT *new_dmgelt(void) { DMGELT *e; e = malloc(sizeof(DMGELT)); e->link = 0; e->hp = 0; e->kind = DK_ERROR; e->flags = 0; return(e); } static const char *dmgkind_str(DMGKIND k) { static char bad[64]; switch (k) { case DK_ERROR: return("ERROR"); break; case DK_ORDINARY: return("ORDINARY"); break; case DK_FIRE: return("FIRE"); break; case DK_COLD: return("COLD"); break; case DK_ELECTRIC: return("ELECTRIC"); break; } sprintf(&bad[0],"?%d",(int)k); return(&bad[0]); } static const char *dmgflags_str(unsigned int flags) { FILE *f; static char *s = 0; const char *p; static const struct { unsigned int b; const char *s; } bits[] = { { DF_TIMEONLY, "TIMEONLY" }, { DF_MAGICONLY, "MAGICONLY" }, { DF_NOREDUCTION, "NOREDUCTION" }, { 0, 0 } }; int i; free(s); f = fopenmalloc(&s,0); fprintf(f,"<"); p = ""; for (i=0;bits[i].s;i++) { if (flags & bits[i].b) { fprintf(f,"%s%s",p,bits[i].s); p = "|"; flags &= ~bits[i].b; } } if (flags) fprintf(f,"%s0x%x",p,flags); fprintf(f,">"); fclose(f); return(s); } DAMAGE damage_add(DAMAGE a, DAMAGE b) { DMGELT *e; DMGELT *e2; DMGELT *f; for <"b"> (e=b.elts;e;e=e2) { e2 = e->link; for (f=a.elts;f;f=f->link) { if ((f->kind == e->kind) && (f->flags == e->flags)) { f->hp += e->hp; free(e); continue <"b">; } } e->link = a.elts; a.elts = e; } return(a); } void damage_free(DAMAGE d) { DMGELT *e; while ((e = d.elts)) { d.elts = e->link; free(e); } } DAMAGE damage_simple(int hp, DMGKIND k, unsigned int flags) { DMGELT *e; e = new_dmgelt(); e->link = 0; e->hp = hp; e->kind = k; e->flags = flags; return((DAMAGE){.elts=e}); } int damage_total(DAMAGE d) { int t; DMGELT *e; t = 0; for (e=d.elts;e;e=e->link) t += e->hp; return(t); } void damage_reduction(DAMAGE *dp, int hp) { int t; int tr; DMGELT *e; DMGELT **ep; int ne; int r; static FILE *f = 0; if (! f) f = fopen("dr.dbg","w"); fprintf(f,"DR:"); for (e=dp->elts;e;e=e->link) fprintf(f," ",e->hp,dmgkind_str(e->kind),dmgflags_str(e->flags)); fprintf(f," -%d\n",hp); t = 0; ne = 0; for (e=dp->elts;e;e=e->link) { if (e->flags & DF_NOREDUCTION) continue; t += e->hp; ne ++; } if (hp > t) hp = t; tr = 0; for (e=dp->elts;e;e=e->link) { if (e->flags & DF_NOREDUCTION) continue; r = (hp * e->hp) / t; if (r > e->hp) r = e->hp; tr += r; fprintf(f,"%d->%d\n",e->hp,e->hp-r); e->hp -= r; } hp -= tr; fprintf(f,"%d left over\n",hp); ep = &dp->elts; while ((e = *ep)) { if (e->hp == 0) { *ep = e->link; fprintf(f,"dropping zero elt k=%s f=%s\n",dmgkind_str(e->kind),dmgflags_str(e->flags)); free(e); } else { ep = &e->link; } } }