Updates
This commit is contained in:
parent
014d591109
commit
86ee482ce3
2
Makefile
2
Makefile
|
@ -1,2 +1,2 @@
|
|||
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h
|
||||
gcc -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c -lncurses
|
||||
gcc -Wall -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c -lncurses
|
||||
|
|
563
ai.c
563
ai.c
|
@ -1,22 +1,36 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ai.h"
|
||||
#include "attack.h"
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "io.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "move.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
#include "spell.h"
|
||||
#include "text.h"
|
||||
|
||||
extern lifeform_t *player;
|
||||
extern enum ERROR reason;
|
||||
|
||||
void aimove(lifeform_t *lf) {
|
||||
int dir;
|
||||
int wantdb = B_TRUE;
|
||||
int db = B_FALSE;
|
||||
object_t *curwep,*bestwep;
|
||||
object_t *curwep,*bestwep, *o;
|
||||
object_t *curgun,*bestgun;
|
||||
flag_t *f;
|
||||
//flag_t *nextf;
|
||||
// lifeform_t *fleefrom = NULL;
|
||||
lifeform_t *target;
|
||||
char buf[BUFLEN];
|
||||
enum BODYPART bp;
|
||||
int x,y;
|
||||
cell_t *c;
|
||||
obpile_t *unarmedpile = NULL;
|
||||
flag_t *unarmedflag = NULL;
|
||||
|
||||
|
||||
|
||||
if (wantdb && haslos(player, lf->cell)) {
|
||||
|
@ -25,16 +39,21 @@ void aimove(lifeform_t *lf) {
|
|||
db = B_FALSE;
|
||||
}
|
||||
|
||||
if (db) dblog("AIMOVE: %s", lf->race->name);
|
||||
|
||||
|
||||
if (db) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(lf, lfname);
|
||||
dblog("AIMOVE: %s", lfname);
|
||||
}
|
||||
|
||||
/*
|
||||
// if lifeform isn't alive, skip turn
|
||||
if (isdead(lf)) {
|
||||
if (db) dblog(".oO { i am not alive, skipping turn. }");
|
||||
taketime(lf, SPEED_DEAD);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// do we have a better weapon we could use?
|
||||
|
@ -44,43 +63,260 @@ void aimove(lifeform_t *lf) {
|
|||
if (curwep != bestwep) {
|
||||
if (db) dblog(".oO { i have a better weapon than my current one (%s > %s) }",bestwep->type->name, curwep ? curwep->type->name : "nothing");
|
||||
// weild better one
|
||||
weild(lf, bestwep);
|
||||
return;
|
||||
if (!weild(lf, bestwep)) return;
|
||||
}
|
||||
|
||||
// do we have a better firearm ?
|
||||
curgun = getfirearm(lf);
|
||||
bestgun = getbestfirearm(lf);
|
||||
|
||||
if (curgun != bestgun) {
|
||||
if (db) dblog(".oO { i have a better gun than my current one (%s > %s) }",bestgun->type->name, curgun ? curgun->type->name : "nothing");
|
||||
// weild better one
|
||||
if (!weild(lf, bestgun)) return;
|
||||
}
|
||||
|
||||
// do we have better armour?
|
||||
for (bp = BP_RIGHTHAND ; bp < MAXBODYPARTS; bp++) {
|
||||
object_t *curarm;
|
||||
curarm = getarmour(lf, bp);
|
||||
// do we have a better one?
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
if (isbetterarmourthan(o, curarm)) {
|
||||
// wear this armour instead
|
||||
if (!wear(lf, o)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now check whetehr we have ANY weapon
|
||||
curwep = getattackwep(lf, &unarmedpile, &unarmedflag);
|
||||
if (unarmedpile) killobpile(unarmedpile);
|
||||
|
||||
// before attacking targets,
|
||||
// look for any object which we _covet_.
|
||||
// ie. if we covet something, we will pick it up
|
||||
// instead of attacking our target.
|
||||
if (db) dblog(".oO { looking for covetted objects... }");
|
||||
if (lookforobs(lf, B_COVETS)) {
|
||||
if (db) dblog(".oO { found covetted object. returning. }");
|
||||
return;
|
||||
}
|
||||
|
||||
// do we already have a target we are attacking?
|
||||
f = hasflag(lf->flags, F_TARGET);
|
||||
if (f) {
|
||||
int targid;
|
||||
int lastx,lasty;
|
||||
if (db) dblog(".oO { i have a target... }");
|
||||
targid = f->val[0];
|
||||
lastx = f->val[1];
|
||||
lasty = f->val[2];
|
||||
target = findlf(lf->cell->map, targid);
|
||||
if (target) {
|
||||
if (db) dblog(".oO { my target is lfid %d (%s). }", targid, target->race->name);
|
||||
if (haslos(lf, target->cell)) {
|
||||
if (db) dblog(".oO { i can see my target. will move towards it. }");
|
||||
movetowards(lf, target->cell);
|
||||
int goingtomove = B_TRUE;
|
||||
enum OBTYPE spell;
|
||||
object_t *gun;
|
||||
|
||||
// reset F_TARGET lifetime to full.
|
||||
f->lifetime = AI_FOLLOWTIME;
|
||||
if (db) dblog(".oO { i can see my target (at %d,%d). will move towards it. }",target->cell->x,target->cell->y);
|
||||
// remember last known loc
|
||||
f->val[1] = target->cell->x;
|
||||
f->val[2] = target->cell->y;
|
||||
|
||||
goingtomove = B_TRUE;
|
||||
|
||||
|
||||
// can we attack with spells (ie. ones which target the victim)?
|
||||
spell = getattackspell(lf);
|
||||
if (spell != OT_NONE) {
|
||||
int spellfailed = B_FALSE;
|
||||
lifeform_t *spelllf = NULL;
|
||||
cell_t *spellcell = NULL;
|
||||
object_t *spellob = NULL;
|
||||
if (db) {
|
||||
objecttype_t *st;
|
||||
st = findot(spell);
|
||||
dblog(".oO { will cast attack spell: %s }", st->name);
|
||||
}
|
||||
|
||||
// special cases: eg. spells like telekenesis
|
||||
if (spell == OT_S_TELEKINESIS) {
|
||||
float maxweight;
|
||||
object_t *poss[MAXPILEOBS];
|
||||
int nposs;
|
||||
int i;
|
||||
// find nearest object which can be picked up
|
||||
|
||||
// this is copied out of the telekenesis spell code!
|
||||
maxweight = getlfweight(lf, B_NOOBS) +
|
||||
(getlfweight(lf, B_NOOBS) * (getstatmod(lf, A_IQ) / 100));
|
||||
|
||||
nposs = 0;
|
||||
for (i = 0; i < lf->nlos; i++) {
|
||||
object_t *o;
|
||||
for (o = lf->los[i]->obpile->first ; o ; o = o->next) {
|
||||
if (!hasflag(o->flags, F_NOPICKUP) &&
|
||||
getobweight(o) <= maxweight) {
|
||||
poss[nposs] = o;
|
||||
nposs++;
|
||||
if (nposs >= MAXPILEOBS) break;
|
||||
}
|
||||
}
|
||||
if (nposs >= MAXPILEOBS) break;
|
||||
}
|
||||
if (nposs > 0) {
|
||||
spellob = poss[rnd(0,nposs-1)];
|
||||
} else {
|
||||
spellfailed = B_TRUE;
|
||||
}
|
||||
|
||||
// cast spell at the player
|
||||
spelllf = target;
|
||||
spellcell = target->cell;
|
||||
} else {
|
||||
spelllf = target;
|
||||
spellcell = target->cell;
|
||||
spellob = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!spellfailed && !castspell(lf, spell, spelllf, spellob, spellcell)) {
|
||||
// spell succesful
|
||||
return;
|
||||
} else {
|
||||
if (db) dblog(".oO { i cannot see my target }");
|
||||
// TODO: move towards last known location
|
||||
if (db) dblog(".oO { cast spell failed! }");
|
||||
}
|
||||
}
|
||||
|
||||
// can we attack by firing something?
|
||||
gun = getfirearm(lf);
|
||||
if (goingtomove && gun && getammo(lf)) {
|
||||
setguntarget(lf, target);
|
||||
if (!shoot(lf)) {
|
||||
// succesful
|
||||
return;
|
||||
} else {
|
||||
if (db) dblog(".oO { shoot gun failed! }");
|
||||
}
|
||||
}
|
||||
|
||||
// can we attack by throwing something?
|
||||
if (goingtomove && getcelldist(lf->cell, target->cell) > 1) {
|
||||
// TODO: or firing! check if we have a firearm first.
|
||||
o = getbestmissile(lf);
|
||||
if (o) {
|
||||
if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name);
|
||||
// try to throw it!
|
||||
if (!throwat(lf, o, target->cell)) {
|
||||
// succesful
|
||||
goingtomove = B_FALSE;
|
||||
} else {
|
||||
if (db) dblog(".oO { throw failed! }");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do we have a valid melee attack?
|
||||
if (!curwep) {
|
||||
if (db) dblog(".oO { won't move towards target - i have no weapon. }");
|
||||
goingtomove = B_FALSE;
|
||||
}
|
||||
|
||||
if (goingtomove) {
|
||||
if (!movetowards(lf, target->cell)) {
|
||||
// success
|
||||
return;
|
||||
} else {
|
||||
if (db) dblog(".oO { move towards failed! - reason = %d }",reason);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (db) dblog(".oO { i cannot see my target. moving to last known loc %d/%d }",lastx,lasty);
|
||||
|
||||
// can't see target.
|
||||
// move towards their last known location instead
|
||||
addflag(lf->flags, F_TARGETCELL, lastx, lasty, NA, NULL);
|
||||
// remove f_target
|
||||
killflag(f);
|
||||
|
||||
/*
|
||||
// just try to move in a random direction
|
||||
if (db) dblog(".oO { will move randomly }");
|
||||
// dorandommove will call taketime() if it fails,
|
||||
// so it's safe to just return
|
||||
dorandommove(lf, B_NOBADMOVES);
|
||||
return;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
if (lookforobs(lf, B_COVETS)) {
|
||||
if (db) dblog(".oO { found covetted object. returning. }");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// do we have a target cell?
|
||||
f = hasflag(lf->flags, F_TARGETCELL);
|
||||
if (f) {
|
||||
// if so, move towards it
|
||||
x = f->val[0];
|
||||
y = f->val[1];
|
||||
if (db) dblog(".oO { walking from %d,%d towards f_targetcell (%d,%d) ... }", lf->cell->x, lf->cell->y, x, y);
|
||||
c = getcellat(lf->cell->map, x, y);
|
||||
if (c) {
|
||||
if (movetowards(lf, c)) {
|
||||
// couldn't move towards it for some reason.
|
||||
// so stop trying.
|
||||
if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }");
|
||||
killflag(f);
|
||||
// remember NOT to target this one.
|
||||
lf->ignorecell = c;
|
||||
} else {
|
||||
if (db) dblog(".oO { successfully walked towards f_targetcell. }");
|
||||
// moved towards it.
|
||||
// reset lifetime
|
||||
f->lifetime = AI_FOLLOWTIME;
|
||||
|
||||
// are we there yet?
|
||||
if (lf->cell == c) {
|
||||
if (db) dblog(".oO { arrived at f_targetcell. removing. }");
|
||||
killflag(f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// not attacking anyone in particular
|
||||
if (db) dblog(".oO { f_targetcell doesn't exist. abandoning. }");
|
||||
// destination doesn't exist!
|
||||
killflag(f);
|
||||
// remember NOT to target this one.
|
||||
lf->ignorecell = c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (db) dblog(".oO { i do not have a target. }");
|
||||
// TODO: are we hostile? if so, look for a target
|
||||
// look for any object which we want
|
||||
if (db) dblog(".oO { looking for any ob which i want. }");
|
||||
if (lookforobs(lf, B_ANY)) {
|
||||
if (db) dblog(".oO { found ob that i want. returning. }");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// not attacking anyone in particular
|
||||
if (db) dblog(".oO { i do not have a target or can't move towards it. }");
|
||||
// are we hostile? if so, look for a target
|
||||
f = hasflag(lf->flags, F_HOSTILE);
|
||||
if (f) {
|
||||
int x,y;
|
||||
cell_t *c;
|
||||
if (db) dblog(".oO { i am hostile. looking for a target. }");
|
||||
// look around for a target
|
||||
// TODO: use our vis rang einstead of 10!
|
||||
|
@ -90,71 +326,294 @@ void aimove(lifeform_t *lf) {
|
|||
// cell exists and we can see it?
|
||||
if (c && haslos(lf, c)) {
|
||||
// player there?
|
||||
if (c->lf && c->lf->controller == C_PLAYER) {
|
||||
if (c->lf && (c->lf != lf) && isplayer(c->lf)) {
|
||||
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
|
||||
// target them!
|
||||
addflag(lf->flags, F_TARGET, c->lf->id, -1, -1, "");
|
||||
addtempflag(lf->flags, F_TARGET, c->lf->id, NA, NA, NULL, AI_FOLLOWTIME);
|
||||
// tell the player
|
||||
if (haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
capitalise(buf);
|
||||
msg("%s sees you!", buf);
|
||||
makenoise(lf, N_GETANGRY);
|
||||
}
|
||||
// then move towards them...
|
||||
if (db) dblog(".oO { moving towards my new target }");
|
||||
movetowards(lf, c);
|
||||
return;
|
||||
|
||||
if (curwep) {
|
||||
if (!movetowards(lf, c)) return;
|
||||
} else {
|
||||
if (db) dblog(".oO { won't move towards target - i have no weapon. }");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// are we friendly? if so, look for a target
|
||||
f = hasflag(lf->flags, F_FRIENDLY);
|
||||
if (f) {
|
||||
int x,y;
|
||||
if (db) dblog(".oO { i am friendly to the player. looking for a target. }");
|
||||
// look around for a target
|
||||
// TODO: use our vis rang einstead of 10!
|
||||
for (y = lf->cell->y - 10; y <= lf->cell->y + 10; y++) {
|
||||
for (x = lf->cell->x - 10; x <= lf->cell->x + 10; x++) {
|
||||
c = getcellat(lf->cell->map, x, y);
|
||||
// cell exists and we can see it?
|
||||
if (c && haslos(lf, c)) {
|
||||
// player there?
|
||||
if (c->lf && (c->lf != lf) && !isplayer(c->lf)) {
|
||||
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
|
||||
// target them!
|
||||
addtempflag(lf->flags, F_TARGET, c->lf->id, NA, NA, NULL, AI_FOLLOWTIME);
|
||||
// then move towards them...
|
||||
if (db) dblog(".oO { moving towards my new target }");
|
||||
if (!movetowards(lf, c)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// just try to move in a random direction
|
||||
if (db) dblog(".oO { default - moving randomly }");
|
||||
dorandommove(lf, B_NOBADMOVES);
|
||||
return;
|
||||
}
|
||||
|
||||
// if we get this far, just wait
|
||||
dowait(lf);
|
||||
rest(lf, B_TRUE);
|
||||
}
|
||||
|
||||
int getdirtowards(lifeform_t *lf, cell_t *dst) {
|
||||
int d;
|
||||
int aipickup(lifeform_t *lf, object_t *o) {
|
||||
if (isedible(o)) {
|
||||
return eat(lf, o);
|
||||
} else {
|
||||
return pickup(lf, o, o->amt);
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
enum OBTYPE getattackspell(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
enum OBTYPE poss[MAXPILEOBS];
|
||||
int nposs = 0;
|
||||
int db = B_TRUE;
|
||||
for (f = lf->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_CANWILL) {
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
} else if (f->id == F_CANCAST) {
|
||||
objecttype_t *ot;
|
||||
ot = findot(f->val[0]);
|
||||
if (cancast(lf, f->val[0], NULL)) {
|
||||
if (db) {
|
||||
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?");
|
||||
|
||||
}
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
} else {
|
||||
if (db) {
|
||||
if (ot) {
|
||||
dblog(".oO { can't cast %s right now (mpcost=%d, i have %d) }",
|
||||
ot ? ot->name : "?unkownspell?",
|
||||
getmpcost(ot->id), lf->mp);
|
||||
} else {
|
||||
dblog(".oO { can't cast ?unknownspell? right now }");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// select a random one
|
||||
if (nposs > 0) {
|
||||
int sel;
|
||||
sel = rnd(0,nposs-1);
|
||||
return poss[sel];
|
||||
}
|
||||
|
||||
return OT_NONE;
|
||||
}
|
||||
|
||||
|
||||
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op) {
|
||||
object_t *o;
|
||||
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (isarmour(o)) {
|
||||
object_t *curarm;
|
||||
enum BODYPART bp;
|
||||
flag_t *f;
|
||||
// where does it go?
|
||||
f = hasflag(o->flags, F_GOESON);
|
||||
bp = f->val[0];
|
||||
// is it better than what we have in that position?
|
||||
curarm = getarmour(lf, bp);
|
||||
if (isbetterwepthan(o, curarm)) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op) {
|
||||
object_t *bestwep, *o;
|
||||
|
||||
bestwep = getbestweapon(lf);
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (isweapon(o) && isbetterwepthan(o, bestwep) && canweild(lf, o)) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// returns B_TRUE if we did something
|
||||
int lookforobs(lifeform_t *lf, int covetsonly) {
|
||||
object_t *o;
|
||||
enum OBTYPE oid[MAXPILEOBS];
|
||||
int noids = 0;
|
||||
enum FLAG wantflag[MAXPILEOBS];
|
||||
int nwantflags = 0;
|
||||
int db = B_TRUE;
|
||||
flag_t *f;
|
||||
cell_t *c;
|
||||
int mindist=9999,bestdir=D_NONE;
|
||||
int n;
|
||||
int i;
|
||||
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
c = getcellindir(lf->cell, d);
|
||||
if (!c) continue;
|
||||
if (c == dst) {
|
||||
// destination is adjacent!
|
||||
bestdir = d;
|
||||
break;
|
||||
// construct a list of objects which we want
|
||||
noids = 0;
|
||||
for (f = lf->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_WANTS) {
|
||||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
oid[noids] = f->val[0];
|
||||
noids++;
|
||||
}
|
||||
|
||||
if (canmove(lf, d)) {
|
||||
int thisdist;
|
||||
thisdist = getcelldist(c, dst);
|
||||
if (thisdist < mindist) {
|
||||
mindist = thisdist;
|
||||
bestdir = d;
|
||||
} else if (f->id == F_WANTSOBFLAG) {
|
||||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
wantflag[nwantflags] = f->val[0];
|
||||
nwantflags++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle ties
|
||||
// current cell has an object we want?
|
||||
o = hasobmulti(lf->cell->obpile, oid, noids);
|
||||
if (o && (canpickup(lf, o) || caneat(lf,o)) ) {
|
||||
if (db) dblog(".oO { current cell has ob i want (%s) }",o->type->name);
|
||||
// try to pick it up
|
||||
if (!aipickup(lf, o)) return B_TRUE;
|
||||
if (db) dblog(".oO { pickup of %s failed, trying to eat! }",o->type->name);
|
||||
if (!eat(lf, o)) return B_TRUE;
|
||||
if (db) dblog(".oO { eating %s failed }",o->type->name);
|
||||
}
|
||||
// has an object with a flag we want?
|
||||
for (n = 0; n < nwantflags; n++) {
|
||||
o = hasobwithflag(lf->cell->obpile, wantflag[n]);
|
||||
if (o && (canpickup(lf, o) || caneat(lf,o)) ) {
|
||||
if (db) dblog(".oO { current cell has ob with flag i want (%s) }",o->type->name);
|
||||
// try to pick it up
|
||||
if (!aipickup(lf, o)) return B_TRUE;
|
||||
if (db) dblog(".oO { pickup of %s with wantflag failed, trying to eat! }",o->type->name);
|
||||
if (!eat(lf, o)) return B_TRUE;
|
||||
if (db) dblog(".oO { eating %s with wantflag failed }",o->type->name);
|
||||
|
||||
return bestdir;
|
||||
}
|
||||
}
|
||||
// current cell has better weapon?
|
||||
f = hasflag(lf->flags, F_WANTSBETTERWEP);
|
||||
if (f ) {
|
||||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
o = hasbetterweapon(lf, lf->cell->obpile);
|
||||
if (o && canpickup(lf, o)) {
|
||||
if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name);
|
||||
// try to pick it up
|
||||
if (!aipickup(lf, o)) return B_TRUE;
|
||||
if (db) dblog(".oO { pickup of better wep %s failed! }",o->type->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// current cell has better armour?
|
||||
f = hasflag(lf->flags, F_WANTSBETTERARM);
|
||||
if (f ) {
|
||||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
o = hasbetterarmour(lf, lf->cell->obpile);
|
||||
if (o && canpickup(lf, o)) {
|
||||
if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name);
|
||||
// try to pick it up
|
||||
if (!aipickup(lf, o)) return B_TRUE;
|
||||
if (db) dblog(".oO { pickup of better armour %s failed! }",o->type->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// look around for objects which we want, if we don't already have a targetcell.
|
||||
if (!hasflag(lf->flags, F_TARGETCELL)) {
|
||||
if (db) dblog(".oO { no targetcell, so looking for remote objects }");
|
||||
for (i = 0 ; i < lf->nlos; i++) {
|
||||
int gothere = B_FALSE;
|
||||
|
||||
c = lf->los[i];
|
||||
if (c != lf->ignorecell) {
|
||||
o = hasobmulti(c->obpile, oid, noids);
|
||||
if (o && (canpickup(lf, o) || caneat(lf,o)) ) {
|
||||
if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
|
||||
gothere = B_TRUE;
|
||||
}
|
||||
if (!gothere) {
|
||||
// has an object with a flag we want?
|
||||
for (n = 0; n < nwantflags; n++) {
|
||||
o = hasobwithflag(c->obpile, wantflag[n]);
|
||||
if (o && (canpickup(lf, o) || caneat(lf, o)) ) {
|
||||
if (db) dblog(".oO { remote cell has ob with flag i want (%s) }", o->type->name);
|
||||
gothere = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gothere) {
|
||||
// remote cell has better weapon?
|
||||
f = hasflag(lf->flags, F_WANTSBETTERWEP);
|
||||
if (f) {
|
||||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
|
||||
o = hasbetterweapon(lf, c->obpile);
|
||||
if (o && canpickup(lf, o)) {
|
||||
if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name);
|
||||
gothere = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gothere) {
|
||||
// remote cell has better armour?
|
||||
f = hasflag(lf->flags, F_WANTSBETTERARM);
|
||||
if (f) {
|
||||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
|
||||
o = hasbetterarmour(lf, c->obpile);
|
||||
if (o && canpickup(lf, o)) {
|
||||
if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name);
|
||||
gothere = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (gothere) {
|
||||
// start walking towards target cell
|
||||
addtempflag(lf->flags, F_TARGETCELL, c->x, c->y, NA, NULL, AI_FOLLOWTIME);
|
||||
// forget about people we are attacking
|
||||
killflagsofid(lf->flags, F_TARGET);
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
void movetowards(lifeform_t *lf, cell_t *dst) {
|
||||
int dir;
|
||||
// move towards them
|
||||
dir = getdirtowards(lf, dst);
|
||||
if (dir != D_NONE) {
|
||||
trymove(lf, dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
7
ai.h
7
ai.h
|
@ -1,5 +1,8 @@
|
|||
#include "defs.h"
|
||||
|
||||
void aimove(lifeform_t *lf);
|
||||
int getdirtowards(lifeform_t *lf, cell_t *dst);
|
||||
void movetowards(lifeform_t *lf, cell_t *dst);
|
||||
int aipickup(lifeform_t *lf, object_t *o);
|
||||
enum OBTYPE getattackspell(lifeform_t *lf);
|
||||
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op);
|
||||
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op);
|
||||
int lookforobs(lifeform_t *lf, int covetsonly);
|
||||
|
|
782
attack.c
782
attack.c
|
@ -1,147 +1,228 @@
|
|||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "attack.h"
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "io.h"
|
||||
#include "lf.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
#include "text.h"
|
||||
|
||||
extern lifeform_t *player;
|
||||
|
||||
int doattack(lifeform_t *lf, lifeform_t *victim) {
|
||||
int dam;
|
||||
|
||||
int attackcell(lifeform_t *lf, cell_t *c) {
|
||||
// anyone there? if so just attack.
|
||||
if (c->lf) {
|
||||
attacklf(lf, c->lf);
|
||||
} else {
|
||||
object_t *o;
|
||||
// has an mpassable object?
|
||||
o = hasobwithflag(c->obpile, F_IMPASSABLE);
|
||||
if (o) {
|
||||
attackob(lf, o);
|
||||
} else {
|
||||
// TODO: attack wall?
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
||||
unsigned int dam[100];
|
||||
enum DAMTYPE damtype[100];
|
||||
int ndam = 0;
|
||||
char buf[BUFLEN];
|
||||
char attackername[BUFLEN];
|
||||
char victimname[BUFLEN];
|
||||
int fatal = B_FALSE;
|
||||
flag_t *f;
|
||||
flag_t *unarmedflag = NULL;
|
||||
object_t *wep;
|
||||
enum DAMTYPE damtype;
|
||||
obpile_t *op;
|
||||
obpile_t *op = NULL;
|
||||
int attacktime;
|
||||
int acc;
|
||||
int hit = B_FALSE;
|
||||
double dampct;
|
||||
int unarmed = B_FALSE;
|
||||
char wepname[BUFLEN];
|
||||
int ev;
|
||||
int i;
|
||||
|
||||
int aidb = B_TRUE;
|
||||
|
||||
|
||||
if (aidb) {
|
||||
if (isplayer(lf)) {
|
||||
aidb = B_FALSE;
|
||||
} else if (!haslos(player, lf->cell)) {
|
||||
aidb = B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// get names
|
||||
getlfname(lf, attackername);
|
||||
getlfname(victim, victimname);
|
||||
|
||||
|
||||
if (aidb) dblog(".oO { trying to attack %s }", victimname);
|
||||
|
||||
// get weapon
|
||||
op = addobpile(lf, NULL); // for use if we are unarmed
|
||||
wep = getweapon(lf);
|
||||
//wep = getweapon(lf);
|
||||
wep = getattackwep(lf, &op, &unarmedflag);
|
||||
if (!wep) {
|
||||
unarmed = B_TRUE;
|
||||
|
||||
// ie. unarmed
|
||||
getunarmedweapon(lf, op);
|
||||
|
||||
if (op->first) {
|
||||
wep = op->first;
|
||||
} else {
|
||||
// cannot attack!
|
||||
if (lf->controller == C_PLAYER) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You cannot attack!");
|
||||
} else if (haslos(player, lf->cell)) {
|
||||
sprintf(buf, "%s",attackername);
|
||||
capitalise(buf);
|
||||
msg("%s looks like it wants to attack!",buf);
|
||||
//msg("%s looks like it wants to attack!",attackername);
|
||||
}
|
||||
|
||||
if (lf->controller != C_PLAYER) {
|
||||
// take some time to avoid infinite loops!
|
||||
taketime(lf, 1);
|
||||
/*
|
||||
if (!isplayer(lf)) {
|
||||
// if ai, take some time to avoid infinite loops!
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
free(op);
|
||||
*/
|
||||
if (op) killobpile(op);
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getobname(wep, wepname, 1);
|
||||
|
||||
|
||||
f = hasflag(wep->flags, F_DAMTYPE);
|
||||
if (f) {
|
||||
damtype = f->val[0];
|
||||
} else {
|
||||
// default - you are just bashing with whatever
|
||||
// you weilded.
|
||||
damtype = DT_BASH;
|
||||
}
|
||||
if (aidb) dblog(".oO { my weapon is %s %s }", wepname, unarmedflag ? "(unarmed)" : "");
|
||||
|
||||
// depends on weapon, race attackspeed modifier flag, etc
|
||||
attacktime = getobattackspeed(wep) + getlfattackspeed(lf);
|
||||
attacktime = getattackspeed(lf);
|
||||
|
||||
taketime(lf, attacktime);
|
||||
|
||||
// TODO: figure out if you hit
|
||||
|
||||
// TODO: figure out if you do damage, and how much
|
||||
|
||||
acc = 100; // base accuracy of 100%
|
||||
|
||||
// modify for weapon's (lack of) accuracy
|
||||
f = hasflag(wep->flags, F_ACCURACY);
|
||||
if (f) {
|
||||
// ie. accuracy of 100% means no penalty
|
||||
// ie. accuracy of 75% means 25% penalty
|
||||
// etc
|
||||
acc -= (100 - f->val[0]);
|
||||
}
|
||||
acc = getlfaccuracy(lf);
|
||||
|
||||
// modify for defender's evasion
|
||||
ev = getevasion(victim);
|
||||
acc -= ev;
|
||||
|
||||
// modify for attacker's level
|
||||
acc += (lf->level * 2);
|
||||
// metal weapon versus magnetic shield?
|
||||
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
|
||||
acc -= 45;
|
||||
}
|
||||
|
||||
if (acc < 0) acc = 0;
|
||||
if (acc > 100) acc = 100;
|
||||
|
||||
if (aidb) dblog(".oO { my modified chance to hit is %d %% }", acc);
|
||||
|
||||
// did you hit?
|
||||
ndam = 0;
|
||||
if (rnd(1,100) <= acc) {
|
||||
hit = B_TRUE;
|
||||
if (aidb) dblog(".oO { i hit! }");
|
||||
|
||||
// special case
|
||||
if (isplayer(lf) && (victim->race->id == R_GLOWBUG)) {
|
||||
if ((wep->type->id == OT_EMPTYFLASK) || (wep->type->id == OT_EMPTYVIAL)) {
|
||||
object_t *o;
|
||||
// catch the glowbug!
|
||||
msg("You catch %s in your %s.", victimname, noprefix(wepname));
|
||||
removeob(wep, 1);
|
||||
killlf(victim); // don't leave a corpse
|
||||
o = addob(lf->pack, "glowing flask");
|
||||
if (o) {
|
||||
getobname(o, buf, o->amt);
|
||||
msglower("%c - %s.",o->letter, buf);
|
||||
} else {
|
||||
hit = B_FALSE;
|
||||
// add to the ground
|
||||
o = addob(lf->cell->obpile, "glowing flask");
|
||||
if (o) {
|
||||
getobname(o, buf, o->amt);
|
||||
msg("%s drops to the ground.", buf);
|
||||
}
|
||||
}
|
||||
if (op) {
|
||||
killobpile(op);
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (hit) {
|
||||
int reducepct;
|
||||
// determine base damage
|
||||
|
||||
// determine damage
|
||||
//if (unarmed && (unarmedflag->val[0] != NA)) {
|
||||
if (unarmedflag) {
|
||||
// this mosnter's unarmed attack will
|
||||
// override normal damage calculation
|
||||
dam[ndam] = getdamrollfromflag(unarmedflag);
|
||||
} else {
|
||||
dam[ndam] = getdamroll(wep);
|
||||
}
|
||||
dblog("rolled dam[%d] = %d",ndam,dam[ndam]);
|
||||
|
||||
// modify for strength
|
||||
dam[ndam] = (int)((float)dam[ndam] * getstrdammod(lf));
|
||||
|
||||
// damtype?
|
||||
damtype[ndam] = getdamtype(wep);
|
||||
if (aidb) dblog(".oO { dealing %d %s damage }", dam[ndam], getdamname(damtype[ndam]));
|
||||
ndam++;
|
||||
|
||||
// blessed vs undead etc?
|
||||
if (isblessed(wep) && lfhasflagval(victim, F_DTVULN, DT_HOLY, NA, NA, NULL)) {
|
||||
// a little extra damage
|
||||
dam[ndam] = (int) ( (float)dam[ndam] * 1.25 );
|
||||
}
|
||||
|
||||
// determine extra damage
|
||||
getextradam(wep, &dam[ndam], &damtype[ndam]);
|
||||
} else {
|
||||
hit = B_FALSE;
|
||||
ndam = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (ndam > 0) {
|
||||
for (i = 0; i < ndam; i++) {
|
||||
float reducepct;
|
||||
int ar;
|
||||
int reduceamt;
|
||||
// determine damage
|
||||
dam = getdamroll(wep);
|
||||
|
||||
// modify for attacker's armour
|
||||
ar = getarmour(victim);
|
||||
reducepct = ar * 2;
|
||||
reduceamt = (int)(((float)reducepct / 100.0) * (float)dam);
|
||||
dblog("initial dam[%d] = %d",i,dam[i]);
|
||||
|
||||
dam -= reduceamt;
|
||||
if (dam < 0) dam = 0;
|
||||
// modify based on resistances
|
||||
adjustdamlf(victim, &dam[i], damtype[i]);
|
||||
dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
|
||||
|
||||
// TODO: armour gets damaged
|
||||
// modify for defender's armour
|
||||
ar = getarmourrating(victim);
|
||||
reducepct = getdamreducepct(ar);
|
||||
reduceamt = (int) ceil((reducepct / 100.0) * (float)dam[i]);
|
||||
|
||||
losehp(victim, dam, damtype, lf, attackername);
|
||||
dam[i] -= reduceamt;
|
||||
if (dam[i] < 0) dam[i] = 0;
|
||||
dblog("reduced by armour to dam[%d] = %d",i,dam[i]);
|
||||
|
||||
if (victim->hp <= 0) {
|
||||
// will this hit be fatal?
|
||||
if (dam[i] >= victim->hp) {
|
||||
fatal = B_TRUE;
|
||||
}
|
||||
|
||||
// announce it
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("You %s %s%s%s",
|
||||
fatal ? getkillverb(damtype, dam) : getattackverb(damtype, dam),
|
||||
victimname,
|
||||
(dam == 0) ? " but do no damage" : "",
|
||||
if (isplayer(lf)) {
|
||||
char extradambuf[BUFLEN];
|
||||
if (dam[i] == 0) {
|
||||
strcpy(extradambuf, " but do no damage");
|
||||
} else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
|
||||
sprintf(extradambuf, " [%d dmg]",dam[i]);
|
||||
} else {
|
||||
strcpy(extradambuf, "");
|
||||
}
|
||||
warn("You %s %s%s%s",
|
||||
fatal ? getkillverb(damtype[i], dam[i], victim->maxhp) : getattackverb(damtype[i], dam[i], victim->maxhp),
|
||||
victimname, extradambuf,
|
||||
fatal ? "!" : ".");
|
||||
|
||||
if (fatal && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
|
||||
|
@ -149,131 +230,398 @@ int doattack(lifeform_t *lf, lifeform_t *victim) {
|
|||
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
} else {
|
||||
if (haslos(player, lf->cell)) {
|
||||
if (haslos(player, lf->cell) || isplayer(victim)) {
|
||||
char withwep[BUFLEN];
|
||||
char attackverb[BUFLEN];
|
||||
char nodamstr[BUFLEN];
|
||||
|
||||
// capitalise first letter
|
||||
sprintf(buf, "%s",attackername);
|
||||
capitalise(buf);
|
||||
|
||||
if (wep && !unarmed) {
|
||||
if (wep && !unarmedflag && (lf->race->id != R_DANCINGWEAPON)) {
|
||||
sprintf(withwep, " with %s", wepname);
|
||||
} else {
|
||||
strcpy(withwep, "");
|
||||
}
|
||||
|
||||
msg("%s %ss %s%s%s.", buf, getattackverb(damtype,dam), victimname,withwep,
|
||||
(dam == 0) ? " but does no damage" : "" );
|
||||
strcpy(attackverb, getattackverb(damtype[i],dam[i],victim->maxhp));
|
||||
if ((dam[i] == 0) && (damtype[i] != DT_TOUCH)) {
|
||||
strcpy(nodamstr, " but does no damage");
|
||||
} else {
|
||||
strcpy(nodamstr, "");
|
||||
}
|
||||
// TODO: else {if (haslineofhearing() etc
|
||||
warn("%s %s%s %s%s%s.", buf, attackverb,
|
||||
attackverb[strlen(attackverb)-1] == 's' ? "es" : "s",
|
||||
victimname,withwep, nodamstr);
|
||||
} else {
|
||||
youhear(lf->cell, "sounds of fighting");
|
||||
}
|
||||
}
|
||||
|
||||
// victim loses hp
|
||||
// don't adjust damage - we've already done that
|
||||
if (wep && !unarmedflag) {
|
||||
char wepname[BUFLEN];
|
||||
getobname(wep, wepname, 1);
|
||||
sprintf(buf, "%s^weilding %s",attackername, wepname);
|
||||
} else {
|
||||
strcpy(buf, attackername);
|
||||
}
|
||||
// check
|
||||
/*
|
||||
if (dam[i] >= 120) {
|
||||
// potential bug
|
||||
msg("DB: potential bug: huge dam=%d",dam[i]);
|
||||
assert(1 == 2);
|
||||
}
|
||||
*/
|
||||
|
||||
losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE);
|
||||
|
||||
// victim's armour loses hp
|
||||
if (reduceamt) {
|
||||
object_t *armour;
|
||||
int adam;
|
||||
// damage reduction goes towards armour
|
||||
adam = (reduceamt / 2);
|
||||
// pick a random piece of armour
|
||||
armour = getrandomarmour(victim);
|
||||
if (armour) {
|
||||
takedamage(armour,adam, damtype[i]);
|
||||
}
|
||||
}
|
||||
} // end foreach damtype
|
||||
|
||||
// special weapon effects
|
||||
wepeffects(wep, victim->cell);
|
||||
} else { // miss!
|
||||
if (aidb) dblog(".oO { i missed! }");
|
||||
// announce it
|
||||
if (lf->controller == C_PLAYER) {
|
||||
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
|
||||
if (isplayer(lf) || haslos(player, lf->cell)) {
|
||||
sprintf(buf, "%s",attackername);
|
||||
|
||||
msg("%s%s magnetic shield repels %s%s attack.", victimname, getpossessive(victimname),
|
||||
buf, getpossessive(buf));
|
||||
}
|
||||
} else {
|
||||
if (isplayer(lf)) {
|
||||
msg("You miss %s.", victimname);
|
||||
} else {
|
||||
if (haslos(player, lf->cell)) {
|
||||
// capitalise first letter
|
||||
sprintf(buf, "%s",attackername);
|
||||
capitalise(buf);
|
||||
|
||||
msg("%s misses %s.", buf, victimname);
|
||||
}
|
||||
}
|
||||
}
|
||||
fightback(victim, lf);
|
||||
}
|
||||
|
||||
// get rid of temp unarmed object
|
||||
if (op->first) {
|
||||
killob(op->first);
|
||||
// get rid of temp unarmed object pile
|
||||
if (op) {
|
||||
killobpile(op);
|
||||
}
|
||||
|
||||
|
||||
// induction of fear?
|
||||
if (!isdead(victim)) {
|
||||
if (lfhasflag(victim, F_INDUCEFEAR)) {
|
||||
scare(lf, victim, rnd(2,3));
|
||||
}
|
||||
}
|
||||
|
||||
if (aidb) dblog(".oO { doattack about to return B_FALSE }");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int attackob(lifeform_t *lf, object_t *o) {
|
||||
unsigned int dam[100];
|
||||
enum DAMTYPE damtype[100];
|
||||
int ndam = 0;
|
||||
char attackername[BUFLEN];
|
||||
char obname[BUFLEN];
|
||||
flag_t *f;
|
||||
flag_t *unarmedflag = NULL;
|
||||
object_t *wep;
|
||||
obpile_t *op = NULL;
|
||||
cell_t *obloc = NULL;
|
||||
int attacktime;
|
||||
int unarmed = B_FALSE;
|
||||
char wepname[BUFLEN];
|
||||
int i;
|
||||
//int aidb = B_TRUE;
|
||||
int maxhp;
|
||||
|
||||
|
||||
// get names
|
||||
getlfname(lf, attackername);
|
||||
getobname(o, obname, o->amt);
|
||||
|
||||
// get target object details
|
||||
obloc = o->pile->where;
|
||||
f = hasflag(o->flags, F_OBHP);
|
||||
if (f) {
|
||||
maxhp = f->val[1];
|
||||
} else {
|
||||
maxhp = 1;
|
||||
}
|
||||
|
||||
// get weapon
|
||||
wep = getattackwep(lf, &op, &unarmedflag);
|
||||
if (!wep) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You cannot attack!");
|
||||
} else if (haslos(player, lf->cell)) {
|
||||
//msg("%s looks like it wants to attack!",attackername);
|
||||
}
|
||||
if (!isplayer(lf)) {
|
||||
// if ai, take some time to avoid infinite loops!
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
if (op) killobpile(op);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
getobname(wep, wepname, 1);
|
||||
|
||||
// depends on weapon, race attackspeed modifier flag, etc
|
||||
attacktime = getattackspeed(lf);
|
||||
|
||||
taketime(lf, attacktime);
|
||||
|
||||
// don't need to figure out accuracy - we always hit.
|
||||
|
||||
// determine damage
|
||||
ndam = 0;
|
||||
//if (unarmedflag && (unarmedflag->val[0] != NA)) {
|
||||
if (unarmedflag) {
|
||||
// this mosnter's unarmed attack will
|
||||
// override normal damage calculation
|
||||
dam[ndam] = getdamrollfromflag(unarmedflag);
|
||||
} else {
|
||||
dam[ndam] = getdamroll(wep);
|
||||
}
|
||||
|
||||
// damtype?
|
||||
damtype[ndam] = getdamtype(wep);
|
||||
ndam++;
|
||||
|
||||
// don't need to check for blessed vs mosnters
|
||||
|
||||
// determine extra damage
|
||||
getextradam(wep, &dam[ndam], &damtype[ndam]);
|
||||
|
||||
for (i = 0; i < ndam; i++) {
|
||||
// announce the hit
|
||||
if (isplayer(lf)) {
|
||||
char extradambuf[BUFLEN];
|
||||
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
|
||||
sprintf(extradambuf, " [%d dmg]",dam[i]);
|
||||
} else {
|
||||
strcpy(extradambuf, "");
|
||||
}
|
||||
msg("You %s %s.", getattackverb(damtype[i], dam[i], maxhp),
|
||||
obname, extradambuf);
|
||||
} else if (haslos(player, lf->cell)) {
|
||||
char withwep[BUFLEN];
|
||||
|
||||
if (wep && !unarmed && !isblind(player)) { // announce weapon used
|
||||
sprintf(withwep, " with %s", wepname);
|
||||
} else {
|
||||
strcpy(withwep, "");
|
||||
}
|
||||
|
||||
msg("%s %ss %s%s.", attackername,
|
||||
getattackverb(damtype[i],dam[i],maxhp), obname,withwep);
|
||||
} else {
|
||||
youhear(lf->cell, "sounds of fighting");
|
||||
}
|
||||
|
||||
// object loses hp
|
||||
takedamage(o, dam[i], damtype[i]);
|
||||
|
||||
} // end foreach damtype
|
||||
|
||||
// special weapon effects
|
||||
wepeffects(wep, obloc);
|
||||
|
||||
// get rid of temp unarmed object pile
|
||||
if (op) {
|
||||
killobpile(op);
|
||||
}
|
||||
free(op);
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
char *getattackverb(enum DAMTYPE damtype, int dam) {
|
||||
|
||||
// returns a const char *
|
||||
const char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
if (damtype == DT_PROJECTILE) {
|
||||
return "hit";
|
||||
} else if (damtype == DT_HOLY) {
|
||||
switch (rnd(1,2)) {
|
||||
case 1:
|
||||
return "smite";
|
||||
case 2:
|
||||
return "cleanse";
|
||||
}
|
||||
} else if (damtype == DT_PIERCE) {
|
||||
if (dam == 0) {
|
||||
if (pct <= 5) {
|
||||
return "poke";
|
||||
} else if (dam <= 5) {
|
||||
return "nick";
|
||||
} else if (dam <= 10) {
|
||||
} else if (pct <= 15) {
|
||||
return "stab";
|
||||
} else if (dam <= 15) {
|
||||
} else if (pct <= 30) {
|
||||
return "pierce";
|
||||
} else if (dam <= 20) {
|
||||
} else if (pct <= 40) {
|
||||
return "spear";
|
||||
} else {
|
||||
return "deeply stab";
|
||||
}
|
||||
} else if (damtype == DT_POISONGAS) {
|
||||
return "poison";
|
||||
} else if (damtype == DT_ELECTRIC) {
|
||||
if (pct <= 5) {
|
||||
return "zap";
|
||||
} else if (pct <= 15) {
|
||||
return "jolt";
|
||||
} else if (pct <= 20) {
|
||||
return "shock";
|
||||
} else if (pct <= 30) {
|
||||
return "electrify";
|
||||
} else {
|
||||
return "electrocute";
|
||||
}
|
||||
} else if (damtype == DT_CLAW) {
|
||||
if (dam == 0) {
|
||||
if (pct <= 5) {
|
||||
return "scratch";
|
||||
} else if (dam <= 5) {
|
||||
} else if (pct <= 15) {
|
||||
return "claw";
|
||||
} else if (dam <= 15) {
|
||||
} else if (pct <= 30) {
|
||||
return "rake";
|
||||
} else if (dam <= 30) {
|
||||
} else if (pct <= 50) {
|
||||
return "gouge";
|
||||
} else {
|
||||
return "eviscerate";
|
||||
}
|
||||
} else if (damtype == DT_SLASH) {
|
||||
if (dam == 0) {
|
||||
if (pct <= 5) {
|
||||
return "scratch";
|
||||
} else if (dam <= 10) {
|
||||
} else if (pct <= 15) {
|
||||
return "hit";
|
||||
} else if (dam <= 20) {
|
||||
} else if (pct <= 30) {
|
||||
return "slash";
|
||||
} else {
|
||||
return "slice";
|
||||
}
|
||||
} else if (damtype == DT_CHOP) {
|
||||
if (dam == 0) {
|
||||
if (pct <= 5) {
|
||||
return "hit";
|
||||
} else if (dam <= 10) {
|
||||
} else if (pct <= 15) {
|
||||
return "hack";
|
||||
} else {
|
||||
return "chop";
|
||||
}
|
||||
} else if (damtype == DT_BASH) {
|
||||
if (dam == 0) {
|
||||
if (pct <= 5) {
|
||||
return "whack";
|
||||
} else if (dam <= 5) {
|
||||
} else if (pct <= 20) {
|
||||
if (rnd(1,2) == 1) {
|
||||
return "hit";
|
||||
} else if (dam <= 10) {
|
||||
return "bash";
|
||||
} else if (dam <= 15) {
|
||||
return "pummel";
|
||||
} else if (dam <= 20) {
|
||||
return "pound";
|
||||
} else {
|
||||
return "flatten";
|
||||
return "bash";
|
||||
}
|
||||
} else {
|
||||
return "pummel";
|
||||
}
|
||||
} else if (damtype == DT_BITE) {
|
||||
if (dam == 0) {
|
||||
if (pct <= 5) {
|
||||
return "gnaw";
|
||||
} else if (dam <= 15) {
|
||||
} else if (pct <= 30) {
|
||||
return "bite";
|
||||
} else {
|
||||
return "savage";
|
||||
}
|
||||
} else if (damtype == DT_FIRE) {
|
||||
if (pct <= 5) {
|
||||
return "scorch";
|
||||
} else if (pct <= 20) {
|
||||
return "burn";
|
||||
} else if (pct <= 40) {
|
||||
return "scald";
|
||||
} else {
|
||||
return "incinerate";
|
||||
}
|
||||
} else if (damtype == DT_COLD) {
|
||||
if (pct <= 10) {
|
||||
return "chill";
|
||||
} else {
|
||||
return "freeze";
|
||||
}
|
||||
} else if (damtype == DT_TOUCH) {
|
||||
return "touch";
|
||||
}
|
||||
return "hit";
|
||||
}
|
||||
|
||||
char *getkillverb(enum DAMTYPE damtype, int dam) {
|
||||
object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag) {
|
||||
object_t *wep;
|
||||
|
||||
wep = getweapon(lf);
|
||||
if (!wep) {
|
||||
// ie. unarmed
|
||||
*unarmedpile = getunarmedweapon(lf, unarmedflag);
|
||||
|
||||
if ((*unarmedpile)->first) {
|
||||
wep = (*unarmedpile)->first;
|
||||
} else {
|
||||
wep = NULL;
|
||||
}
|
||||
}
|
||||
return wep;
|
||||
}
|
||||
|
||||
enum DAMTYPE getdamtype(object_t *wep) {
|
||||
flag_t *f;
|
||||
enum DAMTYPE dt = DT_NONE;
|
||||
|
||||
f = hasflag(wep->flags, F_DAMTYPE);
|
||||
if (f) {
|
||||
dt = f->val[0];
|
||||
} else {
|
||||
// default - you are just bashing with whatever
|
||||
// you weilded.
|
||||
dt = DT_BASH;
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
int getextradam(object_t *wep, unsigned int *dam, enum DAMTYPE *damtype) {
|
||||
flag_t *f;
|
||||
for (f = wep->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_ONFIRE) {
|
||||
*dam = rnd(5,10); // TODO: don't hardcode?
|
||||
*damtype = DT_FIRE;
|
||||
}
|
||||
}
|
||||
return *dam;
|
||||
}
|
||||
|
||||
char *getkillverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
|
||||
if (damtype == DT_HOLY) {
|
||||
return "smite";
|
||||
}
|
||||
|
||||
if (dam >= 50) {
|
||||
if (damtype == DT_PIERCE) return "fatally stab";
|
||||
if (pct >= 70) {
|
||||
if (damtype == DT_PIERCE) return "impale";
|
||||
if (damtype == DT_BASH) return "flatten";
|
||||
if (damtype == DT_BITE) return "gore";
|
||||
if (damtype == DT_CLAW) return "disembowel";
|
||||
if (damtype == DT_SLASH) return "behead"; // TODO: only if they have a head! otherwise "bisect"
|
||||
|
@ -285,12 +633,11 @@ char *getkillverb(enum DAMTYPE damtype, int dam) {
|
|||
|
||||
|
||||
|
||||
// return TRUE if no damage
|
||||
int getdamrange(object_t *o, int *min, int *max) {
|
||||
void getdamrange(flagpile_t *fp, int *min, int *max) {
|
||||
int mindam,maxdam;
|
||||
flag_t *f;
|
||||
|
||||
f = hasflag(o->flags, F_DAM);
|
||||
f = hasflag(fp, F_DAM);
|
||||
if (f) {
|
||||
int mod,ndice,sides;
|
||||
ndice = f->val[0];
|
||||
|
@ -304,6 +651,7 @@ int getdamrange(object_t *o, int *min, int *max) {
|
|||
mindam = (ndice * 1) + mod;
|
||||
maxdam = (ndice * sides) + mod;
|
||||
} else {
|
||||
// TODO wepaon does damage based on weight
|
||||
mindam = 0;
|
||||
maxdam = 0;
|
||||
}
|
||||
|
@ -315,53 +663,219 @@ int getdamrange(object_t *o, int *min, int *max) {
|
|||
// roll for damage
|
||||
int getdamroll(object_t *o) {
|
||||
int dam;
|
||||
int ndice, sides, mod;
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_DAM);
|
||||
|
||||
if (f) {
|
||||
ndice = f->val[0];
|
||||
sides = f->val[1];
|
||||
if (f->val[2] != NA) {
|
||||
mod = f->val[2];
|
||||
} else {
|
||||
mod = 0;
|
||||
dam = getdamrollfromflag(f);
|
||||
if (isblessed(o)) {
|
||||
int dam2;
|
||||
// blessed weapons get two rolls, and take the best
|
||||
dam2 = getdamrollfromflag(f);
|
||||
if (dam2 > dam) dam = dam2;
|
||||
} else if (iscursed(o)) {
|
||||
int dam2;
|
||||
// cursed weapons get two rolls, and take the worst
|
||||
dam2 = getdamrollfromflag(f);
|
||||
if (dam2 < dam) dam = dam2;
|
||||
}
|
||||
dam = rolldie(ndice, sides) + mod;
|
||||
|
||||
} else {
|
||||
// TODO wepaon does damage based on weight
|
||||
// weapon does no damage
|
||||
dam = 0;
|
||||
}
|
||||
|
||||
// modify for bonus
|
||||
f = hasflag(o->flags, F_BONUS);
|
||||
if (f) {
|
||||
dam += f->val[0];
|
||||
}
|
||||
|
||||
if (dam < 0) dam = 0;
|
||||
|
||||
return dam;
|
||||
}
|
||||
|
||||
float getdamreducepct(float armourrating) {
|
||||
float reducepct;
|
||||
reducepct = (armourrating * 1.5);
|
||||
return reducepct;
|
||||
}
|
||||
|
||||
int getdamrollfromflag(flag_t *f) {
|
||||
objecttype_t *ot;
|
||||
int dam;
|
||||
int ndice, sides, mod;
|
||||
flag_t *damflag = NULL;
|
||||
|
||||
ot = findotn(f->text);
|
||||
if (ot) {
|
||||
damflag = hasflag(ot->flags, F_DAM);
|
||||
}
|
||||
|
||||
// how many dice?
|
||||
ndice = f->val[0];
|
||||
if (ndice == NA) {
|
||||
// get it from weapon definition
|
||||
if (damflag && (damflag->val[0] != NA)) {
|
||||
ndice = damflag->val[0];
|
||||
} else {
|
||||
ndice = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sides = f->val[1];
|
||||
if (sides == NA) {
|
||||
// get it from weapon definition
|
||||
if (damflag && (damflag->val[1] != NA)) {
|
||||
sides = damflag->val[1];
|
||||
} else {
|
||||
sides = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mod = f->val[2];
|
||||
if (mod == NA) {
|
||||
// get it from weapon definition
|
||||
if (damflag && (damflag->val[2] != NA)) {
|
||||
mod = damflag->val[2];
|
||||
} else {
|
||||
mod = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dam = rolldie(ndice, sides) + mod;
|
||||
|
||||
assert(dam < 1000);
|
||||
assert(dam >= 0);
|
||||
|
||||
return dam;
|
||||
}
|
||||
|
||||
|
||||
// returns a multiplier
|
||||
float getstrdammod(lifeform_t *lf) {
|
||||
float mod = 0;
|
||||
float base;
|
||||
// <9 = penalty
|
||||
// 9,10,11,12 = average
|
||||
// >12 = bonus
|
||||
base = getattr(lf, A_STR);
|
||||
if ((base >= 9) && (base <= 12)) {
|
||||
mod = 1;
|
||||
} else if (base > 12) {
|
||||
base -= 12; // ie. 1 - 6
|
||||
|
||||
// 13 = 1 = 1.1
|
||||
// 14 = 2 = 1.2
|
||||
// 15 = 3 = 1.3
|
||||
// 16 = 4 = 1.4
|
||||
// 17 = 5 = 1.6
|
||||
// 18 = 6 = 1.5
|
||||
|
||||
mod = 1 + (base / 10.0);
|
||||
} else { // ie. 0 through 8
|
||||
// 0 = 0.1
|
||||
// 1 = 0.2
|
||||
// 2 = 0.3
|
||||
// 3 = 0.4
|
||||
// 4 = 0.5
|
||||
// 5 = 0.6
|
||||
// 6 = 0.7
|
||||
// 7 = 0.8
|
||||
// 8 = 0.9
|
||||
|
||||
mod = (base * 0.1); // ie. 8 -> 0.8 or 4 -> 0.4
|
||||
mod += 0.1; // ie. 8 -> 0.9 or 4 -> 0.5
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
||||
|
||||
// determine attack type for lifeform.
|
||||
// add an object of this kind to the pile 'op'
|
||||
// return its type;
|
||||
objecttype_t *getunarmedweapon(lifeform_t *lf,obpile_t *op) {
|
||||
// allocate a pile and add weapon to it.
|
||||
// return the pile. remember to free it!
|
||||
obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) {
|
||||
int nposs;
|
||||
flag_t *f;
|
||||
int sel;
|
||||
char poss[MAXPILEOBS][BUFLEN];
|
||||
obpile_t *op;
|
||||
flag_t *possflag[MAXPILEOBS];
|
||||
|
||||
op = addobpile(NULL, NULL);
|
||||
|
||||
// pick a random attack type.
|
||||
nposs = 0;
|
||||
for (f = lf->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_UNARMEDATTACKOB) {
|
||||
if (f->id == F_HASATTACK) {
|
||||
strcpy(poss[nposs],f->text);
|
||||
possflag[nposs] = f;
|
||||
nposs++;
|
||||
}
|
||||
}
|
||||
if (nposs > 0) {
|
||||
object_t *uob;
|
||||
sel = rnd(0,nposs-1);
|
||||
addob(op, poss[sel]);
|
||||
uob = addob(op, poss[sel]);
|
||||
assert(uob);
|
||||
if (uflag) *uflag = possflag[sel];
|
||||
}
|
||||
|
||||
if (op->first) {
|
||||
return op->first->type;
|
||||
if (!op->first) {
|
||||
if (uflag) *uflag = NULL;
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
void wepeffects(object_t *wep, cell_t *where) {
|
||||
flag_t *f;
|
||||
lifeform_t *victim;
|
||||
|
||||
victim = where->lf;
|
||||
|
||||
if (!where) return;
|
||||
for (f = wep->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_FLAMESTRIKE) {
|
||||
if (!hasob(where->obpile, OT_FIRESMALL)) {
|
||||
// ignite!
|
||||
addob(where->obpile, "small fire");
|
||||
// announce
|
||||
if (haslos(player, where)) {
|
||||
msg("A column of fire erupts from the ground!");
|
||||
f->known = B_KNOWN;
|
||||
}
|
||||
}
|
||||
} else if ((f->id == F_HITCONFER) && victim) {
|
||||
enum FLAG fid;
|
||||
int val0,val1;
|
||||
int min,max,howlong;
|
||||
fid = f->val[0];
|
||||
if (!lfhasflag(victim, fid)) {
|
||||
val0 = f->val[1];
|
||||
val1 = f->val[2];
|
||||
if (f->text) {
|
||||
char loctext[BUFLEN];
|
||||
char *word, *dummy;
|
||||
strcpy(loctext,f->text);
|
||||
word = strtok_r(loctext, "-", &dummy);
|
||||
if (word) {
|
||||
min = atoi(word);
|
||||
word = strtok_r(NULL, "-", &dummy);
|
||||
if (word) {
|
||||
max = atoi(word);
|
||||
howlong = rnd(min,max);
|
||||
} else {
|
||||
return NULL;
|
||||
howlong = PERMENANT;
|
||||
}
|
||||
} else {
|
||||
howlong = PERMENANT;
|
||||
}
|
||||
} else {
|
||||
howlong = PERMENANT;
|
||||
}
|
||||
addtempflag(victim->flags, fid, val0, val1, NA, NULL, howlong);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
19
attack.h
19
attack.h
|
@ -1,8 +1,17 @@
|
|||
#include "defs.h"
|
||||
|
||||
int doattack(lifeform_t *lf, lifeform_t *victim);
|
||||
char *getattackverb(enum DAMTYPE damtype, int dam);
|
||||
char *getkillverb(enum DAMTYPE damtype, int dam);
|
||||
int getdamrange(object_t *o, int *min, int *max);
|
||||
int attackcell(lifeform_t *lf, cell_t *c);
|
||||
int attacklf(lifeform_t *lf, lifeform_t *victim);
|
||||
int attackob(lifeform_t *lf, object_t *o);
|
||||
const char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp);
|
||||
object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag);
|
||||
enum DAMTYPE getdamtype(object_t *wep);
|
||||
int getextradam(object_t *wep, unsigned int *dam, enum DAMTYPE *damtype);
|
||||
char *getkillverb(enum DAMTYPE damtype, int dam, int maxhp);
|
||||
void getdamrange(flagpile_t *fp, int *min, int *max);
|
||||
float getdamreducepct(float armourrating);
|
||||
int getdamroll(object_t *o);
|
||||
objecttype_t *getunarmedweapon(lifeform_t *lf, obpile_t *op);
|
||||
int getdamrollfromflag(flag_t *f);
|
||||
float getstrdammod(lifeform_t *lf);
|
||||
obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
|
||||
void wepeffects(object_t *wep, cell_t *where);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
in defs.h:
|
||||
add a new BODYPART enum entry
|
||||
increment MAXBODYPARTS
|
||||
|
||||
in lf.c:
|
||||
update getbodypartname
|
||||
update getbodypartequipname
|
||||
update getbodyparthitchance
|
|
@ -0,0 +1,10 @@
|
|||
in defs.h:
|
||||
add enum
|
||||
increment MAXDAMTYPE
|
||||
in objcets.c:
|
||||
update getdamname() - eg. you take 5 "electrical" damage
|
||||
update getdamnamenoun() - eg. you are immune to "electricity"
|
||||
|
||||
in attack.c
|
||||
update getattackverb if required
|
||||
update getkillverb if required
|
|
@ -0,0 +1,5 @@
|
|||
defs.h:
|
||||
add H_xx enum
|
||||
|
||||
map.c:
|
||||
update getemptycelltype()
|
|
@ -0,0 +1,13 @@
|
|||
defs.h:
|
||||
add F_WHATEVER
|
||||
|
||||
io.c:
|
||||
update describeob() for when an object confers this property
|
||||
|
||||
update showlfstats() to describe the property
|
||||
|
||||
update announceflaggain() to describe adding it
|
||||
update announceflagloss() to describe losing it
|
||||
|
||||
|
||||
then make it do something!
|
|
@ -0,0 +1,8 @@
|
|||
defs.h:
|
||||
define the MT_* enum
|
||||
|
||||
objects.c:
|
||||
add an addmaterial() line
|
||||
update adjustdammaterial() as required
|
||||
|
||||
|
|
@ -6,7 +6,11 @@ In defs.h:
|
|||
In objects.c:
|
||||
define the class with addoc()
|
||||
add the class to sortorder[] at the top
|
||||
findotn() must know how to un-pluralise the name
|
||||
findotn() must know how to un-pluralise the name (eg. potions)
|
||||
|
||||
update genhiddenname() if this class isn't known
|
||||
also add hidden names up the top
|
||||
also update numXXXnames count in initobjects()
|
||||
|
||||
In text.c:
|
||||
makeplural() must know about the name
|
||||
makeplural() must know about the name (eg. potion -> potions)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
defs.h:
|
||||
update enum SPELLSCHOOL
|
||||
|
||||
objects.c:
|
||||
update getschoolname
|
|
@ -0,0 +1,19 @@
|
|||
defs.h:
|
||||
add the OT_xxx enum
|
||||
(optional) add a scroll to do the same effect
|
||||
(optional) add a potion to do the same effect
|
||||
|
||||
objects.c:
|
||||
define the spell
|
||||
remember to have spelllevle
|
||||
(optional) add a scroll to do the same effect, use F_LINKSPELL
|
||||
(optional) add a potion to do the same effect
|
||||
|
||||
spell.c:
|
||||
implement the effects
|
||||
remember to fill in *seenbyplayer if there is a scroll version
|
||||
cope with:
|
||||
blessed/cursed
|
||||
target having antimagic - use hasmr(victim)
|
||||
blindness if the effect is vision-based
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
baesball (0.14 kg) can be thrown 100 metres
|
||||
|
||||
so let's say:
|
||||
|
||||
1 kg = 10 metres (cells)
|
||||
10 kg = 5m
|
||||
20 kg = 1m
|
||||
|
||||
distance = 10m - (weight/2)
|
||||
|
||||
|
||||
|
281
flag.c
281
flag.c
|
@ -3,12 +3,42 @@
|
|||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "io.h"
|
||||
#include "lf.h"
|
||||
#include "objects.h"
|
||||
#include "text.h"
|
||||
|
||||
extern int gamestarted;
|
||||
|
||||
flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text) {
|
||||
return addflag_real(fp, id, val1, val2, val3, text, PERMENANT, B_KNOWN);
|
||||
}
|
||||
flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft) {
|
||||
return addflag_real(fp, id, val1, val2, val3, text, timeleft, B_KNOWN);
|
||||
}
|
||||
|
||||
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known) {
|
||||
flag_t *f;
|
||||
int i;
|
||||
|
||||
// identified things mean all new flags are autmaticlaly known.
|
||||
if (hasflag(fp, F_IDENTIFIED)) {
|
||||
known = B_KNOWN;
|
||||
}
|
||||
|
||||
// certain flags stack...
|
||||
if (flagstacks(id)) {
|
||||
f = hasflag(fp, id);
|
||||
if (f) {
|
||||
// add values!
|
||||
f->val[0] += val1;
|
||||
f->val[1] += val2;
|
||||
f->val[2] += val3;
|
||||
// TODO: how to handle text??
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
if (fp->first == NULL) {
|
||||
fp->first = malloc(sizeof(flag_t));
|
||||
f = fp->first;
|
||||
|
@ -25,7 +55,10 @@ flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char
|
|||
f->next = NULL;
|
||||
|
||||
// fill in props
|
||||
f->id = id; // increment next ob id
|
||||
f->id = id;
|
||||
f->lifetime = lifetime;
|
||||
f->known = known;
|
||||
f->obfrom = -1;
|
||||
|
||||
// first blank values
|
||||
for (i = 0; i < 3; i++) {
|
||||
|
@ -50,34 +83,88 @@ flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char
|
|||
|
||||
f->pile = fp;
|
||||
|
||||
|
||||
// notify
|
||||
if (gamestarted) {
|
||||
if (f->pile->owner) {
|
||||
if (announceflaggain(f->pile->owner, f)) {
|
||||
f->known = B_TRUE;
|
||||
}
|
||||
if (isplayer(f->pile->owner)) {
|
||||
switch (f->id) {
|
||||
case F_BLIND:
|
||||
case F_SEEINDARK:
|
||||
drawscreen();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (f->pile->ob) {
|
||||
if (announceobflaggain(f->pile->ob, f)) {
|
||||
f->known = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
flagpile_t *addflagpile(void) {
|
||||
flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) {
|
||||
flagpile_t *fp;
|
||||
fp = malloc(sizeof(flagpile_t));
|
||||
fp->first = NULL;
|
||||
fp->last = NULL;
|
||||
fp->owner = owner;
|
||||
fp->ob = ob;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
flag_t *hasflag(flagpile_t *fp, int id) {
|
||||
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {
|
||||
flag_t *f;
|
||||
for (f = fp->first ; f ; f = f->next) {
|
||||
if (f->id == id) return f;
|
||||
for (f = src->first ; f ; f = f->next) {
|
||||
addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
|
||||
(lifetime == NA) ? f->lifetime : lifetime, f->known);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text) {
|
||||
int flagstacks(enum FLAG fid) {
|
||||
int res = B_FALSE;
|
||||
switch (fid) {
|
||||
case F_EVASION:
|
||||
case F_BONUS:
|
||||
res = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
res = B_FALSE;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
flag_t *hasflag(flagpile_t *fp, int id) {
|
||||
return hasflag_real(fp, id, NA);
|
||||
}
|
||||
|
||||
flag_t *hasflagknown(flagpile_t *fp, int id) {
|
||||
return hasflag_real(fp, id, B_TRUE);
|
||||
}
|
||||
|
||||
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown) {
|
||||
flag_t *f;
|
||||
lifeform_t *owner;
|
||||
owner = fp->owner;
|
||||
|
||||
for (f = fp->first ; f ; f = f->next) {
|
||||
if (f->id == id) {
|
||||
if ( ((val1 == NA) || (f->val[0] == val1)) &&
|
||||
((val2 == NA) || (f->val[1] == val2)) &&
|
||||
((val3 == NA) || (f->val[2] == val3)) &&
|
||||
((text == NULL) || strstr(f->text, text))) {
|
||||
int valid = B_TRUE;
|
||||
if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE;
|
||||
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) {
|
||||
valid = B_FALSE;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
@ -85,9 +172,79 @@ flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *t
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text) {
|
||||
return hasflagval_real(fp, id, val1, val2, val3, text, B_FALSE); // doesn't have to be known
|
||||
}
|
||||
|
||||
flag_t *hasflagvalknown(flagpile_t *fp, int id, int val1, int val2, int val3, char *text) {
|
||||
return hasflagval_real(fp, id, val1, val2, val3, text, B_TRUE); // must be known
|
||||
}
|
||||
|
||||
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown) {
|
||||
flag_t *f;
|
||||
lifeform_t *owner;
|
||||
owner = fp->owner;
|
||||
for (f = fp->first ; f ; f = f->next) {
|
||||
if (f->id == id) {
|
||||
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) {
|
||||
// invalid
|
||||
} else {
|
||||
if ( ((val1 == NA) || (f->val[0] == val1)) &&
|
||||
((val2 == NA) || (f->val[1] == val2)) &&
|
||||
((val3 == NA) || (f->val[2] == val3)) &&
|
||||
((text == NULL) || strstr(f->text, text))) {
|
||||
if (!wantknown || f->known) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void killflagsofid(flagpile_t *fp, enum FLAG fid) {
|
||||
flag_t *f,*nextf;
|
||||
for (f = fp->first ; f ; f = nextf) {
|
||||
nextf = f->next;
|
||||
if (f->id == fid) {
|
||||
killflag(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void killflag(flag_t *f) {
|
||||
int i;
|
||||
flag_t *nextone, *lastone;
|
||||
lifeform_t *lf;
|
||||
int needredraw = B_FALSE;
|
||||
|
||||
lf = f->pile->owner;
|
||||
|
||||
if (isplayer(lf)) {
|
||||
switch (f->id) {
|
||||
case F_BLIND:
|
||||
case F_SEEINDARK:
|
||||
needredraw = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// notify
|
||||
if (gamestarted) {
|
||||
if (f->pile->owner) {
|
||||
announceflagloss(f->pile->owner, f);
|
||||
} else if (f->pile->ob) {
|
||||
announceobflagloss(f->pile->ob, f);
|
||||
}
|
||||
}
|
||||
|
||||
// we will revert to our original form at the end of timeeffectslf().
|
||||
if (lf && (f->id == F_POLYMORPHED)) {
|
||||
lf->polyrevert = B_TRUE;
|
||||
}
|
||||
|
||||
// free mem
|
||||
|
||||
|
@ -109,6 +266,10 @@ void killflag(flag_t *f) {
|
|||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
|
||||
if (gamestarted && needredraw) {
|
||||
drawscreen();
|
||||
}
|
||||
}
|
||||
|
||||
void killflagpile(flagpile_t *fp) {
|
||||
|
@ -118,3 +279,99 @@ void killflagpile(flagpile_t *fp) {
|
|||
free(fp);
|
||||
}
|
||||
|
||||
void timeeffectsflag(flag_t *f) {
|
||||
if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) {
|
||||
f->lifetime--;
|
||||
if (f->lifetime <= 0) {
|
||||
killflag(f);
|
||||
return;
|
||||
} else if (f->lifetime == 5) {
|
||||
// warn about certain flags......
|
||||
if (isplayer(f->pile->owner)) {
|
||||
switch (f->id) {
|
||||
case F_CANWILL:
|
||||
switch (f->val[0]) {
|
||||
case OT_A_JUMP:
|
||||
warn("Your ability to jump is starting to run out...");;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case F_DTIMMUNE:
|
||||
warn("Your %s immunity is starting to run out...", getdamname(f->val[0]));
|
||||
break;
|
||||
case F_DTRESIST:
|
||||
warn("Your %s resistance is starting to run out...", getdamname(f->val[0]));
|
||||
break;
|
||||
case F_DTVULN:
|
||||
warn("You feel a little less vulnerable to %s...", getdamname(f->val[0]));
|
||||
break;
|
||||
case F_MAGSHIELD:
|
||||
warn("Your magnetic shield is weakening...");
|
||||
break;
|
||||
case F_POLYMORPHED:
|
||||
warn("You are starting to revert to your original form...");
|
||||
break;
|
||||
default: // no message
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (f->lifetime == 1) {
|
||||
// warn about certain flags......
|
||||
if (isplayer(f->pile->owner)) {
|
||||
switch (f->id) {
|
||||
case F_CANWILL:
|
||||
switch (f->val[0]) {
|
||||
case OT_A_JUMP:
|
||||
warn("Your ability to jump is about to expire!");;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case F_DTIMMUNE:
|
||||
warn("Your %s immunity is about to expire!", getdamname(f->val[0]));
|
||||
break;
|
||||
case F_DTRESIST:
|
||||
warn("Your %s resistance is about to expire!", getdamname(f->val[0]));
|
||||
break;
|
||||
case F_DTVULN:
|
||||
warn("You feel a little less vulnerable to %s...", getdamname(f->val[0]));
|
||||
break;
|
||||
case F_MAGSHIELD:
|
||||
warn("Your magnetic shield is about to expire!");
|
||||
break;
|
||||
case F_POLYMORPHED:
|
||||
warn("You are about to revert to your original form!");
|
||||
break;
|
||||
default: // no message
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2) {
|
||||
flag_t *f;
|
||||
if (val0) *val0 = 0;
|
||||
if (val1) *val1 = 0;
|
||||
if (val2) *val2 = 0;
|
||||
for (f = fp->first ; f ; f = f->next) {
|
||||
if (f->id == id) {
|
||||
if (val0) *val0 = *val0 + f->val[0];
|
||||
if (val1) *val1 = *val1 + f->val[1];
|
||||
if (val2) *val2 = *val2 + f->val[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void timeeffectsflags(flagpile_t *fp) {
|
||||
flag_t *f,*nextf;
|
||||
for (f = fp->first ; f ; f = nextf) {
|
||||
nextf = f->next;
|
||||
timeeffectsflag(f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
15
flag.h
15
flag.h
|
@ -3,8 +3,21 @@
|
|||
|
||||
// functions
|
||||
flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text);
|
||||
flagpile_t *addflagpile(void);
|
||||
flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft);
|
||||
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known);
|
||||
flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
|
||||
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
|
||||
int flagstacks(enum FLAG fid);
|
||||
flag_t *hasflag(flagpile_t *fp, int id);
|
||||
flag_t *hasflagknown(flagpile_t *fp, int id);
|
||||
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown);
|
||||
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text);
|
||||
flag_t *hasflagvalknown(flagpile_t *fp, int id, int val1, int val2, int val3, char *text);
|
||||
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown);
|
||||
void killflagsofid(flagpile_t *fp, enum FLAG fid);
|
||||
void killflag(flag_t *f);
|
||||
void killflagpile(flagpile_t *fp);
|
||||
void makeflagknown(flagpile_t *fp);
|
||||
void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2);
|
||||
void timeeffectsflag(flag_t *f);
|
||||
void timeeffectsflags(flagpile_t *fp);
|
||||
|
|
59
io.h
59
io.h
|
@ -1,23 +1,58 @@
|
|||
#include <ncurses.h>
|
||||
#include "defs.h"
|
||||
|
||||
void addchoice(prompt_t *p, char ch, char *text, char *desc, void *data);
|
||||
void addheading(prompt_t *p, char *text);
|
||||
void addmsghist(char *text);
|
||||
void anim(cell_t *src, cell_t *dst, char ch);
|
||||
void animradial(cell_t *src, int radius, char ch);
|
||||
//void announceob(enum OBTYPE oid);
|
||||
int announceflaggain(lifeform_t *lf, flag_t *f);
|
||||
void announceflagloss(lifeform_t *lf, flag_t *f);
|
||||
int announceobflaggain(object_t *o, flag_t *f);
|
||||
void announceobflagloss(object_t *o, flag_t *f);
|
||||
object_t *askobject(obpile_t *op, char *title, int *count, int opts);
|
||||
object_t *askobjectwithflag(obpile_t *op, char *title, int *count, int opts, enum FLAG withflag);
|
||||
object_t *askobjectofclass(obpile_t *op, char *title, int *count, int opts, enum OBCLASS obclass);
|
||||
object_t *doaskobject(obpile_t *op, char *title, int *count, int opts, enum OBCLASS obclass);
|
||||
cell_t *askcoords(char *prompt);
|
||||
object_t *doaskobject(obpile_t *op, char *title, int *count, int opts, enum OBCLASS obclass, enum FLAG withflag);
|
||||
int askobjectmulti(obpile_t *op, char *prompt, int opts);
|
||||
char askchar(char *prompt, char *validchars, char *def, int showchars);
|
||||
cell_t *askcoords(char *prompt, int targettype);
|
||||
char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def);
|
||||
void centre(WINDOW *win, int y, char *format, ... );
|
||||
int chartodir(char ch);
|
||||
int cleanupgfx(void);
|
||||
void clearmsg(void);
|
||||
void real_clearmsg(int force);
|
||||
void clearretobs(void);
|
||||
void cls(void);
|
||||
void describeob(object_t *o);
|
||||
void dodrop(obpile_t *op);
|
||||
void doattackcell(char dirch);
|
||||
void doclose(void);
|
||||
void dodrop(obpile_t *op, int wantmulti);
|
||||
void doeat(obpile_t *op);
|
||||
void doenter(lifeform_t *lf);
|
||||
void doexplain(void);
|
||||
void dofinaloblist(obpile_t *op);
|
||||
void dofire(void);
|
||||
void doinventory(obpile_t *op);
|
||||
void doknowledgelist(void);
|
||||
void dolook(cell_t *where);
|
||||
void domagic(enum OBTYPE spellid, int cellx, int celly);
|
||||
void domsghist(void);
|
||||
void dooperate(obpile_t *op);
|
||||
int dopickup(obpile_t *op);
|
||||
void dolockpick(obpile_t *op);
|
||||
void donextguntarget(void);
|
||||
void dopour(obpile_t *op);
|
||||
void doquit(void);
|
||||
void doquaff(obpile_t *op);
|
||||
void doread(obpile_t *op);
|
||||
void dorest(void);
|
||||
void doselguntarget(void);
|
||||
void dostairs(int dir);
|
||||
int dotakeoff(obpile_t *op);
|
||||
void dothrow(obpile_t *op);
|
||||
void dovendingmachine(lifeform_t *lf, object_t *vm);
|
||||
int dowear(obpile_t *op);
|
||||
int doweild(obpile_t *op);
|
||||
void drawunviscell(cell_t *cell, int x, int y);
|
||||
|
@ -27,17 +62,25 @@ void drawlevelfor(lifeform_t *lf);
|
|||
void drawmsg(void);
|
||||
void drawscreen(void);
|
||||
void drawstatus(void);
|
||||
int drop(object_t *o, int count);
|
||||
char getchoice(prompt_t *prompt);
|
||||
char getchoicestr(prompt_t *prompt);
|
||||
int getkey(void);
|
||||
void handleinput(void);
|
||||
void initgfx(void);
|
||||
void initprompt(prompt_t *p, char *q1);
|
||||
int keycodetokey(int keycode);
|
||||
void more(void);
|
||||
void warn(char *format, ... );
|
||||
void msg(char *format, ... );
|
||||
int pickup(lifeform_t *lf, object_t *what, int howmany);
|
||||
void msglower(char *format, ... );
|
||||
void msg_real(char *format, ... );
|
||||
void nothinghappens(void);
|
||||
void dblog(char *format, ... );
|
||||
void redraw(void);
|
||||
int savequit(void);
|
||||
int takeoff(lifeform_t *lf, object_t *o);
|
||||
void showlfarmour(lifeform_t *lf);
|
||||
void showlfstats(lifeform_t *lf, int showall);
|
||||
void tombstone(lifeform_t *lf);
|
||||
void updatestatus(void);
|
||||
void updateviewfor(cell_t *cell);
|
||||
int wear(lifeform_t *lf, object_t *o);
|
||||
int weild(lifeform_t *lf, object_t *o);
|
||||
|
|
144
lf.h
144
lf.h
|
@ -1,34 +1,162 @@
|
|||
#include "defs.h"
|
||||
|
||||
|
||||
lifeform_t *addlf(cell_t *cell, enum RACE rid, int level);
|
||||
race_t *addrace(enum RACE id, char *name, char glyph);
|
||||
lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller);
|
||||
job_t *addjob(enum JOB id, char *name);
|
||||
race_t *addrace(enum RACE id, char *name, float weight, char glyph, enum MATERIAL mat);
|
||||
void adjustdamlf(lifeform_t *lf, unsigned int *amt, enum DAMTYPE damtype);
|
||||
void autotarget(lifeform_t *lf);
|
||||
void autoweild(lifeform_t *lf);
|
||||
int appearsrandomly(enum RACE rid);
|
||||
void bleed(lifeform_t *lf);
|
||||
int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost);
|
||||
int caneat(lifeform_t *lf, object_t *o);
|
||||
int canhear(lifeform_t *lf, cell_t *c);
|
||||
int canpickup(lifeform_t *lf, object_t *o);
|
||||
int canwear(lifeform_t *lf, object_t *o);
|
||||
int canpush(lifeform_t *lf, object_t *o, int dir);
|
||||
int canquaff(lifeform_t *lf, object_t *o);
|
||||
int canrest(lifeform_t *lf);
|
||||
int canwear(lifeform_t *lf, object_t *o, enum BODYPART where);
|
||||
int canweild(lifeform_t *lf, object_t *o);
|
||||
int cantakeoff(lifeform_t *lf, object_t *o);
|
||||
int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell);
|
||||
void die(lifeform_t *lf);
|
||||
void dumplf(void);
|
||||
int eat(lifeform_t *lf, object_t *o);
|
||||
object_t *eyesshaded(lifeform_t *lf);
|
||||
void fightback(lifeform_t *lf, lifeform_t *attacker);
|
||||
job_t *findjob(enum JOB jobid);
|
||||
lifeform_t *findlf(map_t *m, int lfid);
|
||||
race_t *findrace(enum RACE id);
|
||||
race_t *findracebyname(char *name);
|
||||
int flee(lifeform_t *lf);
|
||||
void gainhp(lifeform_t *lf, int amt);
|
||||
int getarmour(lifeform_t *lf);
|
||||
void gainlevel(lifeform_t *lf);
|
||||
void gainmp(lifeform_t *lf, int amt);
|
||||
void gainxp(lifeform_t *lf, long amt);
|
||||
object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
|
||||
int getarmourrating(lifeform_t *lf);
|
||||
int getattackspeed(lifeform_t *lf);
|
||||
int getattr(lifeform_t *lf, enum ATTRIB attr);
|
||||
int getdexmod(lifeform_t *lf);
|
||||
int getevasion(lifeform_t *lf);
|
||||
object_t *getbestmissile(lifeform_t *lf);
|
||||
object_t *getbestweapon(lifeform_t *lf);
|
||||
object_t *getbestfirearm(lifeform_t *lf);
|
||||
int getbodyparthitchance(enum BODYPART bp);
|
||||
char *getbodypartname(enum BODYPART bp);
|
||||
char *getbodypartequipname(enum BODYPART bp);
|
||||
object_t *getequippedob(obpile_t *op, enum BODYPART bp);
|
||||
int getlfattackspeed(lifeform_t *lf);
|
||||
object_t *getfirearm(lifeform_t *lf);
|
||||
lifeform_t *getguntarget(lifeform_t *lf);
|
||||
int getguntargetid(lifeform_t *lf);
|
||||
//int gethealtime(lifeform_t *lf);
|
||||
int gethearingrange(lifeform_t *lf);
|
||||
enum HUNGER gethungerlevel(int hunger);
|
||||
char * gethungername(enum HUNGER hunger, char *buf);
|
||||
int gethungerval(lifeform_t *lf);
|
||||
job_t *getjob(lifeform_t *lf);
|
||||
int getlfaccuracy(lifeform_t *lf);
|
||||
enum LFCONDITION getlfcondition(lifeform_t *lf);
|
||||
int getnightvisrange(lifeform_t *lf);
|
||||
char *getlfconditionname(enum LFCONDITION cond);
|
||||
char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer);
|
||||
enum MATERIAL getlfmaterial(lifeform_t *lf);
|
||||
float getmaxcarryweight(lifeform_t *lf);
|
||||
float getmaxliftweight(lifeform_t *lf);
|
||||
float getmaxpushweight(lifeform_t *lf);
|
||||
int getvisrange(lifeform_t *lf);
|
||||
int getmovespeed(lifeform_t *lf);
|
||||
char *getmoveverb(lifeform_t *lf);
|
||||
char *getlfname(lifeform_t *lf, char *buf);
|
||||
race_t *getrandomlf(map_t *map, int *level);
|
||||
char *getlfnamea(lifeform_t *lf, char *buf);
|
||||
enum LFSIZE getlfsize(lifeform_t *lf);
|
||||
float getlfweight(lifeform_t *lf, int withobs);
|
||||
int getspellspeed(lifeform_t *lf);
|
||||
char *getplayername(char *buf);
|
||||
char *getplayernamefull(char *buf);
|
||||
object_t *getrandomarmour(lifeform_t *lf);
|
||||
//int getrandommonlevel(int depth);
|
||||
race_t *getrandomrace(map_t *map);
|
||||
race_t *getreallyrandomrace(void);
|
||||
char *getspeedname(int speed, char *buf);
|
||||
float getstatmod(lifeform_t *lf, enum ATTRIB att);
|
||||
enum STRBRACKET getstrname(int str, char *buf);
|
||||
enum DEXBRACKET getdexname(int dex, char *buf);
|
||||
enum IQBRACKET getiqname(int iq, char *buf);
|
||||
int getthrowspeed(int str);
|
||||
int getunarmedattackspeed(lifeform_t *lf);
|
||||
object_t *getweapon(lifeform_t *lf);
|
||||
long getxpforlev(int level);
|
||||
void givejob(lifeform_t *lf, enum JOB jobid);
|
||||
void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype);
|
||||
void givestartobs(lifeform_t *lf, flagpile_t *fp);
|
||||
map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs);
|
||||
job_t *hasjob(lifeform_t *lf, enum JOB job);
|
||||
flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid);
|
||||
flag_t *lfhasflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, char *text);
|
||||
flag_t *lfhasknownflag(lifeform_t *lf, enum FLAG fid);
|
||||
flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, char *text);
|
||||
int lockpick(lifeform_t *lf, object_t *target, object_t *device);
|
||||
void loseobflags(lifeform_t *lf, object_t *o, int kind);
|
||||
int haslof(lifeform_t *viewer, cell_t *dest);
|
||||
int haslos(lifeform_t *viewer, cell_t *dest);
|
||||
int hasmr(lifeform_t *lf);
|
||||
void initjobs(void);
|
||||
void initrace(void);
|
||||
void interrupt(lifeform_t *lf);
|
||||
int isbleeding(lifeform_t *lf);
|
||||
int isblind(lifeform_t *lf);
|
||||
enum BURDENED isburdened(lifeform_t *lf);
|
||||
int isdead(lifeform_t *lf);
|
||||
int isfleeing(lifeform_t *lf);
|
||||
int isfreebp(lifeform_t *lf, enum BODYPART bp);
|
||||
int isgenius(lifeform_t *lf);
|
||||
int isingunrange(lifeform_t *lf, cell_t *where);
|
||||
int isimmobile(lifeform_t *lf);
|
||||
int ispeaceful(lifeform_t *lf);
|
||||
int isplayer(lifeform_t *lf);
|
||||
int ispolymorphed(lifeform_t *lf);
|
||||
void killjob(job_t *job);
|
||||
void killlf(lifeform_t *lf);
|
||||
void killrace(race_t *race);
|
||||
void losehp(lifeform_t *lf, int amt, int damtype, lifeform_t *fromlf, char *damsrc);
|
||||
int losehp(lifeform_t *lf, unsigned int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc);
|
||||
int losehp_real(lifeform_t *lf, unsigned int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam);
|
||||
void makenoise(lifeform_t *lf, enum NOISETYPE nid);
|
||||
void maycastspellschool(flagpile_t *fp, enum SPELLSCHOOL ss);
|
||||
int modattr(lifeform_t *lf, enum ATTRIB attr, int amt);
|
||||
void modhunger(lifeform_t *lf, int amt);
|
||||
void outfitlf(lifeform_t *lf);
|
||||
void taketime(lifeform_t *lf, int howlong);
|
||||
int pickup(lifeform_t *lf, object_t *what, int howmany);
|
||||
void precalclos(lifeform_t *lf);
|
||||
int push(lifeform_t *lf, object_t *o, int dir);
|
||||
void relinklf(lifeform_t *src, map_t *dst);
|
||||
int rest(lifeform_t *lf, int onpurpose);
|
||||
void startresting(lifeform_t *lf);
|
||||
int rolldex(enum DEXBRACKET bracket);
|
||||
int rolliq(enum IQBRACKET bracket);
|
||||
int rollstr(enum STRBRACKET bracket);
|
||||
int savingthrow(lifeform_t *lf, enum ATTRIB attr);
|
||||
int scare(lifeform_t *lf, lifeform_t *scarer, int howlong);
|
||||
int setammo(lifeform_t *lf, object_t *o);
|
||||
void setattr(lifeform_t *lf, enum ATTRIB attr, int val);
|
||||
void setguntarget(lifeform_t *lf, lifeform_t *targ);
|
||||
void setrace(lifeform_t *lf, enum RACE rid);
|
||||
void setlastdam(lifeform_t *lf, char *buf);
|
||||
int shoot(lifeform_t *lf);
|
||||
void sortlf(map_t *map, lifeform_t *lf);
|
||||
void stopresting(lifeform_t *lf);
|
||||
void stoprunning(lifeform_t *lf);
|
||||
int takeoff(lifeform_t *lf, object_t *o);
|
||||
void taketime(lifeform_t *lf, long howlong);
|
||||
int throwat(lifeform_t *thrower, object_t *o, cell_t *where);
|
||||
void timeeffectslf(lifeform_t *lf);
|
||||
void turneffectslf(lifeform_t *lf);
|
||||
int touch(lifeform_t *lf, object_t *o);
|
||||
int unweild(lifeform_t *lf, object_t *o);
|
||||
int useability(lifeform_t *lf, enum OBTYPE aid);
|
||||
int usestairs(lifeform_t *lf, object_t *o);
|
||||
int validateraces(void);
|
||||
int wear(lifeform_t *lf, object_t *o);
|
||||
int weild(lifeform_t *lf, object_t *o);
|
||||
int youhear(cell_t *c, char *text);
|
||||
|
|
703
map.c
703
map.c
|
@ -4,15 +4,21 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "io.h"
|
||||
#include "move.h"
|
||||
#include "nexus.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "objects.h"
|
||||
#include "text.h"
|
||||
|
||||
extern map_t *firstmap,*lastmap;
|
||||
extern int viewx,viewy,vieww,viewh;
|
||||
extern lifeform_t *player;
|
||||
|
||||
extern enum OBCLASS sortorder[];
|
||||
|
||||
cell_t *addcell(map_t *m, int x, int y) {
|
||||
cell_t *cell;
|
||||
m->cell[(y*m->w)+x] = malloc(sizeof(cell_t));
|
||||
|
@ -25,6 +31,9 @@ cell_t *addcell(map_t *m, int x, int y) {
|
|||
cell->obpile = addobpile(NOOWNER, cell);
|
||||
cell->lf = NULL;
|
||||
cell->roomid = -1;
|
||||
cell->lit = B_FALSE;
|
||||
cell->writing = NULL;
|
||||
return cell;
|
||||
}
|
||||
|
||||
map_t *addmap(void) {
|
||||
|
@ -56,33 +65,214 @@ map_t *addmap(void) {
|
|||
// props
|
||||
a->id = id;
|
||||
a->lf = NULL;
|
||||
a->nextlfid = 0;
|
||||
for (i = 0; i < MAXDIR_ORTH; i++) {
|
||||
a->nextmap[i] = -1;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void addrandomthing(cell_t *c) {
|
||||
char buf[BUFLEN];
|
||||
int level;
|
||||
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid) {
|
||||
lifeform_t *lf = NULL;
|
||||
race_t *r;
|
||||
|
||||
// ie. don't create mosnters on closed doors!
|
||||
if (!cellwalkable(NULL, c, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((raceid == R_NONE) || (raceid == R_RANDOM)) {
|
||||
r = getrandomrace(c->map);
|
||||
} else {
|
||||
r = findrace(raceid);
|
||||
}
|
||||
assert(r);
|
||||
|
||||
dblog("adding rand lf %s to cell %d,%d",r->name,c->x,c->y);
|
||||
|
||||
if (r) {
|
||||
//lf = addlf(c, r->id, getrandommonlevel(c->map->depth));
|
||||
lf = addlf(c, r->id, 1);
|
||||
if (lf) {
|
||||
int amt;
|
||||
flag_t *f;
|
||||
// appears in groups?
|
||||
f = hasflag(lf->flags, F_NUMAPPEAR);
|
||||
if (f) {
|
||||
amt = rnd(f->val[0], f->val[1]);
|
||||
} else {
|
||||
amt = 1;
|
||||
}
|
||||
if (amt > 1) {
|
||||
cell_t *adjcell;
|
||||
amt--; // we've already added one
|
||||
adjcell = c;
|
||||
for ( ; amt > 0; amt--) {
|
||||
// add more in adjacent cells
|
||||
adjcell = getrandomadjcell(adjcell, WE_NOTSOLID);
|
||||
if (!adjcell) break;
|
||||
|
||||
//lf = addlf(adjcell, r->id, getrandommonlevel(adjcell->map->depth));
|
||||
lf = addlf(adjcell, r->id, 1);
|
||||
if (!lf) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return lf;
|
||||
}
|
||||
|
||||
void addrandomob(cell_t *c) {
|
||||
char buf[BUFLEN];
|
||||
|
||||
if (c->type->solid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getrandomob(c->map, buf)) {
|
||||
dblog("adding rand obj %s to cell %d,%d",buf,c->x,c->y);
|
||||
addob(c->obpile, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void addrandomthing(cell_t *c) {
|
||||
// if there's already someone there,
|
||||
// then add an object.
|
||||
if (c->lf || (rnd(1,2) == 1)) {
|
||||
// object
|
||||
if (getrandomob(c->map, buf)) {
|
||||
dblog("adding %s to cell %d,%d",buf,c->x,c->y);
|
||||
addob(c->obpile, buf);
|
||||
}
|
||||
addrandomob(c);
|
||||
} else {
|
||||
r = getrandomlf(c->map, &level);
|
||||
if (r) {
|
||||
dblog("adding %s to cell %d,%d",buf,c->x,c->y);
|
||||
addlf(c, r->id, level);
|
||||
// monster
|
||||
addmonster(c, R_RANDOM);
|
||||
}
|
||||
}
|
||||
|
||||
int cellhaslos(cell_t *c1, cell_t *dest) {
|
||||
int deltax, deltay;
|
||||
int numpixels;
|
||||
int d;
|
||||
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
|
||||
int xinc,yinc,dinc;
|
||||
int i;
|
||||
int x1,y1;
|
||||
int x;
|
||||
int y;
|
||||
//int wentuphill = B_FALSE;
|
||||
//int origheight;
|
||||
//int shopwall;
|
||||
int x2,y2;
|
||||
map_t *map;
|
||||
|
||||
if (!dest) return B_FALSE;
|
||||
|
||||
// let the player see when dead, otherwise the screen wil
|
||||
// go black when "You die" appears.
|
||||
map = c1->map;
|
||||
|
||||
|
||||
x1 = c1->x;
|
||||
y1 = c1->y;
|
||||
x2 = dest->x;
|
||||
y2 = dest->y;
|
||||
|
||||
|
||||
|
||||
deltax = (x2 - x1);
|
||||
if (deltax < 0) deltax = -deltax;
|
||||
deltay = (y2 - y1);
|
||||
if (deltay < 0) deltay = -deltay;
|
||||
|
||||
// can always see your own cell
|
||||
if ((deltax == 0) && (deltay == 0)) {
|
||||
//if (viewer->controller == C_HUMAN) wreck->mazelev[z].maze[y2*MAZEW+x2].known = B_PERM;
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (deltax >= deltay) {
|
||||
numpixels = deltax + 1;
|
||||
d = (deltay*2) - deltax;
|
||||
dinc1 = deltay << 1;
|
||||
dinc2 = (deltay-deltax) << 1;
|
||||
xinc1 = 1;
|
||||
xinc2 = 1;
|
||||
yinc1 = 0;
|
||||
yinc2 = 1;
|
||||
} else {
|
||||
numpixels = deltay + 1;
|
||||
d = (deltax*2) - deltay;
|
||||
dinc1 = deltax << 1;
|
||||
dinc2 = (deltax - deltay) << 1;
|
||||
xinc1 = 0;
|
||||
xinc2 = 1;
|
||||
yinc1 = 1;
|
||||
yinc2 = 1;
|
||||
}
|
||||
|
||||
if (x1 > x2) {
|
||||
xinc1 = - xinc1;
|
||||
xinc2 = - xinc2;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
yinc1 = - yinc1;
|
||||
yinc2 = - yinc2;
|
||||
}
|
||||
|
||||
x = x1; y = y1;
|
||||
|
||||
for (i = 0; i < numpixels ; i++) {
|
||||
cell_t *cell;
|
||||
|
||||
// don't need to move out of the last one
|
||||
if ((x == x2) && (y == y2)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (d < 0) {
|
||||
xinc = xinc1;
|
||||
yinc = yinc1;
|
||||
dinc = dinc1;
|
||||
} else {
|
||||
xinc = xinc2;
|
||||
yinc = yinc2;
|
||||
dinc = dinc2;
|
||||
}
|
||||
|
||||
|
||||
// you can always see your own cell
|
||||
if (i != 0) {
|
||||
// solid cells stop los - but if you are standing on a solid
|
||||
// cell you can still see out.
|
||||
cell = getcellat(map, x, y);
|
||||
if (!cell->type->transparent) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
// check for smoke
|
||||
if ((x != x1) || (y != y1)) { // if not in first cell
|
||||
if (hasopaqueobject(viewer, x,y,z) && (getheight(x,y,z) >= origheight)) {
|
||||
if (!hasproplf(viewer, P_SEEINSMOKE)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// check for objects which block view
|
||||
if (hasobwithflag(cell->obpile, F_BLOCKSVIEW)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// move to next cell
|
||||
d += dinc;
|
||||
x += xinc;
|
||||
y += yinc;
|
||||
}
|
||||
|
||||
// made it to the target cell!
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
cell_t *getcellat(map_t *map, int x, int y) {
|
||||
|
@ -98,6 +288,87 @@ int getcelldist(cell_t *src, cell_t *dst) {
|
|||
return (int)sqrt(xd*xd + yd*yd);
|
||||
}
|
||||
|
||||
int getcelldistorth(cell_t *src, cell_t *dst) { // add x/y
|
||||
return abs(dst->x - src->x) + abs(dst->y - src->y);
|
||||
}
|
||||
|
||||
enum CELLTYPE getemptycelltype(enum HABITAT hab) {
|
||||
switch (hab) {
|
||||
case H_DUNGEON:
|
||||
return CT_CORRIDOR;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CT_CORRIDOR;
|
||||
}
|
||||
|
||||
object_t *gettopobject(cell_t *where) {
|
||||
object_t *o;
|
||||
int c;
|
||||
// draw highest object in sort order
|
||||
c = 0;
|
||||
while (sortorder[c] != OC_NULL) {
|
||||
// check each object against this ob class
|
||||
// count backwards so more recently dropped objects
|
||||
// appear first.
|
||||
for (o = where->obpile->last ; o ; o = o->prev) {
|
||||
if (o->type->obclass->id == sortorder[c]) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void calclight(map_t *map) {
|
||||
int x,y;
|
||||
cell_t *c;
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
c = getcellat(map, x,y);
|
||||
if (c && (c->lit != B_PERM)) c->lit = B_FALSE;
|
||||
}
|
||||
}
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
c = getcellat(map, x,y);
|
||||
if (c) {
|
||||
int radius;
|
||||
object_t *o;
|
||||
// lit based on depth
|
||||
if (map->depth <= 5) {
|
||||
c->lit = B_PERM;
|
||||
}
|
||||
// has lightproducing lf? (ie.hasflag f_produceslight)
|
||||
if (c->lf) {
|
||||
if (lfhasflag(c->lf, F_PRODUCESLIGHT)) {
|
||||
sumflags(c->lf->flags, F_PRODUCESLIGHT, &radius, NULL, NULL);
|
||||
|
||||
makelitradius(c, radius, B_TEMP);
|
||||
}
|
||||
// objects in hands or on body...
|
||||
for (o = c->lf->pack->first ; o ; o = o->next) {
|
||||
if (obproduceslight(o) && isequipped(o)) {
|
||||
sumflags(o->flags, F_PRODUCESLIGHT, &radius, NULL, NULL);
|
||||
|
||||
makelitradius(c, radius, B_TEMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
// has light-producing object on ground?
|
||||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
if (obproduceslight(o)) {
|
||||
sumflags(o->flags, F_PRODUCESLIGHT, &radius, NULL, NULL);
|
||||
makelitradius(c, radius, B_TEMP);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int calcroompos(map_t *map, int w, int h, int *bx, int *by) {
|
||||
int x,y;
|
||||
int bestx = -1, besty = -1;
|
||||
|
@ -159,6 +430,19 @@ int calcroompos(map_t *map, int w, int h, int *bx, int *by) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int countadjcellswithflag(cell_t *cell, enum FLAG fid) {
|
||||
int d;
|
||||
int count = 0;
|
||||
cell_t *newcell;
|
||||
for (d = D_N; d < MAXDIR_ORTH; d++) {
|
||||
newcell = getcellindir(cell, d);
|
||||
if (newcell && hasobwithflag(cell->obpile, fid)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int countadjcellsoftype(cell_t *cell, int id) {
|
||||
int d;
|
||||
int count = 0;
|
||||
|
@ -193,11 +477,10 @@ int countcellexits(cell_t *cell) {
|
|||
looppct = percentage change of turning dead-end into loop
|
||||
maxrooms = max # of rooms
|
||||
*/
|
||||
void createmap(map_t *map, int habitat) {
|
||||
lifeform_t *lf;
|
||||
void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_t *returnstairtype) {
|
||||
char buf[BUFLEN];
|
||||
int wantrooms = B_TRUE;
|
||||
int x,y,newx,newy;
|
||||
int x,y;
|
||||
int d;
|
||||
int i;
|
||||
int done,unused;
|
||||
|
@ -212,9 +495,10 @@ void createmap(map_t *map, int habitat) {
|
|||
int maxroomh = MAX_ROOMH;
|
||||
int bestx,besty;
|
||||
int w,h;
|
||||
int startdir,forcex,forcey,ntries;
|
||||
cell_t *cell;
|
||||
//object_t *o;
|
||||
objecttype_t *ot;
|
||||
//int startdir,forcex,forcey,ntries;
|
||||
cell_t *cell, *c;
|
||||
object_t *o;
|
||||
|
||||
// parameters
|
||||
int turnpct = DEF_TURNPCT;
|
||||
|
@ -225,7 +509,9 @@ void createmap(map_t *map, int habitat) {
|
|||
|
||||
int moved = 0;
|
||||
|
||||
int db = B_TRUE;
|
||||
enum CELLTYPE emptycell;
|
||||
|
||||
//int db = B_TRUE;
|
||||
|
||||
sprintf(buf, "Map %d",map->id);
|
||||
map->name = strdup(buf);
|
||||
|
@ -238,8 +524,13 @@ void createmap(map_t *map, int habitat) {
|
|||
map->w = MAX_MAPW;
|
||||
map->h = MAX_MAPH;
|
||||
|
||||
// map depth?
|
||||
map->depth = depth;
|
||||
|
||||
// rememebr seed
|
||||
//map->seed = 11734;
|
||||
map->seed = rand() % 65535;
|
||||
srand(map->seed);
|
||||
|
||||
// fill entire maze with walls
|
||||
for (y = 0; y < map->h; y++) {
|
||||
|
@ -248,9 +539,14 @@ void createmap(map_t *map, int habitat) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// what kind of cells will 'empty' ones be?
|
||||
emptycell = getemptycelltype(map->habitat);
|
||||
|
||||
// pick initial random spot
|
||||
cell = getrandomcell(map);
|
||||
setcelltype(cell, CT_CORRIDOR);
|
||||
|
||||
setcelltype(cell, emptycell);
|
||||
cell->visited = B_TRUE;
|
||||
//if (db) printf("- Starting (%d,%d)\n",cell->x, cell->y);
|
||||
|
||||
|
@ -279,7 +575,7 @@ void createmap(map_t *map, int habitat) {
|
|||
|
||||
// pick new EMPTY random spot
|
||||
cell = getrandomcell(map);
|
||||
while (cell->type->solid) {
|
||||
while (!isempty(cell)) {
|
||||
cell = getrandomcell(map);
|
||||
}
|
||||
//if (db) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",cell->x, cell->y);
|
||||
|
@ -298,7 +594,7 @@ void createmap(map_t *map, int habitat) {
|
|||
moved++;
|
||||
|
||||
// blank it
|
||||
setcelltype(cell,CT_CORRIDOR);
|
||||
setcelltype(cell,emptycell);
|
||||
cell->visited = B_TRUE;
|
||||
// mark surrounding cells as visited
|
||||
for (d = DC_N; d < MAXDIR_COMPASS; d++) {
|
||||
|
@ -399,7 +695,7 @@ void createmap(map_t *map, int habitat) {
|
|||
connected = B_TRUE;
|
||||
} else {
|
||||
// blank adjacent cell
|
||||
setcelltype(newcell, CT_CORRIDOR);
|
||||
setcelltype(newcell, emptycell);
|
||||
newcell->visited = B_TRUE;
|
||||
}
|
||||
cell = newcell;
|
||||
|
@ -454,6 +750,29 @@ void createmap(map_t *map, int habitat) {
|
|||
}
|
||||
|
||||
|
||||
// add return staircase to previous map
|
||||
c = NULL;
|
||||
while (!c || !isempty(c) || countobs(c->obpile)) {
|
||||
c = getrandomroomcell(map, ANYROOM);
|
||||
}
|
||||
|
||||
o = addob(c->obpile, returnstairtype->name);
|
||||
if (parentmap) {
|
||||
addflag(o->flags, F_MAPLINK, parentmap->id, NA, NA, NULL);
|
||||
}
|
||||
|
||||
// add staircase continuing on (normally this will be down)
|
||||
if ((map->depth >= MAXDEPTH) && (returnstairtype->id == OT_STAIRSUP)) {
|
||||
// no need for a down staircase on the last level!
|
||||
} else {
|
||||
c = NULL;
|
||||
while (!c || !isempty(c) || countobs(c->obpile)) {
|
||||
c = getrandomroomcell(map, ANYROOM);
|
||||
}
|
||||
ot = getoppositestairs(returnstairtype);
|
||||
addob(c->obpile, ot->name);
|
||||
}
|
||||
|
||||
|
||||
/* void around map
|
||||
// N
|
||||
|
@ -627,9 +946,8 @@ void createmap(map_t *map, int habitat) {
|
|||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
cell_t *c;
|
||||
int obchance;
|
||||
c = getcellat(map, x, y);
|
||||
if (c && !c->type->solid) {
|
||||
if (c && isempty(c)) {
|
||||
if (rnd(1,100) <= getobchance(map->habitat)) {
|
||||
addrandomthing(c);
|
||||
}
|
||||
|
@ -641,7 +959,6 @@ void createmap(map_t *map, int habitat) {
|
|||
// add pillars & objects & monsters to rooms
|
||||
for (i = 0; i < numrooms; i++) {
|
||||
int numobsmin,numobsmax,numobs,n;
|
||||
int x,y;
|
||||
int maxpillars;
|
||||
|
||||
//dblog("Adding obs to room %d/%d",i+1,numrooms);
|
||||
|
@ -657,7 +974,7 @@ void createmap(map_t *map, int habitat) {
|
|||
cell_t *c;
|
||||
c = getrandomroomcell(map, i);
|
||||
|
||||
if (c && !c->type->solid && !countobs(c->obpile)) {
|
||||
if (c && isempty(c) && !countobs(c->obpile)) {
|
||||
setcelltype(cell, CT_WALL);
|
||||
}
|
||||
}
|
||||
|
@ -671,7 +988,7 @@ void createmap(map_t *map, int habitat) {
|
|||
} else {
|
||||
*/
|
||||
numobsmin = 0;
|
||||
numobsmax = MAXOF(roomw[i],roomh[i]);
|
||||
numobsmax = MAXOF(roomw[i],roomh[i]) / 2;
|
||||
|
||||
//}
|
||||
|
||||
|
@ -689,7 +1006,7 @@ void createmap(map_t *map, int habitat) {
|
|||
while (!done) {
|
||||
c = getrandomroomcell(map, i);
|
||||
// if nothing there
|
||||
if (c && !countobs(c->obpile)) {
|
||||
if (c && isempty(c) && !countobs(c->obpile)) {
|
||||
/*
|
||||
if (roomspecial[i]) {
|
||||
if (getrand(1,4) == 1) { // less chance of monster
|
||||
|
@ -901,8 +1218,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
|
||||
doorcount = countadjcellsoftype(cell, CT_DOOROPEN) +
|
||||
countadjcellsoftype(cell, CT_DOORCLOSED);
|
||||
doorcount = countadjcellswithflag(cell, F_DOOR);
|
||||
|
||||
if (doorcount == 0) {
|
||||
if ((countcellexits(newcell) == 1) &&
|
||||
|
@ -934,8 +1250,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
|
||||
doorcount = countadjcellsoftype(cell, CT_DOOROPEN) +
|
||||
countadjcellsoftype(cell, CT_DOORCLOSED);
|
||||
doorcount = countadjcellswithflag(cell, F_DOOR);
|
||||
|
||||
if (doorcount == 0) {
|
||||
if ((countcellexits(newcell) == 1) &&
|
||||
|
@ -966,8 +1281,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
newcell = getcellindir(cell, D_W);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
doorcount = countadjcellsoftype(cell, CT_DOOROPEN) +
|
||||
countadjcellsoftype(cell, CT_DOORCLOSED);
|
||||
doorcount = countadjcellswithflag(cell, F_DOOR);
|
||||
if (doorcount == 0) {
|
||||
if ((countcellexits(newcell) == 1) &&
|
||||
(iswallindir(newcell,D_N)) &&
|
||||
|
@ -997,8 +1311,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
newcell = getcellindir(cell, D_E);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
doorcount = countadjcellsoftype(cell, CT_DOOROPEN) +
|
||||
countadjcellsoftype(cell, CT_DOORCLOSED);
|
||||
doorcount = countadjcellswithflag(cell, F_DOOR);
|
||||
if (doorcount == 0) {
|
||||
if ((countcellexits(newcell) == 1) &&
|
||||
(iswallindir(newcell,D_N)) &&
|
||||
|
@ -1072,6 +1385,7 @@ int dirtoy(int dt, int dir) {
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1088,6 +1402,54 @@ printf("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h);
|
|||
}
|
||||
}
|
||||
|
||||
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int wantannounce) {
|
||||
int x,y;
|
||||
animradial(c, range, '}');
|
||||
|
||||
if (haslos(player, c)) {
|
||||
if (wantannounce) {
|
||||
msg("You see %s explosion!", (range > 0) ? "a huge" : "an");
|
||||
}
|
||||
} else {
|
||||
youhear(c, "an explosion!");
|
||||
}
|
||||
|
||||
for (y = c->y - range ; y <= c->y + range ; y++) {
|
||||
for (x = c->x - range ; x <= c->x + range ; x++) {
|
||||
cell_t *cc;
|
||||
cc = getcellat(c->map, x,y);
|
||||
if (cc && (getcelldist(c, cc) <= range)) {
|
||||
explodesinglecell(cc, dam, killwalls, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o) {
|
||||
char obname[BUFLEN];
|
||||
|
||||
if (c->lf) {
|
||||
char buf[BUFLEN];
|
||||
if (o) {
|
||||
getobname(o, obname, 1);
|
||||
sprintf(buf, "an exploding %s",strchr(obname, ' ')+1);
|
||||
} else {
|
||||
sprintf(buf, "an explosion");
|
||||
}
|
||||
losehp(c->lf, dam, DT_EXPLOSIVE, NULL, buf);
|
||||
}
|
||||
damageallobs(o, c->obpile, dam, DT_EXPLOSIVE);
|
||||
|
||||
if (killwalls) {
|
||||
if (c->type->solid) {
|
||||
// make it empty!
|
||||
setcelltype(c, getemptycelltype(c->map->habitat));
|
||||
// add some rubble
|
||||
addob(c->obpile, "10-50 stones");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map_t *findmap(int mid) {
|
||||
map_t *m;
|
||||
for (m = firstmap ; m ; m = m->next) {
|
||||
|
@ -1096,6 +1458,29 @@ map_t *findmap(int mid) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
map_t *findmapofdepth(int depth) {
|
||||
map_t *m;
|
||||
for (m = firstmap ; m ; m = m->next) {
|
||||
if (m->depth == depth) return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// find the cell in 'map' which contains object oid
|
||||
cell_t *findobinmap(map_t *m, enum OBCLASS oid) {
|
||||
cell_t *c;
|
||||
int x,y;
|
||||
for (y = 0; y < m->h; y++) {
|
||||
for (x = 0; x < m->w; x++) {
|
||||
c = getcellat(m, x, y);
|
||||
if (hasob(c->obpile, oid)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void forgetcells(map_t *map, int amt) {
|
||||
int amtleft;
|
||||
//int totcells;
|
||||
|
@ -1155,6 +1540,8 @@ cell_t *getcellindir(cell_t *cell, int dir) {
|
|||
case DC_NW:
|
||||
dt = DT_COMPASS;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
newx = cell->x + dirtox(dt, dir);
|
||||
newy = cell->y + dirtoy(dt, dir);
|
||||
|
@ -1181,8 +1568,6 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) {
|
|||
}
|
||||
|
||||
while (!foundvaliddir) { // keep going until we get a valid direction
|
||||
int newx,newy;
|
||||
|
||||
if (numtries >= MAXDIR_ORTH) { // no valid dirs
|
||||
return D_NONE; // (pick a new random spot and refresh tried dirs and current dir)
|
||||
}
|
||||
|
@ -1225,6 +1610,10 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) {
|
|||
newcell1 = getcellindir(newcell,D_N);
|
||||
newcell2 = getcellindir(newcell,D_S);
|
||||
break;
|
||||
default: // should never happen
|
||||
newcell1 = NULL;
|
||||
newcell2 = NULL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
newcell1 = NULL;
|
||||
|
@ -1275,6 +1664,37 @@ int getobchance(int habitat) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
cell_t *getrandomadjcell(cell_t *c, int wantempty) {
|
||||
int dir;
|
||||
int ntries = 0;
|
||||
cell_t *new;
|
||||
dir = getrandomdir(DT_COMPASS);
|
||||
while (ntries < 8) {
|
||||
new = getcellindir(c, dir);
|
||||
if (new) {
|
||||
if (wantempty == WE_EMPTY) {
|
||||
// make sure it's empty
|
||||
if (isempty(new)) {
|
||||
return new;
|
||||
}
|
||||
} else if (wantempty == WE_NOTSOLID) {
|
||||
if (cellwalkable(NULL, new, NULL)) {
|
||||
return new;
|
||||
}
|
||||
} else {
|
||||
// always ok
|
||||
return new;
|
||||
}
|
||||
}
|
||||
// not found yet...
|
||||
dir++;
|
||||
if (dir > DC_NW) dir = DC_N;
|
||||
ntries++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cell_t *getrandomcell(map_t *map) {
|
||||
int x,y;
|
||||
cell_t *cell;
|
||||
|
@ -1317,12 +1737,23 @@ cell_t *getrandomroomcell(map_t *map, int roomid) {
|
|||
for (x = 0; x < map->w; x++) {
|
||||
c = getcellat(map, x, y);
|
||||
// is this cell in the correct room and not a wall?
|
||||
if (c && !c->type->solid && (c->roomid == roomid)) {
|
||||
if (c && isempty(c)) {
|
||||
int ok = B_FALSE;
|
||||
if (c->roomid == roomid) {
|
||||
ok = B_TRUE;
|
||||
} else if (roomid == ANYROOM) {
|
||||
if (c->roomid != -1) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
poss[npossible] = c;
|
||||
npossible++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (npossible <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1333,6 +1764,143 @@ cell_t *getrandomroomcell(map_t *map, int roomid) {
|
|||
return c;
|
||||
}
|
||||
|
||||
lifeform_t *haslf(cell_t *c) {
|
||||
if (c->lf && !isdead(c->lf)) {
|
||||
return c->lf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hasobject(cell_t *c) {
|
||||
if (c->obpile->first) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int isadjacent(cell_t *src, cell_t *dst) {
|
||||
if (getcelldist(src, dst) == 1) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int isdiggable(cell_t *c) {
|
||||
switch (c->type->id) {
|
||||
case CT_WALL: return B_TRUE;
|
||||
case CT_ROOMWALL: return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// if isopen provided, returns whether or not the door is opened
|
||||
int isdoor(object_t *o, int *isopen) {
|
||||
int isdoor = B_FALSE;
|
||||
if (hasflag(o->flags, F_DOOR)) {
|
||||
isdoor = B_TRUE;
|
||||
} else {
|
||||
isdoor = B_FALSE;
|
||||
}
|
||||
|
||||
if (isdoor) {
|
||||
if (isopen) {
|
||||
if (hasflag(o->flags, F_OPEN)) {
|
||||
*isopen = B_TRUE;
|
||||
} else {
|
||||
*isopen = B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isdoor;
|
||||
}
|
||||
|
||||
int isempty(cell_t *c) {
|
||||
if (!c) return B_FALSE;
|
||||
if (c->type->solid) return B_FALSE;
|
||||
if (c->lf) return B_FALSE;
|
||||
if (!cellwalkable(NULL, c, NULL)) return B_FALSE;
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
//returns TT_ based on what you can scan there
|
||||
int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) {
|
||||
flag_t *f;
|
||||
// handle scanner
|
||||
f = lfhasflag(player, F_DETECTLIFE);
|
||||
if (f) {
|
||||
if (c->lf) {
|
||||
if (getcelldistorth(player->cell, c) <= f->val[0]) {
|
||||
*thing = c->lf;
|
||||
if (desc) {
|
||||
char *p;
|
||||
p = getsizetext(getlfsize(c->lf));
|
||||
sprintf(desc, "%s %s monster", isvowel(*p) ? "an" : "a", p);
|
||||
}
|
||||
if (glyph) {
|
||||
// select glyph based on size
|
||||
switch(getlfsize(c->lf)) {
|
||||
case SZ_ENORMOUS:
|
||||
*glyph = '6';
|
||||
break;
|
||||
case SZ_HUGE:
|
||||
*glyph = '5';
|
||||
break;
|
||||
case SZ_LARGE:
|
||||
*glyph = '4';
|
||||
break;
|
||||
case SZ_HUMAN:
|
||||
*glyph = '3';
|
||||
break;
|
||||
case SZ_MEDIUM:
|
||||
*glyph = '2';
|
||||
break;
|
||||
case SZ_SMALL:
|
||||
*glyph = '1';
|
||||
break;
|
||||
case SZ_MINI:
|
||||
case SZ_TINY:
|
||||
default:
|
||||
*glyph = '0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TT_MONSTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
f = lfhasflag(player, F_DETECTMETAL);
|
||||
if (f) {
|
||||
if (getcelldistorth(player->cell, c) <= f->val[0]) {
|
||||
if (c->lf && ismetal(c->lf->race->material->id) ) {
|
||||
*thing = c->lf;
|
||||
if (glyph) *glyph = '*';
|
||||
if (desc) sprintf(desc, "something metallic");
|
||||
return TT_MONSTER;
|
||||
} else {
|
||||
object_t *o;
|
||||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
if (ismetal(o->material->id)) {
|
||||
*thing = o;
|
||||
if (glyph) *glyph = '*';
|
||||
if (desc) sprintf(desc, "something metallic");
|
||||
return TT_OBJECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int islit(cell_t *c) {
|
||||
if (c->lit) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
int isloopdirok(cell_t *cell, int dir) {
|
||||
int dirok = B_FALSE;
|
||||
cell_t *newcell;
|
||||
|
@ -1393,12 +1961,47 @@ int iswallindir(cell_t *cell, int dir) {
|
|||
}
|
||||
|
||||
void makedoor(cell_t *cell) {
|
||||
setcelltype(cell, CT_DOORCLOSED);
|
||||
object_t *o;
|
||||
setcelltype(cell, getemptycelltype(cell->map->habitat));
|
||||
o = addob(cell->obpile, "wooden door");
|
||||
if (o && (rnd(1,2) == 1)) {
|
||||
opendoor(NULL, o);
|
||||
} else {
|
||||
// door is closed - lock it?
|
||||
if (rnd(1,3) == 1) {
|
||||
addflag(o->flags, F_LOCKED, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void makelit(cell_t *c, int how) {
|
||||
if (how == B_FALSE) {
|
||||
c->lit = how;
|
||||
} else if (c->lit != B_PERM) { // don't override permenant light with temp light!
|
||||
c->lit = how;
|
||||
}
|
||||
}
|
||||
|
||||
void makelitradius(cell_t *c, int radius, int how) {
|
||||
int x,y;
|
||||
cell_t *c2;
|
||||
|
||||
if (radius <= 0) return;
|
||||
|
||||
for (y = c->y - radius ; y <= c->y + radius; y++) {
|
||||
for (x = c->x - radius ; x <= c->x + radius; x++) {
|
||||
c2 = getcellat(c->map, x, y);
|
||||
if (c2 && (getcelldistorth(c, c2) <= radius)) {
|
||||
if (cellhaslos(c,c2)) {
|
||||
makelit(c2, how);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setcelltype(cell_t *cell, int id) {
|
||||
int i;
|
||||
|
||||
assert(cell);
|
||||
cell->type = findcelltype(id);
|
||||
assert(cell->type);
|
||||
|
@ -1409,16 +2012,28 @@ void setcelltype(cell_t *cell, int id) {
|
|||
void updateknowncells(void) {
|
||||
int x,y;
|
||||
map_t *map;
|
||||
object_t *wep;
|
||||
int seenundead = B_FALSE;
|
||||
|
||||
|
||||
map = player->cell->map;
|
||||
wep = getweapon(player);
|
||||
|
||||
for (y = viewy; y < viewy + viewh; y++) {
|
||||
for (x = viewx; x < viewx + vieww; x++) {
|
||||
cell_t *cell;
|
||||
cell = getcellat(map, x, y);
|
||||
if (cell && !cell->known && haslos(player, cell)) {
|
||||
if (cell) {
|
||||
//if ((player->cell == cell) || haslos(player, cell)) {
|
||||
if (haslos(player, cell)) {
|
||||
if (!cell->known) {
|
||||
cell->known = B_TRUE;
|
||||
}
|
||||
if (cell->lf && lfhasflag(cell->lf, F_UNDEAD)) {
|
||||
seenundead = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
25
map.h
25
map.h
|
@ -2,30 +2,53 @@
|
|||
|
||||
cell_t *addcell(map_t *map, int x, int y);
|
||||
map_t *addmap(void);
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid);
|
||||
void addrandomob(cell_t *c);
|
||||
void addrandomthing(cell_t *c);
|
||||
int cellhaslos(cell_t *c1, cell_t *dest);
|
||||
cell_t *getcellat(map_t *map, int x, int y);
|
||||
int getcelldist(cell_t *src, cell_t *dst);
|
||||
int getcelldistorth(cell_t *src, cell_t *dst);
|
||||
enum CELLTYPE getemptycelltype(enum HABITAT hab);
|
||||
object_t *gettopobject(cell_t *where);
|
||||
void calclight(map_t *map);
|
||||
int calcroompos(map_t *map, int w, int h, int *bx, int *by);
|
||||
int countadjcellsoftype(cell_t *cell, int id);
|
||||
int countadjcellswithflag(cell_t *cell, enum FLAG fid);
|
||||
int countcellexits(cell_t *cell);
|
||||
void createmap(map_t *map, int habitat);
|
||||
void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_t *returnstairtype);
|
||||
void createroom(map_t *map, int minx, int miny, int w, int h, int roomid);
|
||||
int dirtox(int dt, int dir);
|
||||
int dirtoy(int dt, int dir);
|
||||
void dumpmap(map_t *map);
|
||||
void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o);
|
||||
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int wantannounce);
|
||||
map_t *findmap(int mid);
|
||||
map_t *findmapofdepth(int depth);
|
||||
cell_t *findobinmap(map_t *m, enum OBCLASS oid);
|
||||
void forgetcells(map_t *map, int amt);
|
||||
cell_t *getcellindir(cell_t *cell, int dir);
|
||||
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
|
||||
int getobchance(int habitat);
|
||||
cell_t *getrandomadjcell(cell_t *c, int wantempty);
|
||||
cell_t *getrandomcell(map_t *map);
|
||||
cell_t *getrandomcelloftype(map_t *map, int id);
|
||||
int getrandomdir(int dirtype);
|
||||
cell_t *getrandomroomcell(map_t *map, int roomid);
|
||||
lifeform_t *haslf(cell_t *c);
|
||||
int hasobject(cell_t *c);
|
||||
int isadjacent(cell_t *src, cell_t *dst);
|
||||
int isdiggable(cell_t *c);
|
||||
int isdoor(object_t *o, int *isopen);
|
||||
int isempty(cell_t *c);
|
||||
int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph);
|
||||
int islit(cell_t *c);
|
||||
int isloopdirok(cell_t *cell, int dir);
|
||||
int isnewcellok(cell_t *cell, char *err);
|
||||
int isonmap(map_t *map, int x, int y);
|
||||
int iswallindir(cell_t *cell, int dir);
|
||||
void makedoor(cell_t *cell);
|
||||
void makelit(cell_t *c, int how);
|
||||
void makelitradius(cell_t *c, int radius, int how);
|
||||
void setcelltype(cell_t *cell, int id);
|
||||
void updateknowncells(void);
|
||||
|
|
709
move.c
709
move.c
|
@ -1,32 +1,97 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "attack.h"
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "io.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "move.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
#include "text.h"
|
||||
|
||||
extern lifeform_t *player;
|
||||
|
||||
extern int statdirty;
|
||||
|
||||
extern enum ERROR reason;
|
||||
extern void *rdata;
|
||||
|
||||
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
if (isplayer(lf)) {
|
||||
if (canmove(lf, dir, error)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (canmove(lf, dir, error) && willmove(lf, dir, error)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
cell_t *cell;
|
||||
|
||||
// default
|
||||
if (error) {
|
||||
*error = E_OK;
|
||||
rdata = NULL;
|
||||
}
|
||||
|
||||
if (lfhasflag(lf, F_GRAVBOOSTED)) {
|
||||
if (error) *error = E_GRAVBOOSTED;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// TODO: check if we are burdened, paralyzed, etc
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
|
||||
return cellwalkable(lf, cell, error);
|
||||
}
|
||||
|
||||
|
||||
int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
||||
object_t *o;
|
||||
// default
|
||||
if (error) {
|
||||
*error = E_OK;
|
||||
rdata = NULL;
|
||||
}
|
||||
if (!cell || cell->type->solid) {
|
||||
if (error) *error = E_WALLINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
if (cell->lf) {
|
||||
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
if (lf) {
|
||||
if ((lf->race->material->id != MT_GAS) &&
|
||||
(lf->race->material->id != MT_SLIME)) {
|
||||
rdata = o;
|
||||
if (error) *error = E_OBINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
} else {
|
||||
rdata = o;
|
||||
if (error) *error = E_OBINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->lf && (cell->lf != lf)) {
|
||||
if (error) *error = E_LFINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dorandommove(lifeform_t *lf, int badmovesok) {
|
||||
int dir;
|
||||
int tries = 0;
|
||||
|
@ -36,64 +101,190 @@ void dorandommove(lifeform_t *lf, int badmovesok) {
|
|||
// find a valid direction
|
||||
dir = getrandomdir(DT_COMPASS);
|
||||
|
||||
moveok = canmove(lf, dir, &why);
|
||||
moveok = canandwillmove(lf, dir, &why);
|
||||
|
||||
if (!moveok && badmovesok) {
|
||||
switch (why) {
|
||||
// actually okay to move into someone
|
||||
case E_WALLINWAY:
|
||||
case E_LFINWAY:
|
||||
moveok = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!moveok) {
|
||||
// try next direction...
|
||||
if (++dir > DC_NW) dir = DC_N;
|
||||
if (++tries >= MAXDIR_COMPASS) {
|
||||
dowait(lf);
|
||||
rest(lf, B_TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
// check this direction...
|
||||
moveok = canmove(lf, dir, &why);
|
||||
moveok = canandwillmove(lf, dir, &why);
|
||||
if (!moveok && badmovesok) {
|
||||
switch (why) {
|
||||
case E_WALLINWAY:
|
||||
case E_LFINWAY:
|
||||
moveok = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
trymove(lf, dir);
|
||||
}
|
||||
|
||||
int dowait(lifeform_t *lf) {
|
||||
taketime(lf, SPEED_WAIT);
|
||||
if (lf->controller == C_PLAYER) {
|
||||
// clear msg bar
|
||||
clearmsg();
|
||||
|
||||
int getdiraway(cell_t *src, cell_t *dst, int wantcheck) {
|
||||
int d;
|
||||
cell_t *c;
|
||||
int maxdist=-1,bestdir=D_NONE;
|
||||
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
int thisdist = -1;
|
||||
int ok = B_FALSE;
|
||||
c = getcellindir(src, d);
|
||||
if (!c) continue;
|
||||
|
||||
if (c == dst) {
|
||||
// destination is the thing we're fleeing from!
|
||||
thisdist = -1;
|
||||
} else {
|
||||
if (wantcheck) {
|
||||
if (src->lf && canandwillmove(src->lf, d, NULL)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!src->lf) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
} else {
|
||||
if (src->lf && cellwalkable(src->lf, c, NULL)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!src->lf) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
thisdist = getcelldist(c, dst);
|
||||
} else {
|
||||
thisdist = -1;
|
||||
}
|
||||
|
||||
if (thisdist > maxdist) {
|
||||
maxdist = thisdist;
|
||||
bestdir = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle ties
|
||||
|
||||
return bestdir;
|
||||
}
|
||||
|
||||
void movelf(lifeform_t *lf, cell_t *newcell) {
|
||||
|
||||
int getdirtowards(cell_t *src, cell_t *dst, int wantcheck) {
|
||||
int d;
|
||||
cell_t *c;
|
||||
int mindist=9999,bestdir=D_NONE;
|
||||
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
int ok = B_FALSE;
|
||||
c = getcellindir(src, d);
|
||||
if (!c) continue;
|
||||
if (c == dst) {
|
||||
// destination is adjacent!
|
||||
bestdir = d;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wantcheck) {
|
||||
if (src->lf && canandwillmove(src->lf, d, NULL)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!src->lf) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (src->lf && cellwalkable(src->lf, c, NULL)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!src->lf) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
int thisdist;
|
||||
thisdist = getcelldist(c, dst);
|
||||
if (thisdist < mindist) {
|
||||
mindist = thisdist;
|
||||
bestdir = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle ties
|
||||
|
||||
return bestdir;
|
||||
}
|
||||
|
||||
|
||||
int moveawayfrom(lifeform_t *lf, cell_t *dst) {
|
||||
int dir;
|
||||
int rv = B_TRUE;
|
||||
// move towards them
|
||||
dir = getdiraway(lf->cell, dst, B_TRUE);
|
||||
if (dir != D_NONE) {
|
||||
rv = trymove(lf, dir);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// returns TRUE if something happened
|
||||
int movelf(lifeform_t *lf, cell_t *newcell) {
|
||||
object_t *o,*nexto;
|
||||
char obname[BUFLEN],lfname[BUFLEN],buf[BUFLEN];
|
||||
lifeform_t *l;
|
||||
int didmsg = B_FALSE;
|
||||
flag_t *f;
|
||||
|
||||
// update current cell
|
||||
lf->cell->lf = NULL;
|
||||
|
||||
// if required, relink lifeform to new map
|
||||
if (newcell->map != lf->cell->map) {
|
||||
if (isplayer(lf)) {
|
||||
statdirty = B_TRUE;
|
||||
}
|
||||
relinklf(lf, newcell->map);
|
||||
}
|
||||
|
||||
// update lifeform
|
||||
lf->cell = newcell;
|
||||
|
||||
// nothing should be in new cell..
|
||||
assert(!newcell->lf);
|
||||
|
||||
// update new cell
|
||||
newcell->lf = lf;
|
||||
|
||||
if (isbleeding(lf)) {
|
||||
if (rnd(1,2) == 1) {
|
||||
bleed(lf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check ground objects
|
||||
if (!hasflag(lf->flags, F_FLYING)) {
|
||||
if (!lfhasflag(lf, F_FLYING)) {
|
||||
for (o = newcell->obpile->first ; o ; o = nexto ) {
|
||||
nexto = o->next;
|
||||
if (hasflag(o->flags, F_SHARP)) {
|
||||
f = hasflag(o->flags, F_SHARP);
|
||||
if (f) {
|
||||
object_t *boots;
|
||||
// has boots on?
|
||||
boots = getequippedob(lf->pack, BP_FEET);
|
||||
|
@ -106,16 +297,18 @@ void movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
// we want 'xx steps on some pieces of broken glass'
|
||||
// not 'xx steps on 5 pieces of broken glass'
|
||||
newname = makeplural(obname);
|
||||
strrep(newname, "a ", "some ");
|
||||
newname = strrep(newname, "a ", "some ", NULL);
|
||||
strcpy(obname, newname);
|
||||
free(newname);
|
||||
}
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("You crush %s underfoot.",obname);
|
||||
didmsg = B_TRUE;
|
||||
} else if (haslos(player, newcell)) {
|
||||
getlfname(lf, lfname);
|
||||
capitalise(lfname);
|
||||
msg("%s crushes %s.",lfname, obname);
|
||||
didmsg = B_TRUE;
|
||||
}
|
||||
// kill object
|
||||
removeob(o, o->amt);
|
||||
|
@ -124,13 +317,15 @@ void movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
getobname(o, obname, 1);
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("Ow - you step on %s!",obname);
|
||||
didmsg = B_TRUE;
|
||||
} else if (haslos(player, newcell)) {
|
||||
getlfname(lf, lfname);
|
||||
capitalise(lfname);
|
||||
msg("%s steps on %s!",lfname, obname);
|
||||
didmsg = B_TRUE;
|
||||
}
|
||||
sprintf(buf, "stepping on %s", obname);
|
||||
losehp(lf, rnd(1,2), DT_SLASH, NULL, buf);
|
||||
losehp(lf, rnd(f->val[0],f->val[1]), DT_SLASH, NULL, buf);
|
||||
}
|
||||
}
|
||||
} // end foreach object in cell
|
||||
|
@ -138,100 +333,474 @@ void movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
|
||||
// update where player knows
|
||||
// (but without a map you will then slowly forget it)
|
||||
if (lf->controller == C_PLAYER) {
|
||||
if (isplayer(lf)) {
|
||||
updateknowncells();
|
||||
}
|
||||
|
||||
// does anyone else see you?
|
||||
for (l = newcell->map->lf ; l ; l = l->next) {
|
||||
if (l != lf) {
|
||||
if (haslos(l, newcell)) {
|
||||
interrupt(lf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return didmsg;
|
||||
}
|
||||
|
||||
// basically this is a warpper for 'movelf' which
|
||||
// does other game things like telling the player
|
||||
// what is here.
|
||||
int moveto(lifeform_t *lf, cell_t *newcell) {
|
||||
char lfname[BUFLEN];
|
||||
int didmsg;
|
||||
|
||||
getlfname(lf, lfname);
|
||||
|
||||
// actually do the move
|
||||
movelf(lf, newcell);
|
||||
didmsg = movelf(lf, newcell);
|
||||
|
||||
// tell player about things
|
||||
if (!isdead(lf) && (lf->controller == C_PLAYER)) {
|
||||
if (!isdead(lf)) {
|
||||
// some lifeforms can go through things
|
||||
if (lf->race->material->id == MT_GAS) {
|
||||
object_t *o;
|
||||
char obname[BUFLEN];
|
||||
for (o = newcell->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
getobname(o, obname, o->amt);
|
||||
if (isplayer(lf)) {
|
||||
msg("You seep around %s.", obname);
|
||||
} else if (haslos(player, newcell)) {
|
||||
msg("%s seeps around %s.", lfname, obname);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (lf->race->material->id == MT_SLIME) {
|
||||
object_t *o;
|
||||
char obname[BUFLEN];
|
||||
for (o = newcell->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
getobname(o, obname, o->amt);
|
||||
if (isplayer(lf)) {
|
||||
msg("You seep under %s.", obname);
|
||||
} else if (haslos(player, newcell)) {
|
||||
msg("%s seeps under %s.", lfname, obname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// see objects on ground
|
||||
if (isplayer(lf)) {
|
||||
int numobs;
|
||||
char buf[BUFLEN];
|
||||
numobs = countobs(newcell->obpile);
|
||||
if (numobs == 1) {
|
||||
getobname(newcell->obpile->first, buf, newcell->obpile->first->amt);
|
||||
msg("You see %s here.", buf);
|
||||
} else if ((numobs > 1) && (numobs <= 3)) {
|
||||
msg("You see a few objects here.");
|
||||
} else if ((numobs > 3) && (numobs <= 6)) {
|
||||
msg("You see some objects here.");
|
||||
} else if (numobs > 6) {
|
||||
msg("You see many objects here.");
|
||||
} else {
|
||||
if ((numobs == 0) && !newcell->writing) {
|
||||
// just clear the message buffer
|
||||
clearmsg();
|
||||
if (!didmsg) clearmsg();
|
||||
} else { // tell player what is here
|
||||
dolook(newcell);
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int opendoor(lifeform_t *lf, cell_t *cell) {
|
||||
char buf[BUFLEN];
|
||||
if (cell->type->id == CT_DOORCLOSED) {
|
||||
// open it
|
||||
setcelltype(cell, CT_DOOROPEN);
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("You open a door.");
|
||||
int movetowards(lifeform_t *lf, cell_t *dst) {
|
||||
int dir;
|
||||
int rv = B_TRUE;
|
||||
// move towards them
|
||||
dir = getdirtowards(lf->cell, dst, B_TRUE);
|
||||
if (dir != D_NONE) {
|
||||
rv = trymove(lf, dir);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int opendoorat(lifeform_t *lf, cell_t *c) {
|
||||
object_t *o;
|
||||
int rv;
|
||||
o = hasobwithflag(c->obpile, F_DOOR);
|
||||
if (o) {
|
||||
rv = opendoor(lf, o);
|
||||
} else {
|
||||
// TODO: only announce if player can see it
|
||||
if (haslos(player, cell)) {
|
||||
rv = B_TRUE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int opendoor(lifeform_t *lf, object_t *o) {
|
||||
cell_t *doorcell;
|
||||
char buf[BUFLEN];
|
||||
char obname[BUFLEN];
|
||||
flag_t *f;
|
||||
|
||||
doorcell = o->pile->where;
|
||||
assert(doorcell);
|
||||
|
||||
|
||||
getobname(o, obname, 1);
|
||||
|
||||
if (!isdoor(o, NULL)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (lf && lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You have no hands with which to open the door!");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
f = hasflag(o->flags, F_OPEN);
|
||||
if (f) {
|
||||
if (lf && isplayer(lf)) {
|
||||
msg("It is already open!");
|
||||
}
|
||||
return B_TRUE;
|
||||
} else {
|
||||
// locked?
|
||||
if (hasflag(o->flags, F_LOCKED)) {
|
||||
if (lf && isplayer(lf)) {
|
||||
msg("The door is locked.");
|
||||
}
|
||||
return B_TRUE;
|
||||
} else {
|
||||
// open it
|
||||
addflag(o->flags, F_OPEN, B_TRUE, NA, NA, NULL);
|
||||
|
||||
f = hasflag(o->flags, F_IMPASSABLE);
|
||||
if (f) killflag(f);
|
||||
f = hasflag(o->flags, F_BLOCKSVIEW);
|
||||
if (f) killflag(f);
|
||||
|
||||
if (lf) {
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("You open %s.",obname);
|
||||
} else {
|
||||
if (haslos(player, lf->cell) && isadjacent(lf->cell, doorcell)) {
|
||||
getlfname(lf, buf);
|
||||
capitalise(buf);
|
||||
msg("%s opens a door.",buf);
|
||||
msg("%s opens %s.",buf, obname);
|
||||
} else if (haslos(player, doorcell)) {
|
||||
capitalise(obname);
|
||||
msg("%s opens.",obname);
|
||||
}
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
|
||||
touch(lf, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int closedoorat(lifeform_t *lf, cell_t *c) {
|
||||
object_t *o;
|
||||
int rv;
|
||||
o = hasobwithflag(c->obpile, F_DOOR);
|
||||
if (o) {
|
||||
rv = closedoor(lf, o);
|
||||
} else {
|
||||
rv = B_TRUE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int closedoor(lifeform_t *lf, object_t *o) {
|
||||
cell_t *cell;
|
||||
char buf[BUFLEN];
|
||||
char obname[BUFLEN];
|
||||
flag_t *f;
|
||||
|
||||
getobname(o, obname, 1);
|
||||
|
||||
if (!isdoor(o, NULL)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("There is nothing to close there!");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (lf && lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You have no hands with which to close the door!");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
f = hasflag(o->flags, F_OPEN);
|
||||
if (!f) {
|
||||
if (lf && (lf->controller == C_PLAYER)) {
|
||||
msg("It is already closed!");
|
||||
}
|
||||
return B_TRUE;
|
||||
} else {
|
||||
// close it
|
||||
killflag(f);
|
||||
addflag(o->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(o->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
||||
|
||||
if (lf) {
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("You close %s.", obname);
|
||||
} else {
|
||||
if (haslos(player, lf->cell) && isadjacent(lf->cell, cell)) {
|
||||
getlfname(lf, buf);
|
||||
capitalise(buf);
|
||||
msg("%s closes %s.",buf, obname);
|
||||
} else if (haslos(player, cell)) {
|
||||
capitalise(obname);
|
||||
msg("%s closes.",obname);
|
||||
}
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
touch(lf, o);
|
||||
}
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int tryrun(lifeform_t *lf, int dir) {
|
||||
// continue moving until we fail
|
||||
while (canmove(lf, dir, NULL)) {
|
||||
trymove(lf,dir);
|
||||
if (!trymove(lf, dir)) {
|
||||
addflag(lf->flags, F_RUNNING, dir, NA, NA, NULL);
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int trymove(lifeform_t *lf, int dir) {
|
||||
cell_t *cell;
|
||||
enum ERROR errcode;
|
||||
char buf[BUFLEN], buf2[BUFLEN];
|
||||
// try to pull lifeform towards cell c (or next to it)
|
||||
int pullnextto(lifeform_t *lf, cell_t *c) {
|
||||
int dir;
|
||||
cell_t *dst = NULL;
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
if (canmove(lf, dir, &errcode)) {
|
||||
moveto(lf, cell);
|
||||
taketime(lf, getmovespeed(lf));
|
||||
} else {
|
||||
switch (errcode) {
|
||||
case E_WALLINWAY:
|
||||
// is it a door in the way?
|
||||
if (cell->type->id == CT_DOORCLOSED) {
|
||||
// try to open it
|
||||
opendoor(lf, cell);
|
||||
} else {
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("Ouch! You walk into a wall.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E_LFINWAY:
|
||||
// attack!
|
||||
doattack(lf, cell->lf);
|
||||
break;
|
||||
}
|
||||
dst = c;
|
||||
|
||||
while (dst->lf) {
|
||||
dir = getdirtowards(dst, lf->cell, B_FALSE);
|
||||
if (dir == D_NONE) {
|
||||
return B_TRUE;
|
||||
} else {
|
||||
dst = getcellindir(dst, dir);
|
||||
if (dst == lf->cell) {
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// is the path clear?
|
||||
if (!dst || !haslof(lf, dst)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
if (isplayer(lf) || haslos(player, lf->cell)) {
|
||||
char buf[BUFLEN];
|
||||
getlfname(lf, buf);
|
||||
msg("%s %s pulled %s!", buf, isplayer(lf) ? "are" : "is",
|
||||
lfhasflag(lf, F_FLYING) ? "through the air" :
|
||||
"along the ground");
|
||||
}
|
||||
movelf(lf, dst);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// teleport somewhere, along with puffs of smoke etc
|
||||
int teleportto(lifeform_t *lf, cell_t *c) {
|
||||
char buf[BUFLEN];
|
||||
if (!isplayer(lf) && haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s disappears in a puff of smoke!", buf);
|
||||
}
|
||||
addob(lf->cell->obpile, "puff of smoke");
|
||||
movelf(lf, c);
|
||||
addob(lf->cell->obpile, "cloud of smoke");
|
||||
if (isplayer(lf)) {
|
||||
msg("Suddenly, your surroundings appear different!");
|
||||
} else if (haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s appears in a cloud of smoke!", buf);
|
||||
}
|
||||
// show any objects here, just like if we moved.
|
||||
// BUT don't let dolook() clear the msg bar if there are
|
||||
// no objects here.
|
||||
if (isplayer(lf) && countobs(lf->cell->obpile)) {
|
||||
dolook(lf->cell);
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
int trymove(lifeform_t *lf, int dir) {
|
||||
cell_t *cell;
|
||||
enum ERROR errcode;
|
||||
char buf[BUFLEN];
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
if (canandwillmove(lf, dir, &errcode)) {
|
||||
reason = E_OK;
|
||||
moveto(lf, cell);
|
||||
taketime(lf, getmovespeed(lf));
|
||||
} else {
|
||||
object_t *inway;
|
||||
int door, dooropen;
|
||||
reason = errcode;
|
||||
switch (errcode) {
|
||||
case E_WALLINWAY:
|
||||
if (isplayer(lf)) {
|
||||
msg("Ouch! You %s into a wall.", getmoveverb(lf));
|
||||
} else if (haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s %ss into a wall.", buf, getmoveverb(lf));
|
||||
}
|
||||
if (isblind(lf)) {
|
||||
if (isplayer(lf)) {
|
||||
// only take damage if we didn't know about this
|
||||
if (!cell->known) {
|
||||
sprintf(buf, "%sing into a wall", getmoveverb(lf));
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
cell->known = B_TRUE;
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
} else {
|
||||
sprintf(buf, "%sing into a wall", getmoveverb(lf));
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E_OBINWAY:
|
||||
inway = (object_t *)rdata;
|
||||
door = isdoor(inway, &dooropen);
|
||||
if (door && !dooropen) {
|
||||
if (isblind(lf)) {
|
||||
// run into it
|
||||
if (isplayer(lf)) {
|
||||
if (cell->known) {
|
||||
// try to open it
|
||||
opendoor(lf, inway);
|
||||
} else {
|
||||
msg("Ouch! You %s into a door.", getmoveverb(lf));
|
||||
cell->known = B_TRUE;
|
||||
sprintf(buf, "%sing into a door", getmoveverb(lf));
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
} else {
|
||||
if (haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s %ss into a wall.", buf, getmoveverb(lf));
|
||||
}
|
||||
sprintf(buf, "%sing into a door", getmoveverb(lf));
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
} else {
|
||||
// try to open it
|
||||
opendoor(lf, inway);
|
||||
}
|
||||
} else {
|
||||
// can we push this?
|
||||
if (ispushable(inway)) {
|
||||
if (canpush(lf, inway, dir)) {
|
||||
// push it!
|
||||
push(lf, inway, dir);
|
||||
} else {
|
||||
if (lf->controller == C_PLAYER) {
|
||||
char obname[BUFLEN];
|
||||
getobname(inway, obname, 1);
|
||||
switch (reason) {
|
||||
case E_TOOHEAVY:
|
||||
msg("The %s is too heavy to move.",strchr(obname, ' ')+1);
|
||||
break;
|
||||
case E_INSUBSTANTIAL:
|
||||
msg("You cannot push %s without a physical body!",strchr(obname, ' ')+1);
|
||||
break;
|
||||
default:
|
||||
msg("The %s won't move for some reason.",strchr(obname, ' ')+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // object is in the way
|
||||
if (lf->controller == C_PLAYER) {
|
||||
char obname[BUFLEN];
|
||||
getobname(inway, obname, 1);
|
||||
msg("There is %s in your way.",obname);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E_LFINWAY:
|
||||
// attack!
|
||||
return attacklf(lf, cell->lf);
|
||||
break;
|
||||
case E_GRAVBOOSTED:
|
||||
if (isplayer(lf)) {
|
||||
msg("You try to move but are unable to lift your feet!");
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (reason == E_OK) {
|
||||
return B_FALSE;
|
||||
} else {
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
cell_t *cell;
|
||||
object_t *o;
|
||||
enum IQBRACKET iq;
|
||||
|
||||
// default
|
||||
if (error) {
|
||||
*error = E_OK;
|
||||
rdata = NULL;
|
||||
}
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
// check for cursed objects + animals
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
if (!isplayer(lf)) {
|
||||
if (o->blessed == B_CURSED) {
|
||||
if (lfhasflag(lf, F_ANIMAL)) {
|
||||
if (!lfhasflag(lf, F_FLYING)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for dangerous objects
|
||||
iq = getiqname(getattr(lf, A_IQ), NULL);
|
||||
if (iq >= IQ_AVERAGE) {
|
||||
flag_t *f;
|
||||
object_t *o;
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
// don't walk on sharp objects without boots
|
||||
if (hasflag(o->flags, F_SHARP)) {
|
||||
if (!getequippedob(lf->pack, BP_FEET)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
f = hasflag(o->flags, F_WALKDAM);
|
||||
if (f) {
|
||||
// are we immune to this?
|
||||
if (!lfhasflagval(lf, F_DTIMMUNE, f->val[1], NA, NA, NULL)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
|
17
move.h
17
move.h
|
@ -1,8 +1,21 @@
|
|||
#include "defs.h"
|
||||
|
||||
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error);
|
||||
int closedoorat(lifeform_t *lf, cell_t *c);
|
||||
int closedoor(lifeform_t *lf, object_t *o);
|
||||
void dorandommove(lifeform_t *lf, int badmovesok);
|
||||
int dowait(lifeform_t *lf);
|
||||
void movelf(lifeform_t *lf, cell_t *newcell);
|
||||
int getdiraway(cell_t *src, cell_t *dst, int wantcheck);
|
||||
int getdirtowards(cell_t *src, cell_t *dst, int wantcheck);
|
||||
int moveawayfrom(lifeform_t *lf, cell_t *dst);
|
||||
int movelf(lifeform_t *lf, cell_t *newcell);
|
||||
int moveto(lifeform_t *lf, cell_t *newcell);
|
||||
int movetowards(lifeform_t *lf, cell_t *dst);
|
||||
int opendoorat(lifeform_t *lf, cell_t *c);
|
||||
int opendoor(lifeform_t *lf, object_t *o);
|
||||
int pullnextto(lifeform_t *lf, cell_t *c);
|
||||
int teleportto(lifeform_t *lf, cell_t *c);
|
||||
int trymove(lifeform_t *lf, int dir);
|
||||
int tryrun(lifeform_t *lf, int dir);
|
||||
int willmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
|
|
523
nexus.c
523
nexus.c
|
@ -1,38 +1,77 @@
|
|||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "ai.h"
|
||||
#include "attack.h"
|
||||
#include "io.h"
|
||||
#include "flag.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "move.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
#include "save.h"
|
||||
#include "text.h"
|
||||
|
||||
material_t *material = NULL,*lastmaterial = NULL;
|
||||
objectclass_t *objectclass = NULL,*lastobjectclass = NULL;
|
||||
objecttype_t *objecttype = NULL,*lastobjecttype = NULL;
|
||||
celltype_t *firstcelltype = NULL,*lastcelltype = NULL;
|
||||
race_t *firstrace = NULL,*lastrace = NULL;
|
||||
job_t *firstjob = NULL,*lastjob = NULL;
|
||||
map_t *firstmap = NULL,*lastmap = NULL;
|
||||
knowledge_t *knowledge = NULL, *lastknowledge = NULL;
|
||||
|
||||
// maintains unique lifeform ID numbers
|
||||
long nextlfid = 0;
|
||||
|
||||
int SCREENW = DEF_SCREENW;
|
||||
int SCREENH = DEF_SCREENH;
|
||||
|
||||
// object return list
|
||||
object_t *retobs[MAXPILEOBS+1];
|
||||
int retobscount[MAXPILEOBS+1];
|
||||
int nretobs = 0;
|
||||
|
||||
FILE *logfile;
|
||||
|
||||
prompt_t prompt;
|
||||
|
||||
char msghist[MAXHISTORY][BUFLEN];
|
||||
int nmsghist = 0;
|
||||
|
||||
enum ERROR reason; // global for returning errors
|
||||
void *rdata; // globel for returning data
|
||||
|
||||
lifeform_t *player = NULL;
|
||||
int gameover;
|
||||
|
||||
int gamestarted = B_FALSE;
|
||||
|
||||
int main(char **argv, int argc) {
|
||||
long curtime = 0;
|
||||
long timeleft = 0;
|
||||
|
||||
extern int statdirty;
|
||||
|
||||
int needredraw = B_TRUE;
|
||||
int numdraws = 0;
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int newworld = B_FALSE;
|
||||
object_t *o;
|
||||
|
||||
atexit(cleanup);
|
||||
|
||||
// init params
|
||||
init();
|
||||
if (init()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// load whatever maps are available
|
||||
loadall();
|
||||
|
@ -44,25 +83,60 @@ int main(char **argv, int argc) {
|
|||
if (!firstmap) {
|
||||
newworld = B_TRUE;
|
||||
addmap();
|
||||
createmap(firstmap, H_DUNGEON);
|
||||
createmap(firstmap, 1, H_DUNGEON, NULL, findot(OT_STAIRSUP));
|
||||
}
|
||||
|
||||
if (!knowledge) {
|
||||
// populate scroll names
|
||||
// populate scroll, potion, etc names
|
||||
genhiddennames();
|
||||
}
|
||||
|
||||
// if no player (ie. didn't load a game), add them
|
||||
if (!player) {
|
||||
char *user;
|
||||
char pname[BUFLEN];
|
||||
job_t *j;
|
||||
char ch;
|
||||
cell_t *where;
|
||||
|
||||
// ask for race
|
||||
initprompt(&prompt, "Select your race:");
|
||||
ch = 'a';
|
||||
for (j = firstjob ; j ; j = j->next) {
|
||||
addchoice(&prompt, ch++, j->name, NULL, j);
|
||||
}
|
||||
j = NULL;
|
||||
while (!j) {
|
||||
getchoice(&prompt);
|
||||
j = prompt.result;
|
||||
}
|
||||
|
||||
// find staircase
|
||||
where = findobinmap(firstmap, OT_STAIRSUP);
|
||||
assert(where);
|
||||
// add player
|
||||
player = addlf(getrandomcelloftype(firstmap, CT_ROOM), R_HUMAN, 1);
|
||||
player->controller = C_PLAYER;
|
||||
real_addlf(where, R_HUMAN, 1, C_PLAYER); // this will assign 'player'
|
||||
|
||||
user = getenv("USER");
|
||||
if (user) {
|
||||
addflag(player->flags, F_NAME, NA, NA, NA, getenv("USER"));
|
||||
} else {
|
||||
addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous");
|
||||
}
|
||||
givejob(player, j->id);
|
||||
|
||||
// player needs hunger
|
||||
addflag(player->flags, F_HUNGER, 0, NA, NA, NULL);
|
||||
|
||||
drawscreen();
|
||||
msg("Welcome to %snexus!", newworld ? "the new " : "");
|
||||
getplayernamefull(pname);
|
||||
msg("Greetings %s, welcome to %snexus!", pname, newworld ? "the new " : "");
|
||||
more();
|
||||
// XXX testing
|
||||
//addlf(getcellindir(player->cell, D_N), R_GOBLIN, 1);
|
||||
|
||||
// 00:00 - 23:59
|
||||
curtime = rnd(0,86399);
|
||||
} else {
|
||||
drawscreen();
|
||||
msg("Welcome back!");
|
||||
|
@ -73,38 +147,71 @@ int main(char **argv, int argc) {
|
|||
// start game - this will cause debug messages to now
|
||||
// go to the log file instead of stdout.
|
||||
gamestarted = B_TRUE;
|
||||
timeleft = 0; // reset game timer
|
||||
|
||||
// calculate initial light
|
||||
calclight(player->cell->map);
|
||||
// pre-calc line-of-sight for player
|
||||
precalclos(player);
|
||||
|
||||
// show level
|
||||
drawscreen();
|
||||
|
||||
// MAIN LOOP
|
||||
|
||||
// basic flow is:
|
||||
//
|
||||
// donextturn() - process a turn for a lifeform
|
||||
// turneffectslf() Rest effects, Damage from floor objects, etc
|
||||
// lifeform takes action
|
||||
// checkdeath() - check for object/player death. remove dead things.
|
||||
// timeeffectsworld() Fires burn out, ice melts, etc
|
||||
// Also keeps lf->timespent values under control.
|
||||
//
|
||||
//
|
||||
// redraw screen
|
||||
//
|
||||
// checkendgame() - has the game ended yet?
|
||||
|
||||
|
||||
gameover = B_FALSE;
|
||||
while (!gameover) {
|
||||
map_t *curmap;
|
||||
curmap = player->cell->map;
|
||||
|
||||
// default to no redraw - donextturn() will change this if needed.
|
||||
needredraw = B_FALSE;
|
||||
numdraws = 0;
|
||||
|
||||
// someone has a turn - this will then call taketime -> timehappens();
|
||||
donextturn(curmap);
|
||||
|
||||
// someone has a turn
|
||||
donextturn(player->cell->map);
|
||||
// update lifeform structue to figure out who goes next
|
||||
sortlf(player->cell->map);
|
||||
//timehappens(curmap);
|
||||
|
||||
// TODO: monsters move etc
|
||||
|
||||
// check for death etc
|
||||
doeffects();
|
||||
|
||||
// show level
|
||||
// show level (if required)
|
||||
//if (haslos(player, curmap->lf->cell)) {
|
||||
drawscreen();
|
||||
//dblog("**** END of turn, numdraws = %d", numdraws);
|
||||
|
||||
|
||||
// check end of game
|
||||
checkendgame();
|
||||
|
||||
}
|
||||
|
||||
// identify all objects
|
||||
for (o = player->pack->first ; o ; o = o->next) {
|
||||
identify(o);
|
||||
}
|
||||
// show possessions
|
||||
dofinaloblist(player->pack);
|
||||
// print tombstone
|
||||
tombstone(player);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
celltype_t *addcelltype(int id, char glyph, int solid, int transparent) {
|
||||
celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transparent, enum MATERIAL mat) {
|
||||
celltype_t *a;
|
||||
|
||||
// add to the end of the list
|
||||
|
@ -124,11 +231,47 @@ celltype_t *addcelltype(int id, char glyph, int solid, int transparent) {
|
|||
|
||||
// set props
|
||||
a->id = id;
|
||||
a->name = strdup(name);
|
||||
a->glyph = glyph;
|
||||
a->solid = solid;
|
||||
a->transparent = transparent;
|
||||
a->material = findmaterial(mat);
|
||||
|
||||
a->flags = addflagpile(NULL, NULL);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void checkdeath(void) {
|
||||
lifeform_t *lf, *nextlf;
|
||||
int x,y;
|
||||
for (lf = player->cell->map->lf; lf ; lf = nextlf) {
|
||||
nextlf = lf->next;
|
||||
|
||||
// check for death
|
||||
if (lf->hp <= 0) {
|
||||
// die!
|
||||
die(lf);
|
||||
continue;
|
||||
}
|
||||
// check for object death
|
||||
removedeadobs(lf->pack);
|
||||
}
|
||||
|
||||
// check for object death on map
|
||||
for (y = 0; y < player->cell->map->h; y++) {
|
||||
for (x = 0; x < player->cell->map->w; x++) {
|
||||
cell_t *c;
|
||||
c = getcellat(player->cell->map, x, y);
|
||||
if (c) {
|
||||
removedeadobs(c->obpile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void checkendgame(void) {
|
||||
if (!player->alive) {
|
||||
gameover = B_TRUE;
|
||||
|
@ -141,38 +284,94 @@ void cleanup(void) {
|
|||
}
|
||||
|
||||
|
||||
void doeffects(void) {
|
||||
lifeform_t *lf;
|
||||
// check for death
|
||||
for (lf = player->cell->map->lf; lf ; lf = lf->next) {
|
||||
if (lf->hp <= 0) {
|
||||
// die!
|
||||
die(lf);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void donextturn(map_t *map) {
|
||||
lifeform_t *who;
|
||||
|
||||
// show messages to plaeyr
|
||||
drawmsg();
|
||||
|
||||
who = map->lf;
|
||||
if (who->controller == C_PLAYER) {
|
||||
dblog("**** donextturn for: id %d %s", who->id, who->race->name);
|
||||
|
||||
|
||||
turneffectslf(who);
|
||||
|
||||
// calculate light
|
||||
calclight(map);
|
||||
// pre-calculate line of sight for this lifeform
|
||||
precalclos(who);
|
||||
|
||||
if (isplayer(who) || haslos(player, who->cell)) {
|
||||
needredraw = B_TRUE;
|
||||
}
|
||||
|
||||
// update gun targets
|
||||
autotarget(who);
|
||||
|
||||
|
||||
assert(who->timespent == 0);
|
||||
// keep looping until they actually do something or are dead!
|
||||
while (who->timespent == 0) {
|
||||
if (isdead(who)) {
|
||||
// skip turn
|
||||
taketime(who, SPEED_DEAD);
|
||||
} else {
|
||||
// do we need to run away from something?
|
||||
if (!flee(who)) {
|
||||
int donormalmove = B_TRUE;
|
||||
flag_t *f;
|
||||
|
||||
if (donormalmove) {
|
||||
// paralyzed?
|
||||
f = hasflag(who->flags, F_PARALYZED);
|
||||
if (f) {
|
||||
rest(who, B_FALSE);
|
||||
donormalmove = B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// resting?
|
||||
if (donormalmove) {
|
||||
f = hasflag(who->flags, F_RESTING);
|
||||
if (f) {
|
||||
if (who->hp < who->maxhp) {
|
||||
rest(who, B_TRUE);
|
||||
donormalmove = B_FALSE;
|
||||
} else {
|
||||
killflag(f);
|
||||
if (isplayer(who)) msg("You finish resting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (donormalmove) {
|
||||
if (isplayer(who)) {
|
||||
drawcursor();
|
||||
// find out what player wants to do
|
||||
handleinput();
|
||||
} else {
|
||||
// TODO: do ai move
|
||||
// do ai move
|
||||
aimove(who);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isdead(who) || haslos(player, who->cell)) {
|
||||
needredraw = B_TRUE;
|
||||
}
|
||||
|
||||
// check for death etc
|
||||
checkdeath();
|
||||
|
||||
//////////////////////////////////
|
||||
// effects which happen every GAME TICK
|
||||
// ie. object hp drain etc
|
||||
//////////////////////////////////
|
||||
timeeffectsworld(map);
|
||||
|
||||
// everyone else's time goes down by 1
|
||||
for (who = map->lf->next ; who ; who = who->next ){
|
||||
if (who->timespent > 0) who->timespent--;
|
||||
}
|
||||
//for (who = map->lf->next ; who ; who = who->next ){
|
||||
// if (who->timespent > 0) who->timespent--;
|
||||
//}
|
||||
}
|
||||
|
||||
celltype_t *findcelltype(int id) {
|
||||
|
@ -196,6 +395,10 @@ char *getdirname(int dir) {
|
|||
return "South";
|
||||
case D_W:
|
||||
return "West";
|
||||
case D_UP:
|
||||
return "up";
|
||||
case D_DOWN:
|
||||
return "down";
|
||||
case D_UNKNOWN:
|
||||
return "D_UNKNOWN";
|
||||
case D_NONE:
|
||||
|
@ -204,27 +407,45 @@ char *getdirname(int dir) {
|
|||
return "?errordir?";
|
||||
}
|
||||
|
||||
void getrarity(int depth, int *min, int *max, int range) {
|
||||
int mid;
|
||||
mid = 100 - (depth * 3);
|
||||
*min = mid - range; if (*min < 0) *min = 0;
|
||||
*max = mid + range; if (*max > 100) *max = 100;
|
||||
|
||||
if (*min > 75) *min = 75;
|
||||
if (*max < 25) *max = 25;
|
||||
}
|
||||
|
||||
int init(void) {
|
||||
// random numbers
|
||||
srand(time(NULL));
|
||||
|
||||
|
||||
initobjects();
|
||||
initjobs();
|
||||
initrace();
|
||||
|
||||
// cell types
|
||||
addcelltype(CT_WALL, "rock wall", '#', B_SOLID, B_OPAQUE, MT_STONE);
|
||||
addcelltype(CT_ROOMWALL, "rock wall", '#', B_SOLID, B_OPAQUE, MT_STONE);
|
||||
addcelltype(CT_CORRIDOR, "rock floor", '.', B_EMPTY, B_TRANS, MT_STONE);
|
||||
addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', B_EMPTY, B_TRANS, MT_STONE);
|
||||
addcelltype(CT_ROOM, "rock floor", '.', B_EMPTY, B_TRANS, MT_STONE);
|
||||
//addcelltype(CT_DOOROPEN, "wooden door", '-', B_EMPTY, B_TRANS, MT_WOOD);
|
||||
//addcelltype(CT_DOORCLOSED, "wooden door", '+', B_SOLID, B_OPAQUE, MT_WOOD);
|
||||
|
||||
if (validateobs()) {
|
||||
return B_TRUE;
|
||||
}
|
||||
if (validateraces()) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// open log file
|
||||
logfile = fopen("log.txt","wt");
|
||||
fprintf(logfile, "\n\n\n====== NEW LOGFILE ====\n");
|
||||
|
||||
// cell types
|
||||
addcelltype(CT_WALL, '#', B_SOLID, B_OPAQUE);
|
||||
addcelltype(CT_ROOMWALL, '#', B_SOLID, B_OPAQUE);
|
||||
addcelltype(CT_CORRIDOR, '.', B_EMPTY, B_TRANS);
|
||||
addcelltype(CT_LOOPCORRIDOR, 'L', B_EMPTY, B_TRANS);
|
||||
addcelltype(CT_ROOM, '.', B_EMPTY, B_TRANS);
|
||||
addcelltype(CT_DOOROPEN, '-', B_EMPTY, B_TRANS);
|
||||
addcelltype(CT_DOORCLOSED, '+', B_SOLID, B_OPAQUE);
|
||||
|
||||
initobjects();
|
||||
|
||||
initrace();
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -237,6 +458,10 @@ int isplayerturn(void) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
float pctof(float pct, float num) {
|
||||
return ((pct / 100.0) * num);
|
||||
}
|
||||
|
||||
// get a random number between min and max
|
||||
int rnd(int min, int max) {
|
||||
int res;
|
||||
|
@ -254,70 +479,220 @@ int rolldie(int ndice, int sides) {
|
|||
return res;
|
||||
}
|
||||
|
||||
// sort map's lifeform list by time spent
|
||||
int rollhitdice(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
int ndice, plus;
|
||||
int roll;
|
||||
|
||||
f = hasflag(lf->flags, F_HITDICE);
|
||||
if (f) {
|
||||
ndice = f->val[0];
|
||||
if (f->val[1] == NA) plus = 0;
|
||||
else plus = f->val[1];
|
||||
} else {
|
||||
ndice = 1;
|
||||
plus = 0;
|
||||
}
|
||||
roll = rolldie(ndice, 4) + plus;
|
||||
return roll;
|
||||
}
|
||||
|
||||
int rollmpdice(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
int ndice, plus;
|
||||
int roll;
|
||||
|
||||
f = hasflag(lf->flags, F_MPDICE);
|
||||
if (f) {
|
||||
ndice = f->val[0];
|
||||
if (f->val[1] == NA) plus = 0;
|
||||
else plus = f->val[1];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
roll = rolldie(ndice, 4) + plus;
|
||||
return roll;
|
||||
}
|
||||
|
||||
/*
|
||||
void sortlf(map_t *map) {
|
||||
int donesomething;
|
||||
lifeform_t *l;
|
||||
int adjustby;
|
||||
int db = B_TRUE;
|
||||
int db = B_FALSE;
|
||||
lifeform_t *l,*nextl;
|
||||
int iter = 0;
|
||||
|
||||
// bubblesort
|
||||
/*
|
||||
donesomething = B_TRUE;
|
||||
dblog("doing sort...");
|
||||
while (donesomething) {
|
||||
donesomething = B_FALSE;
|
||||
|
||||
//dblog("ITER %d",iter++);
|
||||
if (db) {
|
||||
dblog("BEFORE sortlf():");
|
||||
dblog("ITER %d",iter++);
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
dblog("- %s (timespent= %d) (sorted=%d)", (l == player) ? "player" : l->race->name, l->timespent,l->sorted);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
donesomething = B_TRUE;
|
||||
while (donesomething) {
|
||||
donesomething = B_FALSE;
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
if (!l->sorted && l->next && (l->timespent > l->next->timespent) ) {
|
||||
|
||||
for (l = map->lf ; l->next ; l = nextl) {
|
||||
nextl = l->next;
|
||||
//if (!l->sorted && (l->timespent >= l->next->timespent) ) {
|
||||
if (l->sorted) {
|
||||
//dblog("skipping id %d %s, already sorted ",l->id, l->race->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (l->timespent >= l->next->timespent) {
|
||||
lifeform_t *temp;
|
||||
//dblog("moving id %d %s upwards",l->id, l->race->name);
|
||||
// remember next element
|
||||
temp = l->next;
|
||||
|
||||
// remove this element from list
|
||||
// don't bother checking if (l->next == NULL) as we know
|
||||
// this won't be true due to the for loop condition
|
||||
if (l->prev == NULL) {
|
||||
// first
|
||||
map->lf = l->next;
|
||||
l->next->prev = NULL;
|
||||
} else {
|
||||
// not first
|
||||
l->prev->next = l->next;
|
||||
}
|
||||
// don't bother checking for next - we know ther eis one.
|
||||
l->next->prev = l->prev;
|
||||
}
|
||||
|
||||
// TESTING: re-add at correct position.
|
||||
while (temp->next && (temp->next->timespent <= l->timespent)) {
|
||||
//dblog("moving past %d %s (timespend=%d)...",temp->next->id, temp->next->race->name, temp->next->timespent);
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
// re-add element afterwards
|
||||
l->next = temp->next;
|
||||
l->prev = temp;
|
||||
temp->next = l;
|
||||
if (l->next == NULL) map->lastlf = l;
|
||||
if (l->next == NULL) {
|
||||
map->lastlf = l;
|
||||
} else {
|
||||
l->next->prev = l;
|
||||
}
|
||||
|
||||
l->sorted = B_TRUE;
|
||||
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
} else {
|
||||
l->sorted = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
//dblog("finished sort.");
|
||||
|
||||
// reset sorted var for next time
|
||||
for (l = map->lf ; l->next ; l = l->next) {
|
||||
l->sorted = B_FALSE;
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (player->next) {
|
||||
assert(player->next->prev == player);
|
||||
}
|
||||
if (player->prev) {
|
||||
assert(player->prev->next == player);
|
||||
}
|
||||
|
||||
if (db) {
|
||||
dblog("AFTER SORT:");
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
if (haslos(player, l->cell)) {
|
||||
// if (haslos(player, l->cell)) {
|
||||
dblog("- %s (timespent= %d) (sorted=%d)", (l == player) ? "player" : l->race->name, l->timespent,l->sorted);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now go through the list and make the first element be 0
|
||||
adjustby = map->lf->timespent;
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
l->timespent -= adjustby;
|
||||
l->sorted = B_FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void timeeffectsworld(map_t *map) {
|
||||
lifeform_t *l;
|
||||
int db = B_TRUE;
|
||||
object_t *o,*nexto;
|
||||
int x,y;
|
||||
long firstlftime;
|
||||
|
||||
// now go through the list and make the first element be 0
|
||||
l = map->lf;
|
||||
|
||||
if (l) {
|
||||
// if (db) dblog("first lf is: %s (id %ld)\n",l->race->name, l->id);
|
||||
firstlftime = l->timespent;
|
||||
assert(firstlftime >= 0);
|
||||
} else {
|
||||
dblog("no lifeforms on map!\n");
|
||||
// no first lf!
|
||||
firstlftime = 0;
|
||||
}
|
||||
|
||||
//if (db) dblog("timespent = %d\n", timespent);
|
||||
dblog("firstlftime = %d\n", firstlftime);
|
||||
|
||||
if (firstlftime > 0) {
|
||||
dblog("making firstlf timespent = 0 (currently %d):", firstlftime);
|
||||
//dumplf();
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
//dblog("shuffling id %d %s timespent=%d -> %d",l->id,l->race->name, l->timespent, l->timespent - firstlftime);
|
||||
l->timespent -= firstlftime;
|
||||
assert(l->timespent >= 0);
|
||||
if (isplayer(l)) {
|
||||
statdirty = B_TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
//dblog("after shuffle:");
|
||||
//dumplf();
|
||||
} else {
|
||||
dblog("firstlf timespent is not greater than 0. no shuffle.");
|
||||
}
|
||||
|
||||
timeleft += firstlftime;
|
||||
// now do effects based on time...
|
||||
while (timeleft >= TICK_INTERVAL) {
|
||||
|
||||
timeleft -= TICK_INTERVAL;
|
||||
|
||||
// global time-based effects on map or map objects
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
cell_t *c;
|
||||
c = getcellat(map, x, y);
|
||||
if (c) {
|
||||
// go through each object in the cell...
|
||||
for (o = c->obpile->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
|
||||
timeeffectsob(o);
|
||||
} // end foreach object here
|
||||
}
|
||||
}
|
||||
} // end for (y...
|
||||
|
||||
// now handle effects on lifeforms and/or their objects
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
timeeffectslf(l);
|
||||
for (o = l->pack->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
timeeffectsob(o);
|
||||
}
|
||||
}
|
||||
|
||||
//dblog("AFTER SORT AND ADJUST.....");
|
||||
//dumplf();
|
||||
} // end if timespent
|
||||
|
||||
// inc game time
|
||||
curtime += firstlftime;
|
||||
|
||||
if (db) dblog("cur time is %ld\n",curtime);
|
||||
}
|
||||
|
|
11
nexus.h
11
nexus.h
|
@ -1,14 +1,19 @@
|
|||
#include "defs.h"
|
||||
|
||||
celltype_t *addcelltype(int id, char glyph, int solid, int transparent);
|
||||
celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transparent, enum MATERIAL mat);
|
||||
void checkdeath(void);
|
||||
void checkendgame(void);
|
||||
void cleanup(void);
|
||||
void doeffects(void);
|
||||
void donextturn(map_t *map);
|
||||
celltype_t *findcelltype(int id);
|
||||
char *getdirname(int dir);
|
||||
void getrarity(int depth, int *min, int *max, int range);
|
||||
int init(void);
|
||||
int isplayerturn(void);
|
||||
float pctof(float pct, float num);
|
||||
int rnd(int min, int max);
|
||||
int rolldie(int ndice, int sides);
|
||||
void sortlf(map_t *map);
|
||||
int rollhitdice(lifeform_t *lf);
|
||||
int rollmpdice(lifeform_t *lf);
|
||||
//void sortlf(map_t *map);
|
||||
void timeeffectsworld(map_t *map);
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
hay
|
||||
pebbles
|
||||
torch
|
||||
boulder / monolith / statue
|
||||
shackles
|
||||
chain
|
||||
bone
|
||||
skeleton
|
||||
scrap of material
|
100
objects.h
100
objects.h
|
@ -2,57 +2,151 @@
|
|||
#define __OBJECTS_H
|
||||
#include "defs.h"
|
||||
|
||||
object_t *addemptyob(obpile_t *where, object_t *o);
|
||||
knowledge_t *addknowledge(enum OBCLASS id, char *hiddenname, int known);
|
||||
material_t *addmaterial(enum MATERIAL id, char *name);
|
||||
material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
|
||||
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph);
|
||||
object_t *addob(obpile_t *where, char *name);
|
||||
object_t *addobject(obpile_t *where, char *name, int canstack);
|
||||
obpile_t *addobpile(lifeform_t *owner, cell_t *where);
|
||||
objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid);
|
||||
void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat);
|
||||
void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype);
|
||||
//void adjustprice(objecttype_t *ot, float *price );
|
||||
void appendinscription(object_t *o, char *text);
|
||||
int blessob(object_t *o);
|
||||
void brightflash(cell_t *centre, int range, lifeform_t *immunelf);
|
||||
object_t *canstackob(obpile_t *op, object_t *match);
|
||||
object_t *canstacknewot(obpile_t *op, objecttype_t *match);
|
||||
int changemat(object_t *o, enum MATERIAL mat);
|
||||
void copyobprops(object_t *dst, object_t *src);
|
||||
int countnames(char **list);
|
||||
int countobs(obpile_t *op);
|
||||
int curseob(object_t *o);
|
||||
void damageallobs(object_t *exception, obpile_t *op, int howmuch, int damtype);
|
||||
void explodeob(object_t *o, flag_t *f, int bigness);
|
||||
void extinguish(object_t *o);
|
||||
material_t *findmaterial(int id);
|
||||
objectclass_t *findoc(int id);
|
||||
object_t *findobl(obpile_t *op, char let); // find object by letter
|
||||
objecttype_t *findot(enum OBTYPE id);
|
||||
objecttype_t *findotn(char *name); // find objecttype by name
|
||||
void genhiddennames(void);
|
||||
int getcharges(object_t *o);
|
||||
int geteffecttime(int min, int max, enum BLESSTYPE isblessed);
|
||||
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt);
|
||||
int getobaccuracy(object_t *wep);
|
||||
int getobvalue(object_t *o);
|
||||
//int getobtypevalue(objecttype_t *ot);
|
||||
char *getaccuracyname(int accpct);
|
||||
object_t *getammo(lifeform_t *lf);
|
||||
object_t *getrandomammo(lifeform_t *lf);
|
||||
char *getdamname(enum DAMTYPE damtype);
|
||||
char *getdamnamenoun(enum DAMTYPE damtype);
|
||||
char *getfillingname(int nutrition);
|
||||
int getfirearmrange(object_t *o);
|
||||
int getfirearmspeed(object_t *o);
|
||||
char getglyph(object_t *o);
|
||||
char *genhiddenname(enum OBCLASS id);
|
||||
char *gethiddenname(object_t *o);
|
||||
int getobattackspeed(object_t *o);
|
||||
int getletindex(char let);
|
||||
int getmaterialvalue(enum MATERIAL mat );
|
||||
int getmaxthrowrange(lifeform_t *lf, object_t *o);
|
||||
char getnextletter(obpile_t *op, char *wantletter);
|
||||
int getnumshards(object_t *o);
|
||||
int getnutritionbase(object_t *o);
|
||||
int getnutrition(object_t *o);
|
||||
char *getobdesc(object_t *o, char *buf);
|
||||
cell_t *getoblocation(object_t *o);
|
||||
char *getobname(object_t *o, char *buf, int count);
|
||||
char *real_getobname(object_t *o, char *buf, int count, int wantcondition, int adjustforblind, int wantblesscurse);
|
||||
float getobpileweight(obpile_t *op);
|
||||
char *getobconditionname(object_t *o, char *buf);
|
||||
char *getobhurtname(object_t *o, enum DAMTYPE damtype);
|
||||
float getobweight(object_t *o);
|
||||
float getobunitweight(object_t *o);
|
||||
objecttype_t *getoppositestairs(objecttype_t *ot);
|
||||
char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth);
|
||||
char *getrandomob(map_t *map, char *buf);
|
||||
char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf);
|
||||
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf);
|
||||
char *getschoolname(enum SPELLSCHOOL sch);
|
||||
int getshatterdam(object_t *o);
|
||||
int getthrowdam(object_t *o);
|
||||
int hasedibleob(obpile_t *op);
|
||||
object_t *hasknownob(obpile_t *op, enum OBTYPE oid);
|
||||
object_t *hasob(obpile_t *op, enum OBTYPE oid);
|
||||
object_t *hasobofclass(obpile_t *op, enum OBCLASS cid);
|
||||
object_t *hasobmulti(obpile_t *op, enum OBTYPE *oid, int noids);
|
||||
object_t *hasobwithflag(obpile_t *op, enum FLAG flagid);
|
||||
object_t *hasobwithflagval(obpile_t *op, enum FLAG flagid, int val0, int val1, int val2, char *text);
|
||||
object_t *hasobid(obpile_t *op, int id);
|
||||
void identify(object_t *o);
|
||||
void initobjects(void);
|
||||
flag_t *isarmour(object_t *o);
|
||||
int isactivated(object_t *o);
|
||||
int isammofor(object_t *ammo, object_t *gun);
|
||||
int isbetterarmourthan(object_t *a, object_t *b);
|
||||
int isbetterwepthan(object_t *a, object_t *b);
|
||||
int isblessed(object_t *o);
|
||||
int isblessknown(object_t *o);
|
||||
int iscorpse(object_t *o);
|
||||
int iscursed(object_t *o);
|
||||
int isdrinkable(object_t *o);
|
||||
int isedible(object_t *o);
|
||||
flag_t *isequipped(object_t *o);
|
||||
int isequippedon(object_t *o, enum BODYPART bp);
|
||||
int isfirearm(object_t *o);
|
||||
int isflammable(object_t *o);
|
||||
int isknown(object_t *o);
|
||||
int isidentified(object_t *o);
|
||||
int ismetal(enum MATERIAL mat);
|
||||
int ismissile(object_t *o);
|
||||
int isoperable(object_t *o);
|
||||
int isplainob(object_t *o);
|
||||
int ispourable(object_t *o);
|
||||
int ispushable(object_t *o);
|
||||
int isreadable(object_t *o);
|
||||
int isrotting(object_t *o);
|
||||
int isweapon(object_t *o);
|
||||
int iswearable(object_t *o);
|
||||
void killmaterial(material_t *m);
|
||||
void killob(object_t *o);
|
||||
void killobpile(obpile_t *o);
|
||||
void killoc(objectclass_t *oc);
|
||||
void killot(objecttype_t *ot);
|
||||
lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level);
|
||||
void makeknown(enum OBTYPE otid);
|
||||
object_t *moveob(object_t *src, obpile_t *dst, int howmany);
|
||||
object_t *newobeffects(object_t *o);
|
||||
void obaction(object_t *o, char *text);
|
||||
object_t *obexists(enum OBTYPE obid);
|
||||
void obdie(object_t *o);
|
||||
int obfits(object_t *o, obpile_t *op);
|
||||
enum DAMTYPE oblastdamtype(object_t *o);
|
||||
flag_t *obproduceslight(object_t *o);
|
||||
int obpropsmatch(object_t *a, object_t *b);
|
||||
int obotpropsmatch(object_t *a, objecttype_t *b);
|
||||
int operate(lifeform_t *lf, object_t *o);
|
||||
int pilehasletter(obpile_t *op, char let);
|
||||
void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, int *seen);
|
||||
int pour(lifeform_t *lf, object_t *o);
|
||||
void quaff(lifeform_t *lf, object_t *o);
|
||||
void read(lifeform_t *lf, object_t *o);
|
||||
void readsomething(lifeform_t *lf, object_t *o);
|
||||
void removedeadobs(obpile_t *op);
|
||||
int removeob(object_t *o, int howmany);
|
||||
object_t *relinkob(object_t *src, obpile_t *dst);
|
||||
void throwat(lifeform_t *thrower, object_t *o, cell_t *where);
|
||||
void setblessed(object_t *o, enum BLESSTYPE wantbless);
|
||||
void setinscription(object_t *o, char *text);
|
||||
object_t *splitob(object_t *o);
|
||||
int takedamage(object_t *o, unsigned int howmuch, int damtype);
|
||||
int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t *firearm);
|
||||
void timeeffectsob(object_t *o);
|
||||
void turnoff(lifeform_t *lf, object_t *o);
|
||||
void turnon(lifeform_t *lf, object_t *o);
|
||||
int usecharge(object_t *o);
|
||||
int validateobs(void);
|
||||
int willshatter(enum MATERIAL mat);
|
||||
#endif
|
||||
|
||||
|
|
208
save.c
208
save.c
|
@ -3,7 +3,10 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "io.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "move.h"
|
||||
|
@ -11,6 +14,8 @@
|
|||
#include "objects.h"
|
||||
#include "save.h"
|
||||
|
||||
extern long curtime;
|
||||
|
||||
extern lifeform_t *player;
|
||||
extern map_t *firstmap;
|
||||
extern knowledge_t *knowledge;
|
||||
|
@ -20,8 +25,6 @@ int loading = B_FALSE;
|
|||
int loadall(void) {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char *filename;
|
||||
FILE *f;
|
||||
|
||||
loading = B_TRUE;
|
||||
|
||||
|
@ -52,6 +55,42 @@ int loadall(void) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int loadflagpile(FILE *f, flagpile_t *fp) {
|
||||
flag_t tempflag;
|
||||
flag_t *fl;
|
||||
char buf[BUFLEN];
|
||||
int rv;
|
||||
int db = B_TRUE;
|
||||
|
||||
rv = fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%ld\n",
|
||||
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2],&tempflag.lifetime, &tempflag.known,&tempflag.obfrom);
|
||||
|
||||
while (tempflag.id != -1) {
|
||||
dblog("got flag id=%d\n",tempflag.id);
|
||||
// get flag text
|
||||
fgets(buf, BUFLEN, f);
|
||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||
|
||||
fl = addflag_real(fp, tempflag.id,
|
||||
tempflag.val[0],
|
||||
tempflag.val[1],
|
||||
tempflag.val[2], strcmp(buf, "^^^") ? buf : NULL, tempflag.lifetime, tempflag.known);
|
||||
|
||||
fl->obfrom = tempflag.obfrom;
|
||||
|
||||
if (db) {
|
||||
dblog("--> added flag id=%d. v0=%d, v1=%d, v2=%d, text=%s, lifetime=%d, known=%d, obfrom=%ld\n",fl->id,
|
||||
fl->val[0], fl->val[1], fl->val[2], fl->text ? fl->text : "(null)", fl->lifetime, fl->known,fl->obfrom);
|
||||
}
|
||||
|
||||
// load next one
|
||||
rv = fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%ld\n",
|
||||
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2],&tempflag.lifetime, &tempflag.known,&tempflag.obfrom);
|
||||
//dblog("fscanf returned %d\n",rv);
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int loadknowledge(FILE *f) {
|
||||
int db = B_FALSE;
|
||||
char buf[BUFLEN];
|
||||
|
@ -74,6 +113,16 @@ int loadknowledge(FILE *f) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int loadvars(FILE *f) {
|
||||
int db = B_FALSE;
|
||||
if (db) dblog("--> Loading knowledge...\n");
|
||||
fscanf(f, "startvars\n");
|
||||
fscanf(f, "curtime:%ld\n",&curtime);
|
||||
fscanf(f, "endvars\n");
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// load and allocate one lifeform from given file
|
||||
lifeform_t *loadlf(FILE *f, cell_t *where) {
|
||||
lifeform_t *l;
|
||||
|
@ -117,9 +166,15 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
|||
l->y = y;
|
||||
|
||||
// load rest of this lf
|
||||
fscanf(f, "str: %d/%d\n",&l->att[A_STR],&l->baseatt[A_STR]);
|
||||
fscanf(f, "dex: %d/%d\n",&l->att[A_DEX],&l->baseatt[A_DEX]);
|
||||
fscanf(f, "int: %d/%d\n",&l->att[A_IQ],&l->baseatt[A_IQ]);
|
||||
fscanf(f, "xp: %ld\n",&l->xp);
|
||||
fscanf(f, "contr: %d\n",&l->controller);
|
||||
fscanf(f, "hp: %d/%d\n",&l->hp, &l->maxhp);
|
||||
fscanf(f, "mp: %d/%d\n",&l->mp, &l->maxmp);
|
||||
fscanf(f, "alive: %d\n",&l->alive);
|
||||
fscanf(f, "lastdamtype: %d\n",(int *)&l->lastdamtype);
|
||||
|
||||
fgets(buf, BUFLEN, f); // lastdam
|
||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||
|
@ -128,9 +183,15 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
|||
fscanf(f, "timespent: %d\n",&l->timespent);
|
||||
|
||||
fscanf(f, "sorted: %d\n",&l->sorted);
|
||||
fscanf(f, "polyrevert: %d\n",&l->polyrevert);
|
||||
fscanf(f, "forgettimer: %f\n",&l->forgettimer);
|
||||
|
||||
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading ob list.",l->hp,l->maxhp,l->timespent,l->sorted);
|
||||
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted);
|
||||
|
||||
// lf flags
|
||||
loadflagpile(f, l->flags);
|
||||
|
||||
if (db) dblog("--> now loading objects");
|
||||
|
||||
// load object list
|
||||
obcount = 0;
|
||||
|
@ -165,6 +226,9 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
|||
if (l->controller == C_PLAYER) {
|
||||
player = l;
|
||||
}
|
||||
|
||||
sortlf(l->cell->map, l);
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
|
@ -173,13 +237,12 @@ map_t *loadmap(char *basefile) {
|
|||
FILE *f;
|
||||
char filename[BUFLEN];
|
||||
char buf[BUFLEN];
|
||||
char buf2[BUFLEN];
|
||||
int obcount;
|
||||
int i;
|
||||
int x,y;
|
||||
int db = B_TRUE;
|
||||
lifeform_t *l;
|
||||
object_t *o,*nexto;
|
||||
object_t *o;
|
||||
map_t *m;
|
||||
cell_t *dummycell;
|
||||
|
||||
|
@ -202,13 +265,13 @@ map_t *loadmap(char *basefile) {
|
|||
// load map info
|
||||
if (db) dblog("--> Loading map info...\n");
|
||||
fscanf(f, "id:%d\n",&m->id); // map id
|
||||
fscanf(f, "depth:%d\n",&m->depth); // map depth
|
||||
fgets(buf, BUFLEN, f); // map name
|
||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||
m->name = strdup(buf + 5); // after 'name:'
|
||||
fscanf(f, "habitat:%d\n",(int *)&m->habitat); // habitat
|
||||
fscanf(f, "seed:%d\n",&m->seed); // seed
|
||||
fscanf(f, "dims:%d,%d\n",&m->w, &m->h); // map dimensons
|
||||
fscanf(f, "nextlfid:%ld\n",&m->nextlfid);
|
||||
fscanf(f, "nextmaps:\n");
|
||||
for (i = 0; i < MAXDIR_ORTH; i++) {
|
||||
fscanf(f, "%d\n",&m->nextmap[i]); // map dimensons
|
||||
|
@ -253,8 +316,8 @@ map_t *loadmap(char *basefile) {
|
|||
*/
|
||||
|
||||
// cell info
|
||||
fscanf(f, "%d,%d,%d,%d\n",
|
||||
&c->roomid, &celltypeid, &c->known, &c->visited);
|
||||
fscanf(f, "%d,%d,%d,%d,%d\n",
|
||||
&c->roomid, &celltypeid, &c->known, &c->visited, &c->lit);
|
||||
|
||||
|
||||
ct = findcelltype(celltypeid);
|
||||
|
@ -286,7 +349,6 @@ map_t *loadmap(char *basefile) {
|
|||
|
||||
// create all objects in a dummy cell
|
||||
for (i = 0; i < obcount; i++) {
|
||||
int n;
|
||||
long thisid;
|
||||
if (db) dblog("-----> loading into dummycell: mapob %d/%d...\n",i+1,obcount);
|
||||
if (loadob(f, dummycell->obpile, &thisid)) {
|
||||
|
@ -398,9 +460,6 @@ int loadob(FILE *f, obpile_t *op, long *id) {
|
|||
long obid;
|
||||
int otid,matid;
|
||||
char buf[BUFLEN];
|
||||
int flagid;
|
||||
flag_t tempflag;
|
||||
int rv;
|
||||
int db = B_TRUE;
|
||||
|
||||
fscanf(f, "id:%ld\n",&obid);
|
||||
|
@ -413,7 +472,7 @@ int loadob(FILE *f, obpile_t *op, long *id) {
|
|||
|
||||
ot = findot(otid);
|
||||
if (!ot) {
|
||||
dblog("ERROR loading objects - can't find obtype id %ld\n",obid);
|
||||
dblog("ERROR loading objects - can't find obtype id %d (obj id %ld)\n",otid,obid);
|
||||
return B_TRUE;
|
||||
}
|
||||
// create the object
|
||||
|
@ -442,29 +501,20 @@ int loadob(FILE *f, obpile_t *op, long *id) {
|
|||
fscanf(f, "bless:%d\n",&o->blessed);
|
||||
fscanf(f, "blessknown:%d\n",&o->blessknown);
|
||||
fscanf(f, "amt:%d\n",&o->amt);
|
||||
fscanf(f, "birthtime:%ld\n",&o->birthtime);
|
||||
|
||||
// now remove ALL obejct flags (which were inherited
|
||||
// from the obtype during addobject() ). these will be
|
||||
// loaded in instead.
|
||||
|
||||
while (o->flags->first) {
|
||||
killflag(o->flags->first);
|
||||
}
|
||||
|
||||
fscanf(f, "flags:\n");
|
||||
|
||||
dblog("About to start loading object flags...");
|
||||
rv = fscanf(f, "%d,%d,%d,%d,%d\n",
|
||||
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2]);
|
||||
|
||||
while (tempflag.id != -1) {
|
||||
dblog("got flag id=%d\n",tempflag.id);
|
||||
// get flag text
|
||||
fgets(buf, BUFLEN, f);
|
||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||
|
||||
|
||||
addflag(o->flags, tempflag.id,
|
||||
tempflag.val[0],
|
||||
tempflag.val[1],
|
||||
tempflag.val[2], strcmp(buf, "^^^") ? buf : NULL);
|
||||
// load next one
|
||||
rv = fscanf(f, "%d,%d,%d,%d,%d\n",
|
||||
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2]);
|
||||
//dblog("fscanf returned %d\n",rv);
|
||||
}
|
||||
loadflagpile(f, o->flags);
|
||||
fscanf(f, "endob\n");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -504,6 +554,10 @@ int loadsavegame(void) {
|
|||
printf("Error loading knowledge from file '%s'",ent->d_name);
|
||||
exit(1);
|
||||
}
|
||||
if (loadvars(f)) {
|
||||
printf("Error loading game variables from file '%s'",ent->d_name);
|
||||
exit(1);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
// successful load - kill the savegame now
|
||||
|
@ -512,14 +566,38 @@ int loadsavegame(void) {
|
|||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int savevars(FILE *f) {
|
||||
int db = B_FALSE;
|
||||
if (db) dblog("--> Saving knowledge...\n");
|
||||
fprintf(f, "startvars\n");
|
||||
fprintf(f, "curtime:%ld\n",curtime);
|
||||
fprintf(f, "endvars\n");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
int saveflagpile(FILE *f, flagpile_t *fp) {
|
||||
flag_t *fl;
|
||||
fprintf(f, "flags:\n");
|
||||
for (fl = fp->first ; fl ; fl = fl->next) {
|
||||
fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%ld\n",
|
||||
fl->id, fl->nvals, fl->val[0], fl->val[1], fl->val[2],fl->lifetime,fl->known,fl->obfrom);
|
||||
if (!fl->text || !strcmp(fl->text, "")) {
|
||||
fprintf(f, "%s\n","^^^");
|
||||
} else {
|
||||
fprintf(f, "%s\n",fl->text);
|
||||
}
|
||||
}
|
||||
fprintf(f, "-1,-1,-1,-1,-1,-1,-1,-1\n");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int saveknowledge(FILE *f) {
|
||||
int db = B_FALSE;
|
||||
char buf[BUFLEN];
|
||||
int otid,known;
|
||||
char hiddenname[BUFLEN];
|
||||
knowledge_t *k;
|
||||
if (db) dblog("--> Saving knowledge...\n");
|
||||
fprintf(f, "startknowledge\n");
|
||||
|
@ -542,14 +620,25 @@ int savelf(FILE *f, lifeform_t *l) {
|
|||
fprintf(f, "map: %d\n",l->cell->map->id);
|
||||
fprintf(f, "pos: %d,%d\n",l->cell->x, l->cell->y);
|
||||
fprintf(f, "level: %d\n",l->level);
|
||||
// liefform will be cfeated after loading the above.
|
||||
// liefform will be created after loading the above.
|
||||
fprintf(f, "str: %d/%d\n",l->att[A_STR],l->baseatt[A_STR]);
|
||||
fprintf(f, "dex: %d/%d\n",l->att[A_DEX],l->baseatt[A_DEX]);
|
||||
fprintf(f, "int: %d/%d\n",l->att[A_IQ],l->baseatt[A_IQ]);
|
||||
fprintf(f, "xp: %ld\n",l->xp);
|
||||
fprintf(f, "contr: %d\n",l->controller);
|
||||
fprintf(f, "hp: %d/%d\n",l->hp, l->maxhp);
|
||||
fprintf(f, "mp: %d/%d\n",l->mp, l->maxmp);
|
||||
fprintf(f, "alive: %d\n",l->alive);
|
||||
fprintf(f, "lastdamtype: %d\n",l->lastdamtype);
|
||||
fprintf(f, "lastdam: %s\n",l->lastdam);
|
||||
fprintf(f, "timespent: %d\n",l->timespent);
|
||||
fprintf(f, "sorted: %d\n",l->sorted);
|
||||
fprintf(f, "polyrevert: %d\n",l->polyrevert);
|
||||
fprintf(f, "forgettimer: %f\n",l->forgettimer);
|
||||
|
||||
// lf flags
|
||||
saveflagpile(f, l->flags);
|
||||
|
||||
// lifeform objects
|
||||
obcount = 0;
|
||||
for (o = l->pack->first ; o ; o = o->next) {
|
||||
|
@ -568,6 +657,33 @@ int savelf(FILE *f, lifeform_t *l) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int savegame(void) {
|
||||
map_t *m;
|
||||
FILE *f;
|
||||
char buf[BUFLEN];
|
||||
int rv;
|
||||
for (m = firstmap; m ; m = m->next) {
|
||||
// save world
|
||||
rv = savemap(m);
|
||||
if (rv) {
|
||||
msg("Could not save map '%s'",m->name);
|
||||
return B_TRUE;
|
||||
}
|
||||
// save player + their objects
|
||||
sprintf(buf, "%s/game.sav",SAVEDIR);
|
||||
f = fopen(buf, "wt");
|
||||
if (!f) {
|
||||
msg("Could not open save file!");
|
||||
return B_TRUE;
|
||||
}
|
||||
savelf(f, player);
|
||||
saveknowledge(f);
|
||||
savevars(f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int savemap(map_t *m) {
|
||||
FILE *f;
|
||||
|
@ -584,11 +700,11 @@ int savemap(map_t *m) {
|
|||
|
||||
// save map info
|
||||
fprintf(f, "id:%d\n",m->id); // map id
|
||||
fprintf(f, "depth:%d\n",m->depth); // map depth
|
||||
fprintf(f, "name:%s\n",m->name); // map name
|
||||
fprintf(f, "habitat:%d\n",m->habitat); // habitat
|
||||
fprintf(f, "seed:%d\n",m->seed); // seed
|
||||
fprintf(f, "dims:%d,%d\n",m->w, m->h); // map dimensons
|
||||
fprintf(f, "nextlfid:%ld\n",m->nextlfid);
|
||||
fprintf(f, "nextmaps:\n");
|
||||
for (i = 0; i < MAXDIR_ORTH; i++) {
|
||||
fprintf(f, "%d\n",m->nextmap[i] ); // map dimensons
|
||||
|
@ -610,8 +726,8 @@ int savemap(map_t *m) {
|
|||
cell_t *c;
|
||||
c = getcellat(m, x, y);
|
||||
// cell info
|
||||
fprintf(f, "%d,%d,%d,%d\n",
|
||||
c->roomid, c->type->id, c->known, c->visited);
|
||||
fprintf(f, "%d,%d,%d,%d,%d\n",
|
||||
c->roomid, c->type->id, c->known, c->visited,c->lit);
|
||||
// cell objects
|
||||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
fprintf(f, "ob:%ld\n",o->id);
|
||||
|
@ -641,7 +757,6 @@ int savemap(map_t *m) {
|
|||
|
||||
|
||||
int saveob(FILE *f, object_t *o) {
|
||||
flag_t *fl;
|
||||
fprintf(f, "id:%ld\n",o->id);
|
||||
fprintf(f, "type:%d\n",o->type->id);
|
||||
fprintf(f, "material:%d\n",o->material->id);
|
||||
|
@ -651,17 +766,8 @@ int saveob(FILE *f, object_t *o) {
|
|||
fprintf(f, "bless:%d\n",o->blessed);
|
||||
fprintf(f, "blessknown:%d\n",o->blessknown);
|
||||
fprintf(f, "amt:%d\n",o->amt);
|
||||
fprintf(f, "flags:\n");
|
||||
for (fl = o->flags->first ; fl ; fl = fl->next) {
|
||||
fprintf(f, "%d,%d,%d,%d,%d\n",
|
||||
fl->id, fl->nvals, fl->val[0], fl->val[1], fl->val[2]);
|
||||
if (!fl->text || !strcmp(fl->text, "")) {
|
||||
fprintf(f, "%s\n","^^^");
|
||||
} else {
|
||||
fprintf(f, "%s\n",fl->text);
|
||||
}
|
||||
}
|
||||
fprintf(f, "-1,-1,-1,-1,-1\n");
|
||||
fprintf(f, "birthtime:%ld\n",o->birthtime);
|
||||
saveflagpile(f, o->flags);
|
||||
fprintf(f, "endob\n");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
|
3
save.h
3
save.h
|
@ -1,12 +1,15 @@
|
|||
#include "defs.h"
|
||||
|
||||
int loadall(void);
|
||||
int loadflagpile(FILE *f, flagpile_t *fp);
|
||||
int loadknowledge(FILE *f);
|
||||
lifeform_t *loadlf(FILE *f, cell_t *where);
|
||||
map_t *loadmap(char *basefile);
|
||||
int loadob(FILE *f, obpile_t *op, long *id);
|
||||
int loadsavegame(void);
|
||||
int saveflagpile(FILE *f, flagpile_t *fp);
|
||||
int saveknowledge(FILE *f);
|
||||
int savelf(FILE *f, lifeform_t *l);
|
||||
int savegame(void);
|
||||
int savemap(map_t *m);
|
||||
int saveob(FILE *f, object_t *o);
|
||||
|
|
10
spell.h
10
spell.h
|
@ -2,7 +2,13 @@
|
|||
#define __SPELLS_H
|
||||
#include "defs.h"
|
||||
|
||||
void dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target);
|
||||
|
||||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid);
|
||||
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer);
|
||||
void fizzle(lifeform_t *caster);
|
||||
int getmpcost(enum OBTYPE oid);
|
||||
void pullobto(object_t *o, lifeform_t *lf);
|
||||
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof);
|
||||
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
281
text.c
281
text.c
|
@ -1,14 +1,131 @@
|
|||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "lf.h"
|
||||
#include "objects.h"
|
||||
#include "text.h"
|
||||
|
||||
extern long curtime;
|
||||
|
||||
char *capitalise(char *text) {
|
||||
if (strlen(text) > 0) {
|
||||
text[0] = toupper(text[0]);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
char *getattrname(enum ATTRIB att) {
|
||||
switch (att) {
|
||||
case A_STR:
|
||||
return "strength";
|
||||
case A_IQ:
|
||||
return "intelligence";
|
||||
case A_DEX:
|
||||
return "dexterity";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "?unknown?";
|
||||
}
|
||||
|
||||
char *getpossessive(char *text) {
|
||||
char lastchar;
|
||||
// you -> your
|
||||
if (!strcmp(text, "you")) {
|
||||
return "r";
|
||||
}
|
||||
|
||||
// xxxs -> xxxs'
|
||||
lastchar = text[strlen(text)-1];
|
||||
if (tolower(lastchar) == 's') {
|
||||
return "'";
|
||||
}
|
||||
// default: 's
|
||||
return "'s";
|
||||
}
|
||||
|
||||
char *getsizetext(enum LFSIZE sz) {
|
||||
switch (sz) {
|
||||
case SZ_ENORMOUS:
|
||||
return "enormous";
|
||||
case SZ_HUGE:
|
||||
return "huge";
|
||||
case SZ_LARGE:
|
||||
return "large";
|
||||
case SZ_HUMAN:
|
||||
return "human-sized";
|
||||
case SZ_MEDIUM:
|
||||
return "medium";
|
||||
case SZ_SMALL:
|
||||
return "small";
|
||||
case SZ_MINI:
|
||||
case SZ_TINY:
|
||||
return "extremely small";
|
||||
default:
|
||||
return "unknown-sized";
|
||||
}
|
||||
return "unknown-sized";
|
||||
}
|
||||
|
||||
char *gettimetext(char *retbuf) {
|
||||
int hours,mins,secs;
|
||||
splittime(&hours, &mins, &secs);
|
||||
|
||||
sprintf(retbuf, "%02d:%02d:%02d",hours,mins,secs);
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
char *gettimetextfuzzy(char *retbuf, int wantpm) {
|
||||
int hours,mins,secs;
|
||||
int pm = B_FALSE;
|
||||
splittime(&hours, &mins, &secs);
|
||||
|
||||
if (hours > 12) {
|
||||
hours -= 12;
|
||||
pm = B_TRUE;
|
||||
}
|
||||
|
||||
if (mins == 0) {
|
||||
sprintf(retbuf, "exactly %d o'clock", hours);
|
||||
} else if (mins <= 15) {
|
||||
sprintf(retbuf, "a little after %d o'clock", hours);
|
||||
} else if (mins <= 25) {
|
||||
sprintf(retbuf, "nearly half past %d", hours);
|
||||
} else if (mins <= 35) {
|
||||
sprintf(retbuf, "around half past %d", hours);
|
||||
} else if (mins <= 45) {
|
||||
sprintf(retbuf, "comung up to %d o'clock", (hours == 12) ? 1 : (hours+1));
|
||||
} else {
|
||||
sprintf(retbuf, "nearly %d o'clock", (hours == 12) ? 1 : (hours+1));
|
||||
}
|
||||
|
||||
if (wantpm) {
|
||||
strcat(retbuf, " in the ");
|
||||
if (pm) {
|
||||
strcat(retbuf, "afternoon");
|
||||
} else {
|
||||
strcat(retbuf, "morning");
|
||||
}
|
||||
}
|
||||
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
char *getweighttext(float weight, char *buf) {
|
||||
if (weight >= 1) {
|
||||
if ((int)weight == weight) { // ie. is weight an integer?
|
||||
sprintf(buf, "%0.0f kg",weight);
|
||||
} else {
|
||||
sprintf(buf, "%0.1f kg",weight);
|
||||
}
|
||||
} else {
|
||||
sprintf(buf, "%0.0f grams", weight * 1000);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
int isvowel (char c) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
|
@ -23,23 +140,47 @@ int isvowel (char c) {
|
|||
|
||||
// allocates and returns new string
|
||||
char *makeplural(char *text) {
|
||||
int newlen;
|
||||
char lastlet;
|
||||
char *newtext;
|
||||
char *p;
|
||||
int rv;
|
||||
|
||||
newtext = strdup(text);
|
||||
|
||||
// scrolls
|
||||
rv = strrep(newtext, "scroll ", "scrolls ");
|
||||
newtext = strrep(newtext, "berry ", "berries ", &rv);
|
||||
if (rv) return newtext;
|
||||
rv = strrep(newtext, "potion ", "potions ");
|
||||
newtext = strrep(newtext, "block ", "blocks ", &rv);
|
||||
if (rv) return newtext;
|
||||
rv = strrep(newtext, "piece ", "pieces ");
|
||||
newtext = strrep(newtext, "can ", "cans ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "chunk ", "chunks ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "gem ", "gems ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "loaf ", "loaves ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "lump ", "lumps ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "piece ", "pieces ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "pile ", "piles ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "pool ", "pools ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "potion ", "potions ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "puddle ", "puddles ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "ring ", "rings ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "scroll ", "scrolls ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "vial ", "vials ", &rv);
|
||||
if (rv) return newtext;
|
||||
|
||||
rv = strrep(newtext, "pair ", "pairs ");
|
||||
|
||||
//
|
||||
newtext = strrep(newtext, "pair ", "pairs ", &rv);
|
||||
// don't return
|
||||
|
||||
// default
|
||||
|
@ -56,27 +197,50 @@ char *makeplural(char *text) {
|
|||
return newtext;
|
||||
}
|
||||
|
||||
int strrep(char *text, char *oldtok, char *newtok) {
|
||||
char *noprefix(char *obname) {
|
||||
char *p;
|
||||
p = strchr(obname, ' ');
|
||||
if (p) {
|
||||
p++;
|
||||
return p;
|
||||
} else {
|
||||
return obname;
|
||||
}
|
||||
}
|
||||
|
||||
void splittime(int *hours, int *mins, int *secs) {
|
||||
long left;
|
||||
left = curtime;
|
||||
|
||||
*hours = left / 3600;
|
||||
left -= (*hours * 3600);
|
||||
*mins = left / 60;
|
||||
left -= (*mins * 60);
|
||||
*secs = left;
|
||||
}
|
||||
|
||||
char *strrep(char *text, char *oldtok, char *newtok, int *rv) {
|
||||
char *temp;
|
||||
int rv;
|
||||
temp = strdup(" ");
|
||||
rv = dostrrep(text, &temp, oldtok, newtok);
|
||||
temp = strdup(" "); // ooooooo is this bad??
|
||||
dostrrep(text, &temp, oldtok, newtok, rv);
|
||||
// swap
|
||||
text = realloc(text, strlen(temp));
|
||||
text = realloc(text, strlen(temp)+1); // extra space for NUL
|
||||
strcpy(text, temp);
|
||||
free(temp);
|
||||
return rv;
|
||||
return text;
|
||||
}
|
||||
|
||||
// returns TRUE if any replacements made
|
||||
int dostrrep(char* in, char** out, char* oldtok, char* newtok) {
|
||||
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv) {
|
||||
char *temp;
|
||||
char *found = strstr(in, oldtok);
|
||||
int idx;
|
||||
if(!found) {
|
||||
*out = realloc(*out, strlen(in) + 1);
|
||||
*out = realloc(*out, strlen(in) + 1); // oooooooo crashing in realloc
|
||||
strcpy(*out, in);
|
||||
return B_FALSE;
|
||||
|
||||
if (rv) *rv = B_FALSE;
|
||||
return *out;
|
||||
}
|
||||
|
||||
idx = found - in;
|
||||
|
@ -90,13 +254,96 @@ int dostrrep(char* in, char** out, char* oldtok, char* newtok) {
|
|||
strncpy(temp,*out,idx+strlen(newtok));
|
||||
temp[idx + strlen(newtok)] = '\0';
|
||||
|
||||
dostrrep(found + strlen(oldtok), out, oldtok, newtok);
|
||||
dostrrep(found + strlen(oldtok), out, oldtok, newtok, rv);
|
||||
temp = realloc(temp, strlen(temp) + strlen(*out) + 1);
|
||||
strcat(temp,*out);
|
||||
free(*out);
|
||||
*out = temp;
|
||||
|
||||
return B_TRUE;
|
||||
if (rv) *rv = B_TRUE;
|
||||
return *out;
|
||||
}
|
||||
|
||||
int strpixmatch(char *haystack, char *needle) {
|
||||
int matched = B_FALSE;
|
||||
char *hword, *nword, *hcont,*ncont;
|
||||
|
||||
if (strchr(needle, ' ') || strchr(haystack, ' ')) {
|
||||
char lochaystack[BUFLEN], locneedle[BUFLEN];
|
||||
strcpy(lochaystack, haystack);
|
||||
strcpy(locneedle, needle);
|
||||
|
||||
// match word for word
|
||||
nword = strtok_r(locneedle, " ", &ncont);
|
||||
hword = strtok_r(lochaystack, " ", &hcont);
|
||||
while (nword && hword) {
|
||||
// all typed words must match
|
||||
if (strcasestr(hword, nword)) {
|
||||
matched = B_TRUE;
|
||||
} else {
|
||||
matched = B_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
nword = strtok_r(NULL, " ", &ncont);
|
||||
hword = strtok_r(NULL, " ", &hcont);
|
||||
if (nword && !hword) {
|
||||
matched = B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (!matched && !strchr(needle, ' ')) {
|
||||
// now try matching typed word against second word in spellname
|
||||
strcpy(lochaystack, haystack);
|
||||
hword = strtok_r(lochaystack, " ", &hcont);
|
||||
while (hword) {
|
||||
if (strcasestr(hword, needle)) {
|
||||
matched = B_TRUE;
|
||||
break;
|
||||
} else {
|
||||
matched = B_FALSE;
|
||||
}
|
||||
|
||||
hword = strtok_r(NULL, " ", &hcont);
|
||||
if (!hword) {
|
||||
matched = B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
if (strcasestr(haystack, needle)) {
|
||||
matched = B_TRUE;
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
char *you(lifeform_t *lf) {
|
||||
if (isplayer(lf)) {
|
||||
return "You";
|
||||
}
|
||||
return "It";
|
||||
}
|
||||
|
||||
char *you_l(lifeform_t *lf) {
|
||||
if (isplayer(lf)) {
|
||||
return "you";
|
||||
}
|
||||
return "it";
|
||||
}
|
||||
|
||||
char *your(lifeform_t *lf) {
|
||||
if (isplayer(lf)) {
|
||||
return "Your";
|
||||
}
|
||||
return "Its";
|
||||
}
|
||||
|
||||
char *your_l(lifeform_t *lf) {
|
||||
if (isplayer(lf)) {
|
||||
return "your";
|
||||
}
|
||||
return "its";
|
||||
}
|
||||
|
|
18
text.h
18
text.h
|
@ -1,8 +1,20 @@
|
|||
#include "defs.h"
|
||||
|
||||
char *capitalise(char *text);
|
||||
char *getattrname(enum ATTRIB att);
|
||||
char *getpossessive(char *text);
|
||||
char *getsizetext(enum LFSIZE sz);
|
||||
char *gettimetext(char *retbuf);
|
||||
char *gettimetextfuzzy(char *retbuf, int wantpm);
|
||||
char *getweighttext(float weight, char *buf);
|
||||
int isvowel(char c);
|
||||
char *makeplural(char *text);
|
||||
|
||||
int strrep(char *text, char *oldtok, char *newtok);
|
||||
int dostrrep(char* in, char** out, char* oldtok, char* newtok);
|
||||
char *noprefix(char *obname);
|
||||
void splittime(int *hours, int *mins, int *secs);
|
||||
char *strrep(char *text, char *oldtok, char *newtok, int *rv);
|
||||
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv);
|
||||
int strpixmatch(char *haystack, char *needle);
|
||||
char *you(lifeform_t *lf);
|
||||
char *you_l(lifeform_t *lf);
|
||||
char *your(lifeform_t *lf);
|
||||
char *your_l(lifeform_t *lf);
|
||||
|
|
Loading…
Reference in New Issue