nexus/text.c

2031 lines
43 KiB
C

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "attack.h"
#include "defs.h"
#include "flag.h"
#include "lf.h"
#include "map.h"
#include "move.h"
#include "nexus.h"
#include "objects.h"
#include "text.h"
extern long curtime;
extern lifeform_t *player;
extern enum GAMEMODE gamemode;
int needan(char *text) {
if (isvowel(tolower(text[0]))) {
return B_TRUE;
}
return B_FALSE;
}
char *capitalise(char *text) {
if (strlen(text)) {
char *p;
p = text;
while (*p == '^') {
p++; // go past the ^
if (!(*p)) return text; // do nothing
p++; // go past the colour char
if (!(*p)) return text; // do nothing
}
*p = toupper(*p);
}
return text;
}
// capitalise all words
char *capitaliseall(char *text) {
if (strlen(text) > 0) {
char *p;
for (p = text ; *p; p++) {
if (p == text) { // first letter
*p = toupper(*p);
} else if (*(p-1) == ' ') { // first letter after a space
*p = toupper(*p);
}
}
}
return text;
}
enum COLOUR chartocol(char ch) {
switch (ch) {
case 'w': // warning
return C_YELLOW;
case 'W': // extra warning
return C_BOLDMAGENTA;
case 'b': // bad
return C_BROWN;
case 'B': // v.bad
return C_RED;
case 'T': // terrible
return C_ORANGE;
case 'g': // good
return C_GREEN;
case 'G': // v.good
return C_CYAN;
case 'E': // excllent
return C_BOLDCYAN;
case 'h': // 'hilite'
return C_WHITE;
case 'l': // 'bLue'
return C_BLUE;
case 'n': // normal
default:
break;
}
return C_GREY;
}
char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackername, char *victimname, char *victimbpname, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp, int idx, int backstab, int critical, int fatal, int isunarmed, char *retbuf) {
int usecrittext = B_FALSE;
char wepname[BUFLEN],buf[BUFLEN];
char locvictimname[BUFLEN];
enum HELPLESSTYPE helpless;
// default
strcpy(retbuf, "");
getobname(wep, wepname, 1);
// modify victimname if required
//if (helpless && !isbehind(lf, victim)) {
if (!isplayer(victim) && ishelplessvictim(victim, lf, &helpless)) {
char *vn;
// strip "the" from "the xxx"
vn = strdup(victimname);
vn = strrep(vn, "the ", "", NULL);
switch (helpless) {
case HL_CANTSEE:
sprintf(locvictimname, "the helpless %s", vn);
break;
case HL_FLEEING:
sprintf(locvictimname, "the fleeing %s", vn);
break;
default: break;
}
free(vn);
} else {
strcpy(locvictimname, victimname);
}
// initial hit...
if (idx == 0) {
if (critical && !fatal) usecrittext = B_TRUE;
if (isplayer(lf)) {
char extradambuf[BUFLEN];
char withwep[BUFLEN];
char *verb;
int needfree = B_FALSE;
int knownnodam = B_FALSE;
int col;
strcpy(extradambuf, "");
if (wep && !ismeleeweapon(wep)) {
snprintf(withwep, BUFLEN, " with %s", wepname);
} else {
strcpy(withwep, "");
}
strcpy(extradambuf, "");
if (dam == 0) {
if (!victim || getlorelevel(lf, victim->race->raceclass->id)) {
//strcpy(extradambuf, " but do no damage");
strcpy(extradambuf, " ineffectually");
knownnodam = B_TRUE;
}
} else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
snprintf(extradambuf, BUFLEN, " [%d dmg]",dam);
}
if (backstab && (idx == 0)) {
verb = strdup("backstab");
needfree = B_TRUE;
} else if (fatal) {
verb = getkillverb(victim, wep, damtype, dam, maxhp);
if (strstr(verb, "knock out") && !isplayer(victim)) knownnodam = B_TRUE;
} else {
if (!victim || // atacking an object
(getlorelevel(lf, victim->race->raceclass->id) >= PR_BEGINNER) || // know about the race
!ismeleedam(damtype)) { // non-physical damage
verb = getattackverb(lf, wep, damtype, dam, maxhp);
} else {
// always use verb for 10%
verb = getattackverb(lf, wep, damtype, pctof(10, maxhp), maxhp);
}
}
if (knownnodam) {
col = C_GREY;
} else if (fatal) {
col = C_GREEN;
} else {
col = C_BROWN; // normal hit
}
snprintf(retbuf, BUFLEN, "^%dYou %s%s %s%s%s%s", col,
usecrittext ? "critically " : "", verb,
usecrittext ? victimbpname : locvictimname, withwep,extradambuf,
(fatal || backstab) ? "!" : ".");
if (needfree) {
free(verb);
}
} else { // ie. the attacker is a monster
if (cansee(player, lf) || (victim && isplayer(victim))) {
char withwep[BUFLEN];
char attackverb[BUFLEN];
char nodamstr[BUFLEN];
int nodam = B_FALSE;
int col;
// capitalise first letter
strcpy(buf, attackername);
capitalise(buf);
if (wep && !isunarmed && (lf->race->id != R_DANCINGWEAPON) && cansee(player, lf)) {
snprintf(withwep, BUFLEN, " with %s", wepname);
} else {
strcpy(withwep, "");
}
strcpy(attackverb, getattackverb(lf, wep, damtype,dam,maxhp));
if ((dam == 0) && (damtype != DT_TOUCH)) {
nodam = B_TRUE;
strcpy(nodamstr, " ineffectually");
} else {
strcpy(nodamstr, "");
}
if (victim && isplayer(victim) && !nodam) {
col = C_YELLOW;
} else {
col = C_GREY;
}
snprintf(retbuf, BUFLEN, "^%d%s %s%s%s %s%s%s.", col, buf,
usecrittext ? "critically " : "", attackverb,
needses(attackverb) ? "es" : "s",
usecrittext ? victimbpname : locvictimname,withwep, nodamstr);
}
}
} else { // follow-up weapon damage (ie from a flaming sword etc)
if (victim && cansee(player, victim)) {
if (dam == 0) { // ineffectual
switch (damtype) {
case DT_COLD:
snprintf(retbuf, BUFLEN, "^n%s %s cold.", locvictimname, isplayer(victim) ? "don't feel" : "doesn't look");
break;
case DT_HEAT:
case DT_FIRE:
snprintf(retbuf, BUFLEN, "^n%s %s hot.", locvictimname, isplayer(victim) ? "don't feel" : "doesn't look");
break;
case DT_MAGIC:
strcpy(retbuf, "");
break;
default:
snprintf(retbuf, BUFLEN, "^n%s shrug%s off the effects.", locvictimname, isplayer(victim) ? "" : "s");
break;
}
} else if (fatal) { // fatal
switch (damtype) {
case DT_COLD:
snprintf(retbuf, BUFLEN, "^%c%s %s chilled to the bone!", getlfcol(victim, CC_BAD), locvictimname, is(victim));
break;
case DT_HEAT:
case DT_FIRE:
snprintf(retbuf, BUFLEN, "^%c%s %s incinerated!", getlfcol(victim, CC_BAD), locvictimname, is(victim));
break;
case DT_MAGIC:
snprintf(retbuf, BUFLEN, "^%c%s %s blasted with magic!", getlfcol(victim, CC_BAD), locvictimname, is(victim));
break;
default:
snprintf(retbuf, BUFLEN, "^%c%s %s killed!", getlfcol(victim, CC_BAD), locvictimname, is(victim));
break;
}
} else { // normal
switch (damtype) {
case DT_COLD:
snprintf(retbuf, BUFLEN, "^n%s %s chilled!", locvictimname, is(victim));
break;
case DT_HEAT:
case DT_FIRE:
snprintf(retbuf, BUFLEN, "^n%s %s burned!", locvictimname, is(victim));
break;
case DT_MAGIC:
snprintf(retbuf, BUFLEN, "^nMagical energy sears %s!", locvictimname);
break;
default:
snprintf(retbuf, BUFLEN, "^n%s %s hurt!", locvictimname, is(victim));
break;
}
}
}
}
capitalise(retbuf);
return retbuf;
}
char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf) {
int localmin, localmax;
if (ndice == NA) ndice = 0;
if (nsides == NA) nsides = 0;
if (bonus == NA) bonus = 0;
// ie. rolled a 1 on all dice
localmin = (ndice * 1) + bonus;
// ie. rolled max on all dice
localmax = (ndice * nsides) + bonus;
if (min) {
*min = localmin;
}
if (max) {
*max = localmax;
}
if (dicebuf) {
if ((ndice == 0) || (nsides == 0)) {
snprintf(dicebuf, BUFLEN, "%d", bonus);
} else {
if (bonus) {
snprintf(dicebuf, BUFLEN, "%dd%d%c%d", ndice, nsides,
(bonus > 0) ? '+' : '-',
abs(bonus));
} else {
snprintf(dicebuf, BUFLEN, "%dd%d", ndice, nsides);
}
}
}
if (minmaxbuf) {
if (localmin == localmax) {
snprintf(minmaxbuf, BUFLEN, "%d", localmin);
} else {
snprintf(minmaxbuf, BUFLEN, "%d-%d", localmin, localmax);
}
}
return dicebuf;
}
int flip(int ch) {
switch (ch) {
case 'a': return 0x0250;
case 'b': return 'q';
case 'c': return 0x0254;
case 'd': return 'p';
case 'e': return 0x01dd;
case 'f': return 0x025f;
case 'g': return 0x0183;
case 'h': return 0x0265;
case 'i': return 0x0131;
case 'j': return 0x027e;
case 'k': return 0x029e;
case 'l': return 0x0283;
case 'm': return 0x026f;
case 'n': return 'u';
case 'r': return 0x0279;
case 't': return 0x0287;
case 'v': return 0x028c;
case 'w': return 0x028d;
case 'y': return 0x028e;
case '.': return 0x02d9;
case '[': return ']';
case '(': return ')';
case '{': return '}';
case '?': return 0x00bf;
case '!': return 0x00a1;
case '<': return '>';
case '_': return 0x203e;
}
return ch;
}
// ie. "it has xxx accuracy"
char *getaccuracyname(int accpct) {
if (accpct >= 200) {
return "incredible";
} else if (accpct >= 150) {
return "excellent";
} else if (accpct >= 120) {
return "great";
} else if (accpct >= 100) {
return "good";
} else if (accpct >= 80) {
return "average";
} else if (accpct >= 70) {
return "mediocre";
} else if (accpct >= 50) {
return "poor";
} else if (accpct >= 30) {
return "very poor";
} else if (accpct >= 20) {
return "extremely poor";
} else {
return "a complete lack of";
}
}
int getaccuracymodnum(int accpctmod) {
return accpctmod / 5;
}
int getaccuracynum(int accpct) {
int num;
num = (accpct - 100) / 5; //
return num;
}
// returns a const char *
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
//float pct;
enum LFSIZE ownersize = SZ_HUMAN;
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0;
if (lf) {
ownersize = getlfsize(lf);
}
//pct = (int)(((float) dam / (float) maxhp) * 100.0);
// base verb on amount of damage, not percentage of target.
// reasoning: just because a monster has lots of hp, doesn't mean
// you can only "scratch" it rather than "slice" it.
//pct = (int)(((float) dam / 50.0) * 100.0);
if (wep) {
int i;
flag_t *f;
getflags(wep->flags, retflag, &nretflags, F_ATTACKVERB, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if ((f->val[0] == NA) && (f->val[1] == NA)) {
return f->text;
} else if (f->val[0]) {
if (dam >= f->val[0]) {
if (f->val[1] == NA) {
return f->text;
} else if (dam <= f->val[1]) {
return f->text;
}
}
} else if (f->val[1]) {
if (dam <= f->val[1]) {
return f->text;
}
}
}
}
if (damtype == DT_ACID) {
return "burn";
} else if (damtype == DT_BASH) {
if (dam <= 2) {
return "whack";
} else if (dam <= 6) {
if (onein(2)) {
return "hit";
} else {
return "bash";
}
} else if (dam <= 12) {
return "pummel";
} else if (dam <= 18) {
if (onein(2)) {
return "slam";
} else {
return "clobber";
}
}
} else if (damtype == DT_BITE) {
if (lf && (ownersize <= SZ_SMALL)) {
if (dam <= 2) {
return "nip";
} else {
return "bite";
}
} else {
if (dam <= 4) {
return "gnaw";
} else if (dam <= 8) {
return "bite";
} else {
return "savage";
}
}
} else if (damtype == DT_CHOP) {
if (dam <= 4) {
return "chop";
} else if (dam <= 8) {
return "hack";
} else {
return "cleave";
}
} else if (damtype == DT_COLD) {
if (dam <= 4) {
return "chill";
} else {
return "freeze";
}
} else if (damtype == DT_CRUSH) {
return "crush";
} else if (damtype == DT_ELECTRIC) {
if (dam <= 2) {
return "zap";
} else if (dam <= 6) {
return "jolt";
} else if (dam <= 12) {
return "shock";
} else if (dam <= 18) {
return "electrify";
} else {
return "electrocute";
}
} else if ((damtype == DT_FIRE) || (damtype == DT_HEAT)) {
if (dam <= 2) {
return "scorch";
} else if (dam <= 6) {
return "singe";
} else if (dam <= 12) {
return "burn";
} else if (dam <= 18) {
return "scald";
} else {
return "incinerate";
}
} else if (damtype == DT_HOLY) {
switch (rnd(1,3)) {
case 1:
return "smite";
case 2:
return "cleanse";
case 3:
return "purify";
}
} else if (damtype == DT_MAGIC) {
if (dam <= 2) {
return "zap";
} else if (dam <= 6) {
return "sear";
} else {
return "blast";
}
} else if (damtype == DT_PIERCE) {
if (dam <= 2) {
return "poke";
} else if (dam <= 6) {
return "stab";
} else if (dam <= 12) {
return "pierce";
} else if (dam <= 18) {
return "spear";
} else {
return "deeply stab";
}
} else if (damtype == DT_POISONGAS) {
return "poison";
} else if (damtype == DT_PROJECTILE) {
return "hit";
} else if (damtype == DT_SLASH) {
if (dam <= 2) {
return "scratch";
} else if (dam <= 6) {
return "hit";
} else if (dam <= 12) {
return "slash";
} else {
return "slice";
}
} else if (damtype == DT_TOUCH) {
return "touch";
} else if (damtype == DT_WATER) {
// for when water-vulnerable things go into water
return "hurt";
} else if (damtype == DT_UNARMED) {
if (onein(2)) {
return "punch";
} else {
return "hit";
}
}
return "hit";
}
char *getattrabbrev(enum ATTRIB att) {
switch (att) {
case A_NONE:
return "??";
case A_CHA:
return "Ch";
case A_CON:
return "Ft";
case A_AGI:
return "Ag";
case A_IQ:
return "Iq";
case A_STR:
return "St";
case A_WIS:
return "Wi";
}
return "??";
}
char *getattrname(enum ATTRIB att) {
switch (att) {
case A_NONE:
return "?attrib_none?";
case A_CHA:
return "charisma";
case A_CON:
return "fitness";
case A_AGI:
return "agility";
case A_IQ:
return "intellect";
case A_STR:
return "strength";
case A_WIS:
return "wisdom";
}
return "?badattrib?";
}
char *getdirname(int dir) {
switch (dir) {
case D_N:
return "North";
case D_E:
return "East";
case D_S:
return "South";
case D_W:
return "West";
case D_UP:
return "up";
case D_DOWN:
return "down";
case D_UNKNOWN:
return "D_UNKNOWN";
case D_NONE:
return "D_NONE";
case DC_N:
return "North";
case DC_NE:
return "Northeast";
case DC_E:
return "East";
case DC_SE:
return "Southeast";
case DC_S:
return "South";
case DC_SW:
return "Southwest";
case DC_W:
return "West";
case DC_NW:
return "Northwest";
}
return "?errordir?";
}
char *getdirnameshort(int dir) {
switch (dir) {
case D_N:
return "N";
case D_E:
return "E";
case D_S:
return "S";
case D_W:
return "W";
case D_UP:
return "U";
case D_DOWN:
return "D";
case D_UNKNOWN:
return "?";
case D_NONE:
return "-";
case DC_N:
return "N";
case DC_NE:
return "NE";
case DC_E:
return "E";
case DC_SE:
return "SE";
case DC_S:
return "S";
case DC_SW:
return "SW";
case DC_W:
return "W";
case DC_NW:
return "NW";
}
return "?";
}
void getdisttext(cell_t *src, cell_t *dst,char *distbuf, char *distbufapprox, char *dirbuf) {
int dist;
int dir;
dist = getcelldist(src, dst);
dir = getdirtowards(src, dst, NULL, B_FALSE, DT_COMPASS);
if (dirbuf) {
strcpy(dirbuf, getdirname(dir));
dirbuf[0] = tolower(dirbuf[0]);
}
if (dist >= 20) { // 20+
if (distbuf) strcpy(distbuf, " very far away");
if (distbufapprox) strcpy(distbufapprox, " far away");
} else if (dist >= 10) { // 10 - 19
if (distbuf) strcpy(distbuf, " far away");
if (distbufapprox) strcpy(distbufapprox, " far away");
} else if (dist >= 5) { // 5 - 9
if (distbuf) strcpy(distbuf, " nearby");
if (distbufapprox) strcpy(distbufapprox, " nearby");
} else if (dist >= 2) { // 2 - 4
if (distbuf) strcpy(distbuf, " very nearby");
if (distbufapprox) strcpy(distbufapprox, " nearby");
} else { // 1
if (distbuf) strcpy(distbuf, " right beside you");
if (distbufapprox) strcpy(distbufapprox, " nearby");
}
}
char *getflagsourcetext(flag_t *f) {
switch (f->lifetime) {
case FROMSKILL: return " (skill perk)";
case FROMJOB: return " (job perk)";
case FROMOBEQUIP:
case FROMOBHOLD:
case FROMOBACTIVATE:
return " (conferred perk)";
case FROMGODGIFT:
return " (god gift)";
default: break;
}
return "";
}
int gethitconferlifetime(char *text, int *min, int *max) {
int howlong;
int localmin = -1,localmax = -1;
if (text) {
char loctext[BUFLEN];
char *word, *dummy;
strcpy(loctext,text);
word = strtok_r(loctext, "-", &dummy);
if (word) {
localmin = atoi(word);
word = strtok_r(NULL, "-", &dummy);
if (word) {
localmax = atoi(word);
howlong = rnd(localmin,localmax);
} else {
howlong = PERMENANT;
}
} else {
localmin = -1;
localmax = -1;
howlong = PERMENANT;
}
} else {
localmin = -1;
localmax = -1;
howlong = PERMENANT;
}
if (min) *min = localmin;
if (max) *max = localmax;
return howlong;
}
char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
float pct;
pct = (int)(((float) dam / (float) maxhp) * 100.0);
if (wep && hasflag(wep->flags, F_MERCIFUL)) {
return "knock out";
}
if (wep && wep->pile->owner && lfhasflag(wep->pile->owner, F_STRIKETOKO)) {
return "knock out";
}
if (victim->race->id == R_DANCINGWEAPON) {
return "defeat";
}
if (getraceclass(victim) == RC_PLANT) {
return "destroy";
}
if (wep) {
flag_t *f;
int i;
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0;
getflags(wep->flags, retflag, &nretflags, F_KILLVERB, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_KILLVERB) {
if ((f->val[0] == NA) && (f->val[1] == NA)) {
return f->text;
} else if (f->val[0]) {
if (pct >= f->val[0]) {
if (f->val[1] == NA) {
return f->text;
} else if (pct <= f->val[1]) {
return f->text;
}
}
} else if (f->val[1]) {
if (pct <= f->val[1]) {
return f->text;
}
}
}
}
}
if ((damtype == DT_BASH) && ismadeofice(victim)) {
return "shatter";
}
if (damtype == DT_CRUSH) {
return "crush";
}
if (damtype == DT_HOLY) {
return "smite";
}
if (pct >= 70) {
if (damtype == DT_PIERCE) return "impale";
if (damtype == DT_BASH) {
if (isunconscious(victim)) {
return "kill";
} else {
return "flatten";
}
}
if (damtype == DT_BITE) return "gore";
if (damtype == DT_SLASH) {
if (!hasbp(victim, BP_HEAD)) {
return "bisect";
} else {
if ((getlfsize(victim) >= SZ_MEDIUM) && onein(3)) {
return "behead";
} else {
return "bisect";
}
}
}
}
if (getraceclass(victim) == RC_UNDEAD) {
// can't "kill" the undead
return "destroy";
}
// never use 'kill' for bashing since you might just knock them out
if (damtype == DT_BASH) {
return "clobber";
}
return "kill";
}
char *getpoisondamverb(enum POISONTYPE ptype) {
switch (ptype) {
case P_FOOD:
case P_VENOM:
return "vomit";
case P_GAS:
case P_COLD:
return "cough";
default:
break;
}
return "";
}
char *getpoisondesc(enum POISONTYPE ptype) {
switch (ptype) {
case P_FOOD:
case P_VENOM:
case P_GAS:
case P_WEAKNESS:
return "Poisoned";
case P_COLD:
return "Sick";
default:
break;
}
return "Poisoned";
}
char *getpoisonname(enum POISONTYPE ptype) {
switch (ptype) {
case P_COLD:
return "hypothermia";
case P_FOOD:
return "food poisoning";
case P_GAS:
return "gas inhalation";
case P_VENOM:
return "venom poisoning";
case P_WEAKNESS:
return "weakening poison";
default:
break;
}
return "";
}
char *getpossessive(char *text) {
char lastchar;
// you -> your
if (!strcasecmp(text, "you")) {
return "r";
}
// xxxs -> xxxs'
lastchar = text[strlen(text)-1];
if (tolower(lastchar) == 's') {
return "'";
}
// default: 's
return "'s";
}
char *getdrunktext(flag_t *drunkflag) {
int bracket;
bracket = (drunkflag->lifetime / TM_DRUNKTIME) + 1;
if (bracket == 1) {
return "tipsy";
} else if (bracket == 2) {
return "drunk";
} else {
return "very drunk";
}
return "??drunk??";
}
char *getinjuredbpname(enum BODYPART bp) {
switch (bp) {
case BP_HEAD: return "head";
case BP_HANDS: return "arm";
case BP_LEGS: return "leg";
default: break;
}
return "body";
}
char *getinjuryname(enum DAMTYPE dt) {
switch (dt) {
case DT_BASH: return "bruised";
case DT_SLASH: return "bleeding";
default: break;
}
return "injured";
}
char *getinjurydesc(enum BODYPART where, enum DAMTYPE dt) {
if (dt == DT_SLASH) {
if (where == BP_LEGS) {
return " (moving causes damage)";
} else if (where == BP_HANDS) {
return " (attacking causes damage)";
} else if (where == BP_BODY) {
return " (take extra damage from melee hits)";
}
} else if (dt == DT_BASH) {
if (where == BP_LEGS) {
return " (penalty to movement speed)";
} else if (where == BP_HANDS) {
return " (penalty to attack accuracy)";
}
}
return "";
}
char *getobmodprefix(object_t *o, obmod_t *om) {
// masterwork/shoddy doors have names based on material.
if (isdoor(o, NULL)) {
// player perceptive enough to notice?
if (om->id == OM_MASTERWORK) {
if ((gamemode == GM_GAMESTARTED) && (getskill(player, SK_PERCEPTION) < PR_BEGINNER)) {
return NULL;
}
switch (o->material->id) {
case MT_STONE: return "reinforced ";
case MT_METAL: return "reinforced ";
default: return "sturdy ";
}
} else if (om->id == OM_SHODDY) {
if ((gamemode == GM_GAMESTARTED) && (getskill(player, SK_PERCEPTION) < PR_BEGINNER)) {
return NULL;
}
switch (o->material->id) {
case MT_STONE: return "crumbling ";
case MT_METAL: return "rusted ";
default: return "rotted ";
}
}
} else if (isweapon(o)) {
flag_t *f = NULL;
skill_t *sk;
sk = getobskill(o);
if (sk) {
if (om->id == OM_MASTERWORK) {
switch (sk->id) {
case SK_CLUBS:
case SK_STAVES:
return "reinforced ";
default: break;
}
} else if (om->id == OM_SHODDY) {
switch (sk->id) {
case SK_LONGBLADES:
case SK_SHORTBLADES:
case SK_AXES:
return "blunted ";
case SK_CLUBS:
return "cracked ";
case SK_POLEARMS:
return "notched ";
case SK_STAVES:
return "blunted ";
default: break;
}
}
}
if (f) return f->text;
} else if (isshield(o)) {
if (om->id == OM_MASTERWORK) {
switch (o->material->id) {
case MT_LEATHER:
return "studded ";
case MT_METAL:
case MT_WOOD:
case MT_DRAGONWOOD:
return "reinforced ";
default: break;
}
} else if (om->id == OM_SHODDY) {
switch (o->material->id) {
case MT_LEATHER:
case MT_RUBBER:
case MT_PAPER:
return "torn ";
case MT_CLOTH:
case MT_SILK:
return "frayed ";
case MT_GLASS:
case MT_STONE:
case MT_BONE:
return "chipped ";
case MT_METAL:
return "dented ";
case MT_WOOD:
case MT_DRAGONWOOD:
return "splintered ";
default: break;
}
}
} else if (isarmour(o)) {
if (om->id == OM_MASTERWORK) {
switch (o->material->id) {
case MT_LEATHER:
return "studded ";
case MT_CLOTH:
case MT_SILK:
return "tailored ";
default: break;
}
} else if (om->id == OM_SHODDY) {
switch (o->material->id) {
case MT_LEATHER:
case MT_RUBBER:
case MT_PAPER:
return "torn ";
case MT_CLOTH:
case MT_SILK:
return "frayed ";
case MT_GLASS:
case MT_STONE:
case MT_BONE:
return "chipped ";
case MT_METAL:
return "dented ";
case MT_WOOD:
case MT_DRAGONWOOD:
return "splintered ";
default: break;
}
}
}
return om->prefix;
}
char *getrarityname(enum RARITY rr) {
switch (rr) {
case RR_UNIQUE: return "Unique";
case RR_NEVER: return "Never";
case RR_VERYRARE: return "Very Rare";
case RR_RARE: return "Rare";
case RR_UNCOMMON: return "Uncommon";
case RR_COMMON: return "Common";
case RR_FREQUENT: return "Frequent";
case RR_NONE: return "None";
}
return "?unknownrarity?";
}
// pass in EITHER m or r, not both.
//
// if withlevel is TRUE, "m" should be passed.
char *getregionname(char *buf, map_t *m, region_t *r, int withlevel) {
if (!r) {
r = m->region;
}
if (withlevel && m) {
flag_t *f;
int x,y;
f = hasflag(m->flags, F_MAPCOORDS);
if (f) {
x = f->val[0];
y = f->val[1];
} else {
x = NA;
y = NA;
}
switch (r->rtype->id) {
case RG_CAVE:
snprintf(buf, BUFLEN, "goblin caves L%d", m->depth);
break;
case RG_WORLDMAP:
snprintf(buf, BUFLEN, "the surface(%d,%d)",x,y);
break;
case RG_MAINDUNGEON:
snprintf(buf, BUFLEN, "dungeon L%d", m->depth);
break;
case RG_HEAVEN:
snprintf(buf, BUFLEN, "the realm of gods");
break;
case RG_PIT:
snprintf(buf, BUFLEN, "a pit L%d", m->depth);
break;
case RG_SEWER:
snprintf(buf, BUFLEN, "a sewer L%d", m->depth);
break;
case RG_STOMACH:
snprintf(buf, BUFLEN, "a stomach");
break;
}
} else {
switch (r->rtype->id) {
case RG_CAVE:
strcpy(buf, "the goblin caves");
break;
case RG_WORLDMAP:
strcpy(buf, "the surface");
break;
case RG_MAINDUNGEON:
strcpy(buf, "the dungeon");
break;
case RG_HEAVEN:
snprintf(buf, BUFLEN, "the realm of gods");
break;
case RG_PIT:
snprintf(buf, BUFLEN, "a pit");
break;
case RG_SEWER:
snprintf(buf, BUFLEN, "a sewer");
break;
case RG_STOMACH:
snprintf(buf, BUFLEN, "a stomach");
break;
}
}
return buf;
}
char *getreldirname(int reldir) {
switch (reldir) {
case RD_FORWARDS:
return "forwards";
case RD_BACKWARDS:
return "backwards";
case RD_SIDEWAYS:
return "sideways";
default: break;
}
return "away";
}
char *getsizetext(enum LFSIZE sz) {
switch (sz) {
case SZ_MAX:
case SZ_ENORMOUS:
return "enormous";
case SZ_HUGE:
return "huge";
case SZ_LARGE:
return "large";
case SZ_HUMAN:
return "human-sized";
case SZ_MEDIUM:
return "medium";
case SZ_SMALL:
return "small";
case SZ_TINY:
return "tiny";
case SZ_MIN:
case SZ_MINI:
return "miniscule";
default:
return "unknown-sized";
}
return "unknown-sized";
}
char *gettimetext(char *retbuf) {
int hours,mins,secs;
splittime(&hours, &mins, &secs);
snprintf(retbuf, BUFLEN, "%02d:%02d:%02d",hours,mins,secs);
return retbuf;
}
char *gettimetextfuzzy(char *retbuf, int wantpm) {
int hours,mins,secs;
int pm = B_FALSE;
splittime(&hours, &mins, &secs);
if (hours > 12) {
hours -= 12;
pm = B_TRUE;
}
if (hours == 0) hours = 12;
if (mins == 0) {
snprintf(retbuf, BUFLEN, "exactly %d o'clock", hours);
} else if (mins <= 15) {
snprintf(retbuf, BUFLEN, "a little after %d o'clock", hours);
} else if (mins <= 25) {
snprintf(retbuf, BUFLEN, "nearly half past %d", hours);
} else if (mins <= 35) {
snprintf(retbuf, BUFLEN, "around half past %d", hours);
} else if (mins <= 45) {
snprintf(retbuf, BUFLEN, "coming up to %d o'clock", (hours == 12) ? 1 : (hours+1));
} else {
snprintf(retbuf, BUFLEN, "nearly %d o'clock", (hours == 12) ? 1 : (hours+1));
}
if (wantpm) {
strcat(retbuf, " in the ");
if (pm) {
strcat(retbuf, "afternoon");
} else {
strcat(retbuf, "morning");
}
}
return retbuf;
}
char *getwaterdepthname(enum DEPTH d) {
switch (d) {
case DP_NONE:
return "shallow";
case DP_TOE:
return "toe-deep";
case DP_ANKLE:
return "ankle-deep";
case DP_FEET:
return "foot-deep";
case DP_CALF:
return "calf-deep";
case DP_KNEE:
return "knee-deep";
case DP_THIGH:
return "thigh-deep";
case DP_WAIST:
return "waist-deep";
case DP_BELLY:
return "belly-deep";
case DP_CHEST:
return "chest-deep";
case DP_SHOULDERS:
return "shoulder-deep";
default:
return "very deep";
}
return "?unknowndepth?";
}
char *getweighttext(float weight, char *buf, int shortfmt) {
if (weight == 0) {
if (shortfmt) snprintf(buf, BUFLEN, "0kg");
else snprintf(buf, BUFLEN, "nothing");
} else if (weight >= 1) {
if ((int)weight == weight) { // ie. is weight an integer?
snprintf(buf, BUFLEN, "%0.0f%skg",weight, shortfmt ? "" : " ");
} else {
snprintf(buf, BUFLEN, "%0.1f%skg",weight, shortfmt ? "" : " ");
}
} else {
snprintf(buf, BUFLEN, "%0.0f%s", weight * 1000, shortfmt ? "g" : " grams");
}
return buf;
}
char *is(lifeform_t *lf) {
if (isplayer(lf)) return "are";
else return "is";
}
int isvowel (char c) {
switch (c) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return B_TRUE;
}
return B_FALSE;
}
// return text for player's F_GUNTARGET flag eg. "goblin [acc:50%]"
void makegunaimstring(lifeform_t *lf, int lfid, char *retbuf) {
char accbuf[BUFLEN];
char targname[BUFLEN];
flag_t *f;
lifeform_t *targ;
targ = findlf(lf->cell->map, lfid);
if (!targ) {
strcpy(retbuf, "");
return;
}
getlfname(targ, targname);
f = addflag(lf->flags, F_THROWING, B_TRUE, NA, NA, NULL);
makethrowaccstring(lf, targ->cell, f, accbuf);
killflagsofid(lf->flags, F_THROWING);
sprintf(retbuf, "%s%s", noprefix(targname), accbuf);
}
char *makekillertext(char *retbuf, char *killverb, char *lastdam, int wantextra) {
char *p, *dummy;
p = strtok_r(lastdam,"^", &dummy);
if (p) {
if (!strcmp(p, "you")) {
strcpy(retbuf, "Committed suicide.");
} else {
snprintf(retbuf, BUFLEN, "%s %s %s.",killverb,
streq(killverb, "Drowned") ? "in" : "by",
p);
}
if (wantextra) {
p = strtok_r(NULL, "^", &dummy);
while (p) {
strcat(retbuf, "\n(");
strcat(retbuf, p);
strcat(retbuf, ")");
p = strtok_r(NULL, "^", &dummy);
}
}
} else {
sprintf(retbuf, "%s by something unknown.", killverb);
}
return retbuf;
}
char *makelowercase(char *text) {
if (strlen(text) > 0) {
char *p;
for (p = text ; *p; p++) {
*p = tolower(*p);
}
}
return text;
}
// allocates and returns new string
char *makeplural(char *text) {
char lastlet;
char *newtext;
int rv;
newtext = strdup(text);
// scrolls
newtext = strrep(newtext, "bag ", "bags ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "berry ", "berries ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "block ", "blocks ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "can ", "cans ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "chunk ", "chunks ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "clove ", "cloves ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "flask ", "flasks ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "gem ", "gems ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "knife", "knives", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "leaf", "leaves", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "loaf ", "loaves ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "lump ", "lumps ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "piece ", "pieces ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "pile ", "piles ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "pinch ", "pinches ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "pool ", "pools ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "potion ", "potions ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "puddle ", "puddles ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "puff ", "puffs ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "ring ", "rings ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "ruby", "rubies", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "scroll ", "scrolls ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "splash ", "splashes ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "set ", "sets ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "sprig ", "sprigs ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "suit ", "suits ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "vial ", "vials ", &rv);
if (rv) return newtext;
//
newtext = strrep(newtext, "pair ", "pairs ", &rv);
// don't return
// default
lastlet = text[strlen(text)-1];
switch (lastlet) {
char *temptext;
case 'y': // change to 'ies'
temptext = strdup(text);
temptext[strlen(temptext)-1] = '\0';
asprintf(&newtext, "%sies",temptext);
free(temptext);
break;
case 's':
case 'o': // append "es"
asprintf(&newtext, "%ses",text);
break;
default: // append "s"
asprintf(&newtext, "%ss",text);
break;
}
return newtext;
}
// throwflag should be either a F_THROWING or a F_FIRING flag.
char *makethrowaccstring(lifeform_t *lf, cell_t *c, flag_t *throwflag, char *retbuf) {
object_t *o = NULL, *gun = NULL;
int acc = 0;
strcpy(retbuf, "");
if (strlen(throwflag->text)) {
// get the object being thrown
o = findobbyid(lf->pack, atol(throwflag->text));
} else { // ie. firing a gun
gun = getfirearm(lf);
if (!gun) return NULL;
o = getammo(gun);
}
if (!o) return NULL;
acc = getmissileaccuracy(lf, c, o, gun, lfhasflag(player, F_TKTHROW)) ;
if (lfhasflag(lf, F_EXTRAINFO)) {
sprintf(retbuf, "^%d [acc:%d%%]^n", getpctcol(acc,100), acc);
} else {
sprintf(retbuf, "^%d [acc:%c]^n", getpctcol(acc,100), getpctletter(acc,100));
}
return retbuf;
}
char *makeuppercase(char *text) {
if (strlen(text) > 0) {
char *p;
for (p = text ; *p; p++) {
*p = toupper(*p);
}
}
return text;
}
// return something like:
// "over the shoulders"
// or
// "on your body, over your eyes and on your legs"
char *makewearstring(lifeform_t *lf, object_t *o, int wantyour, char *posbuf) {
flag_t *retflag[MAXCANDIDATES];
char yourbuf[BUFLEN];
int nretflags = 0,i;
if (wantyour) {
if (!lf) {
strcpy(yourbuf, "the ");
} else if (isplayer(lf)) {
strcpy(yourbuf, "your ");
} else {
strcpy(yourbuf, "its ");
}
} else {
strcpy(yourbuf, "");
}
getflags(o->flags, retflag, &nretflags, F_EQUIPPED, F_NONE);
for (i = 0; i < nretflags; i++) {
char thisposbuf[BUFLEN];
makewearstringsingle(lf, retflag[i], yourbuf, thisposbuf);
if (i == 0) {
strcpy(posbuf, thisposbuf);
} else if (i == (nretflags - 1)) {
strcat(posbuf, " and ");
strcat(posbuf, thisposbuf);
} else {
strcat(posbuf, ", ");
strcat(posbuf, thisposbuf);
}
}
return posbuf;
}
// return something like:
// "on your body"
// OR
// "over the eyes"
char *makewearstringsingle(lifeform_t *lf, flag_t *f, char *yourbuf , char *posbuf) {
enum BODYPART bp;
bp = f->val[0];
sprintf(posbuf, "%s %s%s", getbodypartequipname(bp), yourbuf, getbodypartname(lf, bp));
return posbuf;
}
int needses(char *text) {
if (text[strlen(text)-1] == 's') {
return B_TRUE;
}
if (strlen(text) >= 2) {
if ((text[strlen(text)-2] == 'c') &&
(text[strlen(text)-1] == 'h')) {
return B_TRUE;
}
}
return B_FALSE;
}
char *noprefix(char *obname) {
char *p;
p = strchr(obname, ' ');
if (p) {
p++;
return p;
} else {
return obname;
}
}
char *numtotext(int num, char *buf) {
switch (num) {
case 1:
snprintf(buf, BUFLEN, "a");
break;
case 2:
snprintf(buf, BUFLEN, "two");
break;
case 3:
snprintf(buf, BUFLEN, "three");
break;
case 4:
snprintf(buf, BUFLEN, "four");
break;
case 5:
snprintf(buf, BUFLEN, "five");
break;
case 6:
snprintf(buf, BUFLEN, "six");
break;
case 7:
snprintf(buf, BUFLEN, "seven");
break;
case 8:
snprintf(buf, BUFLEN, "eight");
break;
case 9:
snprintf(buf, BUFLEN, "nine");
break;
case 10:
snprintf(buf, BUFLEN, "ten");
break;
default:
snprintf(buf, BUFLEN, "%d",num);
break;
}
return buf;
}
// returns posiiton AFTER end of copied text, or NULL on failure.
char *readuntil(char *retbuf, char *src, char delim) {
char *bp,*p;
bp = retbuf;
for (p=src; *p && (*p != delim); p++) {
*bp = *p;
bp++;
}
*bp = '\0'; // nul-terminate buffer
if (*p == delim) {
p++; // go past delimiter
}
return p;
}
// convert number to roman numerals
// only copes with 1-10
char *roman(int num) {
switch (num) {
case 1:
return "I";
case 2:
return "II";
case 3:
return "III";
case 4:
return "IV";
case 5:
return "V";
case 6:
return "VI";
case 7:
return "VII";
case 8:
return "VIII";
case 9:
return "IX";
case 10:
return "X";
}
return "";
}
int speedtokph(int speed) {
return speed * speed;
}
void splittime(int *hours, int *mins, int *secs) {
long left;
left = curtime;
*hours = left / 3600;
left -= (*hours * 3600);
*mins = left / 60;
left -= (*mins * 60);
*secs = left;
}
char *strrep(char *text, char *oldtok, char *newtok, int *rv) {
char *temp;
temp = strdup(" "); // ooooooo is this bad??
dostrrep(text, &temp, oldtok, newtok, rv);
// swap
text = realloc(text, strlen(temp)+1); // extra space for NUL
strcpy(text, temp);
free(temp);
return text;
}
// returns TRUE if any replacements made
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv) {
char *temp;
char *found = strstr(in, oldtok);
int idx;
if(!found) {
*out = realloc(*out, strlen(in) + 1); // oooooooo crashing in realloc
strcpy(*out, in);
if (rv) *rv = B_FALSE;
return *out;
}
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));
temp = malloc(idx+strlen(newtok)+1);
strncpy(temp,*out,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;
if (rv) *rv = B_TRUE;
return *out;
}
int streq(char *a, char *b) {
if (!a || !b) return B_FALSE;
return !strcmp(a,b);
}
char *strends(char *a, char *suffix) {
char *ep;
if (!a || !suffix) return NULL;
ep = strstr(a, suffix);
if (ep) {
if ((ep - a) + strlen(ep) == strlen(a)) {
return ep;
}
}
return NULL;
}
char *strstarts(char *a, char *prefix) {
if (!a || !prefix) return NULL;
if (strstr(a, prefix) == a) {
return a;
}
return NULL;
}
int strpixmatch(char *haystack, char *needle) {
int matched = B_FALSE;
char *hword, *nword, *hcont,*ncont;
if (strchr(needle, ' ') || strchr(haystack, ' ')) {
char lochaystack[BUFLEN], locneedle[BUFLEN];
strcpy(lochaystack, haystack);
strcpy(locneedle, needle);
// match word for word
nword = strtok_r(locneedle, " ", &ncont);
hword = strtok_r(lochaystack, " ", &hcont);
while (nword && hword) {
// all typed words must match
if (strcasestr(hword, nword)) {
matched = B_TRUE;
} else {
matched = B_FALSE;
break;
}
nword = strtok_r(NULL, " ", &ncont);
hword = strtok_r(NULL, " ", &hcont);
if (nword && !hword) {
matched = B_FALSE;
}
}
/*
if (!matched && !strchr(needle, ' ')) {
// now try matching typed word against second word in spellname
strcpy(lochaystack, haystack);
hword = strtok_r(lochaystack, " ", &hcont);
while (hword) {
if (strcasestr(hword, needle)) {
matched = B_TRUE;
break;
} else {
matched = B_FALSE;
}
hword = strtok_r(NULL, " ", &hcont);
if (!hword) {
matched = B_FALSE;
}
}
}
*/
} else {
if (strcasestr(haystack, needle)) {
matched = B_TRUE;
}
}
return matched;
}
int texttodice(char *text, int *ndice, int *nsides, int *bonus) {
char *dummy;
char *localtext;
char *p,*plusloc;
localtext = strdup(text);
// number of dice
p = strtok_r(localtext, "d", &dummy);
if (!p) {
return B_TRUE;
}
if (ndice) {
*ndice = atoi(p);
}
// sides on each die
p = strtok_r(NULL, "d", &dummy);
if (!p) {
return B_TRUE;
}
// strip out bonus
plusloc = strchr(p, '+');
if (plusloc) *plusloc = '\0';
plusloc = strchr(p, '-');
if (plusloc) *plusloc = '\0';
if (nsides) {
*nsides = atoi(p);
}
free(localtext);
localtext = strdup(text);
// bonus/plus
if (bonus) {
p = strchr(localtext, '+');
if (p) {
*bonus = atoi(p+1);
} else {
p = strchr(localtext, '-');
if (p) {
*bonus = -(atoi(p+1));
} else {
*bonus = 0;
}
}
}
free(localtext);
return B_FALSE;
}
/*
void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range, char *racestr) {
char *p;
int n;
char *argname[] = {
"pw:",
"dam:",
"needgrab:",
"range:",
"race:",
NULL,
};
void *argval[] = {
power,
damstr,
needgrab,
range,
racestr,
NULL,
};
char argtype[] = {
'i',
's',
'b',
'i',
's',
'\0',
};
// defaults
if (power) *power = 0;
if (damstr) strcpy(damstr, "");
if (needgrab) *needgrab = B_FALSE;
if (range) *range = 0;
if (racestr) strcpy(racestr, "");
if (!strlen(text)) {
return;
}
// for each arg
for (n = 0; argname[n]; n++) {
// search for it in text...
for (p = text ; *p ; p++) {
if (!strncmp(p, argname[n], strlen(argname[n])) ) {
char localval[BUFLEN];
char *valfull;
strcpy(localval, p + strlen(argname[n]));
valfull = strtok(localval, ";");
if (valfull) {
if (argval[n]) {
if (argtype[n] == 'i') {
*((int *)argval[n]) = atoi(valfull);
} else if (argtype[n] == 'b') {
*((int *)argval[n]) = atoi(valfull) ? B_TRUE : B_FALSE;
} else if (argtype[n] == 's') {
strcpy((char *)argval[n], valfull);
}
}
break;
}
}
}
}
}
*/
void texttospellopts(char *text, ... ) {
char *p;
va_list args;
char *validname[] = {
"pw:",
"dam:",
"needgrab:",
"range:",
"race:",
"stamcost:",
NULL,
};
int argdefault[] = {
0,
-1, // string
B_FALSE,
0,
-1, // string
0,
-99, // last
};
char argtype[] = {
'i',
's',
'b',
'i',
's',
'i',
'\0',
};
char *wantname = NULL;
void *writeto = NULL;
va_start(args, text);
wantname = va_arg(args, char *);
if (wantname) writeto = va_arg(args, void *);
while (wantname) { // process this one
int foundidx = -1,i;
// validate 'wantname' - must match one of 'validname[]'
for (i = 0; validname[i]; i++) {
if (streq(validname[i], wantname)) {
foundidx = i;
break;
}
}
assert(foundidx != -1);
// blank our dest buffer
if (argtype[foundidx] == 'i') {
*((int *)writeto) = argdefault[foundidx];
} else if (argtype[foundidx] == 'b') {
*((int *)writeto) = argdefault[foundidx];
} else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, "");
}
// look for 'wantname' within 'text'
for (p = text ; *p ; p++) {
if (!strncmp(p, wantname, strlen(wantname)) ) { // found it!
char localval[BUFLEN];
char *valfull;
// extract value from text
// p will point to "pw:xxx;"
strcpy(localval, p + strlen(wantname)); // localval is "xxx;"
valfull = strtok(localval, ";"); // valfull is "xxx"
if (valfull) {
// if it's there, write the value into 'writeto'
if (argtype[foundidx] == 'i') {
*((int *)writeto) = atoi(valfull);
} else if (argtype[foundidx] == 'b') {
*((int *)writeto) = atoi(valfull) ? B_TRUE : B_FALSE;
} else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, valfull);
}
}
}
}
// get next one
wantname = va_arg(args, char *);
if (wantname) writeto = va_arg(args, void *);
}
va_end(args);
}
char *you(lifeform_t *lf) {
if (isplayer(lf)) {
return "You";
}
return "It";
}
char *you_l(lifeform_t *lf) {
if (isplayer(lf)) {
return "you";
}
return "it";
}
char *your(lifeform_t *lf) {
if (isplayer(lf)) {
return "Your";
}
return "Its";
}
char *your_l(lifeform_t *lf) {
if (isplayer(lf)) {
return "your";
}
return "its";
}