Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from mahjong.utils import is_honor, plus_dora, simplify 

2from utils.decisions_logger import MeldPrint 

3 

4 

5class StatisticsCollector: 

6 @staticmethod 

7 def collect_stat_for_enemy_riichi_hand_cost(tile_136, enemy, main_player): 

8 tile_34 = tile_136 // 4 

9 

10 riichi_discard = [x for x in enemy.discards if x.riichi_discard] 

11 if riichi_discard: 

12 assert len(riichi_discard) == 1 

13 riichi_discard = riichi_discard[0] 

14 else: 

15 # FIXME: it happens when user called riichi and we are trying to decide to we need to open hand on 

16 # riichi tile or not. We need to process this situation correctly. 

17 riichi_discard = enemy.discards[-1] 

18 

19 riichi_called_on_step = enemy.discards.index(riichi_discard) + 1 

20 

21 total_dora_in_game = len(enemy.table.dora_indicators) * 4 + (3 * int(enemy.table.has_aka_dora)) 

22 visible_tiles = enemy.table.revealed_tiles_136 + main_player.closed_hand 

23 visible_dora_tiles = sum( 

24 [plus_dora(x, enemy.table.dora_indicators, add_aka_dora=enemy.table.has_aka_dora) for x in visible_tiles] 

25 ) 

26 live_dora_tiles = total_dora_in_game - visible_dora_tiles 

27 assert live_dora_tiles >= 0, "Live dora tiles can't be less than 0" 

28 

29 number_of_kan_in_enemy_hand = 0 

30 number_of_dora_in_enemy_kan_sets = 0 

31 number_of_yakuhai_enemy_kan_sets = 0 

32 for meld in enemy.melds: 

33 # if he is in riichi he can only have closed kan 

34 assert meld.type == MeldPrint.KAN and not meld.opened 

35 

36 number_of_kan_in_enemy_hand += 1 

37 

38 for tile in meld.tiles: 

39 number_of_dora_in_enemy_kan_sets += plus_dora( 

40 tile, enemy.table.dora_indicators, add_aka_dora=enemy.table.has_aka_dora 

41 ) 

42 

43 tile_meld_34 = meld.tiles[0] // 4 

44 if tile_meld_34 in enemy.valued_honors: 

45 number_of_yakuhai_enemy_kan_sets += 1 

46 

47 number_of_other_player_kan_sets = 0 

48 for other_player in enemy.table.players: 

49 if other_player.seat == enemy.seat: 

50 continue 

51 

52 for meld in other_player.melds: 

53 if meld.type == MeldPrint.KAN or meld.type == MeldPrint.SHOUMINKAN: 

54 number_of_other_player_kan_sets += 1 

55 

56 tile_category = "" 

57 # additional danger for tiles that could be used for tanyao 

58 if not is_honor(tile_34): 

59 # +1 here to make it more readable 

60 simplified_tile = simplify(tile_34) + 1 

61 

62 if simplified_tile in [4, 5, 6]: 

63 tile_category = "middle" 

64 

65 if simplified_tile in [2, 3, 7, 8]: 

66 tile_category = "edge" 

67 

68 if simplified_tile in [1, 9]: 

69 tile_category = "terminal" 

70 else: 

71 tile_category = "honor" 

72 if tile_34 in enemy.valued_honors: 

73 tile_category = "valuable_honor" 

74 

75 return { 

76 "is_dealer": enemy.is_dealer and 1 or 0, 

77 "riichi_called_on_step": riichi_called_on_step, 

78 "current_enemy_step": len(enemy.discards), 

79 "wind_number": main_player.table.round_wind_number, 

80 "scores": enemy.scores, 

81 "is_tsumogiri_riichi": riichi_discard.is_tsumogiri and 1 or 0, 

82 "is_oikake_riichi": enemy.is_oikake_riichi and 1 or 0, 

83 "is_oikake_riichi_against_dealer_riichi_threat": enemy.is_oikake_riichi_against_dealer_riichi_threat 

84 and 1 

85 or 0, 

86 "is_riichi_against_open_hand_threat": enemy.is_riichi_against_open_hand_threat and 1 or 0, 

87 "number_of_kan_in_enemy_hand": number_of_kan_in_enemy_hand, 

88 "number_of_dora_in_enemy_kan_sets": number_of_dora_in_enemy_kan_sets, 

89 "number_of_yakuhai_enemy_kan_sets": number_of_yakuhai_enemy_kan_sets, 

90 "number_of_other_player_kan_sets": number_of_other_player_kan_sets, 

91 "live_dora_tiles": live_dora_tiles, 

92 "tile_plus_dora": plus_dora(tile_136, enemy.table.dora_indicators, add_aka_dora=enemy.table.has_aka_dora), 

93 "tile_category": tile_category, 

94 "discards_before_riichi_34": ";".join([str(x.value // 4) for x in enemy.discards[:riichi_called_on_step]]), 

95 }