1+ #![ windows_subsystem = "windows" ]
2+
13use iced:: { button, container, slider, pick_list, Container , Align , Length , HorizontalAlignment , VerticalAlignment , Background , Button , Slider , PickList , Row , Column , Element , Sandbox , Settings , Text } ;
24use iced:: Font ;
35use chess:: { Board , BoardStatus , ChessMove , Color , Piece , Rank , Square , File } ;
@@ -134,6 +136,30 @@ impl PositionGUI {
134136 } ;
135137 Square :: make_square ( rank, file)
136138 }
139+
140+ pub fn chesssquare_to_posgui ( square : Square ) -> PositionGUI {
141+ let col = match square. get_file ( ) {
142+ File :: A => 0 ,
143+ File :: B => 1 ,
144+ File :: C => 2 ,
145+ File :: D => 3 ,
146+ File :: E => 4 ,
147+ File :: F => 5 ,
148+ File :: G => 6 ,
149+ File :: H => 7 ,
150+ } ;
151+ let row = match square. get_rank ( ) {
152+ Rank :: First => 0 ,
153+ Rank :: Second => 1 ,
154+ Rank :: Third => 2 ,
155+ Rank :: Fourth => 3 ,
156+ Rank :: Fifth => 4 ,
157+ Rank :: Sixth => 5 ,
158+ Rank :: Seventh => 6 ,
159+ Rank :: Eighth => 7 ,
160+ } ;
161+ PositionGUI :: new ( row, col)
162+ }
137163}
138164
139165#[ derive( Debug , Clone ) ]
@@ -167,11 +193,11 @@ pub enum TaticsThemes {
167193 Mate , MateIn1 , MateIn2 , MateIn3 , MateIn4 , MateIn5 , AnastasiaMate , ArabianMate , BackRankMate , BodenMate , DoubleBishopMate , DovetailMate , HookMate , SmotheredMate ,
168194 Castling , EnPassant , Promotion , UnderPromotion , Equality , Advantage , Crushing ,
169195 OneMove , Short , Long , VeryLong ,
170- Master , MasterVsMaster , SuperGM , OfPlayer
196+ Master , MasterVsMaster , SuperGM
171197}
172198
173199impl TaticsThemes {
174- const ALL : [ TaticsThemes ; 62 ] = [
200+ const ALL : [ TaticsThemes ; 61 ] = [
175201 TaticsThemes :: All ,
176202 TaticsThemes :: Opening , TaticsThemes :: Middlegame , TaticsThemes :: Endgame , TaticsThemes :: RookEndgame ,
177203 TaticsThemes :: BishopEndgame , TaticsThemes :: PawnEndgame , TaticsThemes :: KnightEndgame ,
@@ -198,7 +224,7 @@ impl TaticsThemes {
198224
199225 TaticsThemes :: OneMove , TaticsThemes :: Short , TaticsThemes :: Long , TaticsThemes :: VeryLong ,
200226
201- TaticsThemes :: Master , TaticsThemes :: MasterVsMaster , TaticsThemes :: SuperGM , TaticsThemes :: OfPlayer
227+ TaticsThemes :: Master , TaticsThemes :: MasterVsMaster , TaticsThemes :: SuperGM
202228 ] ;
203229}
204230
@@ -281,7 +307,6 @@ impl std::fmt::Display for TaticsThemes {
281307 TaticsThemes :: Master => "master" ,
282308 TaticsThemes :: MasterVsMaster => "masterVsMaster" ,
283309 TaticsThemes :: SuperGM => "superGM" ,
284- TaticsThemes :: OfPlayer => "of-player" ,
285310
286311 }
287312 )
@@ -403,6 +428,9 @@ pub struct OfflinePuzzles {
403428 from_square : Option < PositionGUI > ,
404429 board : Board ,
405430 squares : [ button:: State ; 64 ] ,
431+ last_move_from : Option < PositionGUI > ,
432+ last_move_to : Option < PositionGUI > ,
433+ is_playing : bool ,
406434
407435 theme_list : pick_list:: State < TaticsThemes > ,
408436 theme : TaticsThemes ,
@@ -431,6 +459,9 @@ impl Default for OfflinePuzzles {
431459 from_square : None ,
432460 board : Board :: default ( ) ,
433461 squares : [ button:: State :: default ( ) ; 64 ] ,
462+ last_move_from : None ,
463+ last_move_to : None ,
464+ is_playing : false ,
434465
435466 theme_list : pick_list:: State :: default ( ) ,
436467 theme : TaticsThemes :: default ( ) ,
@@ -499,7 +530,9 @@ impl Sandbox for OfflinePuzzles {
499530 fn update ( & mut self , message : Message ) {
500531 match ( self . from_square , message) {
501532 ( None , Message :: SelectSquare ( pos) ) => {
502- self . from_square = Some ( pos) ;
533+ if self . is_playing && self . board . color_on ( pos. posgui_to_square ( ) ) == Some ( self . board . side_to_move ( ) ) {
534+ self . from_square = Some ( pos) ;
535+ }
503536 } ( Some ( from) , Message :: SelectSquare ( to) ) if from != to => {
504537 self . from_square = None ;
505538
@@ -534,13 +567,12 @@ impl Sandbox for OfflinePuzzles {
534567
535568 // If the move is correct we can apply it to the board
536569 if is_mate || ( move_made == correct_move) {
537- //We can savely do these unwraps as we know it's a valid position
538-
570+
539571 self . board = self . board . make_move_new ( move_made) ;
540572 self . current_puzzle_move += 1 ;
541573
542574 if self . current_puzzle_move == correct_moves. len ( ) {
543- if self . current_puzzle < self . puzzles . len ( ) {
575+ if self . current_puzzle < self . puzzles . len ( ) - 1 {
544576 // The previous puzzle ended, and we still have puzzles available,
545577 // so we prepare the next one.
546578 self . current_puzzle += 1 ;
@@ -556,25 +588,41 @@ impl Sandbox for OfflinePuzzles {
556588 Square :: from_str ( & String :: from ( & puzzle_moves[ 0 ] [ ..2 ] ) ) . unwrap ( ) ,
557589 Square :: from_str ( & String :: from ( & puzzle_moves[ 0 ] [ 2 ..4 ] ) ) . unwrap ( ) , check_promotion ( & puzzle_moves[ 0 ] ) ) ;
558590
591+ self . last_move_from = Some ( PositionGUI :: chesssquare_to_posgui ( movement. get_source ( ) ) ) ;
592+ self . last_move_to = Some ( PositionGUI :: chesssquare_to_posgui ( movement. get_dest ( ) ) ) ;
593+
559594 self . board = self . board . make_move_new ( movement) ;
560595
561596 if self . board . side_to_move ( ) == Color :: White {
562597 self . puzzle_status = String :: from ( "White to move!" ) ;
563598 } else {
564599 self . puzzle_status = String :: from ( "Black to move!" ) ;
565600 }
601+ } else {
602+ self . board = Board :: default ( ) ;
603+ self . last_move_from = None ;
604+ self . last_move_to = None ;
605+ self . is_playing = false ;
606+ self . puzzle_status = String :: from ( "All puzzles done for this search!" ) ;
566607 }
567608 } else {
568609 movement = ChessMove :: new (
569610 Square :: from_str ( & String :: from ( & correct_moves[ self . current_puzzle_move ] [ ..2 ] ) ) . unwrap ( ) ,
570611 Square :: from_str ( & String :: from ( & correct_moves[ self . current_puzzle_move ] [ 2 ..4 ] ) ) . unwrap ( ) , check_promotion ( & correct_moves[ self . current_puzzle_move ] ) ) ;
571612
613+ self . last_move_from = Some ( PositionGUI :: chesssquare_to_posgui ( movement. get_source ( ) ) ) ;
614+ self . last_move_to = Some ( PositionGUI :: chesssquare_to_posgui ( movement. get_dest ( ) ) ) ;
615+
572616 self . board = self . board . make_move_new ( movement) ;
573617 self . current_puzzle_move += 1 ;
574618 self . puzzle_status = String :: from ( "Correct! What now?" ) ;
575619 }
576620 } else {
577- self . puzzle_status = String :: from ( "Ops! Wrong move..." ) ;
621+ if self . board . side_to_move ( ) == Color :: White {
622+ self . puzzle_status = String :: from ( "Ops! Wrong move... White to play." ) ;
623+ } else {
624+ self . puzzle_status = String :: from ( "Ops! Wrong move... Black to play." ) ;
625+ }
578626 }
579627 }
580628 } ( Some ( _) , Message :: SelectSquare ( to) ) => {
@@ -621,16 +669,23 @@ impl Sandbox for OfflinePuzzles {
621669 Square :: from_str ( & puzzle_moves[ 0 ] [ ..2 ] ) . unwrap ( ) ,
622670 Square :: from_str ( & puzzle_moves[ 0 ] [ 2 ..4 ] ) . unwrap ( ) , check_promotion ( & puzzle_moves[ 0 ] ) ) ;
623671
672+ self . last_move_from = Some ( PositionGUI :: chesssquare_to_posgui ( movement. get_source ( ) ) ) ;
673+ self . last_move_to = Some ( PositionGUI :: chesssquare_to_posgui ( movement. get_dest ( ) ) ) ;
674+
624675 self . board = self . board . make_move_new ( movement) ;
625676
626677 if self . board . side_to_move ( ) == Color :: White {
627678 self . puzzle_status = String :: from ( "white to move!" ) ;
628679 } else {
629680 self . puzzle_status = String :: from ( "Black to move!" ) ;
630681 }
682+ self . is_playing = true ;
631683 } else {
632684 // Just putting the default position to make it obvious the search ended.
633685 self . board = Board :: default ( ) ;
686+ self . last_move_from = None ;
687+ self . last_move_to = None ;
688+ self . is_playing = false ;
634689 self . puzzle_status = String :: from ( "Sorry, no puzzle found" ) ;
635690 }
636691 } Err ( _) => {
@@ -682,7 +737,9 @@ impl Sandbox for OfflinePuzzles {
682737 } ;
683738 }
684739 }
685-
740+
741+ let selected = self . from_square == Some ( pos) || self . last_move_from == Some ( pos) || self . last_move_to == Some ( pos) ;
742+
686743 row = row. push ( Button :: new ( button,
687744 Text :: new ( text)
688745 . horizontal_alignment ( HorizontalAlignment :: Center )
@@ -695,7 +752,7 @@ impl Sandbox for OfflinePuzzles {
695752 . width ( Length :: Units ( SETTINGS . square_size ) )
696753 . height ( Length :: Units ( SETTINGS . square_size ) )
697754 . on_press ( Message :: SelectSquare ( pos) )
698- . style ( ChessSquare :: from ( ( pos, self . from_square == Some ( pos ) ) ) )
755+ . style ( ChessSquare :: from ( ( pos, selected ) ) )
699756 ) ;
700757
701758 i += 1 ;
@@ -833,4 +890,4 @@ fn main() -> iced::Result {
833890 } ,
834891 ..Settings :: default ( )
835892 } )
836- }
893+ }
0 commit comments