11use std:: rc:: Rc ;
22use rustc_hash:: { FxHashMap , FxHashSet } ;
3+ use crate :: color:: Color ;
34use crate :: piece_move:: PieceMove ;
45use crate :: pieces:: Piece ;
56use crate :: point:: Point ;
67
78type MovesSetT = FxHashSet < PieceMove > ;
8- type PiecesSetT = FxHashSet < ( Rc < Piece > , PieceMove ) > ;
9+ type PiecesSetT = FxHashMap < Rc < Piece > , MovesSetT > ;
910type PieceToMovesMapT = FxHashMap < Rc < Piece > , MovesSetT > ;
1011type PointToPiecesMapT = FxHashMap < Point , PiecesSetT > ;
1112
@@ -47,17 +48,23 @@ impl MoveConstraints {
4748
4849pub struct MovesMap {
4950 piece_to_moves : PieceToMovesMapT ,
51+ // This is Point-to-Pieces-to-Moves structure that allows to fetch all moves for the certain
52+ // piece in the given point. It is useful because there can be several moves that ends on the
53+ // same point, but have different meaning. E.g. a promotion of a pawn ends up on the same point,
54+ // but with different promotion piece
5055 point_to_pieces : PointToPiecesMapT ,
5156 // Moves map of pieces, except the king when the king is in check
52- constraints : MoveConstraints ,
57+ general_constraints : MoveConstraints ,
58+ pin_constraints : FxHashMap < Rc < Piece > , MovesSetT > ,
5359}
5460
5561impl MovesMap {
5662 pub fn empty ( ) -> Self {
5763 let piece_to_moves = FxHashMap :: default ( ) ;
5864 let point_to_pieces = FxHashMap :: default ( ) ;
59- let constraints = MoveConstraints :: empty ( ) ;
60- Self { piece_to_moves, point_to_pieces, constraints }
65+ let general_constraints = MoveConstraints :: empty ( ) ;
66+ let pin_constraints = FxHashMap :: default ( ) ;
67+ Self { piece_to_moves, point_to_pieces, general_constraints, pin_constraints }
6168 }
6269
6370 fn moves_mut ( & mut self , piece : & Rc < Piece > ) -> & mut MovesSetT {
@@ -67,21 +74,25 @@ impl MovesMap {
6774 self . piece_to_moves . get_mut ( piece) . unwrap ( )
6875 }
6976
70- fn pieces_mut ( & mut self , point : Point ) -> & mut PiecesSetT {
77+ fn pieces_mut ( & mut self , point : Point , piece : & Rc < Piece > ) -> & mut MovesSetT {
7178 if !self . point_to_pieces . contains_key ( & point) {
72- self . point_to_pieces . insert ( point, FxHashSet :: default ( ) ) ;
79+ self . point_to_pieces . insert ( point, FxHashMap :: default ( ) ) ;
7380 }
74- self . point_to_pieces . get_mut ( & point) . unwrap ( )
81+ let pieces_hashmap = self . point_to_pieces . get_mut ( & point) . unwrap ( ) ;
82+ if !pieces_hashmap. contains_key ( piece) {
83+ pieces_hashmap. insert ( Rc :: clone ( piece) , FxHashSet :: default ( ) ) ;
84+ }
85+ self . point_to_pieces . get_mut ( & point) . unwrap ( ) . get_mut ( piece) . unwrap ( )
7586 }
7687
7788 pub fn moves_of ( & self , piece : & Rc < Piece > ) -> Option < & MovesSetT > {
7889 match & * * piece {
7990 Piece :: King ( _) => { self . piece_to_moves . get ( piece) } ,
8091 _ => {
81- if self . constraints . is_enabled ( ) {
82- self . constraints . get ( piece)
92+ if self . general_constraints . is_enabled ( ) {
93+ self . general_constraints . get ( piece)
8394 } else {
84- self . piece_to_moves . get ( piece)
95+ self . pin_constraints . get ( piece ) . or ( self . piece_to_moves . get ( piece) )
8596 }
8697 } ,
8798 }
@@ -99,7 +110,7 @@ impl MovesMap {
99110 match piece_move. destination ( ) {
100111 Some ( point) => {
101112 self . moves_mut ( piece) . insert ( piece_move)
102- && self . pieces_mut ( point) . insert ( ( Rc :: clone ( piece ) , piece_move) )
113+ && self . pieces_mut ( point, piece ) . insert ( piece_move)
103114 } ,
104115 None => self . moves_mut ( piece) . insert ( piece_move) ,
105116 }
@@ -111,7 +122,7 @@ impl MovesMap {
111122 for piece_move in moves. iter ( ) {
112123 if let Some ( point) = piece_move. destination ( ) {
113124 if let Some ( pieces) = self . point_to_pieces . get_mut ( & point) {
114- pieces. remove ( & ( Rc :: clone ( piece) , * piece_move ) ) ;
125+ pieces. remove ( piece) ;
115126 if pieces. is_empty ( ) {
116127 self . point_to_pieces . remove ( & point) ;
117128 }
@@ -121,18 +132,59 @@ impl MovesMap {
121132 }
122133 }
123134
124- pub fn clear_constraints ( & mut self ) {
125- self . constraints . clear ( ) ;
135+ pub fn clear_general_constraints ( & mut self ) {
136+ self . general_constraints . clear ( ) ;
126137 }
127138
128- pub fn add_constraints ( & mut self , piece_move : PieceMove ) {
129- self . constraints . enable ( ) ;
139+ pub fn add_general_constraints ( & mut self , piece_move : PieceMove ) {
140+ self . general_constraints . enable ( ) ;
130141 if let Some ( point) = piece_move. destination ( ) {
131142 if let Some ( pieces) = self . point_to_pieces . get ( & point) {
132- for ( piece, piece_move) in pieces {
133- self . constraints . get_mut ( piece) . insert ( * piece_move) ;
143+ for ( piece, piece_moves) in pieces {
144+ if let Some ( pin_constraints) = self . pin_constraints . get ( piece) {
145+ for piece_move in piece_moves {
146+ if pin_constraints. contains ( piece_move) {
147+ self . general_constraints . get_mut ( piece) . insert ( * piece_move) ;
148+ }
149+ }
150+ } else {
151+ for piece_move in piece_moves {
152+ self . general_constraints . get_mut ( piece) . insert ( * piece_move) ;
153+ }
154+ }
155+
134156 }
135157 }
136158 }
137159 }
160+
161+ pub fn add_pin_constraints ( & mut self , pinned : & Rc < Piece > , points : & Vec < Point > ) {
162+ if !self . pin_constraints . contains_key ( pinned) {
163+ self . pin_constraints . insert ( Rc :: clone ( pinned) , FxHashSet :: default ( ) ) ;
164+ }
165+
166+ // Build an intersection of moves of the given piece based on provided constraints and
167+ // available moves
168+ for point in points {
169+ if let Some ( pieces) = self . point_to_pieces . get ( & point) {
170+ if let Some ( moves) = pieces. get ( pinned) {
171+ for piece_move in moves {
172+ self . pin_constraints . get_mut ( pinned) . unwrap ( ) . insert ( * piece_move) ;
173+ }
174+ }
175+ }
176+ }
177+ }
178+
179+ pub fn clear_pin_constraints_of ( & mut self , pinned : & Rc < Piece > ) {
180+ self . pin_constraints . remove ( pinned) ;
181+ }
182+
183+ pub fn pinned_pieces ( & self ) -> Vec < & Rc < Piece > > {
184+ self . pin_constraints . keys ( ) . collect :: < Vec < _ > > ( )
185+ }
186+
187+ pub fn has_pin_constraints ( & self , piece : & Rc < Piece > ) -> bool {
188+ self . pin_constraints . contains_key ( piece)
189+ }
138190}
0 commit comments