def score_honor_tiles(fixed_hand, grouped_hand, game=None, **kwargs): matched_count = 0 pair_involved = False for meld_type, _, tiles in fixed_hand: is_matched = tiles[0] == Tile.tile_map["honor"]["red"] is_matched = is_matched or tiles[0] == Tile.tile_map["honor"]["green"] is_matched = is_matched or tiles[0] == Tile.tile_map["honor"]["white"] matched_count += is_matched for meld_type, tiles in grouped_hand: is_matched = tiles[0] == Tile.tile_map["honor"]["red"] is_matched = is_matched or tiles[0] == Tile.tile_map["honor"]["green"] is_matched = is_matched or tiles[0] == Tile.tile_map["honor"]["white"] matched_count += is_matched if is_matched and meld_type == "pair": pair_involved = True if matched_count == 3: if not pair_involved: return __score_upper_limit, None if game is None else get_text( game.lang_code, "HKRULE_RGW_LARGE") return 5, None if game is None else get_text(game.lang_code, "HKRULE_RGW_SMALL") return matched_count - pair_involved, None if game is None else get_text( game.lang_code, "HKRULE_RGW_NORMAL") if matched_count - pair_involved > 0 else None
def score_one_suit(fixed_hand, grouped_hand, game=None, **kwargs): non_honor_suit = None honor_involved = False for _, _, tiles in fixed_hand: if tiles[0].suit == "honor": honor_involved = True continue if non_honor_suit is None: non_honor_suit = tiles[0].suit if tiles[0].suit != non_honor_suit: return 0, None for _, tiles in grouped_hand: if tiles[0].suit == "honor": honor_involved = True continue if non_honor_suit is None: non_honor_suit = tiles[0].suit if tiles[0].suit != non_honor_suit: return 0, None if honor_involved: return 3, None if game is None else get_text( game.lang_code, "HKRULE_ONE_SUIT_WITH_HONOR") return 7, None if game is None else get_text(game.lang_code, "HKRULE_ONE_SUIT")
def inline_language(userid, username, callback_data, bot, update): path = "settings/lang" if len(callback_data) == 0: lang_opts = [] for lang_code in get_lang_codes(): lang_opts.append((get_text(lang_code, "LANG_NAME"), lang_code)) keyboard = get_tg_inline_keyboard(path, lang_opts) update.callback_query.edit_message_reply_markup( reply_markup=keyboard, timeout=get_tgmsg_timeout()) else: tg_user = TGUser.load(userid) tg_user.change_lang(callback_data) tg_user.save() bot.send_message(tg_user.tg_userid, "Updated language settings: " + get_text(callback_data, "LANG_NAME"), timeout=get_tgmsg_timeout()) update.callback_query.edit_message_reply_markup( timeout=get_tgmsg_timeout()) bot.send_message(tg_user.tg_userid, get_text(tg_user.lang, "MSG_GREET") % tg_user.username, timeout=get_tgmsg_timeout())
def score_ones_nines(fixed_hand, grouped_hand, game=None, **kwargs): honor_involved = False for meld_type, _, tiles in fixed_hand: if meld_type == "chow": return 0, None if tiles[0].value != 1 and tiles[0].value != 9: if tiles[0].suit != "honor": return 0, None honor_involved = True for meld_type, tiles in grouped_hand: if meld_type == "chow": return 0, None if tiles[0].value != 1 and tiles[0].value != 9: if tiles[0].suit != "honor": return 0, None honor_involved = True if honor_involved: return 1, None if game is None else get_text(game.lang_code, "HKRULE_ONE_NINE_SMALL") return __score_upper_limit, None if game is None else get_text( game.lang_code, "HKRULE_ONE_NINE_LARGE")
def generate_TG_board(lang_code, player_name, fixed_hand, hand, neighbors, game, new_tile = None, print_stolen_tiles = False): global PIL_IMPORTED if not PIL_IMPORTED: raise Exception("failed to import PIL") board = TGBoard() board.add_aligned_line(get_text(lang_code, "TITLE_GAME")%(get_tile_name(lang_code, "honor", game.game_wind), game.deck_size)) for i in range(len(neighbors)): neighbor = neighbors[i] identifier = "%s"%neighbor.name if i == 0: identifier += " (%s)"%get_text(lang_code, "PLAYER_NEXT") elif i == 2: identifier += " (%s)"%get_text(lang_code, "PLAYER_PREV") fixed_hand_list = [] for meld_type, is_secret, tiles in neighbor.fixed_hand: meld_list = [] if is_secret: meld_list += [("back", 1), tiles[0], tiles[0], ("back", 1)] else: meld_list = tiles fixed_hand_list.extend(meld_list) board.add_aligned_line(identifier) if len(fixed_hand_list) > 0: board.add_aligned_line(*fixed_hand_list) board.add_aligned_line(("back", neighbor.hand_size), alignment = "right") board.add_aligned_line() board.add_aligned_line(get_text(lang_code, "TITLE_TILE_DISPOSED")) disposed_tiles = game.disposed_tiles while len(disposed_tiles) > 0: board.add_aligned_line(*disposed_tiles[0:15]) disposed_tiles = disposed_tiles[15:] board.add_aligned_line() fixed_hand_list, hand_list = [], list(hand) for meld_type, is_secret, tiles in fixed_hand: meld_list = [] if is_secret: meld_list = [("back", 1), tiles[0], tiles[0], ("back", 1)] else: meld_list = tiles fixed_hand_list.extend(meld_list) if new_tile is not None: hand_list.extend([("space", 1), new_tile]) board.add_aligned_line(get_text(lang_code, "TITLE_YOUR_TILES")) if len(fixed_hand_list) > 0: board.add_aligned_line(*fixed_hand_list) board.add_aligned_line() board.add_aligned_line(*hand_list, alignment = "right") return board
def score_game_wind(fixed_hand, grouped_hand, game=None, **kwargs): if game is not None: game_wind_tile = Tile.Tile("honor", game.game_wind) for _, _, tiles in fixed_hand: if tiles[0] == game_wind_tile: return 1, None if game is None else get_text( game.lang_code, "HKRULE_GAME_WIND" ) % game_wind_tile.get_display_name(game.lang_code) for _, tiles in grouped_hand: if tiles[0] == game_wind_tile: return 1, None if game is None else get_text( game.lang_code, "HKRULE_GAME_WIND" ) % game_wind_tile.get_display_name(game.lang_code) return 0, None
def decide_win(self, player, grouped_hand, new_tile, src, score, neighbors, game): self.begin_decision() if not self.skip_history and self.history_waiting: self.update_transition("terminal", REWARD_VICTORY) fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: if src == "steal": self.print_game_board(fixed_hand, hand, neighbors, game) self.print_msg("Someone just discarded a %s." % new_tile.symbol) else: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile=new_tile) self.print_msg("%s [%s] chooses to declare victory." % (self.player_name, display_name)) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_VICT") % (self.player_name)) self.print_msg("You can form a victory hand of: ") utils.print_hand(fixed_hand, end=" ") utils.print_hand(grouped_hand, end=" ") self.print_msg("[%d]" % score) self.end_decision() return True
def decide_pong(self, player, new_tile, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) self.print_msg("Someone just discarded a %s." % new_tile.symbol) criteria = self.majority_suit == "mixed" or new_tile.suit in [ self.majority_suit, "honor" ] self.end_decision() if criteria: self.print_msg("%s [%s] chooses to form a Pong %s%s%s." % (self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol)) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_PONG") % (self.player_name, new_tile.get_display_name(game.lang_code, is_short=False))) return True else: self.print_msg("%s [%s] chooses not to form a Pong %s%s%s." % (self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol)) return False
def score_pure_one_to_nine(fixed_hand, grouped_hand, game=None, **kwargs): suit = None record = [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0] for _, is_secret, tiles in fixed_hand: return 0, None for meld_type, tiles in grouped_hand: if tiles[0].suit == "honor": return 0, None if suit is None: suit = tiles[0].suit for tile in tiles: if tile.suit != suit: return 0, None record[tile.value] += 1 for i in range(1, len(record)): if record[i] == 0: return 0, None return __score_upper_limit, None if game is None else get_text( game.lang_code, "HKRULE_PURE_ONE_TO_NINE")
def decide_chow(self, player, new_tile, choices, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game) self.print_msg("Someone just discarded a %s."%new_tile.symbol) action = random.choice(choices) self.end_decision() if action == -1: self.print_msg("%s chooses not to Chow %s."%(self.player_name, new_tile.symbol)) return False, None else: chow_tiles_tgstrs = [] chow_tiles_str = "" for i in range(action - 1, action + 2): neighbor_tile = new_tile.generate_neighbor_tile(i) chow_tiles_str += neighbor_tile.symbol chow_tiles_tgstrs.append(neighbor_tile.get_display_name(game.lang_code, is_short = False)) self.print_msg("%s chooses to Chow %s."%(self.player_name, chow_tiles_str)) if game.lang_code is not None: game.add_notification(get_text(game.lang_code, "NOTI_CHOOSE_CHOW")%(self.player_name, ",".join(chow_tiles_tgstrs))) return True, action
def decide_kong(self, player, new_tile, kong_tile, location, src, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) if src == "steal": self.print_msg("Someone just discarded a %s."%kong_tile.symbol) elif src == "draw": self.print_msg("You just drew a %s"%kong_tile.symbol) elif src == "existing": self.print_msg("You have 4 %s in hand"%kong_tile.symbol) if location == "fixed_hand": location = "fixed hand" else: location = "hand" action = random.choice([0, 1]) self.end_decision() if action == 0: self.print_msg("%s [%s] chooses to form a Kong %s%s%s%s."%(self.player_name, display_name, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol)) if game.lang_code is not None: game.add_notification(get_text(game.lang_code, "NOTI_CHOOSE_KONG")%(self.player_name, kong_tile.get_display_name(game.lang_code, is_short = False))) return True else: self.print_msg("%s [%s] chooses not to form a Kong %s%s%s%s."%(self.player_name, display_name, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol)) return False
def decide_chow(self, player, new_tile, choices, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game) self.print_msg("Someone just discarded a %s."%new_tile.symbol) pg_model = get_MJPGFitted(self.pg_model_path) state = utils.extended_dnn_encode_state(player, neighbors, cpk_tile = new_tile) valid_actions = [34 + decisions_.index("no_action")] for choice in choices: valid_actions.append(34 + decisions_.index("chow_%d"%(choice))) action_filter = np.zeros(n_decisions) action_filter[valid_actions] = 1 action = None if not self.skip_history and self.history_waiting: self.update_transition(state, REWARD_NON_TERMINAL, action_filter) while True: if action is not None and not self.skip_history: self.update_history(state, action, action_filter) self.update_transition(state, REWARD_INVALID_DECISION, action_filter) action, value = pg_model.choose_action(state, action_filter = action_filter, return_value = True, strict_filter = True) if action in valid_actions: break elif not self.is_train: action = random.choice(valid_actions) break if not self.skip_history: self.update_history(state, action, action_filter) self.end_decision() if action == 34 + decisions_.index("no_action"): self.print_msg("%s chooses not to Chow %s [%.2f]."%(self.player_name, new_tile.symbol, value)) return False, None else: chow_tiles_tgstrs = [] chow_tiles_str = "" choice = int(decisions_[action - 34].split("_")[1]) for i in range(choice - 1, choice + 2): neighbor_tile = new_tile.generate_neighbor_tile(i) chow_tiles_str += neighbor_tile.symbol chow_tiles_tgstrs.append(neighbor_tile.get_display_name(game.lang_code, is_short = False)) self.print_msg("%s chooses to Chow %s [%.2f]."%(self.player_name, chow_tiles_str, value)) if game.lang_code is not None: game.add_notification(get_text(game.lang_code, "NOTI_CHOOSE_CHOW")%(self.player_name, ",".join(chow_tiles_tgstrs))) return True, choice
def decide_drop_tile(self, player, new_tile, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand state = utils.extended_dnn_encode_state(player, neighbors, new_tile=new_tile) if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) q_network = get_network[self.network_type](self.q_network_path) valid_actions = [] tiles = player.hand if new_tile is None else player.hand + [new_tile] for tile in tiles: valid_actions.append(Tile.convert_tile_index(tile)) action_filter = np.zeros(n_decisions) action_filter[valid_actions] = 1 action = None if not self.skip_history and self.history_waiting: self.update_transition(state, REWARD_NON_TERMINAL, action_filter) while True: if action is not None and not self.skip_history: self.update_history(state, action, action_filter) self.update_transition(state, REWARD_INVALID_DECISION, action_filter) action, value = q_network.choose_action( state, action_filter=action_filter, eps_greedy=self.is_train, return_value=True, strict_filter=not self.is_train) if action in valid_actions: break elif not self.is_train: action = random.choice(valid_actions) break if not self.skip_history: self.update_history(state, action, action_filter) drop_tile = Tile.convert_tile_index(action) self.print_msg( "%s [%s] chooses to drop %s. [%.2f]" % (self.player_name, display_name, drop_tile.symbol, value)) self.end_decision(True) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_DISCARD") % (self.player_name, drop_tile.get_display_name(game.lang_code, is_short=False))) return drop_tile
def decide_drop_tile(self, player, new_tile, neighbors, game): self.begin_decision() #print("drop") fixed_hand, hand = player.fixed_hand, player.hand state = utils.dnn_encode_state(player, neighbors) if not self.skip_history and self.history_waiting: self.update_transition(state, REWARD_NON_TERMINAL) if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) #model here #pg_model = get_MJPolicyGradient(self.pg_model_path) valid_actions = [] tiles = player.hand if new_tile is None else player.hand + [new_tile] for tile in tiles: valid_actions.append(Tile.convert_tile_index(tile)) action_filter = np.zeros(n_decisions) action_filter[valid_actions] = 1 action, value = self.actor.choose_action( state, action_filter=action_filter, return_value=True, strict_filter=not self.is_train) if action not in valid_actions: #print("invalid") if self.is_train: action = random.choice(valid_actions) if not self.skip_history: self.update_history(state, action, action_filter) self.update_transition(state, REWARD_INVALID_DECISION) else: raise Exception("Invalid action when not training") if not self.skip_history: self.update_history(state, action, action_filter) drop_tile = Tile.convert_tile_index(action) self.print_msg( "%s [%s] chooses to drop %s. [%.2f]" % (self.player_name, display_name, drop_tile.symbol, value)) self.end_decision(True) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_DISCARD") % (self.player_name, drop_tile.get_display_name(game.lang_code, is_short=False))) return drop_tile
def decide_pong(self, player, new_tile, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) self.print_msg("Someone just discarded a %s." % new_tile.symbol) pg_model = get_MJPolicyGradient(self.pg_model_path) state = utils.dnn_encode_state(player, neighbors) if not self.skip_history and self.history_waiting: self.update_transition(None, REWARD_NON_TERMINAL) valid_actions = [ 34 + decisions_.index("%s_pong" % new_tile.suit), 34 + decisions_.index("no_action") ] action_filter = np.zeros(n_decisions) action_filter[valid_actions] = 1 action, value = pg_model.choose_action(state, action_filter=action_filter, return_value=True, strict_filter=not self.is_train) if action not in valid_actions: if self.is_train: action = random.choice(valid_actions) if not self.skip_history: self.update_history(state, action, action_filter) self.update_transition(None, REWARD_INVALID_DECISION) else: raise Exception("Invalid action when not training") if not self.skip_history: self.update_history(state, action, action_filter) self.end_decision() if action == 34 + decisions_.index("no_action"): self.print_msg("%s [%s] chooses to form a Pong %s%s%s. [%.2f]" % (self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol, value)) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_PONG") % (self.player_name, new_tile.get_display_name(game.lang_code, is_short=False))) return True else: self.print_msg( "%s [%s] chooses not to form a Pong %s%s%s. [%.2f]" % (self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol, value)) return False
def decide_kong(self, player, new_tile, kong_tile, location, src, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) if src == "steal": self.print_msg("Someone just discarded a %s." % kong_tile.symbol) elif src == "draw": self.print_msg("You just drew a %s" % kong_tile.symbol) elif src == "existing": self.print_msg("You have 4 %s in hand" % kong_tile.symbol) if location == "fixed_hand": location = "fixed hand" else: location = "hand" q_network = get_DeepQNetwork(self.q_network_path) state = qnetwork_encode_state(fixed_hand, hand) if self.q_network_waiting: self.update_transition(0, state) valid_actions = [ q_decisions.index(new_tile.suit + "_pong"), q_decisions.index("no_action") ] action_filter = np.full(len(q_decisions), float("-inf")) action_filter[valid_actions] = 0 action = q_network.choose_action(state, action_filter=action_filter, eps_greedy=self.q_network_is_train) self.__update_history(state, action, action_filter) self.end_decision() if action == q_decisions.index("no_action"): self.print_msg( "%s [%s] chooses to form a Kong %s%s%s%s." % (self.player_name, display_name, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol)) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_KONG") % (self.player_name, kong_tile.get_display_name(game.lang_code, is_short=False))) return True else: self.print_msg( "%s [%s] chooses not to form a Kong %s%s%s%s." % (self.player_name, display_name, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol)) return False
def decide_kong(self, player, new_tile, kong_tile, location, src, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) if src == "steal": self.print_msg("Someone just discarded a %s."%kong_tile.symbol) elif src == "draw": self.print_msg("You just drew a %s"%kong_tile.symbol) elif src == "existing": self.print_msg("You have 4 %s in hand"%kong_tile.symbol) if location == "fixed_hand": location = "fixed hand" else: location = "hand" pg_model = get_MJPGFitted(self.pg_model_path) state = utils.extended_dnn_encode_state(player, neighbors, cpk_tile = kong_tile) valid_actions = [34 + decisions_.index("pong"), 34 + decisions_.index("no_action")] action_filter = np.zeros(n_decisions) action_filter[valid_actions] = 1 action = None if not self.skip_history and self.history_waiting: self.update_transition(state, REWARD_NON_TERMINAL, action_filter) while True: if action is not None and not self.skip_history: self.update_history(state, action, action_filter) self.update_transition(state, REWARD_INVALID_DECISION, action_filter) action, value = pg_model.choose_action(state, action_filter = action_filter, return_value = True, strict_filter = True) if action in valid_actions: break elif not self.is_train: action = random.choice(valid_actions) break if not self.skip_history: self.update_history(state, action, action_filter) self.end_decision() if action == 34 + decisions_.index("no_action"): self.print_msg("%s [%s] chooses to form a Kong %s%s%s%s [%.2f]."%(self.player_name, display_name, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, value)) if game.lang_code is not None: game.add_notification(get_text(game.lang_code, "NOTI_CHOOSE_KONG")%(self.player_name, kong_tile.get_display_name(game.lang_code, is_short = False))) return True else: self.print_msg("%s [%s] chooses not to form a Kong %s%s%s%s [%.2f]."%(self.player_name, display_name, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, value)) return False
def score_all_pongs(fixed_hand, grouped_hand, game=None, **kwargs): for meld_type, _, _ in fixed_hand: if meld_type == "chow": return 0, None for meld_type, _ in grouped_hand: if meld_type == "chow": return 0, None return 3, None if game is None else get_text(game.lang_code, "HKRULE_ALL_PONGS")
def score_four_kongs(fixed_hand, game=None, **kwargs): count = 0 for meld_type, _, _ in fixed_hand: if meld_type == "kong": count += 1 if count >= 4: return __score_upper_limit, None if game is None else get_text( game.lang_code, "HKRULE_FOUR_KONGS") return 0, None
def score_pure_honor_suit(fixed_hand, grouped_hand, game=None, **kwargs): for _, _, tiles in fixed_hand: if tiles[0].suit != "honor": return 0, None for _, tiles in grouped_hand: if tiles[0].suit != "honor": return 0, None return __score_upper_limit, None if game is None else get_text( game.lang_code, "HKRULE_PURE_HONOR_SUIT")
def score_all_chows(fixed_hand, grouped_hand, game=None, **kwargs): for meld_type, _, _ in fixed_hand: if meld_type != "chow": return 0, None for meld_type, _ in grouped_hand: if meld_type != "chow" and meld_type != "pair": return 0, None return 1, None if game is None else get_text(game.lang_code, "HKRULE_ALL_CHOWS")
def decide_chow(self, player, new_tile, choices, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game) self.print_msg("Someone just discarded a %s." % new_tile.symbol) q_network = get_DeepQNetwork(self.q_network_path) state = qnetwork_encode_state(fixed_hand, hand) if self.q_network_waiting: self.update_transition(0, state) valid_actions = [ q_decisions.index(new_tile.suit + "_chow"), q_decisions.index("no_action") ] action_filter = np.full(len(q_decisions), float("-inf")) action_filter[valid_actions] = 0 action = q_network.choose_action(state, action_filter=action_filter, eps_greedy=self.q_network_is_train) self.__update_history(state, action, action_filter) self.end_decision() if action == q_decisions.index("no_action"): self.print_msg("%s chooses not to Chow %s." % (self.player_name, new_tile.symbol)) return False, None else: chow_tiles_tgstrs = [] chow_tiles_str = "" choice = random.choice(choices) for i in range(choice - 1, choice + 2): neighbor_tile = new_tile.generate_neighbor_tile(i) chow_tiles_str += neighbor_tile.symbol chow_tiles_tgstrs.append( neighbor_tile.get_display_name(game.lang_code, is_short=False)) self.print_msg("%s chooses to Chow %s." % (self.player_name, chow_tiles_str)) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_CHOW") % (self.player_name, ",".join(chow_tiles_tgstrs))) return True, choice
def generate_TG_end_board(lang_code, players, game, center_player, extra_tile = None): global PIL_IMPORTED if not PIL_IMPORTED: raise Exception("failed to import PIL") board = TGBoard() board.add_aligned_line(get_text(lang_code, "TITLE_GAME")%(get_tile_name(lang_code, "honor", game.game_wind), game.deck_size)) center_player_index = players.index(center_player) for i in range(4): player_index = (center_player_index + i + 1) % 4 player = players[player_index] identifier = "%s"%player.name if i == 0: identifier += " (%s)"%get_text(lang_code, "PLAYER_NEXT") elif i == 2: identifier += " (%s)"%get_text(lang_code, "PLAYER_PREV") fixed_hand_list, hand_list = [], list(player.hand) for meld_type, is_secret, tiles in player.fixed_hand: meld_list = [] if is_secret: meld_list = [("back", 1), tiles[0], tiles[0], ("back", 1)] else: meld_list = tiles fixed_hand_list.extend(meld_list) if extra_tile is not None and extra_tile[0] == player: hand_list.extend([("space", 1), extra_tile[1]]) board.add_aligned_line(identifier) if len(fixed_hand_list) > 0: board.add_aligned_line(*fixed_hand_list) board.add_aligned_line() board.add_aligned_line(*hand_list, alignment = "right") board.add_aligned_line() return board
def decide_drop_tile(self, player, new_tile, neighbors, game): self.begin_decision() tiles = player.hand if new_tile is not None: tiles += [new_tile] drop_tile = random.choice(tiles) self.print_msg("%s [%s] chooses to drop %s."%(self.player_name, display_name, drop_tile.symbol)) self.end_decision(True) if game.lang_code is not None: game.add_notification(get_text(game.lang_code, "NOTI_CHOOSE_DISCARD")%(self.player_name, drop_tile.get_display_name(game.lang_code, is_short = False))) return drop_tile
def score_secret_all_pongs_with_draw(fixed_hand, grouped_hand, additional_tile_src, game=None, **kwargs): if additional_tile_src != "draw": return 0, None for meld_type, is_secret, _ in fixed_hand: return 0, None for meld_type, _ in grouped_hand: if meld_type == "chow": return 0, None return __score_upper_limit, None if game is None else get_text( game.lang_code, "HKRULE_ALL_PONGS_WITH_DRAW")
def decide_drop_tile(self, player, new_tile, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) drop_tile_score, drop_tile = None, None hand = list(hand) if new_tile is not None: hand.append(new_tile) used_tiles_map, hand_tiles_map, neighbor_suit_prob = self.preprocess_info( hand, player, neighbors) if (136 - 13 * 4) * (1 - self.s_explore ) >= game.deck_size and self.majority_suit is None: self.majority_suit = self.decide_strategy(hand, used_tiles_map, neighbor_suit_prob) melds_distribution = self.scoring_distribution_melds( hand, used_tiles_map, hand_tiles_map) score_tile_rank = [] for i in range(len(melds_distribution)): score_tile_rank.append((melds_distribution[i], hand[i])) score_tile_rank = sorted(score_tile_rank, key=lambda x: x[0]) drop_tile_score, drop_tile = score_tile_rank[0] self.print_msg("%s [%s] chooses to drop %s (%.2f) [majority = %s]." % (self.player_name, display_name, drop_tile.symbol, drop_tile_score, self.majority_suit)) self.end_decision(True) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_DISCARD") % (self.player_name, drop_tile.get_display_name(game.lang_code, is_short=False))) return drop_tile
def decide_pong(self, player, new_tile, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) self.print_msg("Someone just discarded a %s."%new_tile.symbol) action = random.choice([0, 1]) self.end_decision() if action == 0: self.print_msg("%s [%s] chooses to form a Pong %s%s%s."%(self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol)) if game.lang_code is not None: game.add_notification(get_text(game.lang_code, "NOTI_CHOOSE_PONG")%(self.player_name, new_tile.get_display_name(game.lang_code, is_short = False))) return True else: self.print_msg("%s [%s] chooses not to form a Pong %s%s%s."%(self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol)) return False
def score_four_winds(fixed_hand, grouped_hand, game=None, **kwargs): match_count = 0 for _, _, tiles in fixed_hand: if tiles[0].suit == "honor": match_count += tiles[0] == Tile.tile_map["honor"]["east"] match_count += tiles[0] == Tile.tile_map["honor"]["south"] match_count += tiles[0] == Tile.tile_map["honor"]["west"] match_count += tiles[0] == Tile.tile_map["honor"]["north"] for _, tiles in grouped_hand: if tiles[0].suit == "honor": match_count += tiles[0] == Tile.tile_map["honor"]["east"] match_count += tiles[0] == Tile.tile_map["honor"]["south"] match_count += tiles[0] == Tile.tile_map["honor"]["west"] match_count += tiles[0] == Tile.tile_map["honor"]["north"] if match_count == 4: return __score_upper_limit, None if game is None else get_text( game.lang_code, "HKRULE_FOUR_WINDS") return 0, None
def validate_thirteen_yiu(fixed_hand, hand, additional_tile, game, **kwargs): if len(fixed_hand) > 0: return 0, None required_tiles_map = {tile: 0 for tile in THIRTEEN_YIU_TILES} tiles = hand + [additional_tile] if additional_tile is not None else hand for tile in tiles: if tile not in required_tiles_map: return 0, None else: required_tiles_map[tile] += 1 n_total = 0 for tile, count in required_tiles_map.items(): n_total += count if count == 0: return 0, None if n_total != 14: return 0, None return __score_upper_limit, None if game is None else get_text( game.lang_code, "HKRULE_THIRTEEN_TERMINAL_TILES")
def decide_pong(self, player, new_tile, neighbors, game): self.begin_decision() fixed_hand, hand = player.fixed_hand, player.hand if self.display_step: self.print_game_board(fixed_hand, hand, neighbors, game, new_tile) self.print_msg("Someone just discarded a %s." % new_tile.symbol) q_network = get_network[self.network_type](self.q_network_path) state = utils.extended_dnn_encode_state(player, neighbors, cpk_tile=new_tile) valid_actions = [ 34 + decisions_.index("%s_pong" % new_tile.suit), 34 + decisions_.index("no_action") ] action_filter = np.zeros(n_decisions) action_filter[valid_actions] = 1 action = None if not self.skip_history and self.history_waiting: self.update_transition(state, REWARD_NON_TERMINAL, action_filter) while True: if action is not None and not self.skip_history: self.update_history(state, action, action_filter) self.update_transition(state, REWARD_INVALID_DECISION, action_filter) action, value = q_network.choose_action( state, action_filter=action_filter, eps_greedy=self.is_train, return_value=True, strict_filter=not self.is_train) if action in valid_actions: break elif not self.is_train: action = random.choice(valid_actions) break if not self.skip_history: self.update_history(state, action, action_filter) self.end_decision() if action == 34 + decisions_.index("no_action"): self.print_msg("%s [%s] chooses to form a Pong %s%s%s. [%.2f]" % (self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol, value)) if game.lang_code is not None: game.add_notification( get_text(game.lang_code, "NOTI_CHOOSE_PONG") % (self.player_name, new_tile.get_display_name(game.lang_code, is_short=False))) return True else: self.print_msg( "%s [%s] chooses not to form a Pong %s%s%s. [%.2f]" % (self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol, value)) return False