objects[] infrastructure
The bases[] array allows finding the index of the first object in a particular class. Extend it so that bases[class + 1] - 1 is a reliable way to find the last object in any class. The array had to be extended by one so that the last class has a [class+1] entry available, and object initialization now makes sure that classes within objects[] are in ascending order so that [class+1] always holds a higher index than [class].
This commit is contained in:
@@ -713,7 +713,7 @@ struct instance_globals {
|
||||
const char *hname; /* name of the game (argv[0] of main) */
|
||||
int hackpid; /* current process id */
|
||||
char chosen_windowtype[WINTYPELEN];
|
||||
int bases[MAXOCLASSES];
|
||||
int bases[MAXOCLASSES + 1];
|
||||
int multi;
|
||||
const char *multi_reason;
|
||||
int nroom;
|
||||
|
||||
32
src/o_init.c
32
src/o_init.c
@@ -108,8 +108,8 @@ boolean domaterial;
|
||||
void
|
||||
init_objects()
|
||||
{
|
||||
register int i, first, last, sum;
|
||||
register char oclass;
|
||||
int i, first, last, sum;
|
||||
char oclass, prevoclass;
|
||||
#ifdef TEXTCOLOR
|
||||
#define COPY_OBJ_DESCR(o_dst, o_src) \
|
||||
o_dst.oc_descr_idx = o_src.oc_descr_idx, o_dst.oc_color = o_src.oc_color
|
||||
@@ -120,7 +120,7 @@ init_objects()
|
||||
/* bug fix to prevent "initialization error" abort on Intel Xenix.
|
||||
* reported by mikew@semike
|
||||
*/
|
||||
for (i = 0; i < MAXOCLASSES; i++)
|
||||
for (i = 0; i <= MAXOCLASSES; i++)
|
||||
g.bases[i] = 0;
|
||||
/* initialize object descriptions */
|
||||
for (i = 0; i < NUM_OBJECTS; i++)
|
||||
@@ -128,8 +128,19 @@ init_objects()
|
||||
/* init base; if probs given check that they add up to 1000,
|
||||
otherwise compute probs */
|
||||
first = 0;
|
||||
prevoclass = -1;
|
||||
while (first < NUM_OBJECTS) {
|
||||
oclass = objects[first].oc_class;
|
||||
/*
|
||||
* objects[] sanity check: must be in ascending oc_class order to
|
||||
* be able to use bases[class+1]-1 for the end of a class's range.
|
||||
* Also catches a non-contiguous class because reverting to any
|
||||
* earlier class would involve switching back to a lower class
|
||||
* number after having moved on to one or more other classes.
|
||||
*/
|
||||
if (oclass < prevoclass)
|
||||
panic("objects[%d] class #%d not in order!", first, oclass);
|
||||
|
||||
last = first + 1;
|
||||
while (last < NUM_OBJECTS && objects[last].oc_class == oclass)
|
||||
last++;
|
||||
@@ -170,7 +181,18 @@ init_objects()
|
||||
if (sum != 1000)
|
||||
error("init-prob error for class %d (%d%%)", oclass, sum);
|
||||
first = last;
|
||||
prevoclass = oclass;
|
||||
}
|
||||
/* extra entry allows deriving the range of a class via
|
||||
bases[class] through bases[class+1]-1 for all classes */
|
||||
g.bases[MAXOCLASSES] = NUM_OBJECTS;
|
||||
/* hypothetically someone might remove all objects of some class,
|
||||
or be adding a new class and not populated it yet, leaving gaps
|
||||
in bases[]; guarantee that there are no such gaps */
|
||||
for (last = MAXOCLASSES - 1; last >= 0; --last)
|
||||
if (!g.bases[last])
|
||||
g.bases[last] = g.bases[last + 1];
|
||||
|
||||
/* shuffle descriptions */
|
||||
shuffle_all();
|
||||
#ifdef USE_TILES
|
||||
@@ -221,9 +243,7 @@ int *lo_p, *hi_p; /* output: range that item belongs among */
|
||||
case VENOM_CLASS:
|
||||
/* entire class */
|
||||
*lo_p = g.bases[ocls];
|
||||
for (i = *lo_p; objects[i].oc_class == ocls; i++)
|
||||
continue;
|
||||
*hi_p = i - 1;
|
||||
*hi_p = g.bases[ocls + 1] - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
23
src/objnam.c
23
src/objnam.c
@@ -2897,13 +2897,19 @@ int xtra_prob; /* to force 0% random generation items to also be considered */
|
||||
int i, n = 0;
|
||||
short validobjs[NUM_OBJECTS];
|
||||
register const char *zn;
|
||||
int prob, maxprob = 0;
|
||||
int lo, hi, prob, maxprob = 0;
|
||||
|
||||
if (!name || !*name)
|
||||
return STRANGE_OBJECT;
|
||||
|
||||
memset((genericptr_t) validobjs, 0, sizeof validobjs);
|
||||
|
||||
(void) memset((genericptr_t) validobjs, 0, sizeof validobjs);
|
||||
if (oclass) {
|
||||
lo = g.bases[(uchar) oclass];
|
||||
hi = g.bases[(uchar) oclass + 1] - 1;
|
||||
} else {
|
||||
lo = STRANGE_OBJECT + 1;
|
||||
hi = NUM_OBJECTS - 1;
|
||||
}
|
||||
/* FIXME:
|
||||
* When this spans classes (the !oclass case), the item
|
||||
* probabilities are not very useful because they don't take
|
||||
@@ -2912,9 +2918,7 @@ int xtra_prob; /* to force 0% random generation items to also be considered */
|
||||
* "blank" would have 10/11 chance to yield a blook even though
|
||||
* scrolls are supposed to be much more common than books.]
|
||||
*/
|
||||
for (i = oclass ? g.bases[(int) oclass] : STRANGE_OBJECT + 1;
|
||||
i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
|
||||
++i) {
|
||||
for (i = lo; i <= hi; ++i) {
|
||||
/* don't match extra descriptions (w/o real name) */
|
||||
if ((zn = OBJ_NAME(objects[i])) == 0)
|
||||
continue;
|
||||
@@ -3840,9 +3844,12 @@ struct obj *no_wish;
|
||||
}
|
||||
|
||||
if (((typ = rnd_otyp_by_namedesc(actualn, oclass, 1)) != STRANGE_OBJECT)
|
||||
|| ((typ = rnd_otyp_by_namedesc(dn, oclass, 1)) != STRANGE_OBJECT)
|
||||
|| (dn != actualn
|
||||
&& (typ = rnd_otyp_by_namedesc(dn, oclass, 1)) != STRANGE_OBJECT)
|
||||
|| ((typ = rnd_otyp_by_namedesc(un, oclass, 1)) != STRANGE_OBJECT)
|
||||
|| ((typ = rnd_otyp_by_namedesc(origbp, oclass, 1)) != STRANGE_OBJECT))
|
||||
|| (origbp != actualn
|
||||
&& ((typ = rnd_otyp_by_namedesc(origbp, oclass, 1))
|
||||
!= STRANGE_OBJECT)))
|
||||
goto typfnd;
|
||||
typ = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user