Tweak breakob code again to cope with various numbers of broken object types, not just 2.

Replace all (struct)->weight with (struct)->mass.
This commit is contained in:
Rob Pearce 2016-06-09 11:24:24 +10:00
parent 74b0e9841f
commit 0f90f3b76f
6 changed files with 107 additions and 87 deletions

4
data.c
View File

@ -3186,7 +3186,7 @@ void initobjects(void) {
addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some powder");
addflag(lastot->flags, F_NUMCONVERT, 100, OT_ASHLARGE, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_DUSTCLOUD, VT_OB, NA, NULL);
addot(OT_ASHLARGE, "large pile of ash", "A large pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY);
addot(OT_ASHLARGE, "large pile of ash", "A large pile of ash.", MT_STONE, 2, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_DARKGREY, ',', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_RARE, "");
@ -3197,7 +3197,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NUMCONVERT, 100, OT_ASHHUGE, NA, NULL);
addflag(lastot->flags, F_SHRINKSTO, OT_ASH, VT_OB, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_DUSTCLOUD, VT_OB, NA, NULL);
addot(OT_ASHHUGE, "huge pile of ash", "A huge pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY);
addot(OT_ASHHUGE, "huge pile of ash", "A huge pile of ash.", MT_STONE, 20, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_DARKGREY, ',', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_VERYRARE, "");

13
defs.h
View File

@ -2720,6 +2720,8 @@ enum OBTYPE {
#define MAXBUILDINGTYPES (11)
#define MAXBREAKOBTYPES (5)
//#define BP_NONE (-1)
enum BODYPART {
@ -3038,8 +3040,9 @@ enum FLAG {
// v1 = dirtype for radius
F_BREAKOB, // if killed by damtype v0, change to
// object 'text'.
// IMPORTANT: can only have up to 2 of these per
// damage type.
// IMPORTANT:
// - breakobs with high mass MUST be listed first.
// - can only have up to MAXBREAKOBTYPES of these per damage type.
F_NOBLESS, // can't be blessed or cursed
F_NOQUALITY, // can't be masterwork / shoddy
F_NOSTEAL, // this object can't be stolen, blown away, etc.
@ -5176,7 +5179,7 @@ typedef struct race_s {
char *name;
char *desc;
struct glyph_s glyph;
float weight;
float mass;
struct flagpile_s *flags;
struct bodypart_s bodypart[MAXBODYPARTS];
int nbodyparts;
@ -5416,7 +5419,7 @@ typedef struct objecttype_s {
struct objectclass_s *obclass;
material_t *material;
enum LFSIZE size;
float weight; // in kilograms
float mass; // in kilograms
struct flagpile_s *flags;
struct objecttype_s *next, *prev;
} objecttype_t;
@ -5428,7 +5431,7 @@ typedef struct object_s {
// these variables are initially
// inherited from objecttype:
material_t *material;
float weight; // in kilograms
float mass; // in kilograms
// flags
// these variables are NOT inherited
char *inscription;

4
lf.c
View File

@ -10820,7 +10820,7 @@ enum LFSIZE getlfsize(lifeform_t *lf) {
float getlfweight(lifeform_t *lf, int withobs) {
float weight = 0;
weight = lf->race->weight;
weight = lf->race->mass;
if (lfhasflag(lf, F_OBESE)) {
weight *= 2;
@ -15841,7 +15841,7 @@ race_t *addrace(enum RACE id, char *name, float weight, int glyph, int glyphcolo
assert(a->material);
a->name = strdup(name);
a->desc = strdup(desc);
a->weight = weight;
a->mass = weight;
a->glyph.ch = glyph;
a->glyph.colour = glyphcolour;
a->known = B_FALSE;

167
objects.c
View File

@ -1543,7 +1543,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
// inherit props and flags from objecttype
o->material = ot->material;
assert(o->material);
o->weight = ot->weight;
o->mass = ot->mass;
copyflags(o->flags, ot->flags, NA);
// don't want certain objecttype only flags...
@ -2078,7 +2078,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
corpserace = getrandomcorpserace(NULL, wantarmsize);
}
o->weight = corpserace->weight;
o->mass = corpserace->mass;
o->material = corpserace->material;
// remember the race type
@ -2149,7 +2149,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
ratio = o->material->weightrating / corpserace->material->weightrating;
o->weight = corpserace->weight * ratio;
o->mass = corpserace->mass * ratio;
// remember the race type
addflag(o->flags, F_CORPSEOF, corpserace->id, 1, NA, NULL);
@ -2182,8 +2182,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
assert(corpserace);
o->weight = pctof(8, corpserace->weight);
limitf(&o->weight, 0.01, NA);
o->mass = pctof(8, corpserace->mass);
limitf(&o->mass, 0.01, NA);
o->material = corpserace->material;
// remember the race type
@ -2212,7 +2212,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
if (corpserace->id != corpserace->baseid) corpserace = findrace(corpserace->baseid);
}
o->weight = corpserace->weight / 2;
o->mass = corpserace->mass / 2;
// remember the race type
addflag(o->flags, F_CORPSEOF, corpserace->id, 1, NA, NULL);
@ -2672,7 +2672,7 @@ objecttype_t *addot(enum OBTYPE id, char *name, char *description, int material,
a->name = strdup(name);
a->desc = strdup(description);
a->material = findmaterial(material);
a->weight = weight;
a->mass = weight;
a->size = size;
a->obclass = findoc(obclassid);
a->flags = addflagpile(NULL, NULL);
@ -3520,7 +3520,7 @@ int confirmknowntraps(object_t *o) {
void copyobprops(object_t *dst, object_t *src) {
dst->material = src->material;
dst->weight = src->weight;
dst->mass = src->mass;
if (src->inscription) {
dst->inscription = strdup(src->inscription);
}
@ -4564,16 +4564,23 @@ object_t *getbestcontainer(obpile_t *op) {
return poss2[rnd(0,nposs2-1)];
}
// will ALLOCATE breakobs. remember to free afterwards
//
// returns TRUE if an break obejct was found.
int getbreakob(object_t *o, char *bigobname, char *smallobname) {
int getbreakob(object_t *o, char **breakobname, int *nbreakobs) {
enum MATERIAL mid;
enum DAMTYPE dt;
enum OBTYPE bigoid = OT_NONE,smalloid = OT_NONE;
objecttype_t *big = NULL,*small = NULL;
enum OBTYPE breakoid[MAXBREAKOBTYPES];
objecttype_t *breakob[MAXBREAKOBTYPES];
char adj[BUFLEN][MAXBREAKOBTYPES];
int nobs[MAXBREAKOBTYPES];
//enum OBTYPE bigoid = OT_NONE,smalloid = OT_NONE;
//objecttype_t *big = NULL,*small = NULL;
flag_t *f;
int nsmall = 0,nbig = 0;
double weight;
char bigadj[BUFLEN],smalladj[BUFLEN];
double totmass;
//char bigadj[BUFLEN],smalladj[BUFLEN];
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0,i;
int found = B_FALSE;
@ -4581,46 +4588,46 @@ int getbreakob(object_t *o, char *bigobname, char *smallobname) {
mid = o->material->id;
dt = oblastdamtype(o);
// name to return.
strcpy(bigobname, "");
strcpy(smallobname, "");
// flag overrides code below
found = 0;
getflags(o->flags, retflag, &nretflags, F_BREAKOB, F_NONE);
*nbreakobs = 0;
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f && (f->val[0] == dt)) {
if (found == 0) {
strcpy(bigobname, f->text);
} else if (found == 1) {
strcpy(smallobname, f->text);
} else {
breakobname[*nbreakobs] = strdup(f->text);
strcpy(adj[*nbreakobs], "");
if (++(*nbreakobs) >= MAXBREAKOBTYPES) {
msg("ERROR - too many F_BREAKOB flags in %s",o->type->name);
dblog("ERROR - too many F_BREAKOB flags in %s",o->type->name);
raise(SIGINT);
}
found++;
}
}
if (found) {
if (*nbreakobs) {
// flags have told us what the name is
return B_TRUE;
}
// determine breakobs based on materials
// adjectives
strcpy(bigadj, "");
strcpy(smalladj, "");
switch (mid) {
case MT_WOOD:
if (ismeleedam(dt) || (dt == DT_EXPLOSIVE)) {
bigoid = OT_WOODPLANK;
smalloid = OT_WOODSHARD;
breakoid[0] = OT_WOODPLANK;
breakoid[1] = OT_WOODSHARD;
(*nbreakobs) = 2;
} else {
switch (dt) {
case DT_FIRE:
case DT_HEAT:
case DT_ACID:
bigoid = OT_ASH;
smalloid = OT_ASH;
breakoid[0] = OT_ASHHUGE;
breakoid[1] = OT_ASHLARGE;
breakoid[2] = OT_ASH;
(*nbreakobs) = 3;
break;
default: break;
}
@ -4628,16 +4635,18 @@ int getbreakob(object_t *o, char *bigobname, char *smallobname) {
break;
case MT_GLASS:
if (ismeleedam(dt) || (dt == DT_EXPLOSIVE)) {
bigoid = OT_BROKENGLASS;
smalloid = OT_BROKENGLASS;
breakoid[0] = OT_WOODPLANK;
(*nbreakobs) = 1;
break;
} else {
switch (dt) {
case DT_FIRE:
case DT_HEAT:
case DT_ACID:
bigoid = OT_ASH;
smalloid = OT_ASH;
breakoid[0] = OT_ASHHUGE;
breakoid[1] = OT_ASHLARGE;
breakoid[2] = OT_ASH;
(*nbreakobs) = 3;
break;
default: break;
}
@ -4645,15 +4654,16 @@ int getbreakob(object_t *o, char *bigobname, char *smallobname) {
break;
case MT_ICE:
if (ismeleedam(dt) || (dt == DT_EXPLOSIVE)) {
bigoid = OT_ICECHUNK;
smalloid = OT_ICECHUNK;
breakoid[0] = OT_ICECHUNK;
(*nbreakobs) = 1;
break;
} else {
switch (dt) {
case DT_FIRE:
case DT_HEAT:
bigoid = OT_PUDDLEWATERL;
smalloid = OT_PUDDLEWATER;
breakoid[0] = OT_PUDDLEWATERL;
breakoid[1] = OT_PUDDLEWATER;
(*nbreakobs) = 2;
break;
default: break;
}
@ -4662,8 +4672,10 @@ int getbreakob(object_t *o, char *bigobname, char *smallobname) {
case MT_FLESH:
switch (dt) {
case DT_FIRE:
bigoid = OT_ASH;
smalloid = OT_ASH;
breakoid[0] = OT_ASHHUGE;
breakoid[1] = OT_ASHLARGE;
breakoid[2] = OT_ASH;
(*nbreakobs) = 3;
break;
default: break;
}
@ -4671,28 +4683,31 @@ int getbreakob(object_t *o, char *bigobname, char *smallobname) {
default: break;
}
big = findot(bigoid);
small = findot(smalloid);
// now find out how many big obejcts make up the wight.
weight = getobmass(o) / 3;
if (big) {
nbig = weight / big->weight;
weight -= (nbig*big->weight);
}
if (small){
nsmall = weight / small->weight;
weight -= (nsmall*small->weight);
for (i = 0; i < *nbreakobs; i++) {
breakob[i] = findot(breakoid[i]);
}
if (nbig) {
sprintf(bigobname, "%d %s",nbig,big->name);
}
if (nsmall) {
sprintf(smallobname, "%d %s",nsmall,small->name);
// now find out how many obejcts of each type make up the wight.
totmass = getobmass(o);
for (i = 0; i < *nbreakobs; i++) {
float thismass;
thismass = breakob[i]->mass;
nobs[i] = totmass / thismass;
totmass -= (nobs[i] * thismass);
}
if (strlen(bigobname) || strlen(smallobname)) {
for (i = 0; i < *nbreakobs; i++) {
if (nobs[i] > 0) {
char buf[BUFLEN];
sprintf(buf, "%d %s", nobs[i], breakob[i]->name);
breakobname[i] = strdup(buf);
} else {
breakobname[i] = NULL;
}
}
if (*nbreakobs) {
return B_TRUE;
}
return B_FALSE;
@ -7049,7 +7064,7 @@ float getobweight(object_t *o) {
if (hasflag(o->flags, F_DEEPWATER)) {
weight = 75 * getobdepth(o, NULL);
} else {
weight = o->weight;
weight = o->mass;
}
// has its material been changed?
@ -8596,7 +8611,7 @@ int isoperable(object_t *o) {
// parent objecttype?
int isplainob(object_t *o) {
if (o->material != o->type->material) return B_FALSE;
if (o->weight != o->type->weight) return B_FALSE;
if (o->mass != o->type->mass) return B_FALSE;
if (o->inscription) return B_FALSE;
if (o->blessed != B_UNCURSED) return B_FALSE;
if (isblessknown(o)) return B_FALSE;
@ -10075,23 +10090,25 @@ void obdie(object_t *o) {
if (o->pile->where) {
int minbones,maxbones;
char bonestr[BUFLEN];
minbones = o->weight / 10;
maxbones = o->weight / 5;
minbones = o->mass / 10;
maxbones = o->mass / 5;
if (minbones <= 0) minbones = 1;
if (maxbones <= minbones) maxbones = 2;
snprintf(bonestr, BUFLEN, "%d-%d bones",minbones,maxbones);
addob(o->pile, bonestr);
}
} else {
char bigbreak[BUFLEN],smallbreak[BUFLEN];
// maybe create broken object based on material
getbreakob(o, bigbreak, smallbreak);
char *breakobname[MAXBREAKOBTYPES];
int nbreakobs,i;
if (strlen(smallbreak)) {
addob(loc->obpile, smallbreak);
}
if (strlen(bigbreak)) {
addob(loc->obpile, bigbreak);
// maybe create broken object based on material
getbreakob(o, breakobname, &nbreakobs);
for (i = 0; i < nbreakobs; i++) {
if (breakobname[i]) {
addob(loc->obpile, breakobname[i]);
free(breakobname[i]);
}
}
}
}
@ -10657,7 +10674,7 @@ int obproduceslight(object_t *o) {
int obpropsmatch(object_t *a, object_t *b) {
if (a->type != b->type) return B_FALSE;
if (a->material != b->material) return B_FALSE;
if (a->weight != b->weight) return B_FALSE;
if (a->mass != b->mass) return B_FALSE;
if (a->inscription || b->inscription) return B_FALSE;
// only really need to check one of them, because at this point
// we know they are of the same type.
@ -15193,7 +15210,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce, lif
flag_t *ff;
meat = addob(o->pile, "chunk of roast meat");
// purposely don't use getweight!
meat->weight = o->weight;
meat->mass = o->mass;
copyflag(meat->flags, o->flags, F_CORPSEOF);
ff = hasflag(o->flags, F_OBHP);
if (ff) {
@ -17086,7 +17103,7 @@ void timeeffectsob(object_t *o) {
if (newob) {
int cansee;
// make the weight match.
newob->weight = o->weight;
newob->mass = o->mass;
// announce it?
cansee = B_FALSE;
if (location && haslos(player, location)) {
@ -17319,7 +17336,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
if (newob) {
flag_t *f, *f2;
// inherit weight
newob->weight = trappedob->weight;
newob->mass = trappedob->mass;
// inherit hp from original ob
f = hasflag(trappedob->flags, F_OBHP);
if (f) {

View File

@ -80,7 +80,7 @@ void genhiddennames(void);
enum LFSIZE getarmoursize(object_t *o);
enum RARITY getavgrarity(flagpile_t *fp);
object_t *getbestcontainer(obpile_t *op);
int getbreakob(object_t *o, char *bigobname, char *smallobname);
int getbreakob(object_t *o, char **breakobname, int *nbreakobtypes);
int getchargeinfo(object_t *o, int *cur, int *max);
int getcharges(object_t *o);
enum SKILL getclassloreskill(enum OBCLASS oc);

4
save.c
View File

@ -571,7 +571,7 @@ int loadob(FILE *f, obpile_t *op, long *id) {
}
o->material = mat;
fscanf(f, "weight:%f\n",&o->weight);
fscanf(f, "weight:%f\n",&o->mass);
fgets(buf, BUFLEN, f); // inscription
buf[strlen(buf)-1] = '\0'; // strip newline
@ -1157,7 +1157,7 @@ int saveob(FILE *f, object_t *o) {
fprintf(f, "id:%ld\n",o->id);
fprintf(f, "type:%d\n",o->type->id);
fprintf(f, "material:%d\n",o->material->id);
fprintf(f, "weight:%f\n",o->weight);
fprintf(f, "weight:%f\n",o->mass);
fprintf(f, "inscr:%s\n",o->inscription ? o->inscription : "^^^");
fprintf(f, "letter:%c\n",o->letter);
fprintf(f, "bless:%d\n",o->blessed);