Merge remote-tracking branch 'refs/remotes/origin/master'

This commit is contained in:
Rob Pearce 2023-05-10 14:56:07 +10:00
commit 54980b6cc1
15 changed files with 257 additions and 38 deletions

View File

@ -834,11 +834,12 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
} }
if (dostamloss) { if (dostamloss) {
object_t *priwep; object_t *priwep;
float loss;
priwep = getweapon(lf); priwep = getweapon(lf);
// lose a bit of stamina loss = getattackstamlosslf(lf, priwep);
modstamina(lf, -getattackstamloss(priwep)); // lose a bit of stamina
modstamina(lf, -loss);
} }
//}
// stop sprinting // stop sprinting
stopsprinting(lf); stopsprinting(lf);

11
data.c
View File

@ -174,8 +174,10 @@ void initcommands(void) {
addcommand(CMD_UP, '<', "Go up stairs."); addcommand(CMD_UP, '<', "Go up stairs.");
addcommand(CMD_DOWN, '>', "Go down stairs, enter a shop/portal."); addcommand(CMD_DOWN, '>', "Go down stairs, enter a shop/portal.");
addcommand(CMD_GO, 'G', "Go to a set position (pathfind)."); addcommand(CMD_GO, 'G', "Go to a set position (pathfind).");
addcommand(CMD_EXPLORE, 'z', "Auto-explore the current level");
// Actions // Actions
addcommand(CMD_AGAIN, 'g', "Repeat last action."); addcommand(CMD_AGAIN, 'g', "Repeat last action (do aGain).");
addcommand(CMD_REPEATSPELL, 'p', "RePeat last spell/ability.");
addcommand(CMD_REST, '.', "Rest once."); addcommand(CMD_REST, '.', "Rest once.");
addcommand(CMD_PICKUP, ',', "Pick up something from the ground."); addcommand(CMD_PICKUP, ',', "Pick up something from the ground.");
addcommand(CMD_COMMS, 'c', "Chat/Communicate with someone."); addcommand(CMD_COMMS, 'c', "Chat/Communicate with someone.");
@ -203,7 +205,7 @@ void initcommands(void) {
addcommand(CMD_FIRE, 'f', "Fire your firearm/bow at your current target."); addcommand(CMD_FIRE, 'f', "Fire your firearm/bow at your current target.");
addcommand(CMD_FIRENEW, 'F', "Fire your firearm/bow at a new target."); addcommand(CMD_FIRENEW, 'F', "Fire your firearm/bow at a new target.");
addcommand(CMD_AIM, 'a', "Aim your current firearm/bow at a new target."); addcommand(CMD_AIM, 'a', "Aim your current firearm/bow at a new target.");
addcommand(CMD_GUNRELOAD, 'a', "Reload current firearm/bow with current ammo."); addcommand(CMD_GUNRELOAD, 'v', "Reload (quiVer) firearm/bow with current ammo.");
addcommand(CMD_NEXTTARGET, '\'', "Cycle to next firearm target."); addcommand(CMD_NEXTTARGET, '\'', "Cycle to next firearm target.");
// Information // Information
addcommand(CMD_HELP, '?', "Display this text."); addcommand(CMD_HELP, '?', "Display this text.");
@ -2398,7 +2400,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_IMPORTANT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_IMPORTANT, B_TRUE, NA, NA, NULL);
addot(OT_TREEDOWN, "hollow tree leading down", "A huge hollow tree containing an ascending staircase.", MT_DRAGONWOOD, 3000, OC_DFEATURE, SZ_HUGE); addot(OT_TREEDOWN, "hollow tree leading down", "A huge hollow tree containing a descending staircase.", MT_DRAGONWOOD, 3000, OC_DFEATURE, SZ_HUGE);
addflag(lastot->flags, F_GLYPH, C_WOOD, '>', NA, NULL); addflag(lastot->flags, F_GLYPH, C_WOOD, '>', NA, NULL);
addflag(lastot->flags, F_STAIRS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_STAIRS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, "hollow tree"); addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, "hollow tree");
@ -21201,7 +21203,7 @@ void initskills(void) {
if (isweaponskill(sk->id) || (sk->id == SK_UNARMED)) { if (isweaponskill(sk->id) || (sk->id == SK_UNARMED)) {
addskilldesc(sk->id, PR_INEPT, "This skill increases your accuracy and damage when using matching weapons.", B_FALSE); addskilldesc(sk->id, PR_INEPT, "This skill increases your accuracy and damage when using matching weapons.", B_FALSE);
if (sk->id == SK_CLUBS) addskilldesc(sk->id, PR_NOVICE, "^gYou gain the 'merciful fighting' ability.^n", B_FALSE); addskilldesc(sk->id, PR_INEPT, "Each skill level also decreases stamina usage of matching weapons by 10%.", B_FALSE);
addskilldesc(sk->id, PR_NOVICE, "^gYou can now recognise the quality of matching weapons.^n", B_FALSE); addskilldesc(sk->id, PR_NOVICE, "^gYou can now recognise the quality of matching weapons.^n", B_FALSE);
addskilldesc(sk->id, PR_NOVICE, "^gEliminates accuracy penalties with matching weapons.^n", B_FALSE); addskilldesc(sk->id, PR_NOVICE, "^gEliminates accuracy penalties with matching weapons.^n", B_FALSE);
addskilldesc(sk->id, PR_BEGINNER, "^g+1 accuracy.^n", B_FALSE); addskilldesc(sk->id, PR_BEGINNER, "^g+1 accuracy.^n", B_FALSE);
@ -21220,7 +21222,6 @@ void initskills(void) {
addskilldesc(sk->id, PR_SKILLED, "^gYou can now block certain attacks with this kind of weapon.^n", B_FALSE); addskilldesc(sk->id, PR_SKILLED, "^gYou can now block certain attacks with this kind of weapon.^n", B_FALSE);
} }
addskilldesc(sk->id, PR_EXPERT, "^g+4 accuracy, +30% damage bonus.^n", B_FALSE); addskilldesc(sk->id, PR_EXPERT, "^g+4 accuracy, +30% damage bonus.^n", B_FALSE);
if (sk->id == SK_UNARMED) addskilldesc(sk->id, PR_EXPERT, "^gYou gain the 'flip' ability.^n", B_FALSE);
addskilldesc(sk->id, PR_MASTER, "^g+6 accuracy, +40%% damage bonus, combination strike ability.^n", B_FALSE); addskilldesc(sk->id, PR_MASTER, "^g+6 accuracy, +40%% damage bonus, combination strike ability.^n", B_FALSE);
if (sk->id != SK_UNARMED) { if (sk->id != SK_UNARMED) {

13
defs.h
View File

@ -975,6 +975,7 @@ enum SKILLLEVEL {
PR_MASTER = 6, PR_MASTER = 6,
}; };
#define MAXSKILLLEVEL 7 #define MAXSKILLLEVEL 7
#define MAXSKILLDESC (MAXSKILLLEVEL*3)
#define MAXSKILLWILLS (MAXSKILLLEVEL*5) #define MAXSKILLWILLS (MAXSKILLLEVEL*5)
@ -3747,6 +3748,7 @@ enum FLAG {
F_CAREFULMOVE, // moving slowly on purpose to avoid slipping. F_CAREFULMOVE, // moving slowly on purpose to avoid slipping.
F_AUTOCMD, // val0 = how many times to repeat this F_AUTOCMD, // val0 = how many times to repeat this
F_LASTCMD, // text[0] = last command performed, v0/1 = x/y of cell, v2=various F_LASTCMD, // text[0] = last command performed, v0/1 = x/y of cell, v2=various
F_LASTSPELL, // val0=id of last spell cast, for player only
F_WILLTHROW, // this lf will treat obid v0 as a thrown missile. F_WILLTHROW, // this lf will treat obid v0 as a thrown missile.
F_CANSTUDY, // lf can study spells from school v0 F_CANSTUDY, // lf can study spells from school v0
F_CANLEARN, // lf is able to learn skill val0 F_CANLEARN, // lf is able to learn skill val0
@ -4372,8 +4374,9 @@ enum FLAG {
F_XRAYVIS, //val0=num of walls we can see through F_XRAYVIS, //val0=num of walls we can see through
F_CANSEETHROUGHMAT, //val0=kind of material you can see through F_CANSEETHROUGHMAT, //val0=kind of material you can see through
F_CANSEETHROUGHLF, // larger lifeforms don't block los for us F_CANSEETHROUGHLF, // larger lifeforms don't block los for us
F_PATHFINDING, // you are following a path via 'G' F_PATHFINDING, // you are following a path via 'G' or 'z'
// to coords v0,v1 on mapid v2 // to coords v0,v1 on mapid v2
// str = G or z
F_SPRINTING, // you are sprinting. F_SPRINTING, // you are sprinting.
F_WOUNDING, // increase all damage done by this lf by v0 F_WOUNDING, // increase all damage done by this lf by v0
F_WINDSHIELD,// has a windshield protecting against missiles of speed F_WINDSHIELD,// has a windshield protecting against missiles of speed
@ -4751,6 +4754,7 @@ enum COMMAND {
CMD_DROP, CMD_DROP,
CMD_DROPMULTI, CMD_DROPMULTI,
CMD_EAT, CMD_EAT,
CMD_EXPLORE,
CMD_FIRE, CMD_FIRE,
CMD_FIRENEW, CMD_FIRENEW,
CMD_FORCEATTACK, CMD_FORCEATTACK,
@ -4777,6 +4781,7 @@ enum COMMAND {
CMD_QUAFF, CMD_QUAFF,
CMD_QUIT, CMD_QUIT,
CMD_READ, CMD_READ,
CMD_REPEATSPELL,
CMD_REST, CMD_REST,
CMD_RESTFULL, CMD_RESTFULL,
CMD_SAVEQUIT, CMD_SAVEQUIT,
@ -5371,9 +5376,9 @@ typedef struct skill_s {
char *name; char *name;
char *shortname; char *shortname;
char *desc; char *desc;
enum SKILLLEVEL skilldesclev[MAXSKILLLEVEL*2]; enum SKILLLEVEL skilldesclev[MAXSKILLDESC];
char *skilldesctext[MAXSKILLLEVEL*2]; char *skilldesctext[MAXSKILLDESC];
int skilldescmsg[MAXSKILLLEVEL*2]; int skilldescmsg[MAXSKILLDESC];
int nskilldesc; int nskilldesc;
struct skillwill_s { struct skillwill_s {

2
find_unused_letters.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
echo {a..z} {A..Z} | tr ' ' '\n' | egrep -v $(grep addcom *.c | grep -v '//' | grep -v \\\\ | awk -F\' '{print $2}' | egrep "[a-zA-Z]" | tr '\n' '|' | sed 's/^|//;s/|$//')

7
god.c
View File

@ -1593,7 +1593,6 @@ int godgiftmaybe(enum RACE rid, int fromtemple, int announce) {
f->obfrom = god->race->id; f->obfrom = god->race->id;
} }
break; break;
} }
} }
} }
@ -1672,6 +1671,12 @@ int godgiftmaybe(enum RACE rid, int fromtemple, int announce) {
} else { } else {
msg("You hear something hitting the ground."); msg("You hear something hitting the ground.");
} }
// fire god's gifts are always fireproof
if (rid == R_GODFIRE) {
makefireproof(o);
}
} }
} }

55
io.c
View File

@ -6700,12 +6700,12 @@ char *makedesc_ob(object_t *o, char *retbuf) {
} }
} }
stamcost = getattackstamloss(o); stamcost = getattackstamlosslf(player, o);
snprintf(buf2, BUFLEN, ", and Stamina cost is %0.2f",stamcost); snprintf(buf2, BUFLEN, ", and Stamina cost for you is %0.2f",stamcost);
strcat(buf, buf2); strcat(buf, buf2);
if (compareob) { if (compareob) {
float cstamcost,diff; float cstamcost,diff;
cstamcost = getattackstamloss(compareob); cstamcost = getattackstamlosslf(player, compareob);
diff = stamcost - cstamcost; diff = stamcost - cstamcost;
if (diff == 0) { if (diff == 0) {
strcat(buf, " (=)"); strcat(buf, " (=)");
@ -7811,9 +7811,11 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, " - %s", contentname); sprintf(buf, " - %s", contentname);
if ((o->type->id == OT_SPELLBOOK) || (o->type->id == OT_GRIMOIRE)) { if ((o->type->id == OT_SPELLBOOK) || (o->type->id == OT_GRIMOIRE)) {
char lbuf[BUFLEN]; char lbuf[BUFLEN];
char kbuf[BUFLEN];
sprintf(kbuf, " ^%d[known]^n", C_GREEN);
sprintf(lbuf, " (Lv %d %s)%s", getspelllevel(oo->type->id), getschoolname(getspellschool(oo->type->id)), sprintf(lbuf, " (Lv %d %s)%s", getspelllevel(oo->type->id), getschoolname(getspellschool(oo->type->id)),
lfhasflagval(player, F_CANCAST, oo->type->id, NA, NA, NULL) ? lfhasflagval(player, F_CANCAST, oo->type->id, NA, NA, NULL) ?
" [known]" : ""); kbuf : "");
strcat(buf, lbuf); strcat(buf, lbuf);
} }
strcat(buf, "\n"); strcat(buf, "\n");
@ -8545,7 +8547,7 @@ char *makedesc_spell(objecttype_t *ot, char *retbuf) {
return retbuf; return retbuf;
} }
// if wantunknown is set, lsit spells we DONT know. // if wantunknown is set, list spells we DONT know.
// otherwise list spells we DO know. // otherwise list spells we DO know.
// only include spells which cost <= mpcutoff // only include spells which cost <= mpcutoff
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard, int mpcutoff) { void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard, int mpcutoff) {
@ -11270,6 +11272,9 @@ void handleinput(void) {
case CMD_GO: // go somewhere (pathfind) case CMD_GO: // go somewhere (pathfind)
startpathfind(); startpathfind();
break; break;
case CMD_EXPLORE: // autoexplore
startexplore(B_TRUE);
break;
case CMD_HELP: // help case CMD_HELP: // help
dohelp('?'); dohelp('?');
break; break;
@ -11311,6 +11316,14 @@ void handleinput(void) {
case CMD_MEMMAGIC: // 'M'emorise magic/ability shortcut case CMD_MEMMAGIC: // 'M'emorise magic/ability shortcut
domemmagic(); domemmagic();
break; break;
case CMD_REPEATSPELL: // 're'p'eat last spell/ability
f = hasflag(player->flags, F_LASTSPELL);
if (f) {
domagic(f->val[0], NA, NA);
} else {
msg("There is no previous spell to repeat.");
}
break;
case CMD_UP: // go up case CMD_UP: // go up
if (isprone(player)) { if (isprone(player)) {
standup(player); standup(player);
@ -15260,6 +15273,33 @@ void showpath(lifeform_t *lf) {
restoregamewindows(); restoregamewindows();
} }
// TODO: not quite working. sometimes seems to flip back and forth between 2 positions
int startexplore(int announce) {
cell_t *c;
c = get_explore_target(player);
if (!c) {
msg("Can't find any unknown cells to explore.");
return B_TRUE;
}
killflagsofid(player->flags, F_PATHFINDING);
if (ai_createpathto(player, c)) {
addflag(player->flags, F_PATHFINDING, c->x, c->y, player->cell->map->id, "z");
//msg("Going from %d,%d to unexplored %d,%d", player->cell->x, player->cell->y, c->x, c->y);
if (announce) {
msg("Starting auto-explore.");
} else {
msg("Continuing auto-explore.");
}
} else {
msg("Pathfind failed from %d,%d to unexplored %d,%d", player->cell->x, player->cell->y, c->x, c->y);
}
return B_FALSE;
}
void startpathfind(void) { void startpathfind(void) {
cell_t *c = NULL; cell_t *c = NULL;
c = askcoords("Go to where?", "Goto->", TT_NONE, player, UNLIMITED, LOF_DONTNEED, B_FALSE); c = askcoords("Go to where?", "Goto->", TT_NONE, player, UNLIMITED, LOF_DONTNEED, B_FALSE);
@ -15272,11 +15312,10 @@ void startpathfind(void) {
(haslos(player, c) && !cellwalkable(player, c, NULL))) { (haslos(player, c) && !cellwalkable(player, c, NULL))) {
msg("You don't know how to get there."); msg("You don't know how to get there.");
return; return;
} }
// try to find path. // try to find path.
if (ai_createpathto(player, c)) { if (ai_createpathto(player, c)) {
addflag(player->flags, F_PATHFINDING, c->x, c->y, player->cell->map->id, NULL); addflag(player->flags, F_PATHFINDING, c->x, c->y, player->cell->map->id, "G");
} else { } else {
msg("You don't know how to get there."); msg("You don't know how to get there.");
} }
@ -15413,7 +15452,7 @@ void tombstone(lifeform_t *lf) {
wattroff(mainwin, A_BOLD); wattroff(mainwin, A_BOLD);
wattron(mainwin, A_BOLD); wattron(mainwin, A_BOLD);
mvwprintw(mainwin, y, 0, HISCOREFORMAT, "Pos", "Score", "Name", "Job"); mvwprintw(mainwin, y, 0, HISCOREFORMAT, "Pos", "Score", "Name", "Job");
wprintw(mainwin, "Method of death"); y++; wprintw(mainwin, "Cause of death"); y++;
wmove(mainwin, y, 0); wmove(mainwin, y, 0);
wattroff(mainwin, A_BOLD); wattroff(mainwin, A_BOLD);

1
io.h
View File

@ -158,6 +158,7 @@ int showhiscoreline(void *hilitescore, int ncols, char **argv, char **colname);
void showlfarmour(lifeform_t *lf); void showlfarmour(lifeform_t *lf);
void showlfstats(lifeform_t *lf, int showall); void showlfstats(lifeform_t *lf, int showall);
void showpath(lifeform_t *lf); void showpath(lifeform_t *lf);
int startexplore(int announce);
void startpathfind(void); void startpathfind(void);
void textwithcol(WINDOW *win, char *buf); void textwithcol(WINDOW *win, char *buf);
void textwithcol_real(WINDOW *win, char *buf, int resetcolatend); void textwithcol_real(WINDOW *win, char *buf, int resetcolatend);

36
lf.c
View File

@ -2156,6 +2156,11 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
// lose mp // lose mp
losemp(lf, cost); losemp(lf, cost);
// remember spell for rePeat command
if (isplayer(lf)) {
modflag(lf->flags, F_LASTSPELL, sid, NA, NA, NULL);
}
// spell fails? // spell fails?
// miscast chance? // miscast chance?
if (isplayer(lf) && !hasjob(lf, J_GOD)) { if (isplayer(lf) && !hasjob(lf, J_GOD)) {
@ -5783,7 +5788,7 @@ void enhanceskills(lifeform_t *lf) {
for (i = 0; i < nposs; i++) { for (i = 0; i < nposs; i++) {
char this[2]; char this[2];
snprintf(this, 1, "%c", getattrletter(poss[i])); snprintf(this, 2, "%c", getattrletter(poss[i]));
if (isalpha(this[0])) { if (isalpha(this[0])) {
if (i == 0) { if (i == 0) {
snprintf(ques, BUFLEN, "Increase your %s", getattrname(poss[i])); snprintf(ques, BUFLEN, "Increase your %s", getattrname(poss[i]));
@ -8014,6 +8019,25 @@ int getattackspeed(lifeform_t *lf) {
return (int)speed; return (int)speed;
} }
float getattackstamlosslf(lifeform_t *lf, object_t *wep) {
float loss;
loss = getattackstamloss(wep); // base loss
if (wep && loss > 0) {
flag_t *f;
// modify based on proficiency
f = hasflag(wep->flags, F_USESSKILL);
if (f && (f->val[0] != SK_NONE)) {
enum SKILLLEVEL slev;
slev = getskill(lf, f->val[0]);
if (slev >= PR_NOVICE) {
loss *= ((float)slev/10);
limitf(&loss, 0, NA);
}
}
}
return loss;
}
float getattackstamloss(object_t *wep) { float getattackstamloss(object_t *wep) {
float loss; float loss;
loss = STAMTOATTACK; loss = STAMTOATTACK;
@ -16020,6 +16044,7 @@ void addskillabil(enum SKILL id, enum SKILLLEVEL lev, enum OBTYPE abilid, int ti
skill_t *sk; skill_t *sk;
sk = findskill(id); sk = findskill(id);
assert(sk); assert(sk);
assert(sk->nskillwills < MAXSKILLWILLS);
if (announce) { if (announce) {
objecttype_t *ot; objecttype_t *ot;
@ -16039,8 +16064,6 @@ void addskillabil(enum SKILL id, enum SKILLLEVEL lev, enum OBTYPE abilid, int ti
sk->skillwill[sk->nskillwills].text = NULL; sk->skillwill[sk->nskillwills].text = NULL;
} }
sk->nskillwills++; sk->nskillwills++;
} }
// rid is optional, can be R_NONE // rid is optional, can be R_NONE
@ -16238,6 +16261,7 @@ void addskilldesc(enum SKILL id, enum SKILLLEVEL lev, char *text, int wantmsg) {
skill_t *sk; skill_t *sk;
sk = findskill(id); sk = findskill(id);
assert(sk); assert(sk);
assert(sk->nskilldesc < MAXSKILLDESC);
sk->skilldesclev[sk->nskilldesc] = lev; sk->skilldesclev[sk->nskilldesc] = lev;
sk->skilldesctext[sk->nskilldesc] = strdup(text); sk->skilldesctext[sk->nskilldesc] = strdup(text);
sk->skilldescmsg[sk->nskilldesc] = wantmsg; sk->skilldescmsg[sk->nskilldesc] = wantmsg;
@ -23276,7 +23300,7 @@ int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2,
mod2 += 5; mod2 += 5;
} }
// ignore the difficult, we just want the modified roll. // ignore the difficulty, we just want the modified roll.
real_skillcheck(lf1, ct1, 0, mod1, &roll1); real_skillcheck(lf1, ct1, 0, mod1, &roll1);
real_skillcheck(lf2, ct2, 0, mod2, &roll2); real_skillcheck(lf2, ct2, 0, mod2, &roll2);
@ -26493,6 +26517,10 @@ int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where)
cwflag = lfhasflagval(lf, F_CANWILL, aid, NA, NA, NULL); cwflag = lfhasflagval(lf, F_CANWILL, aid, NA, NA, NULL);
rv = abilityeffects(lf, aid, where, who, cwflag); rv = abilityeffects(lf, aid, where, who, cwflag);
// remember ability for rePeat command
if (isplayer(lf)) {
modflag(lf->flags, F_LASTSPELL, aid, NA, NA, NULL);
}
if (!rv) { if (!rv) {
flag_t *f; flag_t *f;

1
lf.h
View File

@ -170,6 +170,7 @@ int getarmournoise(lifeform_t *lf);
int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, enum BODYPART *hitbp, int *narms); int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, enum BODYPART *hitbp, int *narms);
int getattackspeed(lifeform_t *lf); int getattackspeed(lifeform_t *lf);
float getattackstamloss(object_t *wep); float getattackstamloss(object_t *wep);
float getattackstamlosslf(lifeform_t *lf, object_t *wep);
int getattpoints(lifeform_t *lf); int getattpoints(lifeform_t *lf);
int getattr(lifeform_t *lf, enum ATTRIB attr); int getattr(lifeform_t *lf, enum ATTRIB attr);
enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, /*@null@*/char *buf); enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, /*@null@*/char *buf);

127
map.c
View File

@ -5,6 +5,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "ai.h"
#include "astar.h" #include "astar.h"
#include "attack.h" #include "attack.h"
#include "defs.h" #include "defs.h"
@ -435,6 +436,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
} else if ((player->race->id == R_MAMMOAN) && (lf->race->id == R_ELEPHANT)) { } else if ((player->race->id == R_MAMMOAN) && (lf->race->id == R_ELEPHANT)) {
killflagsofid(lf->flags, F_HOSTILE); killflagsofid(lf->flags, F_HOSTILE);
} else { } else {
int mayoverride = B_TRUE;
// adjust hostility based on player's alignment // adjust hostility based on player's alignment
switch (getalignment(player)) { switch (getalignment(player)) {
case AL_GOOD: case AL_GOOD:
@ -442,18 +444,30 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
killflagsofid(lf->flags, F_HOSTILE); killflagsofid(lf->flags, F_HOSTILE);
} else if (getalignment(lf) == AL_EVIL) { } else if (getalignment(lf) == AL_EVIL) {
if (!lfhasflag(lf, F_HOSTILE)) addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); if (!lfhasflag(lf, F_HOSTILE)) addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
mayoverride = B_FALSE;
} }
break; break;
case AL_EVIL: case AL_EVIL:
if (getalignment(lf) == AL_GOOD) { if (getalignment(lf) == AL_GOOD) {
if (!lfhasflag(lf, F_HOSTILE)) { if (!lfhasflag(lf, F_HOSTILE)) addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); mayoverride = B_FALSE;
}
} }
break; break;
default: default:
break; break;
} }
if ( getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) > IQ_ANIMAL) {
int mod=0;
if (lf->race->id == player-> race->id) {
mod += 15;
}
if (skillcheckvs(player, SC_CHA, mod, lf, SC_CHA, 0)) {
killflagsofid(lf->flags, F_HOSTILE);
} else {
if (!lfhasflag(lf, F_HOSTILE)) addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
}
}
} }
} // end if hasequipped amu_victimisation } // end if hasequipped amu_victimisation
} }
@ -3031,6 +3045,62 @@ cell_t *get_closest_adjcell(cell_t *src, cell_t *dst) {
return NULL; return NULL;
} }
// find the closest known & walkable cell, with an adjacent unknown one
// note: only works when lf == player at the moment
cell_t *get_explore_target(lifeform_t *lf) {
int i;
int maxdist = MAXOF(MAX_MAPW, MAX_MAPH);
cell_t *src, **poss, *sel = NULL;
int x,y;
int nposs;
if (!lf) return NULL;
src = lf->cell;
for (i = 1;(i< maxdist && !sel); i++) {
int nok = 0;
nposs = 0;
poss = malloc(sizeof(cell_t *)*(i+2)*4);
//msg("player is %d,%d, dist %d.", lf->cell->x, lf->cell->y, i);
//msg("Box is %d,%d to %d, %d.", lf->cell->x - i, lf->cell->y - i,
// lf->cell->x + i, lf->cell->y + i);
for (y = lf->cell->y - i; y <= lf->cell->y + i; y++) {
for (x = lf->cell->x - i; x <= lf->cell->x + i; ) {
cell_t *newcell = NULL;
//msg("Checking %d,%d.",x, y);
newcell = getcellat(lf->cell->map,x,y);
if (newcell) {
nok++;
if (newcell->known != KG_UNKNOWN &&
cellwalkable(lf, newcell, NULL) &&
countadjcellsknown(newcell, B_FALSE, DT_COMPASS)) {
poss[nposs] = newcell;
nposs++;
}
}
// change x based on where we are in te square of
// possible cells
if (y == lf->cell->y - i || y== lf->cell->y + i) {
x++;
} else {
x += (i*2);
}
}
}
//msg("%d/%d possible cells at distance %d.",nposs, nok, i);
if (nposs) {
sel = poss[rnd(0,nposs-1)];
}
free(poss);
if (nok == 0) {
// no valid cells
break;
}
}
return sel;
}
int getdoorlockdiff(int depth) { int getdoorlockdiff(int depth) {
return 70 + (depth*3); return 70 + (depth*3);
} }
@ -3443,6 +3513,31 @@ int countadjcellswithflag(cell_t *cell, enum FLAG fid, int dirtype) {
return count; return count;
} }
int countadjcellsknown(cell_t *cell, int wantknown, int dirtype) {
int d;
int count = 0;
int start,end;
cell_t *newcell;
if (dirtype == DT_ORTH) {
start = D_N;
end = D_W;
} else { // ie. DT_COMPASS
start = DC_N;
end = DC_NW;
}
for (d = start; d <= end; d++) {
newcell = getcellindir(cell, d);
if (newcell) {
if (wantknown && (newcell->known != KG_UNKNOWN)) {
count++;
} else if (!wantknown && (newcell->known == KG_UNKNOWN)) {
count++;
}
}
}
return count;
}
int countadjcellsoftype(cell_t *cell, enum CELLTYPE id, int dirtype) { int countadjcellsoftype(cell_t *cell, enum CELLTYPE id, int dirtype) {
int d; int d;
int count = 0; int count = 0;
@ -4717,14 +4812,21 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// did we come from a previous map in the same region?
if (parentmap && (exitdir != D_NONE)) { if (parentmap && (exitdir != D_NONE)) {
if ((parentmap->region->id == map->region->id) || if (parentmap->region->id == map->region->id) {
(map->region->rtype->majorbranch)) { // we came from a previous map in the same region
if (db) dblog(" linking to parentmap %s in dir %s", parentmap->name, getdirname(diropposite(exitdir))); if (db) dblog(" linking to same region parentmap %s in dir %s", parentmap->name, getdirname(diropposite(exitdir)));
// ONLY change parent map's nextmap if it's
// in the same region.
parentmap->nextmap[exitdir] = map->id; parentmap->nextmap[exitdir] = map->id;
assert(exitdir >= 0);
map->nextmap[diropposite(exitdir)] = parentmap->id; map->nextmap[diropposite(exitdir)] = parentmap->id;
} else if (map->region->rtype->majorbranch) {
// we just arrived at the first map of a new region
if (db) dblog(" linking to diff region parentmap %s in dir %s", parentmap->name, getdirname(diropposite(exitdir)));
map->nextmap[diropposite(exitdir)] = parentmap->id;
// don't update parent map's nextmap[] since we
// want it to go to maps of the parent's
// region.
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
@ -7943,6 +8045,15 @@ void forgetcells(map_t *map, int amt) {
} }
} }
cell_t *getcellindirdist(cell_t *src, int dir, int dist) {
cell_t *c = src;
int i;
for (i = 0; (i < dist && c); i++) {
c = getcellindir(c,dir);
}
return c;
}
cell_t *getcellindir(cell_t *cell, int dir) { cell_t *getcellindir(cell_t *cell, int dir) {
cell_t *newcell; cell_t *newcell;
int newx,newy; int newx,newy;

3
map.h
View File

@ -72,6 +72,7 @@ object_t *gettopobject(cell_t *where, int forglyph);
//void calclight(map_t *map); //void calclight(map_t *map);
int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int *by, int force, int stayclose); int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int *by, int force, int stayclose);
int compassdir(int orthdir); int compassdir(int orthdir);
int countadjcellsknown(cell_t *cell, int wantknown, int dirtype);
int countadjcellsoftype(cell_t *cell, enum CELLTYPE id, int dirtype); int countadjcellsoftype(cell_t *cell, enum CELLTYPE id, int dirtype);
int countadjrooms(cell_t *cell, int dirtype); int countadjrooms(cell_t *cell, int dirtype);
int countadjcellswithflag(cell_t *cell, enum FLAG fid, int dirtype); int countadjcellswithflag(cell_t *cell, enum FLAG fid, int dirtype);
@ -141,8 +142,10 @@ room_t *findroom(map_t *m, int roomid);
map_t *findsurfaceexitmap(map_t *m); map_t *findsurfaceexitmap(map_t *m);
void forgetcells(map_t *map, int amt); void forgetcells(map_t *map, int amt);
cell_t *getcellindir(cell_t *cell, int dir); cell_t *getcellindir(cell_t *cell, int dir);
cell_t *getcellindirdist(cell_t *src, int dir, int dist);
enum TEMPERATURE getcelltemp(cell_t *c, int *actualtemp); enum TEMPERATURE getcelltemp(cell_t *c, int *actualtemp);
vault_t *getcellvault(cell_t *c); vault_t *getcellvault(cell_t *c);
cell_t *get_explore_target(lifeform_t *lf);
cell_t *getclosestroomcell(lifeform_t *lf, int roomid); cell_t *getclosestroomcell(lifeform_t *lf, int roomid);
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved); int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
int getobchance(int habitat); int getobchance(int habitat);

12
nexus.c
View File

@ -1145,7 +1145,9 @@ void donextturn(map_t *map) {
// pathfinding? // pathfinding?
if (donormalmove && isplayer(who)) { if (donormalmove && isplayer(who)) {
if (lfhasflag(who, F_PATHFINDING)) { flag_t *pff;
pff = lfhasflag(who, F_PATHFINDING);
if (pff) {
cell_t *c; cell_t *c;
// follow..... // follow.....
c = ai_getnextcellinpath(who); c = ai_getnextcellinpath(who);
@ -1175,8 +1177,16 @@ void donextturn(map_t *map) {
} }
} }
} else { } else {
int keepgoing = B_FALSE;
msg("Arrived at destination."); msg("Arrived at destination.");
if (streq(pff->text, "z")) {
keepgoing = B_TRUE;
}
stoppathfinding(who); stoppathfinding(who);
if (keepgoing) {
startexplore(B_FALSE);
}
} }
} }
} }

View File

@ -2273,9 +2273,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
switch (wantom[n]->id) { switch (wantom[n]->id) {
case OM_FLAMING: // flaming weapons are immune to fire case OM_FLAMING: // flaming weapons are immune to fire
if (o->type->obclass->id == OC_WEAPON) { if (o->type->obclass->id == OC_WEAPON) {
if (!isimmuneto(o->flags, DT_FIRE, B_FALSE)) { makefireproof(o);
addflag(o->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
}
} }
break; break;
case OM_FROZEN: case OM_FROZEN:
@ -9270,6 +9268,13 @@ int makedullermaybe(object_t *o, int howmuch) {
return B_FALSE; return B_FALSE;
} }
flag_t *makefireproof(object_t *o) {
if (!o) return NULL;
if (isimmuneto(o->flags, DT_FIRE, B_FALSE)) return NULL;
return addflag(o->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
}
void makeunequipped(lifeform_t *lf, object_t *o) { void makeunequipped(lifeform_t *lf, object_t *o) {
// remove the equipped flag // remove the equipped flag
killflagsofid(o->flags, F_EQUIPPED); killflagsofid(o->flags, F_EQUIPPED);

View File

@ -265,6 +265,7 @@ lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level);
void makecool(object_t *o, int howmuch, int howlong); void makecool(object_t *o, int howmuch, int howlong);
int makeduller(object_t *o, int howmuch); int makeduller(object_t *o, int howmuch);
int makedullermaybe(object_t *o, int howmuch); int makedullermaybe(object_t *o, int howmuch);
flag_t *makefireproof(object_t *o);
void makeunequipped(lifeform_t *lf, object_t *o); void makeunequipped(lifeform_t *lf, object_t *o);
void makehot(object_t *o, int howmuch, int howlong); void makehot(object_t *o, int howmuch, int howlong);
void makeknown(enum OBTYPE otid); void makeknown(enum OBTYPE otid);

8
text.c
View File

@ -2373,7 +2373,9 @@ char *makeplural(char **text) {
len = strlen(*text); len = strlen(*text);
assert(len > 0); assert(len > 0);
newtext = strdup(*text); // make copy //newtext = strdup(*text); // make copy
// make copy with trailing space
asprintf(&newtext, "%s ", *text);
for (pl = firstplural ; pl ; pl = pl->next) { for (pl = firstplural ; pl ; pl = pl->next) {
strrep(&newtext, pl->singular, pl->plural, &rv); strrep(&newtext, pl->singular, pl->plural, &rv);
@ -2382,6 +2384,10 @@ char *makeplural(char **text) {
break; break;
} }
} }
// now remove trailing space
if ( newtext[strlen(newtext)-1] == ' ') {
newtext[strlen(newtext)-1] = '\0';
}
if (!done) { if (!done) {
// default // default