diff options
author | Adam Borowski <kilobyte@angband.pl> | 2013-03-17 18:36:42 +0100 |
---|---|---|
committer | Adam Borowski <kilobyte@angband.pl> | 2013-03-18 08:34:35 +0100 |
commit | ad6c3632dbaffdf5aff048114b6f20348471372c (patch) | |
tree | 9c343f9faa476915b4d62a5a275054ab644a213a /crawl-ref/source/mon-pick.cc | |
parent | ea243feced8f317da5d449aeb8a1a10fc0ded164 (diff) | |
download | crawl-ref-ad6c3632dbaffdf5aff048114b6f20348471372c.tar.gz crawl-ref-ad6c3632dbaffdf5aff048114b6f20348471372c.zip |
The main workhorse for mon-pick.
Unlike the old code, it doesn't need to retry over and over, there is just
one roll. It also accepts and arbitrary vetoer function.
Diffstat (limited to 'crawl-ref/source/mon-pick.cc')
-rw-r--r-- | crawl-ref/source/mon-pick.cc | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/crawl-ref/source/mon-pick.cc b/crawl-ref/source/mon-pick.cc index cc344feefe..3e6fe8ae62 100644 --- a/crawl-ref/source/mon-pick.cc +++ b/crawl-ref/source/mon-pick.cc @@ -105,6 +105,62 @@ monster_type pick_monster_by_hash(branch_type branch, uint32_t hash) return population[branch].pop[hash % population[branch].count].mons; } +monster_type pick_monster(level_id place, mon_pick_vetoer veto) +{ + struct { monster_type mons; int rarity; } valid[NUM_MONSTERS]; + int nvalid = 0; + int totalrar = 0; + + ASSERT(place.is_valid()); + for (const pop_entry *pop = population[place.branch].pop; pop->mons; pop++) + { + if (place.depth < pop->minr || place.depth > pop->maxr) + continue; + + if (veto && (*veto)(pop->mons)) + continue; + + int rar = pop->rarity; + int len = pop->maxr - pop->minr; + switch (pop->distrib) + { + case FLAT: // 100% everywhere + break; + + case SEMI: // 100% in the middle, 50% at the edges + ASSERT(len > 0); + len *= 2; + rar = rar * (len - abs(pop->minr + pop->maxr - 2 * place.depth)) + / len; + break; + + case PEAK: // 100% in the middle, small at the edges, 0% outside + len += 2; // we want it to zero outside the range, not at the edge + rar = rar * (len - abs(pop->minr + pop->maxr - 2 * place.depth)) + / len; + break; + } + + ASSERT(rar > 0); + + valid[nvalid].mons = pop->mons; + valid[nvalid].rarity = rar; + totalrar += rar; + nvalid++; + } + + if (!nvalid) + return MONS_0; + + totalrar = random2(totalrar); // the roll! + + for (int i = 0; i < nvalid; i++) + if ((totalrar -= valid[i].rarity) < 0) + return valid[i].mons; + + die("mon-pick roll out of range"); +} + bool branch_has_monsters(branch_type branch) { COMPILE_CHECK(ARRAYSZ(population) == NUM_BRANCHES); |