Skip to content

Instantly share code, notes, and snippets.

@craigcalef
Created June 23, 2011 06:44
Show Gist options
  • Save craigcalef/1042037 to your computer and use it in GitHub Desktop.
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.
"""
Figure out how many tengus I have to eat to get both teleportitis and teleport control.
Author: Craig Calef <craig@dod.net>
"""
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)
@craigcalef
Copy link
Author

mlevel for tengu is always 6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment