Skip to content

Commit c4a0db2

Browse files
optimize isAttackedBy() and create board consistency check for debugging
1 parent 662a027 commit c4a0db2

File tree

4 files changed

+123
-85
lines changed

4 files changed

+123
-85
lines changed

attack.go

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,11 @@ func colorAttackMap(brd *Board, occ BB, sq int, c, e uint8) BB {
3535
}
3636

3737
func isAttackedBy(brd *Board, occ BB, sq int, attacker, defender uint8) bool {
38-
if pawnAttackMasks[defender][sq]&brd.pieces[attacker][PAWN] > 0 { // Pawns
39-
return true
40-
}
41-
if knightMasks[sq]&(brd.pieces[attacker][KNIGHT]) > 0 { // Knights
42-
return true
43-
}
44-
if kingMasks[sq]&(brd.pieces[attacker][KING]) > 0 { // Kings
45-
return true
46-
}
47-
if bishopAttacks(occ, sq)&(brd.pieces[attacker][BISHOP]|brd.pieces[attacker][QUEEN]) > 0 { // Bishops and Queens
48-
return true
49-
}
50-
if rookAttacks(occ, sq)&(brd.pieces[attacker][ROOK]|brd.pieces[attacker][QUEEN]) > 0 { // Rooks and Queens
51-
return true
52-
}
53-
return false
38+
return (pawnAttackMasks[defender][sq]&brd.pieces[attacker][PAWN] > 0) || // Pawns
39+
(knightMasks[sq]&(brd.pieces[attacker][KNIGHT]) > 0) || // Knights
40+
(kingMasks[sq]&(brd.pieces[attacker][KING]) > 0) || // Kings
41+
(bishopAttacks(occ, sq)&(brd.pieces[attacker][BISHOP]|brd.pieces[attacker][QUEEN]) > 0) || // Bishops and Queens
42+
(rookAttacks(occ, sq)&(brd.pieces[attacker][ROOK]|brd.pieces[attacker][QUEEN]) > 0) // Rooks and Queens
5443
}
5544

5645
func pinnedCanMove(brd *Board, from, to int, c, e uint8) bool {

board.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,21 @@ var printMutex sync.Mutex
1919

2020
// When spawning new goroutines for subtree search, a deep copy of the Board struct will have to be made
2121
// and passed to the new goroutine. Keep this struct as small as possible.
22+
// TODO: change material to uint16
2223
type Board struct {
2324
pieces [2][6]BB // 768 bits
2425
squares [64]Piece // 512 bits
2526
occupied [2]BB // 128 bits
26-
material [2]int32 // 64 bits
27-
hashKey uint64 // 64 bits
28-
pawnHashKey uint32 // 32 bits
29-
c uint8 // 8 bits
30-
castle uint8 // 8 bits
31-
enpTarget uint8 // 8 bits
32-
halfmoveClock uint8 // 8 bits
33-
endgameCounter uint8 // 8 bits
34-
worker *Worker
27+
material [2]int32 // 64 bits
28+
hashKey uint64 // 64 bits
29+
worker *Worker // 64 bits
30+
pawnHashKey uint32 // 32 bits
31+
c uint8 // 8 bits
32+
castle uint8 // 8 bits
33+
enpTarget uint8 // 8 bits
34+
halfmoveClock uint8 // 8 bits
35+
endgameCounter uint8 // 8 bits
36+
3537
}
3638

3739
type BoardMemento struct { // memento object used to store board state to unmake later.

move_gen_test.go

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -102,63 +102,3 @@ func PerftValidation(brd *Board, htable *HistoryTable, stk Stack, depth, ply int
102102
}
103103
return sum
104104
}
105-
106-
func CompareBoards(brd, other *Board) bool {
107-
equal := true
108-
if brd.pieces != other.pieces {
109-
fmt.Println("Board.pieces unequal")
110-
equal = false
111-
}
112-
if brd.squares != other.squares {
113-
fmt.Println("Board.squares unequal")
114-
fmt.Println("original:")
115-
brd.Print()
116-
fmt.Println("new board:")
117-
other.Print()
118-
equal = false
119-
}
120-
if brd.occupied != other.occupied {
121-
fmt.Println("Board.occupied unequal")
122-
for i := 0; i < 2; i++ {
123-
fmt.Printf("side: %d\n", i)
124-
fmt.Println("original:")
125-
brd.occupied[i].Print()
126-
fmt.Println("new board:")
127-
other.occupied[i].Print()
128-
}
129-
equal = false
130-
}
131-
if brd.material != other.material {
132-
fmt.Println("Board.material unequal")
133-
equal = false
134-
}
135-
if brd.hashKey != other.hashKey {
136-
fmt.Println("Board.hashKey unequal")
137-
equal = false
138-
}
139-
if brd.pawnHashKey != other.pawnHashKey {
140-
fmt.Println("Board.pawnHashKey unequal")
141-
equal = false
142-
}
143-
if brd.c != other.c {
144-
fmt.Println("Board.c unequal")
145-
equal = false
146-
}
147-
if brd.castle != other.castle {
148-
fmt.Println("Board.castle unequal")
149-
equal = false
150-
}
151-
if brd.enpTarget != other.enpTarget {
152-
fmt.Println("Board.enpTarget unequal")
153-
equal = false
154-
}
155-
if brd.halfmoveClock != other.halfmoveClock {
156-
fmt.Println("Board.halfmoveClock unequal")
157-
equal = false
158-
}
159-
if brd.endgameCounter != other.endgameCounter {
160-
fmt.Println("Board.endgameCounter unequal")
161-
equal = false
162-
}
163-
return equal
164-
}

utilities.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,110 @@ func correctMove(epd *EPD, moveStr string) bool {
6060
}
6161
return false
6262
}
63+
64+
func CompareBoards(brd, other *Board) bool {
65+
equal := true
66+
if brd.pieces != other.pieces {
67+
fmt.Println("Board.pieces unequal")
68+
equal = false
69+
}
70+
if brd.squares != other.squares {
71+
fmt.Println("Board.squares unequal")
72+
fmt.Println("original:")
73+
brd.Print()
74+
fmt.Println("new board:")
75+
other.Print()
76+
equal = false
77+
}
78+
if brd.occupied != other.occupied {
79+
fmt.Println("Board.occupied unequal")
80+
for i := 0; i < 2; i++ {
81+
fmt.Printf("side: %d\n", i)
82+
fmt.Println("original:")
83+
brd.occupied[i].Print()
84+
fmt.Println("new board:")
85+
other.occupied[i].Print()
86+
}
87+
equal = false
88+
}
89+
if brd.material != other.material {
90+
fmt.Println("Board.material unequal")
91+
equal = false
92+
}
93+
if brd.hashKey != other.hashKey {
94+
fmt.Println("Board.hashKey unequal")
95+
equal = false
96+
}
97+
if brd.pawnHashKey != other.pawnHashKey {
98+
fmt.Println("Board.pawnHashKey unequal")
99+
equal = false
100+
}
101+
if brd.c != other.c {
102+
fmt.Println("Board.c unequal")
103+
equal = false
104+
}
105+
if brd.castle != other.castle {
106+
fmt.Println("Board.castle unequal")
107+
equal = false
108+
}
109+
if brd.enpTarget != other.enpTarget {
110+
fmt.Println("Board.enpTarget unequal")
111+
equal = false
112+
}
113+
if brd.halfmoveClock != other.halfmoveClock {
114+
fmt.Println("Board.halfmoveClock unequal")
115+
equal = false
116+
}
117+
if brd.endgameCounter != other.endgameCounter {
118+
fmt.Println("Board.endgameCounter unequal")
119+
equal = false
120+
}
121+
return equal
122+
}
123+
124+
func isBoardConsistent(brd *Board) bool {
125+
var squares [64]Piece
126+
var occupied [2]BB
127+
var material [2]int32
128+
129+
var sq int
130+
for sq := 0; sq < 64; sq++ {
131+
squares[sq] = EMPTY
132+
}
133+
consistent := true
134+
135+
for c := uint8(BLACK); c <= WHITE; c++ {
136+
for pc := Piece(PAWN); pc <= KING; pc++ {
137+
if occupied[c]&brd.pieces[c][pc] > 0 {
138+
fmt.Printf("brd.pieces[%d][%d] overlaps with another pieces bitboard.\n", c, pc)
139+
consistent = false
140+
}
141+
occupied[c] |= brd.pieces[c][pc]
142+
143+
for bb := brd.pieces[c][pc]; bb > 0; bb.Clear(sq) {
144+
sq = furthestForward(c, bb)
145+
material[c] += int32(pc.Value() + mainPst[c][pc][sq])
146+
if squares[sq] != EMPTY {
147+
fmt.Printf("brd.pieces[%d][%d] overlaps with another pieces bitboard at %s.\n", c, pc, SquareString(sq))
148+
consistent = false
149+
}
150+
squares[sq] = pc
151+
}
152+
}
153+
}
154+
155+
if squares != brd.squares {
156+
fmt.Println("brd.squares inconsistent")
157+
consistent = false
158+
}
159+
if occupied != brd.occupied {
160+
fmt.Println("brd.occupied inconsistent")
161+
consistent = false
162+
}
163+
if material != brd.material {
164+
fmt.Println("brd.material inconsistent")
165+
consistent = false
166+
}
167+
168+
return consistent
169+
}

0 commit comments

Comments
 (0)