- [+] 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:
parent
98ba363e8a
commit
ca132c87c7
21
ai.c
21
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.
|
||||
|
|
10
attack.c
10
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);
|
||||
}
|
||||
|
|
60
data.c
60
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);
|
||||
|
|
BIN
data/hiscores.db
BIN
data/hiscores.db
Binary file not shown.
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -19,5 +19,6 @@ autodoors:50
|
|||
mayrotate
|
||||
autopop
|
||||
rarity:uncommon
|
||||
maintainedge
|
||||
@end
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
10
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)
|
||||
|
||||
|
|
8
flag.c
8
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) {
|
||||
|
|
10
god.c
10
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);
|
||||
|
|
17
io.c
17
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.
|
||||
|
|
45
lf.c
45
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);
|
||||
|
|
2
lf.h
2
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);
|
||||
|
|
104
map.c
104
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;
|
||||
|
|
2
map.h
2
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);
|
||||
|
|
6
move.c
6
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);
|
||||
}
|
||||
|
|
56
objects.c
56
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);
|
||||
|
|
2
save.c
2
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);
|
||||
|
|
2
shops.c
2
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
|
||||
|
|
53
spell.c
53
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);
|
||||
}
|
||||
}
|
||||
|
|
147
text.c
147
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 <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
5
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);
|
||||
|
|
Loading…
Reference in New Issue