Files

117 lines
4.0 KiB
Go
Raw Permalink Normal View History

2026-08-14 13:17:03 +08:00
package ddz
import "testing"
// TestBidRobFlow 叫地主 → 抢地主 → 确定地主的完整流程与倍数计算
func TestBidRobFlow(t *testing.T) {
g := NewGame()
g.Turn = 0
g.BidStart = 0
// 座位 0 叫地主 → 进入抢地主,轮到座位 1
if _, err := g.Bid(0, true); err != nil {
t.Fatal(err)
}
if g.Phase != PhaseRobbing || g.Turn != 1 || g.Landlord != 0 || g.Multiplier != 1 {
t.Fatalf("叫地主后状态异常:phase=%s turn=%d landlord=%d mult=%d", g.Phase, g.Turn, g.Landlord, g.Multiplier)
}
// 座位 1 抢地主 → 地主候选换成 1,倍数×2,轮到座位 2
if err := g.Rob(1, true); err != nil {
t.Fatal(err)
}
if g.Landlord != 1 || g.Multiplier != 2 || g.Turn != 2 {
t.Fatalf("抢地主后状态异常:landlord=%d mult=%d turn=%d", g.Landlord, g.Multiplier, g.Turn)
}
// 座位 2 不抢 → 地主确定为 1,底牌并入(20张),进入出牌阶段
if err := g.Rob(2, false); err != nil {
t.Fatal(err)
}
if g.Phase != PhasePlaying || g.Landlord != 1 || g.Turn != 1 {
t.Fatalf("抢地主结束后状态异常:phase=%s landlord=%d turn=%d", g.Phase, g.Landlord, g.Turn)
}
if len(g.Hands[1]) != 20 {
t.Fatalf("地主应有 20 张手牌,实际 %d", len(g.Hands[1]))
}
}
// TestRobNonePass 两家都不抢:首叫者当地主,倍数不变
func TestRobNonePass(t *testing.T) {
g := NewGame()
g.Turn = 2
g.BidStart = 2
g.Bid(2, true)
if g.Turn != 0 {
t.Fatalf("抢地主应从下家开始,实际 turn=%d", g.Turn)
}
g.Rob(0, false)
if g.Turn != 1 {
t.Fatalf("第二位抢地主表态者应为座位 1,实际 %d", g.Turn)
}
g.Rob(1, false)
if g.Phase != PhasePlaying || g.Landlord != 2 || g.Multiplier != 1 {
t.Fatalf("两家不抢后状态异常:phase=%s landlord=%d mult=%d", g.Phase, g.Landlord, g.Multiplier)
}
}
// TestRedealWhenAllPass 三家都不叫应重新发牌
func TestRedealWhenAllPass(t *testing.T) {
g := NewGame()
start := g.Turn
for i := 0; i < 2; i++ {
redeal, err := g.Bid(g.Turn, false)
if err != nil || redeal {
t.Fatalf("前两家不叫不应触发重发:redeal=%v err=%v", redeal, err)
}
}
redeal, err := g.Bid(g.Turn, false)
if err != nil || !redeal {
t.Fatalf("三家都不叫应返回重发:redeal=%v err=%v(start=%d)", redeal, err, start)
}
}
// TestSpringMultiplier 春天与反春的判定
func TestSpringMultiplier(t *testing.T) {
// 春天:地主赢且农民从未出过牌
g := &Game{Landlord: 0, Winner: 0, Phase: PhaseOver, Multiplier: 1}
g.History = []PlayEvent{
{Seat: 0, Cards: []int{1}}, {Seat: 1}, {Seat: 2},
{Seat: 0, Cards: []int{2}}, {Seat: 1}, {Seat: 2},
}
if g.SpringMultiplier() != 2 {
t.Fatalf("地主全程压制应判春天 ×2,实际 %d", g.SpringMultiplier())
}
// 反春:农民赢且地主只出过第一手
g2 := &Game{Landlord: 0, Winner: 1, Phase: PhaseOver, Multiplier: 1}
g2.History = []PlayEvent{
{Seat: 0, Cards: []int{1}},
{Seat: 1, Cards: []int{2}}, {Seat: 2},
{Seat: 1, Cards: []int{3}},
}
if g2.SpringMultiplier() != 2 {
t.Fatalf("地主只出一手被打完应判反春 ×2,实际 %d", g2.SpringMultiplier())
}
// 普通局:双方都出过多手
g3 := &Game{Landlord: 0, Winner: 1, Phase: PhaseOver, Multiplier: 1}
g3.History = []PlayEvent{
{Seat: 0, Cards: []int{1}}, {Seat: 1, Cards: []int{2}},
{Seat: 0, Cards: []int{3}}, {Seat: 1, Cards: []int{4}},
}
if g3.SpringMultiplier() != 1 {
t.Fatalf("普通局春天倍数应为 1,实际 %d", g3.SpringMultiplier())
}
}
// TestTotalMultiplier 结算总倍数 = 叫抢 × 炸弹 × 春天(含上限)
func TestTotalMultiplier(t *testing.T) {
g := &Game{Landlord: 0, Winner: 0, Phase: PhaseOver, Multiplier: 2, Bombs: 2}
g.History = []PlayEvent{{Seat: 0, Cards: []int{1}}, {Seat: 1, Cards: []int{2}}}
// 2(抢1次)× 4(2个炸弹)× 1(无春天)= 8
if got := g.TotalMultiplier(); got != 8 {
t.Fatalf("总倍数应为 8,实际 %d", got)
}
// 上限保护:巨量炸弹也不超过 64
g.Bombs = 10
if got := g.TotalMultiplier(); got != 64 {
t.Fatalf("总倍数应封顶 64,实际 %d", got)
}
}