- [+] before removing deadends:

- [+] find any four corridors in a square
    - [+] where one of them has 4 exits, and the rest have 3
    - [+] fill in the ones with 3
- [+] VALGRIND.
- [+] reduce ID costs at shops
- [+] necromancer mods
    - [+] start with a dagger, since you don't get early attack spells
    - [+] start with limited short blades skill
    - [+] start with animate dead (now a level 1 spell)
- [+] increase TR of ice wraith.
- [+] replace strrep function:
    - [+] strrep(&mystring, find,replacewith)
    - [+] code:
        - [+] char *strrep(char **mystring, char *x, char *y)
        - [+] char *temp
        - [+] temp = dostrrep(x,x,x)
        - [+] free(*mystring)
        - [+] *mystring = temp
- [+] flag loop in F_IGNORECELL!
    - [+] problem: i'm getting f->next == f
    - [+] added a new assertino in addflag()
    - [+] change how killflagsofid() works, maybe this is the problem.
    - [+] i think my "insertbefore" is being freed somehow...v
    - [+] fixed with valgrind?
- [+] try harder to link using tunnels rather than portals
This commit is contained in:
Rob Pearce 2012-11-14 04:59:18 +00:00
parent 98ba363e8a
commit ca132c87c7
30 changed files with 633 additions and 149 deletions

19
ai.c
View File

@ -2319,7 +2319,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
int x,y;
cell_t *c,*origc;
cell_t *c = NULL,*origc,*targetc;
int db = B_FALSE;
if (lfhasflag(lf, F_DEBUG)) {
@ -2330,17 +2330,17 @@ int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
y = f->val[1];
if (db) dblog(".oO { walking from %d,%d towards f_targetcell (%d,%d) ... }", lf->cell->x, lf->cell->y, x, y);
origc = lf->cell;
c = getcellat(lf->cell->map, x, y);
if (c) {
targetc = getcellat(lf->cell->map, x, y);
if (targetc) {
flag_t *pathf = NULL;
if (!haslof(lf->cell, c, LOF_WALLSTOP, NULL)) {
if (!haslof(lf->cell, targetc, LOF_WALLSTOP, NULL)) {
// if we DONT have LOF to the target cell, use
// a pathfinding algorithm.
// do we ahv an existing path?
pathf = lfhasflag(lf, F_AIPATH);
if (!pathf) {
// if we DONT have a direct path, then pathfind.
pathf = ai_createpathto(lf, c);
pathf = ai_createpathto(lf, targetc);
}
if (pathf) {
@ -2349,8 +2349,10 @@ int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
// couldn't find a path there...
// just try to move directly towards it.
}
}
} else {
// if we _DO_ have lof to the cell, we'll just walk direclty towards it.
c = targetc;
}
if (c) {
// try to move towards the cell
@ -2358,7 +2360,7 @@ int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
// couldn't move towards it for some reason.
// so stop trying.
if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }");
killflag(f);
loseaitargets(lf);
// remember NOT to target this one.
addignorecell(lf, c);
c = NULL;
@ -2380,7 +2382,7 @@ int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
f->lifetime = aigetchasetime(lf);
// are we there yet?
if (lf->cell == c) {
if (lf->cell == targetc) {
// yes. remove target cell
if (db) dblog(".oO { arrived at f_targetcell. removing. }");
if (f->val[2] == MR_LF) {
@ -2410,7 +2412,6 @@ int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
if (!c) {
if (db) dblog(".oO { f_targetcell doesn't exist anymore. moving randomly. }");
// destination doesn't exist!
killflag(f);
loseaitargets(lf);
// move randomly now.

View File

@ -829,8 +829,8 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
}
int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) {
int dam[100];
enum DAMTYPE damtype[100];
int dam[MAX_HITS];
enum DAMTYPE damtype[MAX_HITS];
int ndam = 0;
char buf[BUFLEN];
char attackername[BUFLEN];
@ -860,6 +860,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
enum BODYPART critpos = BP_NONE;
int missby = 0;
// init
for (i = 0; i < MAX_HITS; i++) {
dam[i] = 0;
damtype[i] = DT_NONE;
}
if (wep) {
wepsk = getobskill(wep->flags);
}

60
data.c
View File

@ -1349,7 +1349,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DEMONS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_RELICS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SPEECH, PR_NOVICE, NA, NULL);
@ -1408,7 +1408,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DEMONS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_RELICS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SPEECH, PR_NOVICE, NA, NULL);
@ -1466,7 +1466,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DEMONS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_RELICS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SPEECH, PR_NOVICE, NA, NULL);
@ -1512,7 +1512,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_JOBATTRMOD, A_CON, -15, NA, NULL);
addflag(lastjob->flags, F_ALIGNMENT, AL_EVIL, NA, NA, "e");
// initial objects
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "enchanted neophyte staff");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "bloodstained bone dagger");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "wizard hat");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "robe");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "2 potions of magic");
@ -1524,9 +1524,10 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DEMONS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_RELICS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SPEECH, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_AIR, PR_NOVICE, NA, NULL);
@ -1538,11 +1539,11 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_SS_TRANSLOCATION, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_WILD, PR_NOVICE, NA, NULL);
// learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, PR_NOVICE, NA, NULL); // limit
addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, PR_ADEPT, NA, NULL); // limit
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SWIMMING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STAVES, PR_ADEPT, NA, NULL); // limit
@ -1551,7 +1552,6 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_NEEDOBFORSPELLS, NA, F_WIZSTAFF, NA, "wizard staff");
addflag(lastjob->flags, F_MAXHPMOD, 80, NA, NA, NULL); // low hp
addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL);
addflag(lastjob->flags, F_RESTHEALTIME, 6, NA, NA, NULL); // wizard heals slowly, but regenerates mp
@ -1582,7 +1582,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DEMONS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_RELICS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SPEECH, PR_NOVICE, NA, NULL);
@ -3894,15 +3894,6 @@ void initobjects(void) {
// death magic / necromancy
///////////////////
// l1
addot(OT_S_STENCH, "stench of death", "Nauseates the target with the smell of dying flesh.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 1, NA, NULL);
addot(OT_S_BLIGHT, "blight", "Covers the target location with a miasma of decay, tainting food and damaging living beings.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines damage and amount of food affected.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
@ -3913,7 +3904,25 @@ void initobjects(void) {
addflag(lastot->flags, F_RANGE, 2, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 1, NA, NULL);
addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the chances of the zombies being friendly.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many corpses are affected.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many hit points the zombies have.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
// TODO: should be "castnearob ot_corpse"
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 1, NA, NULL);
// l2
addot(OT_S_STENCH, "stench of death", "Nauseates the target with the smell of dying flesh.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 1, NA, NULL);
addot(OT_S_BLINDNESS, "blindness", "Temporarily blinds the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
@ -4019,13 +4028,6 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 4, NA, NULL);
addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the chances of the zombies being friendly.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
// TODO: should be "castnearob ot_corpse"
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 4, NA, NULL);
// l5
addot(OT_S_DEATHKEEN, "midnight dirge", "Emits a dreadful wailing keen which instantly slays any who hear it.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell will only function at night.");
@ -7491,7 +7493,7 @@ void initobjects(void) {
// armour objects
// armour - multipart
addot(OT_WETSUIT, "wetsuit", "Full-body rubber suit which provides good insulation from cold.", MT_RUBBER, 6, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESONMULTI, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
@ -7499,7 +7501,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 3, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 0, 5, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_DTRESIST, DT_COLD, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_COLD, NA, NULL);
addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 15, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 80, NA, NA, NULL);
@ -8038,7 +8040,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_VERYRARE, NULL);
addflag(lastot->flags, F_VALUE, 1400, NA, NA, NULL);
addot(OT_AMU_CHEF, "chef's amulet", "Greatly lowers its wearers' metabolism.", MT_METAL, 0.3, OC_AMULET, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SLOWMETAB, 3, NA, NULL);
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
addot(OT_AMU_CHOKING, "amulet of choking", "Once worn, this evil amulet will immediately begin to shrink, choking the life from its wearer!", MT_METAL, 0.3, OC_AMULET, SZ_TINY);
@ -18349,7 +18351,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 6, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHCHILL, 7, NA, NULL);

Binary file not shown.

View File

@ -0,0 +1,25 @@
@id:bedroom_common
@map
#####
##c##
#b.b#
#b.b#
#b.b#
##+##
@end
@legend
.:cell:carpetted floor
#:cell:SOLID
b:ob:wooden bed
b:mon:sleeping humanoid:50
c:ob:chest:50:ob:ornate chest
+:ob:iron door
@end
@flags
goesin:dungeon
mayrotate
rarity:uncommon
@end

25
data/vaults/coldroom.vlt Normal file
View File

@ -0,0 +1,25 @@
!
@id:cold_room
@map
random(4,4)
@end
@legend
@end
@flags
cellsolid:ice wall
goesin:dungeon
autodoors
autopop
! tables & chairs
fill(1,1,-2,-2) cell:tiled floor
fill(1,1,-2,-2) ob:sheet of ice
scatter(1,1,-2,-2) ob:frozen corpse:30%
! ice pillars
scatter(1,1,-2,-2) cell:ice wall:1-2
! mayrotate
! mayscale
rarity:uncommon
@end

View File

@ -0,0 +1,22 @@
@id:fire_crossroads
@map
##x##
#s.s#
x.f.x
#s.s#
##x##
@end
@legend
#:cell:SOLID
f:ob:immutable medium fire:50:ob:immutable large fire
s:ob:statue:
x:exit
@end
@flags
goesin:dungeon
rarity:frequent
maintainedge
@end

30
data/vaults/firepit.vlt Normal file
View File

@ -0,0 +1,30 @@
@id:firepit
@map
####+####
####.####
##ff_ff##
##ff_ff##
##ff.ff##
##ffcff##
####d####
@end
@legend
#:cell:SOLID
.:cell:rock floor
+:ob:wooden door
+:exit
_:ob:barricade:30
f:ob:immutable large fire
c:ob:untrapped ornate chest
d:ob:secret door:15:cell:SOLID
@end
@flags
mayrotate
goesin:dungeon
autopop
rarity:vrare
maintainedge
@end

View File

@ -0,0 +1,25 @@
@id:fortified_room
@map
##+###
#....#
#^^^^#
#....#
#^^^^#
#....#
###+##
@end
@legend
#:cell:SOLID
^:ob:barricade:50:ob:rubble
+:ob:wooden door
+:exit
@end
@flags
goesin:dungeon
mayrotate
autopop
rarity:rare
@end

View File

@ -19,5 +19,6 @@ autodoors:50
mayrotate
autopop
rarity:uncommon
maintainedge
@end

19
data/vaults/pitbridge.vlt Normal file
View File

@ -0,0 +1,19 @@
@id:bridge_over_pit
@map
^_^
^_^
^_^
@end
@legend
_:ob:barricade
^:ob:hole in the ground
@end
@flags
goesin:dungeon
mayrotate
autopop
rarity:rare
@end

View File

@ -0,0 +1,24 @@
@id:guarded_pitbridge
@map
##X###
#^_^##
#^_^m#
#^_^##
##X###
@end
@legend
#:cell:SOLID
_:ob:barricade
^:ob:hole in the ground
m:mon:humanoid with firearm
X:exit
@end
@flags
goesin:dungeon
mayrotate
autopop
rarity:rare
@end

30
data/vaults/pub.vlt Normal file
View File

@ -0,0 +1,30 @@
@id:pub
@map
w##########
g#pppppppp#
s+pppppppf#
g#pppppppp#
w##########
@end
@legend
w:cell:SOLID
#:cell:wooden wall
p:cell:wood floor
g:cell:grass
+:cell:dirt
+:ob:wooden door
s:cell:grass
s:ob:sign "Village Pub"
f:ob:brazier
@end
@flags
scatter(2,1,-2,-2) mon:hirable humanoid:3-5
scatter(2,1,-2,-2) ob:furniture:1-4
mayrotate
maintainedge
margin:3,3
monstersstay
@end

View File

@ -0,0 +1,18 @@
@id:wall_with_window
@map
x#x
.G.
x#x
@end
@legend
#:cell:SOLID
G:cell:glass wall
x:exit
@end
@flags
goesin:dungeon
rarity:frequent
mayrotate
@end

10
defs.h
View File

@ -50,7 +50,7 @@
// Map building defaults
#define DEF_LOOPPCT 95
#define DEF_SPARSENESS 20
#define DEF_SPARSENESS 25
#define DEF_TURNPCT 40
#define DEF_WINDOWPCT 5
@ -234,6 +234,8 @@
#define MAX_PATHFIND_ADJ (MAX_MAPW*MAX_MAPH*10)
#define MAX_PATHFIND_STEPS (MAX_MAPW*MAX_MAPH)
#define MAX_HITS 100
#define MAXPILEOBS 52
#define MAXRANDOMOBCANDIDATES 100
@ -261,8 +263,10 @@
#define MINROOMS 5
#define MAXROOMS 20
#define MIN_ROOMH 4
#define MIN_ROOMW 4
//#define MIN_ROOMH 4
//#define MIN_ROOMW 4
#define MIN_ROOMH 5
#define MIN_ROOMW 5
#define MAX_ROOMW (MAX_MAPW / 3)
#define MAX_ROOMH (MAX_MAPH / 3)

8
flag.c
View File

@ -161,25 +161,29 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
fml = FIRST;
} else {
flag_t *ff;
flag_t *ff,*insertbefore = NULL,*insertafter = NULL;
// we will keep flags sorted.
// find correct position in list...
ff = fp->first;
while (ff && (ff->id < id)) {
ff = ff->next;
}
if (ff) {
insertbefore = ff;
insertafter = ff->prev;
}
if (ff) {
// start or middle of list
// insert BEFORE this one
flag_t *newone = NULL;
flag_t *prev;
prev = ff->prev;
// allocate new flag
newone = (flag_t *)calloc(1, sizeof(flag_t));
assert(newone != NULL);
assert(newone != ff);
// link to previous element
if (prev) {

10
god.c
View File

@ -702,13 +702,13 @@ void dooffer(void) {
} else {
p = strdup(f->text);
}
p = strrep(p, "OB", obname, NULL);
strrep(&p, "OB", obname, NULL);
if (o->amt == 1) {
p = strrep(p, "IS", "is", NULL);
p = strrep(p, "#S", "s", NULL);
strrep(&p, "IS", "is", NULL);
strrep(&p, "#S", "s", NULL);
} else {
p = strrep(p, "IS", "are", NULL);
p = strrep(p, "#S", "", NULL);
strrep(&p, "IS", "are", NULL);
strrep(&p, "#S", "", NULL);
}
msg("%s", p);

15
io.c
View File

@ -131,7 +131,7 @@ void addmsghist(char *text) {
char *localtext;
int db = B_FALSE;
localtext = strdup(text);
localtext = strrep(localtext, MORESTRING, "", NULL);
strrep(&localtext, MORESTRING, "", NULL);
if (nmsghist < MAXHISTORY) {
strcpy(msghist[nmsghist], localtext);
nmsghist++;
@ -1878,7 +1878,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
case F_FROZEN:
// strip "frozen" out...
buf2 = strdup(lfname);
buf2 = strrep(buf2, "frozen ","",NULL);
strrep(&buf2, "frozen ","",NULL);
msg("%s %s to ice!",lfname, isplayer(lf) ? "turn" : "turns");
donesomething = B_TRUE;
free(buf2);
@ -3044,7 +3044,7 @@ void announceobflagloss(object_t *o, flag_t *f) {
// replace "the flaming xxx is no longer on fire"
// with "the xxx is no longer on fire"
temp = strdup(prefix);
temp = strrep(temp, "flaming ","",NULL);
strrep(&temp, "flaming ","",NULL);
msg("%s %s no longer on fire.",temp,isare);
free(temp);
break;
@ -5217,7 +5217,7 @@ void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf) {
}
capitalise(text);
p = strdup(text);
p = strrep(p, "NAME", lfname, NULL);
strrep(&p, "NAME", lfname, NULL);
msg("%s",p); more();
free(p);
ndone++;
@ -5935,7 +5935,8 @@ char *makedesc_job(job_t *j, char *retbuf) {
strcat(thisline, buf);
if (count == 4) {
count = 0;
assert(strlen_without_colours(thisline) < 78);
// should use getmaxx(win) here instead...
//assert(strlen_without_colours(thisline) < 78);
// print it.
strcat(thisline, "\n");
strcat(retbuf, thisline);
@ -14723,7 +14724,7 @@ void wingame(void) {
msg("The combined voices the gods ring out:"); more();
buf = strdup(winflag->text);
strrep(buf, "&", "and", NULL);
strrep(&buf, "&", "and", NULL);
makeuppercase(buf);
msg("^%c\"ALL HAIL THE NEW GOD OF %s!!\"", getlfcol(player, CC_VGOOD), buf);
more();
@ -14796,7 +14797,7 @@ char wrapprint(WINDOW *win, int *y, int *x, int newlineindent, char *format, ...
repword = strdup(word);
while (rv) {
repword = strrep(repword, "@", " ", &rv);
strrep(&repword, "@", " ", &rv);
}
}
// if this word won't fit, put it on the next line.

45
lf.c
View File

@ -4720,7 +4720,7 @@ int eat(lifeform_t *lf, object_t *o) {
setlastdam(lf, "merging with a corpse");
lf->lastdamtype = DT_DIRECT;
lf->hp = 0;
newlf = makezombie(o);
newlf = makezombie(o, 0);
if (newlf) {
addflag(newlf->flags, F_CORPSELF, R_LINGPARASITE, NA, NA, NULL);
}
@ -13860,6 +13860,7 @@ void killlf(lifeform_t *lf) {
// free mem
if (lf->lastdam) free(lf->lastdam);
if (lf->killverb) free(lf->killverb);
// kill any remaining obs
while (lf->pack->first) {
@ -14707,7 +14708,7 @@ skill_t *addskill(enum SKILL id, char *name, char *desc, int traintime) {
a->shortname = strdup(name);
//
if (strstr(a->shortname, "Sorcery:")) {
strrep(a->shortname, "Sorcery:", "", NULL);
strrep(&(a->shortname), "Sorcery:", "", NULL);
}
a->desc = strdup(desc);
a->traintime = traintime;
@ -14980,7 +14981,9 @@ void makepeaceful(lifeform_t *who, lifeform_t *causedby) {
loseaitargets(who);
}
lifeform_t *makezombie(object_t *o) {
// 'power' is 0-10, determines how poewrful the zombie is.
// if 0, don't do any special changes.
lifeform_t *makezombie(object_t *o, int power) {
flag_t *f;
race_t *r;
lifeform_t *lf;
@ -15065,6 +15068,13 @@ lifeform_t *makezombie(object_t *o) {
killflagsofid(lf->flags, F_CANCAST);
killflagsofid(lf->flags, F_CANWILL);
// modify max hp based on power
if (power > 0) {
lf->maxhp = pctof(power*10, lf->maxhp);
limit(&(lf->maxhp), 1, NA);
lf->hp = lf->maxhp;
}
// remove the object
removeob(o,o->amt);
@ -15564,7 +15574,8 @@ void autospells(lifeform_t *lf, int howmany) {
getflags(lf->flags, retflag, &nretflags, F_RNDSPELLPOSS, F_NONE);
for (i = 0; i < nretflags; i++) {
poss[nposs] = retflag[i]->val[0];
texttospellopts(retflag[i]->text, "pw:", &powerposs[nposs], NULL);
powerposs[nposs] = 1; // will be overridden
texttospellopts(retflag[i]->text, "pw:", &(powerposs[nposs]), NULL);
nposs++;
}
// random spells from schools?
@ -17389,7 +17400,7 @@ void modstamina(lifeform_t *lf, float howmuch) {
char *p;
getlfname(lf, lfname);
p = strdup(lfname);
p = strrep(p, "exhausted ","", NULL);
strrep(&p, "exhausted ","", NULL);
msg("%s looks exhausted.", p);
free(p);
}
@ -19203,9 +19214,9 @@ int say(lifeform_t *lf, char *text, int volume) {
switch (lf->race->id) {
case R_GODMAGIC:
volume = SV_TALK;
strrep(localtext, "You have", "One has", NULL);
strrep(localtext, "You", "One", NULL);
strrep(localtext, "you", "one", NULL);
strrep(&localtext, "You have", "One has", NULL);
strrep(&localtext, "You", "One", NULL);
strrep(&localtext, "you", "one", NULL);
break;
case R_GODTHIEVES:
case R_GODDEATH:
@ -19281,7 +19292,7 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
break;
case SP_ALLY_ATTACKUNSEEN:
p = strdup(text);
strrep(p, "the ","a ", NULL);
strrep(&p, "the ","a ", NULL);
switch (rnd(1,3)) {
case 1: snprintf(buf, BUFLEN, "There's %s over here!", p); break;
case 2: snprintf(buf, BUFLEN, "I'm attacking %s!", p); break;
@ -22234,23 +22245,23 @@ void startlfturn(lifeform_t *lf) {
p = strdup(pt->damverb);
if (isplayer(lf)) {
p = strrep(p, "YOUR", "Your", NULL);
strrep(&p, "YOUR", "Your", NULL);
if (asleep) {
p = strrep(p, "YOU", "You wake up and", NULL);
strrep(&p, "YOU", "You wake up and", NULL);
} else {
p = strrep(p, "YOU", "You", NULL);
strrep(&p, "YOU", "You", NULL);
}
p = strrep(p, "#S", "", NULL);
strrep(&p, "#S", "", NULL);
} else {
p = strrep(p, "YOUR", lfnameposs, NULL);
strrep(&p, "YOUR", lfnameposs, NULL);
if (asleep) {
char replacetext[BUFLEN];
sprintf(replacetext, "%s wakes and", lfname);
p = strrep(p, "YOU", replacetext, NULL);
strrep(&p, "YOU", replacetext, NULL);
} else {
p = strrep(p, "YOU", lfname, NULL);
strrep(&p, "YOU", lfname, NULL);
}
p = strrep(p, "#S", "s", NULL);
strrep(&p, "#S", "s", NULL);
}
msg("%s", p);

2
lf.h
View File

@ -424,7 +424,7 @@ int makelearnable(lifeform_t *lf, enum SKILL skid);
int makenauseated(lifeform_t *lf, int amt, int howlong, enum ERROR *why);
void makenoise(lifeform_t *lf, enum NOISETYPE nid);
void makepeaceful(lifeform_t *lf, lifeform_t *causedby);
lifeform_t *makezombie(object_t *o);
lifeform_t *makezombie(object_t *o, int power);
void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how, int overridepower);
int meetsallattreqs(lifeform_t *lf, object_t *o);
int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o, int *modpct);

96
map.c
View File

@ -2329,6 +2329,7 @@ int fix_reachability(map_t *m) {
if (db) dblog(" attempting to fix unreachable area at %d,%d.",
ucell->x, ucell->y);
// first: try to link up the two areas.
ndoors = fix_unreach_via_doors(m);
if (!ndoors) {
@ -3847,6 +3848,9 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
}
// remove 2x2 dead-end rooms
remove_smallrooms(map);
// use sparseness to cut down dead ends
remove_deadends(map, sparseness);
@ -4672,6 +4676,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
if (!failed) {
remove_baddoors(map);
//remove_deadends(map, 5);
}
// ensure there are no unreachable areas
if (!failed) {
@ -9218,12 +9223,9 @@ enum RACE parserace(char *name, flagpile_t *wantflags, condset_t *cs, enum JOB *
donesomething = B_TRUE;
}
free(localname);
// now get raceid
if (streq(p, "random")) {
free(localname);
return R_RANDOM;
} else if (strstarts(p, "random ")) {
race_t *baser,*r;
@ -9243,6 +9245,7 @@ enum RACE parserace(char *name, flagpile_t *wantflags, condset_t *cs, enum JOB *
}
}
if (nposs) {
free(localname);
return poss[rnd(0,nposs-1)];
}
}
@ -9250,9 +9253,11 @@ enum RACE parserace(char *name, flagpile_t *wantflags, condset_t *cs, enum JOB *
race_t *r;
r = findracebyname(p, cs);
if (r) {
free(localname);
return r->id;
}
}
free(localname);
return R_NONE;
}
@ -9264,17 +9269,25 @@ int remove_deadends(map_t *m, int howmuch) {
solidcell = getmapsolid(m);
for (i = 0; i < howmuch; i++) {
int thiscount = 0;
for (n = 0; n < m->w * m->h; n++) {
cell_t *c;
c = m->cell[n];
if (!c->room && (countcellexits(c, DT_ORTH) == 1)) {
if (!c->room) {
//if ((countcellexits(c, DT_ORTH) == 1) ||
// (countcellexits(c, DT_COMPASS) == 1)) {
if (countcellexits(c, DT_ORTH) == 1) {
// erase this cell
clearcell(c);
setcelltype(c, solidcell);
setcellreason(c, "dead-end removed.");
count++;
thiscount++;
}
}
}
if (!thiscount) break;
}
return count;
}
@ -9311,6 +9324,35 @@ int remove_baddoors(map_t *m) {
return num;
}
int remove_smallrooms(map_t *m) {
int x,y,nremoved = 0;
cell_t *c;
for (y = 0; y < m->h - 3; y++) {
for (x = 0; x < m->w - 3 ; x++) {
c = getcellat(m, x, y);
if (smallroomat(c)) {
int xx,yy;
// fill it in.
for (yy = y+1; yy <= y+2; yy++) {
for (xx = x+1; xx <= x+2; xx++) {
c = getcellat(m, xx, yy);
if (c) {
clearcell(c);
setcelltype(c, getmapsolid(m));
setcellreason(c, "small room at %d,%d removed.",
xx,yy);
}
}
}
nremoved++;
// move on.
x += 4;
}
}
}
return nremoved;
}
void selectcelltypes(map_t *map) {
if (map->habitat->id == H_DUNGEON) {
// random chance of different wall type
@ -9534,6 +9576,50 @@ int shuffledown(map_t *map) {
return B_TRUE;
}
int smallroomat(cell_t *where) {
map_t *m;
int x,y,sx,sy;
int row = 0,col=0;
int gotexit = B_FALSE;
int checkagainst[16] = {
1, 1, 1, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 1, 1, 1
};
cell_t *c;
m = where->map;
sx = where->x;
sy = where->y;
for (y = sy; y <= sy+3 ; y++,row++) {
for (x = sx,col=0; x < sx+3; x++,col++) {
int want,matched = B_FALSE;
c = getcellat(m,x,y);
if (!c) return B_FALSE;
want = checkagainst[row*4+col];
if ((want == 0) && !issolid(c)) {
matched = B_TRUE;
} else if (want == 1) {
if (issolid(c)) {
matched = B_TRUE;
} else {
// we can have one exit through the
// wall
if (!gotexit) {
gotexit = B_TRUE;
matched = B_TRUE;
}
}
}
if (!matched) return B_FALSE;
}
}
return B_TRUE;
}
int unlinkstairsto(map_t *unlinkmap) {
map_t *m;
object_t *o;

2
map.h
View File

@ -197,6 +197,7 @@ int orthdir(int compassdir);
enum RACE parserace(char *name, flagpile_t *wantflags, condset_t *cs, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour);
int remove_deadends(map_t *m, int howmuch);
int remove_baddoors(map_t *m);
int remove_smallrooms(map_t *m);
void selectcelltypes(map_t *map);
void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph);
void setcellknown(cell_t *cell, int forcelev);
@ -205,6 +206,7 @@ void setcellreason(cell_t *c, char *why, ...);
void setcelltype(cell_t *cell, enum CELLTYPE id);
int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring);
int shuffledown(map_t *map);
int smallroomat(cell_t *where);
int unlinkstairsto(map_t *unlinkmap);
void unmakemap(map_t *map);
void updateknowncells(void);

6
move.c
View File

@ -732,7 +732,7 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in
int dist[MAXDIR_COMPASS];
int poss[MAXDIR_COMPASS];
int nposs;
enum ERROR error;
enum ERROR error = E_OK;
if (dirtype == DT_ORTH) {
mindist = getcelldistorth(src, dst);
@ -1468,7 +1468,7 @@ int movelf(lifeform_t *lf, cell_t *newcell, int onpurpose) {
// we want 'xx steps on some pieces of broken glass'
// not 'xx steps on 5 pieces of broken glass'
newname = makeplural(obname);
newname = strrep(newname, "a ", "some ", NULL);
strrep(&newname, "a ", "some ", NULL);
strcpy(obname, newname);
free(newname);
}
@ -2827,7 +2827,7 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
} else if (cansee(player, lf)) {
getlfname(lf, buf);
if (getraceclass(lf) == RC_GOD) {
msg("%s %s!", buf, getflagtext(lf->flags, F_GODTEXTAPPEAR));
msg("^w%s %s!", buf, getflagtext(lf->flags, F_GODTEXTAPPEAR));
} else {
msg("%s appears!", buf);
}

View File

@ -587,7 +587,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
for (om = firstobmod ; om ; om = om->next) {
if (db) dblog("DB: checking for '%s' in '%s'",om->prefix, localname);
if (strstr(localname, om->prefix)) {
localname = strrep(localname, om->prefix, "", NULL);
strrep(&localname, om->prefix, "", NULL);
if (db) dblog("DB: found obmod prefix '%s'",om->prefix);
wantom[nom] = om;
@ -597,7 +597,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
int i;
for (i = 0; i < om->naltprefix; i++) {
if (strstr(localname, om->altprefix[i])) {
localname = strrep(localname, om->altprefix[i], "", NULL);
strrep(&localname, om->altprefix[i], "", NULL);
if (db) dblog("DB: found obmod altprefix '%s'",om->altprefix[i]);
wantom[nom] = om;
nom++;
@ -1321,26 +1321,30 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
o->next = NULL;
// fill in props
// fill in default props
o->id = nextoid++; // increment next ob id
o->type = ot;
o->pile = where;
o->contents = addobpile(NOOWNER, NOLOC, o);
o->birthtime = curtime;
o->dying = B_FALSE;
// inherit props from objecttype
o->flags = addflagpile(NULL, o);
o->contents = addobpile(NOOWNER, NOLOC, o);
// defaults
o->inscription = NULL; // non-inherited
o->letter = '\0';
o->blessed = B_UNCURSED;
o->blessknown = B_FALSE;
o->amt = 1;
// inherit props and flags from objecttype
o->material = ot->material;
assert(o->material);
o->weight = ot->weight;
o->flags = addflagpile(NULL, o);
o->inscription = NULL; // non-inherited
// inherit flags from objecttype
copyflags(o->flags, ot->flags, NA);
// don't want certain objecttype only flags...
//killflagsofid(o->flags, F_RARITY);
@ -3705,31 +3709,31 @@ objecttype_t *findotn(char *name) {
// make some replacements
//replace scrolls with scroll etc
for (pl = firstplural ; pl ; pl = pl->next) {
modname = strrep(modname, pl->plural, pl->singular, NULL);
strrep(&modname, pl->plural, pl->singular, NULL);
}
// only at start...
if (strstr(modname, "the ") == modname) modname = strrep(modname, "the ", "", NULL);
if (strstr(modname, "an ") == modname) modname = strrep(modname, "an ", "", NULL);
if (strstr(modname, "a ") == modname) modname = strrep(modname, "a ", "", NULL);
if (strstr(modname, "the ") == modname) strrep(&modname, "the ", "", NULL);
if (strstr(modname, "an ") == modname) strrep(&modname, "an ", "", NULL);
if (strstr(modname, "a ") == modname) strrep(&modname, "a ", "", NULL);
modname = strrep(modname, "blessed ", "", NULL);
modname = strrep(modname, "uncursed ", "", NULL);
modname = strrep(modname, "cursed ", "", NULL);
strrep(&modname, "blessed ", "", NULL);
strrep(&modname, "uncursed ", "", NULL);
strrep(&modname, "cursed ", "", NULL);
//realloc(modname, strlen(temp)); strcpy(modname, temp); free(temp); // swap
// strip out pre mods
modname = strrep(modname, "flaming ", "", NULL);
modname = strrep(modname, "headless ", "", NULL);
strrep(&modname, "flaming ", "", NULL);
strrep(&modname, "headless ", "", NULL);
// strip out brands (but not only for certain object classes)
for (om = firstbrand; om ; om = om->next) {
modname = strrep(modname, om->suffix, "", NULL);
strrep(&modname, om->suffix, "", NULL);
}
// special cases
modname = strrep(modname, "holy water", "water", NULL);
modname = strrep(modname, "incompetence", "competence", NULL);
strrep(&modname, "holy water", "water", NULL);
strrep(&modname, "incompetence", "competence", NULL);
// skip past bonusses
p = strchr(modname, '+');
@ -5524,6 +5528,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
switch (sk->id) {
case SK_ARMOUR: strcat(basename, "Armour Usage"); break;
case SK_LISTEN: strcat(basename, "Listening"); break;
case SK_LORE_LANGUAGE: strcat(basename, "Linguistics"); break;
case SK_LORE_RELICS: strcat(basename, "Ancient Relics"); break;
default:
strcat(basename, sk->name);
break;
@ -15179,8 +15185,8 @@ void timeeffectsob(object_t *o) {
capitalise(locbuf);
if (o->pile->owner == player) {
// Remove prefix
locbuf = strrep(locbuf, "An ", "", NULL);
locbuf = strrep(locbuf, "A ", "", NULL);
strrep(&locbuf, "An ", "", NULL);
strrep(&locbuf, "A ", "", NULL);
}
msg("%s%s %s.", (o->pile->owner == player) ? "Your " : "", locbuf, f2->text);
free(locbuf);

2
save.c
View File

@ -1349,7 +1349,7 @@ int writehiscore(lifeform_t *lf, int *rank) {
// add escapes
escaped = strdup(killedby);
escaped = strrep(escaped, "'", "''", NULL);
strrep(&escaped, "'", "''", NULL);
if (!lfhasflag(lf, F_NOSCORE)) {
asprintf(&cmd, "insert into 'hiscores' (score,name,job,killedby) VALUES (%ld, '%s', '%s', '%s')", score, pname, jobname, escaped);

View File

@ -20,7 +20,7 @@
#define DEF_REMCURSECOST 60
#define DEF_BLESSCOST 50
#define DEF_IDCOST 50
#define DEF_IDCOST 20
#define DEF_SURCHARGE 15
#define DEF_RESIZECOST 80
#define DEF_REPAIRCOSTPERHP 2

29
spell.c
View File

@ -4292,12 +4292,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
}
} else if (spellid == OT_S_ANIMATEDEAD) {
int i;
int i,nposs = 0;
object_t *o,*nexto;
int donesomething = B_FALSE;
object_t **poss;
if (!target) {
target = caster;
}
poss = malloc(target->nlos * sizeof(object_t *));
// animate corpses within lof of caster
for (i = 0; i < target->nlos; i++) {
targcell = target->los[i];
@ -4305,8 +4307,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = targcell->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (o->type->id == OT_CORPSE) {
poss[nposs++] = o;
}
}
}
}
for (i = 0 ; (i < power) && (nposs > 0); i++) {
lifeform_t *newlf;
newlf = makezombie(o);
int sel,n;
sel = rnd(0,nposs-1);
o = poss[sel];
newlf = makezombie(o, power);
if (newlf) {
if (isplayer(target)){
if (caster && isgod(caster)) {
@ -4320,10 +4332,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
donesomething = B_TRUE;
}
// remove from list
for (n = sel; n < nposs - 1; n++) {
poss[n] = poss[n+1];
}
nposs--;
}
}
}
free(poss);
if (donesomething) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -13763,7 +13778,7 @@ enum OBTYPE getfirstwizspell(enum SPELLSCHOOL school) {
case SS_AIR: firstspell = OT_S_PROPELMISSILE; break;
case SS_COLD: firstspell = OT_S_CHILL; break;
case SS_FIRE: firstspell = OT_S_SPARK; break;
case SS_DEATH: firstspell = OT_S_STENCH; break;
case SS_DEATH: firstspell = OT_S_ANIMATEDEAD; break;
case SS_DIVINATION: firstspell = OT_S_SIXTHSENSE; break;
case SS_TRANSLOCATION: firstspell = OT_S_APPORTATION; break;
case SS_SUMMONING: firstspell = OT_S_GLYPHWARDING; break;
@ -14768,11 +14783,11 @@ void spellcloud(cell_t *srcloc, int radius, int dirtype, int ch, enum COLOUR col
// replace "OB" in seetext/noseetext based on fromob
getobname(fromob, obname, 1);
if (see) {
see = strrep(see, "OB", obname, NULL);
strrep(&see, "OB", obname, NULL);
capitalise(see);
}
if (nosee) {
nosee = strrep(nosee, "OB", obname, NULL);
strrep(&nosee, "OB", obname, NULL);
capitalise(nosee);
}
}

145
text.c
View File

@ -206,7 +206,7 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
char *vn;
// strip "the" from "the xxx"
vn = strdup(victimname);
vn = strrep(vn, "the ", "", NULL);
strrep(&vn, "the ", "", NULL);
switch (helpless) {
case HL_CANTSEE:
sprintf(locvictimname, "the helpless %s", vn);
@ -2192,7 +2192,7 @@ char *makeplural(char *text) {
newtext = strdup(text);
for (pl = firstplural ; pl ; pl = pl->next) {
newtext = strrep(newtext, pl->singular, pl->plural, &rv);
strrep(&newtext, pl->singular, pl->plural, &rv);
if (rv && pl->stopafter) return newtext;
}
@ -2488,6 +2488,7 @@ void splittime(int *hours, int *mins, int *secs) {
*secs = left;
}
/*
char *strrep(char *text, char *oldtok, char *newtok, int *rv) {
char *temp;
temp = strdup(" "); // ooooooo is this bad??
@ -2503,11 +2504,15 @@ char *strrep(char *text, char *oldtok, char *newtok, int *rv) {
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv) {
char *temp;
char *found;
char *newout = NULL;
int idx;
found = strstr(in, oldtok);
if(!found) {
*out = realloc(*out, strlen(in) + 1); // oooooooo crashing in realloc
strcpy(*out, in);
newout = calloc(1, strlen(in)+1);
strcpy(newout, in);
free(*out);
*out = newout;
if (rv) *rv = B_FALSE;
return *out;
@ -2515,24 +2520,136 @@ char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv) {
idx = found - in;
*out = realloc(*out, strlen(in) - strlen(oldtok) + strlen(newtok) + 1);
strncpy(*out, in, idx);
strcpy(*out + idx, newtok);
strcpy(*out + idx + strlen(newtok), in + idx + strlen(oldtok));
newout = calloc(1, strlen(in) - strlen(oldtok) + strlen(newtok) + 1);
strncpy(newout, in, idx);
strcpy(newout + idx, newtok);
strcpy(newout + idx + strlen(newtok), in + idx + strlen(oldtok));
temp = malloc(idx+strlen(newtok)+1);
strncpy(temp,*out,idx+strlen(newtok));
strncpy(temp,newout,idx+strlen(newtok));
temp[idx + strlen(newtok)] = '\0';
dostrrep(found + strlen(oldtok), out, oldtok, newtok, rv);
temp = realloc(temp, strlen(temp) + strlen(*out) + 1);
strcat(temp,*out);
free(*out);
*out = temp;
*out = newout;
dostrrep(found + strlen(oldtok), out, oldtok, newtok, rv);
newout = calloc(1,strlen(temp) + strlen(*out) + 1);
strcpy(newout, temp);
strcat(newout,*out);
free(temp);
free(*out);
*out = newout;
if (rv) *rv = B_TRUE;
return *out;
}
*/
// returns a NEW string: copy of s1 but with occurences of s2 replaced by s3.
// Taken from https://gist.github.com/975639
// Written in 2011 by Drew Hess <dhess-src@bothan.net>.
//
char *do_strrep(const char *s1, const char *s2, const char *s3) {
if (!s1 || !s2 || !s3)
return NULL;
size_t s1_len = strlen(s1);
if (!s1_len)
//return (char *)s1;
return NULL;
size_t s2_len = strlen(s2);
if (!s2_len)
//return (char *)s1;
return NULL;
/*
* Two-pass approach: figure out how much space to allocate for
* the new string, pre-allocate it, then perform replacement(s).
*/
size_t count = 0;
const char *p = s1;
assert(s2_len); /* otherwise, strstr(s1,s2) will return s1. */
do {
p = strstr(p, s2);
if (p) {
p += s2_len;
++count;
}
} while (p);
if (!count)
return (char *)s1;
/*
* The following size arithmetic is extremely cautious, to guard
* against size_t overflows.
*/
assert(s1_len >= count * s2_len);
assert(count);
size_t s1_without_s2_len = s1_len - count * s2_len;
size_t s3_len = strlen(s3);
size_t newstr_len = s1_without_s2_len + count * s3_len;
if (s3_len &&
((newstr_len <= s1_without_s2_len) || (newstr_len + 1 == 0)))
/* Overflow. */
return 0;
char *newstr = (char *)malloc(newstr_len + 1); /* w/ terminator */
if (!newstr)
/* ENOMEM, but no good way to signal it. */
return 0;
char *dst = newstr;
const char *start_substr = s1;
size_t i;
for (i = 0; i != count; ++i) {
const char *end_substr = strstr(start_substr, s2);
assert(end_substr);
size_t substr_len = end_substr - start_substr;
memcpy(dst, start_substr, substr_len);
dst += substr_len;
memcpy(dst, s3, s3_len);
dst += s3_len;
start_substr = end_substr + s2_len;
}
/* copy remainder of s1, including trailing '\0' */
size_t remains = s1_len - (start_substr - s1) + 1;
assert(dst + remains == newstr + newstr_len + 1);
memcpy(dst, start_substr, remains);
assert(strlen(newstr) == newstr_len);
return newstr;
}
// reallocates text
// returns TRUE if replacements were made.
char *strrep(char **text, char *oldtok, char *newtok, int *rv) {
char *temp;
if (rv) *rv = B_FALSE;
temp = do_strrep(*text, oldtok, newtok);
if (!temp) {
// failed
return *text;
}
if (streq(temp, *text)) {
// no change
return *text;
}
// there WAS a change. free original pointer contents and
// point at new text instead.
if (rv) *rv = B_TRUE;
free(*text);
*text = temp;
return *text;
}
int streq(char *a, char *b) {
if (!a || !b) return B_FALSE;
@ -2894,6 +3011,8 @@ int texttospellopts(char *text, ... ) {
*((int *)writeto) = argdefault[foundidx];
} else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, "");
} else {
assert("texttospellopts() error - argtype not found" == 0);
}
// look for 'wantname' within 'text'

5
text.h
View File

@ -74,8 +74,13 @@ 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);
*/
char *strrep(char **text, char *oldtok, char *newtok, int *rv);
char *do_strrep(const char *s1, const char *s2, const char *s3);
int streq(char *a, char *b);
char *strends(char *a, char *suffix);
char *strcasestarts(char *a, char *prefix);

View File

@ -1627,6 +1627,9 @@ vault_t *loadvault(char *dir, char *filename) {
v->state = VS_NOID;
// init line.
bzero(line, BUFLEN);
// read a line
fgets(line, BUFLEN, f);
while (!feof(f)) {