* [+] vaiultlegend_t
* [+] vaultdef_t
- [+] implement addlegend()
- [+] implement addvault()
- [+] function to read in a vault from a data file
    - [+] vs_noid
    - [+] vs_loadingmap
    - [+] vs_loadinglegend
    - [+] vs_loadingflags
    - [+] vs_loading
- [+] load all vaultdefs in at start
- [+] change createroom to calculate the posistion
- [+] for each room, give a %chance of haivng a vault. (based on
      habitat?)
* [+] createvault(map_t, roomid?, char *vaultid)
- [+] mapdata with letters
* [+] MSG up vault errors on load.
- [+] Select job _before_ generating first map.
* [+] make addob() handle door flags:
* [+] addob() improvements
* [+] wish bug: first object goes in pack, rest on ground.
- [+] genericise getroomedge()
- [+] finish 'autodoors' (at the end, add doors if none already done)
- [+] at(x,y):type:what:pct -> f_vaultob / vaultlf / vaultcell, v0=x,
      v1=y, v2=pct text=what
* [+] "what" can be:
* [+] scatter:y1:x2:y2:what:chance%:howmany
* [+] some way to make the @map bit just say 'random room at least 2x4'
- [+] make "scatter" able to take range instead of count.
- [+] make "scatter"able to take x% instead of count.
- [+] upsidedown chars no longer working with winch()
- [+] ensure no DUPE ids
- [+] make legend take percentages (optional)
- [+] make "at" take negative values...
OPTIONS
- [+] autodoors - put doors on edges like with normal dungeon rooms.
* [+] autopop - fill with obs/monsters like normal rooms
VAULT FILES
- [+] flooded room
- [+] labyrinth
- [+] vault (lots of money, locked secret doors)
- [+] monster zoos (money and monsters)
- [+] diningroom - lots of tables and chairs
- [+] circleroom
- [+] pillared room
- [+] glass pillared room
- [+] cockatrice lair (statues)
- [+] traproom - need "random trap".  need OC_TRAP.
- [+] BUG: piranhas walking out of water sometimes.......
- [+] add startatt x-y rather than just a bracket. use text field.
- [+] make teleport auto move away form lfs
- [+] add minotaur
This commit is contained in:
Rob Pearce 2011-06-02 08:34:44 +00:00
parent af0d8f244d
commit 11c03d71cf
14 changed files with 1629 additions and 821 deletions

View File

@ -1,2 +1,2 @@
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h
gcc -Wall -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c -lncurses
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h vault.c vault.h
gcc -Wall -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c vault.c vault.h -lncurses

104
defs.h
View File

@ -1,6 +1,8 @@
#ifndef __DEFS_H
#define __DEFS_H
// MACROS
#define MAXOF(a,b) (a > b ? a : b)
@ -102,6 +104,7 @@ enum SKILLLEVEL {
// save/load
#define MAPDIR "data/maps"
#define SAVEDIR "data/save"
#define VAULTDIR "vaults"
#define DUMMYCELLTYPE 0xabcd
// SPECIAL NUMBERS/CONSTANTS
@ -110,10 +113,10 @@ enum SKILLLEVEL {
#define NA (-9874)
#define NOBODY (-1)
#define ALLCONFERRED (-9873)
#define PCT (65432) // must be POSITIVE
#define AUTO (-7654)
enum GAMEMODE {
GM_FIRST,
GM_INIT,
@ -407,8 +410,11 @@ enum LOFTYPE {
// Cell types
enum CELLTYPE {
CT_NONE = 0,
// walls
CT_WALL,
CT_WALLGLASS,
CT_WALLMETAL,
CT_ROOMWALL,
// empty
CT_CORRIDOR,
@ -419,12 +425,6 @@ enum CELLTYPE {
CT_ROOM,
};
enum SPECIALROOMTYPE {
RT_NONE = 0,
RT_FLOODED,
};
enum SPELLSCHOOL {
SS_NONE,
SS_DIVINE,
@ -573,17 +573,24 @@ enum HABITAT {
#define RARITYVARIANCELF (5)
#define RARITYVARIANCEOB (10)
/*
enum RARITY {
RR_UNIQUE = 7,
RR_NEVER = 6,
RR_VERYRARE = 5,
RR_RARE = 4,
RR_UNCOMMON = 3,
RR_COMMON = 2,
RR_FREQUENT = 1,
RR_UNIQUE = 6,
RR_NEVER = 5,
RR_VERYRARE = 4,
RR_RARE = 3,
RR_UNCOMMON = 2,
RR_COMMON = 1,
RR_NONE = 0,
};
// for genericising weapons, etc
enum GOODNESS {
G_NA = 0,
G_AVERAGE,
G_GOOD,
G_GREAT,
G_EXCELLENT,
};
*/
enum RACECLASS {
RC_ANY, // not actually ever defined
@ -627,6 +634,7 @@ enum RACE {
R_KOBOLD,
R_LIZARDMAN,
R_LURKINGHORROR,
R_MINOTAUR,
R_OGRE,
R_OGRESAVAGE,
R_OGREWARHULK,
@ -1735,7 +1743,7 @@ enum FLAG {
F_HASHIDDENNAME, // whether this object class has a hidden name
F_IDENTIFIED, // whether this object is fully identified
// bad flags
F_DEEPWATER, // v0 = depth.oooooooooooo
F_DEEPWATER, // v0 = depth.
F_WALKDAM, // val0 = damtype, text = dam per sec
F_WALKDAMBP, // v0 = bodypart, v1 = damtype, text = dam per sec
// if v2 == FALLTHRU, damage falls through to lf if
@ -1805,6 +1813,10 @@ enum FLAG {
// calculation
F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid
F_STARTATT, // val0 = A_xxx, val0 = start bracket (ie. IQ_GENIUS)
// if text is set, it overrides val0.
// text can be:
// x (single number)
// x-y (range)
F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will
// start off hidden
F_CORPSETYPE, // text field specifies what corpse obtype to leave
@ -2088,7 +2100,20 @@ enum FLAG {
F_LEVFLAG, // at level v0, this job gains flagid v1, flagval0=v2,
// flagtext = text
//
// vault flags
F_AUTODOORS, // automatically create at least one door
F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms
F_VAULTATOB, // v0/1=x/y, v1=pctchance, text=obname
F_VAULTATLF, // v0/1=x/y, v1=pctchance, text=lfname
F_VAULTATCELL, // v0/1=x/y, v1=pctchance, text=cellname
F_VAULTBOX, // v0=thingtype, v1=pctchance, v2=fill?, text=x1,y1,x2,y2,thingname
F_VAULTSCATTER, // v0=thingtype, v1=pctchance
// text=x1,y1,x2,y2,mincount-maxcount,thingname
// if maxcount is PCT, mincount is a percentage
// of the total space.
F_VAULTRANDOMMAP, // v0=minwidth, v1=minheight. this vault's map is
// v0/1 can be NA.
// just a normal random room
F_NULL = -1
};
@ -2325,6 +2350,46 @@ typedef struct map_s {
struct map_s *next, *prev;
} map_t; //////////////// remember to modify save/load for new props!!
#define MAXVAULTARGS 10
enum VAULTSTATE {
VS_ALLOCATED,
VS_NOID,
VS_LOADING,
VS_LOADINGMAP,
VS_LOADINGLEGEND,
VS_LOADINGFLAGS,
};
enum VAULTTHING {
VT_NONE,
VT_OB,
VT_LF,
VT_CELL,
};
typedef struct vlegend_s {
char ch;
enum VAULTTHING tt;
char *what;
int pct;
struct vault_s *vault;
struct vlegend_s *next, *prev;
} vlegend_t;
typedef struct vault_s {
char *filename;
char *id;
int valid;
int state;
char map[MAX_MAPW*MAX_MAPH];
int mlen;
int w,h;
struct vlegend_s *legend, *lastlegend;
struct vault_s *next, *prev;
struct flagpile_s *flags;
} vault_t;
typedef struct glyph_s {
int ch;
int colour;
@ -2513,10 +2578,13 @@ typedef struct job_s {
struct job_s *next, *prev;
} job_t;
#define MAXOCNOUNS 5
typedef struct objectclass_s {
enum OBCLASS id;
char *name;
char *desc;
char *noun[MAXOCNOUNS];
int nnouns;
glyph_t glyph;
struct flagpile_s *flags;
struct objectclass_s *next, *prev;

53
doc/vaults.txt Normal file
View File

@ -0,0 +1,53 @@
General format:
@id:textual_name
@map
EITHER
map definition
OR
random(minw,minh)
@end
@legend
k:mon:kobold
s:ob:50:short sword
#:cell:stone wall
@end
@flags
...
@end
Legend is:
c:type:what[:pct]
c = any letter
type = ob, mon or cell
pct = optional pct chance of appearing
what = text of what this letter represents
Flags can be:
at(x,y) type:what[:pct] // put what at position x,y
'type' can be: ob, mon, cell
coords can be negative ("count back from right/bottom")
box(x,y,x2,y2) type:what[:pct] // outline box with what
fill(x,y,x2,y2) type:what[:pct] // filled box with what
coords can be negative ("count back from right/bottom")
scatter(x,y,x2,y2) type:what:howmany[:pct] // scatter what within region
howmany can be:
- a number (x)
- a range (x-y)
- a pct of the total region cells (x%)
coords can be negative ("count back from right/bottom")
autodoors // automatically add at least one door to the edges of
// this room.
autopop // automatically add obs/mons/pillars to this room
NOTES:
when adding lfs/objects, "random" creates a random one.

8
io.c
View File

@ -5038,8 +5038,12 @@ void drawglyph(glyph_t *g, int x, int y) {
col = g->colour;
}
setcol(gamewin, col);
//mvwprintw(gamewin, y, x, "%lc", g->ch);
mvwaddch(gamewin, y, x, g->ch);
if (g->ch > 255) {
// note: much slower
mvwprintw(gamewin, y, x, "%lc", g->ch);
} else {
mvwaddch(gamewin, y, x, g->ch);
}
unsetcol(gamewin, col);
}

57
lf.c
View File

@ -6875,7 +6875,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings");
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_GIANTHILL, "hill giant", 160, 'H', C_BROWN, MT_FLESH, RC_HUMANOID);
addrace(R_GIANTHILL, "hill giant", 160, 'H', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL);
@ -7348,6 +7348,34 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addrace(R_MINOTAUR, "minotaur", 130, 'H', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 62, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HATESRACE, R_GNOLL, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 6, 3, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 12, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "5-7");
addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, ST_TITANIC, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_BUTT, NA, NA, "2d4");
addflag(lastrace->flags, F_HASATTACK, OT_BUTT, NA, NA, "2d4");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "+2 heavy flail");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "greataxe");
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_EXPERT, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "roars^a roar");
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 20, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addrace(R_OGRE, "ogre", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
@ -11391,7 +11419,27 @@ int rollstat(lifeform_t *lf, enum ATTRIB attr) {
f = hasflagval(lf->flags, F_STARTATT, attr, NA, NA, NULL);
if (f) {
bracket = f->val[1];
if (strlen(f->text)) {
int val;
if (strchr(f->text, '-')) {
int min,max;
char *p;
char buf[BUFLENSMALL];
// text is a range
p = readuntil(buf, f->text, '-');
min = atoi(buf);
p = readuntil(buf, p, '-');
max = atoi(buf);
val = rnd(min,max);
} else {
val = atoi(f->text);
}
lf->att[attr] = val;
return B_FALSE;
} else {
bracket = f->val[1];
}
} else {
switch (attr) {
case A_STR:
@ -13686,6 +13734,11 @@ int validateraces(void) {
printf("ERROR in race '%s' - F_HITCONFER, but no HITCONFERVALS defined.\n", r->name);
goterror = B_TRUE;
}
} else if (f->id == F_STARTATT) {
if (strlen(f->text) && (f->val[1] != NA)) {
printf("ERROR in race '%s' - F_STARTATT has both text range and val1.", r->name);
goterror = B_TRUE;
}
} else if (f->id == F_NOISETEXT) {
if (f->val[0] == N_FLY) {
if (!hasflag(r->flags, F_FLYING) && !hasflag(r->flags, F_LEVITATING)) {

725
map.c
View File

@ -12,6 +12,7 @@
#include "map.h"
#include "objects.h"
#include "text.h"
#include "vault.h"
extern map_t *firstmap,*lastmap;
extern celltype_t *firstcelltype, *lastcelltype;
@ -169,12 +170,6 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
if (autogen) {
// sometimes start off asleep in new maps
if (!lfhasflag(lf, F_DEAF) && cansleep(lf)) {
// TODO: base this on the time, and whether monster is nocturnal
if (rnd(1,2) == 1) {
addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
}
}
f = lfhasflag(lf, F_STARTHIDDENPCT);
if (f) {
if (rnd(1,100) <= f->val[0]) {
@ -184,6 +179,12 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
addflag(lf->flags, F_HIDING, 0, NA, NA, NULL);
}
}
if (!lfhasflag(lf, F_HIDING) && !lfhasflag(lf, F_DEAF) && cansleep(lf)) {
// TODO: base this on the time, and whether monster is nocturnal
if (rnd(1,2) == 1) {
addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
}
}
}
// appears in groups?
@ -358,6 +359,134 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) {
return rv;
}
// whichside should be D_ORTH
// for now, this function will NOT include room corners
void getroomedge(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells) {
int x,y;
*ncells = 0;
if (whichside == D_N) {
y = miny;
for (x = minx+1; x <= maxx-1; x++) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
}
} else if (whichside == D_S) {
y = maxy;
for (x = minx+1; x <= maxx-1; x++) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
}
} else if (whichside == D_W) {
x = minx;
for (y = miny+1; y <= maxy-1; y++) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
}
} else if (whichside == D_E) {
x = maxx;
for (y = miny+1; y <= maxy-1; y++) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
}
}
}
void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) {
int i,d;
cell_t *poss[MAXCANDIDATES], *cell[MAXCANDIDATES]; // TODO: should this be maxroomw * maxroomh ?
int ncells = 0, npossible = 0;
int doorsadded = 0;
// for each side, make list of all possible door locations
// then pick one randomly.
// BUT if the nearby corridor only has one exit, always
// place a door.
for (d = D_N; d <= D_W; d++) {
npossible = 0;
getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells);
for (i = 0; i < ncells; i++) {
cell_t *newcell;
// is there empty space on the other side of this wall segment?
newcell = getcellindir(cell[i], d);
if (newcell && !newcell->type->solid) {
int doorcount;
// if so, make sure there are no other adjacent doors
doorcount = countadjcellswithflag(cell[i], F_DOOR);
if (doorcount == 0) {
// if there is only one way out of the adjacent empty cell, and
// walls to either side of the potential door location, then
// always add a door
if ((countcellexits(newcell) == 1) && wallstoleftright(newcell, d)) {
if (onein(2)) {
makedoor(cell[i]);
} else {
setcelltype(cell[i], getemptycelltype(map->habitat));
}
} else {
// otherwise mark this as a _potential_ door location.
poss[npossible] = cell[i];
npossible++;
}
}
}
}
// if we have potential door locations, add one somewhere along this wall.
if (npossible > 0) {
int sel;
sel = rnd(0,npossible-1);
makedoor(poss[sel]);
doorsadded++;
}
} // end foreach direction
if (doorsadded == 0) {
int i,d,used[MAXDIR_ORTH],poss[MAXDIR_ORTH];
int dodoor[MAXDIR_ORTH];
int ndodoors = 0;
int ndoors,nposs = 0;
int sel;
//
for (d = D_N; d <= D_W; d++) {
used[d] = B_FALSE;
}
// no possible door locations - add a random number
ndoors = rnd(1,4);
for (i = 0; i < ndoors; i++) {
// find a dir we haven't already used
nposs = 0;
for (d = D_N; d <= D_W; d++) {
if (!used[d]) poss[nposs++] = d;
}
if (nposs <= 0) {
break;
}
sel = rnd(0,nposs-1);
used[poss[sel]] = B_TRUE;
dodoor[ndodoors++] = poss[sel];
}
// actually make the doors
for (i = 0; i < ndodoors; i++) {
int sel;
d = dodoor[i];
getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells);
sel = rnd(0,ncells-1);
if (onein(2)) {
makedoor(cell[sel]);
} else {
setcelltype(cell[sel], getemptycelltype(map->habitat));
}
}
}
}
int cellhaslos(cell_t *c1, cell_t *dest) {
int deltax, deltay;
int numpixels;
@ -579,6 +708,13 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
}
}
int getdoorlockdiff(int depth) {
return 19 + depth;
}
int getdoorsecretdiff(int depth) {
return 20 + (depth / 2);
}
enum CELLTYPE getemptycelltype(enum HABITAT hab) {
switch (hab) {
case H_DUNGEON:
@ -870,13 +1006,10 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
int lastdir;
int numrooms = 0;
int roomw[MAXROOMS],roomh[MAXROOMS];
vault_t *roomvault[MAXROOMS];
//int roomspecial[MAX_MAPROOMS];
int minroomw = MIN_ROOMW;
int minroomh = MIN_ROOMH;
int maxroomw = MAX_ROOMW;
int maxroomh = MAX_ROOMH;
int bestx,besty;
int w,h;
//int bestx,besty;
//int w,h;
//int startdir,forcex,forcey,ntries;
cell_t *cell, *c;
object_t *o;
@ -1075,40 +1208,24 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
//printf("using %d rooms\n",numrooms);
//dblog("Adding %d rooms...\n",numrooms);
for (i = 0; i < numrooms; i++) {
// select random width/height
w = rnd(minroomw, maxroomw);
h = rnd(minroomh, maxroomh);
roomw[i] = w;
roomh[i] = h;
if (calcroompos(map, w, h, &bestx, &besty)) {
//printf("** couldn't make room!\n");
} else {
// we now have the room position - fill it in
createroom(map, bestx,besty, w,h, i);
/*
if (getrand(1,100) <= CH_SPECIALROOM) {
int curpos;
int roomid;
roomid = getrandomspecialroom(wreck->mazelev[curz].type);
for (y = besty; y <= (besty + (h-1)); y++) {
for (x = bestx; x <= (bestx + (w-1)); x++) {
curpos = y*MAZEW+x;
wreck->mazelev[curz].maze[curpos].floorver = roomid;
}
}
roomspecial[i] = roomid;
} else {
roomspecial[i] = B_FALSE;
}
*/
// maybe make it a special room
roomvault[i] = NULL;
if (rnd(1,100) <= getvaultchance(map)) {
vault_t *v;
v = getvaulttype(map);
if (!createvault(map, i, v, &roomw[i],&roomh[i])) {
// success
roomvault[i] = v;
}
}
if (!roomvault[i]) {
// just do a normal room
createroom(map, i, NA, NA, NULL, NULL, &roomw[i],&roomh[i]);
roomvault[i] = B_FALSE;
}
}
}
// add staircases - dungeons always have an up and down stairs
for (i = 0; i < 3; i++) {
// add up stairs
@ -1150,84 +1267,76 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
// add pillars & objects & monsters to rooms
if (wantrooms && (numrooms > 0)) {
for (i = 0; i < numrooms; i++) {
int numobsmin,numobsmax,numobs,n;
int maxpillars;
if (!roomvault[i] || hasflag(roomvault[i]->flags, F_AUTOPOPULATE)) {
int numobsmin,numobsmax,numobs,n;
int maxpillars;
//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)) {
int n;
int numpillars;
numpillars = rnd(1,maxpillars);
if (db) dblog("--> Will add %d pillars",numpillars);
for (n = 0; n < numpillars;n++ ) {
//dblog("----> Adding pillar %d/%d",n+1,numpillars);
cell_t *c;
c = getrandomroomcell(map, i);
//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)) {
int n;
int numpillars;
numpillars = rnd(1,maxpillars);
if (db) dblog("--> Will add %d pillars",numpillars);
for (n = 0; n < numpillars;n++ ) {
//dblog("----> Adding pillar %d/%d",n+1,numpillars);
cell_t *c;
c = getrandomroomcell(map, i);
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
setcelltype(cell, CT_WALL);
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
setcelltype(cell, CT_WALL);
}
}
}
}
/*
if (roomspecial[i]) {
// chance is increased
numobsmin = (roomw[i]*roomh[i]) / 4 ;
numobsmax = (roomw[i]*roomh[i]) / 2 ;
} else {
*/
numobsmin = 0;
//numobsmax = MAXOF(roomw[i],roomh[i]) / 2;
numobsmax = MAXOF(roomw[i],roomh[i]);
numobsmin = 0;
//numobsmax = MAXOF(roomw[i],roomh[i]) / 2;
numobsmax = MAXOF(roomw[i],roomh[i]);
//}
// then objects/monsters
if (numobsmax <= numobsmin) {
numobs = numobsmin;
} else {
numobs = rnd(numobsmin,numobsmax);
}
if (db) dblog("--> Will add %d objects to room %d (of %d)",numobs,i,numrooms);
for (n = 0 ; n < numobs; n++) {
int ntries = 0;
int nmonsters = 0;
cell_t *c;
done = B_FALSE;
while (!done) {
c = getrandomroomcell(map, i);
// if nothing there
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
int obchance;
int nadded = 0;
// then objects/monsters
if (numobsmax <= numobsmin) {
numobs = numobsmin;
} else {
numobs = rnd(numobsmin,numobsmax);
}
if (db) dblog("--> Will add %d objects to room %d (of %d)",numobs,i,numrooms);
for (n = 0 ; n < numobs; n++) {
int ntries = 0;
int nmonsters = 0;
cell_t *c;
done = B_FALSE;
while (!done) {
c = getrandomroomcell(map, i);
// if nothing there
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
int obchance;
int nadded = 0;
// limit # monster per room to depth+1
if (nmonsters >= (depth+1)) {
obchance = 100;
} else {
// slightly more chance of objects in rooms
obchance = getobchance(map->habitat) + 10;
}
// limit # monster per room to depth+1
if (nmonsters >= (depth+1)) {
obchance = 100;
if (addrandomthing(c,obchance, &nadded) == TT_MONSTER) {
nmonsters += nadded;
}
done = B_TRUE;
} else {
// slightly more chance of objects in rooms
obchance = getobchance(map->habitat) + 10;
ntries++;
}
if (addrandomthing(c,obchance, &nadded) == TT_MONSTER) {
nmonsters += nadded;
if (ntries >= numobs) {
break;
}
done = B_TRUE;
} else {
ntries++;
}
if (ntries >= numobs) {
break;
}
}
}
}
}
} // end if !vault
} // end foreach room
} // end if wantrooms & nrooms>0
if (db) dblog("Finished adding objects.");
}
@ -1541,12 +1650,194 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
map->beingcreated = B_FALSE;
}
void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
int w,h,x,y;
int minx,miny,maxx,maxy;
flag_t *f;
if (!v) {
return B_TRUE;
}
f = hasflag(v->flags, F_VAULTRANDOMMAP);
if (f) {
// just make a normal room to start with.
if (createroom(map, roomid, f->val[0], f->val[1], &minx, &miny, &w, &h)) {
return B_TRUE;
}
maxx = minx + w - 1;
maxy = miny + h - 1;
} else {
// get width/height from vault
w = v->w;
h = v->h;
if (retw) *retw = w;
if (reth) *reth = h;
// find vault position
if (calcroompos(map, w, h, &minx, &miny)) {
dblog("** couldn't make vault room!\n");
return B_TRUE;
}
maxx = minx + (w-1);
maxy = miny + (h-1);
// now make it
for (y = miny; y <= maxy; y++) {
for (x = minx; x <= maxx; x++) {
cell_t *cell;
celltype_t *ct;
cell = getcellat(map, x, y);
// set cell type
ct = getvaultcelltype(v, x-minx,y-miny);
setcelltype(cell, ct ? ct->id : getemptycelltype(cell->map->habitat));
// set roomid
cell->roomid = roomid;
// add objects
addvaultcellcontents(cell, v, x-minx,y-miny);
}
}
}
// add other stuff to the vault
addvaultcontents(map, v, minx, miny, maxx, maxy);
// auto add doors if required
if (hasflag(v->flags, F_AUTODOORS)) {
autodoors(map, roomid, minx, miny, maxx, maxy);
}
linkdoors(map, roomid, minx, miny, maxx,maxy);
return B_FALSE;
}
// make sure doors in a given room link up to the rest of the map.
void linkdoors(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
int x,y,i;
cell_t *poss[MAXCANDIDATES],*c;
int nposs = 0;
int db = B_FALSE;
if (db) dblog("linkdoors for roomid %d", roomid);
// find all doors // TODO: ...or "exits"
for (y = miny; y <= maxy; y++) {
for (x = minx; x <= maxx; x++) {
c = getcellat(m, x, y);
if (!c) continue;
if (hasobwithflag(c->obpile, F_DOOR)) {
if (db) dblog("found door at %d,%d",x,y);
poss[nposs++] = c;
}
}
}
if (db) dblog("%d doors found.",nposs);
// 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;
for (d = DC_N; d <= DC_NW; d++) {
c = getcellindir(poss[i], d);
if (c && cellwalkable(NULL, c, NULL) && (c->roomid != roomid)) {
ncorridors++;
}
}
if (db) dblog("Door #%d leads to %d corridors. ",i, ncorridors);
// no corridors?
if (ncorridors == 0) {
int poss2[MAXCANDIDATES],nposs2;
int dist[MAXDIR_ORTH];
int bestdist = 999;
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 not of this 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;
c = getcellindir(poss[i], d);
while (c) {
dist[d]++;
if (c->roomid == roomid) {
// mark dir as invalid
dist[d] = 999;
break;
} else if (cellwalkable(NULL, c, NULL)) {
// walkable and not in this vault. finished.
break;
}
// check next cell
c = getcellindir(c, d); // getting the same cell!
}
if (dist[d] < bestdist) bestdist = dist[d];
}
if (bestdist != 999) {
int whichway,sel;
// now pick the shortest one
// get list of all the maximums and randomly tie-break
nposs2 = 0;
for (d = D_N; d <= D_W; d++) {
if (dist[d] == bestdist) {
poss2[nposs2++] = d;
}
}
sel = rnd(0,nposs2-1);
whichway = poss2[sel];
// now create a path
if (db) dblog(" Linking %s (distance %d).", getdirname(whichway), bestdist);
c = getcellindir(poss[i], whichway);
while (c && !cellwalkable(NULL, c, NULL)) {
setcelltype(c, getemptycelltype(c->map->habitat));
c = getcellindir(poss[i], whichway);
}
}
} // end if ncorridors = 0
} // end for each door
if (db) dblog("linkdoors complete.");
}
// room w/h are returned in *w and *h if given.
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth) {
int x,y;
int poss[MAXOF(MAX_MAPW,MAX_MAPH)];
int npossible;
cell_t *cell, *newcell;
cell_t *cell;
int minx,miny;
int maxx,maxy;
int w,h;
int minroomw = MIN_ROOMW;
int minroomh = MIN_ROOMH;
int maxroomw = MAX_ROOMW;
int maxroomh = MAX_ROOMH;
if (overrideminw != NA) {
minroomw = overrideminw;
}
if (overrideminh != NA) {
minroomh = overrideminh;
}
// select random width/height
w = rnd(minroomw, maxroomw);
h = rnd(minroomh, maxroomh);
if (retw) *retw = w;
if (reth) *reth = h;
// find room position
if (calcroompos(map, w, h, &minx, &miny)) {
dblog("** couldn't make room!\n");
return B_TRUE;
}
if (retx) *retx = minx;
if (rety) *rety = miny;
// we now have the room position - fill it in
//printf("trying to create room at (%d,%d) w=%d,h=%d\n", minx, miny, w, h);
@ -1556,7 +1847,6 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
for (y = miny; y <= maxy; y++) {
for (x = minx; x <= maxx; x++) {
cell = getcellat(map, x, y);
// make it a border or room
if ((y == miny) || (y == maxy) ||
(x == minx) || (x == maxx)) {
@ -1570,172 +1860,13 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
}
}
// add doors
autodoors(map, roomid, minx, miny, maxx, maxy);
// for each side, make list of all possible door locations
// then pick one randomly.
// BUT if the nearby corridor only has one exit, always
// place a door.
// N
npossible = 0;
y = miny;
for (x = minx+1; x <= maxx-1; x++) {
cell = getcellat(map, x, y);
newcell = getcellindir(cell, D_N);
if (newcell && !newcell->type->solid) {
int doorcount;
doorcount = countadjcellswithflag(cell, F_DOOR);
if (doorcount == 0) {
if ((countcellexits(newcell) == 1) &&
(iswallindir(newcell,D_E)) &&
(iswallindir(newcell,D_W))) { // always add door
makedoor(cell);
} else {
poss[npossible] = x;
npossible++;
}
}
}
}
if (npossible > 0) {
int sel = rand() % npossible;
//printf("adding N door at %d\n",poss[sel]);
cell = getcellat(map, poss[sel], y);
makedoor(cell);
}
// S
npossible = 0;
y = maxy;
for (x = minx+1; x <= maxx-1; x++) {
cell = getcellat(map, x, y);
newcell = getcellindir(cell, D_S);
if (newcell && !newcell->type->solid) {
int doorcount;
doorcount = countadjcellswithflag(cell, F_DOOR);
if (doorcount == 0) {
if ((countcellexits(newcell) == 1) &&
(iswallindir(newcell,D_E)) &&
(iswallindir(newcell,D_W))) { // always add door
makedoor(cell);
} else {
poss[npossible] = x;
npossible++;
}
}
}
}
if (npossible > 0) {
int sel = rand() % npossible;
//printf("adding S door at %d\n",poss[sel]);
cell = getcellat(map, poss[sel], y);
makedoor(cell);
}
// W
npossible = 0;
x = minx;
for (y = miny+1; y <= maxy-1; y++) {
cell = getcellat(map, x, y);
newcell = getcellindir(cell, D_W);
if (newcell && !newcell->type->solid) {
int doorcount;
doorcount = countadjcellswithflag(cell, F_DOOR);
if (doorcount == 0) {
if ((countcellexits(newcell) == 1) &&
(iswallindir(newcell,D_N)) &&
(iswallindir(newcell,D_S))) { // always add door
makedoor(cell);
} else {
poss[npossible] = y;
npossible++;
}
}
}
}
if (npossible > 0) {
int sel = rand() % npossible;
//printf("adding W door at %d\n",poss[sel]);
cell = getcellat(map, x, poss[sel]);
makedoor(cell);
}
// E
npossible = 0;
x = maxx;
for (y = miny+1; y <= maxy-1; y++) {
cell = getcellat(map, x, y);
newcell = getcellindir(cell, D_E);
if (newcell && !newcell->type->solid) {
int doorcount;
doorcount = countadjcellswithflag(cell, F_DOOR);
if (doorcount == 0) {
if ((countcellexits(newcell) == 1) &&
(iswallindir(newcell,D_N)) &&
(iswallindir(newcell,D_S))) { // always add door
makedoor(cell);
} else {
poss[npossible] = y;
npossible++;
}
}
}
}
if (npossible > 0) {
int sel = rand() % npossible;
//printf("adding E door at %d\n",poss[sel]);
cell = getcellat(map, x, poss[sel]);
makedoor(cell);
}
// maybe make it a special room
if (rnd(1,100) <= getspecialroomchance(map)) {
enum SPECIALROOMTYPE rt;
rt = getspecialroomtype(map);
if (rt == RT_FLOODED) {
int sx,sy,ex,ey;
char wtype[BUFLEN];
switch (rnd(1,2)) {
case 1: strcpy(wtype, "deep water"); break;
case 2: strcpy(wtype, "shallow water"); break;
}
switch (rnd(1,2)) {
case 1: // entire room flooded
sx = minx+1;
sy = miny+1;
ex = maxx-1;
ey = maxy-1;
break;
case 2: // small walkway around the edge
sx = minx+2;
sy = miny+2;
ex = maxx-2;
ey = maxy-2;
if (sx > ex) sx = ex;
if (sy > ey) sy = ey;
break;
}
for (y = sy; y <= ey; y++) {
for (x = sx; x <= ex; x++) {
cell = getcellat(map, x, y);
addob(cell->obpile, wtype);
}
}
}
}
return B_FALSE;
}
int dirtox(int dt, int dir) {
if (dt == DT_ORTH) {
switch (dir) {
@ -1897,6 +2028,14 @@ celltype_t *findcelltype(enum CELLTYPE cid) {
return NULL;
}
celltype_t *findcelltypebyname(char *name) {
celltype_t *ct;
for (ct = firstcelltype ; ct ; ct = ct->next) {
if (!strcmp(ct->name, name)) return ct;
}
return NULL;
}
map_t *findmap(int mid) {
map_t *m;
for (m = firstmap ; m ; m = m->next) {
@ -2199,10 +2338,10 @@ int getobchance(int habitat) {
return 0;
}
// chance that a room is a 'special' one
int getspecialroomchance(map_t *m) {
int getvaultchance(map_t *m) {
switch (m->habitat) {
case H_DUNGEON:
return 5;
return 10;
default:
return 0;
}
@ -2210,17 +2349,6 @@ int getspecialroomchance(map_t *m) {
return 0;
}
enum SPECIALROOMTYPE getspecialroomtype(map_t *m) {
if (m->habitat == H_DUNGEON) {
/*
switch (rnd(1,1)) {
}
*/
return RT_FLOODED;
}
return RT_NONE;
}
// chance of each empty cell in a map has of getting an object/monster
@ -2844,7 +2972,7 @@ void makedoor(cell_t *cell) {
chance = rolldie(1,6) - (m->depth / 10);
if (chance <= 1) {
addflag(o->flags, F_LOCKED, B_TRUE, 19 + (m->depth), NA, NULL);
addflag(o->flags, F_LOCKED, B_TRUE, getdoorlockdiff(m->depth), NA, NULL);
}
// make it secret?
@ -2855,7 +2983,7 @@ void makedoor(cell_t *cell) {
// l10 = 25
// l20 = 30
if (chance <= 1) {
addflag(o->flags, F_SECRET, 20 + (m->depth / 2), NA, NA, NULL);
addflag(o->flags, F_SECRET, getdoorsecretdiff(m->depth), NA, NA, NULL);
}
}
}
@ -2960,6 +3088,9 @@ void setcelltype(cell_t *cell, int id) {
cell->type = findcelltype(id);
assert(cell->type);
cell->roomid = 0;
if ((gamemode == GM_GAMESTARTED) && haslos(player, cell)) {
needredraw = B_TRUE;
}
}
@ -2989,3 +3120,19 @@ void updateknowncells(void) {
}
}
}
int wallstoleftright(cell_t *c, int dir) {
int d1,d2;
switch (dir) {
case D_N:
case D_S:
d1 = D_E; d2 = D_W; break;
case D_E:
case D_W:
d1 = D_N; d2 = D_S; break;
}
if (iswallindir(c,d1) && iswallindir(c,d2)) {
return B_TRUE;
}
return B_FALSE;
}

14
map.h
View File

@ -6,15 +6,19 @@ map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded);
object_t *addrandomob(cell_t *c);
int addrandomthing(cell_t *c, int obchance, int *nadded);
void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy);
int cellhaslos(cell_t *c1, cell_t *dest);
cell_t *getcellat(map_t *map, int x, int y);
int getcelldist(cell_t *src, cell_t *dst);
int getcelldistorth(cell_t *src, cell_t *dst);
void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer);
int getdoorlockdiff(int depth);
int getdoorsecretdiff(int depth);
enum CELLTYPE getemptycelltype(enum HABITAT hab);
enum CELLTYPE getwallcelltype(enum HABITAT hab);
flag_t *getmapcoords(map_t *m, int *x, int *y);
int getmapdifficulty(map_t *m);
void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells);
object_t *gettopobject(cell_t *where);
void calclight(map_t *map);
int calcroompos(map_t *map, int w, int h, int *bx, int *by);
@ -24,13 +28,15 @@ int countcellexits(cell_t *cell);
void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir);
void createforest(map_t *map, int depth, map_t *parentmap, int exitdir);
void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap, int exitdir);
void createroom(map_t *map, int minx, int miny, int w, int h, int roomid);
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth);
int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth);
int dirtox(int dt, int dir);
int dirtoy(int dt, int dir);
void dumpmap(map_t *map);
void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre);
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce);
celltype_t *findcelltype(enum CELLTYPE cid);
celltype_t *findcelltypebyname(char *name);
map_t *findmap(int mid);
map_t *findmapofdepth(int depth);
cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf);
@ -41,8 +47,8 @@ void forgetcells(map_t *map, int amt);
cell_t *getcellindir(cell_t *cell, int dir);
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
int getobchance(int habitat);
int getspecialroomchance(map_t *m);
enum SPECIALROOMTYPE getspecialroomtype(map_t *m);
int getvaultchance(map_t *m);
char getvaultchar(vault_t *v, int x, int y);
int getthingchance(int habitat);
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob);
@ -70,6 +76,7 @@ int isnewcellok(cell_t *cell, char *err);
int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m);
int iswallindir(cell_t *cell, int dir);
void linkdoors(map_t *m, int roomid, int minx, int miny, int maxx, int maxy);
int linkstairs(object_t *o);
void makedoor(cell_t *cell);
void makelit(cell_t *c, enum LIGHTLEV how, int howlong);
@ -77,3 +84,4 @@ void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);
void setcellknown(cell_t *cell, int forcelev);
void setcelltype(cell_t *cell, int id);
void updateknowncells(void);
int wallstoleftright(cell_t *c, int dir);

68
move.c
View File

@ -143,6 +143,16 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
// obvious things that you can see
if (!onlyifknown || (haslos(lf, cell) && !lfhasflag(lf, F_UNDEAD))) {
// water needing creature out of water?
if (lfhasflag(lf, F_NEEDSWATER)) {
if (!hasobwithflag(cell->obpile, F_DEEPWATER)) {
if (error) {
*error = E_DANGEROUS;
}
return B_TRUE;
}
}
for (o = cell->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_DEEPWATER);
if (f) {
@ -156,14 +166,6 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
return B_TRUE;
}
}
} else {
// water needing creature out of water?
if (lfhasflag(lf, F_NEEDSWATER)) {
if (error) {
*error = E_DANGEROUS;
}
return B_TRUE;
}
}
f = hasflag(o->flags, F_WALKDAM);
if (f) {
@ -566,7 +568,6 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
char newlfname[BUFLEN];
int seen;
int mightfall = B_TRUE;
cell_t *newcell;
lifeform_t *newlf;
// calculate chance of falling
@ -600,6 +601,9 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
trymove(lf, dir, B_FALSE);
}
if (reason != E_OK) {
char buf[BUFLEN];
cell_t *newcell;
newcell = getcellindir(lf->cell, dir);
// failed to move
switch (reason) {
case E_OFFMAP:
@ -611,8 +615,10 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
}
// fall through
case E_WALLINWAY:
if (seen) msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s");
losehp(lf, rnd(1,6), DT_BASH, pusher, "slamming into a wall");
if (seen) msg("%s slam%s into a %s!",lfname,isplayer(lf) ? "" : "s",
newcell ? newcell->type->name : "wall");
sprintf(buf, "slamming into a %s", newcell ? newcell->type->name : "wall");
losehp(lf, rnd(1,6), DT_BASH, pusher, buf);
// stop moving
i = howfar;
// don't fall
@ -1313,7 +1319,11 @@ int opendoor(lifeform_t *lf, object_t *o) {
if (amt < 0) amt = 0;
if (lf && isplayer(lf)) {
msg("You yank on the door but it holds fast.");
if (amt > 0) {
msg("The door moves slightly but seems jammed.");
} else {
msg("The door is jammed.");
}
}
// loosen a bit
if (amt) {
@ -1758,10 +1768,14 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
// can't teleport on top of something else
if (c->lf) {
if (isplayer(lf)) {
msg("You feel a wrenching sensation.");
// go somewhere nearby
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
if (!c) {
if (isplayer(lf)) {
msg("You feel a wrenching sensation.");
}
return B_TRUE;
}
return B_TRUE;
}
if (!isplayer(lf) && cansee(player, lf)) {
@ -1953,25 +1967,31 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
// otherwise fall through...
case E_WALLINWAY:
if (isplayer(lf)) {
msg("Ouch! You %s into a wall.", getmoveverb(lf));
msg("Ouch! You %s into a %s.", getmoveverb(lf),
cell ? cell->type->name : "wall");
} else if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s %ss into a wall.", buf, getmoveverb(lf));
msg("%s %ss into a %s.", buf, getmoveverb(lf),
cell ? cell->type->name : "wall");
}
//if (isblind(lf) || !haslos(lf, cell)) {
if (!haslos(lf, cell)) {
if (!cell || !haslos(lf, cell)) {
if (isplayer(lf)) {
// only take damage if we didn't know about this
if (!cell->known || isdrunk(lf)) {
sprintf(buf, "%sing into a wall", getmoveverb(lf));
if ((cell && !cell->known) || isdrunk(lf)) {
sprintf(buf, "%sing into a %s", getmoveverb(lf),
cell ? cell->type->name : "wall");
losehp(lf, 1, DT_BASH, NULL, buf);
// we now know there is a wall there.
setcellknown(cell, B_FALSE);
if (cell) {
// we now know there is a wall there.
setcellknown(cell, B_FALSE);
}
if (onpurpose) taketime(lf, getmovespeed(lf));
}
} else {
sprintf(buf, "%sing into a wall", getmoveverb(lf));
sprintf(buf, "%sing into a %s", getmoveverb(lf),
cell ? cell->type->name : "wall");
losehp(lf, 1, DT_BASH, NULL, buf);
if (onpurpose) taketime(lf, getmovespeed(lf));
}
@ -1997,7 +2017,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} else {
if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s %ss into a wall.", buf, getmoveverb(lf));
msg("%s %ss into a door.", buf, getmoveverb(lf));
}
sprintf(buf, "%sing into a door", getmoveverb(lf));
losehp(lf, 1, DT_BASH, NULL, buf);

26
nexus.c
View File

@ -17,6 +17,7 @@
#include "objects.h"
#include "save.h"
#include "text.h"
#include "vault.h"
material_t *material = NULL,*lastmaterial = NULL;
objectclass_t *objectclass = NULL,*lastobjectclass = NULL;
@ -33,6 +34,8 @@ map_t *firstmap = NULL,*lastmap = NULL;
knowledge_t *knowledge = NULL, *lastknowledge = NULL;
hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
extern vault_t *firstvault;
glyph_t playerglyph,tempglyph;
double startticks,lastticks;
@ -86,6 +89,7 @@ int main(int argc, char **argv) {
FILE *playerfile = NULL;
int x,y;
cell_t *c;
vault_t *v;
atexit(cleanup);
@ -117,11 +121,11 @@ int main(int argc, char **argv) {
// init graphics
initgfx();
// if no maps, make the initial level
if (!firstmap) {
newworld = B_TRUE;
addmap();
createmap(firstmap, 1, RG_FIRSTDUNGEON, H_DUNGEON, NULL, D_NONE);
// warn about vault problems.
for (v = firstvault ; v ; v = v->next) {
if (!v->valid) {
msg("warning: invalid vaultfile '%s'",v->filename); more();
}
}
if (!knowledge) {
@ -169,6 +173,13 @@ int main(int argc, char **argv) {
}
}
// if no maps (ie. ALWAYS now that maps aren't persistent),
// make the initial level
if (!firstmap) {
newworld = B_TRUE;
addmap();
createmap(firstmap, 1, RG_FIRSTDUNGEON, H_DUNGEON, NULL, D_NONE);
}
// find staircase
where = findobinmap(firstmap, OT_STAIRSUP);
@ -740,6 +751,8 @@ int init(void) {
// cell types
addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE);
addcelltype(CT_WALLGLASS, "glass wall", '#', C_CYAN, B_SOLID, B_TRANS, MT_GLASS);
addcelltype(CT_WALLMETAL, "metal wall", '#', C_WHITE, B_SOLID, B_OPAQUE, MT_METAL);
addcelltype(CT_ROOMWALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE);
addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
@ -759,6 +772,9 @@ int init(void) {
logfile = fopen("log.txt","wt");
fprintf(logfile, "\n\n\n====== NEW LOGFILE ====\n");
// load in vaults
loadvaults();
return B_FALSE;
}

1247
objects.c

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@ hiddenname_t *addhiddenname(enum OBCLASS obclass, char *text);
knowledge_t *addknowledge(enum OBCLASS id, char *hiddenname, int known);
material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour);
void addocnoun(objectclass_t *oc, char *text);
object_t *addob(obpile_t *where, char *name);
object_t *addobject(obpile_t *where, char *name, int canstack);
int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf, enum LOFTYPE needlof);
@ -38,6 +39,7 @@ int countnoncosmeticobs(obpile_t *op, int onlyifknown);
int curseob(object_t *o);
void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype);
void dumprandomobs(int amt);
void dumpobrarity(void);
void explodeob(object_t *o, flag_t *f, int bigness);
void extinguish(object_t *o);
material_t *findmaterial(int id);
@ -64,6 +66,8 @@ int getobvalue(object_t *o);
char *getaccuracyname(int accpct);
object_t *getammo(lifeform_t *lf);
object_t *getrandomammo(lifeform_t *lf);
brand_t *getrandombrandfor(objecttype_t *ot);
objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity);
char *getdamname(enum DAMTYPE damtype);
char *getdamnamenoun(enum DAMTYPE damtype);
char *getfillingname(int nutrition);
@ -193,6 +197,7 @@ int readsomething(lifeform_t *lf, object_t *o);
void removedeadobs(obpile_t *op);
int removeob(object_t *o, int howmany);
object_t *relinkob(object_t *src, obpile_t *dst);
void rrtorarity(enum RARITY r, int *minr, int *maxr);
void setblessed(object_t *o, enum BLESSTYPE wantbless);
void setinscription(object_t *o, char *text);
void setobcreatedby(object_t *o, lifeform_t *lf);

93
spell.c
View File

@ -31,6 +31,10 @@ extern objecttype_t *objecttype;
extern map_t *firstmap;
extern object_t *retobs[MAXPILEOBS+1];
extern int retobscount[MAXPILEOBS+1];
extern int nretobs;
extern enum ERROR reason;
extern int needredraw, statdirty;
@ -2238,11 +2242,17 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int seenthiscell = B_FALSE;
if (haslos(player, retcell[i])) seenthiscell = B_TRUE;
if (retcell[i]->type->solid) {
setcelltype(retcell[i], getemptycelltype(retcell[i]->map->habitat));
if (seenthiscell) {
ndigs++;
numseen++;
if (seenbyplayer) *seenbyplayer = B_TRUE;
// can dig through stone, but nothing else.
if (retcell[i]->type->material->id == MT_STONE) {
setcelltype(retcell[i], getemptycelltype(retcell[i]->map->habitat));
if (seenthiscell) {
ndigs++;
numseen++;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
// stop.
break;
}
} else {
object_t *o;
@ -5436,7 +5446,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// confirm
ch = askchar("Are you sure to want to teleport into the unknown?", "yn", "n", B_TRUE);
if (ch != 'y') c = NULL;
} else if (!cellwalkable(caster, c, NULL)) {
} else if (c->type->solid) {
// confirm
ch = askchar("Are you sure to want to teleport into solid rock?", "yn", "n", B_TRUE);
if (ch != 'y') c = NULL;
@ -5544,9 +5554,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
targcell = c;
if (!cellwalkable(caster, c, NULL)) {
fizzle(caster);
return B_FALSE;
if (c->type->solid) {
// ok, but you'll die!
} else if (!cellwalkable(caster, c, NULL)) {
// go somewhere nearby...
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
if (!c) {
fizzle(caster);
return B_FALSE;
}
}
// we can take up to 'power-1' allies with us.
@ -6104,6 +6120,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster)) {
char lfname[BUFLEN];
char question[BUFLEN];
int i;
if (seenbyplayer) *seenbyplayer = B_TRUE;
// ask for target
if (spellid == OT_S_GIFT) {
@ -6121,34 +6138,40 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
sprintf(question, "For what do you wish");
}
askstring(question, '?', buf, BUFLEN, NULL);
o = addob(target->cell->obpile, buf);
if (o) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
if (!hasflag(o->flags, F_IMPASSABLE) && canpickup(target, o, ALL)) {
relinkob(o, target->pack); // move to pack
if (isplayer(target)) {
msgnocap("%c - %s.", o->letter, obname);
} else {
msg("%s is gifted with %s.", lfname, obname);
}
} else {
// couldn't pick it up - try to place on ground!
// impassable?
if (hasflag(o->flags, F_IMPASSABLE)) {
cell_t *newloc;
// if so, don't put it where the player is!
newloc = getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND);
o = relinkob(o, newloc->obpile);
}
if (o) {
noise(caster->cell, NULL, 1, "something hitting the ground.", NULL);
if (!isblind(caster)) {
msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : "");
addob(target->cell->obpile, buf);
if (nretobs) {
for (i = 0; i < nretobs; i++) {
char obname[BUFLEN];
o = retobs[i];
getobname(o, obname, o->amt);
if (!hasflag(o->flags, F_IMPASSABLE) && canpickup(target, o, ALL)) {
// you gain it.
relinkob(o, target->pack); // move to pack
if (isplayer(target)) {
msgnocap("%c - %s.", o->letter, obname);
} else {
msg("%s is gifted with %s.", lfname, obname);
}
} else {
// couldn't make it appear
msg("The air in front of %s seems to ripple for a moment.", lfname);
// can't pick this up...
// impassable? goes in a nearby cell instead of at your feet.
if (hasflag(o->flags, F_IMPASSABLE)) {
cell_t *newloc;
// if so, don't put it where the player is!
newloc = real_getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL);
o = relinkob(o, newloc->obpile);
}
if (o) {
noise(caster->cell, NULL, 1, "something hitting the ground.", NULL);
if (!isblind(caster)) {
msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : "");
}
} else {
// ob exists but couldn't make it appear
msg("The air in front of %s seems to ripple for a moment.", lfname);
break; // don't process any more.
}
}
}
} else {

42
text.c
View File

@ -208,6 +208,20 @@ char *getdrunktext(flag_t *drunkflag) {
return "??drunk??";
}
char *getrarityname(enum RARITY rr) {
switch (rr) {
case RR_UNIQUE: return "Unique";
case RR_NEVER: return "Never";
case RR_VERYRARE: return "Very Rare";
case RR_RARE: return "Rare";
case RR_UNCOMMON: return "Uncommon";
case RR_COMMON: return "Common";
case RR_NONE: return "None";
}
return "?unknownrarity?";
}
char *getsizetext(enum LFSIZE sz) {
switch (sz) {
case SZ_ENORMOUS:
@ -458,6 +472,19 @@ char *numtotext(int num, char *buf) {
return buf;
}
// returns posiiton AFTER end of copied text, or NULL on failure.
char *readuntil(char *retbuf, char *src, char delim) {
char *bp,*p;
bp = retbuf;
for (p=src; *p && (*p != delim); p++) {
*bp = *p;
bp++;
}
p++; // go past delimiter
*bp = '\0'; // nul-terminate buffer
return p;
}
// convert number to roman numerals
// only copes with 1-10
char *roman(int num) {
@ -546,6 +573,21 @@ char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv) {
return *out;
}
int streq(char *a, char *b) {
if (!a || !b) return B_FALSE;
return !strcmp(a,b);
}
char *strstarts(char *a, char *prefix) {
if (!a || !prefix) return NULL;
if (strstr(a, prefix) == a) {
return a;
}
return NULL;
}
int strpixmatch(char *haystack, char *needle) {
int matched = B_FALSE;
char *hword, *nword, *hcont,*ncont;

4
text.h
View File

@ -10,6 +10,7 @@ char *getattrname(enum ATTRIB att);
int gethitconferlifetime(char *text, int *min, int *max);
char *getpossessive(char *text);
char *getdrunktext(flag_t *drunkflag);
char *getrarityname(enum RARITY rr);
char *getsizetext(enum LFSIZE sz);
char *gettimetext(char *retbuf);
char *gettimetextfuzzy(char *retbuf, int wantpm);
@ -21,11 +22,14 @@ char *makeuppercase(char *text);
int needses(char *text);
char *noprefix(char *obname);
char *numtotext(int num, char *buf);
char *readuntil(char *retbuf, char *src, char delim);
char *roman(int num);
int speedtokph(int speed);
void splittime(int *hours, int *mins, int *secs);
char *strrep(char *text, char *oldtok, char *newtok, int *rv);
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv);
int streq(char *a, char *b);
char *strstarts(char *a, char *prefix);
int strpixmatch(char *haystack, char *needle);
int texttodice(char *text, int *ndice, int *nsides, int *bonus);
void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range);