diff --git a/src/engine/actions.py b/src/engine/actions.py index 8c973db..d3f34f8 100644 --- a/src/engine/actions.py +++ b/src/engine/actions.py @@ -18,12 +18,12 @@ def draw_tile(engine): # 从牌堆中摸一张牌 tile = engine.state.deck.pop(0) # 从牌堆抽取一张牌 engine.state.remaining_tiles -= 1 # 更新剩余牌数 - engine.state.hands[current_player].add_tile(tile) # 将牌加入当前玩家手牌 + engine.state.hands[current_player].add_tile(tile) # 将牌对象加入当前玩家手牌 # 获取牌名 tile_name = str(tile) # 调用 MahjongTile 的 __repr__ 方法 logger.info( - f"玩家 {current_player} 摸到一张牌: {tile_name}(索引 {tile})。" + f"玩家 {current_player} 摸到一张牌: {tile_name}。" f"剩余牌堆数量: {engine.state.remaining_tiles}" ) @@ -52,27 +52,27 @@ def discard_tile(self, tile): raise ValueError("打出的牌必须是 MahjongTile 对象") # 检查是否有这张牌 - if hand[tile] == 0: + if hand.tile_count[tile] == 0: logger.error(f"玩家 {current_player} 尝试打出不存在的牌: {tile}") raise ValueError("玩家没有这张牌") # 检查缺门规则 missing_suit = self.state.missing_suits[current_player] if tile.suit == missing_suit and any(t.suit == missing_suit for t in hand.tiles): - logger.error(f"玩家 {current_player} 尝试打出非缺门的牌: {tile}") + logger.error(f"玩家 {current_player} 仍有缺门的牌: {tile}") raise ValueError("必须先打完缺门花色的牌") # 从手牌中移除 - hand[tile] -= 1 + hand.remove_tile(tile) self.state.discards[current_player].append(tile) # 打出的牌名 - tile_name = get_tile_name(tile) + tile_name = str(tile) # 打出牌后打印状态 logger.info( - f"玩家 {current_player} 打出一张牌: {tile_name}(索引 {tile})。" - f"当前牌河: {[get_tile_name(t) for t in self.state.discards[current_player]]}" + f"玩家 {current_player} 打出一张牌: {tile_name}。" + f"当前牌河: {[str(t) for t in self.state.discards[current_player]]}" ) # 检查是否触发其他玩家的操作(碰、杠、胡牌) @@ -86,41 +86,57 @@ def peng(self, tile): 当前玩家碰牌逻辑,记录碰牌操作和手牌状态。 """ player = self.state.current_player - if self.state.hands[player][tile] < 2: - logger.error(f"玩家 {player} 尝试碰牌失败: {get_tile_name(tile)}(索引 {tile})") + hand = self.state.hands[player] + + if hand.tile_count[tile] < 2: + logger.error(f"玩家 {player} 尝试碰牌失败: {tile}") raise ValueError("碰牌条件不满足") - self.state.hands[player][tile] -= 2 # 减去两张牌 + # 从手牌中移除两张牌 + hand.tile_count[tile] -= 2 self.state.melds[player].append(("peng", tile)) # 加入明牌列表 - tile_name = get_tile_name(tile) - logger.info(f"玩家 {player} 碰了一张牌: {tile_name}(索引 {tile})。当前明牌: {self.state.melds[player]}") - + logger.info(f"玩家 {player} 碰了一张牌: {tile}。当前明牌: {self.state.melds[player]}") def gang(self, tile, mode): """ 当前玩家杠牌逻辑,记录杠牌类型和状态更新。 """ player = self.state.current_player - tile_name = get_tile_name(tile) - if mode == "ming" and self.state.hands[player][tile] == 3: - self.state.hands[player][tile] -= 3 - self.state.melds[player].append(("ming_gang", tile)) - logger.info(f"玩家 {player} 明杠: {tile_name}(索引 {tile})") - self.state.scores[player] += 1 # 奖励1分 - logger.info(f"玩家 {player} 因明杠获得1分") + # 检查牌的有效性 + if not isinstance(tile, MahjongTile): + logger.error(f"玩家 {player} 尝试杠牌时提供了无效的牌: {tile}") + raise ValueError("杠的牌必须是 MahjongTile 对象") - elif mode == "an" and self.state.hands[player][tile] == 4: - self.state.hands[player][tile] -= 4 - self.state.melds[player].append(("an_gang", tile)) - logger.info(f"玩家 {player} 暗杠: {tile_name}(索引 {tile})") - self.state.scores[player] += 1 # 奖励1分 - logger.info(f"玩家 {player} 因暗杠获得1分") + tile_name = str(tile) # 使用 MahjongTile 的 __repr__ 方法 + if mode == "ming": + # 明杠逻辑 + if self.state.hands[player].tile_count[tile] >= 3: + self.state.hands[player].tile_count[tile] -= 3 # 移除三张牌 + self.state.melds[player].append(("ming_gang", tile)) # 添加到明牌 + logger.info(f"玩家 {player} 明杠成功: {tile_name}") + self.state.scores[player] += 1 # 明杠奖励1分 + logger.info(f"玩家 {player} 因明杠获得1分,当前得分: {self.state.scores[player]}") + else: + logger.error(f"玩家 {player} 明杠失败: 手中牌数量不足") + raise ValueError("明杠条件不满足,需要至少三张相同的牌") + + elif mode == "an": + # 暗杠逻辑 + if self.state.hands[player].tile_count[tile] >= 4: + self.state.hands[player].tile_count[tile] -= 4 # 移除四张牌 + self.state.melds[player].append(("an_gang", tile)) # 添加到明牌 + logger.info(f"玩家 {player} 暗杠成功: {tile_name}") + self.state.scores[player] += 1 # 暗杠奖励1分 + logger.info(f"玩家 {player} 因暗杠获得1分,当前得分: {self.state.scores[player]}") + else: + logger.error(f"玩家 {player} 暗杠失败: 手中牌数量不足") + raise ValueError("暗杠条件不满足,需要至少四张相同的牌") else: - logger.error(f"玩家 {player} 尝试杠牌失败: {tile_name}(索引 {tile}),条件不满足") - raise ValueError("杠牌条件不满足") + logger.error(f"玩家 {player} 提供了无效的杠牌类型: {mode}") + raise ValueError("无效的杠牌类型,仅支持 'ming'、'an' 或 'bu'")