1
This commit is contained in:
2024-12-01 16:23:45 +08:00
parent efc71af70c
commit 66310aa2f5
4 changed files with 112 additions and 118 deletions

View File

@@ -2,6 +2,7 @@ from random import random
from loguru import logger
from src.engine.mahjong_tile import MahjongTile
from src.engine.calculate_fan import calculate_fan
def draw_tile(engine):
@@ -204,21 +205,21 @@ def check_other_players(self, tile):
# 优先检查胡牌
if self.can_win(self.state.hands[player], self.state.melds[player], self.state.missing_suits[player]):
logger.info(f"玩家 {player} 可以胡玩家 {current_player} 的牌: {tile}")
self.handle_win(player, current_player, tile)
handle_win(player, current_player, tile)
actions_taken = True
break # 胡牌后结束
# 检查是否可以杠牌
if self.state.hands[player].tile_count[tile] >= 3:
logger.info(f"玩家 {player} 可以杠玩家 {current_player} 的牌: {tile}")
if self.handle_gang(player, tile, mode="ming"): # 执行明杠逻辑
if handle_gang(player, tile, mode="ming"): # 执行明杠逻辑
actions_taken = True
break # 杠牌后不检查其他玩家
# 检查是否可以碰牌
if self.state.hands[player].tile_count[tile] >= 2:
logger.info(f"玩家 {player} 可以碰玩家 {current_player} 的牌: {tile}")
if self.handle_peng(player, tile): # 执行碰牌逻辑
if handle_peng(player, tile): # 执行碰牌逻辑
actions_taken = True
break # 碰牌后不检查其他玩家
@@ -241,22 +242,10 @@ def handle_peng(self, player, tile):
logger.info(f"玩家 {player} 碰了牌: {tile}。当前明牌: {self.state.melds[player]}")
# 设置出牌顺序为碰牌的玩家
self.state.current_player = player
# 提供玩家手牌信息,等待玩家选择打出的牌
chosen_tile = self.get_player_discard_choice(player)
# 验证玩家选择的牌是否合法
if chosen_tile not in self.state.hands[player].tiles:
logger.error(f"玩家 {player} 选择了不合法的牌: {chosen_tile}")
raise ValueError("打出的牌必须存在于玩家的手牌中")
# 玩家选择打出这张牌
self.discard_tile(player, chosen_tile)
return True
def get_player_discard_choice(self, player):
"""
模拟获取玩家打牌的选择。
@@ -273,28 +262,53 @@ def get_player_discard_choice(self, player):
def handle_gang(self, player, tile, mode):
"""
处理玩家杠牌逻辑并更新状态。
处理玩家杠牌逻辑、计算分数并更新状态。
:param player: 杠牌玩家索引
:param tile: 杠牌的那张牌
:param mode: 杠牌的类型 ("ming""an")
:return: True 如果操作成功,否则 False
"""
if mode == "ming" and self.state.hands[player].tile_count[tile] < 3:
logger.error(f"玩家 {player} 无法明杠: {tile}")
return False
base_score = self.state.bottom_score # 底分
# 减少牌数量并更新明牌
if mode == "ming":
if mode == "ming": # 明杠逻辑
if self.state.hands[player].tile_count[tile] < 3:
logger.error(f"玩家 {player} 无法明杠: {tile}")
return None
# 减少牌数量并更新明牌
self.state.hands[player].tile_count[tile] -= 3
self.state.melds[player].append(("ming_gang", tile))
self.state.melds[player].append(("", tile))
logger.info(f"玩家 {player} 明杠了牌: {tile}")
elif mode == "an":
# 明杠分数计算
gang_score = base_score * 2 # 明杠的分数倍率
for i in range(4):
if i != player:
self.state.scores[i] -= gang_score # 每个其他玩家扣分
self.state.scores[player] += gang_score * 3 # 杠牌玩家得总分
logger.info(f"玩家 {player} 明杠,总分变化: +{gang_score * 3},其他玩家每人扣分: -{gang_score}")
return True
elif mode == "an": # 暗杠逻辑
if self.state.hands[player].tile_count[tile] < 4:
logger.error(f"玩家 {player} 无法暗杠: {tile}")
return False
# 减少牌数量并更新暗牌
self.state.hands[player].tile_count[tile] -= 4
self.state.melds[player].append(("an_gang", tile))
logger.info(f"玩家 {player} 暗杠了牌: {tile}")
# 杠牌后玩家补摸一张牌
self.draw_tile_for_player(player)
return True
# 暗杠分数计算
gang_score = base_score * 4 # 暗杠的分数倍率
for i in range(4):
if i != player:
self.state.scores[i] -= gang_score # 每个其他玩家扣分
self.state.scores[player] += gang_score * 3 # 杠牌玩家得总分
logger.info(f"玩家 {player} 暗杠,总分变化: +{gang_score * 3},其他玩家每人扣分: -{gang_score}")
return True
def random_discard_tile(engine):
@@ -401,3 +415,40 @@ def select_discard_tile(self, player):
return tile
# 如果没有缺门牌,随机打出一张
return hand.tiles[0]
def handle_win(self, player, current_player, tile):
"""
处理胡牌逻辑,包括判断地胡,计算番数和分数。
:param player: 胡牌玩家索引
:param current_player: 打出牌的玩家索引
:param tile: 胡牌的那张牌
"""
logger.info(f"玩家 {player} 胡牌!胡的牌是: {tile}")
# 判断是否地胡
is_dihu = self.state.draw_counts[player] == 0 and player != self.state.current_player
if is_dihu:
logger.info(f"玩家 {player} 地胡!")
else:
logger.info(f"玩家 {player} 不是地胡")
# 计算分数
fan_count = 5 # 按你逻辑固定番数为5
base_score = self.state.bottom_score # 底分
win_score = base_score * (2 ** fan_count)
self.state.scores[player] += win_score * 3 # 胡牌玩家得总分
self.state.scores[current_player] -= win_score # 点炮玩家扣除分数
# 更新赢家状态
self.state.winners.append(player)
self.state.print_game_state(player)
# 输出日志
logger.info(f"玩家 {player} 胡牌类型: {'地胡' if is_dihu else '普通胡牌'}")
logger.info(f"玩家 {player} 总番数: {fan_count}")
logger.info(f"玩家 {current_player} 点炮,扣分: {win_score}")
logger.info(f"玩家 {player} 加分: {win_score * 3}")
logger.info(f"当前分数: {self.state.scores}")

View File

@@ -1,6 +1,6 @@
import random
from loguru import logger
from src.engine.actions import set_missing_suit
from src.engine.actions import set_missing_suit, check_other_players
from src.engine.chengdu_mahjong_state import ChengduMahjongState
from src.engine.actions import draw_tile, discard_tile, peng, gang, check_blood_battle,should_gang,random_choice
@@ -84,7 +84,7 @@ class ChengduMahjongEngine:
logger.info(f"玩家 {self.current_player} 杠牌,类型: {gang_type}")
else:
random_choice(self.state.hands[self.current_player], self.state.missing_suits[self.current_player])
check_other_players(self.state.hands[self.current_player], self.state.missing_suits[self.current_player])