class TestFuriten(unittest.TestCase): def setUp(self): # tenpai: TON and NAN self.player = Player('test', 1) self.player.hand[Tile(Suit.JIHAI.value, Jihai.TON.value).index] += 2 self.player.hand[Tile(Suit.JIHAI.value, Jihai.NAN.value).index] += 2 naki_tile_1 = Tile(Suit.SOUZU.value, 5) naki_tile_1.owner = 0 naki_tile_2 = Tile(Suit.PINZU.value, 5) naki_tile_2.owner = 3 naki_tile_3 = Tile(Suit.MANZU.value, 8) naki_tile_3.owner = 0 naki_tile_4 = Tile(Suit.MANZU.value, 6) naki_tile_4.owner = 0 self.player.kabe.append( Huro(Naki.PON, naki_tile_1, [Tile(Suit.SOUZU.value, 5) for i in range(3)])) self.player.kabe.append( Huro(Naki.PON, naki_tile_2, [Tile(Suit.PINZU.value, 5) for i in range(3)])) self.player.kabe.append( Huro(Naki.CHII, naki_tile_3, [Tile(Suit.MANZU.value, i) for i in range(7, 10)])) self.player.kabe.append( Huro(Naki.CHII, naki_tile_4, [Tile(Suit.MANZU.value, i) for i in range(6, 9)])) def test_furiten(self): self.player.add_kawa(Tile(Suit.JIHAI.value, Jihai.TON.value)) self.assertEqual(check_furiten(self.player), True) def test_no_furiten(self): self.assertEqual(check_furiten(self.player), False) def test_own_discard_furiten(self): self.player.add_kawa(Tile(Suit.JIHAI.value, Jihai.TON.value)) self.assertEqual(check_own_discard_furiten(self.player), True) def test_no_own_discard_furiten(self): self.assertEqual(check_own_discard_furiten(self.player), False)
class TestRon(unittest.TestCase): def setUp(self): # tenpai: 3 MANZU 5 SOUZU self.player = Player('test', 1) self.player.hand[Tile(Suit.PINZU.value, 1).index] += 1 self.player.hand[Tile(Suit.PINZU.value, 2).index] += 1 self.player.hand[Tile(Suit.PINZU.value, 3).index] += 1 self.player.hand[Tile(Suit.PINZU.value, 4).index] += 1 self.player.hand[Tile(Suit.PINZU.value, 5).index] += 1 self.player.hand[Tile(Suit.PINZU.value, 6).index] += 1 self.player.hand[Tile(Suit.PINZU.value, 7).index] += 1 self.player.hand[Tile(Suit.PINZU.value, 8).index] += 1 self.player.hand[Tile(Suit.PINZU.value, 9).index] += 1 self.player.hand[Tile(Suit.MANZU.value, 3).index] += 2 self.player.hand[Tile(Suit.SOUZU.value, 5).index] += 2 self.stack = Stack() self.bakaze = Jihai.TON def test_ron(self): discard_1 = Tile(Suit.MANZU.value, 3) discard_2 = Tile(Suit.SOUZU.value, 5) ron_1 = check_ron(self.player, discard_1, self.stack, self.bakaze) ron_2 = check_ron(self.player, discard_2, self.stack, self.bakaze) self.assertEqual(ron_1, True) self.assertEqual(ron_2, True) def test_no_ron(self): discard_1 = Tile(Suit.MANZU.value, 4) ron_1 = check_ron(self.player, discard_1, self.stack, self.bakaze) self.assertEqual(ron_1, False) # 振聴 discard_2 = Tile(Suit.MANZU.value, 3) self.player.add_kawa(Tile(Suit.MANZU.value, 3)) ron_2 = check_ron(self.player, discard_2, self.stack, self.bakaze) self.assertEqual(ron_2, False)
class TestTurnDrawFlow(unittest.TestCase): def setUp(self): self.player_1 = Player('player 1', 0) self.player_2 = Player('player 2', 1) self.player_3 = Player('player 3', 2) self.player_4 = Player('player 4', 3) self.players = [ self.player_1, self.player_2, self.player_3, self.player_4 ] self.tile_stack = Stack() self.logger = KyokuLogger() for player in self.players: for i in range(13): player.hand[self.tile_stack.draw().index] += 1 self.turn = Turn(self.players, self.tile_stack, Jihai.TON, self.logger) def test_riichi(self): self.player_1.action_with_new_tile = MagicMock( return_value=((Action.RIICHI, Naki.NONE), None)) self.assertEqual(self.turn.draw_flow(self.player_1), (0, None, 0, Action.RIICHI)) def test_tsumo(self): self.player_1.action_with_new_tile = MagicMock( return_value=((Action.TSUMO, Naki.NONE), None)) self.assertEqual(self.turn.draw_flow(self.player_1), (1, None, None, Action.TSUMO)) def test_ankan(self): naki_tile = Tile(Suit.SOUZU.value, 5) naki_tile.owner = self.player_1.seating_position kan = Huro(Naki.ANKAN, naki_tile, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) self.player_1.tmp_huro = kan self.player_1.action_with_new_tile = MagicMock() self.player_1.action_with_new_tile.side_effect = [ ((Action.NAKI, Naki.CHAKAN), None), ((Action.NOACT, Naki.NONE), Tile(0, 1)) ] self.turn.kan_flow = MagicMock(return_value=0) state, discard_tile, discard_pos, act = self.turn.draw_flow( self.player_1) self.assertEqual(state, 0) self.assertEqual(discard_tile, Tile(0, 1)) self.assertEqual(discard_pos, 0) self.assertEqual(self.player_1.kawa[0], Tile(0, 1)) self.assertEqual(len(self.tile_stack.doras), 2) def test_chakan(self): # change type from PON to KAN, what's tmp_huro in this case? naki_tile = Tile(Suit.SOUZU.value, 5) naki_tile.owner = self.player_1.seating_position kan = Huro(Naki.ANKAN, naki_tile, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) self.player_1.tmp_huro = kan self.player_1.action_with_new_tile = MagicMock() self.player_1.action_with_new_tile.side_effect = [ ((Action.NAKI, Naki.CHAKAN), None), ((Action.NOACT, Naki.NONE), Tile(0, 1)) ] self.turn.kan_flow = MagicMock(return_value=0) state, discard_tile, discard_pos, act = self.turn.draw_flow( self.player_1) self.assertEqual(state, 0) self.assertEqual(discard_tile, Tile(0, 1)) self.assertEqual(discard_pos, 0) self.assertEqual(self.player_1.kawa[0], Tile(0, 1)) self.assertEqual(len(self.tile_stack.doras), 2) def test_chakan_chankan(self): naki_tile = Tile(Suit.SOUZU.value, 5) naki_tile.owner = self.player_1.seating_position kan = Huro(Naki.ANKAN, naki_tile, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) self.player_1.tmp_huro = kan self.player_1.action_with_new_tile = MagicMock() self.player_1.action_with_new_tile.side_effect = [ ((Action.NAKI, Naki.CHAKAN), None), ((Action.NOACT, Naki.NONE), Tile(0, 1)) ] self.turn.kan_flow = MagicMock(return_value=1) state, discard_tile, discard_pos = self.turn.draw_flow(self.player_1) self.assertEqual(state, 1) self.assertEqual(discard_tile, None) self.assertEqual(discard_pos, None) def test_ankan_twice(self): naki_tile_1 = Tile(Suit.SOUZU.value, 5) naki_tile_1.owner = self.player_1.seating_position naki_tile_2 = Tile(Suit.SOUZU.value, 6) naki_tile_2.owner = self.player_1.seating_position kan_1 = Huro(Naki.ANKAN, naki_tile_1, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) kan_2 = Huro(Naki.ANKAN, naki_tile_2, [Tile(Suit.SOUZU.value, 6) for i in range(4)]) self.player_1 = Mock() self.player_1.seating_position = 0 self.player_1.get_shimocha = lambda: 1 % 4 self.player_1.hand = defaultdict(int) self.player_1.kawa = [] self.player_1.add_kawa = lambda tile: self.player_1.kawa.append(tile) p = PropertyMock(side_effect=[kan_1, kan_2]) type(self.player_1).tmp_huro = p self.player_1.action_with_new_tile = MagicMock() self.player_1.action_with_new_tile.side_effect = [ ((Action.NAKI, Naki.ANKAN), None), ((Action.NAKI, Naki.ANKAN), None), ((Action.NOACT, Naki.NONE), Tile(0, 1)) ] state, discard_tile, discard_pos, act = self.turn.draw_flow( self.player_1) self.assertEqual(state, 0) self.assertEqual(discard_tile, Tile(0, 1)) self.assertEqual(discard_pos, 0) self.assertEqual(self.player_1.kawa[0], Tile(0, 1)) self.assertEqual(len(self.tile_stack.doras), 3) def test_draw_flow_suukaikan(self): # is declared when four quads are formed by different players. for _ in range(3): self.tile_stack.add_dora_indicator() naki_tile = Tile(Suit.SOUZU.value, 5) naki_tile.owner = self.player_1.seating_position kan = Huro(Naki.ANKAN, naki_tile, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) self.player_1.action_with_new_tile = MagicMock() self.player_1.action_with_new_tile.side_effect = [ ((Action.NAKI, Naki.ANKAN), None), ((Action.NOACT, Naki.NONE), Tile(0, 1)) ] self.player_1.action_with_naki = MagicMock( self.player_1.kabe.append(kan)) state, discard_tile, discard_pos, _ = self.turn.draw_flow( self.player_1) self.assertEqual(state, 0) self.assertEqual(discard_tile, Tile(0, 1)) self.assertEqual(discard_pos, self.player_1.seating_position) self.assertEqual(len(self.tile_stack.doras), 5) self.assertEqual(self.turn.suukaikan, True) def test_draw_flow_suukantsu(self): for _ in range(3): self.tile_stack.add_dora_indicator() naki_tile_1 = Tile(Suit.SOUZU.value, 5) naki_tile_1.owner = self.player_1.seating_position naki_tile_2 = Tile(Suit.SOUZU.value, 6) naki_tile_2.owner = self.player_1.seating_position naki_tile_3 = Tile(Suit.SOUZU.value, 7) naki_tile_3.owner = self.player_1.seating_position naki_tile_4 = Tile(Suit.SOUZU.value, 8) naki_tile_4.owner = self.player_1.seating_position kan_1 = Huro(Naki.ANKAN, naki_tile_1, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) kan_2 = Huro(Naki.ANKAN, naki_tile_2, [Tile(Suit.SOUZU.value, 6) for i in range(4)]) kan_3 = Huro(Naki.ANKAN, naki_tile_3, [Tile(Suit.SOUZU.value, 7) for i in range(4)]) kan_4 = Huro(Naki.ANKAN, naki_tile_4, [Tile(Suit.SOUZU.value, 8) for i in range(4)]) self.player_1.kabe.append(kan_1) self.player_1.kabe.append(kan_2) self.player_1.kabe.append(kan_3) self.player_1.action_with_new_tile = MagicMock() self.player_1.action_with_new_tile.side_effect = [ ((Action.NAKI, Naki.ANKAN), None), ((Action.NOACT, Naki.NONE), Tile(0, 1)) ] self.player_1.action_with_naki = MagicMock() def m(_): self.player_1.kabe.append(kan_4) self.player_1.action_with_naki.side_effect = m state, discard_tile, discard_pos, act = self.turn.draw_flow( self.player_1) self.assertEqual(state, 0) self.assertEqual(discard_tile, Tile(0, 1)) self.assertEqual(discard_pos, 0) self.assertEqual(len(self.tile_stack.doras), 5) def test_suukantsu_other_player(self): for _ in range(3): self.tile_stack.add_dora_indicator() naki_tile = Tile(Suit.SOUZU.value, 5) naki_tile.owner = self.player_1.seating_position kan = Huro(Naki.DAMINKAN, naki_tile, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) kabe = [kan] self.turn.check_suukaikan(kabe) self.assertEqual(len(self.tile_stack.doras), 5) self.assertEqual(self.turn.suukaikan, True) def test_suukaikan(self): for _ in range(3): self.tile_stack.add_dora_indicator() naki_tile = Tile(Suit.SOUZU.value, 5) naki_tile.owner = self.player_1.seating_position kan = Huro(Naki.DAMINKAN, naki_tile, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) kabe = [kan] self.turn.check_suukaikan(kabe) self.assertEqual(len(self.tile_stack.doras), 5) self.assertEqual(self.turn.suukaikan, True) def test_suukantsu(self): for _ in range(3): self.tile_stack.add_dora_indicator() naki_tile_1 = Tile(Suit.SOUZU.value, 5) naki_tile_1.owner = self.player_1.seating_position naki_tile_2 = Tile(Suit.SOUZU.value, 6) naki_tile_2.owner = self.player_1.seating_position naki_tile_3 = Tile(Suit.SOUZU.value, 7) naki_tile_3.owner = self.player_1.seating_position naki_tile_4 = Tile(Suit.SOUZU.value, 8) naki_tile_4.owner = self.player_1.seating_position kan_1 = Huro(Naki.ANKAN, naki_tile_1, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) kan_2 = Huro(Naki.ANKAN, naki_tile_2, [Tile(Suit.SOUZU.value, 6) for i in range(4)]) kan_3 = Huro(Naki.ANKAN, naki_tile_3, [Tile(Suit.SOUZU.value, 7) for i in range(4)]) kan_4 = Huro(Naki.ANKAN, naki_tile_4, [Tile(Suit.SOUZU.value, 8) for i in range(4)]) kabe = [kan_1, kan_2, kan_3, kan_4] self.turn.check_suukaikan(kabe) self.assertEqual(len(self.tile_stack.doras), 5) self.assertEqual(self.turn.suukaikan, False) def test_no_suukaikan(self): self.tile_stack.add_dora_indicator() naki_tile = Tile(Suit.SOUZU.value, 5) naki_tile.owner = self.player_1.seating_position kan = Huro(Naki.ANKAN, naki_tile, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) kabe = [kan] self.turn.check_suukaikan(kabe) self.assertEqual(self.turn.suukaikan, False) def test_rinshan_kaihou(self): naki_tile = Tile(Suit.SOUZU.value, 5) naki_tile.owner = self.player_1.seating_position kan = Huro(Naki.ANKAN, naki_tile, [Tile(Suit.SOUZU.value, 5) for i in range(4)]) self.player_1.tmp_huro = kan self.player_1.action_with_new_tile = MagicMock() self.player_1.action_with_new_tile.side_effect = [ ((Action.NAKI, Naki.ANKAN), None), ((Action.TSUMO, Naki.NONE), None) ] state, discard_tile, discard_pos, act = self.turn.draw_flow( self.player_1) self.assertEqual(state, 1) self.assertEqual(discard_tile, None) self.assertEqual(discard_pos, None) def test_suufon_renda(self): tile_ton = Tile(Suit.JIHAI.value, Jihai.TON.value) self.player_1.add_kawa(tile_ton) self.player_2.add_kawa(tile_ton) self.player_3.add_kawa(tile_ton) self.player_4.add_kawa(tile_ton) self.assertEqual(self.turn.check_suufon_renda(), True) def test_suufon_renda_counter_example(self): tile_ton = Tile(Suit.JIHAI.value, Jihai.TON.value) tile_nan = Tile(Suit.JIHAI.value, Jihai.NAN.value) self.player_1.add_kawa(tile_nan) self.player_2.add_kawa(tile_ton) self.player_3.add_kawa(tile_ton) self.player_4.add_kawa(tile_ton) self.assertEqual(self.turn.check_suufon_renda(), False)