fix: rule game for kot and hakem kot

This commit is contained in:
2026-06-15 20:09:39 +03:30
parent 390ef96e7e
commit 7dadb23fbe
7 changed files with 79 additions and 8 deletions
+9 -2
View File
@@ -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,
}
+43
View File
@@ -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]