fix: rule game for kot and hakem kot
This commit is contained in:
@@ -45,8 +45,9 @@ type TrickCard struct {
|
||||
// HandResult نتیجه یک هَند.
|
||||
type HandResult struct {
|
||||
WinnerTeam int `json:"winner_team"`
|
||||
Kot bool `json:"kot"` // کُت: تیم بازنده هیچ دستی نبرد
|
||||
Points int `json:"points"` // امتیاز این هَند (۱ معمولی، ۲ کُت)
|
||||
Kot bool `json:"kot"` // کُت: تیم بازنده هیچ دستی نبرد
|
||||
HakemKot bool `json:"hakem_kot"` // حاکمکُت: تیمِ حاکم کُت شد (۳ امتیاز)
|
||||
Points int `json:"points"` // امتیاز این هَند (۱ معمولی، ۲ کُت، ۳ حاکمکُت)
|
||||
NextHakem int `json:"next_hakem"`
|
||||
}
|
||||
|
||||
@@ -269,6 +270,11 @@ func (g *Game) checkHandOver() {
|
||||
points := 1
|
||||
if kot {
|
||||
points = 2
|
||||
// حاکمکُت: اگر تیمِ بازنده همان تیمِ حاکم باشد (حاکم صفر دست برده)،
|
||||
// کُت سنگینتر است ⇒ ۳ امتیاز.
|
||||
if Team(g.Hakem) == loserTeam {
|
||||
points = 3
|
||||
}
|
||||
}
|
||||
g.Scores[winnerTeam] += points
|
||||
|
||||
@@ -281,6 +287,7 @@ func (g *Game) checkHandOver() {
|
||||
g.LastResult = &HandResult{
|
||||
WinnerTeam: winnerTeam,
|
||||
Kot: kot,
|
||||
HakemKot: points == 3,
|
||||
Points: points,
|
||||
NextHakem: nextHakem,
|
||||
}
|
||||
|
||||
@@ -114,6 +114,49 @@ func TestFullGamePlaysOut(t *testing.T) {
|
||||
t.Logf("final scores: %v", g.Scores)
|
||||
}
|
||||
|
||||
// TestTargetScoreRespected بررسی میکند بازی دقیقاً وقتی یک تیم به TargetScore
|
||||
// رسید تمام میشود (نه زودتر، نه دیرتر) — برای میزهایی مثل مبتدی (۳ دست).
|
||||
func TestTargetScoreRespected(t *testing.T) {
|
||||
for _, target := range []int{1, 3, 5, 7} {
|
||||
for trial := 0; trial < 20; trial++ {
|
||||
g := NewGame(target, FirstHakem())
|
||||
for g.Phase != PhaseGameOver {
|
||||
switch {
|
||||
case g.TrickDone:
|
||||
if err := g.CollectTrick(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
case g.Phase == PhaseChooseTrump:
|
||||
if err := g.ChooseTrump(g.Hakem, g.hands[g.Hakem][0].Suit); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
case g.Phase == PhaseHandOver:
|
||||
if err := g.NextHand(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
default: // playing
|
||||
if err := g.PlayCard(g.Turn, legalMove(g, g.Turn)); err != nil {
|
||||
t.Fatalf("play: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
w := g.Scores[0]
|
||||
if g.Scores[1] > w {
|
||||
w = g.Scores[1]
|
||||
}
|
||||
if w < target {
|
||||
t.Fatalf("target %d: game over but max score %d < target (scores %v)",
|
||||
target, w, g.Scores)
|
||||
}
|
||||
// بازنده نباید به هدف رسیده باشد (بازی باید بهمحضِ رسیدنِ یک تیم تمام شود).
|
||||
loser := g.Scores[0] + g.Scores[1] - w
|
||||
if loser >= target {
|
||||
t.Fatalf("target %d: both teams reached target %v", target, g.Scores)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// legalMove یک حرکت مجاز برای ربات انتخاب میکند (follow suit در صورت امکان).
|
||||
func legalMove(g *Game, seat int) Card {
|
||||
hand := g.hands[seat]
|
||||
|
||||
Reference in New Issue
Block a user