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_v2.chinitsu import ChinitsuStrategy 

3from game.ai.strategies_v2.common_open_tempai import CommonOpenTempaiStrategy 

4from game.ai.strategies_v2.formal_tempai import FormalTempaiStrategy 

5from game.ai.strategies_v2.honitsu import HonitsuStrategy 

6from game.ai.strategies_v2.main import BaseStrategy 

7from game.ai.strategies_v2.tanyao import TanyaoStrategy 

8from game.ai.strategies_v2.yakuhai import YakuhaiStrategy 

9from mahjong.shanten import Shanten 

10from mahjong.tile import TilesConverter 

11 

12 

13class OpenHandHandlerV2: 

14 player = None 

15 current_strategy = None 

16 last_discard_option = None 

17 

18 def __init__(self, player): 

19 self.player = player 

20 

21 def determine_strategy(self, tiles_136, meld_tile=None): 

22 # for already opened hand we don't need to give up on selected strategy 

23 if self.player.is_open_hand and self.current_strategy: 

24 return False 

25 

26 old_strategy = self.current_strategy 

27 self.current_strategy = None 

28 

29 # order is important, we add strategies with the highest priority first 

30 strategies = [] 

31 

32 # first priority 

33 if self.player.table.has_open_tanyao: 

34 strategies.append(TanyaoStrategy(BaseStrategy.TANYAO, self.player)) 

35 

36 # second priority 

37 strategies.append(HonitsuStrategy(BaseStrategy.HONITSU, self.player)) 

38 strategies.append(ChinitsuStrategy(BaseStrategy.CHINITSU, self.player)) 

39 

40 # third priority 

41 strategies.append(YakuhaiStrategy(BaseStrategy.YAKUHAI, self.player)) 

42 

43 # fourth priority 

44 strategies.append(FormalTempaiStrategy(BaseStrategy.FORMAL_TEMPAI, self.player)) 

45 strategies.append(CommonOpenTempaiStrategy(BaseStrategy.COMMON_OPEN_TEMPAI, self.player)) 

46 

47 for strategy in strategies: 

48 if strategy.should_activate_strategy(tiles_136, meld_tile=meld_tile): 

49 self.current_strategy = strategy 

50 break 

51 

52 if self.current_strategy and (not old_strategy or self.current_strategy.type != old_strategy.type): 

53 self.player.logger.debug( 

54 log.STRATEGY_ACTIVATE, 

55 context=self.current_strategy, 

56 ) 

57 

58 if not self.current_strategy and old_strategy: 

59 self.player.logger.debug(log.STRATEGY_DROP, context=old_strategy) 

60 

61 return self.current_strategy and True or False 

62 

63 def try_to_call_meld(self, tile_136, is_kamicha_discard): 

64 tiles_136_previous = self.player.tiles[:] 

65 closed_hand_136_previous = self.player.closed_hand[:] 

66 tiles_136 = tiles_136_previous + [tile_136] 

67 self.determine_strategy(tiles_136, meld_tile=tile_136) 

68 

69 if not self.current_strategy: 

70 self.player.logger.debug(log.MELD_DEBUG, "We don't have active strategy. Abort melding.") 

71 return None, None 

72 

73 closed_hand_34_previous = TilesConverter.to_34_array(closed_hand_136_previous) 

74 previous_shanten, _ = self.player.ai.hand_builder.calculate_shanten_and_decide_hand_structure( 

75 closed_hand_34_previous 

76 ) 

77 

78 if previous_shanten == Shanten.AGARI_STATE and not self.current_strategy.can_meld_into_agari(): 

79 return None, None 

80 

81 meld, discard_option = self.current_strategy.try_to_call_meld(tile_136, is_kamicha_discard, tiles_136) 

82 if discard_option: 

83 self.last_discard_option = discard_option 

84 

85 self.player.logger.debug( 

86 log.MELD_CALL, 

87 "We decided to open hand", 

88 context=[ 

89 f"Hand: {self.player.format_hand_for_print(tile_136)}", 

90 f"Meld: {meld.serialize()}", 

91 f"Discard after meld: {discard_option.serialize()}", 

92 ], 

93 ) 

94 

95 return meld, discard_option