diff --git a/mhdb.py b/mhdb.py index ebd1495..8e49c9b 100755 --- a/mhdb.py +++ b/mhdb.py @@ -118,11 +118,16 @@ class MHDB(object): """, quest_id) return v - def get_monster_rewards(self, monster_id, rank): - v = self._get_memoized("monster_rewards", """ + def get_monster_rewards(self, monster_id, rank=None): + q = """ SELECT * FROM hunting_rewards - WHERE monster_id=? AND rank=? - """, monster_id, rank) + WHERE monster_id=? + """ + if rank is not None: + q += "AND rank=?" + v = self._get_memoized("monster_rewards", q, monster_id, rank) + else: + v = self._get_memoized("monster_rewards", q, monster_id) return v def get_quest_monsters(self, quest_id): @@ -152,3 +157,11 @@ class MHDB(object): quests.append(Quest(quest_row, rewards_rows)) return quests + + def get_item_monsters(self, item_id): + v = self._get_memoized("item_monsters", """ + SELECT DISTINCT monster_id, rank FROM hunting_rewards + WHERE item_id=? + """, item_id) + + return v diff --git a/mhrewards.py b/mhrewards.py index 4efb38d..54fc415 100755 --- a/mhrewards.py +++ b/mhrewards.py @@ -36,6 +36,90 @@ def find_item(db, item_name, err_out): return item_row +def print_monsters_and_rewards(db, item_row, out): + item_id = item_row["_id"] + monsters = db.get_item_monsters(item_id) + for m in monsters: + mid = m["monster_id"] + rank = m["rank"] + monster = db.get_monster(mid) + cap_ev = [0, 0] + kill_ev = [0, 0] + shiny_ev = 0 + has_item = False + rewards = db.get_monster_rewards(mid, rank) + for reward in rewards: + cap = kill = shiny = False + if reward["item_id"] != item_id: + continue + if not has_item: + has_item = True + out.write("%s %s\n" % (monster["name"], rank)) + if reward["condition"] == "Body Carve": + totals = [ + 3 + mhprob.carve_delta_expected_c(skill) + for skill in xrange(mhprob.CARVING_SKILL_PRO, + mhprob.CARVING_SKILL_GOD+1) + ] + cap = False + kill = True + elif reward["condition"] == "Tail Carve": + totals = [ + 1 + mhprob.carve_delta_expected_c(skill) + for skill in xrange(mhprob.CARVING_SKILL_PRO, + mhprob.CARVING_SKILL_GOD+1) + ] + cap = kill = True + elif reward["condition"] == "Capture": + totals = [ + mhprob.capture_reward_expected_c(skill) + for skill in xrange(mhprob.CAP_SKILL_NONE, + mhprob.CAP_SKILL_GOD+1) + ] + cap = True + kill = False + else: + totals = [1] + # don't include Shiny in ev calculations + if reward["condition"].startswith("Shiny"): + cap = kill = False + shiny = True + elif reward["condition"].startswith("Break"): + cap = kill = True + else: + raise ValueError("Unknown condition: " + + reward["condition"]) + + evs = [i * reward["stack_size"] * reward["percentage"] + for i in totals] + if cap: + cap_ev[0] += evs[0] + cap_ev[1] += evs[-1] + if kill: + kill_ev[0] += evs[0] + kill_ev[1] += evs[-1] + if shiny: + shiny_ev += evs[0] + + out.write(" %20s %d %5.2f / 100" % (reward["condition"], + reward["stack_size"], + evs[0])) + out.write(" (%2d each)" % reward["percentage"]) + if len(totals) > 1: + out.write(" " + " ".join("%0.2f" % i for i in evs[1:])) + out.write("\n") + + if has_item: + out.write(" %20s\n" % "= Totals") + out.write(" %20s %s / 100\n" + % ("Kill", _format_range(*kill_ev))) + out.write(" %20s %s / 100\n" + % ("Cap", _format_range(*cap_ev))) + if shiny_ev: + out.write(" %20s %5.2f / 100\n" % ("Shiny", shiny_ev)) + out.write("\n") + + def print_quests_and_rewards(db, item_row, out): """ Get a list of the quests for acquiring a given item and the probability @@ -43,6 +127,9 @@ def print_quests_and_rewards(db, item_row, out): """ item_id = item_row["_id"] quests = db.get_item_quest_objects(item_id) + print_monsters_and_rewards(db, item_row, out) + if not quests: + return for q in quests: out.write(unicode(q) + "\n") out.write(" %20s" % "= Quest\n") @@ -65,7 +152,7 @@ def print_quests_and_rewards(db, item_row, out): for slot in total_reward_p.keys(): if total_reward_p[slot] not in (0, 100): print("WARNING: bad total p for %s = %d" - % (slot, total_reward_p[slot]), file=sys.stderr) + % (slot, total_reward_p[slot]), file=out) for reward in q._rewards: slot = reward["reward_slot"] @@ -100,11 +187,15 @@ def print_quests_and_rewards(db, item_row, out): for m in monsters: mid = m["monster_id"] monster = db.get_monster(mid) - out.write(" %20s\n" % ("= " + monster["name"] + " " + q.rank)) + has_item = False rewards = db.get_monster_rewards(mid, q.rank) for reward in rewards: cap = kill = shiny = False if reward["item_id"] == item_id: + if not has_item: + has_item = True + out.write(" %20s\n" + % ("= " + monster["name"] + " " + q.rank)) if reward["condition"] == "Body Carve": totals = [ 3 + mhprob.carve_delta_expected_c(skill) @@ -161,7 +252,8 @@ def print_quests_and_rewards(db, item_row, out): out.write(" %20s\n" % "= Totals") out.write(" %20s %s / 100\n" % ("Kill", _format_range(*kill_ev))) out.write(" %20s %s / 100\n" % ("Cap", _format_range(*cap_ev))) - out.write(" %20s %5.2f / 100\n" % ("Shiny", shiny_ev)) + if shiny_ev: + out.write(" %20s %5.2f / 100\n" % ("Shiny", shiny_ev)) out.write("\n")