From b125822172de8768566d2ce2c22c2e4039c11ffa Mon Sep 17 00:00:00 2001 From: Bryce Allen Date: Sun, 15 Mar 2015 09:51:05 -0500 Subject: [PATCH] improve doc, exit codes --- .gitignore | 1 + README.adoc | 29 +++++++++++++++++++++++++++++ mhprob.py | 6 ++++++ mhrewards.py | 22 ++++++++++++---------- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 0d20b64..3114844 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.pyc +README.html diff --git a/README.adoc b/README.adoc index 8cca860..6076e76 100644 --- a/README.adoc +++ b/README.adoc @@ -2,3 +2,32 @@ This repository contains scripts for calculating probalities and expected values for rewards and carves in Monster Hunter games. + +== Dependencies + +Tested using Python 2.7, might work with 2.6. Uses sqlite3, which is part of +the standard library now but I'm not sure it's always compiled in by default +in all Python distributions (e.g. for Windows or Mac OS X). + +== Example usage + +For a list of quests providing the specified monster part: + + ./mhrewards.py "Zinogre Jasper" + +This gives expected values for the item from different sources, including +quest rewards, carves, capture, and shiny drops. An expected value of +8% means that on average, you would get 8 of the item from 100 quests. Note +that this is different from the probability of getting at least one, which +will be lower and is a pain to calculate when there can be different number +of rewards. + +For more manual calculations, mhprob.py can be used directly. The quest +"Plain Dangerous" in 3U has 2 fixed rewards in A, one in B. Diablos hardhorns +have a 5% chance: + + ./mhprop.py 5 2 3 69 + ./mhprop.py 5 1 1 69 + +For great luck, you would replace 69 with 90. The output includes both expected +value and probability of getting at least one. diff --git a/mhprob.py b/mhprob.py index 8728170..aa5543f 100755 --- a/mhprob.py +++ b/mhprob.py @@ -106,6 +106,11 @@ def quest_reward_p(reward_percent, min_rewards, max_rewards, extend_percent=69): def reward_expected_c(min_rewards, max_rewards, extend_percent): + """ + Expected value for number of rewards, if @min_rewards are gauranteed + and there is an @extend_percent chance of getting one more each time + with at most @max_rewards. + """ total_p = 0.0 expected_attempts = 0.0 for reward_count in xrange(min_rewards, max_rewards + 1): @@ -185,6 +190,7 @@ def carve_delta_expected_c(carve_skill): return 1 elif carve_skill == CARVING_SKILL_GOD: # Description: Increases the number of carving chances by one (maybe more) and prevents knockbacks while carving. + # TODO: max 2 and 50% extend is a guess, find the actual values min_c = 1 max_c = 2 extend_p = 50 diff --git a/mhrewards.py b/mhrewards.py index 924ac36..6aadb6f 100755 --- a/mhrewards.py +++ b/mhrewards.py @@ -18,30 +18,29 @@ def _format_range(min_v, max_v): return "%5.2f%% to %5.2f%%" % (min_v, max_v) -def find_item(db, item_name, out): +def find_item(db, item_name, err_out): item_row = db.get_item_by_name(item_name) if item_row is None: print("Item '%s' not found. Listing partial matches:" % item_name, - file=out) + file=err_out) terms = item_name.split() for term in terms: if len(term) < 2: # single char terms aren't very useful, too many results continue - print("= Matching term '%s'" % term, file=out) + print("= Matching term '%s'" % term, file=err_out) rows = db.search_item_name(term, "Flesh") for row in rows: - print(" ", row["name"], file=out) + print(" ", row["name"], file=err_out) return None return item_row -def print_quests_and_rewards(db, item_name, out): +def print_quests_and_rewards(db, item_row, out): """ Get a list of the quests for acquiring a given item and the probability of getting the item, depending on cap or kill and luck skills. """ - item_row = db.get_item_by_name(item_name) item_id = item_row["_id"] quests = db.get_item_quest_objects(item_id) for q in quests: @@ -168,21 +167,24 @@ def print_quests_and_rewards(db, item_name, out): if __name__ == '__main__': import sys + import os import os.path if len(sys.argv) != 2: print("Usage: %s 'item name'" % sys.argv[0]) - sys.exit(1) + sys.exit(os.EX_USAGE) item_name = sys.argv[1] out = get_utf8_writer(sys.stdout) + err_out = get_utf8_writer(sys.stderr) # TODO: doesn't work if script is symlinked db_path = os.path.dirname(sys.argv[0]) db_path = os.path.join(db_path, "db", "mh4u.db") db = mhdb.MHDB(db_path) - item_row = find_item(db, item_name, out) - if item_row is not None: - print_quests_and_rewards(db, item_name, out) + item_row = find_item(db, item_name, err_out) + if item_row is None: + sys.exit(os.EX_DATAERR) + print_quests_and_rewards(db, item_row, out)