Created
June 23, 2011 06:44
-
-
Save craigcalef/1042037 to your computer and use it in GitHub Desktop.
Figure out how many tengus you have to eat to get both teleportitis and teleport control. Also calculate the probability of getting teleportitis and teleport control using Monte Carlo integration.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Figure out how many tengus I have to eat to get both teleportitis and teleport control. | |
Author: Craig Calef <[email protected]> | |
""" | |
import random, sys, os, pprint | |
def rn2(i): | |
return random.randint(0, i-1) | |
def debug(s): | |
#print s | |
pass | |
POISON = 0 | |
TELEPORT = 1 | |
TELECTRL = 2 | |
chances = [15, 10, 12] | |
def givit(mlevel, intrinsic): | |
""" Model the givit() function in NetHack in a basic way. """ | |
# Eat.c 662 | |
chance = chances[intrinsic] | |
# Eat.c 676 | |
outcome = rn2(chance) | |
debug("Givit chance: %d mlevel: %d outcome: %d " % (chance, mlevel, outcome)) | |
return mlevel <= outcome | |
def eat(mlevel): | |
""" Model the 'eat a tengu' process, returning the intrinsic gained or -1 if none. """ | |
debug("Eating level %d corpse" % mlevel) | |
# Eat.c 928 | |
count = 0 | |
tmp = 0 | |
for i in range(0, 3): | |
count = count + 1 | |
if not rn2(count): | |
debug("Intrinsic %d replacing %d" % (i, tmp)) | |
tmp = i | |
# if this check fails givit returns early and the intrinsic is not granted | |
if not givit(mlevel, tmp): | |
return tmp | |
return -1 | |
def montecarlo(mlevel, trials, intrin): | |
""" Monte Carlo integration of intrinsic granting. Given more trials will converge on the | |
exact probability of being granted an intrinsic """ | |
a = 0 | |
for i in range(0, trials): | |
got = eat(mlevel) | |
if got == intrin: | |
debug("Got target intrinsic %d" % intrin) | |
a = a + 1 | |
else: | |
debug("Different intrinsic %d target=%d" % (got, intrin)) | |
debug( "%d positive trials out of %d" % (a, trials)) | |
return a | |
def chowdown(mlevel): | |
""" Return the number of tengu I had to eat to get teleport and telectrl via random trial """ | |
telectrl = False | |
teleport = False | |
i = 0 | |
while not (telectrl and teleport): | |
i = i + 1 | |
print "--- TRIAL %d --- telectrl:" % i, telectrl, " teleport:", teleport | |
grant = eat(mlevel) | |
if grant == 1: | |
teleport = True | |
debug("Got teleport") | |
if grant == 2: | |
telectrl = True | |
debug("Got telectrl") | |
if not grant == 1 and not grant == 2: | |
debug("Got %d" % grant) | |
return i | |
def feast(mlevel, trials): | |
results = [0, 0, 0] | |
for i in range(trials): | |
intrin = eat(mlevel) | |
print "---" | |
if intrin >= 0: | |
results[intrin] = results[intrin] + 1 | |
return results | |
def gorge(mlevel, trials): | |
results = [] | |
for i in range(trials): | |
results.append(chowdown(mlevel)) | |
return results | |
def rungorge(mlevel, trials): | |
results = gorge(mlevel, trials) | |
print "Tengu feast. mlevel: %d trials %d" % (mlevel, trials) | |
print "Results:", results | |
results.sort() | |
print "Min:", results[0], "Max:", results[-1], "Median:", results[len(results) // 2], "Avg:", sum(results) / len(results) | |
def runmontecarlo(mlevel, trials): | |
tpp = float(montecarlo(mlevel, trials, 1)) | |
tcp = float(montecarlo(mlevel, trials, 2)) | |
print "Teleport Probability for %d trials: %f" % (trials, tpp / trials) | |
print "TeleCtrl Probability for %d trials: %f" % (trials, tcp / trials) | |
if __name__ == '__main__': | |
if len(sys.argv) != 3: | |
print "%s <monster level> <number of trials>" % sys.argv[0] | |
mlevel = 10 | |
trials = 100 | |
else: | |
mlevel = int(sys.argv[1]) | |
trials = int(sys.argv[2]) | |
#results = feast(mlevel, trials) | |
#results = chowdown(mlevel) | |
#rungorge(mlevel, trials) | |
runmontecarlo(mlevel, trials) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
mlevel for tengu is always 6.