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

1import utils.decisions_constants as log 

2from game.ai.strategies.main import BaseStrategy 

3from mahjong.tile import TilesConverter 

4from utils.test_helpers import tiles_to_string 

5 

6 

7class CommonOpenTempaiStrategy(BaseStrategy): 

8 min_shanten = 1 

9 

10 def should_activate_strategy(self, tiles_136, meld_tile=None): 

11 """ 

12 We activate this strategy only when we have a chance to meld for good tempai. 

13 """ 

14 result = super(CommonOpenTempaiStrategy, self).should_activate_strategy(tiles_136) 

15 if not result: 

16 return False 

17 

18 # we only use this strategy for meld opportunities, if it's a self draw, just skip it 

19 if meld_tile is None: 

20 assert tiles_136 == self.player.tiles 

21 return False 

22 

23 # only go from 1-shanten to tempai with this strategy 

24 if self.player.ai.shanten != 1: 

25 return False 

26 

27 tiles_copy = self.player.closed_hand[:] + [meld_tile] 

28 tiles_34 = TilesConverter.to_34_array(tiles_copy) 

29 # we only open for tempai with that strategy 

30 new_shanten = self.player.ai.calculate_shanten_or_get_from_cache(tiles_34, use_chiitoitsu=False) 

31 

32 # we always activate this strategy if we have a chance to get tempai 

33 # then we will validate meld to see if it's really a good one 

34 return self.player.ai.shanten == 1 and new_shanten == 0 

35 

36 def is_tile_suitable(self, tile): 

37 """ 

38 All tiles are suitable for formal tempai. 

39 :param tile: 136 tiles format 

40 :return: True 

41 """ 

42 return True 

43 

44 def validate_meld(self, chosen_meld_dict): 

45 # if we have already opened our hand, let's go by default riles 

46 if self.player.is_open_hand: 

47 return True 

48 

49 # choose if base method requires us to keep hand closed 

50 if not super(CommonOpenTempaiStrategy, self).validate_meld(chosen_meld_dict): 

51 return False 

52 

53 selected_tile = chosen_meld_dict["discard_tile"] 

54 logger_context = { 

55 "hand": tiles_to_string(self.player.closed_hand), 

56 "meld": chosen_meld_dict, 

57 "new_shanten": selected_tile.shanten, 

58 "new_ukeire": selected_tile.ukeire, 

59 } 

60 

61 if selected_tile.shanten != 0: 

62 self.player.logger.debug( 

63 log.MELD_DEBUG, 

64 "Common tempai: for whatever reason we didn't choose discard giving us tempai, so abort melding", 

65 logger_context, 

66 ) 

67 return False 

68 

69 if not selected_tile.tempai_descriptor: 

70 self.player.logger.debug( 

71 log.MELD_DEBUG, "Common tempai: no tempai descriptor found, so abort melding", logger_context 

72 ) 

73 return False 

74 

75 if selected_tile.ukeire == 0: 

76 self.player.logger.debug(log.MELD_DEBUG, "Common tempai: 0 ukeire, abort melding", logger_context) 

77 return False 

78 

79 if selected_tile.tempai_descriptor["hand_cost"]: 

80 hand_cost = selected_tile.tempai_descriptor["hand_cost"] 

81 else: 

82 hand_cost = selected_tile.tempai_descriptor["cost_x_ukeire"] / selected_tile.ukeire 

83 

84 if hand_cost == 0: 

85 self.player.logger.debug(log.MELD_DEBUG, "Common tempai: hand costs nothing, abort melding", logger_context) 

86 return False 

87 

88 # maybe we need a special handling due to placement 

89 # we have already checked that our meld is enough, now let's check that maybe we don't need to aim 

90 # for higher costs 

91 enough_cost = 32000 

92 if self.player.ai.placement.is_oorasu: 

93 placement = self.player.ai.placement.get_current_placement() 

94 if placement and placement["place"] == 4: 

95 enough_cost = self.player.ai.placement.get_minimal_cost_needed_considering_west() 

96 

97 if self.player.round_step <= 6: 

98 if hand_cost >= min(7700, enough_cost): 

99 self.player.logger.debug(log.MELD_DEBUG, "Common tempai: the cost is good, call meld", logger_context) 

100 return True 

101 elif self.player.round_step <= 12: 

102 if self.player.is_dealer: 

103 if hand_cost >= min(5800, enough_cost): 

104 self.player.logger.debug( 

105 log.MELD_DEBUG, 

106 "Common tempai: the cost is ok for dealer and round step, call meld", 

107 logger_context, 

108 ) 

109 return True 

110 else: 

111 if hand_cost >= min(3900, enough_cost): 

112 self.player.logger.debug( 

113 log.MELD_DEBUG, 

114 "Common tempai: the cost is ok for non-dealer and round step, call meld", 

115 logger_context, 

116 ) 

117 return True 

118 else: 

119 self.player.logger.debug( 

120 log.MELD_DEBUG, "Common tempai: taking any tempai in the late round", logger_context 

121 ) 

122 return True 

123 

124 self.player.logger.debug(log.MELD_DEBUG, "Common tempai: the cost is meh, so abort melding", logger_context) 

125 return False