This commit is contained in:
Rob Pearce 2011-03-16 04:45:46 +00:00
parent 5f393e02e0
commit 8d05746bf1
23 changed files with 17484 additions and 34744 deletions

128
ai.c
View File

@ -37,7 +37,7 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
int ok = B_FALSE;
if (hasflag(ot->flags, F_AICASTATVICTIM)) {
int range;
range = getspellrange(f->val[0]);
range = getspellrange(f->val[0], getspellpower(lf, f->val[0]));
if ((range == UNLIMITED) || (getcelldist(lf->cell, victim->cell) <= range)) {
if (db) {
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?");
@ -104,6 +104,59 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
return OT_NONE;
}
enum OBTYPE aigetfleespell(lifeform_t *lf) {
flag_t *f;
enum OBTYPE poss[MAXPILEOBS];
int nposs = 0;
int db = B_FALSE;
if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE;
}
for (f = lf->flags->first ; f ; f = f->next) {
if ((f->id == F_CANCAST) || (f->id == F_CANWILL)) {
objecttype_t *ot;
ot = findot(f->val[0]);
if (cancast(lf, f->val[0], NULL)) {
int ok = B_FALSE;
if (hasflag(ot->flags, F_AICASTTOFLEE)) {
if (db) {
dblog(".oO { flee spell possibility: %s }", ot ? ot->name : "?unkownspell?");
}
ok = B_TRUE;
}
if (ok) {
if (aispellok(lf, ot, lf)) {
poss[nposs] = f->val[0];
nposs++;
}
}
} else {
if (db) {
if (ot) {
dblog(".oO { can't cast %s right now (mpcost=%d, i have %d) }",
ot ? ot->name : "?unkownspell?",
getmpcost(ot->id), lf->mp);
} else {
dblog(".oO { can't cast ?unknownspell? right now }");
}
}
}
}
}
// select a random one
if (nposs > 0) {
int sel;
sel = rnd(0,nposs-1);
return poss[sel];
}
return OT_NONE;
}
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob) {
if (hasflag(spelltype->flags, F_AICASTATVICTIM)) {
if (spelllf) *spelllf = victim;
@ -137,7 +190,7 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi
}
}
object_t * aigetwand(lifeform_t *lf) {
object_t *aigetwand(lifeform_t *lf) {
object_t *o;
object_t *poss[MAXPILEOBS];
int nposs = 0;
@ -146,7 +199,7 @@ object_t * aigetwand(lifeform_t *lf) {
if ((o->type->obclass->id == OC_WAND) && (getcharges(o) > 0)) {
// do we know how to use it?
if (hasflag(o->flags, F_AICASTATVICTIM) || hasflag(o->flags, F_AICASTATSELF) || hasflag(o->flags, F_AICASTANYWHERE)) {
// TODO: if castatself, check whether we actually need to (ie. healing etc)
// TODO: if castatself, check whether we actually need to (ie. healing, invis, etc)
poss[nposs] = o;
nposs++;
}
@ -277,7 +330,7 @@ void aimove(lifeform_t *lf) {
target = findlf(lf->cell->map, targid);
if (target) {
if (db) dblog(".oO { my target is lfid %d (%s). }", targid, target->race->name);
if (haslos(lf, target->cell)) {
if (cansee(lf, target)) {
int goingtomove = B_TRUE;
enum OBTYPE spell;
object_t *gun;
@ -523,13 +576,13 @@ void aimove(lifeform_t *lf) {
cell_t *c;
c = lf->los[i];
if (c->lf) {
if (c->lf && cansee(lf, c->lf)) {
if (isplayer(c->lf)) { // TODO: change to if isenemy ?
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
// target them!
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
// tell the player
if (haslos(player, lf->cell)) {
if (cansee(player, lf)) {
makenoise(lf, N_GETANGRY);
}
// then move towards them...
@ -557,9 +610,9 @@ void aimove(lifeform_t *lf) {
for (x = lf->cell->x - 10; x <= lf->cell->x + 10; x++) {
c = getcellat(lf->cell->map, x, y);
// cell exists and we can see it?
if (c && haslos(lf, c)) {
if (c && c->lf && (c->lf != lf) && cansee(lf, c->lf)) {
// player there?
if (c->lf && (c->lf != lf) && !isplayer(c->lf)) {
if (!isplayer(c->lf)) {
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
// target them!
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
@ -586,6 +639,16 @@ void aimove(lifeform_t *lf) {
rest(lf, B_TRUE);
}
// need to train skills?
if (lf->skillpoints || lfhasflag(lf, F_STATGAINREADY)) {
if (canrest(lf)) {
// special case - monsters don't need to actually rest to gain
// skills, although they DO still need to wait until the player
// is out of sight.
enhanceskills(lf);
}
}
// just try to move in a random direction
if (db) dblog(".oO { default - moving randomly }");
dorandommove(lf, B_NOBADMOVES);
@ -604,11 +667,32 @@ int aipickup(lifeform_t *lf, object_t *o) {
return B_FALSE;
}
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target) {
switch (o->type->id) {
case OT_POT_INVIS:
case OT_WAND_INVIS:
if (lfhasflag(target, F_INVISIBLE)) {
return B_FALSE;
}
break;
case OT_POT_INVULN:
if (lfhasflag(target, F_INVULNERABLE)) {
return B_FALSE;
}
break;
default:
break;
}
return B_TRUE;
}
int aispellok(lifeform_t *lf, objecttype_t *st, lifeform_t *victim) {
if ((st->id == OT_S_BLINDNESS) && isblind(victim)) {
return B_FALSE;
}
if ((st->id == OT_S_INVISIBILITY) && lfhasflag(victim, F_INVISIBLE)) {
return B_FALSE;
}
if ((st->id == OT_S_PAIN) && lfhasflag(victim, F_PAIN)) {
return B_FALSE;
}
@ -806,3 +890,31 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
return B_FALSE;
}
// try to use an item with the given flag on ourself.
// returns B_FALSE if successful
int useitemwithflag(lifeform_t *lf, enum FLAG whichflag) {
object_t *o;
for (o = lf->pack->first ; o ; o = o->next) {
if (hasflag(o->flags, whichflag)) {
if (aiobok(lf, o, lf)) {
if (o->type->obclass->id == OC_POTION) {
if (canquaff(lf, o)) {
quaff(lf, o);
return B_FALSE;
}
} else if (o->type->obclass->id == OC_SCROLL) {
if (!readsomething(lf, o)) {
return B_FALSE;
}
} else if ((o->type->obclass->id == OC_WAND) && getcharges(o)) {
// if wand, use it on ourself
if (!operate(lf, o, lf->cell)) {
return B_FALSE;
}
}
}
}
}
// failed to use an item
return B_TRUE;
}

3
ai.h
View File

@ -1,11 +1,14 @@
#include "defs.h"
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim);
enum OBTYPE aigetfleespell(lifeform_t *lf);
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob);
object_t * aigetwand(lifeform_t *lf);
void aimove(lifeform_t *lf);
int aipickup(lifeform_t *lf, object_t *o);
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target);
int aispellok(lifeform_t *lf, objecttype_t *st, lifeform_t *victim);
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op);
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op);
int lookforobs(lifeform_t *lf, int covetsonly);
int useitemwithflag(lifeform_t *lf, enum FLAG whichflag);

View File

@ -125,7 +125,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
if (!wep) {
if (isplayer(lf)) {
msg("You cannot attack!");
} else if (haslos(player, lf->cell)) {
} else if (cansee(player, lf)) {
//msg("%s looks like it wants to attack!",attackername);
}
if (op) killobpile(op);
@ -289,7 +289,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
}
} else {
if (haslos(player, lf->cell) || isplayer(victim)) {
if (cansee(player, lf) || isplayer(victim)) {
char withwep[BUFLEN];
char attackverb[BUFLEN];
char nodamstr[BUFLEN];
@ -298,7 +298,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
sprintf(buf, "%s",attackername);
capitalise(buf);
if (wep && !unarmedflag && (lf->race->id != R_DANCINGWEAPON) && haslos(player, lf->cell)) {
if (wep && !unarmedflag && (lf->race->id != R_DANCINGWEAPON) && cansee(player, lf)) {
sprintf(withwep, " with %s", wepname);
} else {
strcpy(withwep, "");
@ -320,7 +320,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
if (willheal) {
if (haslos(player, victim->cell)) {
if (cansee(player, victim)) {
flag_t *f;
msg("%s is healed!",victimname);
f = hasflag(wep->flags, F_BALANCE);
@ -341,7 +341,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
(lf == victim) ? "using" : "weilding",
wepname);
} else {
char attackername2[BUFLEN];
strcpy(buf, attackername2);
}
@ -375,7 +374,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
dam = rolldie(f->val[0], f->val[1]) + f->val[2];
real_getlfname(lf, lfname, B_FALSE);
losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE);
if (isplayer(victim) || haslos(player, victim->cell)) {
if (isplayer(victim) || cansee(player, victim)) {
msg("%s bites %s!", lfname, victimname);
}
}
@ -399,7 +398,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
char damstring[BUFLEN];
sprintf(damstring, "a %s pack", f->text);
losehp(victim, f->val[0], f->val[1], lf, damstring);
if (isplayer(victim) || haslos(player, victim->cell)) {
if (isplayer(victim) || cansee(player, victim)) {
msg("The %s pack attacks %s!", f->text, victimname);
}
}
@ -410,7 +409,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
if (aidb) dblog(".oO { i missed! }");
// announce it
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
if (isplayer(lf) || haslos(player, lf->cell)) {
if (isplayer(lf) || cansee(player, lf)) {
sprintf(buf, "%s",attackername);
msg("%s%s magnetic shield repels %s%s attack.", victimname, getpossessive(victimname),
@ -420,7 +419,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
if (isplayer(lf)) {
msg("You miss %s.", victimname);
} else {
if (haslos(player, lf->cell)) {
if (cansee(player, lf)) {
// capitalise first letter
sprintf(buf, "%s",attackername);
@ -497,7 +496,7 @@ int attackob(lifeform_t *lf, object_t *o) {
if (!wep) {
if (isplayer(lf)) {
msg("You cannot attack!");
} else if (haslos(player, lf->cell)) {
} else if (cansee(player, lf)) {
//msg("%s looks like it wants to attack!",attackername);
}
if (!isplayer(lf)) {
@ -549,7 +548,7 @@ int attackob(lifeform_t *lf, object_t *o) {
}
msg("You %s %s.", getattackverb(damtype[i], dam[i], maxhp),
obname, extradambuf);
} else if (haslos(player, lf->cell)) {
} else if (cansee(player, lf)) {
char withwep[BUFLEN];
if (wep && !unarmed && !isblind(player)) { // announce weapon used
@ -564,7 +563,7 @@ int attackob(lifeform_t *lf, object_t *o) {
youhear(lf->cell, "sounds of fighting");
}
if ((i == 0) && unarmedflag) {
if ((i == 0) && unarmedflag && hasflag(o->flags, F_HARD)) {
char buf[BUFLEN];
sprintf(buf, "punching %s", obname);
if ( losehp(lf, 1, DT_BASH, lf, buf)) {
@ -582,8 +581,12 @@ int attackob(lifeform_t *lf, object_t *o) {
// special weapon effects
wepeffects(wep, obloc);
if (unarmedflag) {
// touch effects
touch(lf, o);
} else {
// weapon gets damaged ?
if (!unarmedflag && wep && (ndam > 0)) {
if (wep && (ndam > 0)) {
switch (damtype[0]) {
case DT_PIERCE:
case DT_SLASH:
@ -594,8 +597,8 @@ int attackob(lifeform_t *lf, object_t *o) {
break;
}
}
}
// hitting an object with our hands will hurt
// get rid of temp unarmed object pile
if (op) {
@ -1097,6 +1100,11 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
ev = getevasion(victim);
acc -= ev;
// modify if we can't see the victim
if (!cansee(lf, victim)) {
acc -= 50;
}
// metal weapon versus magnetic shield?
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
acc -= 45;
@ -1206,7 +1214,7 @@ void wepeffects(object_t *wep, cell_t *where) {
if (isplayer(owner)) {
msg("Your %s blasts %s!",noprefix(obname),victimname);
f->known = B_TRUE;
} else if (haslos(player, owner->cell)) {
} else if (cansee(player, owner)) {
msg("%s%s %s blasts %s!",buf, getpossessive(buf),noprefix(obname),victimname);
f->known = B_TRUE;
}

55
defs.h
View File

@ -98,6 +98,7 @@ enum LFCONDITION {
#define MORESTRING "--More--"
#define SOLDOUTSTRING "--SOLD OUT--"
// hunger constant
#define HUNGERCONST 10000
@ -356,9 +357,10 @@ enum DAMTYPE {
DT_UNARMED = 20,
DT_LIGHT = 21,
DT_CRUSH = 22,
DT_NONE = 23, // for direclty dealt damage, not really any type
DT_FALL = 23,
DT_NONE = 24, // for direclty dealt damage, not really any type
};
#define MAXDAMTYPE 24
#define MAXDAMTYPE 25
// Object Classes
enum OBCLASS {
@ -561,6 +563,7 @@ enum OBTYPE {
OT_POT_GASEOUSFORM,
OT_POT_HEALING,
OT_POT_HEALINGMIN,
OT_POT_INVIS,
OT_POT_INVULN,
OT_POT_MAGIC,
OT_POT_OIL,
@ -587,7 +590,7 @@ enum OBTYPE {
OT_SCR_ENCHANT,
OT_SCR_FREEZEOB,
OT_SCR_REMOVECURSE,
OT_SCR_TELEPORTRND,
OT_SCR_TELEPORT,
OT_SCR_TURNUNDEAD,
OT_SCR_WISH,
// SPELLBOOKS
@ -630,12 +633,12 @@ enum OBTYPE {
OT_SB_GASEOUSFORM,
OT_SB_KNOCK,
OT_SB_INSCRIBE,
OT_SB_INVISIBILITY,
OT_SB_LIGHT,
OT_SB_DARKNESS,
OT_SB_PASSWALL,
OT_SB_PETRIFY,
OT_SB_POLYMORPH,
OT_SB_POLYMORPHRND,
// -- summoning
OT_SB_CREATEMONSTER,
// -- translocation
@ -643,7 +646,6 @@ enum OBTYPE {
OT_SB_DISPERSAL,
OT_SB_GATE,
OT_SB_TELEPORT,
OT_SB_TELEPORTRND,
// -- wild can't be learned from books
// spells
// -- allomancy
@ -694,6 +696,7 @@ enum OBTYPE {
OT_S_ENCHANT,
OT_S_GASEOUSFORM,
OT_S_INSCRIBE,
OT_S_INVISIBILITY,
OT_S_KNOCK,
OT_S_LIGHT,
OT_S_DARKNESS,
@ -708,7 +711,6 @@ enum OBTYPE {
OT_S_DISPERSAL,
OT_S_GATE,
OT_S_TELEPORT,
OT_S_TELEPORTRND,
// -- wild
OT_S_MANASPIKE,
OT_S_DETONATE,
@ -730,9 +732,11 @@ enum OBTYPE {
// wands
OT_WAND_COLD,
OT_WAND_DETONATION,
OT_WAND_DISPERSAL,
OT_WAND_FIRE,
OT_WAND_FIREBALL,
OT_WAND_HASTE,
OT_WAND_INVIS,
OT_WAND_KNOCK,
OT_WAND_LIGHT,
OT_WAND_POLYMORPH,
@ -835,11 +839,13 @@ enum OBTYPE {
OT_SHIELD,
OT_SHIELDLARGE,
// rings
OT_RING_INVIS,
OT_RING_INVULN,
OT_RING_MPREGEN,
OT_RING_PROTFIRE,
OT_RING_REGENERATION,
OT_RING_RESISTMAG,
OT_RING_SEEINVIS,
// animal weapons
OT_CLAWS,
OT_FISTS,
@ -953,7 +959,8 @@ enum FLAG {
F_STACKABLE, // can stack multiple objects togethr
F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money)
F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold)
F_CONTAINSOB, // for vending machiens. text is an object it contains.
F_CONTAINSOB, // for vending machiens. v0 is ob letter
// text is an object it contains.
// for items in shops
F_SHOPITEM, // causes shops to show this item as identified
F_VALUE, // how much an item is worth (over its base weight+material)
@ -1016,7 +1023,10 @@ enum FLAG {
// technology flags
F_TECHLEVEL, // v0 is a PR_xxx enum for tech usage skill
// what can you do with this object?
F_EDIBLE, // you can eat this. val2 = nutrition. 100 = a meal
F_TAINTED, // will give food poisoning if you eat/drink it
F_EDIBLE, // you can eat this. val1 = nutrition. 100 = a meal
// -1 means "nutrition is weight x abs(val1)"
F_DRINKABLE, // you can drink this. val1 = nutrition. 100 = a meal
// -1 means "nutrition is weight x abs(val1)"
F_OPERABLE, // can operate?
F_POURABLE, // can pour?
@ -1036,6 +1046,7 @@ enum FLAG {
F_MAPLINK, // val0 = map to link to. optional v1/v2 = x/y
// ob interaction flags
F_HARD, // object is hard (ie. punching it will hurt!)
F_SHARP, // does damage when you step on it. v0/1 are min/max dam
F_SLIPPERY, // you might slip when stepping on it. v0 is amt
F_SLIPMOVE, // if someone slips on this, it will move to an adj cell
@ -1082,6 +1093,7 @@ enum FLAG {
F_NODIECONVERTTEXT, // don't anounce when this object changes
// scroll flags
F_LINKSPELL, // val0 = spell this scroll will cast when read
// v1 = spell power
// ob identification flags
F_HASHIDDENNAME, // whether this object class has a hidden name
F_IDENTIFIED, // whether this object is fully identified
@ -1090,6 +1102,7 @@ enum FLAG {
// magic
F_SPELLSCHOOL, // val0 = SPELLSCHOOL enum
F_SPELLLEVEL, // val0 = difficulty level of spell
F_MAXPOWER, // val0 = max power of this spell (1-10)
F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2
//F_SPELLLETTER, // text[0] = letter to cast this spell
F_AICASTATVICTIM, // hints for AI to cast spells
@ -1097,9 +1110,12 @@ enum FLAG {
F_AICASTATSELF, // hints for AI to cast spells
F_AICASTNEXTTOVICTIM, // hints for AI to cast spells
F_AICASTANYWHERE, // hints for AI to cast spells
F_AIBOOSTITEM, // ai will use this item to boost/buff itself
F_AICASTTOFLEE, // hints for AI to cast spells
F_AIBOOSTITEM, // ai will use this item to boost/buff itself.
// if using this on wands, update aiobok() !
F_AIHEALITEM, // ai will use this item when low on hp
F_AIFLEEITEM, // ai will use this item when fleeing
// if using this on wands, update aiobok() !
// object _AND_ lifeform flags
F_NOSTRDAMMOD, // this object/lf does not have attacks modified
// using their strength
@ -1171,6 +1187,9 @@ enum FLAG {
F_ORIGRACE, // original player race (if you polymorphed)
F_ORIGJOB, // original player job (if you polymorphed)
F_POLYMORPHED, // lf has been polymorphed
F_SHORTCUT, // spell keyboard shortcut.
// v0=slot (0-9)
// text=spell text
// for monsters
F_INSECT, // this race is classed as an insect
F_ANIMAL, // this race is classed as an animal
@ -1207,13 +1226,14 @@ enum FLAG {
F_GRABBEDBY,// you've been grabbed by lf id v0
F_GRABBING, // you are grabbing lf id v0
F_HEAVYBLOW, // next attack is a heavy blow
F_INVISIBLE, // lifeform is invisible
F_INVULNERABLE,// immune to most damage
F_QUICKBITE, // deals v0 d d1 + d2 damage when you hit a bleeding victim
// (bypasses armour)
F_GRAVBOOSTED,// cannot walk or throw stuff
F_PAIN, // take damage if you walk
F_PARALYZED,// cannot do anything
F_FROZEN, // made of ice
F_INVULNERABLE,// immune to most damage
F_LEVITATING, // like flying but uncontrolled
F_MAGSHIELD,// magnetic shield
F_NAUSEATED, // lf has a stench penalty of v0 (-v0*10 to hit).
@ -1224,6 +1244,7 @@ enum FLAG {
F_RESISTMAG, // immune to most magic effects
F_MPREGEN, // regenerate MP at val0 per turn
F_SEEINDARK, // nightvis range is val0
F_SEEINVIS, // can see invisible things
F_SEEWITHOUTEYES, // doesn't need eyes to see
F_STABILITY, // doesn't slip over
F_STENCH, // creatures within v0 gain f_nauseated = v1
@ -1248,7 +1269,11 @@ enum FLAG {
F_EVASION, // % chance of evading an attack
// healing
F_STATGAINREADY, // ready to increase str/int etc. v2 is how many times
// we can do it.
F_RESTING, // are we resting? cleared on any action other than rest.
// v2 = if not, NA it is the training counter.
// when it hits 0, you finish trainign.
//
F_RUNNING, // are we running?
// nutrition
@ -1378,6 +1403,7 @@ enum ERROR {
E_GRABBEDBY = 33,
E_CANTMOVE = 34,
E_NOTKNOWN = 35,
E_TOOPOWERFUL = 36,
};
@ -1399,6 +1425,7 @@ enum COMMAND {
CMD_LOOKAROUND,
CMD_LOOKHERE,
CMD_MAGIC,
CMD_MEMMAGIC,
CMD_MSGHIST,
CMD_OPERATE,
CMD_PICKLOCK,
@ -1494,6 +1521,7 @@ typedef struct lifeform_s {
struct race_s *race;
int level;
long xp;
int skillpoints;
int hp,maxhp;
int mp,maxmp;
int alive;
@ -1579,8 +1607,10 @@ enum SKILL {
SK_ATHLETICS,
SK_LOCKPICKING,
SK_RESEARCH,
SK_SPELLCASTING,
SK_TECHUSAGE,
};
#define MAXSKILLS 5
// proficiency levels
enum SKILLLEVEL {
@ -1665,6 +1695,7 @@ typedef struct object_s {
enum OBMOD {
OM_FLAMING,
OM_FROZEN,
OM_HEADLESS,
OM_MASTERWORK,
OM_SHODDY,
@ -1681,7 +1712,9 @@ enum BRAND {
BR_INTELLIGENCE,
BR_KNOWLEDGE,
BR_LEVITATION,
BR_MAGRESIST,
BR_FEATHERFALL,
BR_ANTIMAG,
BR_CONCEALMENT,
BR_SHARPNESS,
BR_PYROMANIA,
BR_REVENGE,

6
doc/add_skill.txt Normal file
View File

@ -0,0 +1,6 @@
defs.h:
add SK_xxx
inc MAXSKILLS
lf.c:
add addskill()

30
flag.c
View File

@ -12,6 +12,8 @@ extern int gamestarted;
extern int needredraw;
extern int statdirty;
extern lifeform_t *player;
flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text) {
return addflag_real(fp, id, val1, val2, val3, text, PERMENANT, B_KNOWN, -1);
}
@ -93,7 +95,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
if (announceflaggain(f->pile->owner, f)) {
interrupt(f->pile->owner);
f->known = B_TRUE;
if (f->obfrom) { // ooooooo it's getting -1 ?!?!?!?
if (f->obfrom) {
object_t *ob;
ob = findobbyid(f->pile->owner->pack, f->obfrom);
@ -116,6 +118,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
}
}
}
// player flags which cause a redraw
if (isplayer(f->pile->owner)) {
switch (f->id) {
case F_BLIND:
@ -124,6 +127,17 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
case F_TIRED:
case F_FASTMOVE:
case F_SLOWMOVE:
case F_INVISIBLE:
case F_SEEINVIS:
doredraw = B_TRUE;
break;
default:
break;
}
} else if (haslos(player, f->pile->owner->cell)) {
// monster flags which cause a redraw
switch (f->id) {
case F_INVISIBLE:
doredraw = B_TRUE;
break;
default:
@ -259,6 +273,8 @@ void killflag(flag_t *f) {
lf = f->pile->owner;
// player flags which cause a redraw
if (lf) {
if (isplayer(lf)) {
switch (f->id) {
case F_BLIND:
@ -267,11 +283,23 @@ void killflag(flag_t *f) {
case F_TIRED:
case F_FASTMOVE:
case F_SLOWMOVE:
case F_INVISIBLE:
case F_SEEINVIS:
doredraw = B_TRUE;
break;
default:
break;
}
} else if (haslos(player, lf->cell)) {
// monster flags which cause a redraw
switch (f->id) {
case F_INVISIBLE:
doredraw = B_TRUE;
break;
default:
break;
}
}
}
// notify

650
io.c

File diff suppressed because it is too large Load Diff

4
io.h
View File

@ -42,6 +42,7 @@ void doinventory(obpile_t *op);
void doknowledgelist(void);
void dolook(cell_t *where);
void domagic(enum OBTYPE spellid, int cellx, int celly);
void domemmagic(void);
void domsghist(void);
void dooperate(obpile_t *op);
int dopickup(obpile_t *op);
@ -69,13 +70,14 @@ void drawscreen(void);
void drawstatus(void);
int drop(object_t *o, int count);
char getchoice(prompt_t *prompt);
char getchoicestr(prompt_t *prompt);
char getchoicestr(prompt_t *prompt, int useshortcuts);
int getkey(void);
void handleinput(void);
void doheading(WINDOW *win, int *y, int x, char *what);
void initgfx(void);
void initprompt(prompt_t *p, char *q1);
int keycodetokey(int keycode);
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2);
void more(void);
void warn(char *format, ... );
void msg(char *format, ... );

557
lf.c

File diff suppressed because it is too large Load Diff

8
lf.h
View File

@ -13,20 +13,24 @@ void bleed(lifeform_t *lf);
int calcxp(lifeform_t *lf);
int calcxprace(enum RACE rid);
int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost);
int candrink(lifeform_t *lf, object_t *o);
int caneat(lifeform_t *lf, object_t *o);
int canhear(lifeform_t *lf, cell_t *c);
int canpickup(lifeform_t *lf, object_t *o, int amt);
int canpush(lifeform_t *lf, object_t *o, int dir);
int canquaff(lifeform_t *lf, object_t *o);
int canrest(lifeform_t *lf);
int cansee(lifeform_t *viewer, lifeform_t *viewee);
int canwear(lifeform_t *lf, object_t *o, enum BODYPART where);
int canweild(lifeform_t *lf, object_t *o);
int cantakeoff(lifeform_t *lf, object_t *o);
int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell);
int countmoney(lifeform_t *lf);
void die(lifeform_t *lf);
void dumplf(void);
void dumpxp(void);
int eat(lifeform_t *lf, object_t *o);
void enhanceskills(lifeform_t *lf);
object_t *eyesshaded(lifeform_t *lf);
void fightback(lifeform_t *lf, lifeform_t *attacker);
job_t *findjob(enum JOB jobid);
@ -135,6 +139,7 @@ int isgenius(lifeform_t *lf);
int isimmobile(lifeform_t *lf);
flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt);
int isingunrange(lifeform_t *lf, cell_t *where);
int ismaxedskill(lifeform_t *lf, enum SKILL skid);
int ispeaceful(lifeform_t *lf);
int isplayer(lifeform_t *lf);
int ispolymorphed(lifeform_t *lf);
@ -159,7 +164,7 @@ void precalclos(lifeform_t *lf);
int push(lifeform_t *lf, object_t *o, int dir);
void relinklf(lifeform_t *src, map_t *dst);
int rest(lifeform_t *lf, int onpurpose);
void startresting(lifeform_t *lf);
void startresting(lifeform_t *lf, int willtrain);
int rollcon(enum CONBRACKET bracket);
int rolldex(enum DEXBRACKET bracket);
int rolliq(enum IQBRACKET bracket);
@ -189,7 +194,6 @@ void turneffectslf(lifeform_t *lf);
int touch(lifeform_t *lf, object_t *o);
int unweild(lifeform_t *lf, object_t *o);
int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where);
int useitemwithflag(lifeform_t *lf, enum FLAG whichflag);
int usestairs(lifeform_t *lf, object_t *o);
int validateraces(void);
int wear(lifeform_t *lf, object_t *o);

48908
log.txt

File diff suppressed because it is too large Load Diff

15
map.c
View File

@ -2034,13 +2034,26 @@ int iswallindir(cell_t *cell, int dir) {
void makedoor(cell_t *cell) {
object_t *o;
map_t *m;
m = cell->map;
setcelltype(cell, getemptycelltype(cell->map->habitat));
o = addob(cell->obpile, "wooden door");
if (o && (rnd(1,2) == 1)) {
opendoor(NULL, o);
} else {
int chance;
// door is closed - lock it?
if (rnd(1,3) == 1) {
chance = rolldie(1,6); // ie. 1 in 6
// ie. at dungeon lev 10, chance is 2 in 6
// at dungeon lev 20, chance is 3 in 6
// ...
// at dungeon lev 50, chance is 5 in 6
chance -= (m->depth / 10);
if (chance <= 1) {
addflag(o->flags, F_LOCKED, B_TRUE, NA, NA, NULL);
}
}

34
move.c
View File

@ -350,7 +350,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher) {
int seen;
getlfname(lf,lfname);
if (haslos(player, lf->cell)) {
if (cansee(player, lf)) {
seen = B_TRUE;
} else {
seen = B_FALSE;
@ -451,7 +451,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
losehp(lf, rolldie(2,4)+2, DT_DIRECT, NULL, "extreme pain");
if (isplayer(lf)) {
msg("Your body is wracked with pain!");
} else if (haslos(player, lf->cell)) {
} else if (cansee(player, lf)) {
msg("%s convulses in pain!",lfname);
}
}
@ -720,7 +720,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
if (lf->controller == C_PLAYER) {
msg("You open %s.",obname);
} else {
if (haslos(player, lf->cell) && isadjacent(lf->cell, doorcell)) {
if (cansee(player, lf) && isadjacent(lf->cell, doorcell)) {
getlfname(lf, buf);
capitalise(buf);
msg("%s opens %s.",buf, obname);
@ -790,10 +790,9 @@ int closedoor(lifeform_t *lf, object_t *o) {
return B_TRUE;
}
// impassable object other than the door?
// any object other than the door?
for (oo = cell->obpile->first ; oo ; oo = oo->next) {
if (oo != o) {
if (hasflag(oo->flags, F_IMPASSABLE)) {
if (lf && isplayer(lf)) {
char inwayname[BUFLEN];
getobname(oo, inwayname, oo->amt);
@ -802,7 +801,6 @@ int closedoor(lifeform_t *lf, object_t *o) {
return B_TRUE;
}
}
}
f = hasflag(o->flags, F_OPEN);
if (!f) {
@ -820,7 +818,7 @@ int closedoor(lifeform_t *lf, object_t *o) {
if (lf->controller == C_PLAYER) {
msg("You close %s.", obname);
} else {
if (haslos(player, lf->cell) && isadjacent(lf->cell, cell)) {
if (cansee(player, lf) && isadjacent(lf->cell, cell)) {
getlfname(lf, buf);
capitalise(buf);
msg("%s closes %s.",buf, obname);
@ -867,7 +865,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
if (!dst || !haslof(lf, dst)) {
return B_TRUE;
}
if (isplayer(lf) || haslos(player, lf->cell)) {
if (isplayer(lf) || cansee(player, lf)) {
char buf[BUFLEN];
getlfname(lf, buf);
msg("%s %s pulled %s!", buf, isplayer(lf) ? "are" : "is",
@ -879,7 +877,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
}
// teleport somewhere, along with puffs of smoke etc
int teleportto(lifeform_t *lf, cell_t *c) {
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
char buf[BUFLEN];
// can't teleport on top of something else
@ -890,16 +888,22 @@ int teleportto(lifeform_t *lf, cell_t *c) {
return B_TRUE;
}
if (!isplayer(lf) && haslos(player, lf->cell)) {
if (!isplayer(lf) && cansee(player, lf)) {
getlfname(lf, buf);
if (wantsmoke) {
msg("%s disappears in a cloud of smoke!", buf);
} else {
msg("%s vanishes!", buf);
}
}
if (wantsmoke) {
addob(lf->cell->obpile, "cloud of smoke");
}
movelf(lf, c);
// addob(lf->cell->obpile, "cloud of smoke");
if (isplayer(lf)) {
msg("Suddenly, your surroundings appear different!");
} else if (haslos(player, lf->cell)) {
} else if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s appears!", buf);
}
@ -929,7 +933,7 @@ int trymove(lifeform_t *lf, int dir) {
if (o->blessed == B_CURSED) {
if (lfhasflag(lf, F_ANIMAL)) {
if (!isairborne(lf)) {
if (haslos(player, lf->cell)) {
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf,lfname);
getobname(o, buf, o->amt);
@ -975,7 +979,7 @@ int trymove(lifeform_t *lf, int dir) {
case E_WALLINWAY:
if (isplayer(lf)) {
msg("Ouch! You %s into a wall.", getmoveverb(lf));
} else if (haslos(player, lf->cell)) {
} else if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s %ss into a wall.", buf, getmoveverb(lf));
}
@ -1013,7 +1017,7 @@ int trymove(lifeform_t *lf, int dir) {
taketime(lf, getmovespeed(lf));
}
} else {
if (haslos(player, lf->cell)) {
if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s %ss into a wall.", buf, getmoveverb(lf));
}
@ -1066,7 +1070,7 @@ int trymove(lifeform_t *lf, int dir) {
case E_GRAVBOOSTED:
if (isplayer(lf)) {
msg("You try to move but are unable to lift your feet!");
} else if (haslos(player, lf->cell)) {
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s tries to move but is unable to lift its feet!",lfname);

2
move.h
View File

@ -19,7 +19,7 @@ int movetowards(lifeform_t *lf, cell_t *dst);
int opendoorat(lifeform_t *lf, cell_t *c);
int opendoor(lifeform_t *lf, object_t *o);
int pullnextto(lifeform_t *lf, cell_t *c);
int teleportto(lifeform_t *lf, cell_t *c);
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke);
int trymove(lifeform_t *lf, int dir);
int tryrun(lifeform_t *lf, int dir);
int willmove(lifeform_t *lf, int dir, enum ERROR *error);

14
nexus.c
View File

@ -337,7 +337,7 @@ void donextturn(map_t *map) {
// pre-calculate line of sight for this lifeform
precalclos(who);
if (isplayer(who) || haslos(player, who->cell)) {
if (isplayer(who) || cansee(player, who)) {
needredraw = B_TRUE;
}
@ -391,7 +391,7 @@ void donextturn(map_t *map) {
if (hasflag(player->flags, F_RESTING)) {
// ooo is this right ?
needredraw = B_FALSE;
} else if (isdead(who) || haslos(player, who->cell)) {
} else if (isdead(who) || cansee(player, who)) {
needredraw = B_TRUE;
}
@ -499,13 +499,15 @@ void initcommands(void) {
addcommand(CMD_DROP, 'd', "Drop an item.");
addcommand(CMD_DROPMULTI, 'D', "Drop multiple items.");
addcommand(CMD_EAT, 'e', "Eat something.");
addcommand(CMD_EAT, 'E', "Enhance your skills.");
addcommand(CMD_MAGIC, 'm', "Use magic or abilities.");
addcommand(CMD_MEMMAGIC, 'M', "Memorise a magic shortcut");
addcommand(CMD_OPERATE, 'o', "Operate a tool/wand/device.");
addcommand(CMD_PICKLOCK, 'p', "Pick a lock.");
addcommand(CMD_POUR, 'P', "Pour a potion onto something.");
addcommand(CMD_QUAFF, 'q', "Quaff (drink) a potion.");
addcommand(CMD_READ, 'r', "Read a scroll/book.");
addcommand(CMD_RESTFULL, 'R', "Rest until healed.");
addcommand(CMD_RESTFULL, 'R', "Rest until healed, or train your skills.");
addcommand(CMD_TAKEOFF, 'T', "Take off an item of clothing/jewelery.");
addcommand(CMD_WEILD, 'w', "Weild a weapon.");
addcommand(CMD_WEAR, 'W', "Wear an item of clothing/jewelery.");
@ -624,6 +626,7 @@ int rollmpdice(lifeform_t *lf) {
flag_t *f;
int ndice, plus;
int roll;
float mod;
f = hasflag(lf->flags, F_MPDICE);
if (f) {
@ -633,7 +636,12 @@ int rollmpdice(lifeform_t *lf) {
} else {
return 0;
}
mod = getstatmod(lf, A_IQ);
if (mod > 0) mod *= 2;
roll = rolldie(ndice, 4) + plus;
roll = roll + (int)((float)roll * (mod/100));
return roll;
}

474
objects.c

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL ma
void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype);
//void adjustprice(objecttype_t *ot, float *price );
void appendinscription(object_t *o, char *text);
void applyobmod(object_t *o, obmod_t *om);
int blessob(object_t *o);
void brightflash(cell_t *centre, int range, lifeform_t *immunelf);
object_t *canstackob(obpile_t *op, object_t *match);
@ -84,6 +85,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
char *getrandomob(map_t *map, char *buf);
char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf);
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf);
int getobrarity(object_t *o);
enum SPELLSCHOOL getschool(enum OBTYPE sid);
char *getschoolname(enum SPELLSCHOOL sch);
int getshatterdam(object_t *o);
@ -92,6 +94,7 @@ int getthrowdam(object_t *o);
int hasedibleob(obpile_t *op);
object_t *hasknownob(obpile_t *op, enum OBTYPE oid);
object_t *hasob(obpile_t *op, enum OBTYPE oid);
object_t *hasobletter(obpile_t *op, char letter);
object_t *hasobofclass(obpile_t *op, enum OBCLASS cid);
object_t *hasobmulti(obpile_t *op, enum OBTYPE *oid, int noids);
object_t *hasobwithflag(obpile_t *op, enum FLAG flagid);

2
save.c
View File

@ -169,6 +169,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
fscanf(f, "dex: %d/%d\n",&l->att[A_DEX],&l->baseatt[A_DEX]);
fscanf(f, "int: %d/%d\n",&l->att[A_IQ],&l->baseatt[A_IQ]);
fscanf(f, "xp: %ld\n",&l->xp);
fscanf(f, "skp: %d\n",&l->skillpoints);
fscanf(f, "contr: %d\n",&l->controller);
fscanf(f, "hp: %d/%d\n",&l->hp, &l->maxhp);
fscanf(f, "mp: %d/%d\n",&l->mp, &l->maxmp);
@ -624,6 +625,7 @@ int savelf(FILE *f, lifeform_t *l) {
fprintf(f, "dex: %d/%d\n",l->att[A_DEX],l->baseatt[A_DEX]);
fprintf(f, "int: %d/%d\n",l->att[A_IQ],l->baseatt[A_IQ]);
fprintf(f, "xp: %ld\n",l->xp);
fprintf(f, "skp: %d\n",l->skillpoints);
fprintf(f, "contr: %d\n",l->controller);
fprintf(f, "hp: %d/%d\n",l->hp, l->maxhp);
fprintf(f, "mp: %d/%d\n",l->mp, l->maxmp);

452
spell.c

File diff suppressed because it is too large Load Diff

10
spell.h
View File

@ -3,16 +3,18 @@
#include "defs.h"
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target);
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer);
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer);
void fizzle(lifeform_t *caster);
int getiqreq(enum OBTYPE oid);
//int getiqreq(enum OBTYPE oid);
int getmpcost(enum OBTYPE oid);
int getspellduration(int min,int max,int blessed);
int getspelllevel(enum OBTYPE spellid);
int getspellmaxpower(enum OBTYPE spellid);
int getspellpower(lifeform_t *lf, enum OBTYPE spellid);
enum SPELLSCHOOL getspellschool(enum OBTYPE spellid);
int getspellrange(enum OBTYPE spellid);
int getspellrange(enum OBTYPE spellid, int power);
void pullobto(object_t *o, lifeform_t *lf);
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid);
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid, int power);
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
#endif

67
text.c
View File

@ -230,6 +230,73 @@ char *noprefix(char *obname) {
}
}
char *numtotext(int num, char *buf) {
switch (num) {
case 1:
sprintf(buf, "a");
break;
case 2:
sprintf(buf, "two");
break;
case 3:
sprintf(buf, "three");
break;
case 4:
sprintf(buf, "four");
break;
case 5:
sprintf(buf, "five");
break;
case 6:
sprintf(buf, "six");
break;
case 7:
sprintf(buf, "seven");
break;
case 8:
sprintf(buf, "eight");
break;
case 9:
sprintf(buf, "nine");
break;
case 10:
sprintf(buf, "ten");
break;
default:
sprintf(buf, "%d",num);
break;
}
return buf;
}
// convert number to roman numerals
// only copes with 1-10
char *roman(int num) {
switch (num) {
case 1:
return "I";
case 2:
return "II";
case 3:
return "III";
case 4:
return "IV";
case 5:
return "V";
case 6:
return "VI";
case 7:
return "VII";
case 8:
return "VIII";
case 9:
return "IX";
case 10:
return "X";
}
return "";
}
void splittime(int *hours, int *mins, int *secs) {
long left;
left = curtime;

2
text.h
View File

@ -11,6 +11,8 @@ char *getweighttext(float weight, char *buf);
int isvowel(char c);
char *makeplural(char *text);
char *noprefix(char *obname);
char *numtotext(int num, char *buf);
char *roman(int num);
void splittime(int *hours, int *mins, int *secs);
char *strrep(char *text, char *oldtok, char *newtok, int *rv);
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv);