/* o_init.c */
short disco[NUM_OBJECTS];
+ short oclass_prob_totals[MAXOCLASSES];
/* objname.c */
/* distantname used by distant_name() to pass extra information to
/* ### o_init.c ### */
extern void init_objects(void);
+extern void init_oclass_probs(void);
extern void obj_shuffle_range(int, int *, int *);
extern int find_skates(void);
extern boolean objdescr_is(struct obj *, const char *);
OBJECT(OBJ(name, stone), \
BITS(0, 0, spec, 0, mgc, spec, 0, 0, 0, \
HARDGEM(mohs), 0, P_NONE, metal), \
- power, RING_CLASS, 0, 0, 3, cost, 0, 0, 0, 0, 15, color,sn)
+ power, RING_CLASS, 1, 0, 3, cost, 0, 0, 0, 0, 15, color,sn)
RING("adornment", "wooden",
ADORNED, 100, 1, 1, 2, WOOD, HI_WOOD, RIN_ADORNMENT),
RING("gain strength", "granite",
/* o_init.c */
DUMMY, /* disco */
+ DUMMY, /* oclass_prob_totals */
/* objname.c */
0, /* distantname */
struct obj *
mkobj(int oclass, boolean artif)
{
- int tprob, i, prob = rnd(1000);
+ int tprob, i, prob;
if (oclass == RANDOM_CLASS) {
const struct icp *iprobs = Is_rogue_level(&u.uz)
i = rnd_class(g.bases[SPBOOK_CLASS], SPE_BLANK_PAPER);
oclass = SPBOOK_CLASS; /* for sanity check below */
} else {
+ prob = rnd(g.oclass_prob_totals[oclass]);
i = g.bases[oclass];
while ((prob -= objects[i].oc_prob) > 0)
++i;
}
- if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
- panic("probtype error, oclass=%d i=%d", (int) oclass, i);
+ if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i])) {
+ impossible("probtype error, oclass=%d i=%d", (int) oclass, i);
+ i = g.bases[oclass];
+ }
return mksobj(i, TRUE, artif);
}
static void
setgemprobs(d_level* dlev)
{
- int j, first, lev;
+ int j, first, lev, sum = 0;
if (dlev)
lev = (ledger_no(dlev) > maxledgerno()) ? maxledgerno()
}
for (j = first; j <= LAST_GEM; j++)
objects[j].oc_prob = (171 + j - first) / (LAST_GEM + 1 - first);
+
+ /* recompute GEM_CLASS total oc_prob - including rocks/stones */
+ for (j = g.bases[GEM_CLASS]; j < g.bases[GEM_CLASS + 1]; j++)
+ sum += objects[j].oc_prob;
+ g.oclass_prob_totals[GEM_CLASS] = sum;
}
/* shuffle descriptions on objects o_low to o_high */
void
init_objects(void)
{
- int i, first, last, sum, prevoclass;
+ int i, first, last, prevoclass;
char oclass;
#ifdef TEXTCOLOR
#define COPY_OBJ_DESCR(o_dst, o_src) \
break;
}
}
- checkprob:
- sum = 0;
- for (i = first; i < last; i++)
- sum += objects[i].oc_prob;
- if (sum == 0) {
- for (i = first; i < last; i++)
- objects[i].oc_prob = (1000 + i - first) / (last - first);
- goto checkprob;
- }
- if (sum != 1000)
- error("init-prob error for class %d (%d%%)", oclass, sum);
first = last;
prevoclass = (int) oclass;
}
objects[i].oc_name_known = nmkn ? 0 : 1;
}
}
+ /* compute oclass_prob_totals */
+ init_oclass_probs();
/* shuffle descriptions */
shuffle_all();
objects[WAN_NOTHING].oc_dir = rn2(2) ? NODIR : IMMEDIATE;
}
+/* Compute the total probability of each object class.
+ * Assumes g.bases[] has already been set. */
+void
+init_oclass_probs(void)
+{
+ int i;
+ short sum;
+ int oclass;
+ for (oclass = 0; oclass < MAXOCLASSES; ++oclass) {
+ sum = 0;
+ for (i = g.bases[oclass]; i < g.bases[oclass + 1]; ++i) {
+ sum += objects[i].oc_prob;
+ }
+ if (sum <= 0 && oclass != ILLOBJ_CLASS
+ && g.bases[oclass] != g.bases[oclass + 1]) {
+ impossible("zero or negative probability total for oclass %d",
+ oclass);
+ /* gracefully fail by setting all members of this class to 1 */
+ for (i = g.bases[oclass]; i < g.bases[oclass + 1]; ++i) {
+ objects[i].oc_prob = 1;
+ sum++;
+ }
+ }
+ g.oclass_prob_totals[oclass] = sum;
+ }
+}
+
/* retrieve the range of objects that otyp shares descriptions with */
void
obj_shuffle_range(
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &uid, sizeof uid);
-
+
if (SYSOPT_CHECK_SAVE_UID
&& uid != (unsigned long) getuid()) { /* strange ... */
/* for wizard mode, issue a reminder; for others, treat it
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &u, sizeof(struct you));
g.youmonst.cham = u.mcham;
-
+
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) timebuf, 14);
timebuf[14] = '\0';
}
freefruitchn(g.ffruit); /* clean up fruit(s) made by initoptions() */
g.ffruit = loadfruitchn(nhfp);
-
+
restnames(nhfp);
restore_waterlevel(nhfp);
restore_msghistory(nhfp);
substitute_tiles(&u.uz);
#endif
max_rank_sz(); /* to recompute g.mrank_sz (botl.c) */
+ init_oclass_probs(); /* recompute g.oclass_prob_totals[] */
/* take care of iron ball & chain */
for (otmp = fobj; otmp; otmp = otmp->nobj)
if (otmp->owornmask)
g.doorindex = g.rooms[g.nroom - 1].fdoor + g.rooms[g.nroom - 1].doorct;
else
g.doorindex = 0;
-
+
restore_timers(nhfp, RANGE_LEVEL, elapsed);
restore_light_sources(nhfp);
fmon = restmonchn(nhfp);