Skip to content

Instantly share code, notes, and snippets.

@leberechtreinhold
Last active October 26, 2018 16:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leberechtreinhold/5bdb6c345eb8842b5ffc6f8b58cecd73 to your computer and use it in GitHub Desktop.
Save leberechtreinhold/5bdb6c345eb8842b5ffc6f8b58cecd73 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
# import pprint
# import csv
import xlsxwriter
MAX_BONUS = 9
# Assumes the following:
# All elements are unsupported, Pikes are supported, Bows are being charged and
# is considered the first turn, and is close combat (the art is not shooting)
# Terrain is assumed plain
TROOP_NAMES = ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Art","Wwg"]
MOUNTED_TROOPS = ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm"]
TROOPS = {
"El": [4,5],
"Kn": [3,4],
"Hch": [3,4],
"Cv": [3,3],
"Lch": [3,3],
"Sch": [4,4],
"Cm": [2,4],
"Lh": [2,2],
"Lcm": [2,2],
"Sp": [4,4],
"Pk": [6,7],
"Bd": [5,3],
"Bw": [2,4],
"Wb": [3,2],
"Hd": [3,2],
"Ax": [3,2],
"Ps": [2,2],
"Art": [2,2],
"Wwg": [3,4],
}
KILLED_BY_SIMPLE = {
"El": ["Ps", "Ax", "Lh", "Lcm"],
"Kn": ["El", "Sch", "Lh", "Lcm", "Bw"],
"Hch": ["El", "Sch", "Lh", "Lcm", "Bw"],
"Cv": [],
"Lch": [],
"Sch": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Art","Wwg"],
"Cm": [],
"Lh": [],
"Lcm": [],
"Sp": ["El", "Kn", "Lh", "Sch", "Wb"],
"Pk": ["El", "Kn", "Lh", "Sch", "Wb"],
"Bd": ["Kn", "Sch", "Wb"],
"Bw": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm"],
"Wb": ["El","Kn","Sch"],
"Hd": ["El","Kn","Sch","Wb"],
"Ax": ["Kn"],
"Ps": ["Kn","Cv","Cm"],
"Art": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Art","Wwg"],
"Wwg": ["El"],
}
KILLED_BY_DOUBLE = {
"El": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Kn": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Hch": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Cv": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Bd","Bw","Wb","Ax","Ps","Wwg"],
"Lch": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Sch": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Art","Wwg"],
"Cm": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Lh": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Bw","Ps"],
"Lcm": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Bw","Ps"],
"Sp": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Pk": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Bd": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Bw": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Wb": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Hd": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Ax": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
"Ps": ["Kn","Cv","Cm","Lh","Lch","Bw","Ax","Ps"],
"Art": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Art","Wwg"],
"Wwg": ["El","Kn","Hch","Cv","Lch","Sch","Cm","Lh","Lcm","Sp","Pk","Bd","Bw","Wb","Hd","Ax","Ps","Wwg"],
}
def get_bonus(attacker, defender):
your_bonus = TROOPS[attacker][0]
if defender in MOUNTED_TROOPS:
your_bonus = TROOPS[attacker][1]
return your_bonus
def calculate_wins_by_dice():
results_simple_win = {}
results_win_double = {}
for your_bonus in range(0,MAX_BONUS):
results_simple_win[your_bonus] = {}
results_win_double[your_bonus] = {}
for their_bonus in range(0,MAX_BONUS):
win_possibilties_simple = 0;
win_possibilties_double = 0;
for your_dice in range(1,7):
your_result = your_bonus + your_dice
for their_dice in range(1,7):
their_result = their_bonus + their_dice
if your_result > their_result:
win_possibilties_simple += 1
if your_result >= their_result * 2:
win_possibilties_double += 1
results_simple_win[your_bonus][their_bonus] = (win_possibilties_simple / 36.0) * 100.0
results_win_double[your_bonus][their_bonus] = (win_possibilties_double / 36.0) * 100.0
return results_simple_win, results_win_double
def calculate_kills_by_troop(results_simple_win, results_win_double):
# BEWARE, cant use dict.fromkeys(TROOP_NAMES, dict.fromkeys(TROOP_NAMES))
# because that means all entries share the same reference
kill_by_troop = dict.fromkeys(TROOP_NAMES)
for key in kill_by_troop:
kill_by_troop[key] = dict.fromkeys(TROOP_NAMES)
for your_troop in TROOP_NAMES:
for their_troop in TROOP_NAMES:
your_bonus = get_bonus(your_troop, their_troop)
their_bonus = get_bonus(their_troop, your_troop)
is_killed_by_simple = your_troop in KILLED_BY_SIMPLE[their_troop]
is_killed_by_double = your_troop in KILLED_BY_DOUBLE[their_troop]
if is_killed_by_simple:
kill_by_troop[your_troop][their_troop] = results_simple_win[your_bonus][their_bonus]
#print(your_troop + " vs " + their_troop + ": " + str(kill_by_troop[your_troop][their_troop]) + " (Simple)")
elif is_killed_by_double:
kill_by_troop[your_troop][their_troop] = results_win_double[your_bonus][their_bonus]
#print(your_troop + " vs " + their_troop + ": " + str(kill_by_troop[your_troop][their_troop]) + " (Double)")
else:
kill_by_troop[your_troop][their_troop] = 0.0
#print(your_troop + " vs " + their_troop + ": 0 " + "(Cannot)")
return kill_by_troop
def who_kills_what():
kills_at_simple = dict.fromkeys(TROOP_NAMES)
kills_at_double = dict.fromkeys(TROOP_NAMES)
for troop_killed in TROOP_NAMES:
killers = KILLED_BY_SIMPLE[troop_killed]
for killer in killers:
if kills_at_simple[killer] is None:
kills_at_simple[killer] = set()
kills_at_simple[killer].add(troop_killed)
killers = KILLED_BY_DOUBLE[troop_killed]
for killer in killers:
if kills_at_double[killer] is None:
kills_at_double[killer] = set()
kills_at_double[killer].add(troop_killed)
return kills_at_simple, kills_at_double
def print_markdown(kills_at_simple, kills_at_double):
largest_str_simple = 0
for troop in TROOP_NAMES:
len_str = len(','.join(kills_at_simple[troop]))
if (len_str > largest_str_simple):
largest_str_simple = len_str
print("Killer | {msg: <{width}} | Killed by double".format(msg="Killed by simple", width=largest_str_simple))
print("-------|{0}|-----------------------".format('-' * (largest_str_simple + 2)))
for troop in TROOP_NAMES:
print("{killer: <6} | {simple_killed: <{width}} | {double_killed}"
.format(killer=troop, width=largest_str_simple,
simple_killed=','.join(kills_at_simple[troop]),
double_killed=','.join(kills_at_double[troop])))
def write_table_dice_roll(worksheet, current_row, title, y_axis, x_axis, pos_threshold, neg_threshold, table_data, formats):
worksheet.write(current_row, 0, title, formats["format_title"])
worksheet.write(current_row, 2, x_axis, formats["format_header"])
for their_bonus in range(0,MAX_BONUS):
worksheet.write(current_row + 1, their_bonus + 2, their_bonus, formats["format_header"])
worksheet.write(current_row + 2, 0, y_axis, formats["format_header"])
for your_bonus in range(0,MAX_BONUS):
worksheet.write(your_bonus + current_row + 2, 1, your_bonus, formats["format_header"])
for your_bonus in range(0,MAX_BONUS):
for their_bonus in range(0,MAX_BONUS):
row = your_bonus + current_row + 2
col = their_bonus + 2
val = table_data[your_bonus][their_bonus]
cellformat = formats["format_normal"]
if val > pos_threshold:
cellformat = formats["format_better_than"]
elif val < neg_threshold:
cellformat = formats["format_worse_than"]
worksheet.write(row, col, val, cellformat)
def write_table_kills(worksheet, current_row, title, y_axis, x_axis, pos_threshold, neg_threshold, table_data, formats):
worksheet.write(current_row, 0, title, formats["format_title"])
worksheet.write(current_row, 2, x_axis, formats["format_header"])
i = 0
for troop in TROOP_NAMES:
worksheet.write(current_row + 1, i + 2, troop, formats["format_header"])
i += 1
worksheet.write(current_row + 2, 0, y_axis, formats["format_header"])
i = 0
for troop in TROOP_NAMES:
worksheet.write(i + current_row + 2, 1, troop, formats["format_header"])
i += 1
i = 0
for your_troop in TROOP_NAMES:
j = 0
for their_troop in TROOP_NAMES:
row = i + current_row + 2
col = j + 2
val = table_data[your_troop][their_troop]
cellformat = formats["format_normal"]
if val > pos_threshold:
cellformat = formats["format_better_than"]
elif val < neg_threshold:
cellformat = formats["format_worse_than"]
worksheet.write(row, col, val, cellformat)
j += 1
i += 1
def main():
results_simple_win, results_win_double = calculate_wins_by_dice()
kill_by_troop = calculate_kills_by_troop(results_simple_win, results_win_double)
workbook = xlsxwriter.Workbook('dbastats.xlsx')
worksheet = workbook.add_worksheet()
formats = {}
formats["format_title"] = workbook.add_format({'bold': True, 'font_color': '#eeeeee', 'bg_color': '#222222'})
formats["format_header"] = workbook.add_format({'bold': True})
formats["format_better_than"] = workbook.add_format({'font_color': '#eeeeee', 'bg_color': '#46B64A', 'num_format': '0.0'})
formats["format_worse_than"] = workbook.add_format({'font_color': '#eeeeee', 'bg_color': '#C0504D', 'num_format': '0.0'})
formats["format_normal"] = workbook.add_format({'num_format': '0.0'})
current_row = 0
write_table_dice_roll(worksheet, current_row, "Win By Simple", "Your bonus", "Their bonus", 60, 40, results_simple_win, formats)
current_row = MAX_BONUS + 3
write_table_dice_roll(worksheet, current_row, "Win By double", "Your bonus", "Their bonus", 60, 40, results_win_double, formats)
current_row = (MAX_BONUS + 3) * 2
write_table_kills(worksheet, current_row, "Kill by troop", "Your troop", "Their troop", 20, 1, kill_by_troop, formats)
workbook.close()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment