Skip to content

Instantly share code, notes, and snippets.

@josh-hernandez-exe
Last active November 29, 2022 19:21
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 josh-hernandez-exe/921c12e9217aeb8cefeef1cc583c3082 to your computer and use it in GitHub Desktop.
Save josh-hernandez-exe/921c12e9217aeb8cefeef1cc583c3082 to your computer and use it in GitHub Desktop.
Coromon Multi-Type Chart Generation
DEF Type 1 / DEF Type 2 \ ATK Type Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
Normal|50 / Electric|50 1/2 1/2 2 1/2 2 2
Normal|50 / Ghost|50 1/2 1/2 2 1/2
Normal|50 / Sand|50 1/2 1/2 1/2 2 1/2 2
Normal|50 / Fire|50 1/2 1/2 1/2 2 1/2 2 2
Normal|50 / Ice|50 1/2 2 1/2 1/2 2 1/2
Normal|50 / Water|50 2 1/2 1/2 1/2 2 1/2 2 2
Normal|50 / Dark Magic|50 1/2 1/2 1/4 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2
Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
Electric|50 / Normal|50 1/2 1/2 2 1/2 2 2
Electric|50 / Ghost|50 1/2 1/2 2 2 1/2 1/2
Electric|50 / Sand|50 1/4 1/2 2
Electric|50 / Fire|50 1/2 2 1/2 1/2 1/2 2 2
Electric|50 / Ice|50 1/2 2 2 1/2 1/4 2 1/2 1/2 2
Electric|50 / Water|50 1/2 2 1/4 2 2
Electric|50 / Dark Magic|50 1/2 1/4 1/2 1/2 1/2 1/4 1/2 1/2 1/2 1/2 1/2
Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
Ghost|50 / Normal|50 1/2 1/2 2 1/2
Ghost|50 / Electric|50 1/2 1/2 2 2 1/2 1/2
Ghost|50 / Sand|50 1/2 1/2 2 1/2 2 1/2 1/2 1/2
Ghost|50 / Fire|50 1/2 2 1/2 1/2 2 1/2 1/2 2 1/2
Ghost|50 / Ice|50 1/2 2 2 1/2 1/2 1/2 2 1/2 1/2 1/2
Ghost|50 / Water|50 1/2 2 2 1/2 1/2 2 1/2 1/2 2 1/2
Ghost|50 / Dark Magic|50 1/4 1/2 1/2 1/2 1/2 1/2 1/4 1/2 1/2 1/2 1/2 1/4
Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
Sand|50 / Normal|50 1/2 1/2 1/2 2 1/2 2
Sand|50 / Electric|50 1/4 1/2 2
Sand|50 / Ghost|50 1/2 1/2 2 1/2 2 1/2 1/2 1/2
Sand|50 / Fire|50 1/2 1/2 1/2 1/2 4 1/2 1/2 2
Sand|50 / Ice|50 1/2 1/2 2 1/2 1/2 2 1/2 1/2
Sand|50 / Water|50 1/4 1/2 2
Sand|50 / Dark Magic|50 1/2 1/4 1/2 1/4 1/2 1/2 1/2 1/4 1/2 1/2 1/2 1/2
Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
Fire|50 / Normal|50 1/2 1/2 1/2 2 1/2 2 2
Fire|50 / Electric|50 1/2 2 1/2 1/2 1/2 2 2
Fire|50 / Ghost|50 1/2 2 1/2 1/2 2 1/2 1/2 2 1/2
Fire|50 / Sand|50 1/2 1/2 1/2 1/2 4 1/2 1/2 2
Fire|50 / Ice|50 1/4 1/2
Fire|50 / Water|50 2 1/2 1/4 2 1/2 2
Fire|50 / Dark Magic|50 1/2 1/2 1/2 1/2 1/4 1/4 1/2 1/2 1/4 1/2 1/2
Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
Ice|50 / Normal|50 1/2 2 1/2 1/2 2 1/2
Ice|50 / Electric|50 1/2 2 2 1/2 1/4 2 1/2 1/2 2
Ice|50 / Ghost|50 1/2 2 2 1/2 1/2 1/2 2 1/2 1/2 1/2
Ice|50 / Sand|50 1/2 1/2 2 1/2 1/2 2 1/2 1/2
Ice|50 / Fire|50 1/4 1/2
Ice|50 / Water|50 2 1/2 1/4 2 2 1/2 1/2
Ice|50 / Dark Magic|50 1/2 1/2 1/2 1/2 1/4 1/4 1/2 1/2 1/4 1/4 1/2
Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
Water|50 / Normal|50 2 1/2 1/2 1/2 2 1/2 2 2
Water|50 / Electric|50 1/2 2 1/4 2 2
Water|50 / Ghost|50 1/2 2 2 1/2 1/2 2 1/2 1/2 2 1/2
Water|50 / Sand|50 1/4 1/2 2
Water|50 / Fire|50 2 1/2 1/4 2 1/2 2
Water|50 / Ice|50 2 1/2 1/4 2 2 1/2 1/2
Water|50 / Dark Magic|50 1/2 1/2 1/4 1/4 1/4 1/2 1/2 1/2 1/2 1/2
Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
Dark Magic|50 / Normal|50 1/2 1/2 1/4 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2
Dark Magic|50 / Electric|50 1/2 1/4 1/2 1/2 1/2 1/4 1/2 1/2 1/2 1/2 1/2
Dark Magic|50 / Ghost|50 1/4 1/2 1/2 1/2 1/2 1/2 1/4 1/2 1/2 1/2 1/2 1/4
Dark Magic|50 / Sand|50 1/2 1/4 1/2 1/4 1/2 1/2 1/2 1/4 1/2 1/2 1/2 1/2
Dark Magic|50 / Fire|50 1/2 1/2 1/2 1/2 1/4 1/4 1/2 1/2 1/4 1/2 1/2
Dark Magic|50 / Ice|50 1/2 1/2 1/2 1/2 1/4 1/4 1/2 1/2 1/4 1/4 1/2
Dark Magic|50 / Water|50 1/2 1/2 1/4 1/4 1/4 1/2 1/2 1/2 1/2 1/2
Normal|50 Electric|50 Ghost|50 Sand|50 Fire|50 Ice|50 Water|50 Magic|50 Foul|50 Heavy|50 Air|50 Poison|50 Cut|50 Dark Magic|50
import functools
import itertools
from pathlib import Path
import numpy as np
import sympy
cur_dir = Path(__file__).resolve().absolute().parent
type_list_atk = [
'Normal',
'Electric',
'Ghost',
'Sand',
'Fire',
'Ice',
'Water',
'Magic',
'Foul',
'Heavy',
'Air',
'Poison',
'Cut',
'Dark Magic',
]
type_list_skill_only = set([
'Magic',
'Foul',
'Heavy',
'Air',
'Poison',
'Cut',
])
type_list_def = [
_type
for _type in type_list_atk
if _type not in type_list_skill_only
]
type_atk_index_map = {
type_name: idx
for idx, type_name in enumerate(type_list_atk)
}
type_def_index_map = {
type_name: idx
for idx, type_name in enumerate(type_list_def)
}
type_icon_map_local = {
'Normal': 'Normal.webp',
'Electric': 'Electric.webp',
'Ghost': 'Ghost.webp',
'Sand': 'Sand.webp',
'Fire': 'Fire.webp',
'Ice': 'Ice.webp',
'Water': 'Water.webp',
'Magic': 'Magic.webp',
'Foul': 'Foul.webp',
'Heavy': 'Heavy.png',
'Air': 'Air.webp',
'Poison': 'Poison.webp',
'Cut': 'Cut.webp',
'Dark Magic': 'Dark_Magic.webp',
}
type_icon_map_web = {
'Normal': 'https://coromon.wiki.gg/images/f/fb/Normal.png',
'Electric': 'https://coromon.wiki.gg/images/2/2f/Electric.png',
'Ghost': 'https://coromon.wiki.gg/images/a/ab/Ghost.png',
'Sand': 'https://coromon.wiki.gg/images/a/a7/Sand.png',
'Fire': 'https://coromon.wiki.gg/images/3/30/Fire.png',
'Ice': 'https://coromon.wiki.gg/images/7/77/Ice.png',
'Water': 'https://coromon.wiki.gg/images/9/9d/Water.png',
'Magic': 'https://coromon.wiki.gg/images/f/f7/Magic.png',
'Foul': 'https://coromon.wiki.gg/images/9/93/Foul.png',
'Heavy': 'https://coromon.wiki.gg/images/0/08/Heavy.png',
'Air': 'https://coromon.wiki.gg/images/5/5f/Air.png',
'Poison': 'https://coromon.wiki.gg/images/0/05/Poison.png',
'Cut': 'https://coromon.wiki.gg/images/8/8f/Cut.png',
'Dark Magic': 'https://coromon.wiki.gg/images/9/91/Dark_Magic.png',
}
half_coef = sympy.S.Half
double_coef = 2*sympy.S.One
def build_type_row(**kwargs):
row = np.array(
[sympy.S.One for _ in type_list_def],
dtype=sympy.Rational,
)
for idx, type_name in enumerate(type_list_def):
if type_name in kwargs:
row[idx] = kwargs[type_name]
return row
dark_magic_resist = { 'Dark Magic': half_coef }
single_type_chat = {
'Normal':build_type_row(Ghost=half_coef, **dark_magic_resist),
'Electric': build_type_row(
Electric=half_coef, Sand=half_coef,
Water=double_coef,
**dark_magic_resist,
),
'Ghost': build_type_row(
Normal=half_coef,
Ghost=double_coef,
**dark_magic_resist,
),
'Sand': build_type_row(
Sand=half_coef, Water=half_coef,
Electric=double_coef,
**dark_magic_resist,
),
'Fire': build_type_row(
Fire=half_coef, Water=half_coef,
Ice=double_coef,
**dark_magic_resist,
),
'Ice': build_type_row(
Fire=half_coef, Ice=half_coef,
Water=double_coef,
**dark_magic_resist,
),
'Water': build_type_row(
Electric=half_coef, Ice=half_coef, Water=half_coef,
Sand=double_coef,Fire=double_coef,
**dark_magic_resist,
),
'Magic': build_type_row(
Ghost=half_coef,
**dark_magic_resist,
),
'Foul': build_type_row(
Sand=half_coef,
Water=double_coef,
**dark_magic_resist,
),
'Heavy': build_type_row(
Fire=half_coef,
Ice=double_coef,
**dark_magic_resist,
),
'Air': build_type_row(
Ice=half_coef,
Fire=double_coef,
**dark_magic_resist,
),
'Poison': build_type_row(
Ice=half_coef,
Normal=double_coef,
**dark_magic_resist,
),
'Cut': build_type_row(
Ghost=half_coef,
Electric=double_coef,
**dark_magic_resist,
),
'Dark Magic': build_type_row(),
}
def convert_row_array_to_table_str(row, latex_render=False):
return [
''
if val == sympy.S.One
else (
f'${sympy.latex(val)}$' if latex_render else f'{val}'
)
for val in row
]
def build_icon_cell_entry(type_name, mode='local-icon'):
if mode == 'text':
return type_name
if mode == 'local-icon':
return f'![[{type_icon_map_local[type_name]}\|50]]'
if mode == 'web-icon':
return '![{}\|50]({})'.format(
type_name,
type_icon_map_web[type_name],
)
raise Exception('no icon created')
def build_icon_row(first_col_label, col_type_list):
header_list = [
first_col_label,
*[
build_icon_cell_entry(type_name)
for type_name in col_type_list
]
]
header = '|{}|'.format(' | '.join(header_list))
return header
def build_markdown_preamble(corner_label='', col_type_list=None):
output_list = [
build_icon_row(
first_col_label=corner_label,
col_type_list=col_type_list,
)
]
row_col_align_list = [
' :---: '
for _ in range(len(col_type_list)+1)
]
output_list.append(
'|{}|'.format('|'.join(row_col_align_list))
)
return output_list
def build_markdown_single_type_chart():
output_list = [
*build_markdown_preamble(
corner_label=r'ATK Type \\ DEF Type',
col_type_list=type_list_def,
)
]
for type_name in type_list_atk:
row_list = [
build_icon_cell_entry(type_name),
*convert_row_array_to_table_str(single_type_chat[type_name])
]
output_list.append('|{}|'.format(' | '.join(row_list)))
print('\n'.join(output_list))
def build_multi_type_def_row(*def_types):
row = np.array(
[
functools.reduce(
lambda left, right: left*right,
[
single_type_chat[atk_type][type_def_index_map[def_type]]
for def_type in def_types
],
sympy.S.One,
)
for atk_type in type_list_atk
],
dtype=sympy.Rational,
)
return convert_row_array_to_table_str(row)
def build_markdown_double_type_chart():
output_list = [
*build_markdown_preamble(
corner_label=r'DEF Type 1 / DEF Type 2 \\ ATK Type',
col_type_list=type_list_atk,
)
]
for type1 in type_list_def:
for type2 in type_list_def:
if type1 == type2:
continue
row_list = [
'{} / {}'.format(
build_icon_cell_entry(type1),
build_icon_cell_entry(type2),
),
*build_multi_type_def_row(type1, type2),
]
output_list.append('|{}|'.format(' | '.join(row_list)))
output_list.append(build_icon_row('', col_type_list=type_list_atk))
filepath = cur_dir.parent / 'type-charts' / 'dual-type-chart.md'
with filepath.open('w') as fsteam:
print('', file=fsteam)
print('\n'.join(output_list), file=fsteam)
def build_markdown_triple_type_chart():
type_comb_set = set()
output_list = [
*build_markdown_preamble(
corner_label=r'DEF Type 1 / DEF Type 2 / DEF Type 3 \\ ATK Type',
col_type_list=type_list_atk,
)
]
rows_since_divider = 0
display_divider_inner_threshold = 7
display_divider_outer_threshold = 1
for type1 in type_list_def:
for type2 in type_list_def:
for type3 in type_list_def:
if len(set([type1, type2, type3])) < 3:
continue
type_key = tuple(sorted([type1, type2, type3]))
if type_key in type_comb_set:
continue
type_comb_set.add(type_key)
row_list = [
'{} / {} / {}'.format(
build_icon_cell_entry(type1),
build_icon_cell_entry(type2),
build_icon_cell_entry(type3),
),
*build_multi_type_def_row(type1, type2, type3),
]
output_list.append('|{}|'.format(' | '.join(row_list)))
rows_since_divider += 1
if rows_since_divider >= display_divider_inner_threshold:
output_list.append(build_icon_row('', col_type_list=type_list_atk))
rows_since_divider = 0
if rows_since_divider >= display_divider_outer_threshold:
output_list.append(build_icon_row('', col_type_list=type_list_atk))
rows_since_divider = 0
# always add to last row if not there
if rows_since_divider > display_divider_outer_threshold:
output_list.append(build_icon_row('', col_type_list=type_list_atk))
filepath = cur_dir.parent / 'type-charts' / 'triple-type-chart.md'
with filepath.open('w') as fsteam:
print('', file=fsteam)
print('\n'.join(output_list), file=fsteam)
def main():
build_markdown_single_type_chart()
build_markdown_double_type_chart()
build_markdown_triple_type_chart()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment