-
Notifications
You must be signed in to change notification settings - Fork 1
/
pins.go
60 lines (45 loc) · 1.65 KB
/
pins.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package eval
import "github.com/herohde/morlock/pkg/board"
// Pin represents a pinned piece. A pinned piece cannot attack anything but
// the attacker itself, if the relative value of attacker/target is high enough.
type Pin struct {
Attacker, Pinned, Target board.Square
}
// FindPins returns all pins targeting the given piece.
func FindPins(pos *board.Position, side board.Color, piece board.Piece) []Pin {
var ret []Pin
bb := pos.Piece(side, piece)
for bb != 0 {
target := bb.LastPopSquare()
bb ^= board.BitMask(target)
// (1) Rook/Queen pins
rooks := board.RookAttackboard(pos.Rotated(), target)
pins := rooks & pos.Color(side)
for pins != 0 {
pinned := pins.LastPopSquare()
pins ^= board.BitMask(pinned)
attackers := pos.Piece(side.Opponent(), board.Queen) | pos.Piece(side.Opponent(), board.Rook)
candidate := (board.RookAttackboard(pos.Rotated().Xor(pinned), target) &^ rooks) & attackers
if candidate != 0 {
attacker := candidate.LastPopSquare()
p := Pin{Attacker: attacker, Pinned: pinned, Target: target}
ret = append(ret, p)
}
}
// (1) Bishop/Queen pins
bishops := board.BishopAttackboard(pos.Rotated(), target)
pins = bishops & pos.Color(side)
for pins != 0 {
pinned := pins.LastPopSquare()
pins ^= board.BitMask(pinned)
attackers := pos.Piece(side.Opponent(), board.Queen) | pos.Piece(side.Opponent(), board.Bishop)
candidate := (board.BishopAttackboard(pos.Rotated().Xor(pinned), target) &^ bishops) & attackers
if candidate != 0 {
attacker := candidate.LastPopSquare()
p := Pin{Attacker: attacker, Pinned: pinned, Target: target}
ret = append(ret, p)
}
}
}
return ret
}