def _rebuild_bot_shanten_cache(self, player): isolated_tile_34 = find_isolated_tile_indices( TilesConverter.to_34_array(player.closed_hand))[0] isolated_tile_136 = isolated_tile_34 * 4 player.table.revealed_tiles[isolated_tile_34] -= 1 player.draw_tile(isolated_tile_136) player.discard_tile()
def calculate_shanten(self, tiles_34, open_sets_34=None, chiitoitsu=True, kokushi=True): """ Return the count of tiles before tempai :param tiles_34: 34 tiles format array :param open_sets_34: array of array of 34 tiles format :param chiitoitsu: bool :param kokushi: bool :return: int """ # we will modify them later, so we need to use a copy tiles_34 = copy.deepcopy(tiles_34) self._init(tiles_34) count_of_tiles = sum(tiles_34) if count_of_tiles > 14: return -2 # With open hand we need to remove open sets from hand and replace them with isolated pon sets # it will allow to calculate count of shanten correctly if open_sets_34: isolated_tiles = find_isolated_tile_indices(tiles_34) for meld in open_sets_34: if not isolated_tiles: break isolated_tile = isolated_tiles.pop() tiles_34[meld[0]] -= 1 tiles_34[meld[1]] -= 1 tiles_34[meld[2]] -= 1 tiles_34[isolated_tile] = 3 if not open_sets_34: self.min_shanten = self._scan_chiitoitsu_and_kokushi( chiitoitsu, kokushi) self._remove_character_tiles(count_of_tiles) init_mentsu = math.floor((14 - count_of_tiles) / 3) self._scan(init_mentsu) return self.min_shanten
def is_agari(self, tiles_34, open_sets_34=None): """ Determine was it win or not :param tiles_34: 34 tiles format array :param open_sets_34: array of array of 34 tiles format :return: boolean """ # we will modify them later, so we need to use a copy tiles = tiles_34[:] # With open hand we need to remove open sets from hand and replace them with isolated pon sets # it will allow to determine agari state correctly if open_sets_34: isolated_tiles = find_isolated_tile_indices(tiles) for meld in open_sets_34: if not isolated_tiles: break isolated_tile = isolated_tiles.pop() tiles[meld[0]] -= 1 tiles[meld[1]] -= 1 tiles[meld[2]] -= 1 # kan if len(meld) > 3: tiles[meld[3]] -= 1 tiles[isolated_tile] = 3 j = ((1 << tiles[27]) | (1 << tiles[28]) | (1 << tiles[29]) | (1 << tiles[30]) | (1 << tiles[31]) | (1 << tiles[32]) | (1 << tiles[33])) if j >= 0x10: return False # 13 orphans if ((j & 3) == 2) and (tiles[0] * tiles[8] * tiles[9] * tiles[17] * tiles[18] * tiles[26] * tiles[27] * tiles[28] * tiles[29] * tiles[30] * tiles[31] * tiles[32] * tiles[33] == 2): return True # seven pairs if not (j & 10) and sum([tiles[i] == 2 for i in range(0, 34)]) == 7: return True if j & 2: return False n00 = tiles[0] + tiles[3] + tiles[6] n01 = tiles[1] + tiles[4] + tiles[7] n02 = tiles[2] + tiles[5] + tiles[8] n10 = tiles[9] + tiles[12] + tiles[15] n11 = tiles[10] + tiles[13] + tiles[16] n12 = tiles[11] + tiles[14] + tiles[17] n20 = tiles[18] + tiles[21] + tiles[24] n21 = tiles[19] + tiles[22] + tiles[25] n22 = tiles[20] + tiles[23] + tiles[26] n0 = (n00 + n01 + n02) % 3 if n0 == 1: return False n1 = (n10 + n11 + n12) % 3 if n1 == 1: return False n2 = (n20 + n21 + n22) % 3 if n2 == 1: return False if (n0 == 2) + (n1 == 2) + (n2 == 2) + (tiles[27] == 2) + ( tiles[28] == 2) + (tiles[29] == 2) + (tiles[30] == 2) + ( tiles[31] == 2) + (tiles[32] == 2) + (tiles[33] == 2) != 1: return False nn0 = (n00 * 1 + n01 * 2) % 3 m0 = self._to_meld(tiles, 0) nn1 = (n10 * 1 + n11 * 2) % 3 m1 = self._to_meld(tiles, 9) nn2 = (n20 * 1 + n21 * 2) % 3 m2 = self._to_meld(tiles, 18) if j & 4: return (not (n0 | nn0 | n1 | nn1 | n2 | nn2) and self._is_mentsu(m0) and self._is_mentsu(m1) and self._is_mentsu(m2)) if n0 == 2: return (not (n1 | nn1 | n2 | nn2) and self._is_mentsu(m1) and self._is_mentsu(m2) and self._is_atama_mentsu(nn0, m0)) if n1 == 2: return (not (n2 | nn2 | n0 | nn0) and self._is_mentsu(m2) and self._is_mentsu(m0) and self._is_atama_mentsu(nn1, m1)) if n2 == 2: return (not (n0 | nn0 | n1 | nn1) and self._is_mentsu(m0) and self._is_mentsu(m1) and self._is_atama_mentsu(nn2, m2)) return False
def is_agari(self, tiles, melds=None): """ Determine was it win or not :param tiles: 34 tiles format array :param melds: array of array of 34 tiles format :return: boolean """ # we will modify them later, so we need to use a copy #tiles = copy.deepcopy(tiles) # TODO: I am not sure whether it's a bug or not. Originally the author # only took care of a hand of 14 tiles. However, when the closed hand # is consist of kans, there will be 15 or even more tiles. For this # reason, I intentionally remove one tile from any kan here. This might # be a temporally solution. (joseph) if sum(tiles) > 14: tiles = [t - 1 if t == 4 else t for t in tiles] # t==4 means a kan. # With open hand we need to remove open sets from hand and replace them with isolated pon sets # it will allow to determine agari state correctly if melds: isolated_tiles = find_isolated_tile_indices(tiles) for meld in melds: if not isolated_tiles: break isolated_tile = isolated_tiles.pop() tiles[meld[0]] -= 1 tiles[meld[1]] -= 1 tiles[meld[2]] -= 1 tiles[isolated_tile] = 3 j = (1 << tiles[27]) | (1 << tiles[28]) | (1 << tiles[29]) | (1 << tiles[30]) | \ (1 << tiles[31]) | (1 << tiles[32]) | (1 << tiles[33]) if j >= 0x10: return False # 13 orphans if ((j & 3) == 2) and (tiles[0] * tiles[8] * tiles[9] * tiles[17] * tiles[18] * tiles[26] * tiles[27] * tiles[28] * tiles[29] * tiles[30] * tiles[31] * tiles[32] * tiles[33] == 2): return True # seven pairs if not (j & 10) and sum([tiles[i] == 2 for i in range(0, 34)]) == 7: return True if j & 2: return False n00 = tiles[0] + tiles[3] + tiles[6] n01 = tiles[1] + tiles[4] + tiles[7] n02 = tiles[2] + tiles[5] + tiles[8] n10 = tiles[9] + tiles[12] + tiles[15] n11 = tiles[10] + tiles[13] + tiles[16] n12 = tiles[11] + tiles[14] + tiles[17] n20 = tiles[18] + tiles[21] + tiles[24] n21 = tiles[19] + tiles[22] + tiles[25] n22 = tiles[20] + tiles[23] + tiles[26] n0 = (n00 + n01 + n02) % 3 #print("n0={}".format(n0)) if n0 == 1: return False n1 = (n10 + n11 + n12) % 3 #print("n1={}".format(n1)) if n1 == 1: return False n2 = (n20 + n21 + n22) % 3 #print("n2={}".format(n2)) if n2 == 1: return False if ((n0 == 2) + (n1 == 2) + (n2 == 2) + (tiles[27] == 2) + (tiles[28] == 2) + (tiles[29] == 2) + (tiles[30] == 2) + (tiles[31] == 2) + (tiles[32] == 2) + (tiles[33] == 2) != 1): return False nn0 = (n00 * 1 + n01 * 2) % 3 m0 = self._to_meld(tiles, 0) nn1 = (n10 * 1 + n11 * 2) % 3 m1 = self._to_meld(tiles, 9) nn2 = (n20 * 1 + n21 * 2) % 3 m2 = self._to_meld(tiles, 18) if j & 4: return not (n0 | nn0 | n1 | nn1 | n2 | nn2) and self._is_mentsu(m0) \ and self._is_mentsu(m1) and self._is_mentsu(m2) if n0 == 2: return not (n1 | nn1 | n2 | nn2) and self._is_mentsu(m1) and self._is_mentsu(m2) \ and self._is_atama_mentsu(nn0, m0) if n1 == 2: return not (n2 | nn2 | n0 | nn0) and self._is_mentsu(m2) and self._is_mentsu(m0) \ and self._is_atama_mentsu(nn1, m1) if n2 == 2: return not (n0 | nn0 | n1 | nn1) and self._is_mentsu(m0) and self._is_mentsu(m1) \ and self._is_atama_mentsu(nn2, m2) return False
def test_find_isolated_tiles(self): hand_34 = TilesConverter.string_to_34_array(sou='1369', pin='15678', man='25', honors='124') isolated_tiles = find_isolated_tile_indices(hand_34) self.assertEqual( self._string_to_34_tile(sou='1') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou='2') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou='3') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou='4') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou='5') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou='6') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou='7') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou='8') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou='9') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin='1') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin='2') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin='3') in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(pin='4') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin='5') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin='6') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin='7') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin='8') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin='9') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man='1') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man='2') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man='3') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man='4') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man='5') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man='6') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man='7') in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(man='8') in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(man='9') in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(honors='1') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(honors='2') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(honors='3') in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(honors='4') in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(honors='5') in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(honors='6') in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(honors='7') in isolated_tiles, True)
def test_find_isolated_tiles(self): hand_34 = TilesConverter.string_to_34_array(sou="1369", pin="15678", man="25", honors="124") isolated_tiles = find_isolated_tile_indices(hand_34) self.assertEqual( self._string_to_34_tile(sou="1") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou="2") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou="3") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou="4") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou="5") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou="6") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou="7") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou="8") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(sou="9") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin="1") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin="2") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin="3") in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(pin="4") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin="5") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin="6") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin="7") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin="8") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(pin="9") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man="1") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man="2") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man="3") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man="4") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man="5") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man="6") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(man="7") in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(man="8") in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(man="9") in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(honors="1") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(honors="2") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(honors="3") in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(honors="4") in isolated_tiles, False) self.assertEqual( self._string_to_34_tile(honors="5") in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(honors="6") in isolated_tiles, True) self.assertEqual( self._string_to_34_tile(honors="7") in isolated_tiles, True)