Compare commits
2 Commits
6d3b5ae175
...
399ce76f4b
| Author | SHA1 | Date | |
|---|---|---|---|
| 399ce76f4b | |||
| 749caaf980 |
67
src/engine/calculate_fan.py
Normal file
67
src/engine/calculate_fan.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
def calculate_fan(hand, melds, is_self_draw, is_cleared, conditions):
|
||||||
|
"""
|
||||||
|
根据规则动态计算番数。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
- hand: 当前胡牌的手牌(长度为108的列表,表示每张牌的数量)。
|
||||||
|
- melds: 碰杠等明牌列表。
|
||||||
|
- is_self_draw: 是否自摸。
|
||||||
|
- is_cleared: 是否清一色。
|
||||||
|
- conditions: 其他胡牌条件的字典,例如 {'is_seven_pairs': True, 'add_self_draw': True}。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
- fan: 总番数。
|
||||||
|
"""
|
||||||
|
fan = 0 # 初始番数
|
||||||
|
|
||||||
|
# 定义番种规则
|
||||||
|
rules = {
|
||||||
|
"basic_win": lambda: 1, # 平胡
|
||||||
|
"is_cleared": lambda: 2 if is_cleared else 0, # 清一色
|
||||||
|
"is_pure_cleared": lambda: 3 if is_cleared and len(melds) >= 1 else 0, # 清对
|
||||||
|
"is_double_pure_cleared": lambda: 4 if is_cleared and len(melds) >= 2 else 0, # 极中极
|
||||||
|
"is_seven_pairs": lambda: 2 if conditions.get("is_seven_pairs", False) else 0, # 七对
|
||||||
|
"is_dragon_seven_pairs": lambda: 12 if conditions.get("is_dragon_seven_pairs", False) else 0, # 龙七对
|
||||||
|
"is_clear_seven_pairs": lambda: 12 if conditions.get("is_clear_seven_pairs", False) else 0, # 清七对
|
||||||
|
"is_big_pairs": lambda: 2 if conditions.get("is_big_pairs", False) else 0, # 大对子
|
||||||
|
"is_small_pairs": lambda: 2 if conditions.get("is_small_pairs", False) else 0, # 小七对
|
||||||
|
"is_full_request": lambda: 6 if conditions.get("is_full_request", False) else 0, # 全求人
|
||||||
|
"is_gang_flower": lambda: 1 if conditions.get("is_gang_flower", False) else 0, # 杠上开花
|
||||||
|
"is_rob_gang": lambda: 1 if conditions.get("is_rob_gang", False) else 0, # 抢杠胡
|
||||||
|
"is_under_the_sea": lambda: 1 if conditions.get("is_under_the_sea", False) else 0, # 海底捞月
|
||||||
|
"is_cannon": lambda: 1 if conditions.get("is_cannon", False) else 0, # 放炮
|
||||||
|
"is_tian_hu": lambda: 12 if conditions.get("is_tian_hu", False) else 0, # 天胡
|
||||||
|
"is_di_hu": lambda: 12 if conditions.get("is_di_hu", False) else 0, # 地胡
|
||||||
|
"is_self_draw": lambda: 1 if is_self_draw and conditions.get("add_self_draw", True) else 0, # 自摸
|
||||||
|
}
|
||||||
|
|
||||||
|
# 逐一应用规则
|
||||||
|
for rule, func in rules.items():
|
||||||
|
fan += func()
|
||||||
|
|
||||||
|
return fan
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def is_seven_pairs(hand):
|
||||||
|
"""
|
||||||
|
检查手牌是否是七对。
|
||||||
|
"""
|
||||||
|
return sum(1 for count in hand if count == 2) == 7
|
||||||
|
|
||||||
|
|
||||||
|
def is_cleared(hand):
|
||||||
|
"""
|
||||||
|
检查手牌是否是清一色。
|
||||||
|
"""
|
||||||
|
suits = [tile // 36 for tile, count in enumerate(hand) if count > 0]
|
||||||
|
return len(set(suits)) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def is_big_pairs(hand):
|
||||||
|
"""
|
||||||
|
检查手牌是否是大对子(由刻子和一对组成)。
|
||||||
|
"""
|
||||||
|
from collections import Counter
|
||||||
|
counter = Counter(hand)
|
||||||
|
return all(count == 3 or count == 2 for count in counter.values())
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# 计算番数逻辑
|
|
||||||
def calculate_fan(hand, melds, is_self_draw, is_cleared):
|
|
||||||
"""
|
|
||||||
根据胡牌手牌、碰杠、是否自摸等情况计算番数。
|
|
||||||
参数:
|
|
||||||
- hand: 当前胡牌的手牌
|
|
||||||
- melds: 碰杠等明牌列表
|
|
||||||
- is_self_draw: 是否自摸
|
|
||||||
- is_cleared: 是否清一色
|
|
||||||
|
|
||||||
返回:
|
|
||||||
- fan: 计算出的番数
|
|
||||||
"""
|
|
||||||
fan = 1 # 基本胡
|
|
||||||
if is_cleared:
|
|
||||||
fan += 2 # 清一色加番
|
|
||||||
if len(melds) >= 2:
|
|
||||||
fan += len(melds) # 每次碰杠额外加番
|
|
||||||
if is_self_draw:
|
|
||||||
fan += 1 # 自摸加番
|
|
||||||
return fan
|
|
||||||
143
tests/test_calculate_fan.py
Normal file
143
tests/test_calculate_fan.py
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import pytest
|
||||||
|
from src.engine.calculate_fan import calculate_fan, is_seven_pairs, is_cleared, is_big_pairs
|
||||||
|
|
||||||
|
# 测试用例
|
||||||
|
|
||||||
|
def test_basic_win():
|
||||||
|
"""
|
||||||
|
测试平胡(基本胡)计分
|
||||||
|
"""
|
||||||
|
hand = [0] * 108
|
||||||
|
# 模拟平胡手牌: 四组顺子 + 一对将
|
||||||
|
hand[0] = 2 # 将: 两张1条
|
||||||
|
hand[3] = 1 # 2条
|
||||||
|
hand[4] = 1 # 3条
|
||||||
|
hand[5] = 1 # 4条
|
||||||
|
hand[10] = 1 # 5条
|
||||||
|
hand[11] = 1 # 6条
|
||||||
|
hand[12] = 1 # 7条
|
||||||
|
hand[20] = 1 # 8条
|
||||||
|
hand[21] = 1 # 9条
|
||||||
|
hand[22] = 1 # 1筒
|
||||||
|
hand[30] = 1 # 2筒
|
||||||
|
hand[31] = 1 # 3筒
|
||||||
|
|
||||||
|
melds = []
|
||||||
|
conditions = {}
|
||||||
|
|
||||||
|
fan = calculate_fan(hand, melds, is_self_draw=False, is_cleared=False, conditions=conditions)
|
||||||
|
assert fan == 1, f"Expected 1 fan, got {fan}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_clear_win():
|
||||||
|
"""
|
||||||
|
测试清一色计分(不加自摸番)
|
||||||
|
"""
|
||||||
|
hand = [0] * 108
|
||||||
|
# 模拟清一色手牌
|
||||||
|
hand[0] = 2
|
||||||
|
hand[4] = 1
|
||||||
|
hand[5] = 1
|
||||||
|
hand[6] = 1
|
||||||
|
hand[10] = 1
|
||||||
|
hand[11] = 1
|
||||||
|
hand[12] = 1
|
||||||
|
hand[20] = 1
|
||||||
|
hand[21] = 1
|
||||||
|
hand[22] = 1
|
||||||
|
hand[23] = 1
|
||||||
|
|
||||||
|
melds = []
|
||||||
|
conditions = {"is_seven_pairs": False, "add_self_draw": False}
|
||||||
|
|
||||||
|
fan = calculate_fan(hand, melds, is_self_draw=True, is_cleared=is_cleared(hand), conditions=conditions)
|
||||||
|
assert fan == 3, f"Expected 3 fans (1 basic + 2 cleared), got {fan}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_seven_pairs():
|
||||||
|
"""
|
||||||
|
测试七对计分
|
||||||
|
"""
|
||||||
|
hand = [0] * 108
|
||||||
|
# 模拟七对手牌
|
||||||
|
hand[0] = 2 # 1条
|
||||||
|
hand[4] = 2 # 2条
|
||||||
|
hand[8] = 2 # 3条
|
||||||
|
hand[12] = 2 # 4条
|
||||||
|
hand[16] = 2 # 5条
|
||||||
|
hand[20] = 2 # 6条
|
||||||
|
hand[24] = 2 # 7条
|
||||||
|
|
||||||
|
melds = []
|
||||||
|
conditions = {"is_seven_pairs": is_seven_pairs(hand)}
|
||||||
|
|
||||||
|
fan = calculate_fan(hand, melds, is_self_draw=False, is_cleared=False, conditions=conditions)
|
||||||
|
assert fan == 2, f"Expected 2 fans (7 pairs), got {fan}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_big_pairs():
|
||||||
|
"""
|
||||||
|
测试大对子计分
|
||||||
|
"""
|
||||||
|
hand = [0] * 108
|
||||||
|
# 模拟大对子手牌
|
||||||
|
hand[0] = 3 # 1条
|
||||||
|
hand[4] = 3 # 2条
|
||||||
|
hand[8] = 3 # 3条
|
||||||
|
hand[12] = 2 # 将: 4条
|
||||||
|
|
||||||
|
melds = []
|
||||||
|
conditions = {"is_big_pairs": is_big_pairs(hand)}
|
||||||
|
|
||||||
|
fan = calculate_fan(hand, melds, is_self_draw=False, is_cleared=False, conditions=conditions)
|
||||||
|
assert fan == 2, f"Expected 2 fans (big pairs), got {fan}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_gang_flower():
|
||||||
|
"""
|
||||||
|
测试杠上开花计分
|
||||||
|
"""
|
||||||
|
hand = [0] * 108
|
||||||
|
# 模拟杠上开花手牌
|
||||||
|
hand[0] = 2 # 将: 两张1条
|
||||||
|
hand[3] = 1 # 2条
|
||||||
|
hand[4] = 1 # 3条
|
||||||
|
hand[5] = 1 # 4条
|
||||||
|
hand[10] = 1 # 5条
|
||||||
|
hand[11] = 1 # 6条
|
||||||
|
hand[12] = 1 # 7条
|
||||||
|
hand[20] = 1 # 8条
|
||||||
|
hand[21] = 1 # 9条
|
||||||
|
hand[22] = 1 # 1筒
|
||||||
|
|
||||||
|
melds = []
|
||||||
|
conditions = {"is_gang_flower": True}
|
||||||
|
|
||||||
|
fan = calculate_fan(hand, melds, is_self_draw=True, is_cleared=False, conditions=conditions)
|
||||||
|
assert fan == 2, f"Expected 2 fans (1 basic + 1 gang flower), got {fan}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_dragon_seven_pairs():
|
||||||
|
"""
|
||||||
|
测试龙七对计分
|
||||||
|
"""
|
||||||
|
hand = [0] * 108
|
||||||
|
# 模拟龙七对手牌
|
||||||
|
hand[0] = 2 # 1条
|
||||||
|
hand[4] = 2 # 2条
|
||||||
|
hand[8] = 2 # 3条
|
||||||
|
hand[12] = 2 # 4条
|
||||||
|
hand[16] = 2 # 5条
|
||||||
|
hand[20] = 2 # 6条
|
||||||
|
hand[24] = 4 # 龙: 7条
|
||||||
|
|
||||||
|
melds = []
|
||||||
|
conditions = {"is_dragon_seven_pairs": True}
|
||||||
|
|
||||||
|
fan = calculate_fan(hand, melds, is_self_draw=True, is_cleared=False, conditions=conditions)
|
||||||
|
assert fan == 13, f"Expected 13 fans (1 self-draw + 12 dragon seven pairs), got {fan}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user