Skip to content

Commit 28d094b

Browse files
committed
config for bingo bonus
1 parent 59fa468 commit 28d094b

File tree

16 files changed

+118
-51
lines changed

16 files changed

+118
-51
lines changed

ai/bot/elite.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func endGameBest(ctx context.Context, p *BotTurnPlayer, endgamePlies int) (*move
111111
gameCopy := p.Game.Copy()
112112
gameCopy.SetBackupMode(game.SimulationMode)
113113
gameCopy.SetStateStackLength(endgamePlies + 1)
114-
gen1 := movegen.NewGordonGenerator(gd, gameCopy.Board(), p.Game.Rules().LetterDistribution())
114+
gen1 := movegen.NewGordonGenerator(gd, gameCopy.Board(), p.Game.Rules().LetterDistribution(), p.Game.Rules().BingoBonus())
115115
err = p.endgamer.Init(gen1, gameCopy)
116116
if err != nil {
117117
return nil, err

ai/turnplayer/static_player.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func AddAIFields(p *turnplayer.BaseTurnPlayer, conf *config.Config, calculators
5757
if err != nil {
5858
return nil, err
5959
}
60-
gen := movegen.NewGordonGenerator(gd, p.Board(), p.Bag().LetterDistribution())
60+
gen := movegen.NewGordonGenerator(gd, p.Board(), p.Bag().LetterDistribution(), p.Rules().BingoBonus())
6161
gen.SetEquityCalculators(calculators)
6262
ret := &AIStaticTurnPlayer{*p, calculators, gen, conf}
6363
return ret, nil

board/board.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -844,16 +844,16 @@ func (g *GameBoard) formedCrossWord(crossVertical bool, letter tilemapping.Machi
844844
// assume the row stays static as we iterate through the letters of the
845845
// word.
846846
func (g *GameBoard) ScoreWord(word tilemapping.MachineWord, row, col, tilesPlayed int,
847-
crossDir BoardDirection, ld *tilemapping.LetterDistribution) int {
847+
crossDir BoardDirection, ld *tilemapping.LetterDistribution, bingoBonus int) int {
848848

849849
// letterScore:
850850
var ls int
851851

852852
mainWordScore := 0
853853
crossScores := 0
854-
bingoBonus := 0
854+
bonus := 0
855855
if tilesPlayed == 7 {
856-
bingoBonus = 50
856+
bonus = bingoBonus
857857
}
858858
wordMultiplier := 1
859859

@@ -904,7 +904,7 @@ func (g *GameBoard) ScoreWord(word tilemapping.MachineWord, row, col, tilesPlaye
904904
crossScores += ls*letterMultiplier*thisWordMultiplier + cs*thisWordMultiplier
905905
}
906906
}
907-
return mainWordScore*wordMultiplier + crossScores + bingoBonus
907+
return mainWordScore*wordMultiplier + crossScores + bonus
908908

909909
}
910910

config/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const (
4040
ConfigOpenaiApiKey = "openai-api-key"
4141
ConfigDeepseekApiKey = "deepseek-api-key"
4242
ConfigWooglesApiKey = "woogles-api-key"
43+
ConfigBingoBonus = "bingo-bonus"
4344
ConfigAliases = "aliases"
4445
)
4546

@@ -113,6 +114,7 @@ func (c *Config) Load(args []string) error {
113114
c.BindEnv(ConfigOpenaiApiKey)
114115
c.BindEnv(ConfigDeepseekApiKey)
115116
c.BindEnv(ConfigWooglesApiKey)
117+
c.BindEnv(ConfigBingoBonus)
116118

117119
cfgdir, err := os.UserConfigDir()
118120
if err != nil {
@@ -166,6 +168,7 @@ func (c *Config) Load(args []string) error {
166168
c.SetDefault(ConfigOpenaiApiKey, "")
167169
c.SetDefault(ConfigDeepseekApiKey, "")
168170
c.SetDefault(ConfigWooglesApiKey, "")
171+
c.SetDefault(ConfigBingoBonus, 50)
169172

170173
return nil
171174
}

endgame/negamax/solver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ func (s *Solver) makeGameCopies() error {
360360
s.movegens = []movegen.MoveGenerator{}
361361
gaddag := s.stmMovegen.(*movegen.GordonGenerator).GADDAG()
362362
for i := 0; i < s.threads-1; i++ {
363-
mg := movegen.NewGordonGenerator(gaddag, s.gameCopies[i].Board(), s.gameCopies[i].Bag().LetterDistribution())
363+
mg := movegen.NewGordonGenerator(gaddag, s.gameCopies[i].Board(), s.gameCopies[i].Bag().LetterDistribution(), s.gameCopies[i].Rules().BingoBonus())
364364
mg.SetSortingParameter(movegen.SortByNone)
365365
mg.SetGenPass(true)
366366
mg.SetPlayRecorder(movegen.AllPlaysSmallRecorder)

equity/calculators_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func TestEndgameTiming(t *testing.T) {
8787
bd := board.MakeBoard(board.CrosswordGameBoard)
8888
ld, err := tilemapping.EnglishLetterDistribution(DefaultConfig.WGLConfig())
8989
assert.Nil(t, err)
90-
generator := movegen.NewGordonGenerator(gd, bd, ld)
90+
generator := movegen.NewGordonGenerator(gd, bd, ld, 50)
9191
tilesInPlay := bd.SetToGame(gd.GetAlphabet(), board.MavenVsMacondo)
9292
cross_set.GenAllCrossSets(bd, gd, ld)
9393
generator.GenAll(tilemapping.RackFromString("AEEORS?", alph), false)
@@ -131,7 +131,7 @@ func TestPreendgameTiming(t *testing.T) {
131131
bd := board.MakeBoard(board.CrosswordGameBoard)
132132
ld, err := tilemapping.EnglishLetterDistribution(DefaultConfig.WGLConfig())
133133
assert.Nil(t, err)
134-
generator := movegen.NewGordonGenerator(gd, bd, ld)
134+
generator := movegen.NewGordonGenerator(gd, bd, ld, 50)
135135
tilesInPlay := bd.SetToGame(gd.GetAlphabet(), board.VsOxy)
136136
cross_set.GenAllCrossSets(bd, gd, ld)
137137
generator.GenAll(tilemapping.RackFromString("OXPBAZE", alph), false)
@@ -170,7 +170,7 @@ func TestOpeningPlayHeuristic(t *testing.T) {
170170
bd := board.MakeBoard(board.CrosswordGameBoard)
171171
ld, err := tilemapping.EnglishLetterDistribution(DefaultConfig.WGLConfig())
172172
assert.Nil(t, err)
173-
generator := movegen.NewGordonGenerator(gd, bd, ld)
173+
generator := movegen.NewGordonGenerator(gd, bd, ld, 50)
174174
cross_set.GenAllCrossSets(bd, gd, ld)
175175
generator.GenAll(tilemapping.RackFromString("AEFLR", alph), false)
176176
els, err := equity.NewCombinedStaticCalculator(

game/backup.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ func (g *Game) Copy() *Game {
166166
maxScorelessTurns: g.maxScorelessTurns,
167167
exchangeLimit: g.exchangeLimit,
168168
players: copyPlayers(g.players),
169+
rules: g.rules,
169170
// stackPtr only changes during a sim, etc. This Copy should
170171
// only be called at the beginning of everything.
171172
stackPtr: 0,

game/game.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ func (g *Game) CreateAndScorePlacementMove(coords string, tiles string, rack str
823823
// ScoreWord assumes the play is always horizontal, so we have to
824824
// do the transpositions beforehand.
825825
score := g.Board().ScoreWord(mw, row, col, tilesPlayed,
826-
crossDir, g.bag.LetterDistribution())
826+
crossDir, g.bag.LetterDistribution(), g.rules.BingoBonus())
827827
// reset row, col back for the actual creation of the play.
828828
if vertical {
829829
row, col = col, row

game/rules.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type GameRules struct {
4242
boardname string
4343
distname string
4444
exchangeLimit int
45+
bingoBonus int
4546
}
4647

4748
func (g GameRules) Config() *config.Config {
@@ -88,6 +89,10 @@ func (g GameRules) ExchangeLimit() int {
8889
return g.exchangeLimit
8990
}
9091

92+
func (g GameRules) BingoBonus() int {
93+
return g.bingoBonus
94+
}
95+
9196
func NewBasicGameRules(cfg *config.Config,
9297
lexiconName, boardLayoutName, letterDistributionName, csetGenName string,
9398
variant Variant) (*GameRules, error) {
@@ -142,6 +147,12 @@ func NewBasicGameRules(cfg *config.Config,
142147
exchLimit = 1
143148
}
144149

150+
// Set bingo bonus based on board layout
151+
bingoBonus := cfg.GetInt(config.ConfigBingoBonus)
152+
if boardLayoutName == board.CrossplayGameLayout {
153+
bingoBonus = 40
154+
}
155+
145156
rules := &GameRules{
146157
cfg: cfg,
147158
dist: dist,
@@ -152,6 +163,7 @@ func NewBasicGameRules(cfg *config.Config,
152163
crossSetGen: csgen,
153164
variant: variant,
154165
exchangeLimit: exchLimit,
166+
bingoBonus: bingoBonus,
155167
}
156168
return rules, nil
157169
}

game/rules_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package game
33
import (
44
"testing"
55

6+
"github.com/domino14/macondo/board"
7+
"github.com/domino14/macondo/config"
68
"github.com/matryer/is"
79
)
810

@@ -28,3 +30,50 @@ func TestMaxCanExchange(t *testing.T) {
2830
is.Equal(MaxCanExchange(tc.inbag, tc.exchlimit), tc.expected)
2931
}
3032
}
33+
34+
func TestBingoBonus(t *testing.T) {
35+
is := is.New(t)
36+
37+
cfg := config.DefaultConfig()
38+
cfg.Set(config.ConfigBingoBonus, 50) // Set default to 50
39+
40+
// Create rules manually
41+
rules := &GameRules{
42+
cfg: cfg,
43+
bingoBonus: 0,
44+
}
45+
46+
// Simulate the bingo bonus setting logic from NewBasicGameRules
47+
bingoBonus := cfg.GetInt(config.ConfigBingoBonus)
48+
if board.CrossplayGameLayout == board.CrossplayGameLayout {
49+
bingoBonus = 40
50+
}
51+
rules.bingoBonus = bingoBonus
52+
53+
is.Equal(rules.BingoBonus(), 40) // Crossplay overrides to 40
54+
55+
// Test other layouts use configured value
56+
bingoBonus = cfg.GetInt(config.ConfigBingoBonus)
57+
if board.CrosswordGameLayout == board.CrossplayGameLayout {
58+
bingoBonus = 40
59+
}
60+
rules.bingoBonus = bingoBonus
61+
is.Equal(rules.BingoBonus(), 50) // Should use configured value
62+
63+
// Test custom bingo bonus
64+
cfg.Set(config.ConfigBingoBonus, 35)
65+
bingoBonus = cfg.GetInt(config.ConfigBingoBonus)
66+
if board.CrosswordGameLayout == board.CrossplayGameLayout {
67+
bingoBonus = 40
68+
}
69+
rules.bingoBonus = bingoBonus
70+
is.Equal(rules.BingoBonus(), 35) // Should use configured value
71+
72+
// Test Crossplay still overrides to 40 even with custom config
73+
bingoBonus = cfg.GetInt(config.ConfigBingoBonus)
74+
if board.CrossplayGameLayout == board.CrossplayGameLayout {
75+
bingoBonus = 40
76+
}
77+
rules.bingoBonus = bingoBonus
78+
is.Equal(rules.BingoBonus(), 40) // Crossplay should still be 40
79+
}

0 commit comments

Comments
 (0)