MCPcopy Create free account
hub / github.com/NetHack/NetHack / rndmonst_adj

Function rndmonst_adj

src/makemon.c:1658–1732  ·  view source on GitHub ↗

select a random monster type, with adjusted difficulty */

Source from the content-addressed store, hash-verified

1656
1657/* select a random monster type, with adjusted difficulty */
1658struct permonst *
1659rndmonst_adj(int minadj, int maxadj)
1660{
1661 struct permonst *ptr;
1662 int mndx;
1663 int weight, totalweight, selected_mndx, zlevel, minmlev, maxmlev;
1664 boolean elemlevel, upper;
1665
1666 if (u.uz.dnum == quest_dnum && rn2(7) && (ptr = qt_montype()) != 0)
1667 return ptr;
1668
1669 zlevel = level_difficulty();
1670 minmlev = monmin_difficulty(zlevel) + minadj;
1671 maxmlev = monmax_difficulty(zlevel) + maxadj;
1672 upper = Is_rogue_level(&u.uz); /* prefer uppercase only on rogue level */
1673 elemlevel = In_endgame(&u.uz) && !Is_astralevel(&u.uz); /* elmntl plane */
1674
1675 /* amount processed so far */
1676 totalweight = 0;
1677 selected_mndx = NON_PM;
1678
1679 for (mndx = LOW_PM; mndx < SPECIAL_PM; ++mndx) {
1680 ptr = &mons[mndx];
1681
1682 if (montooweak(mndx, minmlev) || montoostrong(mndx, maxmlev))
1683 continue;
1684 if (upper && !isupper(monsym(ptr)))
1685 continue;
1686 if (elemlevel && wrong_elem_type(ptr))
1687 continue;
1688 if (uncommon(mndx))
1689 continue;
1690 if (Inhell && (ptr->geno & G_NOHELL))
1691 continue;
1692
1693 /*
1694 * Weighted reservoir sampling: select ptr with a
1695 * (ptr weight)/(total of all weights so far including ptr's)
1696 * probability. For example, if the previous total is 10, and
1697 * this is now looking at acid blobs with a frequency of 2, it
1698 * has a 2/12 chance of abandoning ptr's previous value in favor
1699 * of acid blobs, and 10/12 chance of keeping whatever it was.
1700 *
1701 * This does not bias results towards either the earlier or the
1702 * later monsters: the smaller pool and better odds from being
1703 * earlier are exactly canceled out by having more monsters to
1704 * potentially steal its spot.
1705 */
1706 weight = (int) (ptr->geno & G_FREQ) + align_shift(ptr);
1707 weight += temperature_shift(ptr);
1708 if (weight < 0 || weight > 127) {
1709 impossible("bad weight in rndmonst for mndx %d", mndx);
1710 weight = 0;
1711 }
1712 /* was unconditional, but if weight==0, rn2() < 0 will always fail;
1713 also need to avoid rn2(0) if totalweight is still 0 so far */
1714 if (weight > 0) {
1715 totalweight += weight; /* totalweight now guaranteed to be > 0 */

Callers 3

pick_familiar_pmFunction · 0.85
rndmonnum_adjFunction · 0.85
rndmonstFunction · 0.85

Calls 9

rn2Function · 0.85
qt_montypeFunction · 0.85
level_difficultyFunction · 0.85
isupperFunction · 0.85
wrong_elem_typeFunction · 0.85
uncommonFunction · 0.85
align_shiftFunction · 0.85
temperature_shiftFunction · 0.85
impossibleFunction · 0.70

Tested by

no test coverage detected