careening = True
foehn = 4
atk_bonus = .1*foehn
hp_bonus = .2*careening + .1*foehn
trials = 1000
army = {
'Galley': {'n': 0, 'atk': 150, 'hp': 2000, 'fire': 0},
'Galleon': {'n': 8, 'atk': 500, 'hp': 15000, 'fire': 0},
'Fireship': {'n': 3, 'atk': 0, 'hp': 4000, 'fire': 100}
}
enemies = {
'Boat': {'n': 0, 'atk': 50, 'hp': 300, 'fire': 0},
'Trireme': {'n': 20, 'atk': 200, 'hp': 3000, 'fire': 0},
'Turtle Ship': {'n': 10, 'atk': 150, 'hp': 10000, 'fire': 0},
'Blast Ship': {'n': 6, 'atk': 800, 'hp': 8000, 'fire': 0}
}
A = ['atk', 'hp', 'fire']
enemy_totals = {}
for a in A: enemy_totals[a] = 0
for unit in enemies:
for a in A: enemy_totals[a] += enemies[unit]['n'] * enemies[unit][a]
army_totals = {}
for a in A: army_totals[a] = 0
for unit in army:
for a in A: army_totals[a] += army[unit]['n'] * army[unit][a]
from numpy.random import rand
def randomize(n): return n * (1 + .25 * (rand() - rand()))
def fight(d):
my_hp = army_totals['hp'] * (1+hp_bonus)
enemy_hp = enemy_totals['hp']
fire = 0
i = 0
while enemy_hp > 0 and i < 50:
i += 1
fire += randomize(army_totals['fire'])
atk = randomize(army_totals['atk'])
my_dmg = (fire + atk)*(1+atk_bonus)
enemy_dmg = randomize(enemy_totals['atk'])
enemy_hp -= my_dmg
my_hp -= enemy_dmg
return my_hp > 0
print sum(map(fight, range(trials))), "/", trials
Y2FyZWVuaW5nID0gVHJ1ZQpmb2VobiA9IDQKCmF0a19ib251cyA9IC4xKmZvZWhuCmhwX2JvbnVzID0gLjIqY2FyZWVuaW5nICsgLjEqZm9laG4KCnRyaWFscyA9IDEwMDAKCmFybXkgPSB7CiAgJ0dhbGxleSc6ICAgeyduJzogIDAsICdhdGsnOiAxNTAsICdocCc6ICAyMDAwLCAnZmlyZSc6IDB9LAogICdHYWxsZW9uJzogIHsnbic6ICA4LCAnYXRrJzogNTAwLCAnaHAnOiAxNTAwMCwgJ2ZpcmUnOiAwfSwKICAnRmlyZXNoaXAnOiB7J24nOiAgMywgJ2F0ayc6ICAgMCwgJ2hwJzogIDQwMDAsICdmaXJlJzogMTAwfQp9CmVuZW1pZXMgPSB7CiAgJ0JvYXQnOiAgICAgICAgeyduJzogMCwgICdhdGsnOiAgIDUwLCAnaHAnOiAgIDMwMCwgJ2ZpcmUnOiAwfSwKICAnVHJpcmVtZSc6ICAgICB7J24nOiAyMCwgJ2F0ayc6ICAyMDAsICdocCc6ICAzMDAwLCAnZmlyZSc6IDB9LAogICdUdXJ0bGUgU2hpcCc6IHsnbic6IDEwLCAnYXRrJzogIDE1MCwgJ2hwJzogMTAwMDAsICdmaXJlJzogMH0sCiAgJ0JsYXN0IFNoaXAnOiAgeyduJzogNiwgICdhdGsnOiAgODAwLCAnaHAnOiAgODAwMCwgJ2ZpcmUnOiAwfQp9CgpBID0gWydhdGsnLCAnaHAnLCAnZmlyZSddCmVuZW15X3RvdGFscyA9IHt9CmZvciBhIGluIEE6IGVuZW15X3RvdGFsc1thXSA9IDAKZm9yIHVuaXQgaW4gZW5lbWllczoKICBmb3IgYSBpbiBBOiBlbmVteV90b3RhbHNbYV0gKz0gZW5lbWllc1t1bml0XVsnbiddICogZW5lbWllc1t1bml0XVthXQoKYXJteV90b3RhbHMgPSB7fQpmb3IgYSBpbiBBOiBhcm15X3RvdGFsc1thXSA9IDAKZm9yIHVuaXQgaW4gYXJteToKICBmb3IgYSBpbiBBOiBhcm15X3RvdGFsc1thXSArPSBhcm15W3VuaXRdWyduJ10gKiBhcm15W3VuaXRdW2FdCgpmcm9tIG51bXB5LnJhbmRvbSBpbXBvcnQgcmFuZApkZWYgcmFuZG9taXplKG4pOiByZXR1cm4gbiAqICgxICsgLjI1ICogKHJhbmQoKSAtIHJhbmQoKSkpCmRlZiBmaWdodChkKToKICBteV9ocCA9IGFybXlfdG90YWxzWydocCddICogKDEraHBfYm9udXMpCiAgZW5lbXlfaHAgPSBlbmVteV90b3RhbHNbJ2hwJ10KICBmaXJlID0gMAogIGkgPSAwCiAgd2hpbGUgZW5lbXlfaHAgPiAwIGFuZCBpIDwgNTA6CiAgICBpICs9IDEKICAgIGZpcmUgKz0gcmFuZG9taXplKGFybXlfdG90YWxzWydmaXJlJ10pCiAgICBhdGsgPSByYW5kb21pemUoYXJteV90b3RhbHNbJ2F0ayddKQogICAgbXlfZG1nID0gKGZpcmUgKyBhdGspKigxK2F0a19ib251cykKICAgIGVuZW15X2RtZyA9IHJhbmRvbWl6ZShlbmVteV90b3RhbHNbJ2F0ayddKQogICAgZW5lbXlfaHAgLT0gbXlfZG1nCiAgICBteV9ocCAtPSBlbmVteV9kbWcKICByZXR1cm4gbXlfaHAgPiAwCnByaW50IHN1bShtYXAoZmlnaHQsIHJhbmdlKHRyaWFscykpKSwgIi8iLCB0cmlhbHMg