From ca132c87c747ed6de46ed41706bbad464749a862 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Wed, 14 Nov 2012 04:59:18 +0000 Subject: [PATCH] - [+] 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 --- ai.c | 21 +++-- attack.c | 10 +- data.c | 60 ++++++------ data/hiscores.db | Bin 17408 -> 17408 bytes data/vaults/bedroom_common.vlt | 25 +++++ data/vaults/coldroom.vlt | 25 +++++ data/vaults/crossroads_fire.vlt | 22 +++++ data/vaults/firepit.vlt | 30 ++++++ data/vaults/fortified_room.vlt | 25 +++++ data/vaults/glasswall.vlt | 1 + data/vaults/pitbridge.vlt | 19 ++++ data/vaults/pitbridge_guarded.vlt | 24 +++++ data/vaults/pub.vlt | 30 ++++++ data/vaults/windowinwall.vlt | 18 ++++ defs.h | 10 +- flag.c | 8 +- god.c | 10 +- io.c | 17 ++-- lf.c | 45 +++++---- lf.h | 2 +- map.c | 104 +++++++++++++++++++-- map.h | 2 + move.c | 6 +- objects.c | 56 +++++++----- save.c | 2 +- shops.c | 2 +- spell.c | 53 +++++++---- text.c | 147 +++++++++++++++++++++++++++--- text.h | 5 + vault.c | 3 + 30 files changed, 633 insertions(+), 149 deletions(-) create mode 100644 data/vaults/bedroom_common.vlt create mode 100644 data/vaults/coldroom.vlt create mode 100644 data/vaults/crossroads_fire.vlt create mode 100644 data/vaults/firepit.vlt create mode 100644 data/vaults/fortified_room.vlt create mode 100644 data/vaults/pitbridge.vlt create mode 100644 data/vaults/pitbridge_guarded.vlt create mode 100644 data/vaults/pub.vlt create mode 100644 data/vaults/windowinwall.vlt diff --git a/ai.c b/ai.c index 78f42a3..53e9519 100644 --- a/ai.c +++ b/ai.c @@ -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 we _DO_ have lof to the cell, we'll just walk direclty towards it. if (c) { // try to move towards the cell @@ -2358,9 +2360,9 @@ 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); + addignorecell(lf, c); c = NULL; } else { int turned = B_FALSE; @@ -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. diff --git a/attack.c b/attack.c index 39f33cd..8e8c280 100644 --- a/attack.c +++ b/attack.c @@ -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); } diff --git a/data.c b/data.c index d0e8355..4855991 100644 --- a/data.c +++ b/data.c @@ -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); diff --git a/data/hiscores.db b/data/hiscores.db index 23c892c6aa63a33d88638b84f3eec10a63326508..30da5fc7172b28ec96e0f4d32b8f855a4fc247c9 100644 GIT binary patch delta 207 zcmZqZU~K4MoFL68xKZW>JF_fv{$zFzGuBGx66XBPP8_<-{4C52jItm?21H12uH$Yq z;A3U-XJB5>9LUVfw3*3&W1%gROp+`+1Cy|3qb%d$qWmPEGGm3X)SMgzzs$U>#K|9( zq=ZWIic1oca#9rv^2<|;6q56cChO_T$oa{z0rlw@GF$;`Gg9y<%}vZx2v003$^Rq&ElJuV(=O-6=Re delta 75 zcmZqZU~K4MoFL7}w^8N=JF^sX-DGwSGgbx0WsD0pJ8|eT^D{FrF*>sXNroN}xw($J c&47c6Igo*QJ#*m3!mCUZ8wxfD+OKB;0F?L=R{#J2 diff --git a/data/vaults/bedroom_common.vlt b/data/vaults/bedroom_common.vlt new file mode 100644 index 0000000..dcac4b6 --- /dev/null +++ b/data/vaults/bedroom_common.vlt @@ -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 + diff --git a/data/vaults/coldroom.vlt b/data/vaults/coldroom.vlt new file mode 100644 index 0000000..65bdc28 --- /dev/null +++ b/data/vaults/coldroom.vlt @@ -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 + diff --git a/data/vaults/crossroads_fire.vlt b/data/vaults/crossroads_fire.vlt new file mode 100644 index 0000000..efc93d7 --- /dev/null +++ b/data/vaults/crossroads_fire.vlt @@ -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 + diff --git a/data/vaults/firepit.vlt b/data/vaults/firepit.vlt new file mode 100644 index 0000000..129fc0a --- /dev/null +++ b/data/vaults/firepit.vlt @@ -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 + diff --git a/data/vaults/fortified_room.vlt b/data/vaults/fortified_room.vlt new file mode 100644 index 0000000..ae5e353 --- /dev/null +++ b/data/vaults/fortified_room.vlt @@ -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 + diff --git a/data/vaults/glasswall.vlt b/data/vaults/glasswall.vlt index 0c72f5a..874701f 100644 --- a/data/vaults/glasswall.vlt +++ b/data/vaults/glasswall.vlt @@ -19,5 +19,6 @@ autodoors:50 mayrotate autopop rarity:uncommon +maintainedge @end diff --git a/data/vaults/pitbridge.vlt b/data/vaults/pitbridge.vlt new file mode 100644 index 0000000..c7fc43f --- /dev/null +++ b/data/vaults/pitbridge.vlt @@ -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 + diff --git a/data/vaults/pitbridge_guarded.vlt b/data/vaults/pitbridge_guarded.vlt new file mode 100644 index 0000000..604a658 --- /dev/null +++ b/data/vaults/pitbridge_guarded.vlt @@ -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 + diff --git a/data/vaults/pub.vlt b/data/vaults/pub.vlt new file mode 100644 index 0000000..4a4f57c --- /dev/null +++ b/data/vaults/pub.vlt @@ -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 + diff --git a/data/vaults/windowinwall.vlt b/data/vaults/windowinwall.vlt new file mode 100644 index 0000000..eba3253 --- /dev/null +++ b/data/vaults/windowinwall.vlt @@ -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 diff --git a/defs.h b/defs.h index d3412e6..3a7ae36 100644 --- a/defs.h +++ b/defs.h @@ -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) diff --git a/flag.c b/flag.c index cced072..bf94733 100644 --- a/flag.c +++ b/flag.c @@ -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) { diff --git a/god.c b/god.c index ac4b5b9..c942850 100644 --- a/god.c +++ b/god.c @@ -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); diff --git a/io.c b/io.c index 7e9993e..6718472 100644 --- a/io.c +++ b/io.c @@ -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); @@ -2218,7 +2218,7 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { } // dont announce loss of flags yoh didnt know about - if (!f->known) { + if (!f->known) { return B_FALSE; } @@ -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. diff --git a/lf.c b/lf.c index debb60b..05548fd 100644 --- a/lf.c +++ b/lf.c @@ -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); diff --git a/lf.h b/lf.h index 4dfd49f..1577548 100644 --- a/lf.h +++ b/lf.h @@ -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); diff --git a/map.c b/map.c index e10a67d..15236e1 100644 --- a/map.c +++ b/map.c @@ -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,16 +9269,24 @@ 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)) { - // erase this cell - clearcell(c); - setcelltype(c, solidcell); - count++; + 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; diff --git a/map.h b/map.h index 775fcba..322b17a 100644 --- a/map.h +++ b/map.h @@ -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); diff --git a/move.c b/move.c index 281a4f3..6abe369 100644 --- a/move.c +++ b/move.c @@ -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); } diff --git a/objects.c b/objects.c index c19575d..7b29eaf 100644 --- a/objects.c +++ b/objects.c @@ -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); diff --git a/save.c b/save.c index 4a417c4..86ce2db 100644 --- a/save.c +++ b/save.c @@ -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); diff --git a/shops.c b/shops.c index 794c710..d74bdfb 100644 --- a/shops.c +++ b/shops.c @@ -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 diff --git a/spell.c b/spell.c index af87bed..a5a166f 100644 --- a/spell.c +++ b/spell.c @@ -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,26 +4307,39 @@ 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) { - lifeform_t *newlf; - newlf = makezombie(o); - if (newlf) { - if (isplayer(target)){ - if (caster && isgod(caster)) { - makefriendly(newlf, PERMENANT); - } else if (skillcheck(target, A_IQ, 100, power)) { - makefriendly(newlf, PERMENANT); - } else if (cansee(target, newlf) && - areenemies(target, newlf)) { - msg("Uh oh, you have a bad feeling about this..."); - } - } - donesomething = B_TRUE; - } + poss[nposs++] = o; } } } } + for (i = 0 ; (i < power) && (nposs > 0); i++) { + lifeform_t *newlf; + int sel,n; + sel = rnd(0,nposs-1); + o = poss[sel]; + newlf = makezombie(o, power); + if (newlf) { + if (isplayer(target)){ + if (caster && isgod(caster)) { + makefriendly(newlf, PERMENANT); + } else if (skillcheck(target, A_IQ, 100, power)) { + makefriendly(newlf, PERMENANT); + } else if (cansee(target, newlf) && + areenemies(target, newlf)) { + msg("Uh oh, you have a bad feeling about this..."); + } + } + 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; } else { @@ -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); } } diff --git a/text.c b/text.c index 15dcc6b..854ef6e 100644 --- a/text.c +++ b/text.c @@ -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 . +// + +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' diff --git a/text.h b/text.h index c7e1037..65696d1 100644 --- a/text.h +++ b/text.h @@ -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); diff --git a/vault.c b/vault.c index e371541..c37d23d 100644 --- a/vault.c +++ b/vault.c @@ -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)) {