1from gi.repository import Gtk 2 3from pychess.Utils.const import UNDOABLE_STATES, PRACTICE_GOAL_REACHED 4from pychess.Utils.Cord import Cord 5from pychess.Utils.LearnModel import learn2str, LESSON, PUZZLE 6from pychess.perspectives.learn.PuzzlesPanel import start_puzzle_from 7from pychess.perspectives.learn.EndgamesPanel import start_endgame_from 8from pychess.perspectives.learn.LessonsPanel import start_lesson_from 9from pychess.widgets import preferencesDialog 10 11HINT, MOVE, RETRY, CONTINUE, BACK_TO_MAINLINE, NEXT = range(6) 12 13 14css = """ 15@define-color error_fg_color rgb (235, 235, 235); 16@define-color error_bg_color rgb (223, 56, 44); 17 18 19.error { 20 background-image: -gtk-gradient (linear, left top, left bottom, 21 from (shade (@error_bg_color, 1.04)), 22 to (shade (@error_bg_color, 0.96))); 23 border-style: solid; 24 border-width: 1px; 25 26 color: @error_fg_color; 27 28 border-color: shade (@error_bg_color, 0.8); 29 border-bottom-color: shade (@error_bg_color, 0.75); 30 31 box-shadow: inset 1px 0 shade (@error_bg_color, 1.08), 32 inset -1px 0 shade (@error_bg_color, 1.08), 33 inset 0 1px shade (@error_bg_color, 1.1), 34 inset 0 -1px shade (@error_bg_color, 1.04); 35} 36""" 37 38 39def add_provider(widget): 40 screen = widget.get_screen() 41 style = widget.get_style_context() 42 provider = Gtk.CssProvider() 43 provider.load_from_data(css.encode('utf-8')) 44 style.add_provider_for_screen(screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_USER) 45 46 47class LearnInfoBar(Gtk.InfoBar): 48 def __init__(self, gamemodel, boardcontrol, annotation_panel): 49 Gtk.InfoBar.__init__(self) 50 self.connect("realize", add_provider) 51 52 self.content_area = self.get_content_area() 53 self.action_area = self.get_action_area() 54 55 self.gamemodel = gamemodel 56 self.boardcontrol = boardcontrol 57 self.boardview = boardcontrol.view 58 self.annotation_panel = annotation_panel 59 60 self.gamemodel.connect("game_changed", self.on_game_changed) 61 self.gamemodel.connect("goal_checked", self.on_goal_checked) 62 self.connect("response", self.on_response) 63 64 self.your_turn() 65 66 def clear(self): 67 for item in self.content_area: 68 self.content_area.remove(item) 69 70 for item in self.action_area: 71 self.action_area.remove(item) 72 73 def your_turn(self, shown_board=None): 74 self.clear() 75 self.set_message_type(Gtk.MessageType.QUESTION) 76 self.content_area.add(Gtk.Label(_("Your turn."))) 77 self.add_button(_("Hint"), HINT) 78 self.add_button(_("Best move"), MOVE) 79 self.show_all() 80 81 def get_next_puzzle(self): 82 self.clear() 83 self.set_message_type(Gtk.MessageType.INFO) 84 if self.gamemodel.learn_type in (LESSON, PUZZLE) and self.gamemodel.current_index + 1 == self.gamemodel.game_count: 85 self.content_area.add(Gtk.Label(_("Well done! %s completed." % learn2str[self.gamemodel.learn_type]))) 86 else: 87 if "FEN" in self.gamemodel.tags: 88 self.content_area.add(Gtk.Label(_("Well done!"))) 89 self.add_button(_("Next"), NEXT) 90 self.show_all() 91 preferencesDialog.SoundTab.playAction("puzzleSuccess") 92 93 self.gamemodel.solved = True 94 95 def opp_turn(self): 96 self.clear() 97 self.set_message_type(Gtk.MessageType.INFO) 98 self.add_button(_("Continue"), CONTINUE) 99 100 # disable playing 101 self.boardcontrol.game_preview = True 102 self.show_all() 103 104 def retry(self): 105 self.clear() 106 self.set_message_type(Gtk.MessageType.ERROR) 107 self.content_area.add(Gtk.Label(_("Not the best move!"))) 108 self.add_button(_("Retry"), RETRY) 109 110 # disable playing 111 self.boardcontrol.game_preview = True 112 113 # disable retry button until engine thinking on next move 114 if self.gamemodel.practice_game and self.gamemodel.status not in UNDOABLE_STATES: 115 self.set_response_sensitive(RETRY, False) 116 self.show_all() 117 118 def back_to_mainline(self): 119 self.clear() 120 self.set_message_type(Gtk.MessageType.INFO) 121 self.content_area.add(Gtk.Label(_("Cool! Now let see how it goes in the main line."))) 122 self.add_button(_("Back to main line"), BACK_TO_MAINLINE) 123 124 # disable playing 125 self.boardcontrol.game_preview = True 126 self.show_all() 127 128 def on_response(self, widget, response): 129 if response in (HINT, MOVE): 130 if self.gamemodel.lesson_game: 131 next_move = self.gamemodel.getMoveAtPly(self.boardview.shown, self.boardview.shown_variation_idx) 132 hints = {self.boardview.shown: ((next_move.as_uci(),),)} 133 else: 134 hints = self.gamemodel.hints 135 136 if self.boardview.shown in hints: 137 if self.boardview.arrows: 138 self.boardview.arrows.clear() 139 if self.boardview.circles: 140 self.boardview.circles.clear() 141 142 hint = hints[self.boardview.shown][0][0] 143 cord0 = Cord(hint[0], int(hint[1]), "G") 144 cord1 = Cord(hint[2], int(hint[3]), "G") 145 if response == HINT: 146 self.boardview.circles.add(cord0) 147 self.boardview.redrawCanvas() 148 else: 149 self.boardview.arrows.add((cord0, cord1)) 150 self.boardview.redrawCanvas() 151 else: 152 # TODO: 153 print("No hint available yet!", self.gamemodel.ply, self.boardview.shown) 154 155 elif response == RETRY: 156 self.your_turn() 157 158 if self.gamemodel.practice_game: 159 me_played_last_move = self.gamemodel.boards[-1].color != self.gamemodel.boards[0].color 160 moves = 1 if self.gamemodel.status in UNDOABLE_STATES and me_played_last_move else 2 161 self.gamemodel.undoMoves(moves) 162 163 elif self.gamemodel.lesson_game: 164 prev_board = self.gamemodel.getBoardAtPly( 165 self.boardview.shown - 1, 166 variation=self.boardview.shown_variation_idx) 167 168 self.annotation_panel.choices_enabled = False 169 170 self.boardview.setShownBoard(prev_board) 171 # We have to fix show_variation_index here, unless 172 # after removing the variation it will be invalid! 173 for vari in self.gamemodel.variations: 174 if prev_board in vari: 175 break 176 self.boardview.shown_variation_idx = self.gamemodel.variations.index(vari) 177 178 self.annotation_panel.choices_enabled = True 179 180 self.boardcontrol.game_preview = False 181 182 elif response == CONTINUE: 183 self.your_turn() 184 self.boardview.showNext() 185 self.boardcontrol.game_preview = False 186 187 elif response == BACK_TO_MAINLINE: 188 self.opp_turn() 189 self.boardview.backToMainLine() 190 self.boardcontrol.game_preview = False 191 192 elif response == NEXT: 193 if self.gamemodel.puzzle_game: 194 if self.gamemodel.from_lesson: 195 start_lesson_from(self.gamemodel.source, self.gamemodel.current_index + 1) 196 else: 197 start_puzzle_from(self.gamemodel.source, self.gamemodel.current_index + 1) 198 elif self.gamemodel.end_game: 199 start_endgame_from(self.gamemodel.source) 200 elif self.gamemodel.lesson_game: 201 start_lesson_from(self.gamemodel.source, self.gamemodel.current_index + 1) 202 else: 203 print(self.gamemodel.__dir__()) 204 205 def opp_choice_selected(self, board): 206 self.your_turn() 207 self.boardcontrol.game_preview = False 208 209 def on_game_changed(self, gamemodel, ply): 210 if gamemodel.practice_game: 211 if len(gamemodel.moves) % 2 == 0: 212 # engine moved, we can enable retry 213 self.set_response_sensitive(RETRY, True) 214 return 215 216 def on_goal_checked(self, gamemodel): 217 if gamemodel.status in UNDOABLE_STATES and self.gamemodel.end_game: 218 self.get_next_puzzle() 219 220 elif gamemodel.reason == PRACTICE_GOAL_REACHED: 221 self.get_next_puzzle() 222 223 elif gamemodel.failed_playing_best: 224 self.retry() 225 226 else: 227 self.your_turn() 228