X-Git-Url: http://git.sourceforge.jp/view?p=amulettoolsmh4%2Fmain.git;a=blobdiff_plain;f=model%2Falchemysimulator.py;fp=model%2Falchemysimulator.py;h=2a312f36f4a85af39d23122337963aed06b205c4;hp=0000000000000000000000000000000000000000;hb=beccdde4ee3b2ff6708703d0ed0deafe26cd9374;hpb=a11787013be465e05af70af6983a70947a143ab4 diff --git a/model/alchemysimulator.py b/model/alchemysimulator.py new file mode 100644 index 0000000..2a312f3 --- /dev/null +++ b/model/alchemysimulator.py @@ -0,0 +1,248 @@ +# -*- coding: utf-8 -*- + +u""" +錬金のシミュレータ +2013/12/19 written by kei9 +""" + +# import modules +import sqlite3 + +import mh4constnumbers +from randomgenerator import RandomGenerator +from skillminmaxtable import SkillMinMaxTableAccessor +from skilltable import SkillTableAccessor +from amulettable import AmuletTableAccessor +from sufficienttable import SufficientTableAccessor +import singleton + +class AlchemySimulator(object): + u""" 特定Seed1,2から生じる錬金結果を模擬するクラス """ + __metaclass__ = singleton.Singleton + def __init__(self, db_cursor): + u""" 錬金結果の模擬クラス """ + self._cursor = db_cursor + acc_minmax = SkillMinMaxTableAccessor(db_cursor) + acc_skill = SkillTableAccessor(db_cursor) + acc_amulet = AmuletTableAccessor(db_cursor) + self._acc_suff = SufficientTableAccessor(db_cursor) + self._skill_id2name, self._skill_name2id = acc_skill.get_dict() + self._amu_id2name, self._amu_name2id = acc_amulet.get_dict() + self._minmax_dict = acc_minmax.get_minmax_by_id() + + def _get_skill_value(self, rand1, rand2, skill_max, skill_min): + u""" 与えられた2つの乱数値とスキルの最大、最小値からスキル値を計算する """ + value = (rand1 ^ rand2) % (skill_max - skill_min + 1) + skill_min # XOR + return value + + def alchemy_nazo_id(self, seed1, seed2): + u""" なぞの錬金 + return (skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name) + """ + gen_c = RandomGenerator(seed1) # generator C + gen_d = RandomGenerator(seed2) # generator D + return self._judge(gen_c, gen_d, mh4constnumbers.NAME_AMULET0) # nazo + + def alchemy_nazo_name(self, seed1, seed2): + u""" なぞの錬金 + return (skill1_name, skill1_val, skill2_name, skill2_val, slot_num, type_name) + """ + val = self.alchemy_nazo_id(seed1, seed2) + skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name = val + if skill2_id in self._skill_id2name: + return (self._skill_id2name[skill1_id], skill1_val, + self._skill_id2name[skill2_id], skill2_val, slot_num, type_name) + else: + return (self._skill_id2name[skill1_id], skill1_val, u"", 0, slot_num, type_name) + + def alchemy_komyou_id(self, seed1, seed2): + u""" 光明の錬金 + return (skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name) + """ + gen_c = RandomGenerator(seed1) # generator C + gen_d = RandomGenerator(seed2) # generator D + return self._judge(gen_c, gen_d, mh4constnumbers.NAME_AMULET1) # komyou + + def alchemy_komyou_name(self, seed1, seed2): + u""" 光明の錬金 + return (skill1_name, skill1_val, skill2_name, skill2_val, slot_num, type_name) + """ + val = self.alchemy_komyou_id(seed1, seed2) + skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name = val + if skill2_id in self._skill_id2name: + return (self._skill_id2name[skill1_id], skill1_val, + self._skill_id2name[skill2_id], skill2_val, slot_num, type_name) + else: + return (self._skill_id2name[skill1_id], skill1_val, u"", 0, slot_num, type_name) + + def alchemy_inishie_id(self, seed1, seed2): + u""" いにしえの錬金 + return (skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name) + """ + gen_c = RandomGenerator(seed1) # generator C + gen_d = RandomGenerator(seed2) # generator D + return self._judge(gen_c, gen_d, mh4constnumbers.NAME_AMULET2) # inishie + + def alchemy_inishie_name(self, seed1, seed2): + u""" いにしえの錬金 + return (skill1_name, skill1_val, skill2_name, skill2_val, slot_num, type_name) + """ + val = self.alchemy_inishie_id(seed1, seed2) + skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name = val + if skill2_id in self._skill_id2name: + return (self._skill_id2name[skill1_id], skill1_val, + self._skill_id2name[skill2_id], skill2_val, slot_num, type_name) + else: + return (self._skill_id2name[skill1_id], skill1_val, u"", 0, slot_num, type_name) + + def alchemy_tenun_id(self, seed1, seed2, alchemy_type): + u""" 天運の錬金 (古*3または歪*3限定。) + return list of (skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name) + """ + if alchemy_type == mh4constnumbers.KEY_TENUN555: + result_num_max = mh4constnumbers.TENUN555_MAX + result_num_min = mh4constnumbers.TENUN555_MIN + yuga_divisor = mh4constnumbers.TENUN555_DIVISOR + elif alchemy_type == mh4constnumbers.KEY_TENUN888: + result_num_max = mh4constnumbers.TENUN888_MAX + result_num_min = mh4constnumbers.TENUN888_MIN + yuga_divisor = mh4constnumbers.TENUN888_DIVISOR + else: + raise NotImplementedError(u"Irregular Alchemy Type!") + + gen_a = RandomGenerator(seed1) # generator A + gen_b = RandomGenerator(seed2) # generator B + + result_num = gen_a.get_next() % (result_num_max - result_num_min + 1) + result_num_min + result_list = [] + + for i in range(result_num): + s1 = gen_a.get_next() + s2 = gen_b.get_next() + amulet_type = s1 % yuga_divisor + if 0 <= amulet_type < 10: + u""" 謎のお守り """ + amulet_name = mh4constnumbers.NAME_AMULET0 + elif 10 <= amulet_type < 55: + u""" 光るお守り """ + amulet_name = mh4constnumbers.NAME_AMULET1 + elif 55 <= amulet_type < 85: + u""" 古びたお守り """ + amulet_name = mh4constnumbers.NAME_AMULET2 + elif 85 <= amulet_type < 100: + u""" 歪んだお守り """ + amulet_name = mh4constnumbers.NAME_AMULET3 + else: + raise NotImplementedError(u"Divisor must be incorrect") + + gen_c = RandomGenerator(s1) # generator C + gen_d = RandomGenerator(s2) # generator D + + result_list.append(self._judge(gen_c, gen_d, amulet_name)) + return result_list + + def alchemy_tenun_name(self, seed1, seed2, alchemy_type): + u""" 天運の錬金(古*3または歪*3限定。) + return list of (skill1_name, skill1_val, skill2_name, skill2_val, slot_num, type_name) + """ + result_list = [] + result = self.alchemy_tenun_id(seed1, seed2, alchemy_type) + for skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name in result: + if skill2_id in self._skill_id2name: + result_list.append( + (self._skill_id2name[skill1_id], skill1_val, + self._skill_id2name[skill2_id], skill2_val, slot_num, type_name)) + else: + result_list.append((self._skill_id2name[skill1_id], skill1_val, u"", 0, slot_num, type_name)) + + return result_list + + def _judge(self, gen_c, gen_d, amulet_name): + u""" 乱数生成器C,Dおよびお守りの種類から鑑定を行う + return (skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name) + """ + amulet_id = self._amu_name2id[amulet_name] + skill1_minmax, skill2_minmax = self._minmax_dict[amulet_id] + s1 = gen_c.get_next() # for skill1 dicision + s1 %= len(skill1_minmax) # skill1_pos + skill1_id = [x for i,x in enumerate(sorted(skill1_minmax.keys())) if i == s1][0] + min1, max1 = skill1_minmax[skill1_id] + + x1 = gen_c.get_next() + x2 = gen_d.get_next() + skill1_val = (x1 ^ x2) % (max1 - min1 + 1) + min1 # XOR + + y1 = gen_c.get_next() + y2 = gen_d.get_next() + border = mh4constnumbers.SKILL2_BORDER_DICT[amulet_name] + + if (y1 ^ y2) % 100 >= border: # decide skill2 to exist + s2 = gen_d.get_next() # for skill2 dicision + s2 %= len(skill2_minmax) # skill2_pos + skill2_id = [x for i,x in enumerate(sorted(skill2_minmax.keys())) if i == s2][0] + min2, max2 = skill2_minmax[skill2_id] + + if min2 < 0: + z0 = gen_c.get_next() + else: + z0 = None + + z1 = gen_c.get_next() + z2 = gen_d.get_next() + if min2 < 0 and z0 % 2 == 0: # skill2 val is minus + skill2_val = (z1 ^ z2) % (1 - min2) + min2 + else: # skill2 val is plus + skill2_val = (z1 ^ z2) % max2 + 1 + + if skill2_id == skill1_id or skill2_val == 0: + skill2_id = None + skill2_val = 0 + else: + skill2_id = None + skill2_val = 0 + + # slot number + if skill2_val <= 0: + suff_val = (skill1_val * 10) // max1 + else: + suff_val = (skill1_val * 10) // max1 + (skill2_val * 10) // max2 + + w = gen_c.get_next() + if (w & mh4constnumbers.SEED_DECIDE_FLAG) != 0: # falg = 128, 50% + w2 = gen_c.get_next() + else: + w2 = gen_d.get_next() + _slot = w2 % 100 + + th1_slot, th2_slot, th3_slot = self._acc_suff.select_thresholds_by_id(amulet_id, suff_val) + if _slot < th1_slot: + slot_num = 0 + slot_point = mh4constnumbers.SLOT_POINT0 + elif th1_slot <= _slot < th2_slot: + slot_num = 1 + slot_point = mh4constnumbers.SLOT_POINT1 + elif th2_slot <= _slot < th3_slot: + slot_num = 2 + slot_point = mh4constnumbers.SLOT_POINT2 + elif th3_slot <= _slot: + slot_num = 3 + slot_point = mh4constnumbers.SLOT_POINT3 + + type_name = self._decide_amulet_type(suff_val, slot_point, amulet_name) + + return (skill1_id, skill1_val, skill2_id, skill2_val, slot_num, type_name) + + + def _decide_amulet_type(self, suff_val, slot_point, amulet_name): + u""" 鑑定結果の護石名を充足値、スロットポイント、お守り名から決定する """ + type_val = suff_val + slot_point + + border1, border2, border3 = mh4constnumbers.TYPE_BORDER_DICT[amulet_name] + if type_val >= border3[0]: + return border3[1] + elif type_val >= border2[0]: + return border2[1] + elif type_val >= border1[0]: # 0 + return border1[1] + else: + return None