From 0ef3a565b7f1c30fe4b0ed92fc146a3e194987f7 Mon Sep 17 00:00:00 2001 From: Darshan Shaligram Date: Sun, 17 Jan 2010 15:38:58 +0530 Subject: Update place-population to report xp stats as well as monster numbers (due). --- crawl-ref/source/scripts/place-population.lua | 97 +++++++++++++++++++++------ 1 file changed, 75 insertions(+), 22 deletions(-) diff --git a/crawl-ref/source/scripts/place-population.lua b/crawl-ref/source/scripts/place-population.lua index 70936f18ed..8b8095d956 100644 --- a/crawl-ref/source/scripts/place-population.lua +++ b/crawl-ref/source/scripts/place-population.lua @@ -8,12 +8,14 @@ local function count_monsters_at(place, set) debug.goto_place(place) test.regenerate_level() - local monsters_here = set or { } + local monsters_here = set or { } for mons in test.level_monster_iterator() do local mname = mons.name if not excluded_things[mname] then - local count = monsters_here[mname] or 0 - monsters_here[mname] = count + 1 + local mstat = monsters_here[mname] or { count = 0, exp = 0 } + mstat.count = mstat.count + 1 + mstat.exp = mstat.exp + mons.experience + monsters_here[mname] = mstat end end return monsters_here @@ -35,9 +37,14 @@ local function report_monster_counts_at(place, mcount_map) total = total + monster_pop[2].total end + text = text .. "Count | XPAv | XPMin | XPMax | XPSigma | CountMin | CountMax | CountSigma | % | Monster\n" for _, monster_pop in ipairs(monster_counts) do - text = text .. string.format("%5.2f (min: %2d, max: %2d, sd: %6.2f, %%: %6.2f%%) %s\n", + text = text .. string.format("%6.2f | %5d | %5d | %5d | %7d | %8d | %8d | %10.2f | %6.2f%% | %s\n", monster_pop[2].mean, + monster_pop[2].emean, + monster_pop[2].emin, + monster_pop[2].emax, + monster_pop[2].esigma, monster_pop[2].min, monster_pop[2].max, monster_pop[2].sigma, @@ -60,35 +67,81 @@ local function report_monster_counts(mcounts) end local function calculate_monster_stats(iter_mpops) - local final_stats = { } - local n = #iter_mpops - for _, mpop in ipairs(iter_mpops) do - for mons, count in pairs(mpop) do - local mstats = - final_stats[mons] or { total = 0, max = 0, min = 0, pops = { } } + local function blank_stats() + return { + total = 0, max = 0, min = 10 ^ 10, + etotal = 0, emax = 0, emin = 10 ^ 10, eiters = { }, + pops = { } } + end - mstats.total = mstats.total + count - if count > mstats.max then - mstats.max = count + local function update_mons_stats(stat, instance_stat) + local function update_total_max_min(value, total, max, min) + stat[total] = stat[total] + value + if value > stat[max] then + stat[max] = value end - if count < mstats.min then - mstats.min = count + if value < stat[min] then + stat[min] = value end - table.insert(mstats.pops, count) - final_stats[mons] = mstats end + update_total_max_min(instance_stat.count, 'total', 'max', 'min') + update_total_max_min(instance_stat.exp, 'etotal', 'emax', 'emin') + table.insert(stat.pops, instance_stat.count) + table.insert(stat.eiters, instance_stat.exp) + return stat end - for mons, stat in pairs(final_stats) do - stat.mean = stat.total / n + local function sum(list) + local total = 0 + for _, num in ipairs(list) do + total = total + num + end + return total + end + + local function combine_stats(target, src) + local total = sum(src.pops) + local etotal = sum(src.eiters) + table.insert(target.pops, total) + table.insert(target.eiters, etotal) + target.total = target.total + total + target.etotal = target.etotal + etotal + target.max = math.max(target.max, total) + target.min = math.min(target.min, total) + target.emax = math.max(target.emax, etotal) + target.emin = math.min(target.emin, etotal) + end + local final_stats = { TOTAL = blank_stats() } + local n = #iter_mpops + for _, mpop in ipairs(iter_mpops) do + local global_stat = blank_stats() + for mons, istat in pairs(mpop) do + local mstats = final_stats[mons] or blank_stats() + final_stats[mons] = update_mons_stats(mstats, istat) + update_mons_stats(global_stat, istat) + end + combine_stats(final_stats.TOTAL, global_stat) + end + + local function calc_mean_sigma(total, instances) + local mean = total / n local totaldelta2 = 0 - local mean = stat.mean - for _, count in ipairs(stat.pops) do + for _, count in ipairs(instances) do local delta = count - mean totaldelta2 = totaldelta2 + delta * delta end - stat.sigma = math.sqrt(totaldelta2 / n) + -- There will be no instances with count 0, handle those: + for extra = 1, (n - #instances) do + totaldelta2 = totaldelta2 + mean * mean + end + local sigma = math.sqrt(totaldelta2 / n) + return mean, sigma + end + + for mons, stat in pairs(final_stats) do + stat.mean, stat.sigma = calc_mean_sigma(stat.total, stat.pops) + stat.emean, stat.esigma = calc_mean_sigma(stat.etotal, stat.eiters) end return final_stats end -- cgit v1.2.3-54-g00ecf