def set (key, value): try: configParser.set (section, key, str(value)) configParser.set (section+"_Types", key, typeEncode[type(value)]) except Exception, e: log.error("Unable to save configuration '%s'='%s' because of error: %s %s"% (repr(key), repr(value), e.__class__.__name__, ", ".join(str(a) for a in e.args)))
def save(self, *args): try: with open(self.jsonpath, "w") as f: json.dump(self._engines, f, indent=1, sort_keys=True) except IOError as e: log.error("Saving engines.json raised exception: %s" % \ ", ".join(str(a) for a in e.args))
def cb(self_, *args): try: with open(self.xmlpath, "w") as f: self.dom.write(f) except IOError, e: log.error("Saving enginexml raised exception: %s\n" % \ ", ".join(str(a) for a in e.args))
def getBoardAtPly(self, ply): try: return self.boards[self._plyToIndex(ply)] except: log.error("%d\t%d\t%d\t%d\n" % (self.lowply, ply, self.ply, len(self.boards))) raise
def load_from_xml(self): if os.path.isfile(self.dockLocation): try: self.dock.loadFromXML(self.dockLocation, self.docks) except Exception as e: # We don't send error message when error caused by no more existing SwitcherPanel if e.args[0] != "SwitcherPanel" and "unittest" not in sys.modules.keys(): stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("Dock loading error: %s\n%s" % (e, error)) msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE) msg_dia.set_markup(_( "<b><big>PyChess was unable to load your panel settings</big></b>")) msg_dia.format_secondary_text(_( "Your panel settings have been reset. If this problem repeats, \ you should report it to the developers")) msg_dia.run() msg_dia.hide() os.remove(self.dockLocation) for title, panel, menu_item in self.docks.values(): title.unparent() panel.unparent()
def _get_waitingplayer(self): try: return self.players[1 - self.getBoardAtPly(self.ply).color] except IndexError: log.error("%s %s" % (self.players, 1 - self.getBoardAtPly(self.ply).color)) raise
def save(self, *args): try: with open(self.jsonpath, "w") as file_handle: json.dump(self.engines, file_handle, indent=1, sort_keys=True) except IOError as err: log.error("Saving engines.json raised exception: %s" % ", ".join(str(a) for a in err.args))
def page_reordered (widget, child, new_num, headbook): old_num = notebooks["board"].page_num(key2gmwidg[child].boardvbox) if old_num == -1: log.error('Games and labels are out of sync!') else: for notebook in notebooks.values(): notebook.reorder_child(notebook.get_nth_page(old_num), new_num)
def _get_curplayer(self): try: return self.players[self.getBoardAtPly(self.ply).color] except IndexError: log.error("%s %s\n" % (self.players, self.getBoardAtPly(self.ply).color)) raise
def getBoardAtPly(self, ply, variation=0): try: return self.variations[variation][self._plyToIndex(ply)] except IndexError: log.error("%d\t%d\t%d\t%d\t%d" % (self.lowply, ply, self.ply, variation, len(self.variations))) raise
def getMoveAtPly(self, ply): try: return self.moves[self._plyToIndex(ply)] except IndexError: log.error("%d\t%d\t%d\t%d\n" % (self.lowply, ply, self.ply, len(self.moves))) raise
def play(self, uri): try: winsound.PlaySound(None, 0) winsound.PlaySound(url2pathname(uri[5:]), winsound.SND_FILENAME | winsound.SND_ASYNC) except RuntimeError: log.error("ERROR: RuntimeError while playing %s." % url2pathname(uri[5:]))
def getMoveAtPly(self, ply, variation=0): try: return Move(self.variations[variation][self._plyToIndex(ply) + 1].board.lastMove) except IndexError: log.error("%d\t%d\t%d\t%d\t%d" % (self.lowply, ply, self.ply, variation, len(self.variations))) raise
def getBoardAtPly (self, ply, variation=0): # Losing on time in FICS game will undo our last move if it was taken too late if variation == 0 and ply > self.ply: ply = self.ply try: return self.variations[variation][self._plyToIndex(ply)] except IndexError: log.error("%d\t%d\t%d\t%d\t%d" % (self.lowply, ply, self.ply, variation, len(self.variations))) raise
def set (key, value): try: configParser.set (section, key, str(value)) except Exception as e: log.error("Unable to save configuration '%s'='%s' because of error: %s %s"% (repr(key), repr(value), e.__class__.__name__, ", ".join(str(a) for a in e.args))) for key_, func, args in idkeyfuncs.values(): if key_ == key: func (None, *args)
def getBoardAtPly(self, ply, variation=0): # Losing on time in FICS game will undo our last move if it was taken too late if variation == 0 and ply > self.ply: ply = self.ply try: return self.variations[variation][self._plyToIndex(ply)] except IndexError: log.error("%d\t%d\t%d\t%d\t%d" % (self.lowply, ply, self.ply, variation, len(self.variations))) raise
def set(key, value): try: configParser.set(section, key, str(value)) except Exception as e: log.error( "Unable to save configuration '%s'='%s' because of error: %s %s" % (repr(key), repr(value), e.__class__.__name__, ", ".join( str(a) for a in e.args))) for key_, func, args in idkeyfuncs.values(): if key_ == key: func(None, *args)
def set(key, value, section=section): try: configParser.set(section, key, str(value)) configParser.write(open(path, "w")) except Exception as err: log.error( "Unable to save configuration '%s'='%s' because of error: %s %s" % (repr(key), repr(value), err.__class__.__name__, ", ".join( str(a) for a in err.args))) for key_, func, args, section_ in idkeyfuncs.values(): if key_ == key and section_ == section: func(None, *args)
def onOfferAdd(self, match): log.debug("OfferManager.onOfferAdd: match.string=%s\n" % match.string) tofrom, index, offertype, parameters = match.groups() if tofrom == "t": # ICGameModel keeps track of the offers we've sent ourselves, so we # don't need this return if offertype not in strToOfferType: log.error("OfferManager.onOfferAdd: Declining unknown offer type: " + \ "offertype=%s parameters=%s index=%s\n" % (offertype, parameters, index)) print >> self.connection.client, "decline", index offertype = strToOfferType[offertype] if offertype == TAKEBACK_OFFER: offer = Offer(offertype, param=int(parameters), index=int(index)) else: offer = Offer(offertype, index=int(index)) self.offers[offer.index] = offer if offer.type == MATCH_OFFER: if matchreUntimed.match(parameters) != None: fname, frating, col, tname, trating, rated, type = \ matchreUntimed.match(parameters).groups() mins = "0" incr = "0" else: fname, frating, col, tname, trating, rated, type_short, mins, incr, type = \ matchre.match(parameters).groups() if not type or "adjourned" in type: type = type_short if type.split()[-1] in unsupportedtypes: self.decline(offer) else: rating = frating.strip() rating = rating.isdigit() and rating or "0" rated = rated == "unrated" and "u" or "r" match = { "tp": convertName(type), "w": fname, "rt": rating, "r": rated, "t": mins, "i": incr } self.emit("onChallengeAdd", index, match) else: log.debug("OfferManager.onOfferAdd: emitting onOfferAdd: %s\n" % offer) self.emit("onOfferAdd", offer)
def run(self): # Avoid racecondition when self.start is called while we are in self.end if self.status != WAITING_TO_START: return self.status = RUNNING for player in self.players + self.spectactors.values(): player.start() self.emit("game_started") while self.status in (PAUSED, RUNNING, DRAW, WHITEWON, BLACKWON): curColor = self.boards[-1].color curPlayer = self.players[curColor] if self.timemodel: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: updating %s's time\n" % \ (id(self), str(self.players), str(self.ply), str(curPlayer))) curPlayer.updateTime( self.timemodel.getPlayerTime(curColor), self.timemodel.getPlayerTime(1 - curColor)) try: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: calling %s.makeMove()\n" % \ (id(self), str(self.players), self.ply, str(curPlayer))) if self.ply > self.lowply: move = curPlayer.makeMove(self.boards[-1], self.moves[-1], self.boards[-2]) else: move = curPlayer.makeMove(self.boards[-1], None, None) log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: got move=%s from %s\n" % \ (id(self), str(self.players), self.ply, move, str(curPlayer))) except PlayerIsDead, e: if self.status in (WAITING_TO_START, PAUSED, RUNNING): stringio = cStringIO.StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error( "GameModel.run: A Player died: player=%s error=%s\n%s" % (curPlayer, error, e)) if curColor == WHITE: self.kill(WHITE_ENGINE_DIED) else: self.kill(BLACK_ENGINE_DIED) break except TurnInterrupt: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: TurnInterrupt\n" % \ (id(self), str(self.players), self.ply)) continue
def savePosition(window, *event): width = window.get_allocation().width height = window.get_allocation().height x, y = window.get_position() if width <= 0: log.error("Setting width = '%d' for %s to conf" % (width, key)) if height <= 0: log.error("Setting height = '%d' for %s to conf" % (height, key)) conf.set(key + "_width", width) conf.set(key + "_height", height) conf.set(key + "_x", x) conf.set(key + "_y", y)
def savePosition (window, *event): width = window.get_allocation().width height = window.get_allocation().height x, y = window.get_position() if width <= 0: log.error("Setting width = '%d' for %s to conf" % (width,key)) if height <= 0: log.error("Setting height = '%d' for %s to conf" % (height,key)) conf.set(key+"_width", width) conf.set(key+"_height", height) conf.set(key+"_x", x) conf.set(key+"_y", y)
def run (self): # Avoid racecondition when self.start is called while we are in self.end if self.status != WAITING_TO_START: return self.status = RUNNING for player in self.players + self.spectactors.values(): player.start() self.emit("game_started") while self.status in (PAUSED, RUNNING, DRAW, WHITEWON, BLACKWON): curColor = self.boards[-1].color curPlayer = self.players[curColor] if self.timemodel: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: updating %s's time\n" % \ (id(self), str(self.players), str(self.ply), str(curPlayer))) curPlayer.updateTime(self.timemodel.getPlayerTime(curColor), self.timemodel.getPlayerTime(1-curColor)) try: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: calling %s.makeMove()\n" % \ (id(self), str(self.players), self.ply, str(curPlayer))) if self.ply > self.lowply: move = curPlayer.makeMove(self.boards[-1], self.moves[-1], self.boards[-2]) else: move = curPlayer.makeMove(self.boards[-1], None, None) log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: got move=%s from %s\n" % \ (id(self), str(self.players), self.ply, move, str(curPlayer))) except PlayerIsDead, e: if self.status in (WAITING_TO_START, PAUSED, RUNNING): stringio = cStringIO.StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("GameModel.run: A Player died: player=%s error=%s\n%s" % (curPlayer, error, e)) if curColor == WHITE: self.kill(WHITE_ENGINE_DIED) else: self.kill(BLACK_ENGINE_DIED) break except TurnInterrupt: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: TurnInterrupt\n" % \ (id(self), str(self.players), self.ply)) continue
def onOfferAdd (self, match): log.debug("OfferManager.onOfferAdd: match.string=%s\n" % match.string) tofrom, index, offertype, parameters = match.groups() if tofrom == "t": # ICGameModel keeps track of the offers we've sent ourselves, so we # don't need this return if offertype not in strToOfferType: log.error("OfferManager.onOfferAdd: Declining unknown offer type: " + \ "offertype=%s parameters=%s index=%s\n" % (offertype, parameters, index)) print >> self.connection.client, "decline", index offertype = strToOfferType[offertype] if offertype == TAKEBACK_OFFER: offer = Offer(offertype, param=int(parameters), index=int(index)) else: offer = Offer(offertype, index=int(index)) self.offers[offer.index] = offer if offer.type == MATCH_OFFER: if matchreUntimed.match(parameters) != None: fname, frating, col, tname, trating, rated, type = \ matchreUntimed.match(parameters).groups() mins = "0" incr = "0" else: fname, frating, col, tname, trating, rated, type_short, mins, incr, type = \ matchre.match(parameters).groups() if not type or "adjourned" in type: type = type_short if type.split()[-1] in unsupportedtypes: self.decline(offer) else: rating = frating.strip() rating = rating.isdigit() and rating or "0" rated = rated == "unrated" and "u" or "r" match = {"tp": convertName(type), "w": fname, "rt": rating, "r": rated, "t": mins, "i": incr} self.emit("onChallengeAdd", index, match) else: log.debug("OfferManager.onOfferAdd: emitting onOfferAdd: %s\n" % offer) self.emit("onOfferAdd", offer)
def savePosition(window, *event): log.debug("keepWindowSize.savePosition: %s" % window.get_title()) width = window.get_allocation().width height = window.get_allocation().height x, y = window.get_position() if width <= 0: log.error("Setting width = '%d' for %s to conf" % (width, key)) if height <= 0: log.error("Setting height = '%d' for %s to conf" % (height, key)) log.debug("Saving window position width=%s height=%s x=%s y=%s" % (width, height, x, y)) conf.set(key + "_width", width) conf.set(key + "_height", height) conf.set(key + "_x", x) conf.set(key + "_y", y) return False
def savePosition(window, *event): log.debug("keepWindowSize.savePosition: %s" % window.get_title()) width = window.get_allocation().width height = window.get_allocation().height x_loc, y_loc = window.get_position() if width <= 0: log.error("Setting width = '%d' for %s to conf" % (width, key)) if height <= 0: log.error("Setting height = '%d' for %s to conf" % (height, key)) log.debug("Saving window position width=%s height=%s x=%s y=%s" % (width, height, x_loc, y_loc)) conf.set(key + "_width", width) conf.set(key + "_height", height) conf.set(key + "_x", x_loc) conf.set(key + "_y", y_loc) return False
def __init__(self): PYTHONBIN = sys.executable.split("/")[-1] try: if getattr(sys, 'frozen', False): gst_player = os.path.join( os.path.abspath(os.path.dirname(sys.executable)), "gst_player.py") else: gst_player = os.path.join( os.path.abspath(os.path.dirname(__file__)), "gst_player.py") self.player = subprocess.Popen([PYTHONBIN, gst_player], stdin=subprocess.PIPE) self.stdin = io.TextIOWrapper(self.player.stdin, encoding='utf-8', line_buffering=True) self.ready = True except Exception: self.player = None log.error('ERROR: starting gst_player failed') raise
def _get_curplayer (self): try: return self.players[self.getBoardAtPly(self.ply).color] except IndexError: log.error("%s %s\n" % (self.players, self.getBoardAtPly(self.ply).color)) raise
def coro(): persp = perspective_manager.get_perspective("games") gmwidg = persp.cur_gmwidg() gamemodel = gmwidg.gamemodel old_check_value = conf.get("analyzer_check") conf.set("analyzer_check", True) if HINT not in gamemodel.spectators: try: yield from asyncio.wait_for(gamemodel.start_analyzer(HINT), 5.0) except asyncio.TimeoutError: log.error("Got timeout error while starting hint analyzer") return except Exception: log.error("Unknown error while starting hint analyzer") return analyzer = gamemodel.spectators[HINT] gmwidg.menuitems["hint_mode"].active = True threat_PV = conf.get("ThreatPV") if threat_PV: old_inv_check_value = conf.get("inv_analyzer_check") conf.set("inv_analyzer_check", True) if SPY not in gamemodel.spectators: try: yield from asyncio.wait_for(gamemodel.start_analyzer(SPY), 5.0) except asyncio.TimeoutError: log.error("Got timeout error while starting spy analyzer") return except Exception: log.error("Unknown error while starting spy analyzer") return inv_analyzer = gamemodel.spectators[SPY] gmwidg.menuitems["spy_mode"].active = True title = _("Game analyzing in progress...") text = _("Do you want to abort it?") content = InfoBar.get_message_content(title, text, Gtk.STOCK_DIALOG_QUESTION) def response_cb(infobar, response, message): conf.set("analyzer_check", old_check_value) if threat_PV: conf.set("inv_analyzer_check", old_inv_check_value) message.dismiss() abort() message = InfoBarMessage(Gtk.MessageType.QUESTION, content, response_cb) message.add_button(InfoBarMessageButton(_("Abort"), Gtk.ResponseType.CANCEL)) gmwidg.replaceMessages(message) @asyncio.coroutine def analyse_moves(): should_black = conf.get("shouldBlack") should_white = conf.get("shouldWhite") from_current = conf.get("fromCurrent") start_ply = gmwidg.board.view.shown if from_current else 0 move_time = int(conf.get("max_analysis_spin")) threshold = int(conf.get("variation_threshold_spin")) for board in gamemodel.boards[start_ply:]: if self.stop_event.is_set(): break gmwidg.board.view.setShownBoard(board) analyzer.setBoard(board) if threat_PV: inv_analyzer.setBoard(board) yield from asyncio.sleep(move_time + 0.1) ply = board.ply - gamemodel.lowply color = (ply - 1) % 2 if ply - 1 in gamemodel.scores and ply in gamemodel.scores and ( (color == BLACK and should_black) or (color == WHITE and should_white)): oldmoves, oldscore, olddepth = gamemodel.scores[ply - 1] oldscore = oldscore * -1 if color == BLACK else oldscore score_str = prettyPrintScore(oldscore, olddepth) moves, score, depth = gamemodel.scores[ply] score = score * -1 if color == WHITE else score diff = score - oldscore if ((diff > threshold and color == BLACK) or (diff < -1 * threshold and color == WHITE)) and ( gamemodel.moves[ply - 1] != parseAny(gamemodel.boards[ply - 1], oldmoves[0])): if threat_PV: try: if ply - 1 in gamemodel.spy_scores: oldmoves0, oldscore0, olddepth0 = gamemodel.spy_scores[ply - 1] score_str0 = prettyPrintScore(oldscore0, olddepth0) pv0 = listToMoves(gamemodel.boards[ply - 1], ["--"] + oldmoves0, validate=True) if len(pv0) > 2: gamemodel.add_variation(gamemodel.boards[ply - 1], pv0, comment="Threatening", score=score_str0, emit=False) except ParsingError as e: # ParsingErrors may happen when parsing "old" lines from # analyzing engines, which haven't yet noticed their new tasks log.debug("__parseLine: Ignored (%s) from analyzer: ParsingError%s" % (' '.join(oldmoves), e)) try: pv = listToMoves(gamemodel.boards[ply - 1], oldmoves, validate=True) gamemodel.add_variation(gamemodel.boards[ply - 1], pv, comment="Better is", score=score_str, emit=False) except ParsingError as e: # ParsingErrors may happen when parsing "old" lines from # analyzing engines, which haven't yet noticed their new tasks log.debug("__parseLine: Ignored (%s) from analyzer: ParsingError%s" % (' '.join(oldmoves), e)) self.widgets["analyze_game"].hide() self.widgets["analyze_ok_button"].set_sensitive(True) conf.set("analyzer_check", old_check_value) if threat_PV: conf.set("inv_analyzer_check", old_inv_check_value) message.dismiss() gamemodel.emit("analysis_finished") create_task(analyse_moves()) hide_window(None) return True
def getBoardAtPly (self, ply): try: return self.boards[self._plyToIndex(ply)] except: log.error("%d\t%d\t%d\t%d\n" % (self.lowply, ply, self.ply, len(self.boards))) raise
def getMoveAtPly (self, ply): try: return self.moves[self._plyToIndex(ply)] except IndexError: log.error("%d\t%d\t%d\t%d\n" % (self.lowply, ply, self.ply, len(self.moves))) raise
def __parseLine (self, line): if not self.connected: return parts = line.split() if not parts: return #---------------------------------------------------------- Initializing if parts[0] == "id": self.ids[parts[1]] = " ".join(parts[2:]) if parts[1] == "name": self.setName(self.ids["name"]) return if parts[0] == "uciok": self.emit("readyForOptions") return if parts[0] == "readyok": self.emit("readyForMoves") return #------------------------------------------------------- Options parsing if parts[0] == "option": dic = {} last = 1 varlist = [] for i in range (2, len(parts)+1): if i == len(parts) or parts[i] in OPTKEYS: key = parts[last] value = " ".join(parts[last+1:i]) if "type" in dic and dic["type"] in TYPEDIC: value = TYPEDIC[dic["type"]](value) if key == "var": varlist.append(value) elif key == "type" and value == "string": dic[key] = "text" else: dic[key] = value last = i if varlist: dic["choices"] = varlist self.options[dic["name"]] = dic return #---------------------------------------------------------------- A Move if self.mode == NORMAL and parts[0] == "bestmove": with self.moveLock: self.needBestmove = False self.__sendQueuedGo() if self.ignoreNext: log.debug("__parseLine: line='%s' self.ignoreNext==True, returning" % \ line.strip(), extra={"task":self.defname}) self.ignoreNext = False self.readyForStop = True return if not self.waitingForMove: log.warning("__parseLine: self.waitingForMove==False, ignoring move=%s" % \ parts[1], extra={"task":self.defname}) self.pondermove = None return self.waitingForMove = False try: move = parseAny(self.board, parts[1]) except ParsingError as e: self.end(WHITEWON if self.board.color == BLACK else BLACKWON, WON_ADJUDICATION) return if not validate(self.board, move): # This is critical. To avoid game stalls, we need to resign on # behalf of the engine. log.error("__parseLine: move=%s didn't validate, putting 'del' in returnQueue. self.board=%s" % \ (repr(move), self.board), extra={"task":self.defname}) self.end(WHITEWON if self.board.color == BLACK else BLACKWON, WON_ADJUDICATION) return self._recordMove(self.board.move(move), move, self.board) log.debug("__parseLine: applied move=%s to self.board=%s" % \ (move, self.board), extra={"task":self.defname}) if self.ponderOn: self.pondermove = None # An engine may send an empty ponder line, simply to clear. if len(parts) == 4: # Engines don't always check for everything in their # ponders. Hence we need to validate. # But in some cases, what they send may not even be # correct AN - specially in the case of promotion. try: pondermove = parseAny(self.board, parts[3]) except ParsingError: pass else: if validate(self.board, pondermove): self.pondermove = pondermove self._startPonder() self.returnQueue.put(move) log.debug("__parseLine: put move=%s into self.returnQueue=%s" % \ (move, self.returnQueue.queue), extra={"task":self.defname}) return #----------------------------------------------------------- An Analysis if self.mode != NORMAL and parts[0] == "info" and "pv" in parts: multipv = 1 if "multipv" in parts: multipv = int(parts[parts.index("multipv")+1]) scoretype = parts[parts.index("score")+1] if scoretype in ('lowerbound', 'upperbound'): score = None else: score = int(parts[parts.index("score")+2]) if scoretype == 'mate': # print >> self.engine, "stop" if score != 0: sign = score/abs(score) score = sign*MATE_VALUE movstrs = parts[parts.index("pv")+1:] try: moves = listToMoves (self.board, movstrs, AN, validate=True, ignoreErrors=False) except ParsingError as e: # ParsingErrors may happen when parsing "old" lines from # analyzing engines, which haven't yet noticed their new tasks log.debug("__parseLine: Ignored (%s) from analyzer: ParsingError%s" % \ (' '.join(movstrs),e), extra={"task":self.defname}) return if "depth" in parts: depth = parts[parts.index("depth")+1] else: depth = "" if multipv <= len(self.analysis): self.analysis[multipv - 1] = (moves, score, depth) self.emit("analyze", self.analysis) return #----------------------------------------------- An Analyzer bestmove if self.mode != NORMAL and parts[0] == "bestmove": with self.moveLock: log.debug("__parseLine: processing analyzer bestmove='%s'" % \ line.strip(), extra={"task":self.defname}) self.needBestmove = False self.__sendQueuedGo(sendlast=True) return # Stockfish complaining it received a 'stop' without a corresponding 'position..go' if line.strip() == "Unknown command: stop": with self.moveLock: log.debug("__parseLine: processing '%s'" % line.strip(), extra={"task":self.defname}) self.ignoreNext = False self.needBestmove = False self.readyForStop = False self.__sendQueuedGo() return
def _ensureReadForGameWidgets(): mainvbox = widgets["mainvbox"] if len(mainvbox.get_children()) == 3: return global background, notebooks notebooks = get_clean_notebooks(mainvbox) background = widgets["mainvbox"].get_children()[1] mainvbox.remove(background) # Initing headbook align = createAlignment(4, 4, 0, 4) align.set_property("yscale", 0) headbook = Gtk.Notebook() headbook.set_scrollable(True) align.add(headbook) mainvbox.pack_start(align, False, True, 0) show_tabs(not conf.get("hideTabs", False)) # Initing center centerVBox = Gtk.VBox() # The dock global dock, dockAlign dock = PyDockTop("main") dockAlign = createAlignment(4, 4, 0, 4) dockAlign.add(dock) centerVBox.pack_start(dockAlign, True, True, 0) dockAlign.show() dock.show() for panel in sidePanels: hbox = Gtk.HBox() pixbuf = get_pixbuf(panel.__icon__, 16) icon = Gtk.Image.new_from_pixbuf(pixbuf) label = Gtk.Label(label=panel.__title__) label.set_size_request(0, 0) label.set_alignment(0, 1) hbox.pack_start(icon, False, False, 0) hbox.pack_start(label, True, True, 0) hbox.set_spacing(2) hbox.show_all() def cb(widget, x, y, keyboard_mode, tooltip, title, desc, filename): table = Gtk.Table(2, 2) table.set_row_spacings(2) table.set_col_spacings(6) table.set_border_width(4) pixbuf = get_pixbuf(filename, 56) image = Gtk.Image.new_from_pixbuf(pixbuf) image.set_alignment(0, 0) table.attach(image, 0, 1, 0, 2) titleLabel = Gtk.Label() titleLabel.set_markup("<b>%s</b>" % title) titleLabel.set_alignment(0, 0) table.attach(titleLabel, 1, 2, 0, 1) descLabel = Gtk.Label(label=desc) descLabel.props.wrap = True table.attach(descLabel, 1, 2, 1, 2) tooltip.set_custom(table) table.show_all() return True hbox.props.has_tooltip = True hbox.connect("query-tooltip", cb, panel.__title__, panel.__desc__, panel.__icon__) docks[panel.__name__] = (hbox, notebooks[panel.__name__]) if os.path.isfile(dockLocation): try: dock.loadFromXML(dockLocation, docks) except Exception as e: stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("Dock loading error: %s\n%s" % (e, error)) msg_dia = Gtk.MessageDialog(widgets["window1"], type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE) msg_dia.set_markup( _("<b><big>PyChess was unable to load your panel settings</big></b>" )) msg_dia.format_secondary_text( _("Your panel settings have been reset. If this problem repeats, \ you should report it to the developers")) msg_dia.run() msg_dia.hide() os.remove(dockLocation) for title, panel in docks.values(): title.unparent() panel.unparent() if not os.path.isfile(dockLocation): leaf = dock.dock(docks["board"][1], CENTER, Gtk.Label(label=docks["board"][0]), "board") docks["board"][1].show_all() leaf.setDockable(False) # S epanel = leaf.dock(docks["bookPanel"][1], SOUTH, docks["bookPanel"][0], "bookPanel") epanel.default_item_height = 45 epanel = epanel.dock(docks["engineOutputPanel"][1], CENTER, docks["engineOutputPanel"][0], "engineOutputPanel") # NE leaf = leaf.dock(docks["annotationPanel"][1], EAST, docks["annotationPanel"][0], "annotationPanel") leaf = leaf.dock(docks["historyPanel"][1], CENTER, docks["historyPanel"][0], "historyPanel") leaf = leaf.dock(docks["scorePanel"][1], CENTER, docks["scorePanel"][0], "scorePanel") # SE leaf = leaf.dock(docks["chatPanel"][1], SOUTH, docks["chatPanel"][0], "chatPanel") leaf = leaf.dock(docks["commentPanel"][1], CENTER, docks["commentPanel"][0], "commentPanel") def unrealize(dock, notebooks): # unhide the panel before saving so its configuration is saved correctly notebooks["board"].get_parent().get_parent().zoomDown() dock.saveToXML(dockLocation) dock._del() dock.connect("unrealize", unrealize, notebooks) hbox = Gtk.HBox() # Buttons notebooks["buttons"].set_border_width(4) hbox.pack_start(notebooks["buttons"], False, True, 0) # The message area # TODO: If you try to fix this first read issue #958 and 1018 align = createAlignment(0, 0, 0, 0) # sw = Gtk.ScrolledWindow() # port = Gtk.Viewport() # port.add(notebooks["messageArea"]) # sw.add(port) # align.add(sw) align.add(notebooks["messageArea"]) hbox.pack_start(align, True, True, 0) def ma_switch_page(notebook, gpointer, page_num): notebook.props.visible = notebook.get_nth_page(page_num).\ get_child().props.visible notebooks["messageArea"].connect("switch-page", ma_switch_page) centerVBox.pack_start(hbox, False, True, 0) mainvbox.pack_start(centerVBox, True, True, 0) centerVBox.show_all() mainvbox.show() # Connecting headbook to other notebooks def hb_switch_page(notebook, gpointer, page_num): for notebook in notebooks.values(): notebook.set_current_page(page_num) # log.debug("HB_switch ficsgame no. %s , %s " % (key2gmwidg[getheadbook().\ # get_nth_page(page_num)].gamemodel.ficsgame.gameno,str(page_num))) gmwidg = key2gmwidg[getheadbook().get_nth_page(page_num)] if isinstance(gmwidg.gamemodel, ICGameModel): primary = "primary " + str(gmwidg.gamemodel.ficsgame.gameno) gmwidg.gamemodel.connection.client.run_command(primary) headbook.connect("switch-page", hb_switch_page) if hasattr(headbook, "set_tab_reorderable"): def page_reordered(widget, child, new_num, headbook): old_num = notebooks["board"].page_num(key2gmwidg[child].boardvbox) if old_num == -1: log.error('Games and labels are out of sync!') else: for notebook in notebooks.values(): notebook.reorder_child(notebook.get_nth_page(old_num), new_num) headbook.connect("page-reordered", page_reordered, headbook)
def init_layout(self): perspective_widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) perspective_manager.set_perspective_widget("games", perspective_widget) self.notebooks = {"board": cleanNotebook("board"), "buttons": cleanNotebook("buttons"), "messageArea": cleanNotebook("messageArea")} for panel in sidePanels: self.notebooks[panel.__name__] = cleanNotebook(panel.__name__) # Initing headbook align = gamewidget.createAlignment(4, 4, 0, 4) align.set_property("yscale", 0) headbook = Gtk.Notebook() headbook.set_name("headbook") headbook.set_scrollable(True) align.add(headbook) perspective_widget.pack_start(align, False, True, 0) self.show_tabs(not conf.get("hideTabs", False)) # Initing center centerVBox = Gtk.VBox() # The dock self.dock = PyDockTop("main", self) self.dockAlign = gamewidget.createAlignment(4, 4, 0, 4) self.dockAlign.add(self.dock) centerVBox.pack_start(self.dockAlign, True, True, 0) self.dockAlign.show() self.dock.show() self.docks = {"board": (Gtk.Label(label="Board"), self.notebooks["board"])} for panel in sidePanels: box = dock_panel_tab(panel.__title__, panel.__desc__, panel.__icon__) self.docks[panel.__name__] = (box, self.notebooks[panel.__name__]) if os.path.isfile(dockLocation): try: self.dock.loadFromXML(dockLocation, self.docks) except Exception as e: stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("Dock loading error: %s\n%s" % (e, error)) widgets = gamewidget.getWidgets() msg_dia = Gtk.MessageDialog(widgets["main_window"], type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE) msg_dia.set_markup(_( "<b><big>PyChess was unable to load your panel settings</big></b>")) msg_dia.format_secondary_text(_( "Your panel settings have been reset. If this problem repeats, \ you should report it to the developers")) msg_dia.run() msg_dia.hide() os.remove(dockLocation) for title, panel in self.docks.values(): title.unparent() panel.unparent() if not os.path.isfile(dockLocation): leaf = self.dock.dock(self.docks["board"][1], CENTER, Gtk.Label(label=self.docks["board"][0]), "board") self.docks["board"][1].show_all() leaf.setDockable(False) # S epanel = leaf.dock(self.docks["bookPanel"][1], SOUTH, self.docks["bookPanel"][0], "bookPanel") epanel.default_item_height = 45 epanel = epanel.dock(self.docks["engineOutputPanel"][1], CENTER, self.docks["engineOutputPanel"][0], "engineOutputPanel") # NE leaf = leaf.dock(self.docks["annotationPanel"][1], EAST, self.docks["annotationPanel"][0], "annotationPanel") leaf = leaf.dock(self.docks["historyPanel"][1], CENTER, self.docks["historyPanel"][0], "historyPanel") leaf = leaf.dock(self.docks["scorePanel"][1], CENTER, self.docks["scorePanel"][0], "scorePanel") # SE leaf = leaf.dock(self.docks["chatPanel"][1], SOUTH, self.docks["chatPanel"][0], "chatPanel") leaf = leaf.dock(self.docks["commentPanel"][1], CENTER, self.docks["commentPanel"][0], "commentPanel") def unrealize(dock, notebooks): # unhide the panel before saving so its configuration is saved correctly self.notebooks["board"].get_parent().get_parent().zoomDown() dock.saveToXML(dockLocation) dock._del() self.dock.connect("unrealize", unrealize, self.notebooks) hbox = Gtk.HBox() # Buttons self.notebooks["buttons"].set_border_width(4) hbox.pack_start(self.notebooks["buttons"], False, True, 0) # The message area # TODO: If you try to fix this first read issue #958 and 1018 align = gamewidget.createAlignment(0, 0, 0, 0) # sw = Gtk.ScrolledWindow() # port = Gtk.Viewport() # port.add(self.notebooks["messageArea"]) # sw.add(port) # align.add(sw) align.add(self.notebooks["messageArea"]) hbox.pack_start(align, True, True, 0) def ma_switch_page(notebook, gpointer, page_num): notebook.props.visible = notebook.get_nth_page(page_num).\ get_child().props.visible self.notebooks["messageArea"].connect("switch-page", ma_switch_page) centerVBox.pack_start(hbox, False, True, 0) perspective_widget.pack_start(centerVBox, True, True, 0) centerVBox.show_all() perspective_widget.show_all() conf.notify_add("hideTabs", self.tabsCallback) # Connecting headbook to other notebooks def hb_switch_page(notebook, gpointer, page_num): for notebook in self.notebooks.values(): notebook.set_current_page(page_num) gmwidg = self.key2gmwidg[self.getheadbook().get_nth_page(page_num)] if isinstance(gmwidg.gamemodel, ICGameModel): primary = "primary " + str(gmwidg.gamemodel.ficsgame.gameno) gmwidg.gamemodel.connection.client.run_command(primary) headbook.connect("switch-page", hb_switch_page) if hasattr(headbook, "set_tab_reorderable"): def page_reordered(widget, child, new_num, headbook): old_num = self.notebooks["board"].page_num(self.key2gmwidg[child].boardvbox) if old_num == -1: log.error('Games and labels are out of sync!') else: for notebook in self.notebooks.values(): notebook.reorder_child( notebook.get_nth_page(old_num), new_num) headbook.connect("page-reordered", page_reordered, headbook)
def open_lounge(self, connection, helperconn, host): if self.first_run: self.init_layout() self.connection = connection self.helperconn = helperconn self.host = host self.finger_sent = False self.messages = [] self.players = [] self.game_cids = {} self.widgets = uistuff.GladeWidgets("fics_lounge.glade") self.widgets["fics_lounge"].hide() fics_home = self.widgets["fics_home"] self.widgets["fics_lounge_content_hbox"].remove(fics_home) self.archive_list = self.widgets["archiveListContent"] self.widgets["fics_panels_notebook"].remove(self.archive_list) self.games_list = self.widgets["gamesListContent"] self.widgets["fics_panels_notebook"].remove(self.games_list) self.news_list = self.widgets["news"] self.widgets["fics_home"].remove(self.news_list) self.players_list = self.widgets["playersListContent"] self.widgets["fics_panels_notebook"].remove(self.players_list) self.seek_graph = self.widgets["seekGraphContent"] self.widgets["fics_panels_notebook"].remove(self.seek_graph) self.seek_list = self.widgets["seekListContent"] self.widgets["fics_panels_notebook"].remove(self.seek_list) self.seek_challenge = SeekChallengeSection(self) def on_autoLogout(alm): self.emit("autoLogout") self.close() self.connection.alm.connect("logOut", on_autoLogout) self.connection.connect("disconnected", lambda connection: self.close()) self.connection.connect("error", self.on_connection_error) if self.connection.isRegistred(): numtimes = conf.get("numberOfTimesLoggedInAsRegisteredUser", 0) + 1 conf.set("numberOfTimesLoggedInAsRegisteredUser", numtimes) self.connection.em.connect( "onCommandNotFound", lambda em, cmd: log.error( "Fics answered '%s': Command not found" % cmd)) self.connection.bm.connect("playGameCreated", self.onPlayGameCreated) self.connection.bm.connect("obsGameCreated", self.onObserveGameCreated) self.connection.bm.connect("exGameCreated", self.onObserveGameCreated) self.connection.fm.connect("fingeringFinished", self.onFinger) # the rest of these relay server messages to the lounge infobar self.connection.bm.connect("tooManySeeks", self.tooManySeeks) self.connection.bm.connect("nonoWhileExamine", self.nonoWhileExamine) self.connection.bm.connect("matchDeclined", self.matchDeclined) self.connection.bm.connect("player_on_censor", self.player_on_censor) self.connection.bm.connect("player_on_noplay", self.player_on_noplay) self.connection.bm.connect("req_not_fit_formula", self.req_not_fit_formula) self.connection.glm.connect("seek-updated", self.on_seek_updated) self.connection.glm.connect("our-seeks-removed", self.our_seeks_removed) self.connection.cm.connect("arrivalNotification", self.onArrivalNotification) self.connection.cm.connect("departedNotification", self.onDepartedNotification) def get_top_games(): if perspective_manager.current_perspective == self: self.connection.client.run_command("games *19") return True if self.connection.ICC: self.event_id = GLib.timeout_add_seconds(5, get_top_games) for user in self.connection.notify_users: user = self.connection.players.get(user) self.user_from_notify_list_is_present(user) self.userinfo = UserInfoSection(self.widgets, self.connection, self.host, self) if not self.first_run: self.notebooks["ficshome"].remove_page(-1) self.notebooks["ficshome"].append_page(fics_home) self.panels = [ panel.Sidepanel().load(self.widgets, self.connection, self) for panel in self.sidePanels ] for panel, instance in zip(self.sidePanels, self.panels): if not self.first_run: self.notebooks[panel.__name__].remove_page(-1) self.notebooks[panel.__name__].append_page(instance) instance.show() tool_buttons = [ self.logoff_button, ] self.quick_seek_buttons = [] if self.connection.ICC: self.quick_seek_buttons = [ self.minute_1_button, self.minute_3_button, self.minute_5_button, self.minute_15_button, self.minute_25_button, self.chess960_button ] tool_buttons += self.quick_seek_buttons perspective_manager.set_perspective_toolbuttons("fics", tool_buttons) if self.first_run: self.first_run = False # After all panel is set up we can push initial messages out self.connection.com.onConsoleMessage("", self.connection.ini_messages)
def _ensureReadForGameWidgets(): mainvbox = widgets["mainvbox"] if len(mainvbox.get_children()) == 3: return global background background = widgets["mainvbox"].get_children()[1] mainvbox.remove(background) # Initing headbook align = createAlignment(4, 4, 0, 4) align.set_property("yscale", 0) headbook = gtk.Notebook() headbook.set_scrollable(True) headbook.props.tab_vborder = 0 align.add(headbook) mainvbox.pack_start(align, expand=False) show_tabs(not conf.get("hideTabs", False)) # Initing center centerVBox = gtk.VBox() # The message area centerVBox.pack_start(notebooks["messageArea"], expand=False) def callback(notebook, gpointer, page_num): notebook.props.visible = notebook.get_nth_page(page_num).child.props.visible notebooks["messageArea"].connect("switch-page", callback) # The dock global dock, dockAlign dock = PyDockTop("main") dockAlign = createAlignment(4, 4, 0, 4) dockAlign.add(dock) centerVBox.pack_start(dockAlign) dockAlign.show() dock.show() dockLocation = addUserConfigPrefix("pydock.xml") for panel in sidePanels: hbox = gtk.HBox() pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(panel.__icon__, 16, 16) icon = gtk.image_new_from_pixbuf(pixbuf) label = gtk.Label(panel.__title__) label.set_size_request(0, 0) label.set_alignment(0, 1) hbox.pack_start(icon, expand=False, fill=False) hbox.pack_start(label, expand=True, fill=True) hbox.set_spacing(2) hbox.show_all() def cb(widget, x, y, keyboard_mode, tooltip, title, desc, filename): table = gtk.Table(2, 2) table.set_row_spacings(2) table.set_col_spacings(6) table.set_border_width(4) pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filename, 56, 56) image = gtk.image_new_from_pixbuf(pixbuf) image.set_alignment(0, 0) table.attach(image, 0, 1, 0, 2) titleLabel = gtk.Label() titleLabel.set_markup("<b>%s</b>" % title) titleLabel.set_alignment(0, 0) table.attach(titleLabel, 1, 2, 0, 1) descLabel = gtk.Label(desc) descLabel.props.wrap = True table.attach(descLabel, 1, 2, 1, 2) tooltip.set_custom(table) table.show_all() return True hbox.props.has_tooltip = True hbox.connect("query-tooltip", cb, panel.__title__, panel.__desc__, panel.__icon__) docks[panel.__name__] = (hbox, notebooks[panel.__name__]) if os.path.isfile(dockLocation): try: dock.loadFromXML(dockLocation, docks) except Exception, e: stringio = cStringIO.StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("Dock loading error: %s\n%s" % (e, error)) md = gtk.MessageDialog(widgets["window1"], type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_CLOSE) md.set_markup(_("<b><big>PyChess was unable to load your panel settings</big></b>")) md.format_secondary_text( _( "Your panel settings have been reset. If this problem repeats, you should report it to the developers" ) ) md.run() md.hide() os.remove(dockLocation) for title, panel in docks.values(): title.unparent() panel.unparent()
def parseLine(self, proc): while True: line = yield from wait_signal(proc, 'line') if not line: break else: line = line[1] parts = line.split() if not parts: continue # Initializing if parts[0] == "id": if parts[1] == "name": self.ids[parts[1]] = " ".join(parts[2:]) self.setName(self.ids["name"]) continue if parts[0] == "uciok": self.emit("readyForOptions") continue if parts[0] == "readyok": self.emit("readyForMoves") continue # Options parsing if parts[0] == "option": dic = {} last = 1 varlist = [] for i in range(2, len(parts) + 1): if i == len(parts) or parts[i] in OPTKEYS: key = parts[last] value = " ".join(parts[last + 1:i]) if "type" in dic and dic["type"] in TYPEDIC: value = TYPEDIC[dic["type"]](value) if key == "var": varlist.append(value) elif key == "type" and value == "string": dic[key] = "text" else: dic[key] = value last = i if varlist: dic["choices"] = varlist if "name" in dic: self.options[dic["name"]] = dic continue # A Move if self.mode == NORMAL and parts[0] == "bestmove": self.needBestmove = False self.bestmove_event.set() self.__sendQueuedGo() if self.ignoreNext: log.debug( "__parseLine: line='%s' self.ignoreNext==True, returning" % line.strip(), extra={"task": self.defname}) self.ignoreNext = False self.readyForStop = True continue movestr = parts[1] if not self.waitingForMove: log.warning( "__parseLine: self.waitingForMove==False, ignoring move=%s" % movestr, extra={"task": self.defname}) self.pondermove = None continue self.waitingForMove = False try: move = parseAny(self.board, movestr) except ParsingError: self.invalid_move = movestr log.info( "__parseLine: ParsingError engine move: %s %s" % (movestr, self.board), extra={"task": self.defname}) self.end( WHITEWON if self.board.color == BLACK else BLACKWON, WON_ADJUDICATION) continue if not validate(self.board, move): # This is critical. To avoid game stalls, we need to resign on # behalf of the engine. log.error( "__parseLine: move=%s didn't validate, putting 'del' \ in returnQueue. self.board=%s" % (repr(move), self.board), extra={"task": self.defname}) self.invalid_move = movestr self.end( WHITEWON if self.board.color == BLACK else BLACKWON, WON_ADJUDICATION) continue self._recordMove(self.board.move(move), move, self.board) log.debug("__parseLine: applied move=%s to self.board=%s" % (move, self.board), extra={"task": self.defname}) if self.ponderOn: self.pondermove = None # An engine may send an empty ponder line, simply to clear. if len(parts) == 4: # Engines don't always check for everything in their # ponders. Hence we need to validate. # But in some cases, what they send may not even be # correct AN - specially in the case of promotion. try: pondermove = parseAny(self.board, parts[3]) except ParsingError: pass else: if validate(self.board, pondermove): self.pondermove = pondermove self._startPonder() self.queue.put_nowait(move) log.debug("__parseLine: put move=%s into self.queue=%s" % (move, self.queue), extra={"task": self.defname}) continue # An Analysis if self.mode != NORMAL and parts[0] == "info" and "pv" in parts: multipv = 1 if "multipv" in parts: multipv = int(parts[parts.index("multipv") + 1]) scoretype = parts[parts.index("score") + 1] if scoretype in ('lowerbound', 'upperbound'): score = None else: score = int(parts[parts.index("score") + 2]) if scoretype == 'mate': # print >> self.engine, "stop" if score != 0: sign = score / abs(score) score = sign * (MATE_VALUE - abs(score)) movstrs = parts[parts.index("pv") + 1:] if "depth" in parts: depth = parts[parts.index("depth") + 1] else: depth = "" if "nps" in parts: nps = parts[parts.index("nps") + 1] else: nps = "" if multipv <= len(self.analysis): self.analysis[multipv - 1] = (self.board.ply, movstrs, score, depth, nps) self.emit("analyze", self.analysis) continue # An Analyzer bestmove if self.mode != NORMAL and parts[0] == "bestmove": log.debug( "__parseLine: processing analyzer bestmove='%s'" % line.strip(), extra={"task": self.defname}) self.needBestmove = False self.bestmove_event.set() if parts[1] == "(none)": self.emit("analyze", []) else: self.__sendQueuedGo(sendlast=True) continue # Stockfish complaining it received a 'stop' without a corresponding 'position..go' if line.strip() == "Unknown command: stop": log.debug("__parseLine: processing '%s'" % line.strip(), extra={"task": self.defname}) self.ignoreNext = False self.needBestmove = False self.readyForStop = False self.__sendQueuedGo() continue
def init_layout(self): perspective_widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) perspective_manager.set_perspective_widget("database", perspective_widget) self.switcher_panel = SwitcherPanel(self) self.notebooks["gamelist"] = new_notebook() self.notebooks["opening_tree"] = new_notebook() self.notebooks["filter"] = new_notebook() self.notebooks["preview"] = new_notebook() self.spinner = Gtk.Spinner() self.spinner.set_size_request(50, 50) self.progressbar0 = Gtk.ProgressBar(show_text=True) self.progressbar1 = Gtk.ProgressBar(show_text=True) mainwindow = gamewidget.getWidgets()["main_window"] self.progress_dialog = Gtk.Dialog("", mainwindow, 0, ( Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)) self.progress_dialog.get_content_area().pack_start(self.spinner, True, True, 0) self.progress_dialog.get_content_area().pack_start(self.progressbar0, True, True, 0) self.progress_dialog.get_content_area().pack_start(self.progressbar1, True, True, 0) self.progress_dialog.get_content_area().show_all() self.dock = PyDockTop("database", self) align = Gtk.Alignment() align.show() align.add(self.dock) self.dock.show() perspective_widget.pack_start(align, True, True, 0) dockLocation = addUserConfigPrefix("pydock-database.xml") docks = { "gamelist": (Gtk.Label(label="gamelist"), self.notebooks["gamelist"]), "switcher": (dock_panel_tab(_("Databases"), "", addDataPrefix("glade/panel_database.svg")), self.switcher_panel.alignment), "openingtree": (dock_panel_tab(_("Openings"), "", addDataPrefix("glade/panel_book.svg")), self.notebooks["opening_tree"]), "filter": (dock_panel_tab(_("Filters"), "", addDataPrefix("glade/panel_filter.svg")), self.notebooks["filter"]), "preview": (dock_panel_tab(_("Preview"), "", addDataPrefix("glade/panel_games.svg")), self.notebooks["preview"]), } if os.path.isfile(dockLocation): try: self.dock.loadFromXML(dockLocation, docks) except Exception as e: stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("Dock loading error: %s\n%s" % (e, error)) msg_dia = Gtk.MessageDialog(None, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE) msg_dia.set_markup(_( "<b><big>PyChess was unable to load your panel settings</big></b>")) msg_dia.format_secondary_text(_( "Your panel settings have been reset. If this problem repeats, \ you should report it to the developers")) msg_dia.run() msg_dia.hide() os.remove(dockLocation) for title, panel in docks.values(): title.unparent() panel.unparent() if not os.path.isfile(dockLocation): leaf = self.dock.dock(docks["gamelist"][1], CENTER, docks["gamelist"][0], "gamelist") leaf.setDockable(False) leaf.dock(docks["switcher"][1], NORTH, docks["switcher"][0], "switcher") leaf = leaf.dock(docks["openingtree"][1], EAST, docks["openingtree"][0], "openingtree") leaf = leaf.dock(docks["filter"][1], CENTER, docks["filter"][0], "filter") leaf.dock(docks["preview"][1], SOUTH, docks["preview"][0], "preview") def unrealize(dock): dock.saveToXML(dockLocation) dock._del() self.dock.connect("unrealize", unrealize) self.dock.show_all() perspective_widget.show_all() perspective_manager.set_perspective_toolbuttons("database", [self.import_button, self.close_button]) self.switcher_panel.connect("chessfile_switched", self.on_chessfile_switched)
def run(self): log.debug("GameModel.run: Starting. self=%s" % self) # Avoid racecondition when self.start is called while we are in # self.end if self.status != WAITING_TO_START: return if not self.isLocalGame(): self.timemodel.handle_gain = False self.status = RUNNING for player in self.players + list(self.spectators.values()): player.start() log.debug("GameModel.run: emitting 'game_started' self=%s" % self) self.emit("game_started") # Let GameModel end() itself on games started with loadAndStart() self.checkStatus() self.curColor = self.boards[-1].color while self.status in (PAUSED, RUNNING, DRAW, WHITEWON, BLACKWON): curPlayer = self.players[self.curColor] if self.timed: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: updating %s's time" % ( id(self), str(self.players), str(self.ply), str(curPlayer))) curPlayer.updateTime( self.timemodel.getPlayerTime(self.curColor), self.timemodel.getPlayerTime(1 - self.curColor)) try: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: calling %s.makeMove()" % ( id(self), str(self.players), self.ply, str(curPlayer))) if self.ply > self.lowply: move = curPlayer.makeMove(self.boards[-1], self.moves[-1], self.boards[-2]) else: move = curPlayer.makeMove(self.boards[-1], None, None) log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: got move=%s from %s" % ( id(self), str(self.players), self.ply, move, str(curPlayer))) except PlayerIsDead as e: if self.status in (WAITING_TO_START, PAUSED, RUNNING): stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error( "GameModel.run: A Player died: player=%s error=%s\n%s" % (curPlayer, error, e)) if self.curColor == WHITE: self.kill(WHITE_ENGINE_DIED) else: self.kill(BLACK_ENGINE_DIED) break except InvalidMove as e: if self.curColor == WHITE: self.end(BLACKWON, WON_ADJUDICATION) else: self.end(WHITEWON, WON_ADJUDICATION) break except TurnInterrupt: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: TurnInterrupt" % ( id(self), str(self.players), self.ply)) self.curColor = self.boards[-1].color continue log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: acquiring self.applyingMoveLock" % ( id(self), str(self.players), self.ply)) assert isinstance(move, Move), "%s" % repr(move) self.applyingMoveLock.acquire() try: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: applying move=%s" % ( id(self), str(self.players), self.ply, str(move))) self.needsSave = True newBoard = self.boards[-1].move(move) newBoard.board.prev = self.boards[-1].board # Variation on next move can exist from the hint panel... if self.boards[-1].board.next is not None: newBoard.board.children = self.boards[ -1].board.next.children self.boards = self.variations[0] self.boards[-1].board.next = newBoard.board self.boards.append(newBoard) self.moves.append(move) if self.timed: self.timemodel.tap() if not self.terminated: self.emit("game_changed", self.ply) for spectator in self.spectators.values(): if spectator.board == self.boards[-2]: spectator.putMove(self.boards[-1], self.moves[-1], self.boards[-2]) self.setOpening() self.checkStatus() self.curColor = 1 - self.curColor finally: log.debug("GameModel.run: releasing self.applyingMoveLock") self.applyingMoveLock.release()
def parseGame (self, matchlist, gameclass, in_progress=False, gameno=None): """ Parses the header and movelist for an observed or stored game from its matchlist (an re.match object) into a gameclass (FICSGame or subclass of) object. in_progress - should be True for an observed game matchlist, and False for stored/adjourned games """ ################# observed game movelist example: # Movelist for game 64: # # Ajido (2281) vs. IMgooeyjim (2068) --- Thu Oct 14, 20:36 PDT 2010 # Rated standard match, initial time: 15 minutes, increment: 3 seconds. # # Move Ajido IMgooeyjim # ---- --------------------- --------------------- # 1. d4 (0:00.000) Nf6 (0:00.000) # 2. c4 (0:04.061) g6 (0:00.969) # 3. Nc3 (0:13.280) Bg7 (0:06.422) # {Still in progress} * # ################## stored game example: # BwanaSlei (1137) vs. mgatto (1336) --- Wed Nov 5, 20:56 PST 2008 # Rated blitz match, initial time: 5 minutes, increment: 0 seconds. # # Move BwanaSlei mgatto # ---- --------------------- --------------------- # 1. e4 (0:00.000) c5 (0:00.000) # 2. d4 (0:05.750) cxd4 (0:03.020) # ... # 23. Qxf3 (1:05.500) # {White lost connection; game adjourned} * # ################## stored wild/3 game with style12: # kurushi (1626) vs. mgatto (1627) --- Thu Nov 4, 10:33 PDT 2010 # Rated wild/3 match, initial time: 3 minutes, increment: 0 seconds. # # <12> nqbrknrn pppppppp -------- -------- -------- -------- PPPPPPPP NQBRKNRN W -1 0 0 0 0 0 17 kurushi mgatto -4 3 0 39 39 169403 45227 1 none (0:00.000) none 0 1 0 # # Move kurushi mgatto # ---- --------------------- --------------------- # 1. Nb3 (0:00.000) d5 (0:00.000) # 2. Nhg3 (0:00.386) e5 (0:03.672) # ... # 28. Rxd5 (0:00.412) # {Black lost connection; game adjourned} * # ################## stored game movelist following stored game(s): # Stored games for mgatto: # C Opponent On Type Str M ECO Date # 1: W BabyLurking Y [ br 5 0] 29-13 W27 D37 Fri Nov 5, 04:41 PDT 2010 # 2: W gbtami N [ wr 5 0] 32-34 W14 --- Thu Oct 21, 00:14 PDT 2010 # # mgatto (1233) vs. BabyLurking (1455) --- Fri Nov 5, 04:33 PDT 2010 # Rated blitz match, initial time: 5 minutes, increment: 0 seconds. # # Move mgatto BabyLurking # ---- ---------------- ---------------- # 1. Nf3 (0:00) d5 (0:00) # 2. d4 (0:03) Nf6 (0:00) # 3. c4 (0:03) e6 (0:00) # {White lost connection; game adjourned} * # ################### stored game movelist following stored game(s): ### Note: A wild stored game in this format won't be parseable into a board because ### it doesn't come with a style12 that has the start position, so we warn and return ################### # Stored games for mgatto: # C Opponent On Type Str M ECO Date # 1: W gbtami N [ wr 5 0] 32-34 W14 --- Thu Oct 21, 00:14 PDT 2010 # # mgatto (1627) vs. gbtami (1881) --- Thu Oct 21, 00:10 PDT 2010 # Rated wild/fr match, initial time: 5 minutes, increment: 0 seconds. # # Move mgatto gbtami # ---- ---------------- ---------------- # 1. d4 (0:00) b6 (0:00) # 2. b3 (0:06) d5 (0:03) # 3. c4 (0:08) e6 (0:03) # 4. e3 (0:04) dxc4 (0:02) # 5. bxc4 (0:02) g6 (0:09) # 6. Nd3 (0:12) Bg7 (0:02) # 7. Nc3 (0:10) Ne7 (0:03) # 8. Be2 (0:08) c5 (0:05) # 9. a4 (0:07) cxd4 (0:38) # 10. exd4 (0:06) Bxd4 (0:03) # 11. O-O (0:10) Qc6 (0:06) # 12. Bf3 (0:16) Qxc4 (0:04) # 13. Bxa8 (0:03) Rxa8 (0:14) # {White lost connection; game adjourned} * # ################## other reasons the game could be stored/adjourned: # Game courtesyadjourned by (Black|White) # Still in progress # This one must be a FICS bug # Game adjourned by mutual agreement # (White|Black) lost connection; game adjourned # Game adjourned by ((server shutdown)|(adjudication)|(simul holder)) index = 0 if in_progress: gameno = int(matchlist[index].groups()[0]) index += 2 header1 = matchlist[index] if isinstance(matchlist[index], str) \ else matchlist[index].group() matches = moveListHeader1.match(header1).groups() wname, wrating, bname, brating = matches[:4] if self.connection.FatICS: year, month, day, hour, minute, timezone = matches[11:] else: weekday, month, day, hour, minute, timezone, year = matches[4:11] month = months.index(month)+1 wrating = self.parseRating(wrating) brating = self.parseRating(brating) rated, game_type, minutes, increment = \ moveListHeader2.match(matchlist[index+1]).groups() minutes = int(minutes) increment = int(increment) game_type = GAME_TYPES[game_type] reason = matchlist[-1].group().lower() if in_progress: result = None result_str = "*" elif "1-0" in reason: result = WHITEWON result_str = "1-0" elif "0-1" in reason: result = BLACKWON result_str = "0-1" elif "1/2-1/2" in reason: result = DRAW result_str = "1/2-1/2" else: result = ADJOURNED result_str = "*" result, reason = parse_reason(result, reason, wname=wname) index += 3 if matchlist[index].startswith("<12>"): style12 = matchlist[index][5:] castleSigns = self.generateCastleSigns(style12, game_type) gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, \ fen = self.parseStyle12(style12, castleSigns) initialfen = fen movesstart = index + 4 else: if game_type.rating_type == TYPE_WILD: # we need a style12 start position to correctly parse a wild/* board log.error("BoardManager.parseGame: no style12 for %s board." % game_type.fics_name) return None castleSigns = ("k", "q") initialfen = None movesstart = index + 2 if in_progress: self.castleSigns[gameno] = castleSigns moves = {} times = {} wms = bms = minutes * 60 * 1000 for line in matchlist[movesstart:-1]: if not moveListMoves.match(line): log.error("BoardManager.parseGame: unmatched line: \"%s\"" % \ repr(line)) raise Exception("BoardManager.parseGame: unmatched line: \"%s\"" % \ repr(line)) moveno, wmove, whour, wmin, wsec, wmsec, bmove, bhour, bmin, bsec, bmsec = \ moveListMoves.match(line).groups() whour = 0 if whour is None else int(whour[0]) bhour = 0 if bhour is None else int(bhour[0]) ply = int(moveno)*2-2 if wmove: moves[ply] = wmove wms -= (int(whour) * 60 * 60 * 1000) + (int(wmin) * 60 * 1000) + (int(wsec) * 1000) if wmsec is not None: wms -= int(wmsec) else: wmsec = 0 if int(moveno) > 1 and increment > 0: wms += (increment * 1000) times[ply] = "%01d:%02d:%02d.%03d" % (int(whour), int(wmin), int(wsec), int(wmsec)) if bmove: moves[ply+1] = bmove bms -= (int(bhour) * 60 * 60 * 1000) + (int(bmin) * 60 * 1000) + (int(bsec) * 1000) if bmsec is not None: bms -= int(bmsec) else: bmsec = 0 if int(moveno) > 1 and increment > 0: bms += (increment * 1000) times[ply+1] = "%01d:%02d:%02d.%03d" % (int(bhour), int(bmin), int(bsec), int(bmsec)) if in_progress and gameno in self.queuedStyle12s: # Apply queued board updates for style12 in self.queuedStyle12s[gameno]: gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, fen = \ self.parseStyle12(style12, castleSigns) if lastmove == None: continue moves[ply-1] = lastmove # Updated the queuedMoves in case there has been a takeback for moveply in list(moves.keys()): if moveply > ply-1: del moves[moveply] del self.queuedStyle12s[gameno] pgnHead = [ ("Event", "FICS %s %s game" % (rated.lower(), game_type.fics_name)), ("Site", "freechess.org"), ("White", wname), ("Black", bname), ("TimeControl", "%d+%d" % (minutes * 60, increment)), ("Result", result_str), ("WhiteClock", msToClockTimeTag(wms)), ("BlackClock", msToClockTimeTag(bms)), ] if wrating != 0: pgnHead += [ ("WhiteElo", wrating) ] if brating != 0: pgnHead += [ ("BlackElo", brating) ] if year and month and day and hour and minute: pgnHead += [ ("Date", "%04d.%02d.%02d" % (int(year), int(month), int(day))), ("Time", "%02d:%02d:00" % (int(hour), int(minute))), ] if initialfen: pgnHead += [ ("SetUp", "1"), ("FEN", initialfen) ] if game_type.variant_type == FISCHERRANDOMCHESS: pgnHead += [ ("Variant", "Fischerandom") ] # FR is the only variant used in this tag by the PGN generator @ # ficsgames.org. They put all the other wild/* stuff only in the # "Event" header. elif game_type.variant_type == CRAZYHOUSECHESS: pgnHead += [ ("Variant", "Crazyhouse") ] elif game_type.variant_type in (WILDCASTLECHESS, WILDCASTLESHUFFLECHESS): pgnHead += [ ("Variant", "Wildcastle") ] elif game_type.variant_type == ATOMICCHESS: pgnHead += [ ("Variant", "Atomic") ] elif game_type.variant_type == LOSERSCHESS: pgnHead += [ ("Variant", "Losers") ] elif game_type.variant_type == SUICIDECHESS: pgnHead += [ ("Variant", "Suicide") ] pgn = "\n".join(['[%s "%s"]' % line for line in pgnHead]) + "\n" moves = sorted(moves.items()) for ply, move in moves: if ply % 2 == 0: pgn += "%d. " % (ply//2+1) time = times[ply] pgn += "%s {[%%emt %s]} " % (move, time) pgn += "*\n" wplayer = self.connection.players.get(FICSPlayer(wname)) bplayer = self.connection.players.get(FICSPlayer(bname)) for player, rating in ((wplayer, wrating), (bplayer, brating)): if game_type.rating_type in player.ratings and \ player.ratings[game_type.rating_type].elo != rating: player.ratings[game_type.rating_type].elo = rating player.keep_after_logout = True game = gameclass(wplayer, bplayer, game_type=game_type, result=result, rated=(rated.lower() == "rated"), minutes=minutes, inc=increment, board=FICSBoard(wms, bms, pgn=pgn)) if in_progress: game.gameno = gameno else: if gameno is not None: game.gameno = gameno game.reason = reason game = self.connection.games.get(game, emit=False) return game
def open_lounge(self, connection, helperconn, host): if self.first_run: self.init_layout() self.connection = connection self.helperconn = helperconn self.host = host self.finger_sent = False self.messages = [] self.players = [] self.game_cids = {} self.widgets = uistuff.GladeWidgets("fics_lounge.glade") self.widgets["fics_lounge"].hide() fics_home = self.widgets["fics_home"] self.widgets["fics_lounge_content_hbox"].remove(fics_home) self.archive_list = self.widgets["archiveListContent"] self.widgets["fics_panels_notebook"].remove(self.archive_list) self.games_list = self.widgets["gamesListContent"] self.widgets["fics_panels_notebook"].remove(self.games_list) self.news_list = self.widgets["news"] self.widgets["fics_home"].remove(self.news_list) self.players_list = self.widgets["playersListContent"] self.widgets["fics_panels_notebook"].remove(self.players_list) self.seek_graph = self.widgets["seekGraphContent"] self.widgets["fics_panels_notebook"].remove(self.seek_graph) self.seek_list = self.widgets["seekListContent"] self.widgets["fics_panels_notebook"].remove(self.seek_list) self.seek_challenge = SeekChallengeSection(self) def on_autoLogout(alm): self.emit("autoLogout") self.close() self.connection.alm.connect("logOut", on_autoLogout) self.connection.connect("disconnected", lambda connection: self.close()) self.connection.connect("error", self.on_connection_error) if self.connection.isRegistred(): numtimes = conf.get("numberOfTimesLoggedInAsRegisteredUser") + 1 conf.set("numberOfTimesLoggedInAsRegisteredUser", numtimes) self.connection.em.connect("onCommandNotFound", lambda em, cmd: log.error( "Fics answered '%s': Command not found" % cmd)) self.connection.bm.connect("playGameCreated", self.onPlayGameCreated) self.connection.bm.connect("obsGameCreated", self.onObserveGameCreated) self.connection.bm.connect("exGameCreated", self.onObserveGameCreated) self.connection.fm.connect("fingeringFinished", self.onFinger) # the rest of these relay server messages to the lounge infobar self.connection.bm.connect("tooManySeeks", self.tooManySeeks) self.connection.bm.connect("nonoWhileExamine", self.nonoWhileExamine) self.connection.bm.connect("matchDeclined", self.matchDeclined) self.connection.bm.connect("player_on_censor", self.player_on_censor) self.connection.bm.connect("player_on_noplay", self.player_on_noplay) self.connection.bm.connect("req_not_fit_formula", self.req_not_fit_formula) self.connection.glm.connect("seek-updated", self.on_seek_updated) self.connection.glm.connect("our-seeks-removed", self.our_seeks_removed) self.connection.cm.connect("arrivalNotification", self.onArrivalNotification) self.connection.cm.connect("departedNotification", self.onDepartedNotification) def get_top_games(): if perspective_manager.current_perspective == self: self.connection.client.run_command("games *19") return True if self.connection.ICC: self.event_id = GLib.timeout_add_seconds(5, get_top_games) for user in self.connection.notify_users: user = self.connection.players.get(user) self.user_from_notify_list_is_present(user) self.userinfo = UserInfoSection(self.widgets, self.connection, self.host, self) if not self.first_run: self.notebooks["ficshome"].remove_page(-1) self.notebooks["ficshome"].append_page(fics_home) self.panels = [panel.Sidepanel().load(self.widgets, self.connection, self) for panel in self.sidePanels] for panel, instance in zip(self.sidePanels, self.panels): if not self.first_run: self.notebooks[panel_name(panel.__name__)].remove_page(-1) self.notebooks[panel_name(panel.__name__)].append_page(instance) instance.show() tool_buttons = [self.logoff_button, ] self.quick_seek_buttons = [] if self.connection.ICC: self.quick_seek_buttons = [self.minute_1_button, self.minute_3_button, self.minute_5_button, self.minute_15_button, self.minute_25_button, self.chess960_button] tool_buttons += self.quick_seek_buttons perspective_manager.set_perspective_toolbuttons("fics", tool_buttons) if self.first_run: self.first_run = False # After all panel is set up we can push initial messages out self.connection.com.onConsoleMessage("", self.connection.ini_messages)
def coro(): persp = perspective_manager.get_perspective("games") gmwidg = persp.cur_gmwidg() gamemodel = gmwidg.gamemodel old_check_value = conf.get("analyzer_check") conf.set("analyzer_check", True) if HINT not in gamemodel.spectators: try: yield from asyncio.wait_for( gamemodel.start_analyzer(HINT), 5.0) except asyncio.TimeoutError: log.error( "Got timeout error while starting hint analyzer") return except Exception: log.error("Unknown error while starting hint analyzer") return self.analyzer = gamemodel.spectators[HINT] gmwidg.menuitems["hint_mode"].active = True self.threat_PV = conf.get("ThreatPV") if self.threat_PV: old_inv_check_value = conf.get("inv_analyzer_check") conf.set("inv_analyzer_check", True) if SPY not in gamemodel.spectators: try: yield from asyncio.wait_for( gamemodel.start_analyzer(SPY), 5.0) except asyncio.TimeoutError: log.error( "Got timeout error while starting spy analyzer" ) return except Exception: log.error( "Unknown error while starting spy analyzer") return inv_analyzer = gamemodel.spectators[SPY] gmwidg.menuitems["spy_mode"].active = True title = _("Game analyzing in progress...") text = _("Do you want to abort it?") content = InfoBar.get_message_content( title, text, Gtk.STOCK_DIALOG_QUESTION) def response_cb(infobar, response, message): conf.set("analyzer_check", old_check_value) if self.threat_PV: conf.set("inv_analyzer_check", old_inv_check_value) message.dismiss() abort() message = InfoBarMessage(Gtk.MessageType.QUESTION, content, response_cb) message.add_button( InfoBarMessageButton(_("Abort"), Gtk.ResponseType.CANCEL)) gmwidg.replaceMessages(message) @asyncio.coroutine def analyse_moves(): should_black = conf.get("shouldBlack") should_white = conf.get("shouldWhite") from_current = conf.get("fromCurrent") start_ply = gmwidg.board.view.shown if from_current else 0 move_time = int(conf.get("max_analysis_spin")) threshold = int(conf.get("variation_threshold_spin")) for board in gamemodel.boards[start_ply:]: if self.stop_event.is_set(): break gmwidg.board.view.setShownBoard(board) self.analyzer.setBoard(board) if self.threat_PV: inv_analyzer.setBoard(board) yield from asyncio.sleep(move_time + 0.1) ply = board.ply - gamemodel.lowply color = (ply - 1) % 2 if ply - 1 in gamemodel.scores and ply in gamemodel.scores and ( (color == BLACK and should_black) or (color == WHITE and should_white)): oldmoves, oldscore, olddepth = gamemodel.scores[ply - 1] oldscore = oldscore * -1 if color == BLACK else oldscore score_str = prettyPrintScore(oldscore, olddepth) moves, score, depth = gamemodel.scores[ply] score = score * -1 if color == WHITE else score diff = score - oldscore if ((diff > threshold and color == BLACK) or (diff < -1 * threshold and color == WHITE) ) and (gamemodel.moves[ply - 1] != parseAny( gamemodel.boards[ply - 1], oldmoves[0])): if self.threat_PV: try: if ply - 1 in gamemodel.spy_scores: oldmoves0, oldscore0, olddepth0 = gamemodel.spy_scores[ ply - 1] score_str0 = prettyPrintScore( oldscore0, olddepth0) pv0 = listToMoves( gamemodel.boards[ply - 1], ["--"] + oldmoves0, validate=True) if len(pv0) > 2: gamemodel.add_variation( gamemodel.boards[ply - 1], pv0, comment="Threatening", score=score_str0, emit=False) except ParsingError as e: # ParsingErrors may happen when parsing "old" lines from # analyzing engines, which haven't yet noticed their new tasks log.debug( "__parseLine: Ignored (%s) from analyzer: ParsingError%s" % (' '.join(oldmoves), e)) try: pv = listToMoves(gamemodel.boards[ply - 1], oldmoves, validate=True) gamemodel.add_variation( gamemodel.boards[ply - 1], pv, comment="Better is", score=score_str, emit=False) except ParsingError as e: # ParsingErrors may happen when parsing "old" lines from # analyzing engines, which haven't yet noticed their new tasks log.debug( "__parseLine: Ignored (%s) from analyzer: ParsingError%s" % (' '.join(oldmoves), e)) self.widgets["analyze_game"].hide() self.widgets["analyze_ok_button"].set_sensitive(True) conf.set("analyzer_check", old_check_value) if self.threat_PV: conf.set("inv_analyzer_check", old_inv_check_value) message.dismiss() gamemodel.emit("analysis_finished") create_task(analyse_moves()) hide_window(None) return True
def _ensureReadForGameWidgets(): if len(key2gmwidg) > 0: return global notebooks perspective_widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) perspective_manager.set_perspective_widget("games", perspective_widget) perspective = perspective_manager.get_perspective("games") notebooks = get_clean_notebooks(perspective.widget) # Initing headbook align = createAlignment(4, 4, 0, 4) align.set_property("yscale", 0) headbook = Gtk.Notebook() headbook.set_name("headbook") headbook.set_scrollable(True) align.add(headbook) perspective_widget.pack_start(align, False, True, 0) show_tabs(not conf.get("hideTabs", False)) # Initing center centerVBox = Gtk.VBox() # The dock global dock, dockAlign dock = PyDockTop("main", perspective) dockAlign = createAlignment(4, 4, 0, 4) dockAlign.add(dock) centerVBox.pack_start(dockAlign, True, True, 0) dockAlign.show() dock.show() for panel in sidePanels: box = dock_panel_tab(panel.__title__, panel.__desc__, panel.__icon__) docks[panel.__name__] = (box, notebooks[panel.__name__]) if os.path.isfile(dockLocation): try: dock.loadFromXML(dockLocation, docks) except Exception as e: stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("Dock loading error: %s\n%s" % (e, error)) msg_dia = Gtk.MessageDialog(widgets["main_window"], type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE) msg_dia.set_markup( _("<b><big>PyChess was unable to load your panel settings</big></b>" )) msg_dia.format_secondary_text( _("Your panel settings have been reset. If this problem repeats, \ you should report it to the developers")) msg_dia.run() msg_dia.hide() os.remove(dockLocation) for title, panel in docks.values(): title.unparent() panel.unparent() if not os.path.isfile(dockLocation): leaf = dock.dock(docks["board"][1], CENTER, Gtk.Label(label=docks["board"][0]), "board") docks["board"][1].show_all() leaf.setDockable(False) # S epanel = leaf.dock(docks["bookPanel"][1], SOUTH, docks["bookPanel"][0], "bookPanel") epanel.default_item_height = 45 epanel = epanel.dock(docks["engineOutputPanel"][1], CENTER, docks["engineOutputPanel"][0], "engineOutputPanel") # NE leaf = leaf.dock(docks["annotationPanel"][1], EAST, docks["annotationPanel"][0], "annotationPanel") leaf = leaf.dock(docks["historyPanel"][1], CENTER, docks["historyPanel"][0], "historyPanel") leaf = leaf.dock(docks["scorePanel"][1], CENTER, docks["scorePanel"][0], "scorePanel") # SE leaf = leaf.dock(docks["chatPanel"][1], SOUTH, docks["chatPanel"][0], "chatPanel") leaf = leaf.dock(docks["commentPanel"][1], CENTER, docks["commentPanel"][0], "commentPanel") def unrealize(dock, notebooks): # unhide the panel before saving so its configuration is saved correctly notebooks["board"].get_parent().get_parent().zoomDown() dock.saveToXML(dockLocation) dock._del() dock.connect("unrealize", unrealize, notebooks) hbox = Gtk.HBox() # Buttons notebooks["buttons"].set_border_width(4) hbox.pack_start(notebooks["buttons"], False, True, 0) # The message area # TODO: If you try to fix this first read issue #958 and 1018 align = createAlignment(0, 0, 0, 0) # sw = Gtk.ScrolledWindow() # port = Gtk.Viewport() # port.add(notebooks["messageArea"]) # sw.add(port) # align.add(sw) align.add(notebooks["messageArea"]) hbox.pack_start(align, True, True, 0) def ma_switch_page(notebook, gpointer, page_num): notebook.props.visible = notebook.get_nth_page(page_num).\ get_child().props.visible notebooks["messageArea"].connect("switch-page", ma_switch_page) centerVBox.pack_start(hbox, False, True, 0) perspective_widget.pack_start(centerVBox, True, True, 0) centerVBox.show_all() perspective_widget.show_all() # Connecting headbook to other notebooks def hb_switch_page(notebook, gpointer, page_num): for notebook in notebooks.values(): notebook.set_current_page(page_num) gmwidg = key2gmwidg[getheadbook().get_nth_page(page_num)] if isinstance(gmwidg.gamemodel, ICGameModel): primary = "primary " + str(gmwidg.gamemodel.ficsgame.gameno) gmwidg.gamemodel.connection.client.run_command(primary) headbook.connect("switch-page", hb_switch_page) if hasattr(headbook, "set_tab_reorderable"): def page_reordered(widget, child, new_num, headbook): old_num = notebooks["board"].page_num(key2gmwidg[child].boardvbox) if old_num == -1: log.error('Games and labels are out of sync!') else: for notebook in notebooks.values(): notebook.reorder_child(notebook.get_nth_page(old_num), new_num) headbook.connect("page-reordered", page_reordered, headbook)
def coro(): log.debug("GameModel.run: Starting. self=%s" % self) # Avoid racecondition when self.start is called while we are in # self.end if self.status != WAITING_TO_START: return if not self.isLocalGame(): self.timemodel.handle_gain = False self.status = RUNNING for player in self.players + list(self.spectators.values()): event = asyncio.Event() is_dead = set() player.start(event, is_dead) yield from event.wait() if is_dead: if player in self.players[WHITE]: self.kill(WHITE_ENGINE_DIED) break elif player in self.players[BLACK]: self.kill(BLACK_ENGINE_DIED) break log.debug("GameModel.run: emitting 'game_started' self=%s" % self) self.emit("game_started") # Let GameModel end() itself on games started with loadAndStart() if not self.lesson_game: self.checkStatus() if self.isEngine2EngineGame() and self.timed: self.timemodel.start() self.timemodel.started = True self.curColor = self.boards[-1].color book_depth_max = conf.get("book_depth_max") while self.status in (PAUSED, RUNNING, DRAW, WHITEWON, BLACKWON): curPlayer = self.players[self.curColor] if self.timed: log.debug( "GameModel.run: id=%s, players=%s, self.ply=%s: updating %s's time" % (id(self), str(self.players), str( self.ply), str(curPlayer))) curPlayer.updateTime( self.timemodel.getPlayerTime(self.curColor), self.timemodel.getPlayerTime(1 - self.curColor)) try: log.debug( "GameModel.run: id=%s, players=%s, self.ply=%s: calling %s.makeMove()" % (id(self), str( self.players), self.ply, str(curPlayer))) move = None # if the current player is a bot if curPlayer.__type__ == ARTIFICIAL and book_depth_max > 0 and self.ply <= book_depth_max: move = self.get_book_move() log.debug( "GameModel.run: id=%s, players=%s, self.ply=%s: got move=%s from book" % (id(self), str(self.players), self.ply, move)) if move is not None: curPlayer.set_board(self.boards[-1].move(move)) # if the current player is not a bot if move is None: if self.ply > self.lowply: move = yield from curPlayer.makeMove( self.boards[-1], self.moves[-1], self.boards[-2]) else: move = yield from curPlayer.makeMove( self.boards[-1], None, None) log.debug( "GameModel.run: id=%s, players=%s, self.ply=%s: got move=%s from %s" % (id(self), str( self.players), self.ply, move, str(curPlayer))) except PlayerIsDead as e: if self.status in (WAITING_TO_START, PAUSED, RUNNING): stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error( "GameModel.run: A Player died: player=%s error=%s\n%s" % (curPlayer, error, e)) if self.curColor == WHITE: self.kill(WHITE_ENGINE_DIED) else: self.kill(BLACK_ENGINE_DIED) break except InvalidMove as e: stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error( "GameModel.run: InvalidMove by player=%s error=%s\n%s" % (curPlayer, error, e)) if self.curColor == WHITE: self.end(BLACKWON, WON_ADJUDICATION) else: self.end(WHITEWON, WON_ADJUDICATION) break except PassInterrupt: log.debug( "GameModel.run: id=%s, players=%s, self.ply=%s: PassInterrupt" % (id(self), str(self.players), self.ply)) continue except TurnInterrupt: log.debug( "GameModel.run: id=%s, players=%s, self.ply=%s: TurnInterrupt" % (id(self), str(self.players), self.ply)) self.curColor = self.boards[-1].color continue except GameEnded: log.debug("GameModel.run: got GameEnded exception") break assert isinstance(move, Move), "%s" % repr(move) log.debug( "GameModel.run: id=%s, players=%s, self.ply=%s: applying move=%s" % (id(self), str(self.players), self.ply, str(move))) self.needsSave = True newBoard = self.boards[-1].move(move) newBoard.board.prev = self.boards[-1].board # newBoard.printPieces() # Variation on next move can exist from the hint panel... if self.boards[-1].board.next is not None: newBoard.board.children = self.boards[ -1].board.next.children self.boards = self.variations[0] self.boards[-1].board.next = newBoard.board self.boards.append(newBoard) self.moves.append(move) if self.timed: self.timemodel.tap() if not self.terminated: self.emit("game_changed", self.ply) for spectator in self.spectators.values(): if spectator.board == self.boards[-2]: spectator.putMove(self.boards[-1], self.moves[-1], self.boards[-2]) if self.puzzle_game and len(self.moves) % 2 == 1: status, reason = getStatus(self.boards[-1]) self.failed_playing_best = self.check_failed_playing_best( status) if self.failed_playing_best: # print("failed_playing_best() == True -> yield from asyncio.sleep(1.5) ") # It may happen that analysis had no time to fill hints with best moves # so we give him another chance with some additional time to think on it self.spectators[HINT].setBoard(self.boards[-2]) # TODO: wait for an event (analyzer PV reaching 18 ply) # instead of hard coded sleep time yield from asyncio.sleep(1.5) self.failed_playing_best = self.check_failed_playing_best( status) self.checkStatus() self.setOpening() self.curColor = 1 - self.curColor self.checkStatus()
def parseGame(self, matchlist, gameclass, in_progress=False, gameno=None): """ Parses the header and movelist for an observed or stored game from its matchlist (an re.match object) into a gameclass (FICSGame or subclass of) object. in_progress - should be True for an observed game matchlist, and False for stored/adjourned games """ # ################ observed game movelist example: # Movelist for game 64: # # Ajido (2281) vs. IMgooeyjim (2068) --- Thu Oct 14, 20:36 PDT 2010 # Rated standard match, initial time: 15 minutes, increment: 3 seconds. # # Move Ajido IMgooeyjim # ---- --------------------- --------------------- # 1. d4 (0:00.000) Nf6 (0:00.000) # 2. c4 (0:04.061) g6 (0:00.969) # 3. Nc3 (0:13.280) Bg7 (0:06.422) # {Still in progress} * # # ################# stored game example: # BwanaSlei (1137) vs. mgatto (1336) --- Wed Nov 5, 20:56 PST 2008 # Rated blitz match, initial time: 5 minutes, increment: 0 seconds. # # Move BwanaSlei mgatto # ---- --------------------- --------------------- # 1. e4 (0:00.000) c5 (0:00.000) # 2. d4 (0:05.750) cxd4 (0:03.020) # ... # 23. Qxf3 (1:05.500) # {White lost connection; game adjourned} * # # ################# stored wild/3 game with style12: # kurushi (1626) vs. mgatto (1627) --- Thu Nov 4, 10:33 PDT 2010 # Rated wild/3 match, initial time: 3 minutes, increment: 0 seconds. # # <12> nqbrknrn pppppppp -------- -------- -------- -------- PPPPPPPP NQBRKNRN W -1 0 0 0 0 0 17 kurushi mgatto -4 3 0 39 39 169403 45227 1 none (0:00.000) none 0 1 0 # # Move kurushi mgatto # ---- --------------------- --------------------- # 1. Nb3 (0:00.000) d5 (0:00.000) # 2. Nhg3 (0:00.386) e5 (0:03.672) # ... # 28. Rxd5 (0:00.412) # {Black lost connection; game adjourned} * # # ################# stored game movelist following stored game(s): # Stored games for mgatto: # C Opponent On Type Str M ECO Date # 1: W BabyLurking Y [ br 5 0] 29-13 W27 D37 Fri Nov 5, 04:41 PDT 2010 # 2: W gbtami N [ wr 5 0] 32-34 W14 --- Thu Oct 21, 00:14 PDT 2010 # # mgatto (1233) vs. BabyLurking (1455) --- Fri Nov 5, 04:33 PDT 2010 # Rated blitz match, initial time: 5 minutes, increment: 0 seconds. # # Move mgatto BabyLurking # ---- ---------------- ---------------- # 1. Nf3 (0:00) d5 (0:00) # 2. d4 (0:03) Nf6 (0:00) # 3. c4 (0:03) e6 (0:00) # {White lost connection; game adjourned} * # # ################## stored game movelist following stored game(s): # ## Note: A wild stored game in this format won't be parseable into a board because # ## it doesn't come with a style12 that has the start position, so we warn and return # ################## # Stored games for mgatto: # C Opponent On Type Str M ECO Date # 1: W gbtami N [ wr 5 0] 32-34 W14 --- Thu Oct 21, 00:14 PDT 2010 # # mgatto (1627) vs. gbtami (1881) --- Thu Oct 21, 00:10 PDT 2010 # Rated wild/fr match, initial time: 5 minutes, increment: 0 seconds. # # Move mgatto gbtami # ---- ---------------- ---------------- # 1. d4 (0:00) b6 (0:00) # 2. b3 (0:06) d5 (0:03) # 3. c4 (0:08) e6 (0:03) # 4. e3 (0:04) dxc4 (0:02) # 5. bxc4 (0:02) g6 (0:09) # 6. Nd3 (0:12) Bg7 (0:02) # 7. Nc3 (0:10) Ne7 (0:03) # 8. Be2 (0:08) c5 (0:05) # 9. a4 (0:07) cxd4 (0:38) # 10. exd4 (0:06) Bxd4 (0:03) # 11. O-O (0:10) Qc6 (0:06) # 12. Bf3 (0:16) Qxc4 (0:04) # 13. Bxa8 (0:03) Rxa8 (0:14) # {White lost connection; game adjourned} * # # ################# other reasons the game could be stored/adjourned: # Game courtesyadjourned by (Black|White) # Still in progress # This one must be a FICS bug # Game adjourned by mutual agreement # (White|Black) lost connection; game adjourned # Game adjourned by ((server shutdown)|(adjudication)|(simul holder)) index = 0 if in_progress: gameno = int(matchlist[index].groups()[0]) index += 2 header1 = matchlist[index] if isinstance(matchlist[index], str) \ else matchlist[index].group() matches = moveListHeader1.match(header1).groups() wname, wrating, bname, brating = matches[:4] if self.connection.FatICS: year, month, day, hour, minute, timezone = matches[11:] else: weekday, month, day, hour, minute, timezone, year = matches[4:11] month = months.index(month) + 1 wrating = parseRating(wrating) brating = parseRating(brating) rated, game_type, minutes, increment = \ moveListHeader2.match(matchlist[index + 1]).groups() minutes = int(minutes) increment = int(increment) game_type = GAME_TYPES[game_type] reason = matchlist[-1].group().lower() if in_progress: result = None result_str = "*" elif "1-0" in reason: result = WHITEWON result_str = "1-0" elif "0-1" in reason: result = BLACKWON result_str = "0-1" elif "1/2-1/2" in reason: result = DRAW result_str = "1/2-1/2" else: result = ADJOURNED result_str = "*" result, reason = parse_reason(result, reason, wname=wname) index += 3 if matchlist[index].startswith("<12>"): style12 = matchlist[index][5:] castleSigns = self.generateCastleSigns(style12, game_type) gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, \ fen = self.parseStyle12(style12, castleSigns) initialfen = fen movesstart = index + 4 else: if game_type.rating_type == TYPE_WILD: # we need a style12 start position to correctly parse a wild/* board log.error("BoardManager.parseGame: no style12 for %s board." % game_type.fics_name) return None castleSigns = ("k", "q") initialfen = None movesstart = index + 2 if in_progress: self.castleSigns[gameno] = castleSigns moves = {} times = {} wms = bms = minutes * 60 * 1000 for line in matchlist[movesstart:-1]: if not moveListMoves.match(line): log.error("BoardManager.parseGame: unmatched line: \"%s\"" % repr(line)) raise Exception( "BoardManager.parseGame: unmatched line: \"%s\"" % repr(line)) moveno, wmove, whour, wmin, wsec, wmsec, bmove, bhour, bmin, bsec, bmsec = \ moveListMoves.match(line).groups() whour = 0 if whour is None else int(whour[0]) bhour = 0 if bhour is None else int(bhour[0]) ply = int(moveno) * 2 - 2 if wmove: moves[ply] = wmove wms -= (int(whour) * 60 * 60 * 1000) + (int(wmin) * 60 * 1000) + (int(wsec) * 1000) if wmsec is not None: wms -= int(wmsec) else: wmsec = 0 if increment > 0: wms += (increment * 1000) times[ply] = "%01d:%02d:%02d.%03d" % (int(whour), int(wmin), int(wsec), int(wmsec)) if bmove: moves[ply + 1] = bmove bms -= (int(bhour) * 60 * 60 * 1000) + (int(bmin) * 60 * 1000) + (int(bsec) * 1000) if bmsec is not None: bms -= int(bmsec) else: bmsec = 0 if increment > 0: bms += (increment * 1000) times[ply + 1] = "%01d:%02d:%02d.%03d" % (int(bhour), int(bmin), int(bsec), int(bmsec)) if in_progress and gameno in self.queuedStyle12s: # Apply queued board updates for style12 in self.queuedStyle12s[gameno]: gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, fen = \ self.parseStyle12(style12, castleSigns) if lastmove is None: continue moves[ply - 1] = lastmove # Updated the queuedMoves in case there has been a takeback for moveply in list(moves.keys()): if moveply > ply - 1: del moves[moveply] del self.queuedStyle12s[gameno] pgnHead = [ ("Event", "FICS %s %s game" % (rated.lower(), game_type.fics_name)), ("Site", "freechess.org"), ("White", wname), ("Black", bname), ("TimeControl", "%d+%d" % (minutes * 60, increment)), ("Result", result_str), ("WhiteClock", msToClockTimeTag(wms)), ("BlackClock", msToClockTimeTag(bms)), ] if wrating != 0: pgnHead += [("WhiteElo", wrating)] if brating != 0: pgnHead += [("BlackElo", brating)] if year and month and day and hour and minute: pgnHead += [ ("Date", "%04d.%02d.%02d" % (int(year), int(month), int(day))), ("Time", "%02d:%02d:00" % (int(hour), int(minute))), ] if initialfen: pgnHead += [("SetUp", "1"), ("FEN", initialfen)] if game_type.variant_type == FISCHERRANDOMCHESS: pgnHead += [("Variant", "Fischerandom")] # FR is the only variant used in this tag by the PGN generator @ # ficsgames.org. They put all the other wild/* stuff only in the # "Event" header. elif game_type.variant_type == CRAZYHOUSECHESS: pgnHead += [("Variant", "Crazyhouse")] elif game_type.variant_type in (WILDCASTLECHESS, WILDCASTLESHUFFLECHESS): pgnHead += [("Variant", "Wildcastle")] elif game_type.variant_type == ATOMICCHESS: pgnHead += [("Variant", "Atomic")] elif game_type.variant_type == LOSERSCHESS: pgnHead += [("Variant", "Losers")] elif game_type.variant_type == SUICIDECHESS: pgnHead += [("Variant", "Suicide")] pgn = "\n".join(['[%s "%s"]' % line for line in pgnHead]) + "\n" moves = sorted(moves.items()) for ply, move in moves: if ply % 2 == 0: pgn += "%d. " % (ply // 2 + 1) time = times[ply] pgn += "%s {[%%emt %s]} " % (move, time) pgn += "*\n" wplayer = self.connection.players.get(wname) bplayer = self.connection.players.get(bname) for player, rating in ((wplayer, wrating), (bplayer, brating)): if game_type.rating_type in player.ratings and \ player.ratings[game_type.rating_type] != rating: player.ratings[game_type.rating_type] = rating player.emit("ratings_changed", game_type.rating_type, player) game = gameclass(wplayer, bplayer, game_type=game_type, result=result, rated=(rated.lower() == "rated"), minutes=minutes, inc=increment, board=FICSBoard(wms, bms, pgn=pgn)) if in_progress: game.gameno = gameno else: if gameno is not None: game.gameno = gameno game.reason = reason game = self.connection.games.get(game, emit=False) return game
def coro(): log.debug("GameModel.run: Starting. self=%s" % self) # Avoid racecondition when self.start is called while we are in # self.end if self.status != WAITING_TO_START: return if not self.isLocalGame(): self.timemodel.handle_gain = False self.status = RUNNING for player in self.players + list(self.spectators.values()): event = asyncio.Event() is_dead = set() player.start(event, is_dead) yield from event.wait() if is_dead: if player in self.players[WHITE]: self.kill(WHITE_ENGINE_DIED) break elif player in self.players[BLACK]: self.kill(BLACK_ENGINE_DIED) break log.debug("GameModel.run: emitting 'game_started' self=%s" % self) self.emit("game_started") # Let GameModel end() itself on games started with loadAndStart() if not self.lesson_game: self.checkStatus() if self.isEngine2EngineGame() and self.timed: self.timemodel.start() self.timemodel.started = True self.curColor = self.boards[-1].color while self.status in (PAUSED, RUNNING, DRAW, WHITEWON, BLACKWON): curPlayer = self.players[self.curColor] if self.timed: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: updating %s's time" % ( id(self), str(self.players), str(self.ply), str(curPlayer))) curPlayer.updateTime( self.timemodel.getPlayerTime(self.curColor), self.timemodel.getPlayerTime(1 - self.curColor)) try: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: calling %s.makeMove()" % ( id(self), str(self.players), self.ply, str(curPlayer))) if self.ply > self.lowply: move = yield from curPlayer.makeMove(self.boards[-1], self.moves[-1], self.boards[-2]) else: move = yield from curPlayer.makeMove(self.boards[-1], None, None) log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: got move=%s from %s" % ( id(self), str(self.players), self.ply, move, str(curPlayer))) except PlayerIsDead as e: if self.status in (WAITING_TO_START, PAUSED, RUNNING): stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error( "GameModel.run: A Player died: player=%s error=%s\n%s" % (curPlayer, error, e)) if self.curColor == WHITE: self.kill(WHITE_ENGINE_DIED) else: self.kill(BLACK_ENGINE_DIED) break except InvalidMove as e: stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error( "GameModel.run: InvalidMove by player=%s error=%s\n%s" % (curPlayer, error, e)) if self.curColor == WHITE: self.end(BLACKWON, WON_ADJUDICATION) else: self.end(WHITEWON, WON_ADJUDICATION) break except PassInterrupt: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: PassInterrupt" % ( id(self), str(self.players), self.ply)) continue except TurnInterrupt: log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: TurnInterrupt" % ( id(self), str(self.players), self.ply)) self.curColor = self.boards[-1].color continue except GameEnded: log.debug("GameModel.run: got GameEnded exception") break assert isinstance(move, Move), "%s" % repr(move) log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: applying move=%s" % ( id(self), str(self.players), self.ply, str(move))) self.needsSave = True newBoard = self.boards[-1].move(move) newBoard.board.prev = self.boards[-1].board # Variation on next move can exist from the hint panel... if self.boards[-1].board.next is not None: newBoard.board.children = self.boards[ -1].board.next.children self.boards = self.variations[0] self.boards[-1].board.next = newBoard.board self.boards.append(newBoard) self.moves.append(move) if self.timed: self.timemodel.tap() if not self.terminated: self.emit("game_changed", self.ply) for spectator in self.spectators.values(): if spectator.board == self.boards[-2]: spectator.putMove(self.boards[-1], self.moves[-1], self.boards[-2]) if self.puzzle_game and len(self.moves) % 2 == 1: status, reason = getStatus(self.boards[-1]) self.failed_playing_best = self.check_failed_playing_best(status) if self.failed_playing_best: # print("failed_playing_best() == True -> yield from asyncio.sleep(1.5) ") # It may happen that analysis had no time to fill hints with best moves # so we give him another chance with some additional time to think on it self.spectators[HINT].setBoard(self.boards[-2]) # TODO: wait for an event (analyzer PV reaching 18 ply) # instead of hard coded sleep time yield from asyncio.sleep(1.5) self.failed_playing_best = self.check_failed_playing_best(status) self.checkStatus() self.setOpening() self.curColor = 1 - self.curColor self.checkStatus()
def _ensureReadForGameWidgets(): mainvbox = widgets["mainvbox"] if len(mainvbox.get_children()) == 3: return global background background = widgets["mainvbox"].get_children()[1] mainvbox.remove(background) # Initing headbook align = createAlignment(4, 4, 0, 4) align.set_property("yscale", 0) headbook = Gtk.Notebook() headbook.set_scrollable(True) align.add(headbook) mainvbox.pack_start(align, False, True, 0) show_tabs(not conf.get("hideTabs", False)) # Initing center centerVBox = Gtk.VBox() # The dock global dock, dockAlign dock = PyDockTop("main") dockAlign = createAlignment(4, 4, 0, 4) dockAlign.add(dock) centerVBox.pack_start(dockAlign, True, True, 0) dockAlign.show() dock.show() for panel in sidePanels: hbox = Gtk.HBox() pixbuf = get_pixbuf(panel.__icon__, 16) icon = Gtk.Image.new_from_pixbuf(pixbuf) label = Gtk.Label(label=panel.__title__) label.set_size_request(0, 0) label.set_alignment(0, 1) hbox.pack_start(icon, False, False, 0) hbox.pack_start(label, True, True, 0) hbox.set_spacing(2) hbox.show_all() def cb(widget, x, y, keyboard_mode, tooltip, title, desc, filename): table = Gtk.Table(2, 2) table.set_row_spacings(2) table.set_col_spacings(6) table.set_border_width(4) pixbuf = get_pixbuf(filename, 56) image = Gtk.Image.new_from_pixbuf(pixbuf) image.set_alignment(0, 0) table.attach(image, 0, 1, 0, 2) titleLabel = Gtk.Label() titleLabel.set_markup("<b>%s</b>" % title) titleLabel.set_alignment(0, 0) table.attach(titleLabel, 1, 2, 0, 1) descLabel = Gtk.Label(label=desc) descLabel.props.wrap = True table.attach(descLabel, 1, 2, 1, 2) tooltip.set_custom(table) table.show_all() return True hbox.props.has_tooltip = True hbox.connect("query-tooltip", cb, panel.__title__, panel.__desc__, panel.__icon__) docks[panel.__name__] = (hbox, notebooks[panel.__name__]) if os.path.isfile(dockLocation): try: dock.loadFromXML(dockLocation, docks) except Exception as e: stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("Dock loading error: %s\n%s" % (e, error)) msg_dia = Gtk.MessageDialog(widgets["window1"], type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE) msg_dia.set_markup(_( "<b><big>PyChess was unable to load your panel settings</big></b>")) msg_dia.format_secondary_text(_( "Your panel settings have been reset. If this problem repeats, \ you should report it to the developers")) msg_dia.run() msg_dia.hide() os.remove(dockLocation) for title, panel in docks.values(): title.unparent() panel.unparent() if not os.path.isfile(dockLocation): leaf = dock.dock(docks["board"][1], CENTER, Gtk.Label(label=docks["board"][0]), "board") docks["board"][1].show_all() leaf.setDockable(False) # S epanel = leaf.dock(docks["bookPanel"][1], SOUTH, docks["bookPanel"][0], "bookPanel") epanel.default_item_height = 45 epanel = epanel.dock(docks["engineOutputPanel"][1], CENTER, docks["engineOutputPanel"][0], "engineOutputPanel") # NE leaf = leaf.dock(docks["annotationPanel"][1], EAST, docks["annotationPanel"][0], "annotationPanel") leaf = leaf.dock(docks["historyPanel"][1], CENTER, docks["historyPanel"][0], "historyPanel") leaf = leaf.dock(docks["scorePanel"][1], CENTER, docks["scorePanel"][0], "scorePanel") # SE leaf = leaf.dock(docks["chatPanel"][1], SOUTH, docks["chatPanel"][0], "chatPanel") leaf = leaf.dock(docks["commentPanel"][1], CENTER, docks["commentPanel"][0], "commentPanel") def unrealize(dock): # unhide the panel before saving so its configuration is saved correctly notebooks["board"].get_parent().get_parent().zoomDown() dock.saveToXML(dockLocation) dock._del() dock.connect("unrealize", unrealize) hbox = Gtk.HBox() # The status bar notebooks["statusbar"].set_border_width(4) hbox.pack_start(notebooks["statusbar"], False, True, 0) # The message area # TODO: If you try to fix this first read issue #958 and 1018 align = createAlignment(0, 0, 0, 0) # sw = Gtk.ScrolledWindow() # port = Gtk.Viewport() # port.add(notebooks["messageArea"]) # sw.add(port) # align.add(sw) align.add(notebooks["messageArea"]) hbox.pack_start(align, True, True, 0) def ma_switch_page(notebook, gpointer, page_num): notebook.props.visible = notebook.get_nth_page(page_num).\ get_child().props.visible notebooks["messageArea"].connect("switch-page", ma_switch_page) centerVBox.pack_start(hbox, False, True, 0) mainvbox.pack_start(centerVBox, True, True, 0) centerVBox.show_all() mainvbox.show() # Connecting headbook to other notebooks def hb_switch_page(notebook, gpointer, page_num): for notebook in notebooks.values(): notebook.set_current_page(page_num) # log.debug("HB_switch ficsgame no. %s , %s " % (key2gmwidg[getheadbook().\ # get_nth_page(page_num)].gamemodel.ficsgame.gameno,str(page_num))) gmwidg = key2gmwidg[getheadbook().get_nth_page(page_num)] if isinstance(gmwidg.gamemodel, ICGameModel): primary = "primary " + str(gmwidg.gamemodel.ficsgame.gameno) gmwidg.gamemodel.connection.client.run_command(primary) headbook.connect("switch-page", hb_switch_page) if hasattr(headbook, "set_tab_reorderable"): def page_reordered(widget, child, new_num, headbook): old_num = notebooks["board"].page_num(key2gmwidg[child].boardvbox) if old_num == -1: log.error('Games and labels are out of sync!') else: for notebook in notebooks.values(): notebook.reorder_child( notebook.get_nth_page(old_num), new_num) headbook.connect("page-reordered", page_reordered, headbook)
def init_layout(self): perspective_widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) perspective_manager.set_perspective_widget("database", perspective_widget) self.gamelist = GameList(database.load(None)) self.switcher_panel = SwitcherPanel(self.gamelist) self.opening_tree_panel = OpeningTreePanel(self.gamelist) self.filter_panel = FilterPanel(self.gamelist) self.preview_panel = PreviewPanel(self.gamelist) self.progressbar0 = Gtk.ProgressBar(show_text=True) self.progressbar = Gtk.ProgressBar(show_text=True) self.progress_dialog = Gtk.Dialog("Import", None, 0, ( Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)) self.progress_dialog.get_content_area().pack_start(self.progressbar0, True, True, 0) self.progress_dialog.get_content_area().pack_start(self.progressbar, True, True, 0) self.progress_dialog.get_content_area().show_all() perspective = perspective_manager.get_perspective("database") self.dock = PyDockTop("database", perspective) align = Gtk.Alignment() align.show() align.add(self.dock) self.dock.show() perspective_widget.pack_start(align, True, True, 0) dockLocation = addUserConfigPrefix("pydock-database.xml") docks = { "gamelist": (Gtk.Label(label="gamelist"), self.gamelist.box), "switcher": (dock_panel_tab(_("Database switcher"), "", addDataPrefix("glade/panel_docker.svg")), self.switcher_panel.alignment), "openingtree": (dock_panel_tab(_("Opening tree"), "", addDataPrefix("glade/panel_docker.svg")), self.opening_tree_panel.box), "filter": (dock_panel_tab(_("Filter"), "", addDataPrefix("glade/panel_docker.svg")), self.filter_panel.box), "preview": (dock_panel_tab(_("Preview"), "", addDataPrefix("glade/panel_docker.svg")), self.preview_panel.box), } if os.path.isfile(dockLocation): try: self.dock.loadFromXML(dockLocation, docks) except Exception as e: stringio = StringIO() traceback.print_exc(file=stringio) error = stringio.getvalue() log.error("Dock loading error: %s\n%s" % (e, error)) msg_dia = Gtk.MessageDialog(None, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE) msg_dia.set_markup(_( "<b><big>PyChess was unable to load your panel settings</big></b>")) msg_dia.format_secondary_text(_( "Your panel settings have been reset. If this problem repeats, \ you should report it to the developers")) msg_dia.run() msg_dia.hide() os.remove(dockLocation) for title, panel in docks.values(): title.unparent() panel.unparent() if not os.path.isfile(dockLocation): leaf = self.dock.dock(docks["gamelist"][1], CENTER, docks["gamelist"][0], "gamelist") leaf.setDockable(False) leaf.dock(docks["switcher"][1], NORTH, docks["switcher"][0], "switcher") leaf = leaf.dock(docks["filter"][1], EAST, docks["filter"][0], "filter") leaf = leaf.dock(docks["openingtree"][1], SOUTH, docks["openingtree"][0], "openingtree") leaf.dock(docks["preview"][1], SOUTH, docks["preview"][0], "preview") def unrealize(dock): dock.saveToXML(dockLocation) dock._del() self.dock.connect("unrealize", unrealize) self.dock.show_all() perspective_widget.show_all() perspective_manager.set_perspective_toolbuttons("database", [self.import_button, self.close_button]) self.switcher_panel.connect("chessfile_switched", self.on_chessfile_switched)
def __parseLine (self, line): if not self.connected: return parts = line.split() if not parts: return #---------------------------------------------------------- Initializing if parts[0] == "id": self.ids[parts[1]] = " ".join(parts[2:]) return if parts[0] == "uciok": self.emit("readyForOptions") return if parts[0] == "readyok": self.emit("readyForMoves") return #------------------------------------------------------- Options parsing if parts[0] == "option": dic = {} last = 1 varlist = [] for i in xrange (2, len(parts)+1): if i == len(parts) or parts[i] in OPTKEYS: key = parts[last] value = " ".join(parts[last+1:i]) if "type" in dic and dic["type"] in TYPEDIC: value = TYPEDIC[dic["type"]](value) if key == "var": varlist.append(value) else: dic[key] = value last = i if varlist: dic["vars"] = varlist name = dic["name"] del dic["name"] self.options[name] = dic return #---------------------------------------------------------------- A Move if self.mode == NORMAL and parts[0] == "bestmove": with self.moveLock: self.needBestmove = False self.__sendQueuedGo() if self.ignoreNext: log.debug("__parseLine: line='%s' self.ignoreNext==True, returning\n" % \ line.strip(), self.defname) self.ignoreNext = False self.readyForStop = True return if not self.waitingForMove: log.warn("__parseLine: self.waitingForMove==False, ignoring move=%s\n" % \ parts[1], self.defname) self.pondermove = None return self.waitingForMove = False move = parseAN(self.board, parts[1]) if not validate(self.board, move): # This is critical. To avoid game stalls, we need to resign on # behalf of the engine. log.error("__parseLine: move=%s didn't validate, putting 'del' in returnQueue. self.board=%s\n" % \ (repr(move), self.board), self.defname) self.returnQueue.put('del') return self.board = self.board.move(move) log.debug("__parseLine: applied move=%s to self.board=%s\n" % \ (move, self.board), self.defname) if self.getOption('Ponder'): self.pondermove = None # An engine may send an empty ponder line, simply to clear. if len(parts) == 4 and self.board: # Engines don't always check for everything in their # ponders. Hence we need to validate. # But in some cases, what they send may not even be # correct AN - specially in the case of promotion. try: pondermove = parseAN(self.board, parts[3]) except ParsingError: pass else: if validate(self.board, pondermove): self.pondermove = pondermove self._startPonder() self.returnQueue.put(move) log.debug("__parseLine: put move=%s into self.returnQueue=%s\n" % \ (move, self.returnQueue.queue), self.defname) return #----------------------------------------------------------- An Analysis if self.mode != NORMAL and parts[0] == "info" and "pv" in parts: scoretype = parts[parts.index("score")+1] if scoretype in ('lowerbound', 'upperbound'): score = None else: score = int(parts[parts.index("score")+2]) if scoretype == 'mate': # print >> self.engine, "stop" sign = score/abs(score) score = sign * (MATE_VALUE-abs(score)) movstrs = parts[parts.index("pv")+1:] try: moves = listToMoves (self.board, movstrs, AN, validate=True, ignoreErrors=False) except ParsingError, e: # ParsingErrors may happen when parsing "old" lines from # analyzing engines, which haven't yet noticed their new tasks log.debug("__parseLine: Ignored (%s) from analyzer: ParsingError%s\n" % \ (' '.join(movstrs),e), self.defname) return self.emit("analyze", moves, score) return