mjAi/tests/test_chengdu_mahjong_states.py

514 lines
17 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from src import ChengduMahjongState
from src import Hand
from src import MahjongTile
from src import Meld
def test_set_missing_suit():
"""测试设置缺门功能"""
state = ChengduMahjongState()
state.set_missing_suit(0, "")
assert state.missing_suits[0] == "", "测试失败:缺门设置为 '' 后未正确更新"
state.set_missing_suit(1, "")
assert state.missing_suits[1] == "", "测试失败:缺门设置为 '' 后未正确更新"
state.set_missing_suit(2, "")
assert state.missing_suits[2] == "", "测试失败:缺门设置为 '' 后未正确更新"
try:
state.set_missing_suit(0, "")
except ValueError:
print("测试通过:设置无效缺门 '' 抛出异常")
else:
raise AssertionError("测试失败:设置无效缺门 '' 未抛出异常")
def test_can_win_with_pure_sequences():
"""测试纯顺子胡牌"""
hand = Hand()
# 添加牌到手牌中
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 8))
hand.add_tile(MahjongTile("", 9))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
state = ChengduMahjongState()
state.melds[0] = []
state.hands[0] = hand
# 设置缺门为 "条",因为手牌中没有 "条"
missing_suit = ""
print(f"\n,state.hand[0]: {state.hands[0]}")
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0],missing_suit) == True, "测试失败:纯顺子应该可以胡牌"
def test_can_win_with_sequence_and_triplet():
"""测试顺子 + 刻子胡牌"""
hand = Hand()
# 添加牌到手牌中
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 8))
hand.add_tile(MahjongTile("", 9))
state = ChengduMahjongState()
state.hands[0] = hand
state.melds[0] = []
# 设置缺门为 "条",因为手牌中没有 "条"
missing_suit = ""
print(f"\n,state.hand[0]: {state.hands[0]}")
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0],missing_suit) == True, "测试失败:顺子 + 刻子应该可以胡牌"
def test_can_win_with_triplets_and_pair():
"""测试刻子和对子胡牌"""
hand = Hand()
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 4))
state = ChengduMahjongState()
state.hands[0] = hand
state.melds[0] = []
# 设置缺门为 "万",因为手牌中没有 "万"
missing_suit = ""
print(f"\n,state.hand[0]: {state.hands[0]}")
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0],missing_suit) == True, "测试失败:刻子和对子应该可以胡牌"
def test_can_win_with_pure_one_suit():
"""测试清一色不带杠胡牌"""
hand = Hand()
# 添加牌到手牌中
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 8))
hand.add_tile(MahjongTile("", 9))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 9))
hand.add_tile(MahjongTile("", 9))
state = ChengduMahjongState()
state.hands[0] = hand
state.melds[0] = []
# 设置缺门为 "万",因为手牌中只有 "筒"
missing_suit = ""
print(f"\n,state.hand[0]: {state.hands[0]}")
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0],missing_suit) == True, "测试失败:清一色不带杠应该可以胡牌"
def test_can_win_with_pure_one_suit_and_gang():
"""测试带杠的清一色胡牌"""
hand = Hand()
# 添加暗牌
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 8))
hand.add_tile(MahjongTile("", 8))
hand.add_tile(MahjongTile("", 8))
# 添加对子
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 2))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
# 设置明牌(杠)
melds_list = [
Meld(MahjongTile("", 9), "") # 表示明杠了4张9筒
]
state.melds[0] = melds_list # 确保 state.melds[0] 是一个列表
# 设置缺门为 "万"
missing_suit = ""
print(f"\n当前手牌: {state.hands[0]}, 明牌: {state.melds[0]}")
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0], missing_suit), "测试失败:带杠的清一色应该可以胡牌"
def test_can_win_with_yaojiu_sequences():
"""测试带幺九的顺子胡牌"""
hand = Hand()
# 添加顺子和对子
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 8))
hand.add_tile(MahjongTile("", 9))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 9))
hand.add_tile(MahjongTile("", 9))
hand.add_tile(MahjongTile("", 9))
# 添加对子
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
# 无明牌
melds_list = []
state.melds[0] = melds_list
# 设置缺门为 "万"
missing_suit = ""
print(f"\n当前手牌: {state.hands[0]}, 明牌: {state.melds[0]}")
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0], missing_suit), "测试失败:带幺九顺子应该可以胡牌"
def test_can_win_with_seven_pairs():
"""测试清一色七对胡牌"""
hand = Hand()
# 添加 7 对牌
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 7))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
# 无明牌
melds_list = []
state.melds[0] = melds_list
# 设置缺门为 "条"
missing_suit = ""
print(f"\n当前手牌: {state.hands[0]}, 明牌: {state.melds[0]}")
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0], missing_suit), "测试失败:七对应该可以胡牌"
def test_can_win_with_dragon_seven_pairs():
"""测试带暗杠的龙七对胡牌"""
hand = Hand()
# 添加手牌
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1)) # 暗杠
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 6))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
# 无明牌
melds_list = []
state.melds[0] = melds_list
# 设置缺门为 "万"
missing_suit = ""
print(f"\n当前手牌: {state.hands[0]}, 明牌: {state.melds[0]}")
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0], missing_suit), "测试失败:带暗杠的龙七对应该可以胡牌"
def test_can_win_with_mixed_seven_pairs():
"""测试混合七对胡牌"""
hand = Hand()
# 添加手牌
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 7))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
# 无明牌
melds_list = []
state.melds[0] = melds_list
# 设置缺门为 "万"
missing_suit = ""
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0], missing_suit), "测试失败:混合七对应该可以胡牌"
def test_can_win_after_ming_gang():
"""测试明杠后杠上开花胡牌"""
hand = Hand()
# 添加暗牌
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 8))
hand.add_tile(MahjongTile("", 9))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 8))
hand.add_tile(MahjongTile("", 9))
hand.add_tile(MahjongTile("", 2))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
# 设置明牌(明杠)
melds_list = []
state.melds[0] = melds_list
# 别人打出3条明杠了3条
state.hands[0].add_tile(MahjongTile("", 3))
# 设置明杠
state.melds[0].append(Meld(MahjongTile("", 3), ""))
# 从手牌中移除明杠的牌
for _ in range(4):
state.hands[0].remove_tile(MahjongTile("", 3))
# 模拟杠上开花自摸一张3万
hand.add_tile(MahjongTile("", 2))
# 设置缺门
state.missing_suits = ""
# 打印手牌,暗牌,明牌,缺门
state.print_game_state(0)
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0], state.missing_suits), "测试失败:明杠后杠上开花应该可以胡牌"
print("测试通过:明杠后杠上开花胡牌成功!")
def test_qiang_gang_hu():
"""测试抢杠胡"""
# 玩家 A 的手牌
player_a_hand = Hand()
player_a_hand.add_tile(MahjongTile("", 2))
player_a_hand.add_tile(MahjongTile("", 3))
player_a_hand.add_tile(MahjongTile("", 5))
player_a_hand.add_tile(MahjongTile("", 6))
player_a_hand.add_tile(MahjongTile("", 7))
player_a_hand.add_tile(MahjongTile("", 9))
player_a_hand.add_tile(MahjongTile("", 9))
player_a_hand.add_tile(MahjongTile("", 1))
player_a_hand.add_tile(MahjongTile("", 1))
player_a_hand.add_tile(MahjongTile("", 2))
player_a_hand.add_tile(MahjongTile("", 2))
player_a_hand.add_tile(MahjongTile("", 3))
player_a_hand.add_tile(MahjongTile("", 3))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = player_a_hand # 玩家 A 的手牌
state.missing_suits[0] = "" # 玩家 A 的缺门
# 玩家 B 的明牌和手牌
player_b_hand = Hand()
player_b_hand.add_tile(MahjongTile("", 1))
player_b_hand.add_tile(MahjongTile("", 1))
player_b_hand.add_tile(MahjongTile("", 1))
state.hands[1] = player_b_hand
state.missing_suits[1] = ""
# 玩家 B 尝试杠 1 筒
melds_b = [Meld(MahjongTile("", 1), "")]
state.melds[1] = melds_b
# 玩家 A 抢杠胡
gang_tile = MahjongTile("", 1) # 玩家 B 打出用于杠的牌
player_a_hand.add_tile(gang_tile)
can_qiang_gang_hu = state.can_win(player_a_hand, state.melds[0], state.missing_suits[0])
# 打印状态
state.print_game_state(player_index=0) # 打印玩家 A 的状态
state.print_game_state(player_index=1) # 打印玩家 B 的状态
assert can_qiang_gang_hu, "测试失败:玩家 A 应该可以抢杠胡"
print("测试通过:抢杠胡成功!")
def test_can_win_with_big_pairs():
"""测试大对子胡牌"""
hand = Hand()
# 添加对子
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 4))
# 添加刻子
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 5))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
# 设置缺门为 "条",因为手牌和明牌中没有 "条"
missing_suit = ""
# 打印当前玩家状态
state.print_game_state(player_index=0)
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0], missing_suit), "测试失败:大对子应该可以胡牌"
print("测试通过:大对子胡牌成功!")
def test_can_win_with_small_seven_pairs():
"""测试小七对胡牌"""
hand = Hand()
# 添加七对
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 1))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 2))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 3))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 4))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 5))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 6))
hand.add_tile(MahjongTile("", 7))
hand.add_tile(MahjongTile("", 7))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
# 设置缺门为 "条",因为手牌和明牌中没有 "条"
missing_suit = ""
# 打印当前玩家状态
state.print_game_state(player_index=0)
# 调用 can_win 方法并断言胡牌
assert state.can_win(state.hands[0], state.melds[0], missing_suit), "测试失败:小七对应该可以胡牌"
print("测试通过:小七对胡牌成功!")
def test_can_win_with_jin_gou_diao():
"""测试金钩吊胡牌"""
hand = Hand()
# 添加仅剩的一张牌
hand.add_tile(MahjongTile("", 3))
# 初始化游戏状态
state = ChengduMahjongState()
state.hands[0] = hand
state.melds[0] = [
Meld(MahjongTile("", 8), ""), # 8筒碰
Meld(MahjongTile("", 7), ""), # 7筒碰
Meld(MahjongTile("", 9), ""), # 9筒杠
Meld(MahjongTile("", 3), "") # 3筒碰
]
# 设置缺门为 "条",因为手牌和明牌中没有 "条"
missing_suit = ""
# 打印当前玩家状态
state.print_game_state(player_index=0)
# 模拟别人打出一张 "筒3",胡牌
winning_tile = MahjongTile("", 3)
state.hands[0].add_tile(winning_tile)
# 调用 can_win 方法并断言胡牌
can_win = state.can_win(state.hands[0], state.melds[0], missing_suit)
assert can_win, f"测试失败:金钩吊未能胡 {winning_tile}"
print("测试通过:金钩吊胡牌成功!")