- [+] bug: when running, i jumped into deep water!

- [+] instead of evasion skill giving a fixed boost, make it change the
      evasion bonus due to xp level.
* [+] give monsters free moves when you go back onto a level, BEFORE
      placing the player.
- [+] fix dungeon code to eliminate nonlinked rooms
    - [+] force all vaults to be at least 3 squares away from map edges
    * [+] implement flood-fill test.
This commit is contained in:
Rob Pearce 2011-08-24 23:48:29 +00:00
parent f071b379ca
commit 52f6fd21c3
16 changed files with 940 additions and 817 deletions

8
ai.c
View File

@ -528,7 +528,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// reset F_TARGET lifetime to full.
if (targetflag) {
if (targetflag->id == F_TARGETLF) {
targetflag->lifetime = AI_FOLLOWTIME;
targetflag->lifetime = DEF_AIFOLLOWTIME;
}
if (db) dblog(".oO { i can see my target (at %d,%d). might move towards it. }",target->cell->x,target->cell->y);
// remember their location
@ -818,7 +818,7 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y);
// moved towards it.
// reset lifetime
f->lifetime = AI_FOLLOWTIME;
f->lifetime = DEF_AIFOLLOWTIME;
// are we there yet?
if (lf->cell == c) {
@ -1382,7 +1382,7 @@ void aiturn(lifeform_t *lf) {
}
if (newtarget) {
if (aiattack(lf, newtarget, AI_FOLLOWTIME)) {
if (aiattack(lf, newtarget, DEF_AIFOLLOWTIME)) {
// failed for some reason. maybe target was feigning
// death?
} else {
@ -2030,7 +2030,7 @@ int lookforobs(lifeform_t *lf) {
}
}
// start walking towards target cell
if (aigoto(lf, c, MR_OB, o, AI_FOLLOWTIME)) {
if (aigoto(lf, c, MR_OB, o, DEF_AIFOLLOWTIME)) {
return B_FALSE;
}
}

614
defs.h
View File

@ -8,17 +8,292 @@
// #define PRACTICETIME 15 // #attempts it takes to learn new weapon skill
#define WETTIME 10 // how long it takes for things to dry
#define DRUNKTIME 10 // how long it takes for alcohol to wear off
// chances of things happening
// Probabilities
#define ONEIN_FOUNTAINDRYUP 3
#define PCTCH_PILLAR 5
#define SHOPIDENTPRICE 50 // cost to identify a just-purchased item
// Defaults
#define DEF_AIFOLLOWTIME (50) // if target lf is out of view
// for this many turns, abandon chase
#define DEF_ANIMDELAY (1000000 / 50) // 1/100 of a second
#define DEF_RESTHEALTIME (3)
#define DEF_SCREENW 80
#define DEF_SCREENH 24
#define DEF_SHOPIDENTPRICE (50) // cost to identify a just-purchased item
#define DEF_VAULTMARGIN (3)
// Map building defaults
#define DEF_LOOPPCT 95
#define DEF_SPARSENESS 20
#define DEF_TURNPCT 40
#define DEF_WINDOWPCT 5
// getrandomemptycell() params
#define WE_WALKABLE 1
#define WE_EMPTY 2
#define WE_PORTAL 3
#define WE_NOTWALL 4
#define WE_NOLF 5
// Booleans
#define B_FALSE (0)
#define B_TRUE (-1)
#define B_VIS (1)
#define B_UNKNOWN (0)
#define B_NOVIS (-1)
#define B_KEEPLOF (-1)
#define B_MALE (0)
#define B_FEMALE (-1)
#define B_MAYCHASE (-1)
#define B_NODOORS (0)
#define B_DONTKILL (-1)
//#define B_TEMP (-1)
//#define B_PERM (-2)
//#define B_NOT (-3)
#define B_DIEONFAIL (-1)
#define B_BLUNTONFAIL (-2)
#define B_COVETS (-1)
#define B_ANY (0)
#define B_SINGLE (0)
#define B_MULTI (-1)
#define B_MULTIPLE (-1)
#define B_NOOBS (0)
#define B_WITHOBS (-1)
#define B_UNKNOWN (0)
#define B_KNOWN (-1)
#define B_TRIED (1)
#define B_NOBADMOVES (0)
#define B_BADMOVESOK (1)
#define B_NOSTACK (0)
#define B_STACK (-1)
#define B_STACKOK (-1)
#define NOOWNER (NULL)
#define NOLOC (NULL)
#define NOOB (NULL)
#define B_NOTSOLID (0)
#define B_EMPTY (0)
#define B_SOLID (-1)
#define B_OPAQUE (0)
#define B_TRANSPARENT (-1)
#define B_TRANS (-1)
#define B_ALLOWEXPAND (-1)
#define B_NOEXPAND (0)
#define B_IFACTIVATED (-1)
#define B_BIG (-1)
// Limits
#define MAXCANDIDATES 200
#define MAXCHOICES 400
#define MAXDEPTH 25 // max dungeon depth
#define MAXDIR_ORTH 4
#define MAXDIR_COMPASS 8
#define MAXFLAGS 500
#define MAXHISTORY 20 // max lines of history to keep
#define MAX_MAPW 80
#define MAX_MAPH 20
#define MAXPILEOBS 52
#define MAXRANDOMOBCANDIDATES 100
#define MAXRANDOMLFCANDIDATES 100
#define MAXRETCELLS 80
#define MAXSPELLLEV 6
#define MAXVISRANGE 10 // max visible range in full light
#define MAXVISLIMIT (MAXVISRANGE*8)
#define MINCLEARINGRADIUS 2
#define MAXCLEARINGRADIUS 5
#define MINROOMS 5
#define MAXROOMS 10
#define MIN_ROOMH 4
#define MIN_ROOMW 4
#define MAX_ROOMW (MAX_MAPW / 3)
#define MAX_ROOMH (MAX_MAPH / 3)
// askobject options
#define AO_NONE 0
#define AO_INCLUDENOTHING 1
#define AO_ONLYEQUIPPED 2
#define AO_EDIBLE 4
#define AO_NOTIDENTIFIED 8
#define AO_WEARABLE 16
#define AO_OPERABLE 32
#define AO_POURABLE 64
#define AO_EQUIPPEDNONWEAPON 128
#define AO_WEILDABLE 256
#define AO_SPECIFIED 512
#define AO_READABLE 1024
#define AO_ARMOUR 2048
#define AO_NOTKNOWN 4096
#define AO_DAMAGED 8192
#define AO_DRINKABLE 16384
// askcoords target types
#define TT_NONE 0
#define TT_MONSTER 1
#define TT_OBJECT 2
#define TT_DOOR 4
#define TT_PLAYER 8
#define TT_ALLY 16
#define TT_IMPASSABLE 32
// target requirements
#define TR_NONE 0
#define TR_NEEDLOS 1
#define TR_NEEDLOF 2
// CONTROLLERS
#define C_AI 0
#define C_PLAYER 1
// speeds
#define SP_GODLIKE 1
#define SP_ULTRAFAST 5
#define SP_VERYFAST 10
#define SP_FAST 15
#define SP_NORMAL 20
#define SP_SLOW 25
#define SP_VERYSLOW 30
#define SP_ULTRASLOW 35
#define SP_SLOWEST 40
#define SPEEDUNIT 5
// speed settings (lower is faster)
#define SPEED_ATTACK SP_NORMAL
#define SPEED_DEAD 50
#define SPEED_ACTION SP_NORMAL
#define SPEED_MOVE SP_NORMAL
#define SPEED_DROP SP_FAST
#define SPEED_PICKUP SP_FAST
#define SPEED_THROW SP_FAST
#define SPEED_WAIT SP_NORMAL
#define SPEED_READ SP_NORMAL
#define SPEED_DRINK SP_FAST
// DIRECTION TYPES
#define DT_ORTH 0
#define DT_COMPASS 1
// DIRECTIONS
#define D_NONE -1
#define D_UNKNOWN -2
// Orthogonal directions
#define D_N 0
#define D_E 1
#define D_S 2
#define D_W 3
// Compass directions
#define DC_N 4
#define DC_NE 5
#define DC_E 6
#define DC_SE 7
#define DC_S 8
#define DC_SW 9
#define DC_W 10
#define DC_NW 11
// altitude directions
#define D_UP 12
#define D_DOWN 13
#define D_IN 14
#define MAXDIR_MAP 15
///////////////////////////////////////
// STRINGS
///////////////////////////////////////
// String buffer lengths
#define BUFLENTINY 10
#define BUFLENSMALL 64
#define BUFLEN 128
#define BIGBUFLEN 512
#define HUGEBUFLEN 1024
#define MAXPNAMELEN 12 // max player name length
// file i/o
#define DATADIR "data"
#define MAPDIR "data/maps"
#define SAVEDIR "data/save"
#define VAULTDIR "vaults"
// rank, score, name, job, killer
#define HISCOREFORMAT "%-6s%-7s%-14s%-18s%s"
// game strings
#define MORESTRING "--More--"
#define MSGMORESTRING "^n--More--"
#define SOLDOUTSTRING "--SOLD OUT--"
// SPECIAL NUMBERS/CONSTANTS
#define DUMMYCELLTYPE 0xabcd
#define UNLIMITED (-9876)
#define ALL (-9875)
#define NA (-9874)
#define NOBODY (-1)
#define ALLCONFERRED (-9873)
#define PCT (65432) // must be POSITIVE
#define RANDOM (-2610)
#define AUTO (-7654)
// Time periods
#define TM_DRUNKTIME (10) // how long it takes for alcohol to wear off
#define TM_WETTIME (10) // how long it takes for things to dry
#define TM_SCENT (15) // how long scents take to fade
#define TM_FOOTPRINT (20) // how long footprints take to fade
// object conditions for random objects
#define RO_NONE 0
#define RO_DAMTYPE 1
#define RO_OBCLASS 2
#define RO_HOLDABLE 3
// flag lifetimes
#define PERMENANT (-9873)
#define FROMSPELL (-9863)
#define FROMPOISON (-9862)
// flag lifetimes - external sources (ie. don't kill them)
#define FROMEXTERNAL_HIGH (-7000)
#define FROMRACE (-7872)
#define FROMJOB (-7871)
#define FROMOBEQUIP (-7870)
#define FROMOBHOLD (-7869)
#define FROMOBACTIVATE (-7868)
#define FROMMAT (-7867)
#define FROMBLESSING (-9866)
#define FROMBRAND (-7865)
#define FROMOBMOD (-7864)
#define FROMSKILL (-7863)
#define FROMGODGIFT (-7862)
#define FROMEXTERNAL_LOW (-7999)
#define LEVABILITYDONE (-8000)
#define IFKNOWN (-9772) // used by f_xxconfer. only confer a flag if item is known.
#define IFACTIVE (-9771) // used by f_prodeuceslight. only does so if object is activated
// Misc constants
#define ANYROOM (-9770)
#define FALLTHRU (-8765) // for walkdambp
#define TICK_INTERVAL (20)
// ncurses colours
#define C_NONE (-1)
enum COLOUR {
@ -147,24 +422,6 @@ enum SKILLLEVEL {
#define MAXSKILLLEVEL 7
// save/load
#define DATADIR "data"
#define MAPDIR "data/maps"
#define SAVEDIR "data/save"
#define VAULTDIR "vaults"
#define DUMMYCELLTYPE 0xabcd
// SPECIAL NUMBERS/CONSTANTS
#define UNLIMITED (-9876)
#define ALL (-9875)
#define NA (-9874)
#define NOBODY (-1)
#define ALLCONFERRED (-9873)
#define PCT (65432) // must be POSITIVE
#define RANDOM (-2610)
#define AUTO (-7654)
enum GAMEMODE {
GM_FIRST,
GM_INIT,
@ -237,76 +494,12 @@ enum SENSE {
S_TOUCH,
};
// AI defs
// if target lf is out of view for this many turns, abandon chase
#define AI_FOLLOWTIME (50)
#define DEFAULTRESTHEALTIME (3)
// object confitions for random objects
#define RO_NONE 0
#define RO_DAMTYPE 1
#define RO_OBCLASS 2
#define RO_HOLDABLE 3
// flag lifetimes
#define PERMENANT (-9873)
#define FROMSPELL (-9863)
#define FROMPOISON (-9862)
// external sources (ie. don't kill them)
#define FROMEXTERNAL_HIGH (-7000)
#define FROMRACE (-7872)
#define FROMJOB (-7871)
#define FROMOBEQUIP (-7870)
#define FROMOBHOLD (-7869)
#define FROMOBACTIVATE (-7868)
#define FROMMAT (-7867)
#define FROMBLESSING (-9866)
#define FROMBRAND (-7865)
#define FROMOBMOD (-7864)
#define FROMSKILL (-7863)
#define FROMGODGIFT (-7862)
#define FROMEXTERNAL_LOW (-7999)
#define LEVABILITYDONE (-8000)
#define IFKNOWN (-9772) // used by f_xxconfer. only confer a flag if item is known.
#define IFACTIVE (-9771) // used by f_prodeuceslight. only does so if object is activated
enum FLAGCONDITION {
FC_NOCONDITION = 0,
FC_IFPLAYER,
FC_IFMONSTER,
};
//#define NOCONDITION (0)
//#define IFMONSTER (-9769) // used in v2 of f_ifpct job flags
//#define IFPLAYER (-9768) // used in v2 of f_ifpct job flags
#define ANYROOM (-9770)
#define TICK_INTERVAL (20)
#define SCENTTIME (15)
#define FOOTPRINTTIME (20)
// STRINGS
#define BUFLENTINY 10
#define BUFLENSMALL 64
#define BUFLEN 128
#define BIGBUFLEN 512
#define HUGEBUFLEN 1024
#define MAXPNAMELEN 12
#define MORESTRING "--More--"
#define MSGMORESTRING "^n--More--"
#define SOLDOUTSTRING "--SOLD OUT--"
enum MSGCHARCOL {
CC_VBAD,
@ -326,100 +519,6 @@ enum MODTYPE {
};
// LIMITS
#define DEF_SCREENW 80
#define DEF_SCREENH 24
#define MAXPILEOBS 52
#define MAXSPELLLEV 6
#define MAXRETCELLS 80
#define MAXFLAGS 500
#define MAXCHOICES 400
#define MAXDEPTH 25 // max dungeon depth
#define MAXRANDOMOBCANDIDATES 100
#define MAXRANDOMLFCANDIDATES 100
#define MAXCANDIDATES 200
//#define MAX_MAPW 80
//#define MAX_MAPH 50
#define MAX_MAPW 80
#define MAX_MAPH 20
#define MINCLEARINGRADIUS 2
#define MAXCLEARINGRADIUS 5
//#define MAX_MAPROOMS 10
#define MIN_ROOMH 4
#define MIN_ROOMW 4
#define MAX_ROOMW (MAX_MAPW / 3)
#define MAX_ROOMH (MAX_MAPH / 3)
#define MAXDIR_ORTH 4
#define MAXDIR_COMPASS 8
#define MAXHISTORY 20 // max lines of history to keep
// MAP BUILDING
#define DEF_TURNPCT 40
//#define DEF_SPARSENESS 14
#define DEF_SPARSENESS 20
//#define DEF_SPARSENESS 0
//#define DEF_LOOPPCT 70
#define DEF_LOOPPCT 95
//#define DEF_LOOPPCT 0
#define MINROOMS 5
#define MAXROOMS 10
#define DEF_WINDOWPCT 5
//
//#define ANIMDELAY (1000000 / 100) // 1/100 of a second
#define ANIMDELAY (1000000 / 50) // 1/100 of a second
#define MAXVISRANGE 10 // max visible range in full light
#define MAXVISLIMIT (MAXVISRANGE*8)
// askobject options
#define AO_NONE 0
#define AO_INCLUDENOTHING 1
#define AO_ONLYEQUIPPED 2
#define AO_EDIBLE 4
#define AO_NOTIDENTIFIED 8
#define AO_WEARABLE 16
#define AO_OPERABLE 32
#define AO_POURABLE 64
#define AO_EQUIPPEDNONWEAPON 128
#define AO_WEILDABLE 256
#define AO_SPECIFIED 512
#define AO_READABLE 1024
#define AO_ARMOUR 2048
#define AO_NOTKNOWN 4096
#define AO_DAMAGED 8192
#define AO_DRINKABLE 16384
// askcoords target types
#define TT_NONE 0
#define TT_MONSTER 1
#define TT_OBJECT 2
#define TT_DOOR 4
#define TT_PLAYER 8
#define TT_ALLY 16
#define TT_IMPASSABLE 32
// target requirements
#define TR_NONE 0
#define TR_NEEDLOS 1
#define TR_NEEDLOF 2
// line of fire args
enum LOFTYPE {
@ -429,74 +528,6 @@ enum LOFTYPE {
LOF_NEED = 6, // walls AND lfs block
};
// CONTROLLERS
#define C_AI 0
#define C_PLAYER 1
// deafult
//#define DEF_HEALTIME 100 // time to heal 1 hp
// speeds
#define SP_GODLIKE 1
#define SP_ULTRAFAST 5
#define SP_VERYFAST 10
#define SP_FAST 15
#define SP_NORMAL 20
#define SP_SLOW 25
#define SP_VERYSLOW 30
#define SP_ULTRASLOW 35
#define SP_SLOWEST 40
#define SPEEDUNIT 5
// speed settings (lower is faster)
#define SPEED_ATTACK SP_NORMAL
#define SPEED_DEAD 50
#define SPEED_ACTION SP_NORMAL
#define SPEED_MOVE SP_NORMAL
#define SPEED_DROP SP_FAST
#define SPEED_PICKUP SP_FAST
#define SPEED_THROW SP_FAST
#define SPEED_WAIT SP_NORMAL
#define SPEED_READ SP_NORMAL
#define SPEED_DRINK SP_FAST
// DIRECTION TYPES
#define DT_ORTH 0
#define DT_COMPASS 1
// DIRECTIONS
#define D_NONE -1
#define D_UNKNOWN -2
// Orthogonal directions
#define D_N 0
#define D_E 1
#define D_S 2
#define D_W 3
// Compass directions
#define DC_N 4
#define DC_NE 5
#define DC_E 6
#define DC_SE 7
#define DC_S 8
#define DC_SW 9
#define DC_W 10
#define DC_NW 11
// altitude directions
#define D_UP 12
#define D_DOWN 13
#define D_IN 14
#define MAXDIR_MAP 15
// Cell types
enum CELLTYPE {
CT_NONE = 0,
@ -1486,13 +1517,6 @@ enum DEPTH {
DP_NONE = 0,
};
// empty types
#define WE_WALKABLE 1
#define WE_EMPTY 2
#define WE_PORTAL 3
#define WE_NOTWALL 4
#define WE_NOLF 5
enum NOISETYPE {
N_GETANGRY,
N_WALK,
@ -1608,6 +1632,8 @@ enum FLAG {
F_ATTACKABLE, // can attack this with 'A'
F_IMPASSABLE, // cannot walk past this if your size is between v0 and v1
// (inclusive)
F_REALLYIMPASSABLE, // even gaseous form etc won't let you get through
// this.
F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it
F_CAUSESCOUGH, // being in this ob's cell will make you cough unless
// immune to gas.
@ -2354,37 +2380,6 @@ enum PIETYLEV {
PL_ECSTATIC = 3,
};
// probabilities
//#define CH_DEADENDOB 35
//#define CH_EMPTYCELLOB 3
#define CH_PILLAR 5
// Booleans
#define B_FALSE (0)
#define B_TRUE (-1)
#define B_VIS (1)
#define B_UNKNOWN (0)
#define B_NOVIS (-1)
#define B_KEEPLOF (-1)
#define B_MALE (0)
#define B_FEMALE (-1)
#define B_MAYCHASE (-1)
#define B_NODOORS (0)
#define B_DONTKILL (-1)
#define FALLTHRU (-8765)
//#define B_TEMP (-1)
//#define B_PERM (-2)
//#define B_NOT (-3)
enum LIGHTLEV {
L_PERMDARK = -1,
L_NOTLIT = 0,
@ -2404,49 +2399,6 @@ enum SPELLTARGET {
};
#define B_DIEONFAIL (-1)
#define B_BLUNTONFAIL (-2)
#define B_COVETS (-1)
#define B_ANY (0)
#define B_SINGLE (0)
#define B_MULTI (-1)
#define B_MULTIPLE (-1)
#define B_NOOBS (0)
#define B_WITHOBS (-1)
#define B_UNKNOWN (0)
#define B_KNOWN (-1)
#define B_TRIED (1)
#define B_NOBADMOVES (0)
#define B_BADMOVESOK (1)
#define B_NOSTACK (0)
#define B_STACK (-1)
#define B_STACKOK (-1)
#define NOOWNER (NULL)
#define NOLOC (NULL)
#define NOOB (NULL)
#define B_NOTSOLID (0)
#define B_EMPTY (0)
#define B_SOLID (-1)
#define B_OPAQUE (0)
#define B_TRANSPARENT (-1)
#define B_TRANS (-1)
#define B_ALLOWEXPAND (-1)
#define B_NOEXPAND (0)
#define B_IFACTIVATED (-1)
#define B_BIG (-1)
// errors
enum ERROR {
E_OK = 0,
@ -2657,6 +2609,7 @@ typedef struct map_s {
int nrooms; // how many rooms on this map
char *name; // name of this map
habitat_t *habitat;
long lastplayervisit;
unsigned int seed;
int w,h; // width/height of this map
struct cell_s *cell[MAX_MAPW*MAX_MAPH]; // list of cells in this map
@ -2747,6 +2700,7 @@ typedef struct cell_s {
// FOR CONSTRUCTION
int visited;
int filled;
} cell_t;
typedef struct celltype_s {

12
doc/criticals.txt Normal file
View File

@ -0,0 +1,12 @@
Critical effects:
attack.c:
update damtypecausescriteffects()
update criticalhit()
put replacements for similar damage types at the top
lf.c:
update injure() with special effects for bp_head
text.c:
update getinjuryname()
update getinjurydesc()
... then implement effects for f_injury bp_xxx dt_xxx

2
flag.c
View File

@ -1100,7 +1100,7 @@ void timeeffectsflag(flag_t *f, int howlong) {
return;
} else {
// reset timer
f->val[1] = WETTIME;
f->val[1] = TM_WETTIME;
// TODO: announce
}
}

56
io.c
View File

@ -221,7 +221,7 @@ void anim(cell_t *src, cell_t *dst, char ch, int colour) {
//mvwprintw(gamewin, cell->y - viewy, cell->x - viewx, "%c", gl.ch);
wmove(gamewin, cell->y - viewy, cell->x - viewx);
wrefresh(gamewin);
usleep(ANIMDELAY);
usleep(DEF_ANIMDELAY);
}
// move to next cell
@ -279,13 +279,13 @@ void animcells(cell_t *src, cell_t **dst, int ndst, int gradual, char ch, char c
if (gradual) {
wrefresh(gamewin);
usleep(ANIMDELAY);
usleep(DEF_ANIMDELAY);
}
}
if (!gradual) {
wrefresh(gamewin);
usleep(ANIMDELAY);
usleep(DEF_ANIMDELAY);
}
// show cursor
curs_set(1);
@ -332,13 +332,13 @@ void animline(cell_t *src, cell_t *dst, int gradual, char ch, char ch2, int colo
if (gradual) {
wrefresh(gamewin);
usleep(ANIMDELAY);
usleep(DEF_ANIMDELAY);
}
}
if (!gradual) {
wrefresh(gamewin);
usleep(ANIMDELAY);
usleep(DEF_ANIMDELAY);
}
// show cursor
curs_set(1);
@ -378,7 +378,7 @@ void animradial(cell_t *src, int radius, char ch, int colour) {
wrefresh(gamewin);
if (drawn) {
usleep(ANIMDELAY);
usleep(DEF_ANIMDELAY);
}
}
// show cursor
@ -420,7 +420,7 @@ void animradialorth(cell_t *src, int radius, char ch,int colour) {
wrefresh(gamewin);
if (drawn) {
usleep(ANIMDELAY);
usleep(DEF_ANIMDELAY);
}
}
// show cursor
@ -453,7 +453,7 @@ void animsky(cell_t *src, char ch, int colour) {
drawglyph(&gl, src->x - viewx, y);
}
wrefresh(gamewin);
usleep(ANIMDELAY);
usleep(DEF_ANIMDELAY);
// show cursor
curs_set(1);
@ -4212,7 +4212,7 @@ void docomms(lifeform_t *lf) {
} else {
// stop attacking all current targets first...
killflagsofid(lf->flags, F_TARGETLF);
aiattack(lf, lf2, AI_FOLLOWTIME);
aiattack(lf, lf2, DEF_AIFOLLOWTIME);
}
break;
case 'c':
@ -4220,7 +4220,7 @@ void docomms(lifeform_t *lf) {
// find adjacent cell
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) {
aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME);
aigoto(lf, c, MR_OTHER, NULL, DEF_AIFOLLOWTIME);
}
break;
case 'd': // donate
@ -4345,7 +4345,7 @@ void docomms(lifeform_t *lf) {
// stop attacking all current targets first...
killflagsofid(lf->flags, F_TARGETLF);
msg("You say \"Go over there!\" to %s.", lfname);
aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME);
aigoto(lf, c, MR_OTHER, NULL, DEF_AIFOLLOWTIME);
break;
case 'j':
// charisma check to see if they'll join you.
@ -4372,19 +4372,19 @@ void docomms(lifeform_t *lf) {
msg("You buy %s.", buf);
angeramt += 25;
// get it identified?
if (!isknown(o) && (countmoney(player) >= SHOPIDENTPRICE)) {
if (!isknown(o) && (countmoney(player) >= DEF_SHOPIDENTPRICE)) {
char buf2[BUFLEN];
char ch2;
sprintf(buf2, "Pay $%d to identify %s?",(int)SHOPIDENTPRICE, buf);
sprintf(buf2, "Pay $%d to identify %s?",(int)DEF_SHOPIDENTPRICE, buf);
ch2 = askchar(buf2, "yn","n", B_TRUE);
if (ch2 == 'y') {
if (givemoney(player, lf, SHOPIDENTPRICE)) {
if (givemoney(player, lf, DEF_SHOPIDENTPRICE)) {
angeramt += 25;
identify(o);
real_getobname(o, buf, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); // don't adjust for blindness
msgnocap("%c - %s",o->letter, buf);
} else {
msg("You can't afford to pay $%d.", SHOPIDENTPRICE);
msg("You can't afford to pay $%d.", DEF_SHOPIDENTPRICE);
}
}
}
@ -7139,15 +7139,6 @@ void dblog(char *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);
@ -7157,6 +7148,23 @@ void dblog(char *format, ... ) {
}
}
void dblog_nocr(char *format, ... ) {
char buf[HUGEBUFLEN];
va_list args;
va_start(args, format);
vsprintf( buf, format, args );
va_end(args);
if (logfile) {
fprintf(logfile, "%s", buf);
fflush(logfile);
} else {
fprintf(stdout, "%s", buf);
fflush(stdout);
}
}
// force a '--more--' prompt
void more(void) {
//msg("^");

1
io.h
View File

@ -101,6 +101,7 @@ void msg_real(char *format, ... );
int needsbold(enum COLOUR col);
void nothinghappens(void);
void dblog(char *format, ... );
void dblog_nocr(char *format, ... );
void redraw(void);
void redrawpause(void);
void redrawresume(void);

44
lf.c
View File

@ -3199,14 +3199,14 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
if (!isplayer(attacker)) return;
}
aiattack(lf, attacker, AI_FOLLOWTIME);
aiattack(lf, attacker, DEF_AIFOLLOWTIME);
// any nearby monsters which will help out?
if (getallegiance(lf) != AL_FRIENDLY) {
for (l = lf->cell->map->lf ; l ; l = l->next) {
if (!isdead(l) && areallies(l,lf)) {
if (cansee(l, attacker)) {
aiattack(l, attacker, AI_FOLLOWTIME);
aiattack(l, attacker, DEF_AIFOLLOWTIME);
}
}
}
@ -4257,6 +4257,7 @@ int getevasion(lifeform_t *lf) {
int ev = 0,i;
flag_t *retflag[MAXCANDIDATES];
int nretflags;
double level_ev = 0, skillpctmod;
// no evasion if you can't move!
if (isimmobile(lf)) {
@ -4270,30 +4271,11 @@ int getevasion(lifeform_t *lf) {
ev += (f->val[0]);
}
// level based evasion
ev += gethitdice(lf);
// skill based
//ev += (getskill(lf, SK_EVASION)*10);
ev += (getskill(lf, SK_EVASION)*5);
// now get object penalties/bonuses
/*
for (o = lf->pack->first ; o ; o = o->next) {
// armour/weapons must be worn to do anything
if (hasflag(o->flags, F_EQUIPPED)) {
f = hasflag(o->flags, F_EVASION);
if (f) {
if (isarmour(o)) {
// adjust penalties based on armour skill.
ev += adjustarmourpenalty(lf, f->val[0]);
} else {
ev += (f->val[0]);
}
}
}
}
*/
// level based evasion (modified by evasion skill)
level_ev = gethitdice(lf);
skillpctmod = (getskill(lf, SK_EVASION) + 1) * 40;
level_ev = pctof(skillpctmod, level_ev);
ev += level_ev;
// adjust for bulky armour/shield
getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE);
@ -4556,7 +4538,7 @@ object_t *getfirearm(lifeform_t *lf) {
int getfootprinttime(lifeform_t *lf) {
int time;
time = FOOTPRINTTIME;
time = TM_FOOTPRINT;
switch (getlfsize(lf)) {
case SZ_MINI: time = 1; break;
case SZ_TINY: time -= 15; break;
@ -4842,7 +4824,7 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
f = isdrunk(lf);
if (f) {
int amt;
amt = (f->lifetime/DRUNKTIME)+1;
amt = (f->lifetime/TM_DRUNKTIME)+1;
if (hasjob(lf, J_PIRATE)) {
acc += (10*amt);
} else {
@ -11887,12 +11869,12 @@ void addtrail(lifeform_t *lf, int dir) {
scent = hastrailof(lf->cell->obpile, lf, OT_SCENT, &fpflag, NULL);
if (scent) {
assert(fpflag);
fpflag->lifetime = SCENTTIME;
fpflag->lifetime = TM_SCENT;
} else {
char buf[BUFLENTINY];
sprintf(buf, "%d", lf->id);
scent = addobfast(lf->cell->obpile, OT_SCENT);
addtempflag(scent->flags, F_TRAIL, lf->race->id, dir, S_SMELL, buf, SCENTTIME);
addtempflag(scent->flags, F_TRAIL, lf->race->id, dir, S_SMELL, buf, TM_SCENT);
}
}
@ -17602,7 +17584,7 @@ int rest(lifeform_t *lf, int onpurpose) {
healtime = ff->val[0];
} else {
// 3 turns = heal 1 hp
healtime = DEFAULTRESTHEALTIME;
healtime = DEF_RESTHEALTIME;
}
// modify via restob if resting using 'R'

578
map.c
View File

@ -40,6 +40,8 @@ extern enum GAMEMODE gamemode;
extern int needredraw;
extern long curtime;
cell_t *addcell(map_t *m, int x, int y) {
cell_t *cell;
m->cell[(y*m->w)+x] = malloc(sizeof(cell_t));
@ -49,7 +51,6 @@ cell_t *addcell(map_t *m, int x, int y) {
cell->y = y;
cell->habitat = m->habitat;
setcelltype(cell, cell->habitat->solidcelltype);
cell->visited = B_FALSE;
cell->obpile = addobpile(NOOWNER, cell, NOOB);
cell->lf = NULL;
cell->room = NULL;
@ -61,6 +62,8 @@ cell_t *addcell(map_t *m, int x, int y) {
cell->known = B_FALSE;
cell->knownglyph.ch = ' ';
cell->knownglyph.colour = C_GREY;
cell->visited = B_FALSE;
cell->filled = B_FALSE;
return cell;
}
@ -148,6 +151,7 @@ map_t *addmap(void) {
a->flags = addflagpile(NULL, NULL);
a->beingcreated = B_TRUE;
a->habitat = findhabitat(H_DUNGEON); // default!!!
a->lastplayervisit = -1;
return a;
}
@ -1029,6 +1033,67 @@ int dowaterspread(cell_t *c) {
return B_FALSE;
}
void fix_reachability(map_t *m) {
int i,keepgoing = B_TRUE, nfixed = 0;
int db = B_TRUE;
cell_t *c = NULL;
if (db) dblog("fix_reachability starting.");
// find first non-empty cell
for (i = 0; i < m->w * m->h; i++) {
if (!m->cell[i]->type->solid) {
c = m->cell[i];
break;
}
}
// no empty cells in map?
if (!c) return;
while (keepgoing) {
keepgoing = B_FALSE;
// mark all cells as non-filled
for (i = 0; i < m->w * m->h; i++) {
m->cell[i]->filled = FALSE;
}
// floodfill
floodfill(c);
// any remaining non-filled empty cells?
for (i = 0; i < m->w * m->h; i++) {
if (!m->cell[i]->type->solid && !m->cell[i]->filled) {
int nadded = 0;
// found an unreachable cell! link it back to a filled cell.
if (db) dblog(" found unreachable area at %d,%d. will fix it.",
m->cell[i]->x, m->cell[i]->y);
linkexit(m->cell[i], B_TRUE, &nadded);
if (db) dblog(" fixed unreachable area by added %d cells.", nadded);
// now run the test again.
// 'c' will be where the next flood will will happen.
keepgoing = B_TRUE;
c = m->cell[i];
nfixed++;
break;
}
}
}
if (db) dblog(" fix_reachability complete. fixed %d unreachable areas.", nfixed);
}
void floodfill(cell_t *startcell) {
int d;
if (startcell && // not off the map
!startcell->type->solid && // empty cell
!startcell->filled) { // not already filled
startcell->filled = B_TRUE;
} else {
return;
}
for (d = DC_N; d <= DC_NW; d++) {
floodfill(getcellindir(startcell, d)); // recursive call
}
}
cell_t *getcellat(map_t *map, int x, int y) {
if (!isonmap(map, x, y)) return NULL;
return map->cell[y*map->w + x];
@ -1310,6 +1375,7 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int
cell_t *cell;
int sel;
int db = B_FALSE;
int foundvalid = B_FALSE;
// init coords list
for (y = 1 + ymargin; y < (map->h - ymargin); y++) {
@ -1377,6 +1443,7 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int
if (valid) {
if (score < bestscore) {
bestscore = score;
foundvalid = B_TRUE;
}
} else {
score = 9999;
@ -1386,12 +1453,16 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int
if (db) dblog("cell %d,%d - score %d",x,y,score);
}
// now go through and make a list of all BEST positions
nposs = 0;
for (i = 0; i < ncoords; i++) {
if (coordscore[i] == bestscore) {
poss[nposs++] = coord[i];
if (foundvalid) {
// now go through and make a list of all BEST positions
nposs = 0;
for (i = 0; i < ncoords; i++) {
if (coordscore[i] == bestscore) {
poss[nposs++] = coord[i];
}
}
} else {
nposs = 0;
}
if (nposs == 0) {
@ -1652,17 +1723,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
}
// use sparseness to cut down dead ends
for (i = 0; i < sparseness; i++) {
for (y = 0; y < map->h; y++) {
for (x = 0; x < map->w; x++) {
cell = getcellat(map, x,y);
if (countcellexits(cell) == 1) {
// erase this cell
setcelltype(cell, CT_WALL);
}
}
}
}
remove_deadends(map, sparseness);
// introduce loops
for (y = 0; y < map->h; y++) {
@ -1757,6 +1818,8 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
linkexits(map, map->room[i].id);
}
// now clear up dead ends again.
remove_deadends(map, sparseness);
// add staircases.
// first dungeon level has 1 up stairs, 3 down.
@ -1814,7 +1877,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
//dblog("Adding obs to room %d/%d",i+1,numrooms);
maxpillars = (roomw[i] / 4) + (roomh[i] / 4);
// add pillars first
if ((maxpillars > 0) && (rnd(1,100) <= CH_PILLAR)) {
if ((maxpillars > 0) && pctchance(PCTCH_PILLAR)) {
int n;
int numpillars;
numpillars = rnd(1,maxpillars);
@ -1849,7 +1912,6 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
while (!done) {
c = getrandomroomcell(map, i);
// if nothing there
//if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
if (c && cellwalkable(NULL, c, NULL)) {
int obchance;
@ -1880,9 +1942,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
} // end if !vault
} // end foreach room
} // end if wantrooms & nrooms>0
if (db) dblog("Finished adding objects.");
if (db) dblog("Finished adding stuff to rooms.");
// now do a border
y = 0;
@ -1906,6 +1966,9 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
clearcell(c);
setcelltype(c,solidcell);
}
// ensure there are no unreachable areas
fix_reachability(map);
}
void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob, int nclearings) {
@ -2529,7 +2592,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *retx, int *rety) {
int w,h,x,y;
int xmargin = 0,ymargin = 0;
int xmargin = DEF_VAULTMARGIN,ymargin = DEF_VAULTMARGIN; // defaults
int minx,miny,maxx,maxy;
int db = B_FALSE;
int rotation = 0;
@ -2577,7 +2640,7 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r
// forced calcroompos should never fail since it's
// allowed to overlap other rooms.
dblog("** couldn't make vault room!\n");
msg("** ALERT: couldn't make vault room!\n");
//msg("** ALERT: couldn't make vault room!\n");
return B_TRUE;
}
maxx = minx + (w-1);
@ -2633,6 +2696,229 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r
return B_FALSE;
}
// link a single cell up to the rest of the map.
// make sure it links to an empty cell of a DIFFERENT roomid.
// if 'wantfilled' is set, only link to "filled" cells.
// return TRUE on failure.
int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
int db = B_FALSE;
int d, roomid;
int poss2[MAXCANDIDATES],nposs2;
int dist[MAXDIR_ORTH];
int hitsedge[MAXDIR_ORTH];
int mindist = 999,maxdist = -1;
cell_t *c;
if (ncellsadded) *ncellsadded = 0;
if (db) dblog(" calling linkexit() for cell at %d,%d", startcell->x, startcell->y);
roomid = getroomid(startcell);
// link it. starting from the door, count the number of cells in
// each direction until we hit an empty (walkable) cell which isn't a room.
// if we hit a cell of this roomid, mark this dir as invalid.
for (d = D_N; d <= D_W; d++) {
dist[d] = 0;
hitsedge[d] = B_TRUE;
c = getcellindir(startcell, d);
while (c) {
dist[d]++;
if ((roomid >= 0) && getroomid(c) == roomid) { // same room
if (wantfilled && c->type->solid) {
// EXCEPTION:
// if we are calling this function from fix_reachability, then
// startcell will actually be a cell _inside_ the room as opposed to
// a cell inside the room's walls.
// in this case, we ARE allowed to travel through the room's walls.
} else {
// mark dir as invalid
dist[d] = 999;
if (db) dblog(" going %s hits same room. invalid.", getdirname(d));
break;
}
} else if (cellwalkable(NULL, c, NULL)) {
if (!wantfilled || c->filled) {
// walkable and not in this vault. finished.
hitsedge[d] = B_FALSE;
if (db) dblog(" can make %s path (hits empty cell at dist %d)", getdirname(d), dist[d]);
break;
}
} else {
int perpdir[2],n;
cell_t *pcell = NULL;
perpdir[0] = d - 1; if (perpdir[0] < D_N) perpdir[0] = D_W;
perpdir[1] = d + 1; if (perpdir[1] > D_W) perpdir[1] = D_N;
// is there an adjacent walkable cell in a perpendicular direction
// which isn't from the starting room?
for (n = 0; n <= 1; n++) {
pcell = getcellindir(c, perpdir[n]);
if (pcell) {
if (((roomid == -1 ) || (getroomid(pcell) != roomid)) &&
cellwalkable(NULL, pcell, NULL)) {
if (!wantfilled || c->filled) {
// finished.
hitsedge[d] = B_FALSE;
if (db) dblog(" can make %s path (hits adjacent empty cell at dist %d)", getdirname(d), dist[d]);
break;
}
}
}
}
}
// check next cell
c = getcellindir(c, d); // getting the same cell!
}
if (dist[d] != 999) {
if (!hitsedge[d]) {
if (dist[d] < mindist) mindist = dist[d];
}
if (dist[d] > maxdist) maxdist = dist[d];
}
}
if (mindist == 999) {
cell_t *turncell = NULL,*endcell = NULL;
int perpdir[2];
int startdir = D_NONE;
int turndir = D_NONE;
int startdist = 0;
// no good directions.
if (db) dblog(" No directions lead to valid cells. Trying turns.");
// starting at the LONGEST distance, traverse up each dir,
// branching off looking for rooms.
// find longest distance
for (d = D_N; d <= D_W; d++) {
if (dist[d] == maxdist) {
startdir = d;
break;
}
}
assert(startdir != D_NONE);
// figure out perpendicular dirs
perpdir[0] = startdir - 1; if (perpdir[0] < D_N) perpdir[0] = D_W;
perpdir[1] = startdir + 1; if (perpdir[1] > D_W) perpdir[1] = D_N;
if (db) dblog(" Will walk %s (dist %d), checking %s and %s.", getdirname(startdir), maxdist,
getdirname(perpdir[0]), getdirname(perpdir[1]));
// check in startdir
c = getcellindir(startcell, startdir);
while (c && !turncell) {
int n;
cell_t *c2;
startdist++;
// check left/right from this door for rooms
for (n = 0; n <= 1; n++) {
int turndist = 0;
c2 = getcellindir(c, perpdir[n]);
while (c2) {
int gotsolution = B_FALSE;
turndist++;
if ((roomid >= 0) && (getroomid(c2) == roomid)) {
if (wantfilled && c2->type->solid) {
// see EXCEPTION above.
} else {
// hits same room, not ok.
break;
}
} else if (cellwalkable(NULL, c2, NULL)) {
if (!wantfilled || c2->filled) {
if (db) dblog(" Got to an empty cell here.");
gotsolution = B_TRUE;
}
} else if (turndist > 1) {
// check l/r too
int perpdir2[2],nn;
cell_t *pcell = NULL;
perpdir2[0] = perpdir[n] - 1; if (perpdir2[0] < D_N) perpdir2[0] = D_W;
perpdir2[1] = perpdir[n] + 1; if (perpdir2[1] > D_W) perpdir2[1] = D_N;
for (nn = 0; nn <= 1; nn++) {
pcell = getcellindir(c2, perpdir2[nn]);
if (pcell) {
if ( ((roomid == -1) || (getroomid(pcell) != roomid)) &&
cellwalkable(NULL, pcell, NULL)) {
if (!wantfilled || pcell->filled) {
// finished.
if (db) dblog(" Got to an empty cell next to us.");
gotsolution = B_TRUE;
break;
}
}
}
}
}
if (gotsolution) {
if (db) dblog(" Solution found: Walk %d %s, then %d %s.",
startdist, getdirname(startdir),
turndist, getdirname(perpdir[n]));
// walkable and not in this roomid. ok!
turncell = c;
endcell = c2;
turndir = perpdir[n];
break;
}
// check next cell
c2 = getcellindir(c2, perpdir[n]);
}
if (turncell) break;
}
// now keep going in main direction.
c = getcellindir(c, startdir);
}
if (turncell) {
// make a path up to the turn point.
if (db) dblog(" Making path from vault to corner, initdir=%s", getdirname(startdir));
c = getcellindir(startcell, startdir);
while (c != turncell) {
setcelltype(c, c->habitat->emptycelltype);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, startdir);
}
// clear the corner cell
setcelltype(c, c->habitat->emptycelltype);
if (db) dblog(" Making path from corner to rest of map, turndir=%s", getdirname(turndir));
// now turn and clear up to the next room/empty cell
c = getcellindir(c, turndir);
while (c != endcell) {
setcelltype(c, c->habitat->emptycelltype);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, turndir);
}
} else {
// give up??
if (db) dblog(" Cannot find a way to link up.");
return B_TRUE;
}
} else {
int whichway,sel;
// now pick the shortest one which doesn't hits the edge
// get list of all the minimums and randomly tie-break
nposs2 = 0;
for (d = D_N; d <= D_W; d++) {
if (dist[d] == mindist) {
poss2[nposs2++] = d;
}
}
sel = rnd(0,nposs2-1);
whichway = poss2[sel];
// now create a path
if (db) dblog(" Linking %s (distance %d).", getdirname(whichway), mindist);
c = getcellindir(startcell, whichway);
while (c && !cellwalkable(NULL, c, NULL)) {
setcelltype(c, c->habitat->emptycelltype);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, whichway);
}
}
return B_FALSE;
}
// make sure exits/doors in a given room link up to the rest of the map.
int linkexits(map_t *m, int roomid) {
int x,y,i;
@ -2687,202 +2973,25 @@ int linkexits(map_t *m, int roomid) {
// for each door, make sure it links to at least one cell which isn't
// part of this room
for (i = 0; i < nposs; i++) {
int d;
int ncorridors = 0;
int ncorridors = 0,d;
if (db) dblog("linking exit #%d",i);
for (d = D_N; d <= D_W; d++) {
c = getcellindir(poss[i], d);
if (c && cellwalkable(NULL, c, NULL) && (getroomid(c) != roomid)) {
ncorridors++;
}
}
if (db) dblog("Door #%d leads to %d corridors. ",i, ncorridors);
if (db) dblog(" This exit leads to %d corridors. ", ncorridors);
// no corridors?
if (ncorridors == 0) {
int poss2[MAXCANDIDATES],nposs2;
int dist[MAXDIR_ORTH];
int hitsedge[MAXDIR_ORTH];
int mindist = 999,maxdist = -1;
if (db) dblog(" Need to link.");
// link it. starting from the door, count the number of cells in
// each direction until we hit an empty (walkable) cell which isn't a room.
// if we hit a cell of this roomid, mark this dir as invalid.
for (d = D_N; d <= D_W; d++) {
dist[d] = 0;
hitsedge[d] = B_TRUE;
c = getcellindir(poss[i], d);
while (c) {
dist[d]++;
if (getroomid(c) == roomid) {
// mark dir as invalid
dist[d] = 999;
break;
} else if (cellwalkable(NULL, c, NULL)) {
// walkable and not in this vault. finished.
hitsedge[d] = B_FALSE;
break;
} else {
int perpdir[2],n;
cell_t *pcell = NULL;
perpdir[0] = d - 1; if (perpdir[0] < D_N) perpdir[0] = D_W;
perpdir[1] = d + 1; if (perpdir[1] > D_W) perpdir[1] = D_N;
// is there an adjacent walkable cell in a perpendicular direction
// which isn't from the starting room?
for (n = 0; n <= 1; n++) {
pcell = getcellindir(c, perpdir[n]);
if (pcell) {
if ((getroomid(pcell) != roomid) && cellwalkable(NULL, pcell, NULL)) {
// finished.
hitsedge[d] = B_FALSE;
break;
}
}
}
}
// check next cell
c = getcellindir(c, d); // getting the same cell!
}
if (dist[d] != 999) {
if (!hitsedge[d]) {
if (dist[d] < mindist) mindist = dist[d];
}
if (dist[d] > maxdist) maxdist = dist[d];
}
}
if (mindist == 999) {
cell_t *turncell = NULL,*endcell = NULL;
int perpdir[2];
int startdir = D_NONE;
int turndir = D_NONE;
int startdist = 0;
// no good directions.
if (db) dblog(" No directions lead to rooms. Trying turns.");
// starting at the LONGEST distance, traverse up each dir,
// branching off looking for rooms.
// find longest distance
for (d = D_N; d <= D_W; d++) {
if (dist[d] == maxdist) {
startdir = d;
break;
}
}
assert(startdir != D_NONE);
// figure out perpendicular dirs
perpdir[0] = startdir - 1; if (perpdir[0] < D_N) perpdir[0] = D_W;
perpdir[1] = startdir + 1; if (perpdir[1] > D_W) perpdir[1] = D_N;
if (db) dblog(" Will walk %s (dist %d), checking %s and %s.", getdirname(startdir), maxdist,
getdirname(perpdir[0]), getdirname(perpdir[1]));
// check in startdir
c = getcellindir(poss[i], startdir);
while (c && !turncell) {
int n;
cell_t *c2;
startdist++;
// check left/right from this door for rooms
for (n = 0; n <= 1; n++) {
int turndist = 0;
c2 = getcellindir(c, perpdir[n]);
while (c2) {
int gotsolution = B_FALSE;
turndist++;
if (getroomid(c2) == roomid) {
// hits same room, not ok.
break;
} else if (cellwalkable(NULL, c2, NULL)) {
if (db) dblog(" Got to an empty cell here.");
gotsolution = B_TRUE;
} else if (turndist > 1) {
// check l/r too
int perpdir2[2],nn;
cell_t *pcell = NULL;
perpdir2[0] = perpdir[n] - 1; if (perpdir2[0] < D_N) perpdir2[0] = D_W;
perpdir2[1] = perpdir[n] + 1; if (perpdir2[1] > D_W) perpdir2[1] = D_N;
for (nn = 0; nn <= 1; nn++) {
pcell = getcellindir(c2, perpdir2[nn]);
if (pcell) {
if ((getroomid(pcell) != roomid) &&
cellwalkable(NULL, pcell, NULL)) {
// finished.
if (db) dblog(" Got to an empty cell next to us.");
gotsolution = B_TRUE;
break;
}
}
}
}
if (gotsolution) {
if (db) dblog(" Solution found: Walk %d %s, then %d %s.",
startdist, getdirname(startdir),
turndist, getdirname(perpdir[n]));
// walkable and not in this roomid. ok!
turncell = c;
endcell = c2;
turndir = perpdir[n];
break;
}
// check next cell
c2 = getcellindir(c2, perpdir[n]);
}
if (turncell) break;
}
// now keep going in main direction.
c = getcellindir(c, startdir);
}
if (turncell) {
// make a path up to the turn point.
if (db) dblog(" Making path from vault to corner, initdir=%s", getdirname(startdir));
nadded++;
c = getcellindir(poss[i], startdir);
while (c != turncell) {
setcelltype(c, c->habitat->emptycelltype);
c = getcellindir(c, startdir);
}
// clear the corner cell
setcelltype(c, c->habitat->emptycelltype);
if (db) dblog(" Making path from corner to rest of map, turndir=%s", getdirname(turndir));
// now turn and clear up to the next room/empty cell
c = getcellindir(c, turndir);
while (c != endcell) {
setcelltype(c, c->habitat->emptycelltype);
c = getcellindir(c, turndir);
}
} else {
// give up??
if (db) dblog(" Cannot find a way to link up.");
}
} else {
int whichway,sel;
// now pick the shortest one which hits the edge
// get list of all the minimums and randomly tie-break
nposs2 = 0;
for (d = D_N; d <= D_W; d++) {
if (dist[d] == mindist) {
poss2[nposs2++] = d;
}
}
sel = rnd(0,nposs2-1);
whichway = poss2[sel];
// now create a path
if (db) dblog(" Linking %s (distance %d).", getdirname(whichway), mindist);
nadded++;
c = getcellindir(poss[i], whichway);
while (c && !cellwalkable(NULL, c, NULL)) {
setcelltype(c, c->habitat->emptycelltype);
c = getcellindir(c, whichway);
}
}
} // end if ncorridors = 0
nadded += linkexit(poss[i], B_FALSE, NULL);
}
} // end for each door
if (db) dblog("linkexits complete.");
if (db) dblog("linkexits complete (%d added).", nadded);
return nadded;
}
@ -3075,13 +3184,27 @@ int dirtoy(int dt, int dir) {
void dumpmap(map_t *map) {
int x,y;
cell_t *cell;
char ch;
printf("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h);
// top reference row
dblog_nocr(" ");
for (x = 0; x < map->w; x++) {
dblog_nocr("%d",x % 10);
}
dblog_nocr("\n");
for (y = 0; y < map->h; y++) {
dblog_nocr("%d",y % 10);
for (x = 0; x < map->w; x++) {
cell = getcellat(map, x, y);
printf("%c",cell->type->glyph.ch);
ch = cell->type->glyph.ch;
if ((ch == '.') && cell->filled) {
ch = 'o';
}
dblog_nocr("%c",ch);
}
printf("\n");
dblog_nocr("\n");
}
}
@ -3258,7 +3381,6 @@ cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf) {
cell_t *selection = NULL;
cell_t *bestcell = NULL;
int closest = 999;
// oooooo TODO handle side being diagonal
switch (side) {
case D_N:
case DC_N:
@ -4576,6 +4698,16 @@ void mapentereffects(map_t *m) {
addflag(lf->flags, F_STAYINROOM, getroomid(c), B_MAYCHASE, NA, NULL);
}
}
// monsters on the new level now get a bunch of turns to simulate them moving about when the player wasn't there.
if (m->lastplayervisit != -1) {
int nturns;
nturns = (curtime - m->lastplayervisit) / TICK_INTERVAL;
//nturns *= countlfs(m);
for (i = 0; i < nturns; i++) {
donextturn(m);
}
}
}
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob) {
@ -4624,6 +4756,28 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob) {
return R_NONE;
}
// returns # of dead ends removed.
int remove_deadends(map_t *m, int howmuch) {
enum CELLTYPE solidcell;
int i,n,count = 0;
solidcell = m->habitat->solidcelltype;
for (i = 0; i < howmuch; i++) {
for (n = 0; n < m->w * m->h; n++) {
cell_t *c;
c = m->cell[n];
if (countcellexits(c) == 1) {
// erase this cell
setcelltype(c, solidcell);
count++;
}
}
}
return count;
}
void setcellknown(cell_t *cell, int forcelev) {
enum SKILLLEVEL slev;
object_t *o;

5
map.h
View File

@ -15,6 +15,9 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
int cellhaslos(cell_t *c1, cell_t *dest);
void clearcell(cell_t *c);
int dowaterspread(cell_t *c);
void fix_reachability(map_t *m);
int fix_unreachable_cell(cell_t *badcell);
void floodfill(cell_t *startcell);
cell_t *getcellat(map_t *map, int x, int y);
int getcelldist(cell_t *src, cell_t *dst);
int getcelldistorth(cell_t *src, cell_t *dst);
@ -106,6 +109,7 @@ int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m);
int isroom(cell_t *c);
int iswallindir(cell_t *cell, int dir);
int linkexit(cell_t *c, int wantfilled, int *ncellsadded);
int linkexits(map_t *m, int roomid);
int linkholes(map_t *map);
int linkstairs(object_t *o, object_t *o2);
@ -114,6 +118,7 @@ void makelit(cell_t *c, enum LIGHTLEV how, int howlong);
void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);
void mapentereffects(map_t *m);
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob);
int remove_deadends(map_t *m, int howmuch);
void setcellknown(cell_t *cell, int forcelev);
void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype);
void setcelltype(cell_t *cell, enum CELLTYPE id);

82
move.c
View File

@ -31,6 +31,8 @@ extern void *rdata;
extern flag_t *retflag[];
extern int nretflags;
extern long curtime;
extern WINDOW *gamewin, *msgwin;
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) {
@ -148,7 +150,7 @@ int canswapwith(lifeform_t *lf, lifeform_t *lf2) {
// onlyifknown = true means "check for _known_ dangerous objects"
// onlyifknown = false means "check for _any dangerous objects, doesn't matter if we know about them"
int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *error) {
enum ATTRBRACKET iq;
enum ATTRBRACKET wis;
int include_nonobvious = B_FALSE;
flag_t *f;
object_t *o;
@ -177,7 +179,6 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
}
}
for (o = cell->obpile->first ; o ; o = o->next) {
if (onlyifknown && !canseeob(lf, o)) continue;
if (hasflag(o->flags, F_TRAP)) {
@ -239,8 +240,8 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
if (!onlyifknown) {
include_nonobvious = B_TRUE;
} else {
iq = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
if ((iq >= AT_AVERAGE) && haslos(lf, cell)) {
wis = getattrbracket(getattr(lf, A_WIS), A_WIS, NULL);
if ((wis >= AT_AVERAGE) && haslos(lf, cell)) {
if (!lfhasflag(lf, F_UNDEAD)) {
include_nonobvious = B_TRUE;
}
@ -311,7 +312,7 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
if ((mid == MT_GAS) ||
(mid == MT_SLIME)) {
// ok
} else if (lfhasflag(lf, F_NONCORPOREAL)) {
} else if (lfhasflag(lf, F_NONCORPOREAL) && !hasflag(o->flags, F_REALLYIMPASSABLE)) {
// ok but still set error
*error = E_OBINWAY;
} else {
@ -945,9 +946,13 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if (newcell->map != lf->cell->map) {
changedlev = B_TRUE;
if (isplayer(lf)) {
// remember the time which we exitted this map.
lf->cell->map->lastplayervisit = curtime;
}
}
// update current cell + room id
// remember current cell + room id
prespeed = getmovespeed(lf);
preroom = getroomid(lf->cell);
v = getcellvault(lf->cell);
@ -960,6 +965,25 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
prewater = B_TRUE;
}
// special effects when the player moves to a new map
if (changedlev && isplayer(lf)) {
object_t *o;
long barrierid = -1;
// mapentereffects will give all monster on the new map
// a bunch of turns to simulate time passing while the player
// was away. to prevent them from blocking off the staircase cell
// where the player is about to arrive, place a magic barrier over it.
o = addobfast(newcell->obpile, OT_MAGICBARRIER);
if (o) barrierid = o->id;
mapentereffects(newcell->map);
// now remove the barrier
o = hasobid(newcell->obpile, barrierid);
if (o) killob(o);
}
// move out...
lf->cell->lf = NULL;
@ -992,13 +1016,6 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// update new cell
newcell->lf = lf;
/*
// update light
if (lfproduceslight(lf) || (changedlev && isplayer(lf))) {
calclight(lf->cell->map);
precalclos(lf);
}
*/
// update light
if (lfproduceslight(lf)) {
calclight(lf->cell->map);
@ -1009,11 +1026,6 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
needredraw = B_TRUE;
}
// special effects when the player moves to a new map
if (changedlev && isplayer(lf)) {
mapentereffects(newcell->map);
}
didmsg = moveeffects(lf);
killflagsofid(lf->flags, F_HIDING);
@ -1339,7 +1351,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
if (getlfmaterial(lf) == MT_GAS) {
char obname[BUFLEN];
for (o = newcell->obpile->first ; o ; o = o->next) {
if (isimpassableob(o, lf)) {
if (isimpassableob(o, lf) && !hasflag(o->flags, F_REALLYIMPASSABLE)) {
getobname(o, obname, o->amt);
if (isplayer(lf)) {
msg("You seep around %s.", obname);
@ -2087,7 +2099,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
f = isdrunk(lf);
if (f) {
if (!hasjob(lf, J_PIRATE)) {
if (rnd(1,6) <= ((f->lifetime/DRUNKTIME)+1)) {
if (rnd(1,6) <= ((f->lifetime/TM_DRUNKTIME)+1)) {
// randomize move
dir = rnd(DC_N, DC_NW);
drunk = B_TRUE; // ie. you can walk into walls now.
@ -2099,22 +2111,20 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
if (isplayer(lf) && !lfhasflag(lf, F_SNEAK)) {
if (cell && celldangerous(lf, cell, B_TRUE, &errcode)) {
if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_AVERAGE) {
char ques[BUFLEN];
char ch;
if ((errcode == E_AVOIDOB) && rdata) {
char obname[BUFLEN];
object_t *avoidob;
avoidob = (object_t *)rdata;
getobname(avoidob, obname, avoidob->amt);
sprintf(ques, "Really %s into %s?", getmoveverb(lf), obname);
} else {
sprintf(ques, "Really %s there?", getmoveverb(lf));
}
ch = askchar(ques, "yn","n", B_TRUE);
if (ch != 'y') {
return B_TRUE;
}
char ques[BUFLEN];
char ch;
if ((errcode == E_AVOIDOB) && rdata) {
char obname[BUFLEN];
object_t *avoidob;
avoidob = (object_t *)rdata;
getobname(avoidob, obname, avoidob->amt);
sprintf(ques, "Really %s into %s?", getmoveverb(lf), obname);
} else {
sprintf(ques, "Really %s there?", getmoveverb(lf));
}
ch = askchar(ques, "yn","n", B_TRUE);
if (ch != 'y') {
return B_TRUE;
}
}
}

321
nexus.c
View File

@ -375,22 +375,17 @@ int main(int argc, char **argv) {
needredraw = B_FALSE;
numdraws = 0;
// someone has a turn - this will then call taketime -> timehappens();
// someone has a turn - this will then call taketime
donextturn(curmap);
// update lifeform structue to figure out who goes next
//timehappens(curmap);
// show level (if required)
//if (haslos(player, curmap->lf->cell)) {
drawscreen();
//dblog("**** END of turn, numdraws = %d", numdraws);
// check end of game
checkendgame();
}
// identify all objects
@ -559,143 +554,154 @@ void donextturn(map_t *map) {
oldpmap = player->cell->map;
who = map->lf;
if (db) dblog("**** donextturn for: id %d %s", who->id, who->race->name);
if (who) {
if (db) dblog("**** donextturn for: id %d %s", who->id, who->race->name);
assert(who->timespent == 0);
assert(who->timespent == 0);
turneffectslf(who);
turneffectslf(who);
// calculate light
calclight(map);
// pre-calculate line of sight for this lifeform
precalclos(who);
// calculate light
calclight(map);
// pre-calculate line of sight for this lifeform
precalclos(who);
/*
if (isplayer(who) || cansee(player, who)) {
needredraw = B_TRUE;
drawscreen();
}
*/
// update gun targets
autotarget(who);
// update gun targets
autotarget(who);
// keep looping until they actually do something or are dead!
while (who->timespent == 0) {
if (isdead(who)) {
// skip turn
taketime(who, SPEED_DEAD);
} else {
// do we need to run away from something?
if (!flee(who)) {
int donormalmove = B_TRUE;
flag_t *f;
// casting a spell?
if (donormalmove) {
f = lfhasflag(who, F_CASTINGSPELL);
if (f) {
donormalmove = B_FALSE;
f->val[2]--;
if (f->val[2] <= 0) {
char *p;
char buf[BUFLEN];
int lfid,mapid,x,y,power;
long obid;
lifeform_t *targlf;
object_t *targob;
cell_t *targcell;
map_t *targmap;
enum OBTYPE sid;
sid = f->val[0];
power = f->val[1];
// keep looping until they actually do something or are dead!
while (who->timespent == 0) {
if (isdead(who)) {
// skip turn
taketime(who, SPEED_DEAD);
} else {
// do we need to run away from something?
if (!flee(who)) {
int donormalmove = B_TRUE;
flag_t *f;
// finished!
p = f->text;
p = readuntil(buf, p, ';');
lfid = atoi(p);
p = readuntil(buf, p, ';');
obid = atol(p);
p = readuntil(buf, p, ';');
mapid = atoi(p);
p = readuntil(buf, p, ';');
x = atoi(p);
p = readuntil(buf, p, ';');
y = atoi(p);
// casting a spell?
if (donormalmove) {
f = lfhasflag(who, F_CASTINGSPELL);
if (f) {
donormalmove = B_FALSE;
f->val[2]--;
if (f->val[2] <= 0) {
char *p;
char buf[BUFLEN];
int lfid,mapid,x,y,power;
long obid;
lifeform_t *targlf;
object_t *targob;
cell_t *targcell;
map_t *targmap;
enum OBTYPE sid;
sid = f->val[0];
power = f->val[1];
// finished!
p = f->text;
p = readuntil(buf, p, ';');
lfid = atoi(p);
p = readuntil(buf, p, ';');
obid = atol(p);
p = readuntil(buf, p, ';');
mapid = atoi(p);
p = readuntil(buf, p, ';');
x = atoi(p);
p = readuntil(buf, p, ';');
y = atoi(p);
if (lfid >= 0) {
targlf = findlf(NULL, lfid);
} else {
targlf = NULL;
}
if (obid >= 0) {
targob = findobidinmap(who->cell->map, obid);
} else {
targob = NULL;
}
if (mapid >= 0) {
targmap = findmap(mapid);
targcell = getcellat(targmap, x, y);
}
taketime(who, getspellspeed(who));
dospelleffects(who, sid, power, targlf, targob, targcell, B_UNCURSED, NULL, B_FALSE);
killflagsofid(who->flags, F_CASTINGSPELL);
} else {
if (isplayer(who)) {
objecttype_t *sp;
sp = findot(f->val[0]);
msg("You continue casting %s.", sp->name);
} else if (cansee(player, who)) {
flag_t *f2;
char lfname[BUFLEN];
// still going...
getlfname(who, lfname);
f2 = lfhasflag(who,F_SPELLCASTTEXT);
if (f2 && strlen(f2->text)) {
msg("%s %s.", lfname, f2->text);
if (lfid >= 0) {
targlf = findlf(NULL, lfid);
} else {
msg("%s continues casting a spell.", lfname);
targlf = NULL;
}
if (obid >= 0) {
targob = findobidinmap(who->cell->map, obid);
} else {
targob = NULL;
}
if (mapid >= 0) {
targmap = findmap(mapid);
targcell = getcellat(targmap, x, y);
}
taketime(who, getspellspeed(who));
dospelleffects(who, sid, power, targlf, targob, targcell, B_UNCURSED, NULL, B_FALSE);
killflagsofid(who->flags, F_CASTINGSPELL);
} else {
if (isplayer(who)) {
objecttype_t *sp;
sp = findot(f->val[0]);
msg("You continue casting %s.", sp->name);
} else if (cansee(player, who)) {
flag_t *f2;
char lfname[BUFLEN];
// still going...
getlfname(who, lfname);
f2 = lfhasflag(who,F_SPELLCASTTEXT);
if (f2 && strlen(f2->text)) {
msg("%s %s.", lfname, f2->text);
} else {
msg("%s continues casting a spell.", lfname);
}
}
}
}
}
}
// eating?
if (donormalmove) {
f = lfhasflag(who, F_EATING);
if (f) {
object_t *o;
o = findobbyid(who->pack, atol(f->text));
if (!o) {
o = findobidinmap(who->cell->map, atol(f->text));
}
if (o && caneat(who, o) && (getoblocation(o) == who->cell)) {
eat(who,o);
donormalmove = B_FALSE;
} else {
killflag(f);
// eating?
if (donormalmove) {
f = lfhasflag(who, F_EATING);
if (f) {
object_t *o;
o = findobbyid(who->pack, atol(f->text));
if (!o) {
o = findobidinmap(who->cell->map, atol(f->text));
}
if (o && caneat(who, o) && (getoblocation(o) == who->cell)) {
eat(who,o);
donormalmove = B_FALSE;
} else {
killflag(f);
}
}
}
}
// resting?
if (donormalmove) {
f = isresting(who);
if (!f) {
f = lfhasflag(who, F_TRAINING);
// resting?
if (donormalmove) {
f = isresting(who);
if (!f) {
f = lfhasflag(who, F_TRAINING);
}
if (f) {
// check for interrupt of resting...
if (isplayer(who) && checkforkey()) {
msg("Stopped %s.",(f->id == F_TRAINING) ? "training" : "resting");
killflag(f);
} else {
if (isplayer(who)) {
if (++who->turnsskipped >= 10) {
//msg("Time passes...");
msg(".");
who->turnsskipped = 0;
}
}
rest(who, B_TRUE);
donormalmove = B_FALSE;
}
}
}
if (f) {
// check for interrupt of resting...
if (isplayer(who) && checkforkey()) {
msg("Stopped %s.",(f->id == F_TRAINING) ? "training" : "resting");
killflag(f);
} else {
if (donormalmove) {
// paralyzed etc?
if (isimmobile(who)) {
if (isplayer(who)) {
if (++who->turnsskipped >= 10) {
//msg("Time passes...");
@ -703,54 +709,34 @@ void donextturn(map_t *map) {
who->turnsskipped = 0;
}
}
rest(who, B_TRUE);
rest(who, B_FALSE);
donormalmove = B_FALSE;
}
}
}
if (donormalmove) {
// paralyzed etc?
if (isimmobile(who)) {
if (donormalmove) {
if (isplayer(who)) {
if (++who->turnsskipped >= 10) {
//msg("Time passes...");
msg(".");
who->turnsskipped = 0;
}
drawcursor();
// find out what player wants to do
handleinput();
} else {
//char lfname[BUFLEN];
//char buf[BUFLEN];
// do ai move
//real_getlfname(who, lfname, B_FALSE);
//sprintf(buf, "aimove %s",lfname);
//dbtimestart(buf);
aiturn(who);
//dbtimeend(buf);
}
rest(who, B_FALSE);
donormalmove = B_FALSE;
}
}
if (donormalmove) {
if (isplayer(who)) {
drawcursor();
// find out what player wants to do
handleinput();
} else {
//char lfname[BUFLEN];
//char buf[BUFLEN];
// do ai move
//real_getlfname(who, lfname, B_FALSE);
//sprintf(buf, "aimove %s",lfname);
//dbtimestart(buf);
aiturn(who);
//dbtimeend(buf);
}
}
}
}
}
if (hasflag(player->flags, F_ASLEEP)) {
needredraw = B_FALSE;
/*
} else if (isdead(who) || cansee(player, who)) {
needredraw = B_TRUE;
*/
if (hasflag(player->flags, F_ASLEEP)) {
needredraw = B_FALSE;
}
}
// check for death etc
@ -764,7 +750,8 @@ void donextturn(map_t *map) {
// note: can't use 'who->' below since 'who' might have died
// and been de-alloced during checkdeath() above if they
// died.
timeeffectsworld(player->cell->map);
//timeeffectsworld(player->cell->map);
timeeffectsworld(map, B_TRUE);
// the previous call to timeeffectsworld might cause the player to
// change levels (ie. falling down through one or more pits).
@ -773,7 +760,7 @@ void donextturn(map_t *map) {
// values don't get out of whack.
while (player->cell->map != oldpmap) {
oldpmap = player->cell->map;
timeeffectsworld(player->cell->map);
timeeffectsworld(player->cell->map, B_FALSE);
}
}
@ -1425,7 +1412,7 @@ void sortcommands(void) {
void timeeffectsworld(map_t *map) {
void timeeffectsworld(map_t *map, int updategametime) {
flag_t *retflag[MAXCANDIDATES];
int nretflags;
lifeform_t *l;
@ -1544,8 +1531,10 @@ void timeeffectsworld(map_t *map) {
//dumplf();
} // end if timespent
// inc game time
curtime += firstlftime;
if (updategametime) {
// inc game time
curtime += firstlftime;
}
if (db) dblog("cur time is %ld\n",curtime);
}

View File

@ -33,5 +33,5 @@ int rollhitdice(lifeform_t *lf);
int rollmpdice(lifeform_t *lf);
//void sortlf(map_t *map);
void sortcommands(void);
void timeeffectsworld(map_t *map);
void timeeffectsworld(map_t *map, int updategametime);
void usage(char *progname);

View File

@ -2196,7 +2196,7 @@ int canseeob(lifeform_t *lf, object_t *o) {
case PR_INEPT: cutoffpct = 200; break;
}
cutoff = pctof(cutoffpct, FOOTPRINTTIME);
cutoff = pctof(cutoffpct, TM_FOOTPRINT);
if (f->lifetime >= cutoff) {
return B_TRUE;
@ -4129,7 +4129,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
char adjective[BUFLEN];
lifeform_t *who = NULL;
pct = ((float)f->lifetime / (float)SCENTTIME)*100;
pct = ((float)f->lifetime / (float)TM_SCENT)*100;
if (pct >= 66) {
strcpy(adjective, "strong ");
} else if (pct >= 33) {
@ -4161,7 +4161,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
// adept and upwards gets depth
if (slev >= PR_BEGINNER) {
float pct;
pct = ((float)f->lifetime / (float)FOOTPRINTTIME)*100;
pct = ((float)f->lifetime / (float)TM_FOOTPRINT)*100;
if (pct >= 66) {
strcpy(basename, "fresh ");
} else if (pct >= 33) {
@ -8573,6 +8573,7 @@ void initobjects(void) {
addot(OT_MAGICBARRIER, "magical barrier", "A glowing, impassable barrier of magical energy.", MT_MAGIC, 0, OC_EFFECT, SZ_LARGE);
addflag(lastot->flags, F_GLYPH, C_YELLOW, NA, NA, "#");
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_REALLYIMPASSABLE, NA, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes");
@ -10560,10 +10561,10 @@ void makewet(object_t *o, int amt) {
}
*/
f->val[0] += amt;
f->val[1] = WETTIME;
f->val[1] = TM_WETTIME;
} else {
// jsut reset wettime
f->val[1] = WETTIME;
f->val[1] = TM_WETTIME;
}
} else {
@ -10571,7 +10572,7 @@ void makewet(object_t *o, int amt) {
if (haslos(player, loc) && !isdead(player)) {
msg("%s get%s wet.",obnamefull, (o->amt == 1) ? "s" : "");
}
f = addflag(o->flags, F_WET, amt, WETTIME, NA, NULL);
f = addflag(o->flags, F_WET, amt, TM_WETTIME, NA, NULL);
}
}
}
@ -12565,9 +12566,9 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
} else if (cansee(player, lf)) {
msg("%s looks more tipsy.", lfname);
}
f->lifetime += DRUNKTIME;
f->lifetime += TM_DRUNKTIME;
} else {
addtempflag(lf->flags, F_DRUNK, 1, NA, NA, NULL, DRUNKTIME);
addtempflag(lf->flags, F_DRUNK, 1, NA, NA, NULL, TM_DRUNKTIME);
}
}
break;

2
save.c
View File

@ -308,6 +308,7 @@ map_t *loadmap(char *basefile) {
fscanf(f, "habitat:%d\n",(int *)&habitatid); // habitat
m->habitat = findhabitat(habitatid);
fscanf(f, "seed:%d\n",&m->seed); // seed
fscanf(f, "lastplayervisit:%ld\n",&m->lastplayervisit);
fscanf(f, "dims:%d,%d\n",&m->w, &m->h); // map dimensons
fscanf(f, "nextmaps:\n");
for (i = 0; i < MAXDIR_ORTH; i++) {
@ -859,6 +860,7 @@ int savemap(map_t *m) {
fprintf(f, "name:%s\n",m->name); // map name
fprintf(f, "habitat:%d\n",m->habitat->id); // habitat
fprintf(f, "seed:%d\n",m->seed); // seed
fprintf(f, "lastplayervisit:%ld\n",m->lastplayervisit);
fprintf(f, "dims:%d,%d\n",m->w, m->h); // map dimensons
fprintf(f, "nextmaps:\n");
for (i = 0; i < MAXDIR_ORTH; i++) {

View File

@ -2926,12 +2926,17 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("Couldn't create a vault.");
} else {
char ch;
cell_t *c;
// link the new vault to the rest of the map
c = getcellat(caster->cell->map, vx, vy);
linkexits(caster->cell->map, getroomid(c));
msg("BAM! A vault has appeared nearby."); more();
needredraw = B_TRUE;
ch = askchar("Teleport to the new vault", "yn","y", B_TRUE);
if (ch == 'y') {
int x,y;
cell_t *c;
// find it
for (y = vy; y < vy+vh; y++) {
for (x = vy; x < vx + vw; x++) {

2
text.c
View File

@ -241,7 +241,7 @@ char *getpossessive(char *text) {
char *getdrunktext(flag_t *drunkflag) {
int bracket;
bracket = (drunkflag->lifetime / DRUNKTIME) + 1;
bracket = (drunkflag->lifetime / TM_DRUNKTIME) + 1;
if (bracket == 1) {
return "tipsy";
} else if (bracket == 2) {