The transposition table uses keys from the position of player 0 and player 1 from bitboards and includes the player turn at the end, I did that to guarantee unique keys for all states. But this seems to be slow because of fmt.Sprintf.
I have two functions where I store and retrieve, and in each of them I build the key and do a check or store.
type TTFlag int64
const (
Exact TTFlag = 0
UpperBound TTFlag = 1
LowerBound TTFlag = 2
)
type TTEntry struct {
BestScore float64
BestMove int
Flag TTFlag
Depth int
IsValid bool
}
type Solver struct {
NodeVisitCounter int
TTMapHitCounter int
TTMap map[string]TTEntry
}
func NewSolver() *Solver {
return &Solver{
NodeVisitCounter: 0,
TTMapHitCounter: 0,
TTMap: make(map[string]TTEntry),
}
}
func (s *Solver) StoreEntry(p *Position, entry TTEntry) {
key := fmt.Sprintf("%d:%d:%d", p.Bitboard[0], p.Bitboard[1], p.PlayerTurn)
s.TTMap[key] = entry
}
func (s *Solver) RetrieveEntry(p *Position) TTEntry {
key := fmt.Sprintf("%d:%d:%d", p.Bitboard[0], p.Bitboard[1], p.PlayerTurn)
if entry, exists := s.TTMap[key]; exists {
s.TTMapHitCounter++
return entry
}
return TTEntry{}
}
What can I do to optimize this further? How can I make better keys without the use of fmt.Sprintf and string concatenation?
Edit:
The Position struct is keeps track of game state:
type Position struct {
Bitboard [2]uint64
PlayerTurn int
HeightBB [7]int
NumberOfMoves int
}
HeightBB is an array that keeps track of the height of the columns, so we know where to put the piece in the bitmap.
If you pay attention to the design of your data structures then I don't see any need for fmt.Sprintf
.
For example,
type TTKey struct {
Bitboard [2]uint64
PlayerTurn int
}
type TTFlag int64
type TTEntry struct {
BestScore float64
BestMove int
Flag TTFlag
Depth int
IsValid bool
}
type Solver struct {
NodeVisitCounter int
TTMapHitCounter int
TTMap map[TTKey]TTEntry
}
type Position struct {
Key TTKey
HeightBB [7]int
NumberOfMoves int
}
func (s *Solver) StoreEntry(p *Position, entry TTEntry) {
s.TTMap[p.Key] = entry
}
func (s *Solver) RetrieveEntry(p *Position) TTEntry {
if entry, exists := s.TTMap[p.Key]; exists {
s.TTMapHitCounter++
return entry
}
return TTEntry{}
}