Exemplo n.º 1
0
def get_score(tehais_num, furos, taken):
    tehais = []
    for i in range(len(tehais_num)):
        for _ in range(tehais_num[i]):
            tehais.append(Pai.from_id(i))

    taken_index = tehais.index(Pai.from_id(taken))
    taken = tehais.pop(taken_index)

    hora = HoraRs(
        tehais=tehais,
        furos=furos,
        taken=taken,
        hora_type='tsumo',
        oya=False,
        bakaze='E',
        jikaze='S',
        doras=[],
        uradoras=[],
        reach=len(furos) == 0,
        double_reach=False,
        ippatsu=False,
        rinshan=False,
        haitei=False,
        first_turn=False,
        chankan=False,
    )
    return hora
Exemplo n.º 2
0
    def __init__(self, pais):
        self.pais = pais
        self.shanten_analysis = RsShantenAnalysis()
        self.tehai = [0]*34
        for p in pais:
            self.tehai[p.id] += 1
        
        self.furo_num = (14 - len(pais)) // 3
        
        self.shanten = self.shanten_analysis.calc_shanten(self.tehai, self.furo_num)

        self.waiting = []
        if self.shanten != 0:
            return

        for waiting_id in range(34):
            if self.tehai[waiting_id] == 4:
                # already use all pais
                continue

            self.tehai[waiting_id] += 1
            if self.shanten_analysis.calc_shanten(self.tehai, self.furo_num) == -1:
                self.waiting.append(Pai.from_id(waiting_id))
            self.tehai[waiting_id] -= 1
Exemplo n.º 3
0
    def dfs_with_score_normal(
        self,
        tehai:List[int], 
        furos:List[Furo], 
        depth:int, 
        shanten_normal:int,
        oya:bool=False,
        bakaze:str="E", 
        jikaze:str="S", 
        doras:List[Pai]=None, 
        uradoras:List[Pai]=None,
        num_akadoras:int=0,
    ):
        if doras is None:
            doras = []
        if uradoras is None:
            uradoras = []
        
        # print(tehai, len(furos), depth, shanten_normal)
        results = self.dfs_normal(tehai, len(furos), depth, shanten_normal)
        

        # union to min distance
        unioned_results = {}
        
        for result in results:
            result_tehai = result[0]
            distance = result[1]
            
            
            if result_tehai in unioned_results:
                unioned_results[result_tehai] = min(distance, unioned_results[result_tehai])
            else:
                unioned_results[result_tehai] = distance
        
        horas = []
        dahai_horas = {}
        for result_tehai, distance in unioned_results.items():
            (head, mentsus) = result_tehai
            # try to use cache
            changed_tehai_num = [0] * 34
            changed_tehai_num[head] += 2
            for mentsu in mentsus:
                for pai in mentsu:
                    changed_tehai_num[pai] += 1

            diff = [changed_tehai_num[i] - num for i,num in enumerate(tehai)]
            # assert sum([d for d in diff if d>0]) <= depth, f"{tehai}, {result_tehai}, {diff}, {distance}"

            taken_candidate_ids = [i for (i,p) in enumerate(diff) if p > 0]
            hora_key = (
                result_tehai, 
                tuple(sorted(furos)),
                oya,
                bakaze,
                jikaze,
                tuple(sorted(doras)),
                tuple(sorted(uradoras)),
                num_akadoras,
                tuple(sorted(taken_candidate_ids)),
                )
            if hora_key in self.hora_cash:
                (max_result, diff) = self.hora_cash[hora_key]
                horas.append(DfsResult(DfsResultType.Normal, result_tehai, max_result, diff))
                
                continue

            if len(taken_candidate_ids) == 0:
                taken_candidate_ids = [i for (i,p) in enumerate(changed_tehai_num) if p > 0]
            
            changed_tehais = []
            for i, value in enumerate(changed_tehai_num):
                for _ in range(value):
                    changed_tehais.append(Pai.from_id(i))
            
            taken_changed_results = []
            for taken_id in taken_candidate_ids:
                horra_tehai = copy.copy(changed_tehais)
                taken_index = horra_tehai.index(Pai.from_id(taken_id))
                taken = horra_tehai.pop(taken_index)
                
                """
                # print(horra_tehai, taken, taken_id)
                hora = Candidate.from_already_spliteds(
                    head=head, # 9
                    mentsus=mentsus, # ((1,2,3), (4,5,6), (20,20,20), (32,32,32))
                    furos=furos, # List[Furo]
                    taken=taken_id, # 20
                    oya=oya,
                    bakaze=bakaze,
                    jikaze=jikaze,
                    doras=doras,
                    uradoras=uradoras,
                    num_akadoras=num_akadoras,
                    )
                """
                
                hora = HoraRs(
                    tehais=horra_tehai,
                    furos=furos,
                    taken=taken,
                    hora_type='tsumo',
                    oya=oya,
                    bakaze=bakaze,
                    jikaze=jikaze,
                    doras=doras,
                    uradoras=uradoras,
                    reach=len(furos)==0,
                    double_reach=False,
                    ippatsu=False,
                    rinshan=False,
                    haitei=False,
                    first_turn=False,
                    chankan=False,
                    num_akadoras=num_akadoras
                )
                
                # print(hora)
                taken_changed_results.append(hora)
        
            max_result = max(taken_changed_results, key= lambda x:{x.points*1000+x.fan*1000+x.fu})    
            self.hora_cash[hora_key] = (max_result, diff)
            horas.append(DfsResult(DfsResultType.Normal, result_tehai, max_result, diff))
            

        return horas
Exemplo n.º 4
0
    def dfs_with_score_chitoitsu(
        self,
        tehai:List[int],
        furos:List[Furo],
        depth:int, 
        shanten_chitoitsu:int,
        oya:bool=False, 
        bakaze:str="E", 
        jikaze:str="S", 
        doras:List[Pai]=None, 
        uradoras:List[Pai]=None,
        num_akadoras:int=0,
    ):
        if doras is None:
            doras = []
        if uradoras is None:
            uradoras = []
        
        horas = []
        
        results = self.dfs_chitoitsu(tehai, depth, doras, shanten_chitoitsu)
        
        
        for result in results:
            tehais = []
            toitsus = result
            
            for i, toitsu in enumerate(toitsus):
                tehais.append(Pai.from_id(toitsu[0]))
                tehais.append(Pai.from_id(toitsu[1]))


            if len(tehais) > 0:
                taken = tehais.pop()
            else:
                taken = None
            
            # print(horra_tehai, taken, taken_id)
            """
            hora = Candidate.from_already_splited_chitoitsu(
                tehais=tehais,
                furos=furos, # List[Furo]
                taken=taken,
                oya=oya,
                bakaze=bakaze,
                jikaze=jikaze,
                doras=doras,
                uradoras=uradoras,
                num_akadoras=num_akadoras,
                )
            """
            hora = HoraRs(
                tehais=tehais,
                furos=furos,
                taken=taken,
                hora_type='tsumo',
                oya=oya,
                bakaze=bakaze,
                jikaze=jikaze,
                doras=doras,
                uradoras=uradoras,
                reach=len(furos)==0,
                double_reach=False,
                ippatsu=False,
                rinshan=False,
                haitei=False,
                first_turn=False,
                chankan=False,
                num_akadoras=num_akadoras
            )
            nums = [0] * 34
            nums[taken.id] += 1
            for t in tehais:
                nums[t.id] += 1
            diff = [nums[i] - tehai[i] for i in range(34)]
            horas.append(DfsResult(DfsResultType.Chitoitsu, toitsus, hora, diff))
            
        return horas
Exemplo n.º 5
0
    def from_already_spliteds(
        cls,
        head, # 9
        mentsus, # ((1,2,3), (4,5,6), (20,20,20), (32,32,32))
        furos, # List[Furo]
        taken, # 20
        oya,
        bakaze,
        jikaze,
        doras,
        uradoras,
        num_akadoras,
    ):
        
        # need before calclate dora
        pais_buffer = Pai.from_idlist([head, head])
         
        for mentsu in mentsus:
            pais_buffer.extend(Pai.from_idlist(list(mentsu)))
        
        free_pais = copy.copy(pais_buffer)

        for furo in furos:
            pais_buffer.extend(furo.pais)
        all_pais = pais_buffer
        is_menzen = len([f for f in furos if f.type != 'ankan']) == 0
        taken = Pai.from_id(taken)

        num_doras = Hora.count_doras(all_pais, doras)
        num_uradoras = Hora.count_doras(all_pais, uradoras)
        # num_akadora need calclate outside.
        
        num_same_as_taken = len([f for f in free_pais if taken.is_same_symbol(f)])
        
        combination = [
            ["toitsu", Pai.from_idlist([head,head])],
        ]
        for mentsu in mentsus:
            if mentsu[0] == mentsu[1]:
                combination.append(["kotsu", Pai.from_idlist(mentsu)])
            else:
                combination.append(["shuntsu", Pai.from_idlist(mentsu)])
        
        hora_yaku_information = HoraYakuInformation(
            taken=taken,
            all_pais=all_pais,
            hora_type="tsumo",
            oya=oya,
            first_turn=False,
            num_doras=num_doras,
            num_uradoras=num_uradoras,
            num_akadoras=num_akadoras,
            reach=is_menzen,
            ippatsu=False,
            rinshan=False,
            chankan=False,
            haitei=False,
            double_reach=False,
            furos=furos,
            jikaze=jikaze,
            bakaze=bakaze,
        )

        candidates = []
        for i in range(num_same_as_taken):
            candidates.append(Candidate(hora_yaku_information, combination, i))
        
        if len(candidates) > 0:
            best_candidate = max(candidates, key=lambda x:(x.fan, x.points))
            if best_candidate.valid:
                return HoraInfo(
                    fu=best_candidate.fu,
                    fan=best_candidate.fan,
                    yakus=best_candidate.yakus,
                    points=best_candidate.points,
                    oya_payment=best_candidate.oya_payment,
                    ko_payment=best_candidate.ko_payment,
                )

            return HoraInfo(
                    fu=0,
                    fan=0,
                    yakus=[],
                    points=0,
                    oya_payment=0,
                    ko_payment=0
                )