This commit is contained in:
2022-06-30 22:19:59 +08:00
parent f424be4a1d
commit a579b5334e
9 changed files with 773 additions and 0 deletions

156
find_recipe.py Normal file
View File

@@ -0,0 +1,156 @@
from base64 import decode
from utils import load_dict
from colors import colors, colornames, decode_color
import math
def calculate_leather_color(recipes):
cache = {}
for layer in recipes:
for color in recipes[layer]:
cache[color] = {
"color": decode_color(color),
"step": layer
}
return cache
def color_distance(c1, c2):
return sum([abs(x - y) for x, y in zip(c1, c2)])
def find_closest_color(cache, color, max_step=-1):
min_dist = 10000
closest_color = None
for name, this_color in cache.items():
if max_step > 0 and this_color['step'] > max_step:
continue
this_dist = color_distance(color, this_color['color'])
if this_dist < min_dist:
min_dist = this_dist
closest_color = name
return closest_color, min_dist
def decode_recipe(encoded):
encoded = int(encoded, base=16)
counts = []
while len(counts) < 16:
counts.append(encoded%9)
encoded //=9
return {name:count for name, count in zip(colornames, counts) if count > 0}
def query_recipe(recipes, name):
# search color layer.
recipe = None
for layer in recipes:
recipe = recipes[layer].get(name, None)
if recipe is not None:
break
if recipe is None:
raise ValueError('Color not craftable.')
base_color, recipe = recipe
recipe = decode_recipe(recipe)
if base_color == '#000000':
return [recipe]
else:
steps = query_recipe(recipes, base_color)
steps.append(recipe)
return steps
def explain_recipe(steps):
infos = []
for i, step in enumerate(steps):
info = ','.join(['{0}*{1}'.format(colors[name]['name'], count) for name, count in step.items()])
infos.append(info)
print('->'.join(infos))
def calculate_multipler(diff, enchant=False):
diff = 256 if diff > 256 else diff
multiplier = None
if enchant:
multiplier = 1 - (0.50) * (256.0 - diff)*0.5 / 256.0
else:
multiplier = 1 - (0.50) * (256.0 - diff) / 256.0
multiplier = multiplier * math.log(80) / math.log(125) # single cloth.
return multiplier
def show_protection(diff):
print('============= 减伤系数 =============')
multiplier = calculate_multipler(diff, enchant=False)
multiplier_full = multiplier**4
multiplier_elytra = multiplier**3 * math.log(432) / math.log(125)
info = '\n'.join([
"无附魔情况下,单件衣服减伤系数为:{0}".format(multiplier),
"无附魔情况下,全套衣服减伤系数为:{0}".format(multiplier_full),
"无附魔情况下,三件衣服+鞘翅减伤系数为:{0}".format(multiplier_elytra),
])
print(info)
multiplier = calculate_multipler(diff, enchant=True)
multiplier_full = multiplier**4
multiplier_elytra = multiplier**3 * math.log(432) / math.log(125)
info = '\n'.join([
"有附魔情况下,单件衣服减伤系数为:{0}".format(multiplier),
"有附魔情况下,全套衣服减伤系数为:{0}".format(multiplier_full),
"有附魔情况下,三件衣服+鞘翅减伤系数为:{0}".format(multiplier_elytra),
])
print(info)
print('在有保护类附魔存在时实际减伤表格如下所示。其中横排分别表示单件、全套、有鞘翅三种情况纵列分别表示保护系数为0/1/2/3/4/5')
print('(保护系数的计算上限为5其中保护四记为1火焰、爆炸、弹射物保护对其对应的伤害时记为2摔落保护对摔落保护记为3每件衣服的保护系数可以直接相加且上限为5超过5记为5)')
multiplier_protection = [1 - x*4/25 for x in range(6)]
multiplier_protect_enchant = [multiplier*this_protection for this_protection in multiplier_protection]
multiplier_full_protect_enchant = [multiplier_full*this_protection for this_protection in multiplier_protection]
multiplier_elytra_protect_enchant = [multiplier_elytra*this_protection for this_protection in multiplier_protection]
info = '\n'.join([
' '.join(['%.4f']*6)%tuple(multiplier_protect_enchant),
' '.join(['%.4f']*6)%tuple(multiplier_full_protect_enchant),
' '.join(['%.4f']*6)%tuple(multiplier_elytra_protect_enchant)
])
print(info)
if __name__ == '__main__':
print('正在加载配方数据...')
recipes = load_dict('./recipes.json')
print('配方数据库加载完成!正在准备数据...')
leather_color_cache = calculate_leather_color(recipes)
print('数据准备完毕,共加载{0}种可合成颜色。'.format(len(leather_color_cache)))
note = '\n'.join(
[
'请输入你的幸运色,用空格分隔。',
'如你的幸运色为100 200 100, 请输入 100 200 100。',
'默认所有颜色可用,若你希望限制合成的步骤数量,可以在幸运色后追加一个数字表示每种颜色的最大合成步骤',
'如 100 200 100 2 表示给出的配方中最多进行两次合成。'
])
print(note)
while True:
luckycolor = None
max_step = -1
while luckycolor is None:
try:
luckycolor_str = input('>>> ')
luckycolor = luckycolor_str.split()
luckycolor = [int(x) for x in luckycolor]
if len(luckycolor) < 3 or len(luckycolor) > 4:
raise ValueError
if len(luckycolor) == 4:
max_step = luckycolor[3]
luckycolor = luckycolor[:3]
except Exception:
print('幸运色颜色格式错误qwq')
luckycolor = None
print('正在寻找最接近的可合成颜色...')
name, dist = find_closest_color(leather_color_cache, luckycolor, max_step=max_step)
color = decode_color(name)
print('最接近的可合成颜色为: {0}{1},曼哈顿距离误差为:{2}'.format(
name, tuple(color), dist
))
show_protection(dist)
print('查找配方中...')
crafting_steps = query_recipe(recipes, name)
print('合成配方如下:')
explain_recipe(crafting_steps)