def new_yuukouhai_explore(shanten_suu, janshi, taku): hash_table = taku.hash_table #tehai = np.array(function.tehai_convert(janshi.tehai)) #ツモって来る牌に赤ドラは考慮しない yama = np.array( function.tehai_convert( function.akadora_convert(janshi.vertual_yama)[0])) init_shanten_suu = shanten_suu #index_list = [0]*len(tehai) sum_val = 0 #mean_list = [0]*len(tehai) #hai_list = find_yuukou_sutehai(janshi, init_shanten_suu, hash_table) #print(hai_list) #print(hai_list) if init_shanten_suu >= 3: itr = 15 else: itr = 25 for j in range(itr): count = 1. temp_janshi = copy.deepcopy(janshi) if len(temp_janshi.fuurohai) == 0: temp_janshi.riichi = 1 temp_yama = yama.copy() sum_val += yuukouhai_explore(temp_yama, init_shanten_suu, count, hash_table, temp_janshi, taku) sum_val /= float(itr) return sum_val
def new_yuukouhai_explore(shanten_suu, janshi, taku): hash_table = taku.hash_table tehai = np.array(function.tehai_convert(janshi.tehai)) #ツモって来る牌に赤ドラは考慮しない yama = np.array( function.tehai_convert( function.akadora_convert(janshi.vertual_yama)[0])) init_shanten_suu = shanten_suu #index_list = [0]*len(tehai) sum_list = [0] * len(tehai) #mean_list = [0]*len(tehai) hai_list = find_yuukou_sutehai(janshi, init_shanten_suu, hash_table) #print(hai_list) #副露した時でアガリ役なしの場合 if len(hai_list) == 0: return random.choice(range(len(janshi.tehai))), 0 #バグ防止用 for i in hai_list: sum_list[i] += 0.001 #print(hai_list) itr = 25 for i in hai_list: for j in range(itr): count = 1. temp_janshi = copy.deepcopy(janshi) temp_tehai = tehai.copy() temp_yama = yama.copy() temp_tehai[i] -= 1 temp_janshi.tehai = function.tehai_convert_reverse(temp_tehai) a = yuukouhai_explore(temp_yama, init_shanten_suu, count, hash_table, temp_janshi, taku) #index_list[i] += 1 sum_list[i] += a sum_list[i] /= float(itr) #for i in range(len(tehai)): # mean_list[i] = sum_list[i]/float(itr) maximum_index_num = -1 #print(janshi.tehai) #print(np.round(sum_list,2)) maximum_expect = np.max(sum_list) return_hai_str = function.hai_convert_reverse(np.argmax(sum_list)) #print(return_hai_str) for i in range(len(janshi.tehai)): if janshi.tehai[i] == return_hai_str: maximum_index_num = i break #print(maximum_index_num) assert maximum_index_num >= 0 return maximum_index_num, maximum_expect
def new_yuukouhai_explore(shanten_suu, janshi, taku, kuikae_list): hash_table = taku.hash_table tehai = np.array(function.tehai_convert(janshi.tehai)) yama = np.array(function.tehai_convert(function.akadora_convert(janshi.vertual_yama)[0])) init_shanten_suu = shanten_suu sum_list = [0]*len(tehai) hai_list = find_yuukou_sutehai(janshi, init_shanten_suu, hash_table) #hai_listからkuikae_listを削除 temp_hai_list = hai_list.copy() for i in range(len(hai_list)): if temp_hai_list[i] in kuikae_list: hai_list.remove(temp_hai_list) #副露した時でアガリ役なしの場合 if len(hai_list) == 0: return random.choice(range(len(janshi.tehai))), 0 #バグ防止用 for i in hai_list: sum_list[i] += 0.001 itr = 25 for j in range(itr): count = 1. for i in hai_list: temp_janshi = copy.deepcopy(janshi) temp_tehai = tehai.copy() temp_yama = yama.copy() temp_tehai[i] -= 1 temp_janshi.tehai = function.tehai_convert_reverse(temp_tehai) a = yuukouhai_explore(temp_yama, init_shanten_suu, count, hash_table, temp_janshi, taku) sum_list[i] += a maximum_index_num = -1 maximum_expect = np.max(sum_list) return_hai_str = function.hai_convert_reverse(np.argmax(sum_list)) for i in range(len(janshi.tehai)): if janshi.tehai[i] == return_hai_str: maximum_index_num = i break assert maximum_index_num >= 0 return maximum_index_num, maximum_expect
def chii_add(self, taku, hai_arr, last_dahai): last_hai = function_tenhou.hai_convert_136_to_str(last_dahai) #tehaiとtehai_136の操作。tehai_136の中にhai_arrのIDがあれば削除 #print(hai_arr) #print(self.tehai_136) for i in range(3): if hai_arr[i] in self.tehai_136: self.tehai_136.remove(hai_arr[i]) self.tehai.remove( function_tenhou.hai_convert_136_to_str(hai_arr[i])) #print(self.tehai_136) #print(self.tehai) #副露リストへの追加 last_hai_index = function.hai_convert( function.akadora_hai_convert(last_hai)) temp = function.akadora_convert( function_tenhou.tehai_convert_136_to_str(hai_arr)) #print(temp) temp_arr_str = temp[0] #print(temp_arr_str) akadora_flag = temp[1] #枚数 hai_arr_index = sorted(function.tehai_convert2(temp_arr_str)) #print(hai_arr_index) #print(last_hai_index) if hai_arr_index[0] == last_hai_index: self.fuurohai.append([1, last_hai_index, 2]) elif hai_arr_index[1] == last_hai_index: self.fuurohai.append([1, last_hai_index, 1]) else: #hai_arr_index[2] == last_hai_index: self.fuurohai.append([1, last_hai_index, 0]) if akadora_flag: self.fuuro_akadora_list.append(True) else: self.fuuro_akadora_list.append(False)
def eval_tehai_point(janshi, taku): #デバッグモード debug_mode = 0 #パラメータ関連 #各シャンテン数に対する平均有効牌枚数 mean_list = [ 4.575752953784895, 12.18668553881974, 23.338351152742664, 40.50627978155267, 60.56931288649266, 77.81782501846193, 100.03097486813587 ] shanten_bonus = 5 yuukouhai_bonus = 2.0 yuukouhai_pow_const = 1.0 dora_bonus0 = 1.1 #ドラインデックスの牌 dora_bonus1 = 0.6 #ドラインデックス前後の牌 dora_bonus2 = 0.3 #ドラインデックスから2枚離れた牌 yakuhai_bonus = [0, 0.2, 0.7, 1.2] #0枚~3枚以上 ryanmen_bonus = 0.3 penchan_penalty = -0.5 koritsu_yaochu_penalty = -0.25 #1,9 koritsu_suuhai_penalty2 = -0.05 #2,8 koritsu_suuhai_penalty3 = -0.01 #3~7 koritsu_jihai_penalty = -0.33 koritsu_nokori_yakuhai_penalty = [-0.5, -0.35, -0.2, 0.0] toitsu_nokori_yakuhai_penalty = [-1.2, -0.7, 0.0, 0.0] koritsu_nokori_jihai_penalty = [-0.3, -0.2, -0.1, 0.0] toitsu_nokori_jihai_penalty = [-0.4, -0.3, 0.0, 0.0] tanyao_bonus = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.3, 0.6, 1.0] ittsuu_bonus = [0, 0, 0, 0, 0, 0, 0.2, 0.7, 1.1, 1.4] sansyoku_bonus = [0, 0, 0, 0, 0, 0, 0.2, 0.8, 1.2, 1.6] honitsu_bonus = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 1.0, 2.0, 3.0] yipeko_param1 = 1.0 #222 yipeko_param2 = 0.8 #122, 221 yipeko_param3 = 0.6 #212 yipeko_param4 = 0.5 #212(1,9含む) yipeko_param5 = 0.4 #221, 122(1,9含む) furiten_penalty = [-0.2, -0.5, -0.2] furiten_penalty_for_yuukouhai = -0.4 mentsu_bonus = 1.0 #メイン eval_point_list = [0] * len(janshi.tehai) old_shanten_suu = shanten_check_new.shanten_check(janshi, taku.hash_table) for i in range(len(janshi.tehai)): if debug_mode: print("捨てる牌: " + janshi.tehai[i]) #コピーして手牌を1つ削除 temp_janshi = copy.deepcopy(janshi) temp_janshi.sutehai.append(temp_janshi.tehai[i]) del temp_janshi.tehai[i] #赤ドラだけ抜き出してあとは赤ナシで考える temp = function.akadora_convert(temp_janshi.tehai) akadora_maisuu = temp[1] temp_janshi.tehai = temp[0] tehai = function.tehai_convert(temp_janshi.tehai) #vertual_yama vertual_yama_index = function.tehai_convert(temp_janshi.vertual_yama) #print(vertual_yama_index) #メンツカウント mentsu_suu = mentsu_count.mentsu_count(temp_janshi) mentsu_point = mentsu_suu * mentsu_bonus eval_point_list[i] += mentsu_point if debug_mode: print("メンツボーナス: " + str(mentsu_point)) #シャンテン数関連 new_shanten_suu = shanten_check_new.shanten_check( temp_janshi, taku.hash_table) if old_shanten_suu == new_shanten_suu: eval_point_list[i] += shanten_bonus if debug_mode: print("シャンテンアップボーナス: " + str(shanten_bonus)) else: if debug_mode: print("シャンテンアップボーナス: " + str(0)) #print(eval_point_list[i]) #有効牌関連 yuukouhai_maisuu = function.calc_yuukouhai_maisuu( temp_janshi, new_shanten_suu, taku.hash_table) yuukouhai_point = ((yuukouhai_maisuu / (len(temp_janshi.vertual_yama) / 123.0 * mean_list[new_shanten_suu]))** yuukouhai_pow_const) * yuukouhai_bonus eval_point_list[i] += yuukouhai_point if debug_mode: print("有効牌ボーナス: " + str(yuukouhai_point)) #print(eval_point_list[i]) #ドラ関連とりあえず1枚の時だけ dora_index = [] dora_hyouji_index = function.tehai_convert2( function.akadora_convert(taku.dorahyouji)[0]).copy() for j in range(len(taku.dorahyouji)): ##まずドラのインデックスを求める if dora_hyouji_index[j] < 30: if dora_hyouji_index[j] % 10 == 9: dora_index.append(dora_hyouji_index[j] - 8) else: dora_index.append(dora_hyouji_index[j] + 1) else: if dora_hyouji_index[j] == 34: dora_index.append(31) elif dora_hyouji_index[j] == 37: dora_index.append(35) else: dora_index.append(dora_hyouji_index[j] + 1) dora_point = 0 #赤ドラ dora_point += akadora_maisuu * dora_bonus0 for j in range(len(dora_index)): if dora_index[j] < 30: if dora_index[j] % 10 == 1: dora_point += tehai[dora_index[j]] * dora_bonus0 dora_point += bool(tehai[dora_index[j] + 1]) * dora_bonus1 dora_point += bool(tehai[dora_index[j] + 2]) * dora_bonus2 elif dora_index[j] % 10 == 2: dora_point += bool(tehai[dora_index[j] - 1]) * dora_bonus2 dora_point += tehai[dora_index[j]] * dora_bonus0 dora_point += bool(tehai[dora_index[j] + 1]) * dora_bonus1 dora_point += bool(tehai[dora_index[j] + 2]) * dora_bonus2 elif dora_index[j] % 10 == 8: dora_point += bool(tehai[dora_index[j] - 2]) * dora_bonus2 dora_point += bool(tehai[dora_index[j] - 1]) * dora_bonus1 dora_point += tehai[dora_index[j]] * dora_bonus0 dora_point += bool(tehai[dora_index[j] + 1]) * dora_bonus2 elif dora_index[j] % 10 == 1: dora_point += tehai[dora_index[j]] * dora_bonus0 dora_point += bool(tehai[dora_index[j] - 1]) * dora_bonus1 dora_point += bool(tehai[dora_index[j] - 2]) * dora_bonus2 else: dora_point += bool(tehai[dora_index[j] - 2]) * dora_bonus2 dora_point += bool(tehai[dora_index[j] - 1]) * dora_bonus1 dora_point += tehai[dora_index[j]] * dora_bonus0 dora_point += bool(tehai[dora_index[j] + 1]) * dora_bonus1 dora_point += bool(tehai[dora_index[j] + 2]) * dora_bonus2 else: dora_point += tehai[dora_index[j]] * dora_bonus0 eval_point_list[i] += dora_point if debug_mode: print("ドラボーナス: " + str(dora_point)) #print(eval_point_list[i]) #役牌 if taku.kaze_honba[0] < 4: bakaze_index = 31 else: bakaze_index = 32 jikaze_index = temp_janshi.kaze + 31 yakuhai_point = 0 yakuhai_point += yakuhai_bonus[tehai[bakaze_index]] yakuhai_point += yakuhai_bonus[tehai[jikaze_index]] yakuhai_point += yakuhai_bonus[tehai[35]] yakuhai_point += yakuhai_bonus[tehai[36]] yakuhai_point += yakuhai_bonus[tehai[37]] #ペナ if tehai[bakaze_index] == 1: yakuhai_point += koritsu_nokori_yakuhai_penalty[ vertual_yama_index[bakaze_index]] elif tehai[bakaze_index] == 2: yakuhai_point += toitsu_nokori_yakuhai_penalty[ vertual_yama_index[bakaze_index]] if tehai[jikaze_index] == 1: yakuhai_point += koritsu_nokori_yakuhai_penalty[ vertual_yama_index[jikaze_index]] elif tehai[jikaze_index] == 2: yakuhai_point += toitsu_nokori_yakuhai_penalty[ vertual_yama_index[jikaze_index]] for j in range(3): if tehai[35 + j] == 1: yakuhai_point += koritsu_nokori_yakuhai_penalty[ vertual_yama_index[35 + j]] elif tehai[35 + j] == 2: yakuhai_point += toitsu_nokori_yakuhai_penalty[ vertual_yama_index[35 + j]] #役牌以外の字牌に対するペナ for j in range(4): if 31 + j != bakaze_index and 31 + j != jikaze_index: if tehai[31 + j] == 1: yakuhai_point += koritsu_nokori_jihai_penalty[ vertual_yama_index[31 + j]] elif tehai[31 + j] == 2: yakuhai_point += toitsu_nokori_jihai_penalty[ vertual_yama_index[31 + j]] eval_point_list[i] += yakuhai_point if debug_mode: print("役牌ボーナス: " + str(yakuhai_point)) #print(eval_point_list[i]) #リャンメンボーナス(テスト) ryanmen_point = 0 for j in range(30): if 2 <= j % 10 <= 7: if tehai[j - 1] == 0 and tehai[j] >= 1 and tehai[ j + 1] >= 1 and tehai[j + 2] == 0: ryanmen_point += ryanmen_bonus eval_point_list[i] += ryanmen_point if debug_mode: print("リャンメンボーナス: " + str(ryanmen_point)) #print(eval_point_list[i]) #ペンチャンペナルティ penchan_point = 0 for j in range(30): if j % 10 == 1 or j % 10 == 8: if tehai[j - 1] == 0 and tehai[j] == 1 and tehai[ j + 1] == 1 and tehai[j + 2] == 0: penchan_point += penchan_penalty elif tehai[j - 1] == 0 and tehai[j] >= 1 and tehai[ j + 1] >= 1 and tehai[j + 2] == 0: penchan_point += penchan_penalty * 0.1 if debug_mode: print("ペンチャンペナルティ: " + str(penchan_point)) eval_point_list[i] += penchan_point #孤立牌ペナルティandフリテンペナルティ koritsu_suuhai_point = 0 koritsu_jihai_point = 0 koritsu_list = function.tehai_koritsu_hantei(temp_janshi.tehai) for j in koritsu_list: koritsu_index = function.hai_convert(temp_janshi.tehai[j]) if koritsu_index < 30: if (koritsu_index % 10 == 2) or (koritsu_index % 10 == 8): koritsu_suuhai_point += koritsu_suuhai_penalty2 elif 3 <= koritsu_index % 10 <= 7: koritsu_suuhai_point += koritsu_suuhai_penalty3 else: koritsu_suuhai_point += koritsu_yaochu_penalty else: koritsu_jihai_point += koritsu_jihai_penalty eval_point_list[i] += koritsu_suuhai_point if debug_mode: print("孤立数牌ペナルティ: " + str(koritsu_suuhai_point)) eval_point_list[i] += koritsu_jihai_point if debug_mode: print("孤立字牌ペナルティ: " + str(koritsu_jihai_point)) #print(eval_point_list[i]) #フリテンペナルティ 孤立牌がフリテン絡みand有効牌がフリテン絡み furiten_point = 0 kawa_no_akadora = function.tehai_convert( function.akadora_convert(temp_janshi.sutehai)[0]) for j in range(len(kawa_no_akadora)): kawa_no_akadora[j] = bool(kawa_no_akadora[j]) #孤立牌に対して for j in koritsu_list: koritsu_index = function.hai_convert(temp_janshi.tehai[j]) if koritsu_index < 30: if 2 <= koritsu_index % 10 <= 8: if kawa_no_akadora[koritsu_index - 2]: furiten_point += furiten_penalty[2] if kawa_no_akadora[koritsu_index - 1]: furiten_point += furiten_penalty[1] if kawa_no_akadora[koritsu_index]: furiten_point += furiten_penalty[0] if kawa_no_akadora[koritsu_index + 1]: furiten_point += furiten_penalty[1] if kawa_no_akadora[koritsu_index + 2]: furiten_point += furiten_penalty[2] elif koritsu_index % 10 == 1: if kawa_no_akadora[koritsu_index]: furiten_point += furiten_penalty[0] if kawa_no_akadora[koritsu_index + 1]: furiten_point += furiten_penalty[1] if kawa_no_akadora[koritsu_index + 2]: furiten_point += furiten_penalty[2] elif koritsu_index % 10 == 9: if kawa_no_akadora[koritsu_index - 2]: furiten_point += furiten_penalty[2] if kawa_no_akadora[koritsu_index - 1]: furiten_point += furiten_penalty[1] if kawa_no_akadora[koritsu_index]: furiten_point += furiten_penalty[0] else: if kawa_no_akadora[koritsu_index]: furiten_point += furiten_penalty[0] #有効牌に対して yuukouhai_index_list = function.find_yuukouhai(temp_janshi, new_shanten_suu, taku.hash_table) for index in yuukouhai_index_list: if kawa_no_akadora[index]: furiten_point += furiten_penalty_for_yuukouhai eval_point_list[i] += furiten_point if debug_mode: print("フリテンペナルティ: " + str(furiten_point)) #タンヤオボーナス tanyao_point = 0 tanyao_sum = function.tanyao_sum_up(temp_janshi) tanyao_point = tanyao_bonus[tanyao_sum] eval_point_list[i] += tanyao_point if debug_mode: print("タンヤオボーナス: " + str(tanyao_point)) #print(eval_point_list[i]) #一通ボーナス ittsuu_point = 0 for j in range(3): ittsuu_point += ittsuu_bonus[function.ittsuu_sum_up( temp_janshi, j)] eval_point_list[i] += ittsuu_point if debug_mode: print("一通ボーナス: " + str(ittsuu_point)) #print(eval_point_list[i]) #三色ボーナス sansyoku_point = 0 for j in range(1, 8): sansyoku_point += sansyoku_bonus[function.sansyoku_sum_up( temp_janshi, j)] eval_point_list[i] += sansyoku_point if debug_mode: print("三色ボーナス: " + str(sansyoku_point)) #ホンイツボーナス honitsu_point = 0 for j in range(3): honitsu_point += honitsu_bonus[function.honitsu_sum_up( temp_janshi, j)] eval_point_list[i] += honitsu_point if debug_mode: print("ホンイツボーナス: " + str(honitsu_point)) #一盃口ボーナス yipeko_point = 0 for j in range(3): yipeko_point += function.yipeko_eval(janshi, j, yipeko_param1, yipeko_param2, yipeko_param3, yipeko_param4, yipeko_param5) eval_point_list[i] += yipeko_point if debug_mode: print("一盃口ボーナス: " + str(yipeko_point)) if debug_mode: print(" トータルポイント: " + str(eval_point_list[i])) print() eval_point_array = np.array(eval_point_list) normalized_eval_point_array = eval_point_array / np.sum(eval_point_array) return normalized_eval_point_array
def new_yuukouhai_explore(shanten_suu, janshi, taku): #print("aaaaaaaaaaaaaaaaaaaaa") global sum_list, pure_point_sum hash_table = taku.hash_table tehai = np.array(function.tehai_convert(janshi.tehai)) #ツモって来る牌に赤ドラは考慮しない yama = np.array( function.tehai_convert( function.akadora_convert(janshi.vertual_yama)[0])) init_shanten_suu = shanten_suu #index_list = [0]*len(tehai) sum_list = [0] * len(tehai) pure_point_sum = [0] * len(tehai) #mean_list = [0]*len(tehai) if shanten_suu >= 2: hai_list = find_yuukou_sutehai(janshi, init_shanten_suu, hash_table) #テンパイならシャンテン戻しも考える else: hai_list = function.tehai_convert3(janshi.tehai) #print(hai_list) #副露した時でアガリ役なしの場合 if len(hai_list) == 0: #print("no_hai_list_error") return [0.001] * len(janshi.tehai), [0.001] * len( janshi.tehai), [0.001] * len(janshi.tehai) #バグ防止用 for i in hai_list: sum_list[i] += 0.001 #print(hai_list) if init_shanten_suu >= 2: itr = 25 elif init_shanten_suu == 1: itr = 20 else: itr = 15 temp_list = [(hai_id, janshi, yama, taku, shanten_suu, pure_point_sum, itr) for hai_id in hai_list] p = Pool(multi.cpu_count()) p.map(test_process, range(1000)) p.close() ''' for i in hai_list: for j in range(itr): count = 1.0 temp_janshi = copy.deepcopy(janshi) #temp_tehai = tehai.copy() temp_yama = yama.copy() #temp_tehai[i] -= 1 temp_janshi.tehai.remove(function.hai_convert_reverse(i)) # = function.tehai_convert_reverse(temp_tehai) temp_janshi.sutehai.append(function.hai_convert_reverse(i)) if j == 0: init_shanten_suu = shanten_check_new.shanten_check(temp_janshi, taku.hash_table) a, b = yuukouhai_explore(temp_yama, init_shanten_suu, count, hash_table, temp_janshi, taku) #index_list[i] += 1 sum_list[i] += a pure_point_sum[i] += b #shanten_suu + 1で平均打点を割る pure_point_sum[i] /= max(init_shanten_suu + 1, 1)*itr ''' #print(np.max(sum_list)) normalized_index_list = np.array(sum_list) / np.sum(np.array(sum_list)) normalized_list = np.zeros(len(janshi.tehai)) sum_list_for_tehai_str = np.zeros(len(janshi.tehai)) pure_point_sum_for_tehai_str = np.zeros(len(janshi.tehai)) for i in range(len(janshi.tehai)): normalized_list[i] = normalized_index_list[function.hai_convert( janshi.tehai[i])] sum_list_for_tehai_str[i] = sum_list[function.hai_convert( janshi.tehai[i])] pure_point_sum_for_tehai_str[i] = pure_point_sum[function.hai_convert( janshi.tehai[i])] sum_list_for_tehai_str = np.array(sum_list_for_tehai_str) mean_list_for_tehai_str = sum_list_for_tehai_str / float(itr) pure_point_sum_for_tehai_str = np.array(pure_point_sum_for_tehai_str) return normalized_list, mean_list_for_tehai_str, pure_point_sum_for_tehai_str
def shanten_check(janshi, hash_table): tehai = function.tehai_convert(function.akadora_convert(janshi.tehai)[0]) fuurosu = len(janshi.fuurohai) + len(janshi.ankan_list) #国士無双形 Sh_kokushi = 13 # ここから1、9、字牌の数を引いていく kokushi_l = [1, 9, 11, 19, 21, 29, 31, 32, 33, 34, 35, 36, 37] kokushi_toitsu = 0 for i in kokushi_l: if tehai[i] >= 1: Sh_kokushi -= 1 if kokushi_toitsu == 0 and tehai[i] >= 2: #1,9、字牌の対子があれば1つだけシャンテン数が下がる kokushi_toitsu = 1 Sh_kokushi -= kokushi_toitsu #七対子形 Sh_chiitoi = 6 #ここから対子の数だけ引く haisyu = 0 #牌の種類 for i in range(0, 38): if tehai[i] >= 1: haisyu += 1 if tehai[i] >= 2: Sh_chiitoi -= 1 if haisyu < 7: Sh_chiitoi += 7 - haisyu #4面子1雀頭形 #tehaiを色ごとにハッシュ化 manzu_hash = 0 #萬子部分のハッシュ値 for i in range(1, 10): manzu_hash = manzu_hash * 5 + tehai[i] pinzu_hash = 0 #筒子部分のハッシュ値 for i in range(11, 20): pinzu_hash = pinzu_hash * 5 + tehai[i] souzu_hash = 0 #索子部分のハッシュ値 for i in range(21, 30): souzu_hash = souzu_hash * 5 + tehai[i] zihai_hash = 0 #字牌部分のハッシュ値 for i in range(31, 38): zihai_hash = zihai_hash * 5 + tehai[i] #各ハッシュ値をキーにハッシュテーブルにある部分置換数t,uを取得 t_manzu = [] #萬子部分の部分置換数tの配列 u_manzu = [] #萬子部分の部分置換数uの配列 for i in range(0, 5): t_manzu.append(int(hash_table[0][manzu_hash].split()[i])) for i in range(5, 10): u_manzu.append(int(hash_table[0][manzu_hash].split()[i])) t_pinzu = [] #筒子部分の部分置換数tの配列 u_pinzu = [] #筒子部分の部分置換数uの配列 for i in range(0, 5): t_pinzu.append(int(hash_table[0][pinzu_hash].split()[i])) for i in range(5, 10): u_pinzu.append(int(hash_table[0][pinzu_hash].split()[i])) t_souzu = [] #索子部分の部分置換数tの配列 u_souzu = [] #索子部分の部分置換数uの配列 for i in range(0, 5): t_souzu.append(int(hash_table[0][souzu_hash].split()[i])) for i in range(5, 10): u_souzu.append(int(hash_table[0][souzu_hash].split()[i])) t_zihai = [] #字牌部分の部分置換数tの配列 u_zihai = [] #字牌部分の部分置換数uの配列 for i in range(0, 5): t_zihai.append(int(hash_table[1][zihai_hash].split()[i])) for i in range(5, 10): u_zihai.append(int(hash_table[1][zihai_hash].split()[i])) t = [t_manzu, t_pinzu, t_souzu, t_zihai] u = [u_manzu, u_pinzu, u_souzu, u_zihai] #計算部分 x = [[0 for m in range(0, 5)] for n in range(0, 4)] y = [[0 for m in range(0, 5)] for n in range(0, 4)] for m in range(0, 5): x[0][m] = t[0][m] y[0][m] = u[0][m] for n in range(1, 4): for m in range(0, 5): x_temp = 15 y_temp = 15 for l in range(0, m + 1): x_temp = min(x_temp, x[n - 1][l] + t[n][m - l]) y_temp = min( y_temp, min(y[n - 1][l] + t[n][m - l], x[n - 1][l] + u[n][m - l])) x[n][m] = x_temp y[n][m] = y_temp Th_temp = 15 for l in range(0, 5 - fuurosu): Th_temp = min( Th_temp, min(x[2][l] + u[3][(4 - fuurosu) - l], y[2][l] + t[3][(4 - fuurosu) - l])) Sh_normal = Th_temp - 1 #最終的なシャンテン数 Shanten_su = min(Sh_normal, Sh_kokushi, Sh_chiitoi) return Shanten_su
def new_yuukouhai_explore(shanten_suu, janshi, taku, kuikae_list, top4_list, janshi_list, bakyou_list): hash_table = taku.hash_table tehai = np.array(function.tehai_convert(janshi.tehai)) danger_degree_list = danger_degree.create_danger_degree_list(janshi_list, taku, bakyou_list) #print(danger_degree_list) #ツモって来る牌に赤ドラは考慮しない yama = np.array(function.tehai_convert(function.akadora_convert(janshi.vertual_yama)[0])) init_shanten_suu = shanten_suu #index_list = [0]*len(tehai) sum_list = [0]*len(tehai) pure_point_sum = [0]*len(tehai) pure_pure_point_sum = [0]*len(tehai) max_point = [0]*len(tehai) #mean_list = [0]*len(tehai) if init_shanten_suu >= 2: hai_list = top4_list else: hai_list = find_yuukou_sutehai(janshi, init_shanten_suu, hash_table) #print(hai_list) #hai_listからkuikae_listを削除 temp_hai_list = hai_list.copy() for i in range(len(hai_list)): if temp_hai_list[i] in kuikae_list: hai_list.remove(temp_hai_list[i]) #副露した時でアガリ役なしの場合 if len(hai_list) == 0: #print("no_hai_list_error") return [0.001]*len(janshi.tehai), [0.001]*len(janshi.tehai), [0.001]*len(janshi.tehai), [0.001]*len(janshi.tehai), [0.001]*len(janshi.tehai), [0.001]*len(janshi.tehai) #バグ防止用 for i in hai_list: sum_list[i] += 0.001 #print(hai_list) if init_shanten_suu >= 2: itr = 20 else: itr = 25 for i in hai_list: for j in range(itr): count = 1. temp_janshi = copy.deepcopy(janshi) temp_yama = yama.copy() temp_janshi.tehai.remove(function.hai_convert_reverse(i)) temp_janshi.sutehai.append(function.hai_convert_reverse(i)) #評価用の修正されたpoint, 普通の点数 a, b, c = yuukouhai_explore(temp_yama, init_shanten_suu, count, hash_table, temp_janshi, taku , janshi_list, bakyou_list, danger_degree_list) #オーラス用max_pointの更新など if b > max_point[i]: max_point[i] = b pure_point_sum[i] += b pure_pure_point_sum[i] += c #index_list[i] += 1 sum_list[i] += a pure_pure_point_sum[i] /= max(init_shanten_suu + 1, 1)*itr normalized_index_list = np.array(sum_list)/np.sum(np.array(sum_list)) normalized_list = np.zeros(len(janshi.tehai)) sum_list_for_tehai_str = np.zeros(len(janshi.tehai)) pure_point_mean = np.array(pure_point_sum)/float(itr) max_point_list = np.zeros(len(janshi.tehai)) pure_point_mean_list = np.zeros(len(janshi.tehai)) pure_point_sum_for_tehai_str = np.zeros(len(janshi.tehai)) for i in range(len(janshi.tehai)): normalized_list[i] = normalized_index_list[function.hai_convert(janshi.tehai[i])] sum_list_for_tehai_str[i] = sum_list[function.hai_convert(janshi.tehai[i])] max_point_list[i] = max_point[function.hai_convert(janshi.tehai[i])] pure_point_mean_list[i] = pure_point_mean[function.hai_convert(janshi.tehai[i])] pure_point_sum_for_tehai_str[i] = pure_pure_point_sum[function.hai_convert(janshi.tehai[i])] mean_list_for_tehai_str = sum_list_for_tehai_str/float(itr) return normalized_list, sum_list_for_tehai_str, mean_list_for_tehai_str, max_point_list, pure_point_mean_list, pure_point_sum_for_tehai_str
def new_yuukouhai_explore(shanten_suu, janshi, taku): #print("aaaaaaaaaaaaaaaaaaaaa") global sum_list, pure_point_sum global janshi_global, yama_global, taku_global, shanten_suu_global, itr_global hash_table = taku.hash_table tehai = np.array(function.tehai_convert(janshi.tehai)) #ツモって来る牌に赤ドラは考慮しない yama = np.array( function.tehai_convert( function.akadora_convert(janshi.vertual_yama)[0])) init_shanten_suu = shanten_suu #index_list = [0]*len(tehai) sum_list = [0] * len(tehai) pure_point_sum = [0] * len(tehai) print(len(sum_list)) #mean_list = [0]*len(tehai) if shanten_suu >= 2: hai_list = find_yuukou_sutehai(janshi, init_shanten_suu, hash_table) #テンパイならシャンテン戻しも考える else: hai_list = function.tehai_convert3(janshi.tehai) #print(hai_list) #副露した時でアガリ役なしの場合 if len(hai_list) == 0: #print("no_hai_list_error") return [0.001] * len(janshi.tehai), [0.001] * len( janshi.tehai), [0.001] * len(janshi.tehai) #バグ防止用 for i in hai_list: sum_list[i] += 0.001 #print(hai_list) if init_shanten_suu >= 2: itr = 25 elif init_shanten_suu == 1: itr = 20 else: itr = 15 itr_global = itr janshi_global = janshi yama_global = yama taku_global = taku taku.hash_table = None shanten_suu_global = shanten_suu temp_list = [[hai_id, janshi, yama, taku, shanten_suu, itr] for hai_id in reversed(hai_list)] p = Pool(multi.cpu_count()) print(multi.cpu_count()) print(hai_list) #print(time.time()) p.starmap(temp_process, temp_list) #p.map(test_process, hai_list) p.close() taku.hash_table = hash_table for i in hai_list: print(i) for j in range(itr): count = 1.0 temp_janshi = copy.deepcopy(janshi) #temp_tehai = tehai.copy() temp_yama = yama.copy() #temp_tehai[i] -= 1 temp_janshi.tehai.remove(function.hai_convert_reverse( i)) # = function.tehai_convert_reverse(temp_tehai) temp_janshi.sutehai.append(function.hai_convert_reverse(i)) if j == 0: init_shanten_suu = shanten_check_new.shanten_check( temp_janshi, taku.hash_table) a, b = yuukouhai_explore(temp_yama, init_shanten_suu, count, hash_table, temp_janshi, taku) #index_list[i] += 1 sum_list[i] += a pure_point_sum[i] += b #shanten_suu + 1で平均打点を割る pure_point_sum[i] /= max(init_shanten_suu + 1, 1) * itr
def eval_defense(janshi, taku, shanten_suu, temp_max, pure_point_list, bakyou_list): janshi_list = copy.deepcopy(janshi) janshi_p = janshi_list[0] nokori_tsumo_kaisuu = int(taku.yama_nokori / 4) vertual_yama = janshi_p.vertual_yama vertual_yama_index = function.tehai_convert(vertual_yama) tehai_len = len(janshi_p.tehai) eval_defense_point = np.zeros(tehai_len) for i in range(1, 4): #とりあえず立直者だけ警戒 if janshi_list[i].riichi: tenpai_prob = 3.0 elif janshi_list[i].fuurosuu != 0: tenpai_prob = janshi_list[i].fuurosuu * 0.1 * math.exp( ((17 - nokori_tsumo_kaisuu) / 17 - 1) * math.sqrt(5)) else: continue #打点期待値を設定 if janshi_list[i].kaze == 0: daten_expect = 10000 else: daten_expect = 7000 #max_pointの設定 #オーラスで最下位なら防御をほとんどしない if bakyou_list[0] == 4: max_point = temp_max * 0.1 else: max_point = temp_max #3シャンテン以上は倍 #if shanten_suu >= 3: # max_point *= 1.0 genbutsu_list = function.akadora_convert( janshi_list[i].sutehai)[0] + function.akadora_convert( janshi_list[i].temp_genbutsu)[0] #危険牌枚数を計上 temp_list = [ "1m", "2m", "3m", "4m", "5m", "6m", "7m", "8m", "9m", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "1z", "2z", "3z", "4z", "5z", "6z", "7z" ] for j in range(len(genbutsu_list)): if genbutsu_list[j] in temp_list: temp_list.remove(genbutsu_list[j]) kikenhai_maisuu = len(temp_list) #save_max_point = max_point #手出しリスト作成 tedashi_list = [] for j in range(len(janshi_list[i].sutehai)): if janshi_list[i].tedashi_flag: tedashi_list.append(janshi_list[i].sutehai[j]) ############メイン######################### max_pure = max(pure_point_list) yuuido = max( (max_pure / (daten_expect * tenpai_prob / kikenhai_maisuu))**0.5, 0.66) print(yuuido) max_point /= yuuido for j in range(tehai_len): hai_index = function.hai_convert(janshi_p.tehai[j]) #現物ならmax_point与えてcontinue temp_hai_str = function.akadora_hai_convert(janshi_p.tehai[j]) if temp_hai_str in genbutsu_list: eval_defense_point[j] += max_point continue #字牌 if hai_index > 30: if vertual_yama_index[hai_index] == 0: eval_defense_point[j] += max_point continue elif vertual_yama_index[hai_index] == 1: eval_defense_point[j] += max_point * 0.8 continue elif vertual_yama_index[hai_index] == 2: eval_defense_point[j] += max_point * 0.5 continue elif vertual_yama_index[hai_index] == 3: eval_defense_point[j] += max_point * 0.2 continue #牌の種類によって減点 if hai_index < 30: if hai_index % 10 == 1 or hai_index % 10 == 9: eval_defense_point[j] -= max_point * 0.1 elif hai_index % 10 == 2 or hai_index % 10 == 2: eval_defense_point[j] -= max_point * 0.2 elif hai_index % 10 == 3 or hai_index % 10 == 4 or hai_index % 10 == 5 or hai_index % 10 == 6 or hai_index % 10 == 7: eval_defense_point[j] -= max_point * 0.3 #赤ドラ else: eval_defense_point[j] -= max_point * 0.5 #筋牌ならば加点。宣言牌の筋は知らん if suji_hantei(genbutsu_list, hai_index): eval_defense_point[j] += max_point * 0.5 #最終手出しおよびその一つ前の手出しのマタギならば減点。マタギは赤ドラを考えない。 matagi_list = matagi_henkan(hai_index) if len(tedashi_list) >= 1: if function.hai_convert(tedashi_list[-1]) in matagi_list: eval_defense_point[j] -= max_point * 0.5 if len(tedashi_list) >= 2: if function.hai_convert(tedashi_list[-2]) in matagi_list: eval_defense_point[j] -= max_point * 0.5 #裏筋ならば減点 urasuji_list = urasuji_henkan(hai_index) sutehai_index_list = function.akadora_convert3( function.tehai_convert3(tedashi_list))[0] for k in range(len(urasuji_list)): if urasuji_list[k] in sutehai_index_list: eval_defense_point[j] -= max_point * 0.4 #序盤に切れた数牌の外側に対して加点 sutehai_len = len(janshi_list[i].sutehai) if sutehai_len > 6: sotohai_list = sotohai_find(janshi_list[i].sutehai, min(int(sutehai_len / 3), 4)) if hai_index in sotohai_list: eval_defense_point[j] += max_point * 0.5 #カベの外側に対して加点 eval_defense_point[j] += max_point * kabe_eval( vertual_yama_index, hai_index) #max_pointに補正 if abs(eval_defense_point[j]) > max_point: eval_defense_point[j] *= max_point / abs(eval_defense_point[j]) return eval_defense_point
def naki(self, m, last_dahai, last_teban): naki_info = decode_m(m) self.fuurosu += 1 self.tsumoHai = -1 #自摸切りかどうかの確認。鳴きなのでリセット。 #アンカン if naki_info[0] == 4: #[1][0]だと赤ドラになる可能性があるため[1][1] self.ankan_list.append(convert_mjlog_to_index(naki_info[1][1])) for h in naki_info[1]: if h in self.tehai: self.tehai.remove(h) #チー elif naki_info[0] == 3: hai_arr = naki_info[1] #tehaiから鳴きに使った牌の削除 for h in naki_info[1]: if h in self.tehai: self.tehai.remove(h) #副露リストへの追加 last_hai_index = convert_mjlog_to_index(int(last_dahai)) temp = function.akadora_convert( function_tenhou.tehai_convert_136_to_str(hai_arr)) temp_arr_str = temp[0] akadora_flag = temp[1] hai_arr_index = sorted(function.tehai_convert2(temp_arr_str)) if hai_arr_index[0] == last_hai_index: self.fuurohai.append([1, last_hai_index, 2]) elif hai_arr_index[1] == last_hai_index: self.fuurohai.append([1, last_hai_index, 1]) else: #hai_arr_index[2] == last_hai_index: self.fuurohai.append([1, last_hai_index, 0]) if akadora_flag: self.fuuro_akadora_list.append(True) else: self.fuuro_akadora_list.append(False) #ポン elif naki_info[0] == 1: hai_arr = naki_info[1] teban = last_teban #tehaiの操作 for h in naki_info[1]: if h in self.tehai: self.tehai.remove(h) #副露リストへの追加 #先頭が赤ドラ if hai_arr[0] == 16 or hai_arr[0] == 52 or hai_arr[0] == 88: hai_str = function_tenhou.hai_convert_136_to_str(hai_arr[1]) hai_index = function.hai_convert(hai_str) self.fuurohai.append([2, hai_index, teban]) self.fuuro_akadora_list.append(True) #真ん中が赤ドラ elif hai_arr[1] == 16 or hai_arr[1] == 52 or hai_arr[1] == 88: hai_str = function_tenhou.hai_convert_136_to_str(hai_arr[2]) hai_index = function.hai_convert(hai_str) self.fuurohai.append([2, hai_index, teban]) self.fuuro_akadora_list.append(True) #最後が赤ドラ elif hai_arr[2] == 16 or hai_arr[2] == 52 or hai_arr[2] == 88: hai_str = function_tenhou.hai_convert_136_to_str(hai_arr[0]) hai_index = function.hai_convert(hai_str) self.fuurohai.append([2, hai_index, teban]) self.fuuro_akadora_list.append(True) #赤ドラなし else: hai_str = function_tenhou.hai_convert_136_to_str(hai_arr[0]) hai_index = function.hai_convert(hai_str) self.fuurohai.append([2, hai_index, teban]) self.fuuro_akadora_list.append(True) #ダイミンカン elif naki_info[0] == 2: hai_arr = naki_info[1] teban = last_teban last_hai_str = function_tenhou.hai_convert_136_to_str( int(last_dahai)) last_hai_index = function.hai_convert( function.akadora_hai_convert(last_hai_str)) #手牌から削除 for h in naki_info[1]: if h in self.tehai: self.tehai.remove(h) #副露リストに追加 self.fuurohai.append([3, last_hai_index, teban]) if last_hai_index % 10 == 5 and last_hai_index < 30: self.fuuro_akadora_list.append(True) else: self.fuuro_akadora_list.append(False) #カカン elif naki_info[0] == 5: hai_arr = naki_info[1] #元からソートされているはず #カカンした牌の種類(hai_arr[1]としているので赤の可能性なし) kakan_index = function.hai_convert( function_tenhou.hai_convert_136_to_str(hai_arr[1])) #実際に加えられた牌のID(赤の可能性あり) temp_arr = hai_arr.copy() kakan_hai_id = 6 + temp_arr[0] - ( temp_arr[0] % 4) * 2 - temp_arr[1] % 4 - temp_arr[2] % 4 #remove self.tehai.remove(kakan_hai_id) #副露リスト更新 for i in range(len(self.fuurohai)): if self.fuurohai[i][1] == kakan_index and self.fuurohai[i][ 0] == 2: self.fuurohai[i][0] = 3 #kakan_indexが5,15,25なら赤ドラあり if kakan_index % 10 == 5 and kakan_index < 30: self.fuuro_akadora_list[i] = True
def create_danger_degree_list(janshi, taku, bakyou_list): danger_degree_list = [0] * 38 danger_degree_list_return = [1.0] * 38 #オーラスで最下位ならぜんぶ1.0 if bakyou_list[0] == 4: return danger_degree_list_return janshi_list = copy.deepcopy(janshi) janshi_p = janshi_list[0] nokori_tsumo_kaisuu = int(taku.yama_nokori / 4) vertual_yama = janshi_p.vertual_yama vertual_yama_index = function.tehai_convert(vertual_yama) for i in range(1, 4): #とりあえず立直者だけ警戒 if janshi_list[i].riichi: tenpai_prob = 1.0 elif janshi_list[i].fuurosuu != 0: tenpai_prob = janshi_list[i].fuurosuu * 0.09 * math.exp( ((17 - nokori_tsumo_kaisuu) / 17 - 1) * math.sqrt(5)) else: continue #max_pointの設定 genbutsu_list = function.akadora_convert( janshi_list[i].sutehai)[0] + function.akadora_convert( janshi_list[i].temp_genbutsu)[0] #手出しリスト作成 tedashi_list = [] for j in range(len(janshi_list[i].sutehai)): if janshi_list[i].tedashi_flag: tedashi_list.append(janshi_list[i].sutehai[j]) ############メイン######################### temp_list = list(range(len(danger_degree_list))) temp_list.remove(0) temp_list.remove(10) temp_list.remove(20) temp_list.remove(30) for j in temp_list: hai_index = j #現物ならcontinue temp_hai_str = function.akadora_hai_convert(j) if temp_hai_str in genbutsu_list: continue #字牌 if hai_index > 30: if vertual_yama_index[hai_index] == 0: continue elif vertual_yama_index[hai_index] == 1: continue elif vertual_yama_index[hai_index] == 2: danger_degree_list[j] += 0.05 continue elif vertual_yama_index[hai_index] == 3: danger_degree_list[j] += 0.2 continue #筋牌ならばcontinue if suji_hantei(genbutsu_list, hai_index): continue #序盤に切れた数牌の外側ならばcontinue sutehai_len = len(janshi_list[i].sutehai) if sutehai_len > 6: sotohai_list = sotohai_find(janshi_list[i].sutehai, min(int(sutehai_len / 3), 4)) if hai_index in sotohai_list: continue #カベの外側continue if kabe_eval(vertual_yama_index, hai_index) != 0: continue #補正 danger_degree_list[j] += tenpai_prob * 2.0 danger_degree_list = np.array(danger_degree_list) danger_degree_list_return = np.array(danger_degree_list_return) return danger_degree_list + danger_degree_list_return
def teyaku_check(janshi, taku, agarihai_str: [str]): #janshi,takuオブジェクトを引数に、そのjanshiのアガリ手牌の[符数,翻数,役リスト]を出力する。翻数(n倍役満:-n、役なし:0) #アガリ牌はjanshi.tehaiに含めて入力。 fusuu = 20 hansuu = 0 yaku_list = [] #変数の整理 tehai_akadora = function.akadora_convert(janshi.tehai)[1] tehai_str = function.akadora_convert(janshi.tehai)[0] fuurohai = janshi.fuurohai ankan = janshi.ankan_list fuurosu = len(fuurohai) + len(ankan) tehai_plus_fuuro_len = len(tehai_str) + fuurosu * 3 assert 13 <= tehai_plus_fuuro_len <= 14 if tehai_plus_fuuro_len == 13: if function.hai_convert(agarihai_str) % 10 == 0: tehai_akadora += 1 agarihai_str = function.akadora_hai_convert(agarihai_str) tehai_str.append(agarihai_str) tsumoagari = False else: assert agarihai_str in janshi.tehai if function.hai_convert(agarihai_str) % 10 == 0: agarihai_str = function.akadora_hai_convert(agarihai_str) tsumoagari = True tehai = tehai_fuuro_mix_convert(tehai_str, janshi.fuurohai, janshi.ankan_list) tehai_exc_fuuro = tehai_str riichi = janshi.riichi ippatsu = janshi.ippatsu_flag rinshan = janshi.rinshan_flag zikaze = janshi.kaze first_tsumo = janshi.first_tsumo_flag fuuro_akadora = janshi.fuuro_akadora_list chankan = taku.chankan_flag haitei = taku.haitei_flag is_fuuro = Is_fuuro(fuurohai) #場風 cnv = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2] bakaze = cnv[taku.kaze_honba[0]] #ドラ表示→ドラ str_to_num = { "5M": 0, "5P": 10, "5S": 20, "1m": 1, "2m": 2, "3m": 3, "4m": 4, "5m": 5, "6m": 6, "7m": 7, "8m": 8, "9m": 9, "1p": 11, "2p": 12, "3p": 13, "4p": 14, "5p": 15, "6p": 16, "7p": 17, "8p": 18, "9p": 19, "1s": 21, "2s": 22, "3s": 23, "4s": 24, "5s": 25, "6s": 26, "7s": 27, "8s": 28, "9s": 29, "1z": 31, "2z": 32, "3z": 33, "4z": 34, "5z": 35, "6z": 36, "7z": 37 } dorah = [taku.dorahyouji, taku.uradorahyouji] #dora = [[ドラリスト],[裏ドラリスト]] dora = [[], []] for i in range(0, 2): for j in dorah[i]: j2 = str_to_num[j] if (j2 == 9) or (j2 == 19) or (j2 == 29): dora[i].append(j2 - 8) elif j2 == 34: dora[i].append(31) elif j2 == 37: dora[i].append(35) elif j2 % 10 == 0: dora[i].append(j2 + 6) else: dora[i].append(j2 + 1) agarihai = str_to_num[agarihai_str] fanpai = [tehai[31], tehai[32], tehai[33], tehai[34]] sangenpai = [tehai[35], tehai[36], tehai[37]] #アガリ形の判別(国士形:2、七対形:1、四面子一雀頭形:0、アガってない:-1) agari_kei = -1 #国士形かどうか kokushi_flag = True kokushi_l = [1, 9, 11, 19, 21, 29, 31, 32, 33, 34, 35, 36, 37] for i in kokushi_l: if tehai[i] == 0: kokushi_flag = False if kokushi_flag == True: agari_kei = 2 #七対形かどうか chiitoi_flag = True for i in range(1, 38): if tehai[i] == 1 or tehai[i] >= 3: chiitoi_flag = False if chiitoi_flag == True: agari_kei = 1 #四面子一雀頭形の場合、雀頭と面子に分解して変換 jm_list = jm_convert(tehai_exc_fuuro, fuurohai, ankan) if jm_list != []: agari_kei = 0 if agari_kei == -1: return [0, 0, []] #個別の役について判定する #役満役 yakuman = 0 #天和 if first_tsumo: yaku_list.append("天和") yakuman += 1 #字一色 if inc(tehai, '000000000 000000000 000000000 1111111'): yaku_list.append("字一色") yakuman += 1 #緑一色 if inc(tehai, '000000000 000000000 011101010 0000010'): yaku_list.append("緑一色") yakuman += 1 #清老頭 if inc(tehai, '100000001 100000001 100000001 0000000'): yaku_list.append("清老頭") yakuman += 1 #大三元 sangenpai = [tehai[35], tehai[36], tehai[37]] if sangenpai[0] >= 3 and sangenpai[1] >= 3 and sangenpai[2] >= 3: yaku_list.append("大三元") yakuman += 1 #小四喜 fanpai = [tehai[31], tehai[32], tehai[33], tehai[34]] if (fanpai[0] == 2 and fanpai[1] >= 3 and fanpai[2] >= 3 and fanpai[3] >= 3) or\ (fanpai[0] >= 3 and fanpai[1] == 2 and fanpai[2] >= 3 and fanpai[3] >= 3) or\ (fanpai[0] >= 3 and fanpai[1] >= 3 and fanpai[2] == 2 and fanpai[3] >= 3) or\ (fanpai[0] >= 3 and fanpai[1] >= 3 and fanpai[2] >= 3 and fanpai[3] == 2): yaku_list.append("小四喜") yakuman += 1 #大四喜 fanpai = [tehai[31], tehai[32], tehai[33], tehai[34]] if fanpai[0] >= 3 and fanpai[1] >= 3 and fanpai[2] >= 3 and fanpai[3] >= 3: yaku_list.append("大四喜") yakuman += 1 #九蓮宝橙:萬子 tyuuren_flag = True if not inc(tehai, '111111111 000000000 000000000 0000000'): tyuuren_flag = False for i in range(1, 10): if i == (1 or 9): if tehai[i] < 3: tyuuren_flag = False if tehai[i] == 0: tyuuren_flag = False if tyuuren_flag == True and is_fuuro == False: yaku_list.append("九蓮宝橙") yakuman += 1 #九蓮宝橙:筒子 tyuuren_flag = True if not inc(tehai, '000000000 111111111 000000000 0000000'): tyuuren_flag = False for i in range(11, 20): if i == (11 or 19): if tehai[i] < 3: tyuuren_flag = False if tehai[i] == 0: tyuuren_flag = False if tyuuren_flag == True and is_fuuro == False: yaku_list.append("九蓮宝橙") yakuman += 1 #九蓮宝橙:索子 tyuuren_flag = True if not inc(tehai, '000000000 000000000 111111111 0000000'): tyuuren_flag = False for i in range(21, 30): if i == (21 or 29): if tehai[i] < 3: tyuuren_flag = False if tehai[i] == 0: tyuuren_flag = False if tyuuren_flag == True and is_fuuro == False: yaku_list.append("九蓮宝橙") yakuman += 1 #四槓子 if agari_kei == 0: for jm in jm_list: suukantsu_flag = True for m in jm[1]: if m[1] != 2: suukantsu_flag = False if suukantsu_flag == True: yaku_list.append("四槓子") yakuman += 1 #四暗刻 if agari_kei == 0: for jm in jm_list: suuankou_flag = True for m in jm[1]: if m[0] != 0 or m[1] == 0: suuankou_flag = False if not tsumoagari and jm[0] != agarihai: suuankou_flag = False if suuankou_flag == True: yaku_list.append("四暗刻") yakuman += 1 #国士無双 if kokushi_flag == True: yaku_list.append("国士無双") yakuman += 1 #役満があったとき if yakuman != 0: return [-yakuman, 0, yaku_list] #役満以外の役 #立直、ダブル立直 if riichi == 1: yaku_list.append("立直") hansuu += 1 if riichi == 2: yaku_list.append("ダブル立直") hansuu += 2 #一発 if ippatsu: yaku_list.append("一発") hansuu += 1 #メンゼン自摸 if tsumoagari and not is_fuuro: yaku_list.append("門前清自摸和") hansuu += 1 #嶺上開花 if rinshan: yaku_list.append("嶺上開花") hansuu += 1 #海底、河底 if haitei: yaku_list.append("ハイテイ") hansuu += 1 #槍槓 if chankan: yaku_list.append("槍槓") hansuu += 1 #断么九 if inc(tehai, '011111110 011111110 011111110 0000000'): yaku_list.append("断么九") hansuu += 1 #混老頭 if inc(tehai, '100000001 100000001 100000001 1111111'): yaku_list.append("混老頭") hansuu += 2 #清一色 tinitsu_flag = False if inc(tehai,'111111111 000000000 000000000 0000000') or inc(tehai,'000000000 1111111111 000000000 0000000')\ or inc(tehai,'000000000 000000000 111111111 0000000'): yaku_list.append("清一色") tinitsu_flag = True if is_fuuro: hansuu += 5 else: hansuu += 6 #混一色 if tinitsu_flag == False and ( inc(tehai,'111111111 000000000 000000000 1111111')\ or inc(tehai,'000000000 111111111 000000000 1111111') or inc(tehai,'000000000 000000000 111111111 1111111')): yaku_list.append("混一色") if is_fuuro: hansuu += 2 else: hansuu += 3 #白、發、中 sangenpai = [tehai[35], tehai[36], tehai[37]] if sangenpai[0] >= 3: yaku_list.append("白") hansuu += 1 if sangenpai[1] >= 3: yaku_list.append("發") hansuu += 1 if sangenpai[2] >= 3: yaku_list.append("中") hansuu += 1 #小三元 sangenpai = [tehai[35], tehai[36], tehai[37]] if (sangenpai[0] >= 3 and sangenpai[1] >= 3 and sangenpai[2] == 2) or\ (sangenpai[0] >= 3 and sangenpai[1] == 2 and sangenpai[2] >= 3) or\ (sangenpai[0] == 2 and sangenpai[1] >= 3 and sangenpai[2] >= 3): yaku_list.append("小三元") hansuu += 2 #場風、自風 if tehai[31 + bakaze] >= 3: yaku_list.append("場風") hansuu += 1 if tehai[31 + zikaze] >= 3: yaku_list.append("自風") hansuu += 1 #七対子 if agari_kei == 1: yaku_list.append("七対子") hansuu += 2 fusuu = 25 #三槓子 if agari_kei == 0: kantsu_num = 0 for jm in jm_list: for m in jm[1]: if m[1] == 2: kantsu_num += 1 if kantsu_num >= 3: yaku_list.append("三槓子") hansuu += 2 #面子の分解パターンによってついたりつかなかったりする役(四暗刻をのぞく) #すべての分解パターンについて求め、最も翻数、符数が高いものをえらぶ。 if agari_kei == 0: han_fu_candidate = [] for jm in jm_list: hansuu_tmp = hansuu fusuu_tmp = fusuu yaku_list_tmp = copy(yaku_list) #符計算 shuntsu_lis = [i for i in jm[1] if i[1] == 0] #順子を入れた配列 #符(雀頭) yakuhai_jantou_flag = False if jm[0] == 35 or jm[0] == 36 or jm[0] == 37 or jm[ 0] == 31 + zikaze or jm[0] == 31 + bakaze: fusuu_tmp += 2 yakuhai_jantou_flag = True #符(待ち) #待ち方が複数解釈できる場合平和がつく(符数20)なら両面。それ以外は符がつく待ちを選ぶ。(シャボvs両面は両面(for三暗刻)) #順子数>3の時、両面待ちがあるならピンフ。ないなら符数+2 pinfu_flag = False ryanmen = [[], [1], [2, 4], [3, 5], [4, 6], [5, 7], [6, 8], [9], [], [], [], [11], [12, 14], [13, 15], [14, 16], [15, 17], [16, 18], [19], [], [], [], [21], [22, 24], [23, 25], [24, 26], [25, 27], [26, 28], [29], [], []] if len(shuntsu_lis) > 3: for i in shuntsu_lis: r = ryanmen[i[2]] if len(r) > 0: for j in r: if agarihai < 30 and agarihai == j and yakuhai_jantou_flag == False: pinfu_flag = True if pinfu_flag == False: fusuu_tmp += 2 #順子数<=3の時、符が付く待ち→両面の順に探す。どれもなければシャボ。シャボの場合、ロンアガリならjmのその暗刻を明刻に変える。 else: tanki_flag = False penchan_flag = False kanchan_flag = False ryanmen_flag = False penchan = [ 0, 3, 0, 0, 0, 0, 0, 7, 0, 0, 0, 13, 0, 0, 0, 0, 0, 17, 0, 0, 0, 23, 0, 0, 0, 0, 0, 27, 0, 0 ] kanchan = [ 0, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, 0, 0, 0, 22, 23, 24, 25, 26, 27, 28, 0, 0 ] if agarihai == jm[0]: tanki_flag = True elif len(shuntsu_lis) > 0 and agarihai < 30: for i in shuntsu_lis: if agarihai == penchan[i[2]]: penchan_flag = True elif agarihai == kanchan[i[2]]: kanchan_flag = True else: r = ryanmen[i[2]] if len(r) > 0: for j in r: if agarihai == j: ryanmen_flag = True if tanki_flag == True or penchan_flag == True or kanchan_flag == True: fusuu_tmp += 2 elif ryanmen_flag == False and not tsumoagari: for l in jm[1]: if l[1] == 1 and l[2] == agarihai: l[0] = 1 #刻子、暗刻を入れた配列 koutsu_lis = [i for i in jm[1] if i[1] == 1 or i[1] == 2] #槓子含む anko_lis = [i for i in koutsu_lis if i[0] == 0] #槓子含む #符(刻子、槓子) if len(koutsu_lis) > 0: for l in koutsu_lis: if (1 < l[2] < 9) or (11 < l[2] < 19) or (21 < l[2] < 29): yaotyu = 0 else: yaotyu = 1 if l[0] == 1: ank = 0 else: ank = 1 if l[1] == 1: kant = 0 else: kant = 1 fusuu_tmp += 2 * (2**yaotyu) * (2**ank) * (4**kant) #符(上がり方) if tsumoagari and pinfu_flag == False: fusuu_tmp += 2 elif not tsumoagari and not is_fuuro: fusuu_tmp += 10 #順子が3個以上ならすべての三順子のインデックスを抜き出す。同順、イッツー用 if len(shuntsu_lis) >= 3: san_shuntsu_id = [] if len(shuntsu_lis) == 3: san_shuntsu_id.append([i[2] for i in shuntsu_lis]) else: yon_shuntsu_id = [i[2] for i in shuntsu_lis] for i in range(0, 4): san_shuntsu_id.append(yon_shuntsu_id[:i] + yon_shuntsu_id[(i + 1):]) for i in san_shuntsu_id: i.sort() #刻子が3個以上ならすべての三刻子のインデックスを抜き出す。同刻用。 if len(koutsu_lis) >= 3: san_koutsu_id = [] if len(koutsu_lis) == 3: san_koutsu_id.append([i[2] for i in koutsu_lis]) else: yon_koutsu_id = [i[2] for i in koutsu_lis] for i in range(0, 4): san_koutsu_id.append(yon_koutsu_id[:i] + yon_koutsu_id[(i + 1):]) for i in san_koutsu_id: i.sort() #一盃口、二盃口 if not is_fuuro: l = len(shuntsu_lis) if l >= 2: peko_num = 0 for i in range(0, l - 1): for j in range(i + 1, l): if shuntsu_lis[i][2] == shuntsu_lis[j][2]: peko_num += 1 if peko_num == 1: yaku_list_tmp.append("一盃口") hansuu_tmp += 1 elif peko_num == 2: yaku_list_tmp.append("二盃口") hansuu_tmp += 3 #三暗刻 if len(anko_lis) == 3: yaku_list_tmp.append("三暗刻") hansuu_tmp += 2 #三色同刻 if len(koutsu_lis) >= 3: doukou_flag = False for s in san_koutsu_id: if s[1] == s[0] + 10 and s[2] == s[0] + 20 and s[2] < 30: doukou_flag = True if doukou_flag == True: yaku_list_tmp.append("三色同刻") hansuu_tmp += 2 #三色同順 if len(shuntsu_lis) >= 3: doujun_flag = False for s in san_shuntsu_id: if s[1] == s[0] + 10 and s[2] == s[0] + 20: doujun_flag = True if doujun_flag == True: yaku_list_tmp.append("三色同順") if is_fuuro: hansuu_tmp += 1 else: hansuu_tmp += 2 #対々和 if len(koutsu_lis) >= 4: yaku_list_tmp.append("対々和") hansuu_tmp += 2 #一気通貫 if len(shuntsu_lis) >= 3: ittsu_flag = False for s in san_shuntsu_id: if s == ([1, 4, 7] or [11, 14, 17] or [21, 24, 27]): ittsu_flag = True if ittsu_flag == True: yaku_list_tmp.append("一気通貫") if is_fuuro: hansuu_tmp += 1 else: hansuu_tmp += 2 #純全帯么九、混全帯么九 junchan_flag = True chanta_flag = True if len(shuntsu_lis) >= 1: for l in shuntsu_lis: if (1 < l[2] < 7) or (11 < l[2] < 17) or (21 < l[2] < 27): junchan_flag = False chanta_flag = False if len(koutsu_lis) >= 1: for l in koutsu_lis: if (1 < l[2] < 9) or (11 < l[2] < 19) or (21 < l[2] < 29): junchan_flag = False chanta_flag = False elif 30 < l[2]: junchan_flag = False if (1 < jm[0] < 7) or (11 < jm[0] < 17) or (21 < jm[0] < 27): junchan_flag = False chanta_flag = False elif 30 < jm[0]: junchan_flag = False if junchan_flag == True: yaku_list_tmp.append("純全帯么九") if is_fuuro: hansuu_tmp += 2 else: hansuu_tmp += 3 elif chanta_flag == True: yaku_list_tmp.append("混全帯么九") if is_fuuro: hansuu_tmp += 1 else: hansuu_tmp += 2 #平和 if pinfu_flag == True and not is_fuuro: yaku_list_tmp.append("平和") hansuu_tmp += 1 han_fu_candidate.append([hansuu_tmp, fusuu_tmp, yaku_list_tmp]) for i in han_fu_candidate: if i[0] > hansuu: hansuu = i[0] fusuu = i[1] yaku_list = i[2] elif i[0] == hansuu: if i[1] > fusuu: fusuu = i[1] yaku_list = i[2] if hansuu > 0: od = 0 for i in dora[0]: od += tehai[i] if od > 0: yaku_list.append("ドラ" + str(od)) hansuu += od ad = tehai_akadora if len(fuuro_akadora) > 0: for i in fuuro_akadora: if i: ad += 1 if len(ankan) > 0: for i in ankan: if i == 5 or i == 15 or i == 25: ad += 1 if ad > 0: yaku_list.append("赤ドラ" + str(ad)) hansuu += ad if riichi > 0: ud = 0 for i in dora[1]: ud += tehai[i] if ud > 0: yaku_list.append("裏ドラ" + str(ud)) hansuu += ud if fusuu != 25: fusuu2 = fusuu / 10.0 fusuu = math.ceil(fusuu2) * 10 return [hansuu, fusuu, yaku_list]