nexus/io.c

7443 lines
173 KiB
C

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include <unistd.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 "text.h"
#include "save.h"
#include "spell.h"
WINDOW *mainwin;
WINDOW *gamewin;
WINDOW *msgwin;
WINDOW *statwin;
int statdirty = B_TRUE;
int hascolour = B_TRUE;
extern int needredraw;
extern int numdraws;
extern int SCREENW, SCREENH;
extern enum ERROR reason;
extern char msghist[MAXHISTORY][BUFLEN];
extern int nmsghist;
extern prompt_t prompt;
extern object_t *retobs[MAXPILEOBS+1];
extern int retobscount[MAXPILEOBS+1];
extern int nretobs;
extern FILE *logfile;
extern enum OBCLASS sortorder[];
extern knowledge_t *knowledge;
extern objecttype_t *objecttype;
extern command_t *firstcommand;
extern skill_t *firstskill;
extern enum GAMEMODE gamemode;
extern long curtime;
char msgbuf[HUGEBUFLEN];
char lastmsgbuf[HUGEBUFLEN];
extern lifeform_t *player;
extern map_t *firstmap;
int viewx = -9999,viewy = -9999;
int vieww,viewh;
int msgmod = B_FALSE;
void addchoice(prompt_t *p, char ch, char *text, char *desc, void *data) {
p->choice[p->nchoices].ch = ch;
p->choice[p->nchoices].text = strdup(text);
if (desc) {
p->choice[p->nchoices].desc = strdup(desc);
} else {
p->choice[p->nchoices].desc = strdup(text);
}
p->choice[p->nchoices].data = data;
p->choice[p->nchoices].heading = B_FALSE;
p->nchoices++;
}
void addheading(prompt_t *p, char *text) {
p->choice[p->nchoices].ch = '\0';
p->choice[p->nchoices].text = strdup(text);
p->choice[p->nchoices].desc = strdup(text);
p->choice[p->nchoices].data = NULL;
p->choice[p->nchoices].heading = B_TRUE;
p->nchoices++;
}
void addmsghist(char *text) {
char *localtext;
int db = B_FALSE;
localtext = strdup(text);
localtext = strrep(localtext, MORESTRING, "", NULL);
if (nmsghist < MAXHISTORY) {
strcpy(msghist[nmsghist], localtext);
nmsghist++;
if (db) dblog("adding to msg hist: %s",localtext);
} else {
int i;
// shuffle everything up then replace last one
for (i = 0; i < (MAXHISTORY-1); i++) {
strcpy(msghist[i], msghist[i+1]);
}
strcpy(msghist[MAXHISTORY-1], localtext);
if (db) dblog("replacing last msg hist: %s",localtext);
}
free(localtext);
}
void addpromptq(prompt_t *p, char *q) {
if (p->q[p->nqs]) {
free(p->q[p->nqs]);
}
p->q[p->nqs] = strdup(q);
p->nqs++;
}
void anim(cell_t *src, cell_t *dst, char ch, int colour) {
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;
glyph_t gl;
//int maxvisrange;
//int modmaxvisrange;
//int xray = B_FALSE;
//int wentuphill = B_FALSE;
int x2,y2;
// just in case
if (src->map != dst->map) return;
x1 = src->x;
y1 = src->y;
x2 = dst->x;
y2 = dst->y;
deltax = (x2 - x1);
if (deltax < 0) deltax = -deltax;
deltay = (y2 - y1);
if (deltay < 0) deltay = -deltay;
// going nowhere
if ((deltax == 0) && (deltay == 0)) {
return;
}
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;
gl.ch = ch;
gl.colour = colour;
// hide cursor
curs_set(0);
for (i = 0; i < numpixels ; i++) {
cell_t *cell;
// get current cell
cell = getcellat(src->map, x, y);
// update screen
if (haslos(player, cell)) {
updateviewfor(cell);
drawlevelfor(player);
// draw char & cursor at its current pos...
drawglyph(&gl, cell->x - viewx, cell->y - viewy);
//mvwprintw(gamewin, cell->y - viewy, cell->x - viewx, "%c", gl.ch);
wmove(gamewin, cell->y - viewy, cell->x - viewx);
wrefresh(gamewin);
usleep(ANIMDELAY);
}
// move to next cell
if (d < 0) {
xinc = xinc1;
yinc = yinc1;
dinc = dinc1;
} else {
xinc = xinc2;
yinc = yinc2;
dinc = dinc2;
}
d += dinc;
x += xinc;
y += yinc;
}
// show cursor
curs_set(1);
}
void animradial(cell_t *src, int radius, char ch, int colour) {
glyph_t gl;
int i;
int x,y;
cell_t *c;
gl.ch = ch;
gl.colour = colour;
// hide cursor
curs_set(0);
for (i = 0; i <= radius; i++) {
int drawn = B_FALSE;
// update screen
updateviewfor(src);
drawlevelfor(player);
for (y = src->y - radius ; y <= src->y + radius ; y++) {
for (x = src->x - radius ; x <= src->x + radius ; x++) {
c = getcellat(src->map, x, y);
if (c && haslos(player, c) && (getcelldist(src, c) <= i)) {
// draw char & cursor at its current pos...
//mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
drawglyph(&gl, c->x - viewx, c->y - viewy);
drawn = B_TRUE;
}
}
}
wrefresh(gamewin);
if (drawn) {
usleep(ANIMDELAY);
}
}
// show cursor
curs_set(1);
}
void animradialorth(cell_t *src, int radius, char ch,int colour) {
glyph_t gl;
int i;
int x,y;
cell_t *c;
gl.ch = ch;
gl.colour = colour;
// hide cursor
curs_set(0);
for (i = 0; i <= radius; i++) {
int drawn = B_FALSE;
// update screen
updateviewfor(src);
drawlevelfor(player);
for (y = src->y - radius ; y <= src->y + radius ; y++) {
for (x = src->x - radius ; x <= src->x + radius ; x++) {
c = getcellat(src->map, x, y);
if (c && haslos(player, c) && (getcelldistorth(src, c) <= i)) {
// draw char & cursor at its current pos...
//mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
drawglyph(&gl, c->x - viewx, c->y - viewy);
drawn = B_TRUE;
}
}
}
wrefresh(gamewin);
if (drawn) {
usleep(ANIMDELAY);
}
}
// show cursor
curs_set(1);
}
char askchar(char *prompt, char *validchars, char *def, int showchars) {
char buf[BUFLEN];
char *p;
char temp[2];
char ch;
int valid = B_FALSE;
wclear(msgwin);
if (showchars) {
sprintf(buf, "%s (",prompt);
for (p = validchars ; *p ; ) {
temp[0] = *p;
temp[1] = '\0';
strcat(buf, temp);
p++;
if (*p) {
strcat(buf, "/");
}
}
strcat(buf, ")");
} else {
sprintf(buf, "%s",prompt);
}
if (def) {
strcat(buf, " [");
strcat(buf, def);
strcat(buf, "]");
}
strcat(buf, "? ");
mvwprintw(msgwin, 0, 0, buf);
wrefresh(msgwin);
valid = B_FALSE;
while (!valid) {
ch = getkey();
if (strchr(validchars, ch)) {
valid = B_TRUE;
} else if ((ch == 10) && def) { // enter = default
valid = B_TRUE;
} else {
valid = B_FALSE;
}
}
clearmsg();
if ((ch == 13) && def) {
return def[0];
}
return ch;
}
cell_t *askcoords(char *prompt, int targettype) {
static int startlf = -1;
int finished = B_FALSE;
int moved = B_FALSE;
cell_t *c,*newcell;
char buf[BUFLEN];
cell_t *target[MAX_MAPW*MAX_MAPH];
int ntargets = 0,curtarget = -1;
int x,y;
// remember previously targetted lifeforms
if (startlf > 0) {
if (!findlf(player->cell->map, startlf)) {
startlf = -1;
}
}
// build list of targets if required
if (targettype != TT_NONE) {
for (y = 0; y < player->cell->map->h; y++) {
for (x = 0; x < player->cell->map->w; x++) {
c = getcellat(player->cell->map, x, y);
if (c && haslos(player, c)) {
int valid = B_FALSE;
if ((targettype & TT_MONSTER) && haslf(c) && cansee(player, c->lf) && (c->lf->controller != C_PLAYER)) {
valid = B_TRUE;
} else if ((targettype & TT_PLAYER) && haslf(c) && cansee(player, c->lf) && isplayer(c->lf)) {
valid = B_TRUE;
} else if ((targettype & TT_OBJECT) && hasobject(c)) {
valid = B_TRUE;
}
if (targettype & TT_DOOR) {
object_t *o;
o = hasobwithflag(c->obpile, F_DOOR);
if (o && !hasflag(o->flags, F_SECRETDOOR)) {
valid = B_TRUE;
}
}
if (valid) {
target[ntargets] = c;
if (curtarget == -1) curtarget = ntargets;
ntargets++;
}
}
}
}
}
// start prompting
if (curtarget == -1) {
c = player->cell;
} else {
int i;
// override curtarget based on previous target
for (i = 0; i < ntargets; i++) {
if (target[i]->lf && (target[i]->lf->id == startlf)) {
curtarget = i;
break;
}
}
c = target[curtarget];
}
wclear(msgwin);
mvwprintw(msgwin, 0, 0, "%s", prompt);
wrefresh(msgwin);
while (!finished) {
int dir;
char ch;
drawstatus();
updateviewfor(c);
drawlevelfor(player);
if (moved) {
// show what we are over in msg bar
strcpy(buf, "");
if (haslos(player, c)) {
// can see the cell...
if (c->lf) {
if (cansee(player, c->lf)) {
flag_t *f;
object_t *wep;
char extrainfo[BUFLEN];
strcpy(extrainfo, "");
getlfnamea(c->lf, buf);
// level
/*
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
sprintf(extrainfo, "level %d, ",c->lf->level);
}
*/
switch (getallegiance(c->lf)) {
case AL_FRIENDLY:
if (!isplayer(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
if (lfhasflagval(c->lf, F_PETOF, player->id, NA, NA, NULL)) {
if (lfhasflag(c->lf, F_ANIMAL)) {
strcat(extrainfo, "pet");
} else {
strcat(extrainfo, "ally");
}
} else {
strcat(extrainfo, "friendly");
}
}
break;
case AL_PEACEFUL:
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "peaceful");
break;
case AL_HOSTILE:
break;
}
if (isfleeing(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "fleeing");
}
if (lfhasflag(c->lf, F_RESTING)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "resting");
}
if (lfhasflag(c->lf, F_ASLEEP)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "asleep");
}
// hp
if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) ) {
char buf2[BUFLEN];
// show actual hp
sprintf(buf2, "hp %d/%d",c->lf->hp, c->lf->maxhp);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2);
} else {
char buf2[BUFLEN];
// show condition name
sprintf(buf2, "%s",getseenlfconditionname(c->lf, player));
if (strlen(buf2)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2);
}
}
wep = getweapon(c->lf);
if (wep && (c->lf->race->id != R_DANCINGWEAPON)) {
object_t *secwep;
char obname[BUFLEN];
char buf2[BUFLEN];
getobname(wep, obname, wep->amt);
sprintf(buf2, "weilding %s",obname);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
secwep = getequippedob(c->lf->pack, BP_SECWEAPON);
if (secwep && (secwep != wep)) {
getobname(secwep, obname, secwep->amt);
strcat(buf2, " and ");
strcat(buf2, obname);
}
strcat(extrainfo, buf2);
} else {
wep = getequippedob(c->lf->pack, BP_SECWEAPON);
if (wep) {
char obname[BUFLEN];
char buf2[BUFLEN];
getobname(wep, obname, wep->amt);
sprintf(buf2, "weilding %s",obname);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2);
}
}
f = lfhasflag(c->lf, F_GRABBING);
if (f) {
lifeform_t *lf2;
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
char lfname2[BUFLEN];
char buf2[BUFLEN];
getlfname(lf2, lfname2);
sprintf(buf2, "holding %s",lfname2);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2);
}
}
f = lfhasflag(c->lf, F_GRABBEDBY);
if (f) {
lifeform_t *lf2;
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
char lfname2[BUFLEN];
char buf2[BUFLEN];
getlfname(lf2, lfname2);
sprintf(buf2, "held by %s",lfname2);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2);
}
}
if (strlen(extrainfo)) {
char buf2[BUFLEN];
sprintf(buf2, " [%s]",extrainfo);
strcat(buf, buf2);
}
} else {
void *thing;
// lf there but can't see it
if (isinscanrange(c, &thing, buf, NULL) == TT_MONSTER) {
// if scanned, show it.
} else {
// otherwise, show objects
object_t *o;
// find top object name
o = gettopobject(c);
if (o) {
getobname(o, buf, o->amt);
}
}
}
} else {
object_t *o;
// find top object name
o = gettopobject(c);
if (o) {
getobname(o, buf, o->amt);
}
}
} else {
// can't see objects or lf there
void *thing;
char desc[BUFLEN];
switch (isinscanrange(c, &thing, desc, NULL)) {
case TT_MONSTER:
case TT_OBJECT:
strcpy(buf, desc);
break;
default:
break;
}
}
// dont use msg() to avoid 'more's
capitalise(buf);
wclear(msgwin);
mvwprintw(msgwin, 0, 0, "%s",buf);
wrefresh(msgwin);
}
// move cursor selected position
wmove(gamewin, c->y - viewy, c->x - viewx);
redraw();
// get input
ch = getch();
if (ch == '.') {
clearmsg();
// remember this target
if (c->lf) {
startlf = c->lf->id;
}
return c;
} else if (ch == 27) { // ESC - cancel
finished = B_TRUE;
} else if ((ch == '\'') && (ntargets > 0)) { // cycle targets
if (curtarget != -1) { // -1 means no targets
curtarget++;
if (curtarget >= ntargets) curtarget = 0;
c = target[curtarget];
moved = B_TRUE;
}
} else {
dir = chartodir(ch);
if (dir != D_NONE) {
newcell = getcellindir(c, dir);
if (newcell) {
c = newcell;
moved = B_TRUE;
}
}
}
}
clearmsg();
return NULL;
}
// retbuf must already be allocated
// "def" is optional
char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def) {
char buf[BUFLEN];
char *ending;
wclear(msgwin);
sprintf(buf, "%s",prompt);
if (def) {
strcat(buf, " [");
strcat(buf, def);
strcat(buf, "]");
}
asprintf(&ending, "%c ",punc);
strcat(buf, ending);
free(ending);
mvwprintw(msgwin, 0, 0, buf);
wrefresh(msgwin);
echo();
wgetnstr(msgwin, retbuf, retbuflen);
noecho();
clearmsg();
if (def && (strlen(retbuf) == 0)) {
strcpy(retbuf, def);
}
return retbuf;
}
/*
void announceob(enum OBTYPE oid) {
switch (oid) {
case OT_RING_INVULN:
msg("You feel indestructable!");
break;
default:
break;
}
}
*/
int announceflaggain(lifeform_t *lf, flag_t *f) {
int donesomething = B_FALSE;
lifeform_t *lf2;
char lfname[BUFLEN];
char buf[BUFLEN];
char *buf2;
if (!lf->born) {
return B_FALSE;
}
if (lf->race->id == R_DANCINGWEAPON) {
return B_FALSE;
}
getlfname(lf, lfname);
if (isdead(player)) return B_FALSE;
// player can't see this?
// We need to check "!isplayer(lf)" as well, otherwise
// we'll get no announcement when the player turns
// invisible and doesn't have see invisible.
if (!isplayer(lf) && !cansee(player, lf)) {
return B_FALSE;
}
switch (f->id) {
case F_ATTRMOD:
switch (f->val[0]) {
case A_STR:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "weaker" : "stronger");
break;
case A_IQ:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "foolish" : "smarter");
break;
case A_DEX:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "sluggish" : "agile");
break;
case A_CON:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "frail" : "healthier");
break;
}
donesomething = B_TRUE;
break;
case F_ATTRSET:
if (f->val[1] != real_getattr(lf, f->val[0], B_TRUE)) {
int myatt;
myatt = real_getattr(lf, f->val[0], B_TRUE);
switch (f->val[0]) {
case A_STR:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < myatt) ? "weak" : "strong");
break;
case A_IQ:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < myatt) ? "foolish" : "smart");
break;
case A_DEX:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < myatt) ? "sluggish" : "agile");
break;
case A_CON:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "frail" : "healthier");
break;
}
}
donesomething = B_TRUE;
break;
case F_MAGICARMOUR:
msg("%s %s appears around %s!",needan(f->text) ? "An" : "A", f->text, lfname);
donesomething = B_TRUE;
break;
case F_ASLEEP:
msg("%s fall%s asleep.",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_BEINGSTONED:
msg("%s begin%s to turn to stone!",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_BLIND:
if (isplayer(lf)) {
msg("%s cannot see!",lfname);
} else {
msg("%s is blinded!",lfname);
}
donesomething = B_TRUE;
break;
case F_CANCAST:
if (isplayer(lf)) { // don't know if monsters get it
objecttype_t *ot;
ot = findot(f->val[0]);
if (ot) {
msg("You have learned the spell '%s'.", ot->name);
donesomething = B_TRUE;
}
}
break;
case F_CANWILL:
if (isplayer(lf)) { // don't know if monsters get it
objecttype_t *ot;
ot = findot(f->val[0]);
if (ot && (!hasflag(ot->flags, F_NOANNOUNCE))) {
char buf[BUFLEN];
sprintf(buf, "You have learned the ability '%s'.", ot->name);
/*
if (f->val[2] != NA) {
char turnbuf[BUFLEN];
sprintf(turnbuf, " (every %d turn%s)",f->val[2], (f->val[2] == 1) ? "" : "s");
strcat(buf, turnbuf);
}
strcat(buf, ".");
*/
msg(buf, ot->name); more();
donesomething = B_TRUE;
}
}
break;
case F_CHARMEDBY:
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfname(lf2, buf);
msg("%s %s now under %s%s power!",lfname, isplayer(lf) ? "are" : "is", buf,getpossessive(buf));
donesomething = B_TRUE;
}
break;
case F_CONTROL:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel very in control of yourself.");
donesomething = B_TRUE;
}
break;
case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel immune to %s!", getdamnamenoun(f->val[0]));
donesomething = B_TRUE;
}
break;
case F_DTRESIST:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel resistant to %s!", getdamnamenoun(f->val[0]));
donesomething = B_TRUE;
}
break;
case F_DTVULN:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel vulnerable to %s!", getdamnamenoun(f->val[0]));
donesomething = B_TRUE;
}
break;
case F_DETECTAURAS:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel aware of spiritual auras around you.");
donesomething = B_TRUE;
}
break;
case F_DETECTLIFE:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can now detect nearby lifeforms.");
donesomething = B_TRUE;
}
break;
case F_DETECTOBS:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can now detect nearby objects.");
donesomething = B_TRUE;
}
break;
case F_DETECTMAGIC:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel sensitive to magical enchantments.");
donesomething = B_TRUE;
}
break;
case F_DETECTMETAL:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can now detect nearby metal.");
donesomething = B_TRUE;
}
break;
case F_DODGES:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can now dodge attacks.");
donesomething = B_TRUE;
}
break;
case F_HIDING:
if (isplayer(lf)) { // don't know if monsters get it
if (f->val[0] < 0) {
msg("You are now trying to hide.");
} else {
msg("You are now hiding.");
}
donesomething = B_TRUE;
}
break;
case F_INVISIBLE:
if (isplayer(lf)) {
if (lfhasflag(player, F_SEEINVIS)) {
msg("Your body turns transparent!");
} else {
msg("Your body turns invisible!");
}
donesomething = B_TRUE;
} else {
if (lfhasflag(player, F_SEEINVIS)) {
msg("%s turns transparent!", lfname);
donesomething = B_TRUE;
} else {
msg("%s vanishes!", lfname);
}
}
break;
case F_INVULNERABLE:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel invulnerable!");
donesomething = B_TRUE;
}
break;
case F_FLEEFROM:
// who are they fleeing from?
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfname(lf2, buf);
if ((f->lifetime == PERMENANT) || (f->lifetime >= 4)) {
msg("%s turn%s to flee from %s!", lfname, isplayer(lf) ? "" : "s",
(cansee(player, lf2) || isplayer(lf2)) ? buf : "something");
} else { // jsut scared a little bit
msg("%s cower%s away from %s!", lfname, isplayer(lf) ? "" : "s",
(cansee(player, lf2) || isplayer(lf2)) ? buf : "something");
}
}
break;
case F_POISONED:
msg("%s %s very sick.", lfname, isplayer(lf) ? "feel" : "looks");
donesomething = B_TRUE;
break;
case F_ENHANCESEARCH:
if (isplayer(lf)) {
msg("You feel very perceptive!");
}
donesomething = B_TRUE;
break;
case F_DRUNK:
msg("%s %s tipsy.", lfname, isplayer(lf) ? "feel" : "looks");
donesomething = B_TRUE;
break;
case F_EXTRADAM:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel more dangerous!");
donesomething = B_TRUE;
}
break;
case F_EXTRAMP:
if (isplayer(lf)) { // don't know if monsters get it
msg("Your magical power feels boosted!");
donesomething = B_TRUE;
}
break;
case F_EXTRALUCK:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel lucky!");
donesomething = B_TRUE;
}
break;
case F_FASTACT:
msg("%s %s",lfname, isplayer(lf) ? "feel accelerated!" : "looks accelerated!");
donesomething = B_TRUE;
break;
case F_FASTMOVE:
msg("%s %s faster.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
donesomething = B_TRUE;
break;
case F_FASTACTMOVE:
msg("%s %s",lfname, isplayer(lf) ? "feel faster and quicker!" : "looks faster and quicker.");
donesomething = B_TRUE;
break;
case F_FLYING:
msg("%s begin%s to fly!",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_FROZEN:
// strip "frozen" out...
buf2 = strdup(lfname);
buf2 = strrep(buf2, "frozen ","",NULL);
msg("%s %s to ice!",lfname, isplayer(lf) ? "turn" : "turns");
donesomething = B_TRUE;
free(buf2);
break;
case F_GRABBEDBY:
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfname(lf2, buf);
msg("%s %s %s!",buf, isplayer(lf2) ? "grab" : "grabs", lfname);
donesomething = B_TRUE;
}
break;
// don't announce grabbing.
case F_GRAVBOOSTED:
msg("%s %s stuck to the floor!",lfname, isplayer(lf) ? "are" : "is");
donesomething = B_TRUE;
break;
case F_LEVITATING:
msg("%s begin%s to levitate in the air!",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_MAGSHIELD:
msg("%s %s surrounded by a magnetic shield!",lfname, isplayer(lf) ? "are" : "is");
donesomething = B_TRUE;
break;
case F_NAUSEATED:
if (isplayer(lf)) {
msg("You are nauseated by a disgusting stench!");
donesomething = B_TRUE;
}
break;
case F_NONCORPOREAL:
msg("%s%s body becomes transparent!",lfname, getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_PAIN:
msg("%s%s skin erupts in stings and burns!",lfname, getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_PARALYZED:
if (isplayer(lf)) {
msg("You cannot move!");
} else {
msg("%s stops moving!",lfname);
}
donesomething = B_TRUE;
break;
case F_PHOTOMEM:
if (isplayer(lf)) { // don't know if monsters get it
msg("You will no longer forget your surroundings.");
donesomething = B_TRUE;
}
break;
case F_PRODUCESLIGHT:
msg("%s start%s producing light!", lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_REGENERATES:
if (isplayer(lf)) { // don't know if monsters get it
msg("Your body's healing rate is enhanced!");
donesomething = B_TRUE;
}
break;
case F_RESISTMAG:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel %simmune to magic.", hasflag_real(lf->flags, F_RESISTMAG, NA, f) ? "more " : "");
donesomething = B_TRUE;
}
break;
case F_RISEASGHOST:
if (isplayer(lf)) { // don't know if monsters get it
msg("You will rise as a ghost after death.");
donesomething = B_TRUE;
}
break;
case F_SEEINVIS:
if (isplayer(lf)) { // don't know if monsters get it
msg("You vision seems enhanced.");
donesomething = B_TRUE;
}
break;
case F_SEEINDARK:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can now see in the dark.");
donesomething = B_TRUE;
}
break;
case F_SLOWACT:
msg("%s %s",lfname, isplayer(lf) ? "feel sluggish." : "looks sluggish.");
donesomething = B_TRUE;
break;
case F_SLOWMOVE:
msg("%s %s slower.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
donesomething = B_TRUE;
break;
case F_SLOWACTMOVE:
msg("%s %s",lfname, isplayer(lf) ? "feel slow and sluggish." : "looks slow and sluggish.");
donesomething = B_TRUE;
break;
case F_SPRINTING:
msg("%s %s sprinting!",lfname, isplayer(lf) ? "start" : "starts");
donesomething = B_TRUE;
break;
case F_TIRED:
if (isplayer(lf)) {
msg("You are exhausted.");
} else if (cansee(player, lf)) {
msg("%s looks exhausted.",lfname);
}
break;
case F_TREMORSENSE:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can 'see' by sensing vibrations around you.");
donesomething = B_TRUE;
}
break;
case F_WINDSHIELD:
if (isplayer(lf)) {
msg("You are surrounded by a whirling cyclone!");
} else if (cansee(player, lf)) {
msg("%s is surrounded by a whirling cyclone!",lfname);
}
break;
case F_VISRANGEMOD:
if (isplayer(lf)) { // don't know if monsters get it
char fartext[BUFLEN];
if (f->val[0] > 0) {
int amt;
amt = abs(f->val[0]);
if (amt >= 7) {
strcpy(fartext, "a lot ");
} else if (amt >= 5) {
strcpy(fartext, "");
} else {
strcpy(fartext, "a little ");
}
msg("You can see %sfurther.", fartext);
} else {
int amt;
amt = abs(f->val[0]);
if (amt >= 7) {
msg("Your vision is dramatically reduced.");
} else if (amt >= 5) {
msg("Your vision is reduced.");
} else {
msg("Your vision is slightly reduced.");
}
}
donesomething = B_TRUE;
}
break;
case F_XRAYVIS:
if (isplayer(lf)) { // don't know if monsters get it
msg("The walls around you suddenly turn transparent!");
donesomething = B_TRUE;
}
break;
default: // no message
break;
}
if (donesomething) statdirty = B_TRUE;
return donesomething;
}
int announceflagloss(lifeform_t *lf, flag_t *f) {
char lfname[BUFLEN];
lifeform_t *lf2;
int donesomething = B_FALSE;
if (!lf->born) {
return B_FALSE;
}
if (lf->race->id == R_DANCINGWEAPON) {
return B_FALSE;
}
if (isdead(lf) || isdead(player)) return B_FALSE;
getlfname(lf, lfname);
// player can't see?
if (!cansee(player, lf)) {
return B_FALSE;
}
switch (f->id) {
case F_ATTRMOD:
switch (f->val[0]) {
case A_STR:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less strong" : "less weak");
break;
case A_IQ:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less smart" : "less foolish");
break;
case A_DEX:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less agile" : "less sluggish");
break;
case A_CON:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less healthy" : "less frail");
break;
}
donesomething = B_TRUE;
break;
case F_ATTRSET:
if (f->val[1] != real_getattr(lf, f->val[0], B_TRUE)) {
int myatt;
myatt = real_getattr(lf, f->val[0], B_TRUE);
switch (f->val[0]) {
case A_STR:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > myatt) ? "less strong" : "less weak");
break;
case A_IQ:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > myatt) ? "less smart" : "less foolish");
break;
case A_DEX:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > myatt) ? "less agile" : "less sluggish");
break;
case A_CON:
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less healthy" : "less frail");
break;
}
donesomething = B_TRUE;
}
break;
case F_MAGICARMOUR:
msg("%s%s %s vanishes.",lfname,getpossessive(lfname), f->text);
donesomething = B_TRUE;
break;
case F_ASLEEP:
msg("%s wake%s up.",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_BEINGSTONED:
msg("The fragments of stone around %s%s body drop%s away.",lfname, getpossessive(lfname), isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_BLIND:
msg("%s can see again.",lfname);
donesomething = B_TRUE;
break;
case F_CANCAST:
if (isplayer(lf)) { // don't know if monsters lose it
objecttype_t *ot;
ot = findot(f->val[0]);
if (ot) {
msg("You have forgotten how to cast '%s'.", ot->name);
donesomething = B_TRUE;
}
}
break;
case F_CANWILL:
if (isplayer(lf)) { // don't know if monsters lose it
objecttype_t *ot;
ot = findot(f->val[0]);
if (ot && (!hasflag(ot->flags, F_NOANNOUNCE))) {
msg("You can no longer use the ability '%s'.", ot->name);
donesomething = B_TRUE;
}
}
break;
case F_CHARMEDBY:
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
char buf[BUFLEN];
getlfname(lf2, buf);
msg("%s break%s free of %s%s control!",lfname, isplayer(lf) ? "" : "s", buf,getpossessive(buf));
donesomething = B_TRUE;
}
break;
case F_CONTROL:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You feel less controlled.");
donesomething = B_TRUE;
}
break;
case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer immune to %s.", getdamnamenoun(f->val[0]));
donesomething = B_TRUE;
}
break;
case F_DTRESIST:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer resistant to %s.", getdamnamenoun(f->val[0]));
donesomething = B_TRUE;
}
break;
case F_DTVULN:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer vulnerable to %s.", getdamnamenoun(f->val[0]));
donesomething = B_TRUE;
}
break;
case F_ENHANCESEARCH:
if (isplayer(lf)) {
msg("You no longer feel so perceptive!");
}
donesomething = B_TRUE;
break;
case F_DRUNK:
msg("%s %s more steady now.", lfname, isplayer(lf) ? "feel" : "looks");
donesomething = B_TRUE;
break;
case F_EXTRADAM:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You no longer feel more dangerous.");
donesomething = B_TRUE;
}
break;
case F_EXTRALUCK:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel less lucky.");
donesomething = B_TRUE;
}
break;
case F_EXTRAMP:
if (isplayer(lf)) { // don't know if monsters get it
msg("Your magical power no longer feels boosted.");
donesomething = B_TRUE;
}
break;
case F_FASTACT:
msg("%s %s",lfname, isplayer(lf) ? "are no longer accelerated." : "is no longer accelerated.");
donesomething = B_TRUE;
break;
case F_FASTMOVE:
msg("%s %s slower.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
donesomething = B_TRUE;
break;
case F_FASTACTMOVE:
msg("%s %s",lfname, isplayer(lf) ? "slow down back to normal speed." : "slows down to its normal speed.");
donesomething = B_TRUE;
break;
case F_FLEEFROM:
msg("%s stop%s fleeing.", lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_FRIENDLY:
msg("%s no longer looks quite so friendly!", lfname);
break;
case F_POISONED:
msg("%s %s less sick now.", lfname, isplayer(lf) ? "feel" : "looks");
donesomething = B_TRUE;
break;
case F_DODGES:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You can no longer dodge attacks.");
donesomething = B_TRUE;
}
break;
case F_HIDING:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer hidden.");
donesomething = B_TRUE;
}
break;
case F_INVISIBLE:
if (isplayer(lf)) {
msg("Your are no longer invisible.");
donesomething = B_TRUE;
} else {
if (lfhasflag(player, F_SEEINVIS)) {
msg("%s is no longer transparent.", lfname);
donesomething = B_TRUE;
} else {
msg("%s appears out of nowhere!", lfname);
}
}
break;
case F_INVULNERABLE:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You no longer feel invulnerable.");
donesomething = B_TRUE;
}
break;
case F_DETECTAURAS:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You can no longer detect auras.");
donesomething = B_TRUE;
}
break;
case F_DETECTLIFE:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can no longer detect nearby lifeforms.");
donesomething = B_TRUE;
}
break;
case F_DETECTOBS:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can no longer detect nearby objects.");
donesomething = B_TRUE;
}
break;
case F_DETECTMAGIC:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can no longer detect magical enchantments.");
donesomething = B_TRUE;
}
break;
case F_DETECTMETAL:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can no longer detect nearby metal.");
donesomething = B_TRUE;
}
break;
case F_FLYING:
msg("%s %s flying.", lfname, isplayer(lf) ? "cease" : "stops");
donesomething = B_TRUE;
break;
case F_FROZEN:
if (isplayer(lf)) {
msg("You thaw out.");
} else {
msg("%s thaws out.", lfname);
}
donesomething = B_TRUE;
break;
case F_GRABBEDBY:
lf2 = findlf(NULL, f->val[0]);
if (lf2 && !isdead(lf2)) {
char buf[BUFLEN];
getlfname(lf2, buf);
msg("%s break%s free from %s!",lfname, isplayer(lf) ? "" : "s", buf);
donesomething = B_TRUE;
}
break;
case F_GRAVBOOSTED:
msg("%s %s no longer stuck to the floor.",lfname, isplayer(lf) ? "are" : "is");
donesomething = B_TRUE;
break;
case F_LEVITATING:
msg("%s %s down to the ground.", lfname, isplayer(lf) ? "float" : "floats");
donesomething = B_TRUE;
break;
case F_MAGSHIELD:
if (isplayer(lf)) { // don't know if monsters lose it
msg("Your magnetic shield vanishes.");
donesomething = B_TRUE;
}
break;
case F_NAUSEATED:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You no longer feel nauseated.");
donesomething = B_TRUE;
}
break;
case F_NONCORPOREAL:
msg("%s%s body solidifies.",lfname, getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_PAIN:
if (isplayer(lf)) { // don't konw if it expires for monsters
msg("Your skin stops hurting.");
donesomething = B_TRUE;
}
break;
case F_PARALYZED:
if (isplayer(lf)) { // don't konw if it expires for monsters
msg("You can move again.");
donesomething = B_TRUE;
}
break;
case F_PHOTOMEM:
if (isplayer(lf)) { // don't know if monsters lose it
msg("Your feel like you might forget your surroundings.");
donesomething = B_TRUE;
}
break;
case F_PRODUCESLIGHT:
msg("%s %s no longer producing light.", lfname, isplayer(lf) ? "are" : "is");
donesomething = B_TRUE;
break;
case F_REGENERATES:
if (isplayer(lf)) { // don't know if monsters lose it
msg("Your healing rate is no longer enhanced.");
donesomething = B_TRUE;
}
break;
case F_RESISTMAG:
if (isplayer(lf)) { // don't know if monsters lose it
if (hasflag_real(lf->flags, F_RESISTMAG, NA, f)) {
msg("You feel less immune to magic.");
} else {
msg("You are no longer immune to magic.");
}
donesomething = B_TRUE;
}
break;
/*
case F_RESTCOUNT:
if (isplayer(lf)) {
msg("Restcount expired.");
}
break;
*/
case F_RISEASGHOST:
if (isplayer(lf)) { // don't know if monsters get it
msg("You will no longer rise as a ghost after death.");
donesomething = B_TRUE;
}
break;
case F_SEEINVIS:
if (isplayer(lf)) { // don't know if monsters get it
msg("You vision returns to normal.");
donesomething = B_TRUE;
}
break;
case F_SEEINDARK:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You can no longer see in the dark.");
donesomething = B_TRUE;
}
break;
case F_SLOWACT:
msg("%s %s",lfname, isplayer(lf) ? "no longer feel sluggish." : "no longer looks sluggish.");
donesomething = B_TRUE;
break;
case F_SLOWMOVE:
msg("%s %s faster.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
donesomething = B_TRUE;
break;
case F_SLOWACTMOVE:
msg("%s %s",lfname, isplayer(lf) ? "speed back up." : "speeds back up.");
donesomething = B_TRUE;
break;
case F_SPRINTING:
if (f->val[0]) {
if (isplayer(lf)) { // don't know if monsters lose it (but you'll see them get exhausted)
msg("You stop sprinting.");
donesomething = B_TRUE;
}
} else {
if (isplayer(lf)) { // don't know if monsters get it
msg("You are no longer exhausted.");
} else {
msg("%s looks less exhausted.",lfname);
}
}
break;
case F_TIRED:
if (isplayer(lf)) { // don't know if monsters get it
msg("You are no longer exhausted.");
} else {
msg("%s looks less exhausted.",lfname);
}
donesomething = B_TRUE;
break;
case F_TREMORSENSE:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You no longer sense vibrations around you.");
donesomething = B_TRUE;
}
break;
case F_WINDSHIELD:
if (isplayer(lf) || cansee(player, lf)) {
msg("%s%s cyclonic shield vanishes.", lfname, getpossessive(lfname));
}
break;
case F_VISRANGEMOD:
if (isplayer(lf)) { // don't know if monsters get it
char fartext[BUFLEN];
if (f->val[0] < 0) {
int amt;
amt = abs(f->val[0]);
if (amt >= 7) {
strcpy(fartext, "a lot ");
} else if (amt >= 5) {
strcpy(fartext, "");
} else {
strcpy(fartext, "a little ");
}
msg("You can see %sfurther.", fartext);
} else {
int amt;
amt = abs(f->val[0]);
if (amt >= 7) {
msg("Your vision is dramatically reduced.");
} else if (amt >= 5) {
msg("Your vision is reduced.");
} else {
msg("Your vision is slightly reduced.");
}
}
donesomething = B_TRUE;
}
break;
case F_XRAYVIS:
if (isplayer(lf)) { // don't know if monsters lose it
msg("The walls around you are no longer transparent.");
donesomething = B_TRUE;
}
break;
default: // no message
break;
}
if (donesomething) statdirty = B_TRUE;
return donesomething;
}
int announceobflaggain(object_t *o, flag_t *f) {
int donesomething = B_FALSE;
char obname[BUFLEN];
char prefix[BUFLEN];
cell_t *loc;
loc = getoblocation(o);
if (isdead(player)) return B_FALSE;
// player can't see?
if (!haslos(player, loc)) {
return B_FALSE;
}
real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE);
if (o->pile->owner) {
if (isplayer(o->pile->owner)) {
sprintf(prefix, "Your %s",noprefix(obname));
} else {
char lfname[BUFLEN];
getlfname(o->pile->owner, lfname);
sprintf(prefix, "%s%s %s",lfname, getpossessive(lfname), noprefix(obname));
}
} else {
sprintf(prefix, "%s",obname);
}
switch (f->id) {
case F_ONFIRE:
donesomething = B_TRUE;
// don't want "the flaming sword catches on fire"
real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_TRUE, B_TRUE);
if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, (o->amt == 1) ? "es" : "");
break;
case F_PRODUCESLIGHT:
donesomething = B_TRUE;
if (o->birthtime != curtime) msg("%s start%s glowing!",prefix, (o->amt == 1) ? "s" : "");
break;
default: // no message
break;
}
return donesomething;
}
void announceobflagloss(object_t *o, flag_t *f) {
char obname[BUFLEN];
char prefix[BUFLEN];
char isare[BUFLEN];
cell_t *loc;
loc = getoblocation(o);
if (isdead(player)) return;
// player can't see?
if (!haslos(player, loc)) {
return;
}
real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE);
if (o->pile->owner) {
if (isplayer(o->pile->owner)) {
sprintf(prefix, "Your %s",noprefix(obname));
} else {
char lfname[BUFLEN];
getlfname(o->pile->owner, lfname);
sprintf(prefix, "%s%s %s",lfname, getpossessive(lfname), noprefix(obname));
}
} else {
sprintf(prefix, "%s",obname);
}
if (o->amt == 1) {
strcpy(isare, "is");
} else {
strcpy(isare, "are");
}
switch (f->id) {
case F_ONFIRE:
msg("%s %s no longer on fire.",prefix,isare);
break;
case F_PRODUCESLIGHT:
msg("%s %s no longer glowing.",prefix,isare);
break;
case F_WET:
msg("%s %s out.",prefix, (o->amt == 1) ? "dries" : "dry");
break;
default: // no message
break;
}
}
object_t *askobject(obpile_t *op, char *prompt, int *count, long opts) {
return doaskobject(op, prompt, count, opts, F_NONE);
}
object_t *askobjectwithflag(obpile_t *op, char *prompt, int *count, long opts, enum FLAG withflag) {
return doaskobject(op, prompt, count, opts, withflag, F_NONE);
}
/*
object_t *askobjectofclass(obpile_t *op, char *prompt, int *count, long opts, enum OBCLASS obclass) {
return doaskobject(op, prompt, count, opts, F_NONE, obclass, OC_NULL);
}
*/
int contains(enum OBCLASS *array, int nargs, enum OBCLASS want) {
int i;
for (i = 0; i < nargs; i++) {
if (array[i] == want) {
return B_TRUE;
}
}
return B_FALSE;
}
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters) {
int lastclass = OC_NULL;
int i;
int useobletters = B_TRUE;
if (myletters) {
useobletters = B_FALSE;
}
for (i = firstob ; (mylist[i] != NULL) && (*y < lastline); i++) {
char selchar;
char buf[BUFLEN];
char obname[BUFLEN];
char infobuf[BUFLEN];
char equipbuf[BUFLEN];
if (mylist[i]->type->obclass->id != lastclass) {
// print class heading
wattron(win, A_STANDOUT);
mvwprintw(win, *y, 0, "%s", mylist[i]->type->obclass->name);
(*y)++;
wattroff(win, A_STANDOUT);
lastclass = mylist[i]->type->obclass->id;
}
// print object name
getobname(mylist[i], obname,mylist[i]->amt);
if (sellist && sellist[i]) {
if ((selcount[i] == ALL) || (selcount[i] == mylist[i]->amt)) {
selchar = '*';
} else {
selchar = '#';
}
} else {
selchar = ' ';
}
sprintf(buf, "%c %c - %s", selchar, useobletters ? mylist[i]->letter : myletters[i],
obname);
setobcolour(win, mylist[i]);
getobextrainfo(mylist[i], infobuf);
getobequipinfo(mylist[i], equipbuf);
mvwprintw(win, *y, 0, "%s%s", buf, infobuf);
unsetobcolour(win, mylist[i]);
if (strlen(equipbuf)) {
setcol(win, C_BROWN);
wprintw(win, "%s", equipbuf);
unsetcol(win, C_BROWN);
}
(*y)++;
}
*counter = i;
}
object_t *doaskobject(obpile_t *op, char *prompt, int *count, long opts, ...) {
int c,i;
object_t *mylist[MAXPILEOBS+1];
char myletters[MAXPILEOBS+1];
char numstring[BUFLEN];
int firstob = 0;
int nextpage = -1;
int lastline = SCREENH-4;
int finished;
char nextlet = 'a';
int useobletters;
//flag_t *f;
object_t *ammo;
enum FLAG wantflag[MAXCANDIDATES];
va_list flags;
int nwantflags;
// construct list of valid obclasses
va_start(flags, opts);
nwantflags = 0;
wantflag[nwantflags] = va_arg(flags, enum FLAG);
while (wantflag[nwantflags] != F_NONE) {
nwantflags++;
wantflag[nwantflags] = va_arg(flags, enum FLAG);
}
va_end(flags);
dblog("nwantflags is %d",nwantflags);
// remember player's current ammo
if (op->owner) {
ammo = getammo(op->owner);
}
if (countobs(op) <= 0) {
// no objects in pack
cls();
mvwprintw(mainwin, 2, 0, "You have no possessions.");
// wait for key
centre(mainwin, getmaxy(mainwin)-1, "[Press any key]");
getch();
clearmsg();
drawscreen();
return NULL;
}
reason = E_OK;
// if picking form a player's pack, use the object's letters.
// otherwise just label them a, b, c, etc.
if (op->owner && isplayer(op->owner)) {
useobletters = B_TRUE;
} else {
useobletters = B_FALSE;
}
// construct a list of objects
c = 0;
i = 0;
while (sortorder[c] != OC_NULL) {
object_t *o;
//if (!wantoc || (sortorder[c] == wantoc->id)) {
//if (!nwantflags || contains(wantflag, nwantflags, sortorder[c])) {
// add all objects of this class
for (o = op->first ; o ; o = o->next) {
if (o->type->obclass->id == sortorder[c]) {
int ok;
int n;
// can we include this object?
ok = B_TRUE;
// check for wanted flags
for (n = 0; n < nwantflags; n++) {
if (!hasflag(o->flags, wantflag[n])) {
ok = B_FALSE;
break;
}
}
if (ok) {
if (opts & AO_SPECIFIED) {
int n;
int found = B_FALSE;
// does retlist contain this?
for (n = 0; n < nretobs; n++) {
if (retobs[n] == o) {
found = B_TRUE;
break;
}
}
if (!found) {
ok = B_FALSE;
}
}
}
if (ok) {
ok = obmatchescondition(o, opts);
}
if (ok) {
mylist[i] = o;
myletters[i] = nextlet;
if (++nextlet > 'z') nextlet = 'A';
i++;
}
} // end if ob matches sortorder
} // end for each ob
c++;
}
mylist[i] = NULL;
// start displaying from the first one
firstob = 0;
nextpage = -1;
finished = B_FALSE;
strcpy(numstring, "");
while (!finished) {
int y;
int ch;
cls();
// list the objects
y = 2;
listobs(mainwin, mylist, NULL, NULL, firstob, &i, lastline, &y, useobletters ? NULL : myletters );
if (mylist[i] == NULL) {
nextpage = -1;
} else {
nextpage = i;
}
// draw prompt
if (strlen(numstring) > 0) {
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit) [%s]: ",prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
numstring);
} else {
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit): ", prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "");
}
if (nextpage != -1) {
mvwprintw(mainwin, y, 0, MORESTRING);
}
// update screen
wrefresh(mainwin);
// wait for keypess
ch = getch();
if (ch == 27) { // ESCAPE
finished = B_TRUE;
break;
}
// otherwise look for shift key etc..
ch = keycodetokey(ch);
// then handle input
if (ch == ' ') { // next page
if (nextpage == -1) { // go to first page
firstob = 0;
} else {
firstob = nextpage;
}
} else if (isalpha(ch) || (ch == '$')) {
object_t *o;
// describe that object
if (useobletters) {
o = findobl(op, ch);
} else {
o = NULL;
for (i = firstob ; (mylist[i] != NULL) && (y < lastline); i++) {
if (myletters[i] == ch) {
o = mylist[i];
break;
}
}
}
if (o) {
// make sure count is okay...
if (count && *count > o->amt) {
*count = o->amt;
}
if (count && (*count == ALL)) {
*count = o->amt;
}
// display game windows again
clearmsg();
drawscreen();
return o;
}
} else if ((ch == '-') && (opts & AO_INCLUDENOTHING)) { // select nothing
reason = E_SELNOTHING;
// display game windows again
clearmsg();
drawscreen();
return NULL;
} else if (isdigit(ch) && count) {
char temp[2];
temp[0] = ch;
temp[1] = '\0';
strcat(numstring, temp);
if (count) *count = atoi(numstring);
} else if ((ch == 8) && count) { // backspace
if (strlen(numstring) > 0) {
// remove last letter of number string
numstring[strlen(numstring)-1] = '\0';
if (count) *count = atoi(numstring);
}
}
// sanity check count...
if (count && (*count == 0)) {
strcpy(numstring, "");
}
}
// clear msg bar
clearmsg();
// display game windows again
drawscreen();
return NULL;
}
int askobjectmulti(obpile_t *op, char *prompt, long opts) {
int c,i;
object_t *mylist[MAXPILEOBS+1];
int selected[MAXPILEOBS+1];
int selcount[MAXPILEOBS+1];
char myletters[MAXPILEOBS+1];
char numstring[BUFLEN];
int firstob = 0;
int nextpage = -1;
int lastline = SCREENH-4;
int finished;
int count = ALL;
char nextlet = 'a';
int useobletters;
objectclass_t *wantoc = NULL;
object_t *ammo;
// remember player's current ammo
if (op->owner) {
ammo = getammo(op->owner);
}
clearretobs();
if (countobs(op) <= 0) {
// no objects in pack
cls();
mvwprintw(mainwin, 2, 0, "You have no possessions.");
// wait for key
centre(mainwin, getmaxy(mainwin)-1, "[Press any key]");
getch();
clearmsg();
drawscreen();
return B_TRUE;
}
reason = E_OK;
// if picking form a player's pack, use the object's letters.
// otherwise just label them a, b, c, etc.
if (op->owner && isplayer(op->owner)) {
useobletters = B_TRUE;
} else {
useobletters = B_FALSE;
}
// construct a list of objects
c = 0;
i = 0;
while (sortorder[c] != OC_NULL) {
object_t *o;
if (!wantoc || (sortorder[c] == wantoc->id)) {
// add all objects of this class
for (o = op->first ; o ; o = o->next) {
if (o->type->obclass->id == sortorder[c]) {
int ok;
// can we include this object?
ok = obmatchescondition(o, opts);
if (ok) {
mylist[i] = o;
myletters[i] = nextlet;
selected[i] = B_FALSE;
selcount[i] = 0;
if (++nextlet > 'z') nextlet = 'A';
i++;
}
}
}
}
c++;
}
mylist[i] = NULL;
// start displaying from the first one
firstob = 0;
nextpage = -1;
finished = B_FALSE;
strcpy(numstring, "");
while (!finished) {
int y;
int ch;
cls();
// list the objects
y = 2;
listobs(mainwin, mylist, selected, selcount, firstob, &i, lastline, &y, useobletters ? NULL : myletters );
if (mylist[i] == NULL) {
nextpage = -1;
} else {
nextpage = i;
}
// draw prompt
if (nextpage != -1) {
mvwprintw(mainwin, y, 0, MORESTRING);
}
if (strlen(numstring) > 0) {
mvwprintw(mainwin, 0, 0, "%s (%s','=all, ESC to quit) [%s]: ",prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
numstring);
} else {
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit): ", prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "");
}
// update screen
wrefresh(mainwin);
// wait for keypess
ch = getch();
if (ch == 27) { // ESCAPE
finished = B_TRUE;
break;
}
// otherwise look for shift key etc..
ch = keycodetokey(ch);
// then handle input
if (ch == ' ') { // next page
if (nextpage == -1) { // go to first page
firstob = 0;
} else {
firstob = nextpage;
}
} else if (isalpha(ch) || (ch == '$')) {
int which = -1;
// select it
if (useobletters) {
object_t *o;
o = findobl(op, ch);
// find ob in list
for (i = 0 ; (mylist[i] != NULL) ; i++) {
if (mylist[i] == o) {
which = i;
break;
}
}
} else {
for (i = 0 ; (mylist[i] != NULL) ; i++) {
if (myletters[i] == ch) {
which = i;
break;
}
}
}
if (which != -1) {
int val;
if (selected[i]) val = B_FALSE;
else val = B_TRUE;
selected[i] = val;
if (val == B_TRUE) {
selcount[i] = count;
if (selcount[i] > mylist[i]->amt) selcount[i] = ALL;
} else {
selcount[i] = 0;
}
// reset count
strcpy(numstring, "");
count = ALL;
}
} else if ((ch == '-') && (opts & AO_INCLUDENOTHING)) { // select nothing
reason = E_SELNOTHING;
nretobs = 0;
// display game windows again
clearmsg();
drawscreen();
return B_TRUE;
} else if (ch == ',') { // toggle all/none
int val;
if (selected[0]) { // deselect all
val = B_FALSE;
} else { // select all
val = B_TRUE;
}
for (i = 0 ; (mylist[i] != NULL) ; i++) {
selected[i] = val;
selcount[i] = mylist[i]->amt;
}
} else if (ch == 10) { // enter
// construct list to return
nretobs = 0;
for (i = 0 ; (mylist[i] != NULL); i++) {
if (selected[i]) {
retobs[nretobs] = mylist[i];
retobscount[nretobs] = selcount[i];
nretobs++;
}
}
finished = B_TRUE;
} else if (isdigit(ch) && count) {
char temp[2];
temp[0] = ch;
temp[1] = '\0';
strcat(numstring, temp);
count = atoi(numstring);
} else if ((ch == 8) && count) { // backspace
if (strlen(numstring) > 0) {
// remove last letter of number string
numstring[strlen(numstring)-1] = '\0';
count = atoi(numstring);
}
}
/*
// sanity check count...
if (count && (*count == 0)) {
strcpy(numstring, "");
}
*/
}
// clear msg bar
clearmsg();
// display game windows again
drawscreen();
if (nretobs <= 0) {
return B_TRUE;
}
return B_FALSE;
}
void centre(WINDOW *win, int y, char *format, ... ) {
int w;
char buf[BUFLEN];
va_list args;
int startx;
va_start(args, format);
vsprintf( buf, format, args );
va_end(args);
w = getmaxx(win);
startx = (w/2) - (strlen(buf)/2);
if (startx < 0) startx = 0;
mvwprintw(win, y, (w/2) - (strlen(buf)/2), buf);
}
int chartodir(char c) {
switch (tolower(c)) {
case 'h': return D_W;
case 'j': return D_S;
case 'k': return D_N;
case 'l': return D_E;
case 'y': return DC_NW;
case 'u': return DC_NE;
case 'b': return DC_SW;
case 'n': return DC_SE;
}
return D_NONE;
}
char checkforkey(void) {
char ch;
nodelay(mainwin, TRUE);
ch = getch();
nodelay(mainwin, FALSE);
if (ch == ERR) ch = '\0';
return ch;
}
void clearmsg(void) {
real_clearmsg(B_FALSE);
}
// use forced clear msg when we have
// drawn over the whole screen, eg.
void real_clearmsg(int force) {
// remember message history
if (force || strcmp(msgbuf, "")) {
char *p;
int ok = B_FALSE;
// make sure msg contains non-whitespace characters
for (p = msgbuf; p ; p++) {
if (*p != ' ') {
ok = B_TRUE;
break;
}
}
if (ok) {
addmsghist(msgbuf);
}
strcpy(msgbuf, "");
wclear(msgwin);
wrefresh(msgwin);
}
}
int cleanupgfx(void) {
curs_set(1);
endwin();
return B_FALSE;
}
void updatestatus(void) {
wrefresh(statwin);
}
void updateviewfor(cell_t *cell) {
// calculate viewport if required
if ((viewx == -9999) || (viewy == -9999)) {
// try to centre player
viewx = cell->x - (SCREENW/2);
viewy = cell->y - (SCREENH/2);
}
while ((cell->x - viewx) >= ((SCREENW / 3)*2)) {
viewx++;
}
while ((cell->y - viewy) >= ((SCREENH / 3)*2)) {
viewy++;
}
while ((cell->x - viewx) <= (SCREENW/3)) {
viewx--;
}
while ((cell->y - viewy) <= (SCREENH/3)) {
viewy--;
}
}
void drawscreen(void) {
if (gamemode < GM_GAMESTARTED) {
return;
}
if (statdirty) {
drawstatus();
wrefresh(statwin);
statdirty = B_FALSE;
}
if (needredraw) {
updateviewfor(player->cell);
drawlevelfor(player);
drawcursor(); // this will call redraw gamewin
}
}
void clearretobs(void) {
int i;
for (i = 0; i < MAXPILEOBS+1; i++) {
retobs[i] = NULL;
retobscount[i] = ALL;
}
nretobs = 0;
}
// clears the screen
void cls(void) {
wclear(mainwin);
statdirty = B_TRUE;
}
void describeob(object_t *o) {
char buf[BUFLEN];
char buf2[BUFLEN];
int y;
flag_t *f;
int obknown;
int i;
cls();
obknown = isknown(o);
// title
getobname(o, buf,o->amt);
mvwprintw(mainwin, 0, 0, buf);
getobdesc(o, buf);
mvwprintw(mainwin, 2, 0, buf);
// properties
y = 4;
if (o->material->id != MT_FOOD) {
mvwprintw(mainwin, y, 0, "%s made from %s.",(o->amt == 1) ? "It is" : "They are", o->material->name); y++;
}
if (isedible(o)) {
int basenutr;
basenutr = getnutritionbase(o);
mvwprintw(mainwin, y, 0, "%s edible.",(o->amt == 1) ? "It is" : "They are"); y++;
mvwprintw(mainwin, y, 0, "%s %s.",(o->amt == 1) ? "It is" : "They are each", getfillingname(basenutr)); y++;
}
if (o->amt == 1) {
getweighttext(getobweight(o), buf);
mvwprintw(mainwin, y, 0, "It weighs %s.",buf);
} else {
getweighttext(getobweight(o), buf);
getweighttext(getobunitweight(o), buf2);
mvwprintw(mainwin, y, 0, "They weigh %s (%s each).",buf, buf2);
}
y++;
// weapons?
if (o->type->obclass->id == OC_WEAPON) {
int delay;
if (hasflag(o->flags, F_DAM)) {
int bonus = 0;
f = hasflag(o->flags, F_BONUS);
if (f && f->known) {
// only tell player about bonuses if they are known.!
bonus = f->val[0];
}
f = hasflag(o->flags, F_DAM);
if (f) {
char buf[BUFLEN];
int mindam,maxdam;
enum DAMTYPE damtype;
damtype = f->val[0];
getdamrange(f, &mindam, &maxdam);
mindam += bonus;
maxdam += bonus;
if (mindam < 0) mindam = 0;
if (maxdam < 0) maxdam = 0;
if (mindam == maxdam) {
sprintf(buf, "It inflicts %d %s damage",maxdam, getdamname(damtype));
} else {
sprintf(buf, "It inflicts %d-%d %s damage",mindam,maxdam, getdamname(damtype));
}
//dicetotext(f->val[0], f->val[1], f->val[2], NULL, NULL, dicebuf, NULL);
strcat(buf, " (");
strcat(buf, f->text);
strcat(buf, ").");
mvwprintw(mainwin, y, 0, "%s",buf);
y++;
}
}
// other extra damage or effects?
f = hasflag(o->flags, F_ONFIRE);
if (f) {
mvwprintw(mainwin, y, 0, " It also inflicts extra burning damage.");
y++;
}
delay = 100;
f = hasflag(o->flags, F_OBATTACKDELAY);
if (f) {
delay = f->val[0];
}
mvwprintw(mainwin, y, 0, "Its attack delay is %d%%.",delay - 100);
y++;
f = hasflag(o->flags, F_ACCURACY);
if (f) {
int acc;
acc = getobaccuracy(o, NULL);
mvwprintw(mainwin, y, 0, "It has %s accuracy.",getaccuracyname(acc));
y++;
}
f = hasflag(o->flags, F_DISARMATTACK);
if (f) {
mvwprintw(mainwin, y, 0, "A skilled weilder can disarm opponents with it.");
y++;
}
f = hasflag(o->flags, F_TRIPATTACK);
if (f) {
mvwprintw(mainwin, y, 0, "A skilled weilder can trip opponents with it.");
y++;
}
}
// damage
if (isarmour(o)) {
f = hasflag(o->flags, F_GOESON);
if (f) {
mvwprintw(mainwin, y, 0, "It is worn %s your %s.",getbodypartequipname(f->val[0]), getbodypartname(f->val[0]));
y++;
}
f = hasflag(o->flags, F_ARMOURRATING);
if (f) {
mvwprintw(mainwin, y, 0, "It has an Armour Rating of %d.",f->val[0] + getobbonus(o));
y++;
}
}
if (o->type->obclass->id == OC_WAND) {
if (isidentified(o)) {
int charges;
charges = getcharges(o);
if (charges) {
mvwprintw(mainwin, y, 0, "It has %d charges left.",charges);
} else {
mvwprintw(mainwin, y, 0, "It has no charges left.");
}
y++;
}
}
f = hasflag(o->flags, F_THROWMISSILE);
if (f) {
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
int dam;
dam = getthrowdam(o);
mvwprintw(mainwin, y, 0, "%s good for throwing [base damage %d].",(o->amt == 1) ? "It is" : "They are", dam);
} else {
mvwprintw(mainwin, y, 0, "%s good for throwing.", (o->amt == 1) ? "It is" : "They are");
}
y++;
}
f = hasflag(o->flags, F_ARMOURPIERCE);
if (f && f->known) {
mvwprintw(mainwin, y, 0, "Armour will not reduce %s damage.",(o->amt == 1) ? "its" : "their");
y++;
}
f = hasflag(o->flags, F_PICKLOCKS);
if (f) {
mvwprintw(mainwin, y, 0, "You can use it to pick locks.");
y++;
}
f = hasflag(o->flags, F_SCARY);
if (f) {
mvwprintw(mainwin, y, 0, "It may unnerve others when worn.");
y++;
}
// immunities
for (i = 0; i < MAXDAMTYPE; i++) {
if (isimmuneto(o->flags, i)) {
mvwprintw(mainwin, y, 0, "It is immune to %s.",getdamnamenoun(i));
y++;
}
if (isresistantto(o->flags, i)) {
mvwprintw(mainwin, y, 0, "It is resistant to %s.",getdamnamenoun(i));
y++;
}
if (isvulnto(o->flags, i)) {
mvwprintw(mainwin, y, 0, "It is vulnerable to %s.",getdamnamenoun(i));
y++;
}
}
// been made invulnerable ?
if (hasflag(o->type->flags, F_DAMAGABLE) && !hasflag(o->flags, F_DAMAGABLE)) {
mvwprintw(mainwin, y, 0, "It has been rendered invulnerable to most damage.");
y++;
}
for (f = o->flags->first ; f ; f = f->next) {
if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
mvwprintw(mainwin, y, 0, "It has been coated with poison.");
y++;
}
}
// now special flags...
y++;
f = hasflag(o->flags, F_MASTERWORK);
if (f && f->known) {
mvwprintw(mainwin, y, 0, "It is extremely well crafted.");
y++;
}
f = hasflag(o->flags, F_SHODDY);
if (f && f->known) {
mvwprintw(mainwin, y, 0, "It is very poorly crafted.");
y++;
}
f = hasflag(o->flags, F_ONFIRE);
if (f) {
mvwprintw(mainwin, y, 0, "It is on fire.");
y++;
}
if (obproduceslight(o)) {
mvwprintw(mainwin, y, 0, "It is producing light.");
y++;
}
f = hasflag(o->flags, F_WET);
if (f) {
mvwprintw(mainwin, y, 0, "It is wet.");
y++;
}
f = hasflag(o->flags, F_RUSTED);
if (f) {
mvwprintw(mainwin, y, 0, "It is rusty.");
y++;
}
f = hasflag(o->flags, F_ACTIVATED);
if (f) {
mvwprintw(mainwin, y, 0, "It is activated.");
y++;
}
// if known, show what it confers
for (f = o->flags->first ; f ; f = f->next) {
if ((f->id == F_HOLDCONFER) || (f->id == F_EQUIPCONFER) || (f->id == F_ACTIVATECONFER)) {
if (obknown) {
objecttype_t *ot;
if (f->id == F_HOLDCONFER) strcpy(buf, "When held, it");
else if (f->id == F_ACTIVATECONFER) strcpy(buf, "When activated, it");
else if (f->id == F_HITCONFER) strcpy(buf, "When hit by it, it");
else strcpy(buf, "When equipped, it");
// conferred intrinsics
switch (f->val[0]) {
int amt;
case F_SHIELDPENALTY:
amt = adjustshieldpenalty(player, f->val[1]);
mvwprintw(mainwin, y, 0, "%s lowers your attack accuracy by %d%%.", buf, amt); y++;
break;
case F_ATTRMOD:
mvwprintw(mainwin, y, 0, "%s %s your %s.", buf, (f->val[2] > 0) ? "increases" : "decreases", getattrname(f->val[1])); y++;
break;
case F_ATTRSET:
mvwprintw(mainwin, y, 0, "%s modifies your %s.", buf, getattrname(f->val[1])); y++;
break;
case F_BLIND:
mvwprintw(mainwin, y, 0, "%s prevents you from seeing.", buf); y++;
break;
case F_CONTROL:
mvwprintw(mainwin, y, 0, "%s lets you control teleportation and polymorphic effects.", buf); y++;
break;
case F_DETECTLIFE:
mvwprintw(mainwin, y, 0, "%s will detect nearby lifeforms.", buf); y++;
break;
case F_DETECTOBS:
mvwprintw(mainwin, y, 0, "%s will detect nearby objects.", buf); y++;
break;
case F_DETECTMAGIC:
mvwprintw(mainwin, y, 0, "%s will detect magical enchantments on objects.", buf); y++;
break;
case F_DETECTMETAL:
mvwprintw(mainwin, y, 0, "%s will detect nearby metal.", buf); y++;
break;
case F_ENHANCESEARCH:
mvwprintw(mainwin, y, 0, "%s enhances your searching ability.", buf); y++;
break;
case F_DRUNK:
mvwprintw(mainwin, y, 0, "%s makes you tipsy.", buf); y++;
break;
case F_EXTRAINFO:
mvwprintw(mainwin, y, 0, "%s provides enhanced knowledge to you.", buf); y++;
break;
case F_EXTRADAM:
mvwprintw(mainwin, y, 0, "%s will cause you to deal more damage.", buf); y++;
break;
case F_EXTRALUCK:
mvwprintw(mainwin, y, 0, "%s will give you a bonus to all skill checks.", buf); y++;
break;
case F_EXTRAMP:
mvwprintw(mainwin, y, 0, "%s will increase your mana pool by %d%%.", buf, f->val[0]); y++;
break;
case F_FASTACT:
mvwprintw(mainwin, y, 0, "%s will speed up your actions.", buf); y++;
break;
case F_FASTMOVE:
mvwprintw(mainwin, y, 0, "%s will speed up your movement.", buf); y++;
break;
case F_FLYING:
mvwprintw(mainwin, y, 0, "%s will allow you to fly.", buf); y++;
break;
case F_FREEZINGTOUCH:
mvwprintw(mainwin, y, 0, "%s will cause objects you touch to turn to ice.", buf); y++;
break;
case F_FROZEN:
mvwprintw(mainwin, y, 0, "%s turns you to ice.", buf); y++;
break;
case F_GRAVBOOSTED:
mvwprintw(mainwin, y, 0, "%s increases gravity around you.", buf); y++;
break;
case F_DODGES:
mvwprintw(mainwin, y, 0, "%s allows you to dodge attacks.", buf); y++;
break;
case F_INVISIBLE:
mvwprintw(mainwin, y, 0, "%s renders you invisible to normal sight.", buf); y++;
break;
case F_INVULNERABLE:
mvwprintw(mainwin, y, 0, "%s protects you from all physical harm.", buf); y++;
break;
case F_CANWILL:
ot = findot(f->val[1]);
if (ot) {
strcpy(buf2, ot->name);
capitalise(buf2);
mvwprintw(mainwin, y, 0, "%s allows you to cast '%s' at will.", buf, buf2); y++;
}
break;
case F_CANCAST:
ot = findot(f->val[1]);
if (ot) {
strcpy(buf2, ot->name);
capitalise(buf2);
mvwprintw(mainwin, y, 0, "%s allows you to cast '%s'.", buf, buf2); y++;
}
break;
case F_DETECTAURAS:
mvwprintw(mainwin, y, 0, "%s allows you to detect blessings or curses.", buf); y++;
break;
case F_LEVITATING:
mvwprintw(mainwin, y, 0, "%s causes you to levitate.", buf); y++;
break;
case F_MAGSHIELD:
mvwprintw(mainwin, y, 0, "%s surrounds you with a magnetic shield.", buf); y++;
break;
case F_NAUSEATED:
mvwprintw(mainwin, y, 0, "%s causes you to feel nauseated.", buf); y++;
break;
case F_NONCORPOREAL:
mvwprintw(mainwin, y, 0, "%s makes you non-corporeal.", buf); y++;
break;
case F_PAIN:
mvwprintw(mainwin, y, 0, "%s causes you intense pain.", buf); y++;
break;
case F_PARALYZED:
mvwprintw(mainwin, y, 0, "%s paralyzes you.", buf); y++;
break;
case F_PHOTOMEM:
mvwprintw(mainwin, y, 0, "%s prevents you from forgetting your surroundings.", buf); y++;
break;
case F_STABILITY:
mvwprintw(mainwin, y, 0, "%s prevents you from slipping over.", buf); y++;
break;
case F_STENCH:
mvwprintw(mainwin, y, 0, "%s makes you smell bad.", buf); y++;
break;
case F_PRODUCESLIGHT:
mvwprintw(mainwin, y, 0, "%s produces light.", buf); y++;
break;
case F_REGENERATES:
if (f->val[1] == 1) {
strcpy(buf2, "");
} else if (f->val[1] == 2) {
strcpy(buf2, "quickly");
} else if (f->val[1] == 3) {
strcpy(buf2, "very quickly");
} else { // >= 4
strcpy(buf2, "extremely quickly");
}
mvwprintw(mainwin, y, 0, "%s allows you to regenerate health%s.", buf,buf2); y++;
break;
case F_RESISTMAG:
mvwprintw(mainwin, y, 0, "%s grants you %s immunity to magic.", buf,
(f->val[0] >= 10) ? "strong" : "minor"); y++;
break;
case F_RISEASGHOST:
mvwprintw(mainwin, y, 0, "%s cause you to rise as a ghost after death.", buf); y++;
break;
case F_SEEINVIS:
mvwprintw(mainwin, y, 0, "%s allows you to see invisible things.", buf); y++;
break;
case F_SEEINDARK:
mvwprintw(mainwin, y, 0, "%s allows you to see in the dark.", buf); y++;
break;
case F_SLOWACT:
mvwprintw(mainwin, y, 0, "%s will slow down your actions.", buf); y++;
break;
case F_SLOWMOVE:
mvwprintw(mainwin, y, 0, "%s will slow down your movement.", buf); y++;
break;
case F_TREMORSENSE:
mvwprintw(mainwin, y, 0, "%s allows you to 'see' by sensing vibrations around you.", buf); y++;
break;
case F_WINDSHIELD:
mvwprintw(mainwin, y, 0, "%s will surround you with a cyclonic shield.", buf); y++;
break;
case F_TIRED:
mvwprintw(mainwin, y, 0, "%s make you tired.", buf); y++;
break;
case F_VISRANGEMOD:
mvwprintw(mainwin, y, 0, "%s %s your vision range.", buf, (f->val[1] > 0) ? "increases" : "descreases"); y++;
break;
case F_XRAYVIS:
mvwprintw(mainwin, y, 0, "%s allows you to see through walls.", buf); y++;
break;
}
}
}
}
// show special properties where known
f = hasflag(o->flags, F_BALANCE);
if (f && f->known) {
mvwprintw(mainwin, y, 0, "It heals weaker enemies, and does extra damage to stronger ones.");
y++;
}
f = hasflag(o->flags, F_FLAMESTRIKE);
if (f && f->known) {
mvwprintw(mainwin, y, 0, "It ignites fires wherever it hits.");
y++;
}
f = hasflag(o->flags, F_HEAVYBLOW);
if (f && f->known) {
mvwprintw(mainwin, y, 0, "Its powerful blows knock enemies backwards.");
y++;
}
f = hasflag(o->flags, F_REVENGE);
if (f && f->known) {
mvwprintw(mainwin, y, 0, "It does more damage as your HP are lowered.");
y++;
}
y++;
// skill type?
f = hasflag(o->flags, F_USESSKILL);
if (f) {
mvwprintw(mainwin, y, 0, "It falls into the '%s' category (your skill: %s).",getskillname(f->val[0]),
getskilllevelname(getskill(player, f->val[0])) );
y++;
}
if (hasflag(o->flags, F_NOBLESS)) {
mvwprintw(mainwin, y, 0, "%s cannot be blessed or cursed.", (o->amt == 1) ? "It" : "They" );
y++;
} else {
if (isblessknown(o)) {
if (o->blessed == B_BLESSED) {
mvwprintw(mainwin, y, 0, "%s a blessing bestowed upon %s.",
(o->amt == 1) ? "It has" : "They have",
(o->amt == 1) ? "it" : "them");
y++;
} else if (o->blessed == B_CURSED) {
mvwprintw(mainwin, y, 0, "%s cursed.",
(o->amt == 1) ? "It is" : "They are");
y++;
}
} else {
mvwprintw(mainwin, y, 0, "%s might be blessed or cursed.",
(o->amt == 1) ? "It" : "They");
y++;
}
}
wrefresh(mainwin);
// wait for key
getch();
real_clearmsg(B_TRUE);
drawscreen();
}
void describespell(objecttype_t *ot) {
char buf[BUFLEN];
int y;
flag_t *f;
int i;
int power;
cls();
// title
sprintf(buf, "%s",ot->name);
capitalise(buf);
mvwprintw(mainwin, 0, 0, buf);
sprintf(buf, "%s",ot->desc);
mvwprintw(mainwin, 2, 0, buf);
// properties
y = 5;
f = hasflag(ot->flags, F_SPELLLEVEL);
if (f) {
flag_t *sf;
sf = hasflag(ot->flags, F_SPELLSCHOOL);
assert(sf);
mvwprintw(mainwin, y, 0, "It is a level %d %s spell.",f->val[0], getschoolname(sf->val[0]));
y++;
}
i = getmpcost(NULL, ot->id);
if (i > 0) {
if (hasflag(ot->flags, F_ONGOING)) {
mvwprintw(mainwin, y, 0, "It takes %d MP to keep active - this is an ongoing cost.",i);
} else {
mvwprintw(mainwin, y, 0, "It costs %d MP to cast.",i);
}
y++;
}
y++;
power = getspellpower(player, ot->id);
mvwprintw(mainwin, y, 0, "You can cast it at power level %d (maximum %d).",power, getspellmaxpower(ot->id));
y++;
wrefresh(mainwin);
// wait for key
getch();
real_clearmsg(B_TRUE);
drawscreen();
}
void doattackcell(char dirch) {
int dir;
flag_t *f;
cell_t *c;
if (dirch == '\0') {
dirch = askchar("Attack in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE);
}
if (dirch == '.') {
// yourself!
c = player->cell;
} else {
dir = chartodir(dirch);
if (dir == D_NONE) {
clearmsg();
return;
} else {
c = getcellindir(player->cell, dir);
}
}
if (c) {
// update last cmd
f = hasflag(player->flags, F_LASTCMD);
if (f) {
f->val[2] = dirch;
}
if (attackcell(player, c)) {
// failed
msg("There is nothing there to attack!");
}
}
}
void doclose(void) {
char ch;
int failed = B_TRUE; // default is to fail
int dir;
int adjdoors;
int forcedir;
// how many doors are nearby?
adjdoors = 0;
for (dir = DC_N; dir <= DC_NW; dir++) {
cell_t *c;
c = getcellindir(player->cell, dir);
if (c) {
object_t *door;
door = hasobwithflag(c->obpile, F_DOOR);
if (door) {
int open;
isdoor(door, &open);
if (open) {
forcedir = dir;
adjdoors++;
}
}
}
}
if (adjdoors == 0) {
msg("There are no open doors nearby!");
return;
} else if (adjdoors == 1) {
dir = forcedir;
} else {
ch = askchar("Close door in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
dir = chartodir(ch);
}
if (dir == D_NONE) {
clearmsg();
return;
} else {
cell_t *c;
c = getcellindir(player->cell, dir);
if (c) {
failed = closedoorat(player, c);
}
}
}
void docomms(void) {
lifeform_t *lf = NULL;
cell_t *where;
char buf[BUFLEN];
char lfname[BUFLEN];
char ch;
where = askcoords("Talk to who?", TT_MONSTER);
if (where && where->lf && cansee(player, where->lf)) {
lf = where->lf;
}
if (!lf) {
msg("Cancelled.");
return;
}
getlfname(lf, lfname);
sprintf(buf, "What will you say to %s?",lfname);
initprompt(&prompt, buf);
prompt.maycancel = B_TRUE;
// are they friendly?
if (ispetof(lf, player)) {
addchoice(&prompt, 'a', "Attack something", NULL, NULL);
if (!isadjacent(lf->cell, player->cell)) {
addchoice(&prompt, 'c', "Come here", NULL, NULL);
}
if (isadjacent(lf->cell, player->cell) && !lfhasflag(lf, F_NOPACK)) {
addchoice(&prompt, 't', "Trade items with me", NULL, NULL);
}
if (lfhasflag(lf, F_RESTING)) {
addchoice(&prompt, 'r', "Stop resting.", NULL, NULL);
} else {
addchoice(&prompt, 'r', "Rest until you are healed.", NULL, NULL);
}
} else {
addchoice(&prompt, 'y', "Yeeeeeaaaargh!", NULL, NULL);
}
addchoice(&prompt, 'n', "(nothing)", NULL, NULL);
ch = getchoice(&prompt);
switch (ch) {
cell_t *c;
lifeform_t *lf2 = NULL;
char lfname2[BUFLEN];
case 'a':
sprintf(buf, "Tell %s to attack who?",lfname);
c = askcoords(buf, TT_MONSTER);
if (c && c->lf && cansee(player, c->lf)) {
lf2 = c->lf;
}
if (!lf2) {
msg("Cancelled.");
return;
}
getlfname(lf2, lfname2);
msg("You say \"Attack %s!\" to %s.",isplayer(lf2) ? "me" : lfname2, lfname);
if (isplayer(lf)) {
msg("%s looks confused at your command.", lfname);
} else {
aiattack(lf, lf2, AI_FOLLOWTIME);
}
break;
case 'c':
msg("You say \"Come here!\" to %s.",lfname);
// find adjacent cell
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) {
aigoto(lf, c, AI_FOLLOWTIME);
}
break;
case 'n':
msg("Cancelled.");
return;
case 'r':
if (lfhasflag(lf, F_RESTING)) {
stopresting(lf);
} else {
if (needstorest(lf, NULL)) {
if (safetorest(lf)) {
addflag(lf->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
startresting(lf, B_FALSE);
} else {
msg("%s is too nervous to rest (perhaps there are monsters nearby).", lfname);
}
} else {
msg("%s doesn't need to rest at the moment.", lfname);
}
}
return;
case 't':
// ask whtehr to give/take
initprompt(&prompt, "How will you trade?");
sprintf(buf, "Give items to %s",lfname);
addchoice(&prompt, 'i', buf, NULL, NULL);
sprintf(buf, "Take items from %s",lfname);
addchoice(&prompt, 'o', buf, NULL, NULL);
sprintf(buf, "Both");
addchoice(&prompt, 'b', buf, NULL, NULL);
sprintf(buf, "Neither");
addchoice(&prompt, 'n', buf, NULL, NULL);
ch = getchoice(&prompt);
switch (ch) {
case 'i':
dodrop(player->pack, B_MULTIPLE, lf->pack);
break;
case 'o':
dopickup(lf->pack);
break;
case 'b':
dodrop(player->pack, B_MULTIPLE, lf->pack);
dopickup(lf->pack);
break;
case 'n':
msg("Cancelled.");
return;
}
break;
case 'y':
msg("You shout at %s!", lfname);
noise(where, player, "someone shouting!", NULL);
break;
}
taketime(player, getactspeed(player));
}
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst) {
object_t *o;
char buf[BUFLEN];
int count = ALL;
int i;
lifeform_t *tolf = NULL;
char lfname[BUFLEN];
// where is destination?
if (dst->owner) {
tolf = dst->owner;
getlfname(tolf, lfname);
} else {
// on ground
}
if (tolf) {
sprintf(buf, "Give what to %s",lfname);
} else {
strcpy(buf, "Drop what");
}
if (wantmulti) {
askobjectmulti(op, buf, AO_NONE);
} else {
o = askobject(op, buf, &count, AO_NONE);
if (o) {
retobs[0] = o;
retobscount[0] = count;
nretobs = 1;
} else {
nretobs = 0;
}
}
if (nretobs <= 0) {
return;
}
for (i = 0; i < nretobs; i++) {
flag_t *f;
//pickup(player, retobs[i],retobscount[i]);
o = retobs[i];
count = retobscount[i];
getobname(o, buf, count);
f = hasflag(o->flags, F_EQUIPPED);
if (f) {
if (f->val[0] == BP_WEAPON) {
// first try to unweild it
if (unweild(player, o)) {
if (nretobs > 1) {
if (tolf) {
msg("Not giving %s to %s.",buf, lfname); more();
} else {
msg("Not dropping %s.",buf); more();
}
}
continue;
}
} else { // armour
int ch;
char buf2[BUFLEN];
// take it off first - this takes time.
sprintf(buf2, "Remove %s",buf);
ch = askchar(buf2, "yn","y", B_TRUE);
if (ch == 'y') {
if (takeoff(player, o)) {
// failed to take it off - can't drop it.
if (nretobs > 1) {
if (tolf) {
msg("Not giving %s to %s.",buf, lfname); more();
} else {
msg("Not dropping %s.",buf); more();
}
}
continue;
}
} else {
if (nretobs > 1) {
if (tolf) {
msg("Not giving %s to %s.",buf, lfname); more();
} else {
msg("Not dropping %s.",buf); more();
}
}
continue;
}
}
}
if (count == ALL) count = o->amt;
if (tolf) {
o = moveob(o, dst, count);
if (o) {
getobname(o, buf, o->amt);
msg("%s takes %s from you.",lfname, buf);
} else {
msg("%s can't carry that.",lfname);
}
} else {
drop(o, count);
}
}
}
void doeat(obpile_t *op) {
object_t *o;
char ch;
char buf[BUFLEN];
char obname[BUFLEN];
// stuffed?
if (gethungerlevel(gethungerval(player)) <= H_STUFFED) {
msg("You couldn't eat another bite!");
return;
}
// edible objects here?
for (o = player->cell->obpile->first; o ; o = o->next) {
if (isedible(o)) {
getobname(o, obname, o->amt);
sprintf(buf, "There %s %s here. Eat %s",
(o->amt == 1) ? "is" : "are",
obname,
(o->amt == 1) ? "it" : "one");
ch = askchar(buf, "yn","n", B_TRUE);
if (ch == 'y') {
eat(player, o);
return;
}
}
}
if (!hasedibleob(player->pack)) {
msg("You have nothing to eat!");
return;
}
o = askobject(op, "Eat what", NULL, AO_EDIBLE);
if (o) {
eat(player, o);
}
}
void dovendingmachine(lifeform_t *lf, object_t *vm) {
int y;
flag_t *f;
//int i;
int done;
char ch;
char choices[BUFLEN];
char buf[BUFLEN];
char buf2[BUFLEN];
char toptext[BUFLEN];
obpile_t *op;
strcpy(toptext, "");
op = addobpile(NULL, NULL);
// populate machine with items
strcpy(choices, "");
for (f = vm->flags->first ; f ; f = f->next) {
if (f->id == F_CONTAINSOB) {
object_t *o;
ch = f->val[0];
if (strlen(f->text)) {
o = addobject(op, f->text, B_FALSE); // no stacking!
// remember letter
o->letter = ch;
// make object fully known
addflag(o->flags, F_SHOPITEM, B_TRUE, NA, NA, NULL);
}
}
}
// list objects for sale and ask for input
done = B_FALSE;
while (!done) {
cls();
mvwprintw(mainwin, 0, 0, toptext);
y = 2;
centre(mainwin, y, "VENDING MACINE");
y += 2;
// list objects for sale
strcpy(choices, "");
for (f = vm->flags->first ; f ; f = f->next) {
if (f->id == F_CONTAINSOB) {
char temp[2];
char obname[BUFLEN];
object_t *o;
ch = f->val[0];
sprintf(temp, "%c",ch);
if (strlen(f->text)) {
// add this as a valid choice
strcat(choices, temp);
// construct string
o = hasobletter(op, ch);
// get the name of the object
getobname(o, obname, o->amt);
sprintf(buf, "%c - %s", ch, obname);
sprintf(buf2, "%-60s$%d",buf,getobvalue(o));
mvwprintw(mainwin, y, 0, "%s", buf2);
y++;
} else {
// construct string
sprintf(buf, " %s", SOLDOUTSTRING);
sprintf(buf2, "%-60s",buf);
mvwprintw(mainwin, y, 0, "%s", buf2);
y++;
}
}
}
y++;
mvwprintw(mainwin, y, 0, "You have $%d.", countmoney(player));
y++;
y++;
// ask what to do
mvwprintw(mainwin, y, 0, "What will you buy (ESC to exit)? ");
ch = getch();
if (ch == 27) {
done = B_TRUE;
} else {
object_t *o;
// try to find that object...
o = hasobletter(op, ch);
if (o) {
// do you have enough money?
if (countmoney(player) >= getobvalue(o)) {
object_t *gold;
// if so, buy it
// lose money (do this first to avoid potential weight issues)
gold = hasob(player->pack, OT_GOLD);
if (gold) {
char obname[BUFLEN];
char answer;
// confirm
getobname(o, obname, o->amt);
sprintf(buf, "Buy %s for $%d?",obname, getobvalue(o));
answer = askchar(buf, "yn","n", B_TRUE);
if (answer == 'y') {
gold->amt -= getobvalue(o);
// clear o->letter
o->letter = '\0';
// give object
o = moveob(o, player->pack, ALL);
getobname(o, obname, o->amt);
sprintf(toptext, "Purchased: %c - %s", o->letter, obname);
// set F_CONTAINSOB text to "" - ie. sold out
for (f = vm->flags->first ; f ; f = f->next) {
if (f->val[0] == ch) {
strcpy(f->text, "");
}
}
} else {
// cancelled
strcpy(toptext, "");
}
} else {
// error
sprintf(toptext,"You don't seem to have any gold...");
}
} else {
sprintf(toptext, "You cannot afford that!");
}
} else {
sprintf(toptext, "That item is sold out!");
} // end if o
} // end if ch
} // end while not done
// free mem
while (op->first) {
killob(op->first);
}
killobpile(op);
drawscreen();
real_clearmsg(B_TRUE);
}
int dowear(obpile_t *op) {
object_t *o;
int rv;
o = askobject(op, "Wear what", NULL, AO_WEARABLE);
if (o) {
wear(player, o);
} else {
msg("Cancelled.");
rv = B_TRUE;
}
return rv;
}
int doweild(obpile_t *op) {
object_t *o;
int count = ALL;
int rv;
o = askobject(op, "Weild what", &count, AO_WEILDABLE | AO_INCLUDENOTHING);
if (o) {
rv = weild(player, o);
} else if (reason == E_SELNOTHING) {
// ie. unweild
rv = weild(player, NULL);
} else {
rv = B_TRUE;
}
return rv;
}
void doknowledgelist(void) {
knowledge_t *k;
int y = 0;
int numfound = 0;
int c;
cls();
mvwprintw(mainwin, 0, 0, "Current Knowledge");
y = 2;
for (c = 0; sortorder[c] != OC_NULL ; c++) {
int first = B_TRUE;
for (k = knowledge ; k ; k = k->next) {
if (k->known) {
objecttype_t *ot;
ot = findot(k->id);
if (ot->obclass->id == c) {
if (first) {
mvwprintw(mainwin, y, 0, "%s", ot->obclass->name);
y++;
first = B_FALSE;
}
mvwprintw(mainwin, y, 0, " %-25s (%s)",ot->name, k->hiddenname);
y++;
numfound++;
if (y >= (SCREENH-3)) {
mvwprintw(mainwin, (SCREENH-2), 0, MORESTRING);
wrefresh(mainwin);
getch();
cls();
mvwprintw(mainwin, 0, 0, "Current Knowledge");
y = 2;
}
}
}
}
}
if (numfound == 0) {
mvwprintw(mainwin, y, 0, "You don't know much.");
}
wrefresh(mainwin);
getch();
clearmsg();
drawscreen();
}
void dolook(cell_t *where) {
int numobs;
char buf[BUFLEN];
char seeverb[BUFLEN];
int seensomething = B_FALSE;
//if (isblind(player)) {
if (!haslos(player, player->cell)) {
strcpy(seeverb, "feel");
} else {
strcpy(seeverb, "see");
}
numobs = countobs(where->obpile);
if (numobs > 0) {
if (numobs == 1) {
getobname(where->obpile->first, buf, where->obpile->first->amt);
msg("You %s %s here.", seeverb, buf);
} else if ((numobs > 1) && (numobs <= 3)) {
msg("You %s a few objects here.", seeverb);
} else if ((numobs > 3) && (numobs <= 6)) {
msg("You %s some objects here.", seeverb);
} else if (numobs > 6) {
msg("You %s many objects here.", seeverb);
}
seensomething = B_TRUE;
}
// writing here?
if (where->writing && !isblind(player)) {
msg("There is a magical inscription here:");
msg("\"%s\"", where->writing);
seensomething = B_TRUE;
}
if (!seensomething) {
// just clear the message buffer
//clearmsg();
if (isblind(player)) {
msg("There does not seem to be anything here.");
} else {
msg("There is nothing here.");
}
}
}
// if wantunknown is set, lsit spells we DONT know.
// otherwise list spells we DO know.
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown) {
char ch;
flag_t *f;
char buf[BUFLEN];
char buf2[BUFLEN];
char costbuf[BUFLEN];
enum OBTYPE poss[MAXCANDIDATES];
int mpcost[MAXCANDIDATES];
char mpdesc[MAXCANDIDATES][BUFLEN];
int validspell[MAXCANDIDATES];
int deactspell[MAXCANDIDATES];
int nposs = 0;
int i,n;
enum SPELLSCHOOL lastschool;
objecttype_t *ot;
nposs = 0;
for (i = SS_NONE+1; i < SS_LAST; i++) {
// school doesn't match the one we're asking for?
if ((wantschool != SS_NONE) && (i != wantschool)) {
continue;
}
// we can't cast spells from this school?
if (getschoolskill(i) != SK_NONE) {
if (!getskill(lf, getschoolskill(i))) {
continue;
}
}
// get list of spells/abilities we can cast at will
for (ot = objecttype ; ot ; ot = ot->next) {
if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) {
f = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (!wantunknown && f) {
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) {
poss[nposs] = ot->id;
deactspell[nposs] = B_FALSE; // default
mpcost[nposs] = -1;
if (f->val[2] == NA) {
sprintf(mpdesc[nposs], "(ready)");
validspell[nposs] = B_TRUE;
} else {
if (f->val[1] == f->val[2]) {
sprintf(mpdesc[nposs], "(ready)");
validspell[nposs] = B_TRUE;
} else {
sprintf(mpdesc[nposs], "(%d/%d)",f->val[1],f->val[2]);
validspell[nposs] = B_FALSE;
}
}
nposs++;
}
}
}
}
if (!lfhasflag(lf, F_NOSPELLS)) {
// get list of spells we can cast using mp
for (ot = objecttype ; ot ; ot = ot->next) {
if (ot->obclass->id == OC_SPELL) { // is it a spell?
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) { // from the current school?
// not using 'cancast' here because we want to list spells
// even if we don't have enough mp
f = lfhasflagval(lf, F_CANCAST, ot->id, NA, NA, NULL);
if ((f && !wantunknown) || (!f && wantunknown)) {
int cost;
int found = B_FALSE;
cost = getmpcost(lf, ot->id);
for (n = 0; n < nposs; n++) {
if (poss[n] == ot->id) {
found = B_TRUE;
break;
}
}
if (!found) {
int power;
// add to list
poss[nposs] = ot->id;
mpcost[nposs] = cost;
deactspell[nposs] = B_FALSE; // default
power = getspellpower(lf, ot->id);
if (power > 0) {
if (hasactivespell(lf, ot->id)) {
cost = 0;
mpcost[nposs] = 0;
strcpy(mpdesc[nposs], "(Deactivate, at will)");
deactspell[nposs] = B_TRUE;
} else {
getspellcosttext(lf, ot->id, power, mpdesc[nposs]);
}
if (lf->mp >= mpcost[nposs]) {
validspell[nposs] = B_TRUE;
} else {
validspell[nposs] = B_FALSE;
}
} else {
sprintf(mpdesc[nposs], "(too hard)");
validspell[nposs] = B_FALSE;
}
nposs++;
}
}
}
}
}
}
} // end foreach spell school
if (lfhasflag(lf, F_NOSPELLS) && (nposs == 0)) {
msg("%ss cannot use magic!", lf->race->name);
return;
}
// list player's magic...
ch = 'a';
initprompt(pr, ques);
prompt.maycancel = B_TRUE;
addpromptq(pr, ques2);
lastschool = SS_LAST;
for (i = 0; i < nposs; i++) {
int power;
ot = findot(poss[i]);
assert(ot);
power = getspellpower(lf, poss[i]);
// heading
f = hasflag(ot->flags, F_SPELLSCHOOL);
assert(f);
if (f->val[0] != lastschool) {
lastschool = f->val[0];
addheading(pr, getschoolname(lastschool));
}
getspellname(ot->id, player, buf2);
if (deactspell[i]) {
strcat(buf2, "/deact");
}
if (validspell[i]) {
strcpy(costbuf, "");
} else {
strcpy(costbuf, "(NOT CASTABLE) ");
}
strcat(costbuf, mpdesc[i]);
sprintf(buf, "%-30s%s", buf2, costbuf);
// we don't want spell letters to change
// every time you get a new spell, so the
// choice letter always comes from spell letter
/*
f = hasflag(ot->flags, F_SPELLLETTER);
assert(f);
*/
// letter doesn't matter
addchoice(pr, 'a', buf2, buf, ot);
}
}
void domagic(enum OBTYPE spellid, int cellx, int celly) {
flag_t *f;
objecttype_t *ot;
int finished;
// init the prompt if required.
if (spellid == OT_NONE) {
makespellchoicelist(&prompt, player, "Use which spell/ability:","Describe which spell/ability:", SS_NONE, B_FALSE);
}
finished = B_FALSE;
while (!finished) {
// ask for spell if required
if (spellid == OT_NONE) {
if (prompt.nchoices > 0) {
getchoicestr(&prompt, B_TRUE, B_FALSE);
ot = prompt.result;
if (ot) {
spellid = ot->id;
}
} else {
msg("You don't have any spells or abilities!");
return;
}
} // end if spellid == NONE
// if still no spell, finish.
if (spellid == OT_NONE) {
clearmsg();
msg("Cancelled.");
return;
} else { // otherwise either cast the spell or describe it
cell_t *targcell = NULL;
lifeform_t *targlf = NULL;
if (prompt.whichq == 0) { // cast the spell
// update lastcmd
f = hasflag(player->flags, F_LASTCMD);
if (f) {
f->val[2] = spellid;
}
// try to cast it
ot = findot(spellid);
// specified x/y coords from a repeated cmd?
if (cellx == NA) {
targcell = NULL;
targlf = NULL;
} else {
targcell = getcellat(player->cell->map, cellx, celly);
targlf = haslf(targcell);
}
// should always work...
if (ot->obclass->id == OC_SPELL) {
castspell(player, spellid, targlf, NULL, targcell);
} else {
useability(player, spellid, targlf, targcell);
}
finished = B_TRUE;
} else { // describe it
describespell(ot);
// prompt again!
spellid = OT_NONE;
}
} // end cast/describe test
} // end while not finished
}
void domemmagic(void) {
char ch;
int slot;
objecttype_t *ot;
makespellchoicelist(&prompt, player, "Memorise which spell/ability:","Describe which spell/ability",SS_NONE, B_FALSE);
if (prompt.nchoices <= 0) {
msg("You don't have any spells or abilities!");
return;
}
ch = askchar("Memorise in which slot (1-9)", "1234567890","", B_FALSE);
slot = ch - '0';
getchoicestr(&prompt, B_FALSE, B_FALSE);
ot = (objecttype_t *)prompt.result;
if (ot) {
flag_t *f;
f = lfhasflagval(player, F_SHORTCUT, slot, NA, NA, NULL);
if (f) {
killflag(f);
}
addflag(player->flags, F_SHORTCUT, slot, NA, NA, ot->name);
msg("Shortcut %d set to '%s'",slot,ot->name);
}
}
void domsghist(void) {
int i;
int y;
cls();
mvwprintw(mainwin, 0, 0, "MESSAGE HISTORY:");
y = 1;
for (i = 0; i < nmsghist; i++) {
mvwprintw(mainwin, y, 0, msghist[i]);
y++;
}
wrefresh(mainwin);
getch();
// restore screen
//cls();
drawscreen();
real_clearmsg(B_TRUE);
}
void dooperate(obpile_t *op) {
object_t *o;
// ask which object to read
o = askobject(op, "Operate what", NULL, AO_OPERABLE);
if (o) {
if (isoperable(o)) {
operate(player, o, NULL);
} else {
msg("You can't operate that!");
}
}
}
int dopickup(obpile_t *op) {
int obcount;
//object_t *o = NULL;
int howmany = ALL;
int i;
lifeform_t *fromlf = NULL;
char lfname[BUFLEN];
char buf[BUFLEN];
if (op->owner) {
fromlf = op->owner;
getlfname(fromlf, lfname);
}
obcount = countobs(op);
// anything here?
if (obcount == 0) {
if (fromlf) {
msg("%s is not carrying anything!", lfname);
} else {
msg("There is nothing here to pick up!");
}
return B_TRUE;
} else if (!fromlf && (obcount == 1) && (op->first->amt == 1)) {
// just get it
howmany = ALL;
retobs[0] = op->first;
retobscount[0] = op->first->amt;
nretobs = 1;
} else {
if (fromlf) {
sprintf(buf, "Take what from %s",lfname);
} else {
strcpy(buf, "Pick up what");
}
// prompt which one to pick up
askobjectmulti(op, buf, AO_NONE);
}
if (nretobs <= 0) {
return B_TRUE;
} else if (lfhasflag(player, F_NOPACK)) {
msg("You lack the ability to carry things!");
return B_TRUE;
}
for (i = 0; i < nretobs; i++) {
pickup(player, retobs[i],retobscount[i], B_TRUE);
}
/*
if (o) {
pickup(player, o, howmany);
} else {
return B_TRUE;
}
*/
return B_FALSE;
}
void doenter(lifeform_t *lf) {
object_t *enterob;
if (isplayer(lf)) {
enterob = hasob(lf->cell->obpile, OT_VENDINGMACHINE);
if (enterob) {
dovendingmachine(lf, enterob);
return;
}
enterob = hasob(lf->cell->obpile, OT_PORTAL);
if (enterob) {
usestairs(lf, enterob);
return;
}
// try to go down
dostairs(D_DOWN);
}
}
void doexplain(char *question) {
char buf[BUFLEN];
cell_t *where;
int done = B_FALSE;
while (!done) {
//sprintf(buf, "Select glyph to explain (ESC to cancel):");
where = askcoords(question, TT_NONE);
if (!where) {
clearmsg();
return;
}
// explain it
if (where->lf && cansee(player, where->lf)) {
showlfstats(where->lf, B_FALSE);
} else {
object_t *o;
// object description
o = gettopobject(where);
if (o) {
getobdesc(o, buf);
}
msg("%s", buf);
}
}
msg("Done.");
}
void dofinaloblist(obpile_t *op) {
object_t *o;
o = askobject(op, "Your final possessions were", NULL, AO_NONE);
while (o) {
// describe it
describeob(o);
// ask for another one
o = askobject(op, "Your final possessions were", NULL, AO_NONE);
}
real_clearmsg(B_TRUE);
}
void dofire(void) {
if (shoot(player)) {
// why not?
switch (reason) {
case E_NOTEQUIPPED:
msg("You have no firearm equipped!");
break;
case E_NOTARGET:
msg("You have no target selected!");
break;
case E_NOAMMO:
msg("You are out of ammo!");
break;
default:
msg("You cannot fire for some reason!");
break;
}
}
}
void dohelp(void) {
int h;
int y;
command_t *c;
char *ftext= "%c %s";
h = getmaxy(mainwin);
cls();
centre(mainwin, 0, "COMMAND REFERENCE");
y = 2;
for (c = firstcommand ; c ; c = c->next) {
mvwprintw(mainwin, y, 0, ftext, c->ch, c->desc); y++;
if (y >= (h-2)) {
centre(mainwin, h-1, "[Press any key]");
getch();
cls();
y = 2;
}
}
centre(mainwin, h-1, "[Press any key]");
getch();
drawscreen();
real_clearmsg(B_TRUE);
}
void doinventory(obpile_t *op) {
object_t *o;
char buf[BUFLEN];
float packweight,maxweight,pct;
packweight = getobpileweight(player->pack);
maxweight = getmaxcarryweight(player);
pct = (packweight / maxweight) * 100;
sprintf(buf, "Inventory (%0.0f/%0.0f kg, %0.0f%%)", packweight, maxweight, pct);
o = askobject(op, buf, NULL, AO_NONE);
while (o) {
// describe it
describeob(o);
// ask for another one
o = askobject(op, buf, NULL, AO_NONE);
}
real_clearmsg(B_TRUE);
}
void doquaff(obpile_t *op) {
object_t *o,*liquid = NULL;
// quaffable objects here?
for (o = player->cell->obpile->first; o ; o = o->next) {
if (isdrinkable(o) && canquaff(player, o)) {
char obname[BUFLEN];
char buf[BUFLEN];
char ch;
getobname(o, obname, o->amt);
sprintf(buf, "There %s %s here. Drink %s",
(o->amt == 1) ? "is" : "are",
obname,
(o->amt == 1) ? "it" : "one");
ch = askchar(buf, "yn","n", B_TRUE);
if (ch == 'y') {
liquid = o;
break;
}
}
}
// ask which object to quaff
if (!liquid) {
liquid = askobjectwithflag(op, "Quaff what", NULL, AO_NONE, F_DRINKABLE);
}
if (liquid) {
if (canquaff(player, liquid)) {
quaff(player, liquid);
} else {
switch (reason) {
case E_INSUBSTANTIAL:
msg("You need a physical body to do that!");
break;
case E_WRONGOBTYPE:
default:
msg("You can't drink that!");
break;
}
}
}
}
void dolockpick(obpile_t *op) {
object_t *o;
char ch;
int dir;
if (!hasobwithflag(player->pack, F_PICKLOCKS)) {
msg("You have nothing to use for lockpicking!");
return;
}
// ask direction
ch = askchar("Lockpick in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
dir = chartodir(ch);
if (dir == D_NONE) {
clearmsg();
return;
} else {
cell_t *c;
c = getcellindir(player->cell, dir);
if (c) {
object_t *targ;
// something to lockpick there?
targ = hasobwithflag(c->obpile, F_LOCKED);
if (targ) {
// ask which object to use
o = askobjectwithflag(op, "Lockpick using what", NULL, AO_NONE, F_PICKLOCKS);
if (o) {
if (hasflag(o->flags, F_PICKLOCKS)) {
lockpick(player, targ, o);
} else {
msg("That can't be used to pick locks!");
}
} else {
msg("Cancelled.");
return;
}
} else {
// fail
msg("There is nothing locked there!");
}
} else {
clearmsg();
return;
}
}
}
void donextguntarget(void) {
object_t *gun;
char gunname[BUFLEN];
int i,startpos;
int done;
lifeform_t *targ;
gun = getfirearm(player);
if (!gun) {
msg("You have no firearm equipped!");
return;
}
getobname(gun, gunname, 1);
// get current target
targ = getguntarget(player);
// find current target cell
startpos = 0; // default
for (i = 0; i < player->nlos; i++) {
cell_t *c;
c = player->los[i];
if (c->lf && (c->lf == targ)) {
startpos = i;
break;
}
}
i = startpos;
done = B_FALSE;
while (!done) {
cell_t *c;
c = player->los[i];
if (c->lf && (c->lf != player) && (c->lf != targ)) {
if (haslof(player->cell, c, LOF_NEED, NULL) && isingunrange(player, c)) {
// found one!
setguntarget(player, c->lf);
done = B_TRUE;
}
}
i++;
if (i >= player->nlos) {
i = 0;
}
if (i == startpos) {
// no new targets found - keep current one.
setguntarget(player, targ);
done = B_TRUE;
}
}
}
void dopour(obpile_t *op) {
object_t *o;
// ask which object to read
o = askobject(op, "Pour what", NULL, AO_POURABLE);
if (o) {
if (ispourable(o)) {
pour(player, o);
} else {
msg("That isn't pourable!");
}
}
}
void doquit(void) {
char ch;
ch = askchar("Really quit", "yn","n", B_TRUE);
if (ch == 'y') {
setlastdam(player, "quitting");
player->alive = B_FALSE;
}
}
void doread(obpile_t *op) {
object_t *o;
if (isblind(player)) {
msg("You can't read while blind!");
return;
}
// ask which object to read
o = askobject(op, "Read what", NULL, AO_READABLE);
if (o) {
if (isreadable(o)) {
readsomething(player, o);
} else {
msg("You can't read that!");
}
}
}
void dorest(void) {
// can we rest?
if (safetorest(player)) {
int willtrain = B_FALSE;
if (lfhasflag(player, F_HASNEWLEVEL)) {
int ch;
ch = askchar("Would you like to train your skills?","yn","y", B_TRUE);
if (ch == 'y') {
willtrain = B_TRUE;
}
}
// if not training, only rest if we need to.
if (!willtrain) {
char validchars[BUFLEN];
char ques[BUFLEN];
char ch;
if (needstorest(player, validchars)) {
if (strchr(validchars, 'h') && strchr(validchars, 'm')) {
strcat(validchars, "bn");
strcpy(ques, "Rest until full HP, Mana, Both, or none");
ch = askchar(ques, validchars, "b", B_TRUE);
if (ch == 'b') {
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
} else if (ch == 'h') {
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
} else if (ch == 'm') {
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
}
} else if (strchr(validchars, 'h')) {
strcpy(ques, "Rest until full HP");
ch = askchar(ques, "yn", "y", B_TRUE);
if (ch == 'y') {
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
}
} else if (strchr(validchars, 'm')) {
strcpy(ques, "Rest until full Mana");
ch = askchar(ques, "yn", "y", B_TRUE);
if (ch == 'y') {
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
}
}
} else {
if (countnearbyallies(player)) {
strcpy(ques, "Rest until nearby allies are healed?");
ch = askchar(ques, "yn", "y", B_TRUE);
if (ch == 'y') {
addflag(player->flags, F_RESTUNTILALLIES, B_TRUE, NA, NA, NULL);
}
} else {
msg("You don't need to rest at the moment.");
return;
}
}
if (!lfhasflag(player, F_RESTUNTILHP) &&
!lfhasflag(player, F_RESTUNTILMP) &&
!lfhasflag(player, F_RESTUNTILALLIES)) {
msg("Cancelled.");
return;
}
}
startresting(player, willtrain);
// do the first one right away
rest(player, B_TRUE);
} else {
switch (reason) {
case E_MONSTERNEARBY:
msg("You cannot rest - there are monsters nearby!");
break;
default:
msg("You cannot rest for some reason.");
break;
}
}
}
void doselguntarget(void) {
object_t *gun;
cell_t *where;
char buf[BUFLEN];
char gunname[BUFLEN];
gun = getfirearm(player);
if (!gun) {
msg("You have no firearm equipped!");
return;
}
getobname(gun, gunname, 1);
sprintf(buf, "Aim %s where?",gunname);
where = askcoords(buf, TT_MONSTER);
if (where) {
if (where->lf && haslof(player->cell, where, LOF_NEED, NULL)) {
setguntarget(player, where->lf);
} else {
setguntarget(player, NULL);
}
}
}
void dostairs(int dir) {
object_t *o;
o = hasobwithflagval(player->cell->obpile, F_CLIMBABLE, dir, NA, NA, NULL);
if (o) {
usestairs(player, o);
} else {
msg("There are no stairs going %s here!", getdirname(dir));
}
}
int dotakeoff(obpile_t *op) {
object_t *o;
flag_t *f;
int rv = B_TRUE;
// ask which object to read
o = askobject(op, "Take off what", NULL, AO_EQUIPPEDARMOUR );
if (o) {
if (isarmour(o)) {
f = hasflag(o->flags, F_EQUIPPED);
if (f) {
rv = takeoff(player, o);
} else {
msg("You are not wearing that!");
rv = B_TRUE;
}
} else {
//rv = unweild(player, o);
rv = takeoff(player, o);
}
}
return rv;
}
void dothrow(obpile_t *op) {
object_t *o;
char buf[BUFLEN],buf2[BUFLEN];
if (!hasbp(player, BP_HANDS)) {
msg("You have no hands to throw with!");
return;
}
// ask which object to throw
o = askobject(op, "Throw what", NULL, AO_NONE);
if (o) {
int maxdist;
cell_t *where;
flag_t *f;
getobname(o, buf, 1);
f = hasflag(o->flags, F_EQUIPPED);
if (f && (f->val[0] != BP_WEAPON)) {
msg("You'll need to take it off first.");
return;
}
// calculate throw range
maxdist = getmaxthrowrange(player, o);
// ask where to throw it
sprintf(buf2, "Throw %s where?",buf);
where = askcoords(buf2, TT_MONSTER);
if (where) {
cell_t *newwhere = NULL;
if (!haslof(player->cell, where, LOF_WALLSTOP, &newwhere)) {
if (newwhere) {
// update destination cell.
where = newwhere;
} else {
if (reason == E_NOLOS) {
msg("You can't see there!");
} else { // ie. E_NOLOF
msg("You don't have a clear line of fire to there.");
}
return;
}
}
if (getcelldist(player->cell, where) > maxdist) {
msg("You can't throw %s that far!",buf);
} else {
throwat(player, o, where);
}
}
}
}
/*
void drawscannedcell(cell_t *cell, int x, int y) {
if (cell->lf) {
char glyph;
// draw glyph based on size
switch(getlfsize(cell->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;
}
mvwprintw(gamewin, y, x, "%c", glyph);
}
}
*/
// returns TRUE if escape pressed
int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar) {
char headbuf[BUFLEN];
int ch;
int w;
w = getmaxx(mainwin);
snprintf(headbuf, w-1, "%s (continued)", heading);
(*y)++;
if (*y >= (h-3)) {
centre(mainwin, h-2, MORESTRING);
if (bottomstring) {
centre(mainwin, h-1, bottomstring);
}
ch = getch();
if (cmdchars && strchr(cmdchars, ch)) {
if (retchar) *retchar = ch;
return B_TRUE;
} else if (ch == 27) { // ESC
if (retchar) *retchar = ch;
return B_TRUE;
}
cls(); *y = 0;
centre(mainwin, *y, headbuf);
*y += 2;
wmove(mainwin, *y, 0);
if (subheading) {
doheading(mainwin, y, 0, subheading);
}
}
return B_FALSE;
}
// draw a cell which we remember, but can't see
/*
void drawunviscell(cell_t *cell, int x, int y) {
glyph_t glyph;
object_t *o;
// copy from cell
glyph = cell->type->glyph;
if (glyph.ch == '.') {
glyph.ch = ' ';
}
// show staircases...
o = hasobwithflag(cell->obpile, F_CLIMBABLE);
if (o) {
glyph = *(getglyph(o));
}
// show dungeon features
o = hasobofclass(cell->obpile, OC_DFEATURE);
if (o) {
glyph = *(getglyph(o));
}
//mvwprintw(gamewin, y, x, "%c", glyph);
drawglyph(&glyph, x, y);
}
*/
void drawglyph(glyph_t *g, int x, int y) {
int col;
col = g->colour;
setcol(gamewin, g->colour);
mvwprintw(gamewin, y, x, "%c", g->ch);
unsetcol(gamewin, g->colour);
}
/*
void drawcell(cell_t *cell, int x, int y) {
drawglyph(&cell->type->glyph, x, y);
}
*/
// draw a cell that we have LOS to.
/*
void drawcellwithcontents(cell_t *cell, int x, int y) {
if (cell->lf && cansee(player, cell->lf)) { // lifeform here that we can see
glyph_t *gl;
// draw the lf's race glyph
gl = getlfglyph(cell->lf);
drawglyph(gl, x, y);
return;
} else {
void *thing;
glyph_t glyph;
// scanned lf here?
if (isinscanrange(cell, &thing, NULL, &glyph) == TT_MONSTER) {
//mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph);
drawglyph(&glyph, x, y);
return;
}
}
if ((countobs(cell->obpile) > 0)) {
object_t *o;
// draw highest object in sort order
o = gettopobject(cell);
if (o) {
drawglyph(getglyph(o), x, y);
} else {
// should never happen. if it does, just show the
// first object
dblog("Warn: sorted object glyph drawing matching nothing!");
//mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph);
drawglyph(&cell->obpile->first->type->obclass->glyph, x, y);
}
} else {
// draw cell normally
drawcell(cell, x, y);
}
}
*/
void drawcursor(void) {
// move cursor to player position
wmove(gamewin, player->cell->y - viewy, player->cell->x - viewx);
wrefresh(gamewin);
}
void drawlevelfor(lifeform_t *lf) {
int x,y;
cell_t *cell;
map_t *map;
map = lf->cell->map;
numdraws++;
// turn off cursor
curs_set(0);
// TODO: draw to buffer here...
// buffer is an array of 'glyph_t's
wclear(gamewin);
for (y = viewy; y < viewy + viewh; y++) {
for (x = viewx; x < viewx + vieww; x++) {
cell = getcellat(map, x, y);
if (cell) {
glyph_t glyph,screenglyph;
getcellglyph(&glyph, cell, lf);
//drawglyph(&glyph, x - viewx, y - viewy);
// only draw if screen char/colour is different
screenglyph.ch = mvwinch(gamewin, y - viewy, x - viewx) & A_CHARTEXT;
if (screenglyph.ch != glyph.ch) {
drawglyph(&glyph, x - viewx, y - viewy);
} else {
screenglyph.colour = mvwinch(gamewin, y - viewy, x - viewx) & A_COLOR;
if (screenglyph.colour != glyph.colour) {
drawglyph(&glyph, x - viewx, y - viewy);
}
}
}
}
}
// turn on cursor
curs_set(1);
// move it to the player's position
wmove(gamewin, lf->y - viewy, lf->x - viewx);
}
void doheading(WINDOW *win, int *y, int x, char *what) {
int len;
char *buf;
len = strlen(what) + 1;
buf = malloc(len * sizeof(char));
memset(buf, '-', (size_t)(len-1));
buf[len] = '\0';
mvwprintw(win, *y, x, what); (*y)++;
mvwprintw(win, *y, x, buf); (*y)++;
free(buf);
}
void initgfx(void) {
int msgwinh = 2;
int statwinh = 2;
mainwin = initscr();
// colour setup
if (!has_colors()) {
printf("Terminal does not support colour.\n");
hascolour = B_FALSE;
exit(1);
}
start_color();
init_pair(C_BLACK, COLOR_BLACK, COLOR_BLACK);
init_pair(C_RED, COLOR_RED, COLOR_BLACK);
init_pair(C_GREEN, COLOR_GREEN, COLOR_BLACK);
init_pair(C_BROWN, COLOR_YELLOW, COLOR_BLACK);
init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK);
init_pair(C_BLUE, COLOR_BLUE, COLOR_BLACK);
init_pair(C_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
init_pair(C_CYAN, COLOR_CYAN, COLOR_BLACK);
init_pair(C_GREY, COLOR_WHITE, COLOR_BLACK);
init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK);
init_pair(C_WHITE, COLOR_WHITE, COLOR_BLACK);
init_pair(C_BOLDCYAN, COLOR_CYAN, COLOR_BLACK);
init_pair(C_BOLDBLUE, COLOR_BLUE, COLOR_BLACK);
init_pair(C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_BLACK);
init_pair(C_BOLDGREEN, COLOR_GREEN, COLOR_BLACK);
init_pair(C_ORANGE, COLOR_RED, COLOR_BLACK);
noecho();
cbreak();
nodelay(mainwin, FALSE);
getmaxyx(mainwin, SCREENH, SCREENW);
// determine window sizes
vieww = SCREENW;
//viewh = SCREENH - 4;
//viewh = SCREENH - statwinh - msgwinh - 1;
viewh = SCREENH - statwinh - msgwinh;
// create windows
//msgwin = newwin(1, vieww, 0, 0);
msgwin = newwin(msgwinh, vieww, 0, 0);
gamewin = newwin(viewh, vieww, msgwinh, 0);
//statwin = newwin(statwinh, vieww, msgwinh + viewh + statwinh - 2 ,0);
statwin = newwin(statwinh, vieww, SCREENH - statwinh,0);
statdirty = B_TRUE;
redraw();
refresh();
// init message buffer
strcpy(msgbuf, "");
strcpy(lastmsgbuf, "xxx");
}
int drop(object_t *o, int count) {
object_t *newob;
obpile_t *op;
char obname[BUFLEN];
enum OBTYPE origid;
op = o->pile;
assert(op->owner);
// in case we get burduned
if (isplayer(op->owner)) statdirty = B_TRUE;
getobname(o, obname, count);
origid = o->type->id;
newob = moveob(o, op->owner->cell->obpile, count);
if (newob) { // if drop was successful...
//taketime(op->owner, (SPEED_DROP * count));
taketime(op->owner, SPEED_DROP);
// if object wasn't changed...
if (newob->type->id == origid) {
if (op->owner) {
if (isplayer(op->owner)) {
msg("You drop %s.",obname);
} else if (cansee(player, op->owner)) {
char ownername[BUFLEN];
getlfname(op->owner, ownername);
msg("%s drops %s.",ownername, obname);
}
}
}
} else {
// tell the player why!
if (isplayer(op->owner)) {
switch (reason) {
case E_NOSPACE:
msg("There is no space here for any more objects!");
break;
default:
msg("For some reason, you cannot drop %s!");
break;
}
}
return B_TRUE;
}
return B_FALSE;
}
char getchoice(prompt_t *prompt) {
int i;
int y;
char ch;
int sel;
int gotheadings;
int first= 0;
int nextpage = -1;
int lastline = SCREENH - 4;
gotheadings = B_FALSE;
for (i = 0; i < prompt->nchoices; i++) {
if (prompt->choice[i].heading) {
gotheadings = B_TRUE;
break;
}
}
// loop until result is valid
sel = -1;
while (sel == -1) {
// show choices
cls();
y = 2;
nextpage = -1;
for (i = first; i < prompt->nchoices; i++) {
int atbottom;
atbottom = B_FALSE;
if (y > lastline) { // if we're at the bottom of the screen
atbottom = B_TRUE;
} else if (prompt->choice[i].heading && (y+1 > lastline)) {
// on a heading, and next line is at the bottom
atbottom = B_TRUE;
}
if (atbottom) {
nextpage = i;
mvwprintw(mainwin, y, 0, "--More--");
break;
}
// heading?
if (prompt->choice[i].heading) {
mvwprintw(mainwin, y, 0, "%s", prompt->choice[i].desc);
} else {
mvwprintw(mainwin, y, 0, "%s%c - %s", gotheadings ? " " : "", prompt->choice[i].ch, prompt->choice[i].desc);
}
y++;
}
// display prompt question
mvwprintw(mainwin, 0, 0, "%s %s", prompt->q[prompt->whichq],
prompt->maycancel ? "[ESC to cancel] " : "");
wrefresh(mainwin);
// ask for choice...
ch = getch();
if ((ch == 27) && (prompt->maycancel)) { // ESC - cancel
prompt->result = NULL;
sel = -1;
break;
} else if (ch == ' ') {
if (nextpage == -1) {
first = 0;
} else {
first = nextpage;
}
} else {
sel = -1;
for (i = 0 ; i < prompt->nchoices; i++) {
if (prompt->choice[i].ch == ch) {
sel = i;
break;
}
}
}
}
if (ch != 27) {
// set result pointer
prompt->result = prompt->choice[i].data;
prompt->selection = i;
}
if ((gamemode == GM_GAMESTARTED)) {
drawscreen();
} else {
cls();
wrefresh(mainwin);
}
// return NUL or result char
if (ch == 27) {
return '\0';
}
return prompt->choice[i].ch;
}
char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
int i;
int y;
char ch;
int sel;
int gotheadings;
int first= 0;
int nextpage = -1;
int lastline = SCREENH - 4;
char inpstring[BUFLEN];
char curheading[BUFLEN];
int doneheading;
int nvalid;
char promptstr[BUFLEN];
int showall;
int autochar = 0;
showall = showallatstart;
strcpy(inpstring, "");
// mark valid choices, and determine whether we have
// headings
gotheadings = B_FALSE;
for (i = 0; i < prompt->nchoices; i++) {
if (prompt->choice[i].heading) {
gotheadings = B_TRUE;
prompt->choice[i].valid = B_FALSE;
} else {
prompt->choice[i].valid = B_TRUE;
}
}
strcpy(curheading, "");
doneheading = B_FALSE;
// loop until result is valid
sel = -1;
while (sel == -1) {
int atbottom;
// show choices which match our input string
if (showall) {
cls();
}
y = 2;
nextpage = -1;
nvalid = 0;
atbottom = B_FALSE;
for (i = 0; i < prompt->nchoices; i++) {
if (showall) {
if (!atbottom) {
if (y > lastline) { // if we're at the bottom of the screen
atbottom = B_TRUE;
} else if (prompt->choice[i].heading && (y+1 >= (SCREENH-2))) {
// on a heading, and next line is at the bottom
atbottom = B_TRUE;
}
if (atbottom) {
nextpage = i;
mvwprintw(mainwin, y, 0, "--' for next page--");
}
}
}
// heading?
if (prompt->choice[i].heading) {
strcpy(curheading, prompt->choice[i].desc);
doneheading = B_FALSE;
//mvwprintw(mainwin, y, 0, "%s", prompt->choice[i].text);
prompt->choice[i].valid = B_FALSE;
} else if (strlen(inpstring)) {
int matched = B_FALSE;
// does this choice match? use ->text, not ->desc
matched = strpixmatch(prompt->choice[i].text, inpstring);
if (matched) {
if (showall) {
// if we haven't printed the heading yet...
if (gotheadings && !doneheading) {
// only print if on the page
if ((i >= first) && !atbottom) {
// show heading first
mvwprintw(mainwin, y, 0, "%s", curheading);
y++;
}
doneheading = B_TRUE;
}
// only print if we're not off the bottom
if ((i >= first) && !atbottom) {
mvwprintw(mainwin, y, 0, "%s%s", gotheadings ? " " : "", prompt->choice[i].desc);
y++;
}
}
prompt->choice[i].valid = B_TRUE;
nvalid++;
} else {
prompt->choice[i].valid = B_FALSE;
}
} else {
// if we haven't printed the heading yet...
if (showall) {
if (gotheadings && !doneheading) {
// only print if on the page
if ((i >= first) && !atbottom) {
// show heading first
mvwprintw(mainwin, y, 0, "%s", curheading);
y++;
}
doneheading = B_TRUE;
}
// only print if we're not off the bottom
if ((i >= first) && !atbottom) {
mvwprintw(mainwin, y, 0, "%s%s", gotheadings ? " " : "", prompt->choice[i].desc);
y++;
}
}
}
}
// display prompt question
sprintf(promptstr, "%s [%s%s] %s",
prompt->q[prompt->whichq],
prompt->maycancel ? "ESC," : "",
showall ? "'=next page,?=toggle" : "?=list",
inpstring);
mvwprintw(mainwin, 0, 0, "%s", promptstr);
wclrtoeol(mainwin);
// if there's only one match, complete it
if (nvalid == 1) {
int cx,cy;
int validone = -1;
// remember cursor pos
getyx(mainwin, cy, cx);
// find the valid one
for (i = 0; i < prompt->nchoices; i++) {
if (prompt->choice[i].valid) {
validone = i;
break;
}
}
// fill in the name of the completed choice
/*
sprintf(promptstr, "%s %s %s",
prompt->q[prompt->whichq], prompt->maycancel ? "[ESC=cancel, '=next page] " : "",
prompt->choice[validone].text);
*/
sprintf(promptstr, "%s [%s%s] %s",
prompt->q[prompt->whichq],
prompt->maycancel ? "ESC," : "",
showall ? "'=next page,?=toggle" : "?=list",
prompt->choice[validone].text);
mvwprintw(mainwin, 0, 0, "%s", promptstr);
// move the cursor back
wmove(mainwin, cy, cx);
}
wrefresh(mainwin);
// ask for choice...
if (autochar) {
ch = autochar;
autochar = 0;
} else {
ch = getch();
}
if ((ch >= '0') && (ch <= '9')) { // shortcut
flag_t *f;
// autofill from the shortcut
f = lfhasflagval(player, F_SHORTCUT, ch - '0', NA, NA, NULL);
if (f) {
strcpy(inpstring, f->text);
// now press enter
autochar = 10;
}
} else if ((ch == 27) && (prompt->maycancel)) { // ESC - cancel
sel = -1;
break;
} else if (ch == '\'') {
if (nextpage == -1) {
first = 0;
} else {
first = nextpage;
}
} else if ((ch == '!') || (ch == '?')) { // toggle prompts
if (showall) {
prompt->whichq++;
if (prompt->whichq >= prompt->nqs) prompt->whichq = 0;
} else {
showall = B_TRUE;
}
} else if ((ch == 8) || (ch == 127)) { // backspace
if (strlen(inpstring) > 0) {
inpstring[strlen(inpstring)-1] = '\0';
}
} else if (ch == 10) { // enter
// exactly one valid choice?
if (nvalid == 1) {
for (i = 0; i < prompt->nchoices; i++) {
if (prompt->choice[i].valid) {
sel = i;
break;
}
}
} else if (nvalid == 0) {
// cancel
sel = -1;
break;
}
} else {
char temp[2];
// append to input string
temp[0] = ch;
temp[1] = '\0';
strcat(inpstring, temp);
/*
sel = -1;
for (i = 0 ; i < prompt->nchoices; i++) {
if (prompt->choice[i].ch == ch) {
sel = i;
break;
}
}
*/
}
}
// set result pointer
if (sel == -1) {
prompt->result = NULL;
prompt->selection = -1;
} else {
prompt->result = prompt->choice[i].data;
prompt->selection = i;
}
if ((gamemode == GM_GAMESTARTED)) {
drawscreen();
} else {
cls();
wrefresh(mainwin);
}
// return NUL or result char
if (ch == 27) {
return '\0';
}
return prompt->choice[i].ch;
}
int getkey(void) {
int key_code=0;
key_code = getch();
// XXX NEW CODE:
if (strcmp(msgbuf, "")) {
clearmsg();
//strcpy(msgbuf, "");
//drawmsg();
//drawcursor();
}
return keycodetokey(key_code);
}
void handleinput(void) {
int ch;
//char buf[BUFLEN];
flag_t *f;
int gotcmd = B_FALSE;
char numstring[BUFLEN];
int count = 1;
// if running, automatically do move
f = hasflag(player->flags, F_RUNNING);
if (f) {
int dir;
int hasgettableobs = B_FALSE;
dir = f->val[0];
object_t *o;
for (o = player->cell->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP)) {
hasgettableobs = B_TRUE;
break;
}
}
// something here?
if (hasgettableobs) {
stoprunning(player);
} else if (!canmove(player, dir, NULL)) { // can't move anymore?
stoprunning(player);
} else {
if (trymove(player, dir, B_TRUE)) {
stoprunning(player);
} else {
// moved ok - dont wait for input
return;
}
}
}
drawmsg();
strcpy(numstring, "");
gotcmd = B_FALSE;
while (!gotcmd) {
char temp[2];
flag_t repeatflag;
int wantrepeat = B_FALSE;
repeatflag.text = NULL;
drawcursor();
// repeated commands?
f = hasflag(player->flags, F_AUTOCMD);
if (f) {
ch = f->text[0];
if (f->val[0] <= 0) {
killflag(f);
msg("Finished repeating '%c'.",ch);
} else {
count = 1;
f->val[0]--;
}
} else {
ch = getkey();
}
gotcmd = B_TRUE;
switch (ch) {
// count
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
temp[0] = ch;
temp[1] = '\0';
strcat(numstring, temp);
count = atoi(numstring);
if (count < 1) count = 1;
if (count > 1) {
mvwprintw(msgwin, 0, 0, "count = %d", count);
} else {
wclear(msgwin);
}
wrefresh(msgwin);
gotcmd = B_FALSE;
break;
case 127:
case 8: // ie. backspace
if (strlen(numstring) > 0) {
// remove last letter of number string
numstring[strlen(numstring)-1] = '\0';
count = atoi(numstring);
if (count < 1) count = 1;
if (count > 1) {
mvwprintw(msgwin, 0, 0, "count = %d", count);
} else {
wclear(msgwin);
}
wrefresh(msgwin);
}
gotcmd = B_FALSE;
break;
case 'g': // repeat last command
f = hasflag(player->flags, F_LASTCMD);
if (f) {
ch = f->text[0];
repeatflag.id = f->id;
repeatflag.val[0] = f->val[0];
repeatflag.val[1] = f->val[1];
repeatflag.val[2] = f->val[2];
repeatflag.text = strdup(f->text);
wantrepeat = B_TRUE;
} else {
msg("Cannot repeat last command.");
}
break;
}
// now handle actual commands
f = hasflag(player->flags, F_LASTCMD);
if (f) {
killflag(f);
}
temp[0] = ch;
temp[1] = '\0';
switch (ch) {
// movement
case 'h':
case 'j':
case 'k':
case 'l':
case 'y':
case 'u':
case 'b':
case 'n':
trymove(player, chartodir(ch), B_TRUE);
break;
case 'H':
case 'J':
case 'K':
case 'L':
case 'Y':
case 'U':
case 'B':
case 'N':
tryrun(player, chartodir(ch));
break;
case '.': // wait
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
if (count > 1) {
addflag(player->flags, F_AUTOCMD, count, NA, NA, ".");
} else {
rest(player, B_TRUE);
}
break;
// testing
/*
case '1':
gettimetext(buf);
msg("The current time is %s",buf);
break;
case '2':
msg("Something happens.");
msg("Something else happens.");
msg("Another thing is about to happen now.");
msg("Too many things are happening!");
break;
*/
// player commands
case 'A': // attack
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
if (wantrepeat) {
doattackcell(repeatflag.val[2]);
} else {
doattackcell('\0');
}
break;
case 'i': // inventory
doinventory(player->pack);
break;
case '?': // help
dohelp();
break;
case '@': // display player stats
showlfstats(player, B_FALSE);
break;
case ']': // display armour
showlfarmour(player);
break;
case ':': // look at what's here
dolook(player->cell);
break;
case '|': // msg history - TODO: replace with ctrl-p
domsghist();
break;
case '/': // explain object
doexplain("Select glyph to explain (ESC to cancel):");
break;
case '\\': // list knowledge
doknowledgelist();
break;
case 'R': // rest
dorest();
break;
case 'm': // 'm'agic/abilities (magic)
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
if (wantrepeat) {
//domagic(repeatflag.val[2], repeatflag.val[0], repeatflag.val[1]);
// don't repeat the target cell!
domagic(repeatflag.val[2], NA, NA);
} else {
domagic(OT_NONE, NA, NA);
}
break;
case 'M': // 'M'emorise magic/ability shortcut
domemmagic();
break;
case '<': // go up
dostairs(D_UP);
break;
case '>': // go down
doenter(player);
break;
// firearm functions
case 'f': // fire gun
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
dofire();
break;
case 'a': // aim
doselguntarget();
break;
case 'F': // aim then fire
doselguntarget();
dofire();
break;
case '\'':
donextguntarget();
break;
// object functions
case 'c': // close
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
doclose();
break;
case 'C': // communicate
docomms();
break;
case 'e': // eat
doeat(player->pack);
break;
case 'd': // drop
dodrop(player->pack, B_SINGLE, player->cell->obpile);
break;
case 'D': // drop multiple things
dodrop(player->pack, B_MULTIPLE, player->cell->obpile);
break;
case 'W': // wear
dowear(player->pack);
break;
case 'w': // weild
doweild(player->pack);
break;
case 'T': // takeoff
dotakeoff(player->pack);
break;
case ',': // pickup
dopickup(player->cell->obpile);
break;
case 'r': // read
doread(player->pack);
break;
case 'q': // quaff
doquaff(player->pack);
break;
case 't': // throw
dothrow(player->pack);
break;
case 'p': // pick lock
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
dolockpick(player->pack);
break;
case 'P': // Pour
dopour(player->pack);
break;
case 'o': // operate
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
dooperate(player->pack);
break;
// GAME FUNCTIONS
case 'Q': // quit
doquit();
break;
case 'S': // save + quit
if (savegame()) {
msg("Save failed.");
} else {
msg("Saved successfully. See you later...");
more();
exit(0);
}
break;
default:
gotcmd = B_FALSE;
break;
}
if (repeatflag.text) {
free(repeatflag.text);
}
}
}
void initprompt(prompt_t *p, char *q1) {
int i;
for (i = 0; i < MAXPROMPTQUESTIONS; i++) {
if (p->q[i]) {
free(p->q[i]);
p->q[i] = NULL;
}
}
p->q[0] = strdup(q1);
p->nqs = 1;
p->whichq = 0;
p->maycancel = B_FALSE;
p->result = NULL;
p->nchoices = 0;
for (i = 0; i < MAXCHOICES; i++) {
choice_t *c;
c = &p->choice[i];
if (c->text) {
free(c->text);
c->text = NULL;
}
if (c->desc) {
free(c->desc);
c->desc = NULL;
}
c->data = NULL;
}
}
int keycodetokey(int keycode) {
int keystroke = 0;
if (keycode == -1) return -1;
if (keycode == 27) { // an esc sequence
keycode=getch();
keystroke=keycode;
keycode=getch();
keystroke=keystroke | (keycode<<8);
keycode=getch();
keystroke=keystroke | (keycode<<16);
} else {
// regular keypress
return (int)keycode;
}
return keystroke;
}
void dblog(char *format, ... ) {
char buf[HUGEBUFLEN];
va_list args;
va_start(args, format);
vsprintf( buf, format, args );
va_end(args);
/*
if (gamestarted) {
fprintf(logfile, "%s\n", buf);
fflush(logfile);
} else {
printf("%s\n", buf);
fflush(stdout);
}
*/
if (logfile) {
fprintf(logfile, "%s\n", buf);
fflush(logfile);
} else {
fprintf(stdout, "%s\n", buf);
fflush(stdout);
}
}
// force a '--more--' prompt
void more(void) {
//msg("^");
strcat(msgbuf, MORESTRING);
//mvwprintw(msgwin, 0, 0, msgbuf);
drawmsg();
// wait for space
while (getch() != ' ');
// clear msg
clearmsg();
}
void warn(char *format, ... ) {
char buf[BUFLEN];
va_list args;
// like msg, but interrupts rest ect
interrupt(player);
va_start(args, format);
vsprintf( buf, format, args );
va_end(args);
msg_real("%s", buf);
}
void msgnocap(char *format, ... ) {
char buf[BUFLEN];
va_list args;
va_start(args, format);
vsprintf( buf, format, args );
va_end(args);
// like msg, but don't capitalise
msg_real("%s", buf);
}
void msg(char *format, ... ) {
char buf[BUFLEN];
va_list args;
va_start(args, format);
vsprintf( buf, format, args );
va_end(args);
capitalise(buf);
msg_real("%s", buf);
}
void msg_real(char *format, ... ) {
char buf[BUFLEN];
va_list args;
//char *p;
int db = B_FALSE;
// any msg will interrupt the player
//interrupt(player);
//msgmod = B_TRUE;
va_start(args, format);
vsprintf( buf, format, args );
va_end(args);
if (db) dblog("adding to msgbuf: [%s]",buf);
assert(!strchr(buf, '#'));
// ie. can the message buffer fit:
// what is already there + 2 spaces + the new text + '--more--' ?
//if (strlen(msgbuf) + 2 + strlen(buf) + strlen(MORESTRING) >= SCREENW) {
if (strlen(msgbuf) + 2 + strlen(buf) >= SCREENW) {
// do more
more();
} else {
if (strlen(msgbuf) > 0) {
strcat(msgbuf, " ");
}
}
strcat(msgbuf, buf);
if (db) dblog(" msgbuf is now: [%s]",msgbuf);
msgmod = B_TRUE;
// update msg window
drawmsg();
drawcursor();
}
int needsbold(enum COLOUR col) {
switch (col) {
case C_YELLOW:
case C_WHITE:
case C_BOLDCYAN:
case C_BOLDBLUE:
case C_BOLDMAGENTA:
case C_BOLDGREEN:
case C_ORANGE:
return B_TRUE;
default:
break;
}
return B_FALSE;
}
void nothinghappens(void) {
msg("Nothing seems to happen.");
}
void drawstatus(void) {
char buf[BUFLEN];
char buf2[BUFLEN];
//char mpbuf[BUFLEN];
char waitbuf[BUFLEN];
char pname[BUFLEN];
char maxmpstr[BUFLEN];
flag_t *f;
enum ATTRIB a;
int myatt[MAXATTS];
long xpleft;
getplayernamefull(pname);
wclear(statwin);
xpleft = getxpforlev(player->level + 1) - player->xp;
sprintf(buf, "[%-26s] Lv:%d", pname,
player->level);
mvwprintw(statwin, 0, 0, buf);
if (lfhasflag(player, F_HASNEWLEVEL)) {
setcol(statwin, C_BOLDGREEN);
wprintw(statwin, " LevUp",xpleft);
unsetcol(statwin, C_BOLDGREEN);
} else {
wprintw(statwin, " Next:%ld",xpleft);
}
// blinded?
if (isblind(player)) {
setcol(statwin, C_RED);
wprintw(statwin, " Blind");
unsetcol(statwin, C_RED);
}
// paralysed somehow?
if (isimmobile(player)) {
setcol(statwin, C_RED);
wprintw(statwin, " Immobile");
unsetcol(statwin, C_RED);
} else {
char actbuf[BUFLEN],movebuf[BUFLEN];
getspeednameshort(getactspeed(player), actbuf);
getspeednameshort(getmovespeed(player), movebuf);
// both action and movement speed the same, and not "normal" ?
if (!strcmp(actbuf, movebuf) && strcmp(actbuf, "normal")) {
// show combiner action/movement speed
enum COLOUR col;
if (getactspeed(player) < SP_NORMAL) {
col = C_GREEN;
} else {
col = C_RED;
}
setcol(statwin, col);
capitaliseall(actbuf);
wprintw(statwin, " %s", actbuf);
unsetcol(statwin, col);
} else {
// show action/movement speed seperately
// show player action speed
if (strcmp(actbuf, "normal")) {
enum COLOUR col;
if (getactspeed(player) < SP_NORMAL) {
col = C_GREEN;
} else {
col = C_RED;
}
setcol(statwin, col);
wprintw(statwin, " Act:");
capitaliseall(actbuf);
wprintw(statwin, "%s", actbuf);
unsetcol(statwin, col);
}
// show player movement speed
if (strcmp(movebuf, "normal")) {
enum COLOUR col;
if (getmovespeed(player) < SP_NORMAL) {
col = C_GREEN;
} else {
col = C_RED;
}
setcol(statwin, col);
wprintw(statwin, " Mv:");
capitaliseall(movebuf);
wprintw(statwin, "%s", movebuf);
unsetcol(statwin, col);
}
}
}
// burdened somehow?
switch (isburdened(player)) {
case BR_BURDENED:
setcol(statwin, C_BROWN);
wprintw(statwin, " Burdened");
unsetcol(statwin, C_BROWN);
break;
case BR_STRAINED:
setcol(statwin, C_RED);
wprintw(statwin, " Strained");
unsetcol(statwin, C_RED);
break;
case BR_OVERLOADED:
setcol(statwin, C_YELLOW);
wprintw(statwin, " Overloaded");
unsetcol(statwin, C_YELLOW);
break;
default:
break;
}
// show certain flags
f = isdrunk(player);
if (f) {
char dstring[BUFLEN];
strcpy(dstring, getdrunktext(f));
capitalise(dstring);
setcol(statwin, C_BROWN);
//wprintw(statwin, " %s(%d)", dstring,f->lifetime);
wprintw(statwin, " %s", dstring);
unsetcol(statwin, C_BROWN);
}
f = ispoisoned(player);
if (f) {
// find highest amount of poison
if (getskill(player, SK_FIRSTAID) >= PR_ADEPT) {
if (poisonthreatenslife(player, f)) {
setcol(statwin, C_GREEN);
wprintw(statwin, " Poison(bad)");
unsetcol(statwin, C_GREEN);
} else {
setcol(statwin, C_BROWN);
wprintw(statwin, " Poisoned(mild)");
unsetcol(statwin, C_BROWN);
}
} else {
setcol(statwin, C_GREEN);
wprintw(statwin, " Poisoned");
unsetcol(statwin, C_GREEN);
}
}
//mvwprintw(statwin, 0, 0, buf);
f = hasflag(player->flags, F_HUNGER);
if (f) {
int hlev;
hlev = gethungerlevel(f->val[0]);
if (hlev == H_NONE) {
strcpy(buf2, "");
} else {
gethungername(gethungerlevel(f->val[0]), buf2);
capitalise(buf2);
}
} else {
strcpy(buf2, "");
}
if (strlen(buf2) > 0) {
setcol(statwin, C_BROWN);
wprintw(statwin, " %s", buf2);
unsetcol(statwin, C_BROWN);
}
// good effects
f = lfhasflag(player, F_HIDING);
if (f) {
setcol(statwin, C_BLUE);
if (f->val[0] < 0) {
wprintw(statwin, " Hiding--");
} else {
wprintw(statwin, " Hiding");
}
unsetcol(statwin, C_BLUE);
}
// construct waiting string
strcpy(waitbuf, "");
/*
// timespent > 0?
if (player->timespent) {
sprintf(buf, "busy: %d", player->timespent);
strcat(waitbuf, buf);
}
*/
f = hasflag(player->flags, F_AUTOCMD);
if (f) {
if (strlen(waitbuf)) strcat(waitbuf, ", ");
sprintf(buf, "'%c' x %d", f->text[0], f->val[0]);
strcat(waitbuf, buf);
}
if (strlen(waitbuf)) {
wprintw(statwin, " (%s)",waitbuf);
}
// SECOND LINE
for (a = 0; a < MAXATTS; a++) {
myatt[a] = getattr(player, a);
}
//redraw();
if (getmaxmp(player) == player->maxmp) {
strcpy(maxmpstr, "");
} else {
sprintf(maxmpstr, "(%d)",player->maxmp);
}
// HP
mvwprintw(statwin, 1, 0, "HP:");
setcol(statwin, getpctcol(player->hp, player->maxhp));
wprintw(statwin, "%d",player->hp);
unsetcol(statwin, getpctcol(player->hp, player->maxhp));
wprintw(statwin, "/%d ",player->maxhp);
// MP
if (getmaxmp(player) > 0) {
wprintw(statwin, "MP:");
setcol(statwin, getpctcol(player->mp, getmaxmp(player)));
wprintw(statwin, "%d",player->mp);
unsetcol(statwin, getpctcol(player->mp, getmaxmp(player)));
wprintw(statwin, "/%d%s ",getmaxmp(player),maxmpstr);
} else {
wprintw(statwin, "MP:- ");
}
sprintf(buf, "$:%d AR:%d ", countmoney(player), getarmourrating(player));
wprintw(statwin, buf);
for (a = 0; a < MAXATTS; a++) {
wprintw(statwin, "%s:", getattrabbrev(a));
if (myatt[a] == player->baseatt[a]) {
wprintw(statwin, "%d ",myatt[a]);
} else {
if (myatt[a] > player->baseatt[a]) {
setcol(statwin, C_GREEN);
wprintw(statwin, "%d*",myatt[a]);
unsetcol(statwin, C_GREEN);
} else {
setcol(statwin, C_RED);
wprintw(statwin, "%d*",myatt[a]);
unsetcol(statwin, C_RED);
}
}
}
wprintw(statwin, "DLev:%d", player->cell->map->depth);
}
void drawmsg(void) {
//char *nexttok;
int db = B_FALSE;
if (db) dblog("drawmsg called");
/*
if ( !strcmp(msgbuf, "") ) {
return;
}
if (!isplayerturn() && !msgmod) {
return;
}
*/
//dblog("calling drawmsg");
// is msgbuf has changed...
if (strcmp(msgbuf, lastmsgbuf) || msgmod) {
wclear(msgwin);
wmove(msgwin, 0, 0);
wprintw(msgwin, "%s", msgbuf);
//mvwprintw(msgwin, 0, 0, msgbuf);
wrefresh(msgwin);
strcpy(lastmsgbuf, msgbuf);
}
// drawcursor();
/*
// TODO: if it's a monster's turn, always do a more?
nexttok = strstr(msgbuf, "^");
if (!nexttok) {
// just update msg with current text
wclear(msgwin);
mvwprintw(msgwin, 0, 0, "%s", msgbuf);
wrefresh(msgwin);
} else {
while (nexttok) {
char thistok[BUFLEN];
int thistoklen;
// print up to just before the "^" current token
// remember this token
thistoklen = nexttok - msgbuf;
strncpy(thistok, msgbuf, thistoklen);
thistok[thistoklen] = '\0';
if (db) dblog("drawmsg: thistok is [%s]",thistok);
// is there another token?
nexttok = strstr(msgbuf, "^");
if (nexttok) {
nexttok++; // go forward past the ^
if (db) dblog("drawmsg: nexttok is [%s]",nexttok);
// print with '--more--' added to the end
if (db) dblog("drawmsg: displaying thistok [%s]",thistok);
wclear(msgwin);
mvwprintw(msgwin, 0, 0, "%s%s", thistok,MORESTRING);
wrefresh(msgwin);
// ...wait for spacebar before showing next bit...
while (getch() != ' ');
// we now know the player has read this
if (db) dblog("prompting for --more--");
// now clear msgstring up to end of where
// 'thistok' appears!
strcpy(msgbuf, nexttok);
if (db) dblog(" reduced msgbuf to: [%s]",msgbuf);
} else {
if (db) dblog("drawmsg: no nexttok");
// just print this bit
wclear(msgwin);
mvwprintw(msgwin, 0, 0, "%s", thistok);
wrefresh(msgwin);
}
}
}
// clear message buffer
if (isplayerturn()) {
strcpy(msgbuf, "");
if (db) dblog("clearing msg buf");
}
*/
//msgmod = B_FALSE;
}
void redraw(void) {
//dblog("redraw");
//wrefresh(msgwin);
wrefresh(statwin);
wrefresh(gamewin);
}
void setcol(WINDOW *win, enum COLOUR col) {
if (needsbold(col)) {
wattron(win, A_BOLD);
}
wattron(win, COLOR_PAIR(col));
}
void unsetcol(WINDOW *win, enum COLOUR col) {
wattroff(win, COLOR_PAIR(col));
if (needsbold(col)) {
wattroff(win, A_BOLD);
}
}
void setobcolour(WINDOW *win, object_t *o) {
if (!o) return;
if (o->blessknown) {
if (iscursed(o)) {
setcol(win, C_RED);
} else if (isblessed(o)) {
setcol(win, C_CYAN);
}
}
}
void unsetobcolour(WINDOW *win, object_t *o) {
if (!o) return;
if (o->blessknown) {
if (iscursed(o)) {
unsetcol(win, C_RED);
} else if (isblessed(o)) {
unsetcol(win, C_CYAN);
}
}
}
void showlfarmour(lifeform_t *lf) {
enum BODYPART bp;
object_t *o;
int y;
char buf[BUFLEN];
cls();
if (isplayer(lf)) {
centre(mainwin, 0, "CHARACTER EQUIPMENT");
} else{
centre(mainwin, 0, "MONSTER EQUIPMENT");
}
y = 2;
for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) {
char rhs[BUFLEN];
// default
sprintf(rhs, "-");
if (!lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) {
sprintf(buf, "%15s:%3s",getbodypartname(bp), " ");
o = hasobwithflagval(lf->pack, F_EQUIPPED, bp, NA, NA, NULL);
if (o) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
strcpy(rhs, obname);
} else {
strcpy(rhs, "-");
}
mvwprintw(mainwin, y, 0, "%s", buf);
setobcolour(mainwin, o);
wprintw(mainwin, "%s", rhs);
unsetobcolour(mainwin, o);
y++;
}
}
y = getmaxy(mainwin);
centre(mainwin, y-1, "[Press any key]");
/*
f = hasflag(mylist[i]->flags,F_EQUIPPED);
if (f) {
if (f->val[0] == BP_WEAPON) {
if (hasflag(mylist[i]->flags, F_TWOHANDED)) {
strcat(buf2, " (two-handed weapon)");
} else {
strcat(buf2, " (weapon)");
}
} else {
strcat(buf2, " (");
strcat(buf2, getbodypartequipname(f->val[0]));
strcat(buf2, " ");
strcat(buf2, getbodypartname(f->val[0]));
strcat(buf2, ")");
}
}
*/
getch();
drawscreen();
real_clearmsg(B_TRUE);
}
void showlfstats(lifeform_t *lf, int showall) {
int y = 0, y2 = 0, x2 = 40;
int x;
int arating, evasion;
int speed,acc;
int h;
char buf[BUFLEN],buf2[BUFLEN];
job_t *j;
flag_t *f;
char *ftext= "%12s: ";
long xpneeded;
object_t *w;
objecttype_t *ot;
int first;
int i;
float dammod;
int accmod;
enum BODYPART bp;
enum BODYPART missingbp[MAXBODYPARTS];
int nmissingbp;
obpile_t *op = NULL;
char ch;
char mode = '@';
char prompt[BUFLEN];
char cmdchars[BUFLEN];
int done = B_FALSE;
h = getmaxy(mainwin);
// override showall sometimes...
// need 'player == lf' to cope with mind scans
// where we update the player pointer, but don't
// change the target's '->controller' setting (meaning
// that isplayer(target) still returns false).
if (isplayer(lf) || isgenius(player) || (player == lf)) {
showall = B_TRUE;
}
if (showall) {
sprintf(prompt, "[@=stats S=skills/abilities M=magic E=effects %sESC=quit]", isplayer(lf) ? "" : "I=items " );
sprintf(cmdchars, "@asme%s",isplayer(lf) ? "" : "i");
} else {
sprintf(prompt, "%s", "[ESC=quit]");
sprintf(cmdchars, "%s", "@");
}
while (!done) {
cls();
y = 0;
ch = '\0';
if (mode == '@') {
if (isplayer(lf)) {
centre(mainwin, 0, "CHARACTER DETAILS");
} else{
centre(mainwin, 0, "MONSTER DETAILS");
}
y = 2;
y2 = 2;
dammod = getstrdammod(lf);
accmod = getstatmod(lf, A_DEX);
if (isplayer(lf)) {
getplayername(buf);
} else {
getlfnamea(lf, buf);
}
mvwprintw(mainwin, y, 0, ftext, "Name");
wprintw(mainwin, "%-20s", buf); y++;
if (isplayer(lf)) {
mvwprintw(mainwin, y, 0, ftext, "Race");
wprintw(mainwin, "%-20s", lf->race->name); y++;
}
j = getjob(lf);
if (j) {
mvwprintw(mainwin, y, 0, ftext, "Job");
wprintw(mainwin, "%-20s", j->name); y++;
}
// size
mvwprintw(mainwin, y, 0, ftext, "Size");
wprintw(mainwin, "%-20s", getsizetext(getlfsize(lf))); y++;
if (showall) {
float w;
w = getlfweight(lf, B_NOOBS);
mvwprintw(mainwin, y, 0, ftext, "Weight");
getweighttext(w, buf);
wprintw(mainwin, buf, w); y++;
}
if (showall || (getseenlfconditioncutoff(player) == C_HEALTHY)) {
mvwprintw(mainwin, y, 0, ftext, "Hit Points");
wprintw(mainwin, "%d / %d", lf->hp , lf->maxhp); y++;
} else {
char hpinfo[BUFLEN];
sprintf(hpinfo, "%s",getseenlfconditionname(lf, player));
if (strlen(hpinfo) > 0) {
mvwprintw(mainwin, y, 0, ftext, "Hit Points");
wprintw(mainwin, "%s", hpinfo); y++;
}
}
if (showall) {
char maxmpstr[BUFLEN];
if (getmaxmp(lf) == lf->maxmp) {
strcpy(maxmpstr, "");
} else {
sprintf(maxmpstr, "(%d)",lf->maxmp);
}
mvwprintw(mainwin, y, 0, ftext, "Mana");
wprintw(mainwin, "%d / %d%s", lf->mp , lf->maxmp,maxmpstr); y++;
}
if (showall) {
mvwprintw(mainwin, y, 0, ftext, "Exp Level");
if (isplayer(lf)) {
xpneeded = getxpforlev(lf->level + 1) - lf->xp;
wprintw(mainwin, "%d (%ld XP, %ld for next)", lf->level, lf->xp, xpneeded); y++;
} else {
wprintw(mainwin, "%d", lf->level); y++;
}
if (isplayer(lf)) {
int attpoints;
attpoints = getattpoints(lf);
mvwprintw(mainwin, y, 0, ftext, "Training");
if ((lf->skillpoints == 0) && (attpoints == 0)) {
wprintw(mainwin, "n/a");
} else {
wprintw(mainwin, "%d skill%s, %d attrib%s", lf->skillpoints,
(lf->skillpoints == 1) ? "" : "s",
attpoints,
(attpoints == 1) ? "" : "s");
}
y++;
}
}
y++; // skip line
if (showall) {
char buf2[BUFLEN];
int str;
str = getattr(lf, A_STR);
getstrname(str, buf2);
if (dammod == 1) {
sprintf(buf, "%d (%s)",str, buf2);
} else if (dammod > 1) {
sprintf(buf, "%d (%s, +%d%% dmg)",str, buf2, (int)((dammod * 100) - 100) );
} else { // ie. dammod < 1
sprintf(buf, "%d (%s, -%d%% dmg)",str, buf2, (int)(100 - (dammod * 100)) );
}
if (str != lf->baseatt[A_STR]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "STR");
wprintw(mainwin, "%s", buf); y++;
} else if (!isplayer(lf)) {
int str;
// just show name
str = getattr(lf, A_STR);
getstrname(str, buf);
if (str != lf->baseatt[A_STR]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "STR");
wprintw(mainwin, "%s", buf); y++;
}
if (showall) {
char buf2[BUFLEN];
int dex;
dex = getattr(lf, A_DEX);
getdexname(dex, buf2);
if (accmod == 0) {
sprintf(buf, "%d (%s)",dex, buf2);
} else if (accmod > 0) {
sprintf(buf, "%d (%s, +%d%% bonus)",dex, buf2, accmod );
} else { // ie. accmod < 0
sprintf(buf, "%d (%s, %d%% bonus)",dex, buf2, accmod );
}
if (dex != lf->baseatt[A_DEX]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "DEX");
wprintw(mainwin, "%s", buf); y++;
} else if (!isplayer(lf)) {
int dex;
// just show name
dex = getattr(lf, A_DEX);
getdexname(dex, buf);
if (dex != lf->baseatt[A_DEX]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "DEX");
wprintw(mainwin, "%s", buf); y++;
}
if (showall) {
char buf2[BUFLEN];
int iq;
iq = getattr(lf, A_IQ);
getiqname(iq, buf2);
sprintf(buf, "%d (%s)",iq, buf2);
if (iq != lf->baseatt[A_IQ]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "IQ");
wprintw(mainwin, "%s", buf); y++;
} else if (!isplayer(lf)) {
int iq;
// just show name
iq = getattr(lf, A_IQ);
getiqname(iq, buf);
if (iq != lf->baseatt[A_IQ]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "IQ");
wprintw(mainwin, "%s", buf); y++;
}
if (showall) {
char buf2[BUFLEN];
int con;
con = getattr(lf, A_CON);
getconname(con, buf2);
sprintf(buf, "%d (%s)",con, buf2);
if (con != lf->baseatt[A_CON]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "CON");
wprintw(mainwin, "%s", buf); y++;
} else if (!isplayer(lf)) {
int con;
// just show name
con = getattr(lf, A_CON);
getconname(con, buf);
if (con != lf->baseatt[A_CON]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "CON");
wprintw(mainwin, "%s", buf); y++;
}
//mvwprintw(mainwin, y, 0, ftext, "XP");
//wprintw(mainwin, "%ld (%ld more for next level)", lf->xp, xpneeded); y++;
y++; // skip line
// now go to second column
// current weapon + dam
w = getweapon(lf);
if (w) {
int mindam,maxdam;
int bonus;
// weapon
sprintf(buf, "%s", w->type->name);
mvwprintw(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
if (showall) {
// damage
f = hasflag(w->flags, F_BONUS);
if (f && f->known) {
// only tell player about bonuses if they are known.!
bonus = f->val[0];
} else {
bonus = 0;
}
f = hasflag(w->flags, F_DAM);
if (f) {
getdamrange(f, &mindam, &maxdam);
} else {
mindam = 0;
maxdam = 0;
}
mindam += bonus;
maxdam += bonus;
// apply damage mod for strength
if (!hasflag(w->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
mindam = (int)((float)mindam * dammod);
maxdam = (int)((float)maxdam * dammod);
}
if (mindam < 0) mindam = 0;
if (maxdam < 0) maxdam = 0;
sprintf(buf, "%d-%d",(int)mindam,(int)maxdam);
mvwprintw(mainwin, y2, x2, ftext, "Weapon Dmg");
wprintw(mainwin, "%-20s", buf); y2++;
// chance to hit
acc = getlfaccuracy(lf, w);
mvwprintw(mainwin, y2, x2, ftext, "Wep.Accuracy");
wprintw(mainwin, "%d%%", acc); y2++;
}
} else {
// no damage
sprintf(buf, "N/A");
mvwprintw(mainwin, y2, x2, ftext, "Current Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
}
// skip a line
y2++;
/*
if (showall) {
mvwprintw(mainwin, y2, x2, ftext, "Attack Dmg");
wprintw(mainwin, "%-20s", buf); y2++;
}
*/
// unarmed attacks
op = addobpile(NULL, NULL);
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_HASATTACK) {
object_t *o;
objecttype_t *ot;
ot = findot(f->val[0]);
o = addob(op, ot->name);
if (o) {
sprintf(buf, "%s", o->type->name);
// damage
if (showall) {
char dambuf[BUFLEN];
int mindam,maxdam;
getdamrange(f, &mindam, &maxdam);
// apply damage mod for strength
if (!hasflag(o->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
mindam = (int)((float)mindam * dammod);
maxdam = (int)((float)maxdam * dammod);
}
if (mindam < 0) mindam = 0;
if (maxdam < 0) maxdam = 0;
sprintf(dambuf, " (%d-%d dmg)",(int)mindam,(int)maxdam);
strcat(buf, dambuf);
}
mvwprintw(mainwin, y2, x2, ftext, "Innate Attack");
wprintw(mainwin, "%-20s", buf); y2++;
} // end if o
} // end if fid == hasattack
} // end for each flag
// no attacks at all?
if (!w && !op->first) {
sprintf(buf, "N/A");
mvwprintw(mainwin, y2, x2, ftext, "Attack");
wprintw(mainwin, "%-20s", buf); y2++;
}
// skip line
y2++;
// attack speed
if (w || op->first) {
speed = getattackspeed(lf);
getspeedname(speed, buf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Attack Speed");
wprintw(mainwin, "%-20s", buf); y2++;
}
killobpile(op);
y2++; // skip line
// ARMOUR STUFF
if (showall) {
arating = getarmourrating(lf);
mvwprintw(mainwin, y2, x2, ftext, "Armour");
if (arating > 0) {
wprintw(mainwin, "%d (-%0.0f%% dmg)", arating, getdamreducepct(arating)); y2++;
} else {
wprintw(mainwin, "%d", arating); y2++;
}
evasion = getevasion(lf);
mvwprintw(mainwin, y2, x2, ftext, "Evasion");
wprintw(mainwin, "%d%%", evasion); y2++;
y2++; // skip line
}
speed = getactspeed(lf);
getspeedname(speed, buf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Action Speed");
wprintw(mainwin, "%-20s", buf); y2++;
speed = getmovespeed(lf);
getspeedname(speed, buf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Move Speed");
wprintw(mainwin, "%-20s", buf); y2++;
y2++; // skip line
if (showall) {
f = hasflag(lf->flags, F_HUNGER);
if (f) {
gethungername(gethungerlevel(f->val[0]), buf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Hunger");
wprintw(mainwin, "%-14s", buf); y2++;
/*
if (showall) {
wprintw(mainwin, "%-14s (%d)", buf, f->val[0]); y++;
} else {
wprintw(mainwin, "%-14s", buf); y++;
}
*/
}
}
// back to first column
y++;
// obvious physical effects here.
f = lfhasknownflag(lf, F_ASLEEP);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s sleeping.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasknownflag(lf, F_FLYING);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s flying.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasflag(lf, F_FROZEN);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s been turned to ice, and %s slowly melting.", you(lf), isplayer(lf) ? "have" : "has",
isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasknownflag(lf, F_GRABBEDBY);
if (f && (f->known)) {
lifeform_t *lf2;
char grabbername[BUFLEN];
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfname(lf2, grabbername);
} else {
strcpy(grabbername, "something");
}
sprintf(buf,"%s %s being held by %s.",you(lf), isplayer(lf) ? "are" : "is", grabbername);
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_GRABBING);
if (f && (f->known)) {
lifeform_t *lf2;
char grabeename[BUFLEN];
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfname(lf2, grabeename);
} else {
strcpy(grabeename, "something");
}
sprintf(buf,"%s %s holding on to %s.",you(lf), isplayer(lf) ? "are" : "is", grabeename);
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_HIDING);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s hiding.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasknownflag(lf, F_INVISIBLE);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s invisible.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasknownflag(lf, F_LEVITATING);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s levitating.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasflag(lf, F_NONCORPOREAL);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s noncorporeal and can walk through walls.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasflag(lf, F_PRODUCESLIGHT);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s produce%s light.", you(lf), isplayer(lf) ? "" : "s");
y++;
}
f = lfhasknownflag(lf, F_SPRINTING);
if (f) {
if (f->val[0]) {
mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is");
y++;
} else {
mvwprintw(mainwin, y, 0, "%s %s exhausted.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
}
f = lfhasknownflag(lf, F_UNDEAD);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s undead.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
// non-intrinsic effecst like polymorph, eye shading
f = lfhasknownflag(lf, F_POLYMORPHED);
if (f && (f->known)) {
sprintf(buf, "%s have been polymorphed into a %s.",you(lf), lf->race->name);
//if (lfhasflag(lf, F_OMNIPOTENT) || lfhasflag(lf, F_EXTRAINFO)) {
sprintf(buf2, " [%d left]", f->lifetime);
strcat(buf, buf2);
// }
mvwprintw(mainwin, y, 0, "%s", buf);
y++;
}
// missing body parts?
if (lfhasflagval(lf, F_NOBODYPART, BP_WEAPON, NA, NA, NULL)) {
mvwprintw(mainwin, y, 0, "%s cannot use weapons.", you(lf));
y++;
}
nmissingbp = 0;
for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) {
if (lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) {
if (bp == BP_RIGHTHAND) {
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
missingbp[nmissingbp] = bp;
nmissingbp++;
}
} else if (bp == BP_LEFTHAND) {
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL) &&
!lfhasflagval(lf, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL)
) {
missingbp[nmissingbp] = bp;
nmissingbp++;
}
} else if (bp == BP_SECWEAPON) {
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
missingbp[nmissingbp] = bp;
nmissingbp++;
}
} else {
missingbp[nmissingbp] = bp;
nmissingbp++;
}
}
}
if (nmissingbp) {
sprintf(buf, "%s %s no %s",you(lf), isplayer(lf) ? "have" : "has", getbodypartname(missingbp[0]));
if (nmissingbp > 1) {
// construct list of missing body parts
for (i = 1; i < nmissingbp ; i++) {
if (i == nmissingbp - 1) { // last
strcat(buf, " or ");
strcat(buf, getbodypartname(missingbp[i]));
} else {
strcat(buf, ", ");
strcat(buf, getbodypartname(missingbp[i]));
}
}
}
strcat(buf, ".");
mvwprintw(mainwin, y, 0, "%s", buf);
y++;
}
// fleeing?
if (showall) {
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_FLEEFROM) {
lifeform_t *lf2;
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfname(lf2, buf);
mvwprintw(mainwin, y, 0, "%s %s fleeing from %s.",
you(lf), isplayer(lf) ? "are" : "is", buf);
y++;
}
}
}
}
// diff materials?
if (lf->race->material->id != MT_FLESH) {
mvwprintw(mainwin, y, 0, "%s %s made out of %s.",you(lf), isplayer(lf) ? "are" : "is", lf->race->material->name);
y++;
}
if (showall) {
// resistances
strcpy(buf, "");
f = lfhasflagval(lf, F_DTRESIST, DT_ALL, NA, NA, NULL);
if (f && (showall || f->known)) {
sprintf(buf, "%s %s resistant to %s", you(lf), isplayer(lf) ? "are" : "is", getdamname(DT_ALL));
} else {
first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) {
f = isresistantto(lf->flags, i);
if (f && (showall || f->known)) {
if (first) {
sprintf(buf2, "%s %s resistant to: %s", you(lf), isplayer(lf) ? "are" : "is",getdamnamenoun(i));
first = B_FALSE;
} else {
sprintf(buf2, ", %s", getdamnamenoun(i));
}
if (lfhasknownflag(lf, F_EXTRAINFO) || lfhasflag(lf, F_OMNIPOTENT)) {
if (f->lifetime != PERMENANT) {
char buf3[BUFLEN];
sprintf(buf3, "[%dt]",f->lifetime);
strcat(buf2, buf3);
}
}
strcat(buf, buf2);
}
}
}
if (strlen(buf) > 0) {
strcat(buf, ".");
mvwprintw(mainwin, y, 0, buf);
y++;
}
// immunities
strcpy(buf, "");
f = lfhasflagval(lf, F_DTIMMUNE, DT_ALL, NA, NA, NULL);
if (f && (showall || f->known)) {
sprintf(buf, "%s %s immune to %s", you(lf), isplayer(lf) ? "are" : "is", getdamname(DT_ALL));
} else {
first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) {
f = isimmuneto(lf->flags, i);
if (f && (showall || f->known)) {
if (first) {
sprintf(buf2, "%s %s immune to: %s", you(lf), isplayer(lf) ? "are" : "is", getdamname(i));
first = B_FALSE;
} else {
sprintf(buf2, ", %s", getdamname(i));
}
strcat(buf, buf2);
}
}
}
if (strlen(buf) > 0) {
strcat(buf, ".");
mvwprintw(mainwin, y, 0, buf);
y++;
}
// vulnerabilities
strcpy(buf, "");
f = lfhasflagval(lf, F_DTVULN, DT_ALL, NA, NA, NULL);
if (f && (showall || f->known)) {
sprintf(buf, "%s %s vulnerable to %s", you(lf), isplayer(lf) ? "are" : "is", getdamname(DT_ALL));
} else {
first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) {
f = isvulnto(lf->flags, i);
if (f && (showall || f->known)) {
if (first) {
sprintf(buf2, "%s %s vulnerable to: %s", you(lf), isplayer(lf) ? "are" : "is", getdamnamenoun(i));
first = B_FALSE;
} else {
sprintf(buf2, ", %s", getdamnamenoun(i));
}
if (lfhasknownflag(lf, F_EXTRAINFO) || lfhasflag(lf, F_OMNIPOTENT)) {
if (f->lifetime != PERMENANT) {
char buf3[BUFLEN];
sprintf(buf3, "[%dt]",f->lifetime);
strcat(buf2, buf3);
}
}
strcat(buf, buf2);
}
}
}
if (strlen(buf) > 0) {
strcat(buf, ".");
mvwprintw(mainwin, y, 0, buf);
y++;
}
}
} else if (mode == 's') {
int exitnow = B_FALSE;
// now show intrinsics on next page
centre(mainwin, 0, "ABILITIES");
y = 2;
for (ot = objecttype ; ot ; ot = ot->next) {
if (ot->obclass->id == OC_ABILITY) {
f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (f && (f->known)) {
char expirebuf[BUFLEN];
char eb2[BUFLEN];
int needgrab = B_FALSE;
if (f->val[2] == NA) {
sprintf(expirebuf, "at will");
} else {
sprintf(expirebuf, "every %d turn%s",f->val[2],
(f->val[2] == 1) ? "" : "s");
}
// extra options?
texttospellopts(f->text, NULL, NULL, &needgrab);
if (needgrab) {
strcat(expirebuf, ",after grab");
}
if (strlen(expirebuf)) {
sprintf(eb2,"(%s)",expirebuf);
} else {
strcpy(eb2, "");
}
sprintf(buf, "%-12s%s%s", ot->name, ot->desc, eb2);
mvwprintw(mainwin, y, 0, buf);
if (downline(&y, h, "ABILITIES", NULL, prompt, cmdchars, &ch)) {
exitnow = B_TRUE;
break;
}
}
}
}
y++;
if (!exitnow) {
char skilltitle[BUFLEN];
flag_t *known[MAXSKILLS], *available[MAXSKILLS];
int numknown = 0, numavailable = 0;
int n;
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_HASSKILL) {
known[numknown++] = f;
} else if (f->id == F_CANLEARN) {
if (!getskill(lf, f->val[0])) {
available[numavailable++] = f;
}
}
}
//centre(mainwin, y, "SKILLS"); y ++;
sprintf(skilltitle, "%-40s%-40s","AVAILABLE SKILLS", "KNOWN SKILLS");
doheading(mainwin, &y, 0, skilltitle);
for (n = 0; n < MAXOF(numknown,numavailable); n++) {
if (n < numavailable) {
mvwprintw(mainwin, y, 0, "- %s",
getskillname(available[n]->val[0]) );
}
if (n < numknown) {
mvwprintw(mainwin, y, 40, "%c %s (%s%s)",
ismaxedskill(lf, known[n]->val[0]) ? '*' : '-',
getskillname(known[n]->val[0]),
getskilllevelname(known[n]->val[1]),
ismaxedskill(lf, known[n]->val[0]) ? "/MAX" : "");
}
if (downline(&y, h, "SKILLS", skilltitle, prompt, cmdchars, &ch)) {
exitnow = B_TRUE;
break;
}
}
}
} else if (mode == 'm') {
char subheading[BUFLEN];
int lev;
int anyfound;
int exitnow = B_FALSE;
sprintf(subheading, " %-4s%-26s%-15s%-13s%s","Lv","Spell", "School", "Power", "Cost");
centre(mainwin, y, "MAGIC"); y += 2;
doheading(mainwin, &y, 0, subheading);
//if (!isplayer(lf)) {
// show spells monster can cast using mp
for (lev = 0; (lev <= 9) && !exitnow; lev++) {
for (ot = objecttype ; ot && !exitnow ; ot = ot->next) {
if (ot->obclass->id == OC_SPELL) {
int thislev;
thislev = getspelllevel(ot->id);
if (thislev == lev) {
f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (!f) {
f = lfhasknownflagval(lf, F_CANCAST, ot->id, NA, NA, NULL);
}
if (f && (f->known)) {
char spellname[BUFLEN];
char mpbuf[BUFLEN];
char powerbuf[BUFLEN];
int power;
int mpcost;
// power
power = getspellpower(lf, ot->id);
sprintf(powerbuf, "[");
for (i = 0; i < power; i++) {
strcat(powerbuf, "#");
}
for (i = 0; i < (getspellmaxpower(ot->id) - power); i++) {
strcat(powerbuf, "-");
}
strcat(powerbuf, "]");
// mp cost
if (f->id == F_CANWILL) {
mpcost = 0;
if (f->val[2] == NA) {
sprintf(mpbuf, "At will");
} else {
sprintf(mpbuf, "At will, every %d turn%s",f->val[2],
(f->val[2] == 1) ? "" : "s");
}
} else {
mpcost = getmpcost(lf, ot->id);
if (mpcost) {
getspellcosttext(lf, ot->id, power, mpbuf);
} else {
sprintf(mpbuf, "At will");
}
}
getspellname(ot->id, lf, spellname);
sprintf(buf, " %-4d%-26s%-15s%-13s%s",thislev, spellname, getschoolnameshort(getspellschool(ot->id)), powerbuf, mpbuf);
mvwprintw(mainwin, y, 0, "%s\n", buf);
anyfound = B_TRUE;
if (downline(&y, h, "MAGIC", subheading, prompt, cmdchars, &ch)) {
exitnow = B_TRUE;
break;
}
}
}
}
}
}
if (!anyfound) {
mvwprintw(mainwin, y, 0, "%s cannot cast any spells.", you(lf));
}
} else if (mode == 'e') {
x = 0; // override
// down a line.
centre(mainwin, y, "EFFECTS");
y += 2;
// ready to gain a level?
if (lfhasflag(lf, F_STATGAINREADY)) {
mvwprintw(mainwin, y, 0, "%s are ready to train your attributes.", you(lf));
y++;
}
if (lf->skillpoints) {
mvwprintw(mainwin, y, 0, "%s are ready to learn a new skill.", you(lf));
y++;
}
if (levelabilityready(lf)) {
mvwprintw(mainwin, y, 0, "%s are ready to learn a new job-based ability.", you(lf));
y++;
}
// obvious physical effects first.
f = lfhasknownflag(lf, F_BEINGSTONED);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s being turning to stone.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
if (eyesshaded(lf)) {
mvwprintw(mainwin, y, 0, "%s eyes are shaded.", your(lf), buf);
y++;
}
// show racial effects
if (hasjob(lf, J_PIRATE)) {
mvwprintw(mainwin, y, 0, "%s can hold %s liquor well.", you(lf), isplayer(lf) ? "your" : "its");
y++;
mvwprintw(mainwin, y, 0, "%s %s missing one eye.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
// show intrinsics
f = lfhasknownflag(lf, F_ATTRSET);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s has been modified.", your(lf), getattrname(f->val[0]));
y++;
} else {
f = lfhasknownflag(lf, F_ATTRMOD);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s has been %s.", your(lf), getattrname(f->val[0]), (f->val[2] > 0) ? "increased" : "decreased");
y++;
}
}
f = lfhasknownflag(lf, F_MAGICARMOUR);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s protected by %s %s", you(lf), isplayer(lf) ? "are" : "is",
needan(f->text) ? "an" : "a", f->text);
if (isplayer(lf)) {
wprintw(mainwin, " (+%d AR).",f->val[0]);
} else {
wprintw(mainwin, ".");
}
y++;
}
f = lfhasknownflag(lf, F_NOPACK);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s cannot carry objects.", you(lf));
y++;
}
f = lfhasflag(lf, F_OMNIPOTENT);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s are omnipotent.", you(lf));
y++;
}
if (isblind(lf)) {
mvwprintw(mainwin, y, 0, "%s cannot see.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_CHARMEDBY);
if (f) {
lifeform_t *lf2;
char charmername[BUFLEN];
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfnamea(lf2, charmername);
} else {
strcpy(charmername, "something");
}
sprintf(buf,"%s %s been charmed by %s.",you(lf), isplayer(lf) ? "have" : "has", charmername);
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_CONTROL);
if (f) {
mvwprintw(mainwin, y, 0, "%s can control teleportation and polymorphic effects.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_DETECTAURAS);
if (f) {
mvwprintw(mainwin, y, 0, "%s automatically detect blessings or curses.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_DETECTLIFE);
if (f) {
mvwprintw(mainwin, y, 0, "%s automatically detect %snearby lifeforms.", you(lf),
(f->val[1] == B_TRUE) ? "" : "the size of ");
y++;
}
f = lfhasknownflag(lf, F_DETECTMAGIC);
if (f) {
mvwprintw(mainwin, y, 0, "%s automatically detect magical enchantments on objects.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_DETECTMETAL);
if (f) {
mvwprintw(mainwin, y, 0, "%s automatically detect nearby metal.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_DETECTOBS);
if (f) {
mvwprintw(mainwin, y, 0, "%s automatically detect nearby objects.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_ENHANCESEARCH);
if (f) {
mvwprintw(mainwin, y, 0, "%s searching ability is enhanced.", you(lf), isplayer(lf) ? "Your" : "Its");
y++;
}
f = lfhasknownflag(lf, F_DRUNK);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s %s.", you(lf),
isplayer(lf) ? "are" : "is", getdrunktext(f));
y++;
}
// extra dam - can have it multiple times
for (f = lf->flags->first ; f; f = f->next) {
if (f->id == F_EXTRADAM) {
int ndice,nsides,bonus;
char dicebuf[BUFLEN];
char mmbuf[BUFLEN];
char damtypebuf[BUFLEN];
int min = 0,max = 0;
texttodice(f->text, &ndice,&nsides,&bonus);
if ((f->lifetime == FROMOBEQUIP) ||
(f->lifetime == FROMOBHOLD) ||
(f->lifetime == FROMOBACTIVATE) ) {
object_t *obfrom;
obfrom = findobbyid(lf->pack, f->obfrom);
if (obfrom) {
int bonusdam;
sumflags(obfrom->flags, F_BONUS, &bonusdam, NULL, NULL);
bonus += bonusdam;
}
}
if (f->val[0] == NA) {
strcpy(damtypebuf, "damage");
} else {
sprintf(damtypebuf, "%s damage", getdamname(f->val[0]));
}
dicetotext(ndice, nsides, bonus, &min, &max, dicebuf, mmbuf);
if (strcmp(dicebuf, mmbuf)) {
mvwprintw(mainwin, y, 0, "%s deal%s %s (%s) extra %s each hit.", you(lf),
isplayer(lf) ? "" : "s", dicebuf, mmbuf, damtypebuf);
} else {
mvwprintw(mainwin, y, 0, "%s deal%s %s extra %s each hit.", you(lf),
isplayer(lf) ? "" : "s", dicebuf, damtypebuf);
}
y++;
}
}
f = lfhasknownflag(lf, F_EXTRALUCK);
if (f) {
mvwprintw(mainwin, y, 0, "Your luck is being boosted.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_EXTRAMP);
if (f) {
mvwprintw(mainwin, y, 0, "Your mana pool is being boosted.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_EXTRAINFO);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf));
y++;
}
for (f = lf->flags->first ; f ; f = f->next ){
if (f->known && (f->id == F_POISONED)) {
int knownfatal = B_FALSE;
if (getskill(player, SK_FIRSTAID) >= PR_ADEPT) {
if (poisonthreatenslife(lf, f)) {
knownfatal = B_TRUE;
}
}
sprintf(buf, "%s %s sick with %s%s.", you(lf), isplayer(lf) ? "are" : "is",
getpoisonname(f->val[0]),
knownfatal ? ", potentially fatally" : "");
if (lfhasflag(lf, F_EXTRAINFO) || lfhasflag(lf, F_OMNIPOTENT) ||
(getskill(player, SK_FIRSTAID) >= PR_ADEPT) ) {
char buf2[BUFLEN];
sprintf(buf2, " [max %d turns left]", f->lifetime);
strcat(buf, buf2);
}
mvwprintw(mainwin, y, 0, buf);
y++;
}
}
f = lfhasflag(lf, F_NAUSEATED);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s nauseated.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasknownflag(lf, F_PACKATTACK);
if (f && (f->known)) {
sprintf(buf,"%s deal%s extra damage when in a %s pack.", you(lf), isplayer(lf) ? "" : "s",
f->text);
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_PHALANX);
if (f && (f->known)) {
sprintf(buf,"%s gain%s %d extra armour rating when in a %s pack.", you(lf), isplayer(lf) ? "" : "s",
f->val[0], f->text);
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_HEAVYBLOW);
if (f && (f->known)) {
sprintf(buf,"%s%s attacks knock enemies back.", you(lf), getpossessive(you(lf)));
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_QUICKBITE);
if (f && (f->known)) {
sprintf(buf,"%s can bite wounded enemies for extra damage.", you(lf));
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_FREEZINGTOUCH);
if (f && (f->known)) {
strcpy(buf,"The next object you touch will turn to solid ice.");
if (lfhasflag(lf, F_OMNIPOTENT)) {
char buf2[BUFLEN];
sprintf(buf2, " [%d uses left]", f->val[0]);
strcat(buf, buf2);
}
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasflag(lf, F_GRAVBOOSTED);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "Gravity is increased around %s.", you_l(lf));
y++;
}
f = lfhasknownflag(lf, F_DODGES);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s can dodge attacks.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_INVULNERABLE);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s are protected from all physical harm.", you(lf));
y++;
}
f = lfhasflag(lf, F_MAGSHIELD);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s surrounded by a magnetic shield.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasflag(lf, F_PAIN);
if (f && (f->known)) {
if (isdrunk(lf)) {
mvwprintw(mainwin, y, 0, "%s %s in extreme pain, somewhat mitigated by %s inebriation.", you(lf), isplayer(lf) ? "are" : "is", isplayer(lf) ? "your" : "its");
} else {
mvwprintw(mainwin, y, 0, "%s %s in extreme pain, and movement will cause %s damage.", you(lf), isplayer(lf) ? "are" : "is", isplayer(lf) ? "you" : "it");
}
y++;
}
f = lfhasflag(lf, F_PARALYZED);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s paralyzed.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasflag(lf, F_PHOTOMEM);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s do not forget your surroundings.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_REGENERATES);
if (f) {
char regenspeed[BUFLEN];
if (f->val[0] == 1) {
strcpy(regenspeed, "");
} else if (f->val[0] == 2) {
strcpy(regenspeed, " quickly");
} else if (f->val[0] == 3) {
strcpy(regenspeed, " very quickly");
} else { // >= 4
strcpy(regenspeed, " extremely quickly");
}
mvwprintw(mainwin, y, 0, "%s regenerate%s health%s.", you(lf),isplayer(lf) ? "" : "s", regenspeed);
y++;
}
f = lfhasknownflag(lf, F_RESISTMAG);
if (f) {
int mr;
char adjective[BUFLEN];
mr = getmr(lf);
if (mr <= 5) {
strcpy(adjective, "slightly");
} else if (mr <= 10) {
strcpy(adjective, "quite");
} else if (mr <= 15) {
strcpy(adjective, "very");
} else if (mr <= 20) {
strcpy(adjective, "extremely");
} else { // ie. 21 upwards
strcpy(adjective, "incredibly");
}
mvwprintw(mainwin, y, 0, "%s %s %s resistant to magic.", you(lf), isplayer(lf) ? "are" : "is", adjective);
y++;
}
f = lfhasknownflag(lf, F_TREMORSENSE);
if (f) {
mvwprintw(mainwin, y, 0, "%s can 'see' by sensing vibrations around you.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_WINDSHIELD);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s protected from missiles by a cyclonic shield", you(lf), isplayer(lf) ? "are" : "is");
if (isplayer(lf)) {
wprintw(mainwin, " (power %d).",roman(f->val[0]));
} else {
wprintw(mainwin, ".");
}
y++;
}
f = lfhasknownflag(lf, F_TIRED);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s tired.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasflag(lf, F_RISEASGHOST);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s will rise as a ghost after death.", you(lf));
y++;
}
f = lfhasflag(lf, F_STABILITY);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s will not fall on slippery ground.", you(lf));
y++;
}
f = lfhasflag(lf, F_STENCH);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s smell%s terrible.", you(lf), isplayer(lf) ? "" : "s");
y++;
}
if (!isblind(lf)) {
f = lfhasknownflag(lf, F_SEEINDARK);
if (f) {
mvwprintw(mainwin, y, 0, "%s can see in the dark.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_SEEINVIS);
if (f) {
mvwprintw(mainwin, y, 0, "%s can see invisible things.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_XRAYVIS);
if (f) {
mvwprintw(mainwin, y, 0, "%s can see through walls.", you(lf));
y++;
}
}
} else if (mode == 'i') {
object_t *o;
cls();
centre(mainwin, 0, "INVENTORY");
y = 2;
if (lfhasflag(lf, F_NOPACK)) {
mvwprintw(mainwin, y, 0, "It cannot carry anything.");
} else if (countobs(lf->pack)) {
char invtitle[BUFLEN];
float packweight,maxweight,pct;
packweight = getobpileweight(lf->pack);
maxweight = getmaxcarryweight(lf);
pct = (packweight / maxweight) * 100;
sprintf(invtitle, "It is carrying: (%0.0f/%0.0f kg, %0.0f%%)", packweight, maxweight, pct);
mvwprintw(mainwin, y, 0, "%s", invtitle);
y += 2;
for (o = lf->pack->first ; o ; o = o->next) {
getobname(o, buf,o->amt);
getobextrainfo(o, buf2);
mvwprintw(mainwin, y, 0, "%s%s", buf,buf2);
if (o->next && downline(&y, h, "INVENTORY", NULL, prompt, cmdchars, &ch)) {
break;
}
}
} else {
mvwprintw(mainwin, y, 0, "It is not carrying anything.");
}
}
// wait for key
centre(mainwin, h-1, prompt);
if (ch == '\0') {
ch = getch();
}
switch (ch) {
case 27: // ESC
done = B_TRUE;
break;
case '@':
mode = ch;
break;
case 's':
case 'm':
case 'e':
if (showall) mode = ch;
break;
case 'i':
if (showall && !isplayer(lf)) mode = ch;
break;
default:
break;
}
} // end while !done
statdirty = B_TRUE;
needredraw = B_TRUE;
cls(); wrefresh(mainwin);
drawscreen();
wrefresh(gamewin);
wrefresh(statwin);
real_clearmsg(B_TRUE);
//redraw();
}
void tombstone(lifeform_t *lf) {
char pname[BUFLEN];
int y;
char *p, *dummy;
gamemode = GM_GAMEOVER;
getplayernamefull(pname);
// clear screen
cls();
y = 1;
centre(mainwin, y, "R.I.P."); y++;
//printf("%s\n",lf->name);
centre(mainwin, y, "%s",pname); y++;
p = strtok_r(lf->lastdam,"^", &dummy);
if (p) {
if (!strcmp(p, "you")) {
centre(mainwin, y, "Committed suicide.",p); y++;
} else {
centre(mainwin, y, "Killed by %s.",p); y++;
}
p = strtok_r(NULL, "^", &dummy);
while (p) {
centre(mainwin, y, "(%s)",p); y++;
p = strtok_r(NULL, "^", &dummy);
}
} else {
centre(mainwin, y, "Killed by something unknown."); y++;
}
wrefresh(mainwin);
// wait for key...
getch();
// close down graphics ready to quit
// clear windows
delwin(gamewin);
delwin(statwin);
delwin(msgwin);
// clear screen
cls();
// close down curses
curs_set(1);
endwin();
}