diff --git a/models/ppo_doudizhu_model.zip b/models/ppo_doudizhu_model.zip index 3f6ded5..9390e81 100644 Binary files a/models/ppo_doudizhu_model.zip and b/models/ppo_doudizhu_model.zip differ diff --git a/src/engine/dizhu/dizhu_engine.py b/src/engine/dizhu/dizhu_engine.py index f0ed983..a1dc12c 100644 --- a/src/engine/dizhu/dizhu_engine.py +++ b/src/engine/dizhu/dizhu_engine.py @@ -2,6 +2,8 @@ import numpy as np from loguru import logger from src.engine.dizhu.player_state import PlayerState from src.engine.dizhu.deck import Deck +from src.engine.dizhu.utils import card_to_string + class DiZhuEngine: def __init__(self): @@ -32,9 +34,9 @@ class DiZhuEngine: # 日志输出 logger.info("游戏初始化完成") - logger.info(f"地主牌: {self.landlord_cards}") + logger.info(f"地主牌: {[card_to_string(card) for card in self.landlord_cards]}") for i, player in enumerate(self.players): - logger.info(f"玩家 {i + 1} ({player.role}) 手牌: {player.hand_cards}") + logger.info(f"玩家 {i + 1} ({player.role}) 手牌: {player.get_hand_cards_as_strings()}") def get_current_player(self): """ @@ -42,6 +44,7 @@ class DiZhuEngine: """ current_player = self.players[self.current_player_index] logger.info(f"当前玩家: 玩家 {self.current_player_index + 1} ({current_player.role})") + logger.info(f"当前玩家手牌: {current_player.get_hand_cards_as_strings()}") return current_player def step(self, action): @@ -51,28 +54,24 @@ class DiZhuEngine: """ current_player = self.get_current_player() - logger.info(f"玩家 {self.current_player_index + 1} 的动作: {action}") - if action == "pass": - # 过牌作为单独的历史记录 - current_player.history.append([]) logger.info(f"玩家 {self.current_player_index + 1} 选择过牌") + current_player.history.append([]) else: - # 确保动作始终为列表 if not isinstance(action, list): action = [action] - # 检查动作合法性 if not all(card in current_player.hand_cards for card in action): logger.error(f"玩家 {self.current_player_index + 1} 的动作非法: {action}") raise ValueError(f"玩家手牌不足以完成此次出牌: {action}") + # 移除出牌 for card in action: current_player.hand_cards.remove(card) - # 记录动作 current_player.history.append(action) - logger.info(f"玩家 {self.current_player_index + 1} 出牌: {action}") - # 检查游戏是否结束 + logger.info(f"玩家 {self.current_player_index + 1} 出牌: {[card_to_string(card) for card in action]}") + logger.info(f"玩家 {self.current_player_index + 1} 剩余手牌: {current_player.get_hand_cards_as_strings()}") + if not current_player.hand_cards: self.game_over = True logger.info(f"游戏结束!玩家 {self.current_player_index + 1} ({current_player.role}) 获胜") @@ -100,10 +99,10 @@ class DiZhuEngine: "game_over": self.game_over, } logger.info("当前游戏状态: ") - logger.info(f"地主牌: {self.landlord_cards}") + logger.info(f"地主牌: {[card_to_string(card) for card in self.landlord_cards]}") for i, player in enumerate(self.players): - logger.info(f"玩家 {i + 1} ({player.role}) 手牌: {player.hand_cards}") - logger.info(f"玩家 {i + 1} 出牌历史: {player.history}") + logger.info(f"玩家 {i + 1} ({player.role}) 手牌: {player.get_hand_cards_as_strings()}") + logger.info(f"玩家 {i + 1} 出牌历史: {[card_to_string(card) for play in player.history for card in play]}") logger.info(f"当前玩家索引: {self.current_player_index}") logger.info(f"游戏是否结束: {self.game_over}") return state diff --git a/src/engine/dizhu/player_state.py b/src/engine/dizhu/player_state.py index 5899e2d..dbf284f 100644 --- a/src/engine/dizhu/player_state.py +++ b/src/engine/dizhu/player_state.py @@ -1,7 +1,22 @@ from collections import deque +from src.engine.dizhu.utils import card_to_string class PlayerState: def __init__(self, hand_cards, role): self.hand_cards = hand_cards # 玩家手牌 self.role = role # "地主" 或 "农民" self.history = deque() # 出牌历史,使用 deque + + def get_hand_cards_as_strings(self): + """ + 获取玩家手牌的具体牌型字符串 + :return: 手牌字符串列表 + """ + return [card_to_string(card) for card in self.hand_cards] + + def __repr__(self): + """ + 返回玩家的字符串表示,包括手牌和角色 + """ + hand_cards_str = ", ".join(self.get_hand_cards_as_strings()) + return f"玩家角色: {self.role}, 手牌: [{hand_cards_str}]" diff --git a/src/engine/dizhu/utils.py b/src/engine/dizhu/utils.py new file mode 100644 index 0000000..32d4172 --- /dev/null +++ b/src/engine/dizhu/utils.py @@ -0,0 +1,22 @@ + + +def card_to_string(card_index): + """ + 将牌的索引转换为具体牌型的字符串表示 + :param card_index: 牌的索引(0-53) + :return: 具体牌型字符串 + """ + suits = ['♠️', '♥️', '♦️', '♣️'] # 花色 + values = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2'] + + if card_index < 52: + # 普通牌:计算花色和牌面值 + value = values[card_index // 4] + suit = suits[card_index % 4] + return f"{suit}{value}" + elif card_index == 52: + return "小王" + elif card_index == 53: + return "大王" + else: + raise ValueError(f"无效的牌索引: {card_index}")