Example #1
0
    def checkStatus(self):
        """ Updates self.status so it fits with what getStatus(boards[-1])
            would return. That is, if the game is e.g. check mated this will
            call mode.end(), or if moves have been undone from an otherwise
            ended position, this will call __resume and emit game_unended. """

        log.debug("GameModel.checkStatus:")

        # call flag by engine
        if self.isEngine2EngineGame() and self.status in UNDOABLE_STATES:
            return

        status, reason = getStatus(self.boards[-1])

        if self.endstatus is not None:
            self.end(self.endstatus, reason)
            return

        if status != RUNNING and self.status in (WAITING_TO_START, PAUSED,
                                                 RUNNING):
            if status == DRAW and reason in (DRAW_REPITITION, DRAW_50MOVES):
                if self.isEngine2EngineGame():
                    self.end(status, reason)
                    return
            else:
                self.end(status, reason)
                return

        if status != self.status and self.status in UNDOABLE_STATES \
                and self.reason in UNDOABLE_REASONS:
            self.__resume()
            self.status = status
            self.reason = UNKNOWN_REASON
            self.emit("game_unended")
Example #2
0
    def status_changed(self, player, prop):
        log.debug(
            "%s" % player,
            extra={"task": (self.connection.username, "PTS.status_changed")})
        if player not in self.players:
            return

        try:
            self.store.set(self.players[player]["ti"], 6,
                           player.display_status)
            self.store.set(self.players[player]["ti"], 7,
                           get_player_tooltip_text(player))
        except KeyError:
            pass

        if player.status == IC_STATUS_PLAYING and player.game and \
                "private" not in self.players[player]:
            self.players[player]["private"] = player.game.connect(
                "notify::private", self.private_changed, player)
        elif player.status != IC_STATUS_PLAYING and \
                "private" in self.players[player]:
            game = player.game
            if game and game.handler_is_connected(self.players[player][
                    "private"]):
                game.disconnect(self.players[player]["private"])
            del self.players[player]["private"]

        if player == self.getSelectedPlayer():
            self.onSelectionChanged(None)

        return False
Example #3
0
 def init_chess_db(self):
     """ Create/open polyglot .bin file with extra win/loss/draw stats
         using chess_db parser from https://github.com/mcostalba/chess_db
     """
     if chess_db_path is not None and self.path and self.size > 0:
         try:
             if self.progressbar is not None:
                 self.progressbar.set_text("Creating .bin index file...")
             self.chess_db = Parser(engine=(chess_db_path, ))
             self.chess_db.open(self.path)
             bin_path = os.path.splitext(self.path)[0] + '.bin'
             if not os.path.isfile(bin_path):
                 log.debug("No valid games found in %s" % self.path)
                 self.chess_db = None
             elif getmtime(self.path) > getmtime(bin_path):
                 self.chess_db.make()
         except OSError as err:
             self.chess_db = None
             log.warning("Failed to sart chess_db parser. OSError %s %s" % (err.errno, err.strerror))
         except pexpect.TIMEOUT:
             self.chess_db = None
             log.warning("chess_db parser failed (pexpect.TIMEOUT)")
         except pexpect.EOF:
             self.chess_db = None
             log.warning("chess_db parser failed (pexpect.EOF)")
Example #4
0
 def private_changed(self, game, prop, player):
     log.debug(
         "%s" % player,
         extra={"task": (self.connection.username, "PTS.private_changed")})
     self.status_changed(player, prop)
     self.onSelectionChanged(self.tv.get_selection())
     return False
Example #5
0
 def decline(self, offer):
     log.debug("OfferManager.decline: %s" % offer)
     if offer.index is not None:
         self.declineIndex(offer.index)
     else:
         self.connection.client.run_command("decline t %s" %
                                            offerTypeToStr[offer.type])
Example #6
0
 def playerUndoMoves(self, movecount, gamemodel):
     log.debug("ICPlayer.playerUndoMoves: id(self)=%d self=%s, undoing movecount=%d" % \
         (id(self), self, movecount))
     # If current player has changed so that it is no longer us to move,
     # We raise TurnInterruprt in order to let GameModel continue the game
     if movecount % 2 == 1 and gamemodel.curplayer != self:
         self.queue.put("int")
Example #7
0
 def setBoard (self, board):
     log.debug("setBoardAtPly: board=%s" % board, extra={"task":self.defname})
     self._recordMove(board, None, None)
     
     if not self.readyMoves:
         return
     self._searchNow()
Example #8
0
 def __obsGameCreated (self, bm, ficsgame):
     if self.gamemodel.ficsplayers[0] == ficsgame.wplayer and \
         self.gamemodel.ficsplayers[1] == ficsgame.bplayer and \
         self.gameno == ficsgame.gameno:
             log.debug("ICPlayer.__obsGameCreated: gameno reappeared: gameno=%s white=%s black=%s" % \
                 (ficsgame.gameno, ficsgame.wplayer.name, ficsgame.bplayer.name))
             self.current = False
 def offer (self, offer, curply):
     log.debug("OfferManager.offer: curply=%s %s\n" % (curply, offer))
     self.lastPly = curply
     s = offerTypeToStr[offer.type]
     if offer.type == TAKEBACK_OFFER:
         s += " " + str(curply - offer.param)
     print >> self.connection.client, s
Example #10
0
    def cook_some(self):
        recv = self.sock.recv(self.BUFFER_SIZE)
        if len(recv) == 0:
            return

        if not self.connected:
            log.debug(recv, extra={"task": (self.name, "raw")})
            self.buf += recv
            self.connected = True
            if b"FatICS" in self.buf:
                self.FatICS = True
            elif b"puertorico.com" in self.buf:
                self.USCN = True
                self.buf = self.buf.replace(IAC_WONT_ECHO, b"")
            elif b"Starting FICS session" in self.buf:
                self.buf = self.buf.replace(IAC_WONT_ECHO, b"")
        else:
            recv, g_count, self.stateinfo = self.decode(recv, self.stateinfo)
            recv = recv.replace(b"\r", b"")
            log.debug(recv, extra={"task": (self.name, "raw")})

            for i in range(g_count):
                print(G_RESPONSE, file=self)

            self.buf += recv
Example #11
0
    def offerError(self, offer, error):
        log.debug("Human.offerError: self=%s error=%s %s" %
                  (self, error, offer))
        assert offer.type in ACTION_NAMES
        actionName = ACTION_NAMES[offer.type]
        if error == ACTION_ERROR_NONE_TO_ACCEPT:
            heading = _("Unable to accept %s") % actionName.lower()
            text = _("Probably because it has been withdrawn.")
        elif error == ACTION_ERROR_NONE_TO_DECLINE or \
                error == ACTION_ERROR_NONE_TO_WITHDRAW:
            # If the offer was not there, it has probably already been either
            # declined or withdrawn.
            return
        else:
            heading = _("%s returns an error") % actionName
            text = ERROR_MESSAGES[error]

        content = InfoBar.get_message_content(heading, text,
                                              Gtk.STOCK_DIALOG_WARNING)

        def response_cb(infobar, response, message):
            message.dismiss()

        message = InfoBarMessage(Gtk.MessageType.WARNING, content, response_cb)
        message.add_button(InfoBarMessageButton(Gtk.STOCK_CLOSE,
                                                Gtk.ResponseType.CANCEL))
        self.gmwidg.showMessage(message)
Example #12
0
    def _on_analyze(self, analyzer, analysis, analyzer_type):
        if self.board.view.animating:
            return

        if not self.menuitems[analyzer_type + "_mode"].active:
            return

        if len(analysis) >= 1 and analysis[0] is not None:
            movstrs, score, depth = analysis[0]
            board = analyzer.board
            try:
                moves = listToMoves(board, movstrs, validate=True)
            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))
                return
            except:
                return

            if moves and (self.gamemodel.curplayer.__type__ == LOCAL or
               [player.__type__ for player in self.gamemodel.players] == [REMOTE, REMOTE] or
               self.gamemodel.status not in UNFINISHED_STATES):
                if moves[0].flag == DROP:
                    piece = lmove.FCORD(moves[0].move)
                    color = board.color if analyzer_type == HINT else 1 - board.color
                    cord0 = board.getHoldingCord(color, piece)
                    self._set_arrow(analyzer_type, (cord0, moves[0].cord1))
                else:
                    self._set_arrow(analyzer_type, moves[0].cords)
            else:
                self._set_arrow(analyzer_type, None)
        return False
Example #13
0
    def cook_some(self, data):
        if not self.connected:
            log.debug(data, extra={"task": (self.name, "raw")})
            self.connected = True
            if b"FatICS" in data:
                self.FatICS = True
            elif b"puertorico.com" in data:
                self.USCN = True
                data = data.replace(IAC_WONT_ECHO, b"")
            elif b"chessclub.com" in data:
                self.ICC = True
                data = data.replace(IAC_WONT_ECHO, b"")
            elif b"Starting FICS session" in data:
                data = data.replace(IAC_WONT_ECHO, b"")
        else:
            if self.timeseal:
                data, g_count, self.stateinfo = self.decode(data, self.stateinfo)
            data = data.replace(b"\r", b"").replace(b"\x07", b"")
            # enable this only for temporary debugging
            log.debug(data, extra={"task": (self.name, "raw")})

            if self.timeseal:
                for i in range(g_count):
                    self._stream_writer.write(self.encode(bytearray(G_RESPONSE, "utf-8")) + b"\n")
        return data
Example #14
0
    def on_analyze(self, engine, analysis):
        if self.boardview.animating:
            return

        if self.boardview.model.isPlayingICSGame():
            return

        if not self.active:
            return

        is_FAN = conf.get("figuresInNotation", False)

        for i, line in enumerate(analysis):
            if line is None:
                self.store[self.path + (i, )] = self.textOnlyRow("")
                continue

            board0 = self.engine.board
            board = board0.clone()

            movstrs, score, depth = line
            try:
                pv = listToMoves(board, movstrs, validate=True)
            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))
                return
            except:
                return

            move = None
            if pv:
                move = pv[0]

            ply0 = board.ply if self.mode == HINT else board.ply + 1
            counted_pv = []
            for j, pvmove in enumerate(pv):
                ply = ply0 + j
                if ply % 2 == 0:
                    mvcount = "%d." % (ply / 2 + 1)
                elif j == 0:
                    mvcount = "%d..." % (ply / 2 + 1)
                else:
                    mvcount = ""
                counted_pv.append("%s%s" %
                                  (mvcount, toFAN(board, pvmove)
                                   if is_FAN else toSAN(board, pvmove, True)))
                board = board.move(pvmove)

            goodness = (min(max(score, -250), 250) + 250) / 500.0
            if self.engine.board.color == BLACK:
                score = -score

            self.store[self.path + (i, )] = [
                (board0, move, pv),
                (prettyPrintScore(score, depth), 1, goodness), 0, False,
                " ".join(counted_pv), False, False
            ]
Example #15
0
def generalStart (gamemodel, player0tup, player1tup, loaddata=None):
    """ The player tuples are:
        (The type af player in a System.const value,
         A callable creating the player,
         A list of arguments for the callable,
         A preliminary name for the player)

        If loaddata is specified, it should be a tuple of:
        (A text uri or fileobj,
         A Savers.something module with a load function capable of loading it,
         An int of the game in file you want to load,
         The position from where to start the game) """
    log.debug("ionest.generalStart: %s\n %s\n %s\n" % (gamemodel, player0tup, player1tup))
    worker = GtkWorker (lambda w:
            workfunc(w, gamemodel, player0tup, player1tup, loaddata))

    def onPublished (worker, vallist):
        for val in vallist:
            # The worker will start by publishing (gmwidg, game)
            if type(val) == tuple:
                gmwidg, game = val
                gamewidget.attachGameWidget(gmwidg)
                gamenanny.nurseGame(gmwidg, game)
                handler.emit("gmwidg_created", gmwidg, game)

            # Then the worker will publish functions setting up widget stuff
            elif callable(val):
                val()
    worker.connect("published", onPublished)

    def onDone (worker, (gmwidg, game)):
        gmwidg.connect("close_clicked", closeGame, game)
        worker.__del__()
Example #16
0
    def acceptReceived(self, player, offer):
        log.debug("GameModel.acceptReceived: accepter=%s %s" % (
                  repr(player), offer))
        if player == self.players[WHITE]:
            opPlayer = self.players[BLACK]
        else:
            opPlayer = self.players[WHITE]

        if offer in self.offers and self.offers[offer] == opPlayer:
            if offer.type == DRAW_OFFER:
                self.end(DRAW, DRAW_AGREE)
            elif offer.type == TAKEBACK_OFFER:
                log.debug("GameModel.acceptReceived: undoMoves(%s)" % (
                    self.ply - offer.param))
                self.undoMoves(self.ply - offer.param)
            elif offer.type == ADJOURN_OFFER:
                self.end(ADJOURNED, ADJOURNED_AGREEMENT)
            elif offer.type == ABORT_OFFER:
                self.end(ABORTED, ABORTED_AGREEMENT)
            elif offer.type == PAUSE_OFFER:
                self.pause()
            elif offer.type == RESUME_OFFER:
                self.resume()
            del self.offers[offer]
        else:
            player.offerError(offer, ACTION_ERROR_NONE_TO_ACCEPT)
Example #17
0
 def __onOfferDeclined(self, om, offer):
     for offer_ in list(self.gamemodel.offers.keys()):
         if offer.type == offer_.type:
             offer.param = offer_.param
     log.debug("ICPlayer.__onOfferDeclined: emitting decline for %s" %
               offer)
     self.emit("decline", offer)
Example #18
0
    def makeMove(self, board1, move, board2):
        log.debug("Human.makeMove: move=%s, board1=%s board2=%s" % (
            move, board1, board2))
        if self.board.view.premove_piece and self.board.view.premove0 and \
                self.board.view.premove1 and \
                self.color == self.board.view.premove_piece.color:
            if validate(board1,
                        Move(self.board.view.premove0,
                             self.board.view.premove1,
                             board1,
                             promotion=self.board.view.premove_promotion)):
                log.debug("Human.makeMove: Setting move to premove %s %s" % (
                    self.board.view.premove0, self.board.view.premove1))
                self.board.emit_move_signal(
                    self.board.view.premove0,
                    self.board.view.premove1,
                    promotion=self.board.view.premove_promotion)
            # reset premove
            self.board.view.setPremove(None, None, None, None)
        self.gmwidg.setLocked(False)

        item = yield from self.move_queue.get()
        self.gmwidg.setLocked(True)

        if item == "del":
            log.debug("Human.makeMove got: del")
            raise PlayerIsDead
        elif item == "int":
            log.debug("Human.makeMove got: int")
            raise TurnInterrupt
        elif item == "pass":
            log.debug("Human.makeMove got: pass")
            raise PassInterrupt
        return item
Example #19
0
 def offerDeclined (self, offer):
     log.debug("Human.offerDeclined: self=%s %s\n" % (self, offer))
     if offer.type not in ACTION_NAMES:
         return
     title = _("%s was declined by your opponent") % ACTION_NAMES[offer.type]
     description = _("You can try to send the offer to your opponent later in the game again.")
     self._message(title, description, gtk.MESSAGE_INFO, gtk.BUTTONS_OK)
Example #20
0
        def analyse_moves():
            should_black = conf.get("shouldBlack", True)
            should_white = conf.get("shouldWhite", True)
            from_current = conf.get("fromCurrent", True)
            start_ply = gmwidg.board.view.shown if from_current else 0
            move_time = int(conf.get("max_analysis_spin", 3))
            threshold = int(conf.get("variation_threshold_spin", 50))
            for board in gamemodel.boards[start_ply:]:
                if stop_event.is_set():
                    break

                @idle_add
                def do():
                    gmwidg.board.view.setShownBoard(board)
                do()
                analyzer.setBoard(board)
                if threat_PV:
                    inv_analyzer.setBoard(board)
                time.sleep(move_time + 0.1)

                ply = board.ply
                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):
                        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="Treatening", score=score_str0)
                            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)
                        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))

            widgets["analyze_game"].hide()
            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()
Example #21
0
 def offerWithdrawn (self, offer):
     log.debug("Human.offerWithdrawn: self=%s %s\n" % (self, offer))
     if offer.type not in ACTION_NAMES:
         return
     title = _("%s was withdrawn by your opponent") % ACTION_NAMES[offer.type]
     description = _("Your opponent seems to have changed his or her mind.")
     self._message(title, description, gtk.MESSAGE_INFO, gtk.BUTTONS_OK)
Example #22
0
 def acceptReceived(self, player, offer):
     log.debug("ICGameModel.acceptReceived: accepter=%s %s" %
               (repr(player), offer))
     if player.__type__ == LOCAL:
         GameModel.acceptReceived(self, player, offer)
         log.debug("ICGameModel.acceptReceived: connection.om.accept(%s)" % offer)
         self.connection.om.accept(offer)
Example #23
0
 def __onOfferAdd(self, om, offer):
     if self.gamemodel.status in UNFINISHED_STATES and not self.gamemodel.isObservationGame(
     ):
         log.debug("ICPlayer.__onOfferAdd: emitting offer: self.gameno=%s self.name=%s %s" % \
             (self.gameno, self.name, offer))
         self.offers[offer.index] = offer
         self.emit("offer", offer)
Example #24
0
    def makeMove(self, board1, move, board2):
        log.debug("makeMove: move=%s self.pondermove=%s board1=%s board2=%s self.board=%s" % (
            move, self.pondermove, board1, board2, self.board), extra={"task": self.defname})
        assert self.readyMoves

        self._recordMove(board1, move, board2)
        self.waitingForMove = True
        ponderhit = False

        if board2 and self.pondermove and move == self.pondermove:
            ponderhit = True
        elif board2 and self.pondermove:
            self.ignoreNext = True
            print("stop", file=self.engine)

        self._searchNow(ponderhit=ponderhit)

        # Parse outputs
        try:
            return_queue = yield from self.queue.get()
            if return_queue == "invalid":
                raise InvalidMove
            if return_queue == "del":
                raise PlayerIsDead
            if return_queue == "int":
                self.pondermove = None
                self.ignoreNext = True
                self.needBestmove = True
                self.hurry()
                raise TurnInterrupt
            return return_queue
        finally:
            self.waitingForMove = False
Example #25
0
 def accept(self, offer):
     log.debug("OfferManager.accept: %s" % offer)
     if offer.index is not None:
         self.acceptIndex(offer.index)
     else:
         self.connection.client.run_command("accept t %s" %
                                            offerTypeToStr[offer.type])
Example #26
0
 def on_gmwidg_closed(gmwidg):
     log.debug("GladeHandlers.on_gmwidg_closed")
     del gameDic[gmwidg]
     if not gameDic:
         for widget in MENU_ITEMS:
             gamewidget.getWidgets()[widget].set_property('sensitive',
                                                          False)
Example #27
0
    def offerReceived(self, player, offer):
        log.debug("ICGameModel.offerReceived: offerer=%s %s" %
                  (repr(player), offer))
        if player == self.players[WHITE]:
            opPlayer = self.players[BLACK]
        else:
            opPlayer = self.players[WHITE]

        if offer.type == CHAT_ACTION:
            opPlayer.putMessage(offer.param)

        elif offer.type in (RESIGNATION, FLAG_CALL):
            self.connection.om.offer(offer, self.ply)

        elif offer.type in OFFERS:
            if offer not in self.offers:
                log.debug("ICGameModel.offerReceived: %s.offer(%s)" %
                          (repr(opPlayer), offer))
                self.offers[offer] = player
                opPlayer.offer(offer)
            # If the offer was an update to an old one, like a new takebackvalue
            # we want to remove the old one from self.offers
            for offer_ in list(self.offers.keys()):
                if offer.type == offer_.type and offer != offer_:
                    del self.offers[offer_]
Example #28
0
def init_engine(analyzer_type, gamemodel, force=False):
    """
    Initializes and starts the engine analyzer of analyzer_type the user has
    configured in the Engines tab of the preferencesDialog, for gamemodel. If no
    such engine is set in the preferences, or if the configured engine doesn't
    support the chess variant being played in gamemodel, then no analyzer is
    started and None is returned.
    """
    if analyzer_type == HINT:
        combo_name = "ana_combobox"
        check_name = "analyzer_check"
        mode = ANALYZING
    else:
        combo_name = "inv_ana_combobox"
        check_name = "inv_analyzer_check"
        mode = INVERSE_ANALYZING

    analyzer = None

    if conf.get(check_name, True):
        anaengines = list(discoverer.getAnalyzers())
        engine = discoverer.getEngineByMd5(conf.get(combo_name, 0))
        if engine is None:
            engine = anaengines[0]

        if gamemodel.variant.variant in discoverer.getEngineVariants(engine):
            analyzer = discoverer.initAnalyzerEngine(engine, mode, gamemodel.variant)
            log.debug("%s analyzer: %s" % (analyzer_type, repr(analyzer)))

    return analyzer
Example #29
0
def nurseGame (gmwidg, gamemodel):
    """ Call this function when gmwidget is just created """
    log.debug("nurseGame: %s %s" % (gmwidg, gamemodel))
    gmwidg.connect("infront", on_gmwidg_infront)
    gmwidg.connect("closed", on_gmwidg_closed)
    gmwidg.connect("title_changed", on_gmwidg_title_changed)
    
    # Because of the async loading of games, the game might already be started,
    # when nurseGame is called.
    # Thus we support both cases.
    if gamemodel.status == WAITING_TO_START:
        gamemodel.connect("game_started", on_game_started, gmwidg)
        gamemodel.connect("game_loaded", game_loaded, gmwidg)
    else:
        if gamemodel.uri:
            game_loaded(gamemodel, gamemodel.uri, gmwidg)
        on_game_started(gamemodel, gmwidg)
    
    gamemodel.connect("game_saved", game_saved, gmwidg)
    gamemodel.connect("game_ended", game_ended, gmwidg)
    gamemodel.connect("game_unended", game_unended, gmwidg)
    gamemodel.connect("game_resumed", game_unended, gmwidg)
    gamemodel.connect("game_changed", game_changed, gmwidg)
    gamemodel.connect("game_paused", game_paused, gmwidg)

    if isinstance(gamemodel, ICGameModel):
        gamemodel.connection.connect("disconnected", on_disconnected, gmwidg)
Example #30
0
    def offer(self, offer):
        log.debug("Human.offer: self=%s %s" % (self, offer))
        assert offer.type in OFFER_MESSAGES

        if self.gamemodel.players[1 - self.color].__type__ is LOCAL:
            self.emit("accept", offer)
            return

        heading, text, takes_param = OFFER_MESSAGES[offer.type]
        if takes_param:
            param = offer.param
            if offer.type == TAKEBACK_OFFER and \
                    self.gamemodel.players[1 - self.color].__type__ != REMOTE:
                param = self.gamemodel.ply - offer.param
            heading = heading % param
            text = text % param

        def response_cb(infobar, response, message):
            if response == Gtk.ResponseType.ACCEPT:
                self.emit("accept", offer)
            elif response == Gtk.ResponseType.NO:
                self.emit("decline", offer)
            message.dismiss()

        content = InfoBar.get_message_content(heading, text,
                                              Gtk.STOCK_DIALOG_QUESTION)
        message = InfoBarMessage(Gtk.MessageType.QUESTION, content,
                                 response_cb)
        message.add_button(InfoBarMessageButton(
            _("Accept"), Gtk.ResponseType.ACCEPT))
        message.add_button(InfoBarMessageButton(
            _("Decline"), Gtk.ResponseType.NO))
        message.add_button(InfoBarMessageButton(Gtk.STOCK_CLOSE,
                                                Gtk.ResponseType.CANCEL))
        self.gmwidg.showMessage(message)
Example #31
0
    def playerUndoMoves(self, movecount, gamemodel):
        log.debug("Human.playerUndoMoves:  movecount=%s self=%s gamemodel.curplayer=%s" %
                  (movecount, self, gamemodel.curplayer))
        self.gmwidg.clearMessages()

        # If the movecount is odd, the player has changed, and we have to interupt
        if movecount % 2 == 1 and gamemodel.curplayer != self:
            # If it is no longer us to move, we raise TurnInterruprt in order to
            # let GameModel continue the game.
            log.debug("Human.playerUndoMoves: putting TurnInterrupt into self.move_queue %s" % self.name)
            self.move_queue.put_nowait("int")

        # If the movecount is even, we have to ensure the board is unlocked.
        # This is because it might have been locked by the game ending, but
        # perhaps we have now undone some moves, and it is no longer ended.
        elif movecount % 2 == 0 and gamemodel.curplayer == self:
            log.debug("Human.playerUndoMoves: self=%s: calling gmwidg.setLocked" % (self))
            self.gmwidg.setLocked(False)
            log.debug("Human.playerUndoMoves: putting PassInterrupt into self.move_queue %s" % self.name)
            self.move_queue.put_nowait("pass")
Example #32
0
 def write_stdin(self, writer, line):
     try:
         log.debug(line, extra={"task": self.defname})
         writer.write(line.encode())
         yield from writer.drain()
     except BrokenPipeError:
         log.debug('SubProcess.write_stdin(): BrokenPipeError',
                   extra={"task": self.defname})
         self.emit("died")
         self.terminate()
     except ConnectionResetError:
         log.debug('SubProcess.write_stdin(): ConnectionResetError',
                   extra={"task": self.defname})
         self.emit("died")
         self.terminate()
     except GLib.GError:
         log.debug("SubProcess.write_stdin(): GLib.GError",
                   extra={"task": self.defname})
         self.emit("died")
         self.terminate()
Example #33
0
    def makeMove(self, board1, move, board2):
        log.debug("ICPlayer.makemove: id(self)=%d self=%s move=%s board1=%s board2=%s" % (
            id(self), self, move, board1, board2))
        if board2 and not self.gamemodel.isObservationGame():
            # TODO: Will this work if we just always use CASTLE_SAN?
            castle_notation = CASTLE_KK
            if board2.variant == FISCHERRANDOMCHESS:
                castle_notation = CASTLE_SAN
            self.connection.bm.sendMove(toAN(board2, move, castleNotation=castle_notation))
            # wait for fics to send back our move we made
            item = yield from self.move_queue.get()

        item = yield from self.move_queue.get()
        try:
            if item == "end":
                raise GameEnded
            elif item == "del":
                raise PlayerIsDead

            gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms = item
            self.gamemodel.onBoardUpdate(gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms)

            if self.turn_interrupt:
                self.turn_interrupt = False
                raise TurnInterrupt

            if ply < board1.ply:
                # This should only happen in an observed game
                board1 = self.gamemodel.getBoardAtPly(max(ply - 1, 0))
            log.debug("ICPlayer.makemove: id(self)=%d self=%s from queue got: ply=%d sanmove=%s" % (
                id(self), self, ply, lastmove))

            try:
                move = parseSAN(board1, lastmove)
                log.debug("ICPlayer.makemove: id(self)=%d self=%s parsed move=%s" % (
                    id(self), self, move))
            except ParsingError:
                raise
            return move
        finally:
            log.debug("ICPlayer.makemove: id(self)=%d self=%s returning move=%s" % (id(self), self, move))
Example #34
0
    def onBoardUpdate(self, bm, gameno, ply, curcol, lastmove, fen, wname,
                      bname, wms, bms):
        log.debug(("ICGameModel.onBoardUpdate: id=%s self.ply=%s self.players=%s gameno=%s " + \
                  "wname=%s bname=%s ply=%s curcol=%s lastmove=%s fen=%s wms=%s bms=%s") % \
                  (str(id(self)), str(self.ply), repr(self.players), str(gameno), str(wname), str(bname), \
                   str(ply), str(curcol), str(lastmove), str(fen), str(wms), str(bms)))
        if gameno != self.ficsgame.gameno or len(self.players) < 2 or wname != self.players[0].ichandle \
           or bname != self.players[1].ichandle:
            return
        log.debug("ICGameModel.onBoardUpdate: id=%d, self.players=%s: updating time and/or ply" % \
            (id(self), str(self.players)))

        if self.timed:
            log.debug("ICGameModel.onBoardUpdate: id=%d self.players=%s: updating timemodel" % \
                (id(self), str(self.players)))
            # If game end coming from helper connection before last move made
            # we have to tap() ourselves
            if self.status in (DRAW, WHITEWON, BLACKWON):
                if self.timemodel.ply < ply:
                    self.timemodel.paused = False
                    self.timemodel.tap()
                    self.timemodel.paused = True

            self.timemodel.updatePlayer(WHITE, wms / 1000.)
            self.timemodel.updatePlayer(BLACK, bms / 1000.)

        if ply < self.ply:
            log.debug("ICGameModel.onBoardUpdate: id=%d self.players=%s self.ply=%d ply=%d: TAKEBACK" % \
                (id(self), str(self.players), self.ply, ply))
            offers = self.offers.keys()
            for offer in offers:
                if offer.type == TAKEBACK_OFFER:
                    # There can only be 1 outstanding takeback offer for both players on FICS,
                    # (a counter-offer by the offeree for a takeback for a different number of
                    # moves replaces the initial offer) so we can safely remove all of them
                    del self.offers[offer]

            # In some cases (like lost on time) the last move is resent
            if self.reason != WON_CALLFLAG:
                self.undoMoves(self.ply - ply)
Example #35
0
    def makeMove(self, board1, move, board2):
        log.debug(
            "ICPlayer.makemove: id(self)=%d self=%s move=%s board1=%s board2=%s"
            % (id(self), self, move, board1, board2))
        if board2 and not self.gamemodel.isObservationGame():
            # TODO: Will this work if we just always use CASTLE_SAN?
            castle_notation = CASTLE_KK
            if board2.variant == FISCHERRANDOMCHESS:
                castle_notation = CASTLE_SAN
            self.connection.bm.sendMove(
                toAN(board2, move, castleNotation=castle_notation))

        item = self.queue.get(block=True)
        try:
            if item == "del":
                raise PlayerIsDead
            if item == "int":
                raise TurnInterrupt

            ply, sanmove = item
            if ply < board1.ply:
                # This should only happen in an observed game
                board1 = self.gamemodel.getBoardAtPly(max(ply - 1, 0))
            log.debug(
                "ICPlayer.makemove: id(self)=%d self=%s from queue got: ply=%d sanmove=%s"
                % (id(self), self, ply, sanmove))

            try:
                move = parseSAN(board1, sanmove)
                log.debug(
                    "ICPlayer.makemove: id(self)=%d self=%s parsed move=%s" %
                    (id(self), self, move))
            except ParsingError:
                raise
            return move
        finally:
            log.debug(
                "ICPlayer.makemove: id(self)=%d self=%s returning move=%s" %
                (id(self), self, move))
            self.okqueue.put("ok")
Example #36
0
    def on_icc_my_game_result(self, data):
        log.debug("DG_MY_GAME_RESULT %s" % data)
        # gamenumber become-examined game_result_code score_string2 description-string ECO
        # 1242 1 Res 1-0 {Black resigns} {D89}
        parts = data.split(" ", 4)
        gameno, ex, result_code, result, rest = parts
        gameno = int(gameno)
        comment, rest = rest[2:].split("}", 1)

        try:
            game = self.connection.games.get_game_by_gameno(gameno)
        except KeyError:
            return
        wname = game.wplayer.name
        bname = game.bplayer.name

        result, reason = parse_reason(reprResult.index(result),
                                      comment,
                                      wname=wname)

        try:
            wplayer = self.connection.players.get(wname)
            wplayer.restore_previous_status()
            # no status update will be sent by
            # FICS if the player doesn't become available, so we restore
            # previous status first (not necessarily true, but the best guess)
        except KeyError:
            log.debug("%s not in self.connections.players - creating" % wname)
            wplayer = FICSPlayer(wname)

        try:
            bplayer = self.connection.players.get(bname)
            bplayer.restore_previous_status()
        except KeyError:
            log.debug("%s not in self.connections.players - creating" % bname)
            bplayer = FICSPlayer(bname)

        game = FICSGame(wplayer,
                        bplayer,
                        gameno=int(gameno),
                        result=result,
                        reason=reason)
        if wplayer.game is not None:
            game.rated = wplayer.game.rated
        game = self.connection.games.get(game, emit=False)
        self.connection.games.game_ended(game)
        # Do this last to give anybody connected to the game's signals a chance
        # to disconnect from them first
        wplayer.game = None
        bplayer.game = None
    def parse(self):
        line = yield from self.lines.popleft()

        if not line.line:
            return  # TODO: necessary?
        # print("line.line:", line.line)
        if self.lines.datagram_mode and line.code is not None:
            if line.code_type == DG:
                callback = self.replay_dg_dict[line.code]
                callback(line.line)
                log.debug(
                    line.line,
                    extra={"task": (self.telnet.name, callback.__name__)})
                return
            elif line.code_type == CN and line.code in self.replay_cn_dict:
                callback = self.replay_cn_dict[line.code]
                callback(line.line)
                log.debug(
                    line.line,
                    extra={"task": (self.telnet.name, callback.__name__)})
                return

        predictions = (self.reply_cmd_dict[line.code] if line.code is not None
                       and line.code in self.reply_cmd_dict else
                       self.predictions)
        for pred in list(predictions):
            answer = yield from self.test_prediction(pred, line)
            # print(answer, "  parse_line: trying prediction %s for line '%s'" % (pred.name, line.line[:80]))
            if answer in (RETURN_MATCH, RETURN_MATCH_END):
                log.debug(
                    "\n".join(pred.matches),
                    extra={"task": (self.telnet.name, pred.name)},
                )
                break
        else:
            # print("  NOT MATCHED:", line.line[:80])
            if line.code != BLKCMD_PASSWORD:
                log.debug(line.line,
                          extra={"task": (self.telnet.name, "nonmatched")})
Example #38
0
    def terminate(self):
        log.debug("GameModel.terminate: %s" % self)

        if self.status != KILLED:
            for player in self.players:
                player.end(self.status, self.reason)

            for spectator in self.spectators.values():
                spectator.end(self.status, self.reason)

            if self.timed:
                log.debug("GameModel.terminate: -> timemodel.end()")
                self.timemodel.end()
                log.debug("GameModel.terminate: <- timemodel.end() %s" %
                          repr(self.timemodel))

        self.emit("game_terminated")
Example #39
0
 def playerUndoMoves(self, movecount, gamemodel):
     log.debug("ICPlayer.playerUndoMoves: id(self)=%d self=%s, undoing movecount=%d" % (
         id(self), self, movecount))
     # If current player has changed so that it is no longer us to move,
     # We raise TurnInterrupt in order to let GameModel continue the game
     if movecount % 2 == 1 and gamemodel.curplayer != self:
         log.debug("ICPlayer.playerUndoMoves: set self.turn_interrupt = True %s" % self.name)
         if self.connection.ICC:
             self.move_queue.put_nowait("stm")
         else:
             self.turn_interrupt = True
     if movecount % 2 == 0 and gamemodel.curplayer == self:
         log.debug("ICPlayer.playerUndoMoves: set self.pass_interrupt = True %s" % self.name)
         if self.connection.ICC:
             self.move_queue.put_nowait("pass")
         else:
             self.pass_interrupt = True
Example #40
0
    def __boardUpdate(self, bm, gameno, ply, curcol, lastmove, fen, wname,
                      bname, wms, bms):
        log.debug("ICPlayer.__boardUpdate: id(self)=%d self=%s %s %s %s %d %d %s %s %d %d" % (
            id(self), self, gameno, wname, bname, ply, curcol, lastmove, fen, wms, bms))

        if gameno == self.gameno and len(self.gamemodel.players) >= 2 and self.current:
            # LectureBot allways uses gameno 1 for many games in one lecture
            # and wname == self.gamemodel.players[0].ichandle \
            # and bname == self.gamemodel.players[1].ichandle \
            log.debug("ICPlayer.__boardUpdate: id=%d self=%s gameno=%s: this is my move" % (
                id(self), self, gameno))

            # In some cases (like lost on time) the last move is resent
            if ply <= self.gamemodel.ply:
                return

            if 1 - curcol == self.color and ply == self.gamemodel.ply + 1 and lastmove is not None:
                log.debug("ICPlayer.__boardUpdate: id=%d self=%s ply=%d: \
                          putting move=%s in queue" % (id(self), self, ply, lastmove))
                self.queue.put_nowait((ply, lastmove))
Example #41
0
 def makeMove (self, board1, move, board2):
     log.debug("Human.makeMove: move=%s, board1=%s board2=%s" % \
         (move, board1, board2))
     if self.board.view.premovePiece and self.board.view.premove0 and self.board.view.premove1 and \
         self.color == self.board.view.premovePiece.color:
         if validate(board1, Move(self.board.view.premove0, self.board.view.premove1, board1, promotion=self.board.view.premovePromotion)):
             log.debug("Human.makeMove: Setting move to premove %s %s" % \
                 (self.board.view.premove0, self.board.view.premove1))
             self.board.emit_move_signal(self.board.view.premove0, self.board.view.premove1, promotion=self.board.view.premovePromotion)
         # reset premove
         self.board.view.setPremove(None, None, None, None)
     self.gmwidg.setLocked(False)
     item = self.queue.get(block=True)
     self.gmwidg.setLocked(True)
     if item == "del":
         raise PlayerIsDead("Killed by foreign forces")
     if item == "int":
         log.debug("Human.makeMove: %s: raise TurnInterrupt" % self)
         raise TurnInterrupt
     return item
Example #42
0
 def __boardUpdate (self, bm, gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms):
     log.debug("ICPlayer.__boardUpdate: id(self)=%d self=%s %s %s %s %d %d %s %s %d %d\n" % \
         (id(self), self, gameno, wname, bname, ply, curcol, lastmove, fen, wms, bms))
     
     if gameno == self.gameno and len(self.gamemodel.players) >= 2 \
         and wname == self.gamemodel.players[0].getICHandle() \
         and bname == self.gamemodel.players[1].getICHandle():
         log.debug("ICPlayer.__boardUpdate: id=%d self=%s gameno=%s: this is my move\n" % \
             (id(self), self, gameno))
         
         # In some cases (like lost on time) the last move is resent
         if ply <= self.gamemodel.ply:
             return
         
         if 1-curcol == self.color:
             log.debug("ICPlayer.__boardUpdate: id=%d self=%s ply=%d: putting move=%s in queue\n" % \
                 (id(self), self, ply, lastmove))
             self.queue.put((ply, lastmove))
             # Ensure the fics thread doesn't continue parsing, before the
             # game/player thread has recieved the move.
             # Specifically this ensures that we aren't killed due to end of
             # game before our last move is recieved
             self.okqueue.get(block=True)
Example #43
0
                    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

            log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: acquiring self.applyingMoveLock\n" % \
                (id(self), str(self.players), self.ply))
            self.applyingMoveLock.acquire()
            try:
                log.debug("GameModel.run: id=%s, players=%s, self.ply=%s: applying move=%s\n" % \
                    (id(self), str(self.players), self.ply, str(move)))
                self.needsSave = True
                newBoard = self.boards[-1].move(move)
                self.boards.append(newBoard)
                self.moves.append(move)

                if self.timemodel:
                    self.timemodel.tap()

                self.checkStatus()

                self.emit("game_changed")
Example #44
0
    def onBoardUpdate(self, bm, gameno, ply, curcol, lastmove, fen, wname,
                      bname, wms, bms):
        log.debug(("ICGameModel.onBoardUpdate: id=%s self.ply=%s self.players=%s gameno=%s " + \
                  "wname=%s bname=%s ply=%s curcol=%s lastmove=%s fen=%s wms=%s bms=%s") % \
                  (str(id(self)), str(self.ply), repr(self.players), str(gameno), str(wname), str(bname), \
                   str(ply), str(curcol), str(lastmove), str(fen), str(wms), str(bms)))
        if gameno != self.ficsgame.gameno or len(self.players) < 2:
            # LectureBot allways uses gameno 1 for many games in one lecture
            # or wname != self.players[0].ichandle or bname != self.players[1].ichandle:
            return
        log.debug("ICGameModel.onBoardUpdate: id=%d, self.players=%s: updating time and/or ply" % \
            (id(self), str(self.players)))
        if self.timed:
            log.debug("ICGameModel.onBoardUpdate: id=%d self.players=%s: updating timemodel" % \
                (id(self), str(self.players)))
            # If game end coming from helper connection before last move made
            # we have to tap() ourselves
            if self.status in (DRAW, WHITEWON, BLACKWON):
                if self.timemodel.ply < ply:
                    self.timemodel.paused = False
                    self.timemodel.tap()
                    self.timemodel.paused = True

            self.timemodel.updatePlayer(WHITE, wms / 1000.)
            self.timemodel.updatePlayer(BLACK, bms / 1000.)

        if lastmove is None:
            if bname != self.tags["Black"]:
                self.tags["Black"] = self.players[
                    BLACK].name = self.ficsplayers[BLACK].name = bname
                self.emit("players_changed")
            if wname != self.tags["White"]:
                self.tags["White"] = self.players[
                    WHITE].name = self.ficsplayers[WHITE].name = wname
                self.emit("players_changed")
            if self.boards[-1].asFen() != fen:
                self.status = RUNNING
                self.loadAndStart(StringIO(fen),
                                  fen_loader,
                                  0,
                                  -1,
                                  first_time=False)
                self.emit("game_started")
                curPlayer = self.players[self.curColor]
                curPlayer.resetPosition()

        elif ply < self.ply:
            log.debug("ICGameModel.onBoardUpdate: id=%d self.players=%s \
                      self.ply=%d ply=%d: TAKEBACK"                                                    % \
                      (id(self), str(self.players), self.ply, ply))
            for offer in list(self.offers.keys()):
                if offer.type == TAKEBACK_OFFER:
                    # There can only be 1 outstanding takeback offer for both players on FICS,
                    # (a counter-offer by the offeree for a takeback for a different number of
                    # moves replaces the initial offer) so we can safely remove all of them
                    del self.offers[offer]

            # In some cases (like lost on time) the last move is resent
            # or we just observing an examined game
            if self.reason != WON_CALLFLAG:
                if len(self.moves) >= self.ply - ply:
                    self.undoMoves(self.ply - ply)
                else:
                    self.status = RUNNING
                    self.loadAndStart(StringIO(fen),
                                      fen_loader,
                                      0,
                                      -1,
                                      first_time=False)
                    self.emit("game_started")
                    curPlayer = self.players[self.curColor]
                    curPlayer.resetPosition()

        elif ply > self.ply + 1:
            self.status = RUNNING
            self.loadAndStart(StringIO(fen),
                              fen_loader,
                              0,
                              -1,
                              first_time=False)
            self.emit("game_started")
            curPlayer = self.players[self.curColor]
            curPlayer.resetPosition()
Example #45
0
 def onGameEnded(self, bm, ficsgame):
     if ficsgame == self.ficsgame and len(self.players) >= 2:
         log.debug(
             "ICGameModel.onGameEnded: self.players=%s ficsgame=%s" % \
             (repr(self.players), repr(ficsgame)))
         self.end(ficsgame.result, ficsgame.reason)
Example #46
0
def game_unended(gamemodel, gmwidg):
    log.debug("gamenanny.game_unended: %s" % gamemodel.boards[-1])
    gmwidg.clearMessages()
    _set_statusbar(gmwidg, "")
    return False
Example #47
0
 def on_game_close_clicked(self, button):
     log.debug("gamewidget.on_game_close_clicked %s" % button)
     self.emit("game_close_clicked")
Example #48
0
    def offerReceived(self, player, offer):
        log.debug("GameModel.offerReceived: offerer=%s %s" %
                  (repr(player), offer))
        if player == self.players[WHITE]:
            opPlayer = self.players[BLACK]
        elif player == self.players[BLACK]:
            opPlayer = self.players[WHITE]
        else:
            # Player comments echoed to opponent if the player started a conversation
            # with you prior to observing a game the player is in #1113
            return

        if offer.type == HURRY_ACTION:
            opPlayer.hurry()

        elif offer.type == CHAT_ACTION:
            # print("GameModel.offerreceived(player, offer)", player.name, offer.param)
            opPlayer.putMessage(offer.param)

        elif offer.type == RESIGNATION:
            if player == self.players[WHITE]:
                self.end(BLACKWON, WON_RESIGN)
            else:
                self.end(WHITEWON, WON_RESIGN)

        elif offer.type == FLAG_CALL:
            assert self.timed
            if self.timemodel.getPlayerTime(1 - player.color) <= 0:
                if self.timemodel.getPlayerTime(player.color) <= 0:
                    self.end(DRAW, DRAW_CALLFLAG)
                elif not playerHasMatingMaterial(self.boards[-1],
                                                 player.color):
                    if player.color == WHITE:
                        self.end(DRAW, DRAW_WHITEINSUFFICIENTANDBLACKTIME)
                    else:
                        self.end(DRAW, DRAW_BLACKINSUFFICIENTANDWHITETIME)
                else:
                    if player == self.players[WHITE]:
                        self.end(WHITEWON, WON_CALLFLAG)
                    else:
                        self.end(BLACKWON, WON_CALLFLAG)
            else:
                player.offerError(offer, ACTION_ERROR_NOT_OUT_OF_TIME)

        elif offer.type == DRAW_OFFER and isClaimableDraw(self.boards[-1]):
            reason = getStatus(self.boards[-1])[1]
            self.end(DRAW, reason)

        elif offer.type == TAKEBACK_OFFER and offer.param < self.lowply:
            player.offerError(offer, ACTION_ERROR_TOO_LARGE_UNDO)

        elif offer.type in OFFERS:
            if offer not in self.offers:
                log.debug("GameModel.offerReceived: doing %s.offer(%s)" %
                          (repr(opPlayer), offer))
                self.offers[offer] = player
                opPlayer.offer(offer)
            # If we updated an older offer, we want to delete the old one
            keys = self.offers.keys()
            for offer_ in keys:
                if offer.type == offer_.type and offer != offer_:
                    del self.offers[offer_]
Example #49
0
    def update_board(self, gameno, ply, curcol, lastmove, fen, wname, bname,
                     wms, bms):
        log.debug((
            "ICGameModel.update_board: id=%s self.ply=%s self.players=%s gameno=%s "
            +
            "wname=%s bname=%s ply=%s curcol=%s lastmove=%s fen=%s wms=%s bms=%s"
        ) % (str(id(self)), str(self.ply), repr(
            self.players), str(gameno), str(wname), str(bname), str(ply),
             str(curcol), str(lastmove), str(fen), str(wms), str(bms)))
        if gameno != self.ficsgame.gameno or len(
                self.players) < 2 or self.disconnected:
            return

        if self.timed:
            log.debug(
                "ICGameModel.update_board: id=%d self.players=%s: updating timemodel"
                % (id(self), str(self.players)))
            # If game end coming from helper connection before last move made
            # we have to tap() ourselves
            if self.status in (DRAW, WHITEWON, BLACKWON):
                if self.timemodel.ply < ply:
                    self.timemodel.paused = False
                    self.timemodel.tap()
                    self.timemodel.paused = True

            self.timemodel.updatePlayer(WHITE, wms / 1000.)
            self.timemodel.updatePlayer(BLACK, bms / 1000.)

        if ply < self.ply:
            log.debug("ICGameModel.update_board: id=%d self.players=%s \
                      self.ply=%d ply=%d: TAKEBACK" %
                      (id(self), str(self.players), self.ply, ply))
            for offer in list(self.offers.keys()):
                if offer.type == TAKEBACK_OFFER:
                    # There can only be 1 outstanding takeback offer for both players on FICS,
                    # (a counter-offer by the offeree for a takeback for a different number of
                    # moves replaces the initial offer) so we can safely remove all of them
                    del self.offers[offer]

            if len(self.moves) >= self.ply - ply:
                self.undoMoves(self.ply - ply)
            else:
                self.status = RUNNING
                self.loadAndStart(StringIO(fen),
                                  fen_loader,
                                  0,
                                  -1,
                                  first_time=False)
                self.emit("game_started")
                curPlayer = self.players[self.curColor]
                curPlayer.resetPosition()

        elif ply > self.ply + 1:
            log.debug("ICGameModel.update_board: id=%d self.players=%s \
                      self.ply=%d ply=%d: FORWARD JUMP" %
                      (id(self), str(self.players), self.ply, ply))
            self.status = RUNNING
            self.loadAndStart(StringIO(fen),
                              fen_loader,
                              0,
                              -1,
                              first_time=False)
            self.emit("game_started")
            curPlayer = self.players[self.curColor]
            curPlayer.resetPosition()
Example #50
0
    def init_layout(self):
        perspective_widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        perspective_manager.set_perspective_widget("fics", perspective_widget)
        perspective_manager.set_perspective_menuitems("fics", self.menuitems)

        self.infobar = InfoBarNotebook("fics_lounge_infobar")
        self.infobar.hide()
        perspective_widget.pack_start(self.infobar, False, False, 0)

        self.dock = PyDockTop("fics", self)
        align = Gtk.Alignment()
        align.show()
        align.add(self.dock)
        self.dock.show()
        perspective_widget.pack_start(align, True, True, 0)

        self.notebooks = {"ficshome": new_notebook()}
        self.main_notebook = self.notebooks["ficshome"]
        for panel in self.sidePanels:
            self.notebooks[panel.__name__] = new_notebook(panel.__name__)

        self.docks["ficshome"] = (Gtk.Label(label="ficshome"),
                                  self.notebooks["ficshome"], None)
        for panel in self.sidePanels:
            self.docks[panel.__name__][1] = self.notebooks[panel.__name__]

        self.load_from_xml()

        # Default layout of side panels
        if not os.path.isfile(self.dockLocation):
            leaf = self.dock.dock(self.docks["ficshome"][1], CENTER,
                                  self.docks["ficshome"][0], "ficshome")
            leaf.setDockable(False)

            console_leaf = leaf.dock(self.docks["ConsolePanel"][1], SOUTH,
                                     self.docks["ConsolePanel"][0],
                                     "ConsolePanel")
            console_leaf.dock(self.docks["NewsPanel"][1], CENTER,
                              self.docks["NewsPanel"][0], "NewsPanel")

            seek_leaf = leaf.dock(self.docks["SeekListPanel"][1], WEST,
                                  self.docks["SeekListPanel"][0],
                                  "SeekListPanel")
            seek_leaf.dock(self.docks["SeekGraphPanel"][1], CENTER,
                           self.docks["SeekGraphPanel"][0], "SeekGraphPanel")
            seek_leaf.dock(self.docks["PlayerListPanel"][1], CENTER,
                           self.docks["PlayerListPanel"][0], "PlayerListPanel")
            seek_leaf.dock(self.docks["GameListPanel"][1], CENTER,
                           self.docks["GameListPanel"][0], "GameListPanel")
            seek_leaf.dock(self.docks["ArchiveListPanel"][1], CENTER,
                           self.docks["ArchiveListPanel"][0],
                           "ArchiveListPanel")

            leaf = leaf.dock(self.docks["ChatPanel"][1], SOUTH,
                             self.docks["ChatPanel"][0], "ChatPanel")
            # leaf.dock(self.docks["LecturesPanel"][1], CENTER, self.docks["LecturesPanel"][0], "LecturesPanel")

        def unrealize(dock):
            dock.saveToXML(self.dockLocation)
            dock._del()

        self.dock.connect("unrealize", unrealize)

        self.dock.show_all()
        perspective_widget.show_all()

        log.debug("FICS.__init__: finished")
Example #51
0
 def players_changed(self, model):
     log.debug("annotationPanel.players_changed: starting")
     self.update
     log.debug("annotationPanel.players_changed: returning")
Example #52
0
    def generalStart(self, gamemodel, player0tup, player1tup, loaddata=None):
        """ The player tuples are:
        (The type af player in a System.const value,
        A callable creating the player,
        A list of arguments for the callable,
        A preliminary name for the player)

        If loaddata is specified, it should be a tuple of:
        (A text uri or fileobj,
        A Savers.something module with a load function capable of loading it,
        An int of the game in file you want to load,
        The position from where to start the game)
        """

        log.debug("Games.generalStart: %s\n %s\n %s" %
                  (gamemodel, player0tup, player1tup))
        gmwidg = gamewidget.GameWidget(gamemodel, self)
        self.gamewidgets.add(gmwidg)
        self.gmwidg_cids[gmwidg] = gmwidg.connect("game_close_clicked", self.closeGame)

        # worker.publish((gmwidg,gamemodel))
        self.attachGameWidget(gmwidg)
        game_nanny.nurseGame(gmwidg, gamemodel)
        log.debug("Games.generalStart: -> emit gmwidg_created: %s" % (gmwidg))
        self.emit("gmwidg_created", gmwidg)
        log.debug("Games.generalStart: <- emit gmwidg_created: %s" % (gmwidg))

        # Initing players

        def set_name(none, player, key, alt):
            player.setName(conf.get(key, alt))

        players = []
        for i, playertup in enumerate((player0tup, player1tup)):
            type, func, args, prename = playertup
            if type != LOCAL:
                if type == ARTIFICIAL:
                    player = yield from func(*args)
                else:
                    player = func(*args)
                players.append(player)
                # if type == ARTIFICIAL:
                #    def readyformoves (player, color):
                #        gmwidg.setTabText(gmwidg.display_text))
                #    players[i].connect("readyForMoves", readyformoves, i)
            else:
                # Until PyChess has a proper profiles system, as discussed on the
                # issue tracker, we need to give human players special treatment
                player = func(gmwidg, *args)
                players.append(player)

        if player0tup[0] == ARTIFICIAL and player1tup[0] == ARTIFICIAL:

            def emit_action(board, action, param, gmwidg):
                if gmwidg.isInFront():
                    gamemodel.curplayer.emit("offer", Offer(action, param=param))

            self.board_cids[gmwidg.board] = gmwidg.board.connect("action", emit_action, gmwidg)

        log.debug("Games.generalStart: -> gamemodel.setPlayers(): %s" %
                  (gamemodel))
        gamemodel.setPlayers(players)
        log.debug("Games.generalStart: <- gamemodel.setPlayers(): %s" %
                  (gamemodel))

        # Starting
        if loaddata:
            try:
                uri, loader, gameno, position = loaddata
                gamemodel.loadAndStart(uri, loader, gameno, position)
                if position != gamemodel.ply:
                    gmwidg.board.view.shown = position
            except LoadingError as e:
                d = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.WARNING,
                                      buttons=Gtk.ButtonsType.OK)
                d.set_markup(_("<big><b>Error loading game</big></b>"))
                d.format_secondary_text(", ".join(str(a) for a in e.args))
                d.show()
                d.hide()

        else:
            if gamemodel.variant.need_initial_board:
                for player in gamemodel.players:
                    player.setOptionInitialBoard(gamemodel)
            log.debug("Games..generalStart: -> gamemodel.start(): %s" %
                      (gamemodel))

            gamemodel.start()
            log.debug("Games.generalStart: <- gamemodel.start(): %s" %
                      (gamemodel))

        log.debug("Games.generalStart: returning gmwidg=%s\n gamemodel=%s" %
                  (gmwidg, gamemodel))
Example #53
0
    def closeGame(self, gmwidg):
        log.debug("Games.closeGame")
        response = None
        if not gmwidg.gamemodel.isChanged():
            response = Gtk.ResponseType.OK
        else:
            markup = "<b><big>" + _("Save the current game before you close it?") + "</big></b>"
            if conf.get("autoSave", False):
                x = self.saveGamePGN(gmwidg.gamemodel)
                if x:
                    response = Gtk.ResponseType.OK
                else:
                    markup = "<b><big>" + _("Unable to save to configured file. \
                                            Save the current game before you close it?") + "</big></b>"

            if response is None:
                d = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.WARNING)
                d.add_button(_("Close _without Saving"), Gtk.ResponseType.OK)
                d.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
                if gmwidg.gamemodel.uri:
                    d.add_button(Gtk.STOCK_SAVE, Gtk.ResponseType.YES)
                else:
                    d.add_button(Gtk.STOCK_SAVE_AS, Gtk.ResponseType.YES)

                gmwidg.bringToFront()

                d.set_markup(markup)
                d.format_secondary_text(_(
                    "It is not possible later to continue the game,\nif you don't save it."))

                response = d.run()
                d.destroy()

            if response == Gtk.ResponseType.YES:
                # Test if cancel was pressed in the save-file-dialog
                if self.saveGame(gmwidg.gamemodel) != Gtk.ResponseType.ACCEPT:
                    response = Gtk.ResponseType.CANCEL

        if response not in (Gtk.ResponseType.DELETE_EVENT,
                            Gtk.ResponseType.CANCEL):
            if gmwidg.gamemodel.status in UNFINISHED_STATES:
                gmwidg.gamemodel.end(ABORTED, ABORTED_AGREEMENT)

            gmwidg.disconnect(self.gmwidg_cids[gmwidg])
            del self.gmwidg_cids[gmwidg]

            for cid in self.notify_cids[gmwidg]:
                conf.notify_remove(cid)
            del self.notify_cids[gmwidg]

            if gmwidg.board in self.board_cids:
                gmwidg.board.disconnect(self.board_cids[gmwidg.board])
                del self.board_cids[gmwidg.board]

            self.delGameWidget(gmwidg)
            self.gamewidgets.remove(gmwidg)
            gmwidg.gamemodel.terminate()

            if len(self.gamewidgets) == 0:
                for widget in MENU_ITEMS:
                    gamewidget.getWidgets()[widget].set_property('sensitive', False)

        return response
Example #54
0
    def closeAllGames(self, gamewidgets):
        log.debug("Games.closeAllGames")
        response = None
        changedPairs = [(gmwidg, gmwidg.gamemodel) for gmwidg in gamewidgets
                        if gmwidg.gamemodel.isChanged()]
        if len(changedPairs) == 0:
            response = Gtk.ResponseType.OK

        elif len(changedPairs) == 1:
            response = self.closeGame(changedPairs[0][0])
        else:
            markup = "<big><b>" + ngettext("There is %d game with unsaved moves.",
                                           "There are %d games with unsaved moves.",
                                           len(changedPairs)) % len(changedPairs) + " " + \
                _("Save moves before closing?") + "</b></big>"

            for gmwidg, game in changedPairs:
                if not gmwidg.gamemodel.isChanged():
                    response = Gtk.ResponseType.OK
                else:
                    if conf.get("autoSave", False):
                        x = self.saveGamePGN(game)
                        if x:
                            response = Gtk.ResponseType.OK
                        else:
                            response = None
                            markup = "<b><big>" + _("Unable to save to configured file. \
                                                    Save the games before closing?") + "</big></b>"
                            break

            if response is None:
                widgets = GladeWidgets("saveGamesDialog.glade")
                dialog = widgets["saveGamesDialog"]
                heading = widgets["saveGamesDialogHeading"]
                saveLabel = widgets["saveGamesDialogSaveLabel"]
                treeview = widgets["saveGamesDialogTreeview"]

                heading.set_markup(markup)

                liststore = Gtk.ListStore(bool, str)
                treeview.set_model(liststore)
                renderer = Gtk.CellRendererToggle()
                renderer.props.activatable = True
                treeview.append_column(Gtk.TreeViewColumn("", renderer, active=0))
                treeview.append_column(Gtk.TreeViewColumn("",
                                                          Gtk.CellRendererText(),
                                                          text=1))
                for gmwidg, game in changedPairs:
                    liststore.append((True, "%s %s %s" % (game.players[0], _("vs."), game.players[1])))

                def callback(cell, path):
                    if path:
                        liststore[path][0] = not liststore[path][0]
                    saves = len(tuple(row for row in liststore if row[0]))
                    saveLabel.set_text(ngettext(
                        "_Save %d document", "_Save %d documents", saves) % saves)
                    saveLabel.set_use_underline(True)

                renderer.connect("toggled", callback)

                callback(None, None)

                while True:
                    response = dialog.run()
                    if response == Gtk.ResponseType.YES:
                        for i in range(len(liststore) - 1, -1, -1):
                            checked, name = liststore[i]
                            if checked:
                                cgmwidg, cgame = changedPairs[i]
                                if self.saveGame(cgame) == Gtk.ResponseType.ACCEPT:
                                    liststore.remove(liststore.get_iter((i, )))
                                    del changedPairs[i]
                                    if cgame.status in UNFINISHED_STATES:
                                        cgame.end(ABORTED, ABORTED_AGREEMENT)
                                    cgame.terminate()
                                    self.delGameWidget(cgmwidg)
                                else:
                                    break
                        else:
                            break
                    else:
                        break
                dialog.destroy()

        if response not in (Gtk.ResponseType.DELETE_EVENT,
                            Gtk.ResponseType.CANCEL):
            pairs = [(gmwidg, gmwidg.gamemodel) for gmwidg in gamewidgets]
            for gmwidg, game in pairs:
                if game.status in UNFINISHED_STATES:
                    game.end(ABORTED, ABORTED_AGREEMENT)
                game.terminate()
                if gmwidg.notebookKey in self.key2gmwidg:
                    self.delGameWidget(gmwidg)

        return response
Example #55
0
    def on_window_key_press(self, window, event):
        log.debug('on_window_key_press: %s %s' % (window.get_title(), event))

        # debug leaking memory
        if Gdk.keyval_name(event.keyval) == "F12":
            from pychess.System.debug import print_obj_referrers, print_muppy_sumary
            if event.get_state() & Gdk.ModifierType.SHIFT_MASK:
                print_muppy_sumary()
            else:
                print_obj_referrers()

        # Tabbing related shortcuts
        persp = perspective_manager.get_perspective("games")
        if not persp.getheadbook():
            pagecount = 0
        else:
            pagecount = persp.getheadbook().get_n_pages()
        if pagecount > 1:
            if event.get_state() & Gdk.ModifierType.CONTROL_MASK:
                page_num = persp.getheadbook().get_current_page()
                # Move selected
                if event.get_state() & Gdk.ModifierType.SHIFT_MASK:
                    child = persp.getheadbook().get_nth_page(page_num)
                    if event.keyval == Gdk.KEY_Page_Up:
                        persp.getheadbook().reorder_child(
                            child, (page_num - 1) % pagecount)
                        return True
                    elif event.keyval == Gdk.KEY_Page_Down:
                        persp.getheadbook().reorder_child(
                            child, (page_num + 1) % pagecount)
                        return True
                # Change selected
                else:
                    if event.keyval == Gdk.KEY_Page_Up:
                        persp.getheadbook().set_current_page(
                            (page_num - 1) % pagecount)
                        return True
                    elif event.keyval == Gdk.KEY_Page_Down:
                        persp.getheadbook().set_current_page(
                            (page_num + 1) % pagecount)
                        return True

        gmwidg = persp.cur_gmwidg()
        if gmwidg is not None:
            # Let default handler work if typing inside entry widgets
            current_focused_widget = gamewidget.getWidgets(
            )["main_window"].get_focus()
            if current_focused_widget is not None and isinstance(
                    current_focused_widget, Gtk.Entry):
                return False

            # Prevent moving in game while lesson not finished
            if gmwidg.gamemodel.lesson_game:
                return

            # Navigate on boardview with arrow keys
            if event.keyval in leftkeys:
                if event.get_state() & Gdk.ModifierType.CONTROL_MASK:
                    gmwidg.board.view.backToMainLine()
                    return True
                else:
                    gmwidg.board.view.showPrev()
                    return True
            elif event.keyval in rightkeys:
                gmwidg.board.view.showNext()
                return True
            elif event.keyval in upkeys:
                gmwidg.board.view.showPrev(step=2)
                return True
            elif event.keyval in downkeys:
                gmwidg.board.view.showNext(step=2)
                return True
            elif event.keyval in homekeys:
                gmwidg.board.view.showFirst()
                return True
            elif event.keyval in endkeys:
                gmwidg.board.view.showLast()
                return True

            if (not event.get_state() & Gdk.ModifierType.CONTROL_MASK) and \
                    (not event.get_state() & Gdk.ModifierType.MOD1_MASK) and \
                    (event.keyval != Gdk.KEY_Escape) and \
                    (event.keyval not in functionkeys):
                # Enter moves with keyboard
                board_control = gmwidg.board
                keyname = Gdk.keyval_name(event.keyval)
                board_control.key_pressed(keyname)
                print(board_control.keybuffer)
                return True

            return False
Example #56
0
    def offerRecieved(self, player, offer):
        log.debug("GameModel.offerRecieved: offerer=%s %s\n" %
                  (repr(player), offer))
        if player == self.players[WHITE]:
            opPlayer = self.players[BLACK]
        else:
            opPlayer = self.players[WHITE]

        if self.status not in UNFINISHED_STATES and offer.type in INGAME_ACTIONS:
            player.offerError(offer, ACTION_ERROR_REQUIRES_UNFINISHED_GAME)

        elif offer.type == RESUME_OFFER and self.status in (DRAW, WHITEWON,BLACKWON) and \
                self.reason in UNRESUMEABLE_REASONS:
            player.offerError(offer, ACTION_ERROR_UNRESUMEABLE_POSITION)

        elif offer.type == RESUME_OFFER and self.status != PAUSED:
            player.offerError(offer, ACTION_ERROR_RESUME_REQUIRES_PAUSED)

        elif offer.type == HURRY_ACTION:
            opPlayer.hurry()

        elif offer.type == CHAT_ACTION:
            opPlayer.putMessage(offer.param)

        elif offer.type == RESIGNATION:
            if player == self.players[WHITE]:
                self.end(BLACKWON, WON_RESIGN)
            else:
                self.end(WHITEWON, WON_RESIGN)

        elif offer.type == FLAG_CALL:
            if not self.timemodel:
                player.offerError(offer, ACTION_ERROR_NO_CLOCK)
                return

            if player == self.players[WHITE]:
                opcolor = BLACK
            else:
                opcolor = WHITE

            if self.timemodel.getPlayerTime(opcolor) <= 0:
                if self.timemodel.getPlayerTime(1 - opcolor) <= 0:
                    self.end(DRAW, DRAW_CALLFLAG)
                elif not playerHasMatingMaterial(self.boards[-1],
                                                 (1 - opcolor)):
                    if opcolor == WHITE:
                        self.end(DRAW, DRAW_BLACKINSUFFICIENTANDWHITETIME)
                    else:
                        self.end(DRAW, DRAW_WHITEINSUFFICIENTANDBLACKTIME)
                else:
                    if player == self.players[WHITE]:
                        self.end(WHITEWON, WON_CALLFLAG)
                    else:
                        self.end(BLACKWON, WON_CALLFLAG)
            else:
                player.offerError(offer, ACTION_ERROR_NOT_OUT_OF_TIME)

        elif offer.type == DRAW_OFFER and isClaimableDraw(self.boards[-1]):
            reason = getStatus(self.boards[-1])[1]
            self.end(DRAW, reason)

        elif offer.type == TAKEBACK_OFFER and offer.param < self.lowply:
            player.offerError(offer, ACTION_ERROR_TOO_LARGE_UNDO)

        elif offer.type == TAKEBACK_OFFER and self.status != RUNNING and \
                (self.status not in UNDOABLE_STATES or self.reason not in UNDOABLE_REASONS):
            player.offerError(offer, ACTION_ERROR_GAME_ENDED)

        elif offer.type in OFFERS:
            if offer not in self.offers:
                log.debug("GameModel.offerRecieved: doing %s.offer(%s)\n" % \
                    (repr(opPlayer), offer))
                self.offers[offer] = player
                opPlayer.offer(offer)
            # If we updated an older offer, we want to delete the old one
            for offer_ in self.offers.keys():
                if offer.type == offer_.type and offer != offer_:
                    del self.offers[offer_]
Example #57
0
 def __init__(self):
     log.debug("FICS.__init__: starting")
     GObject.GObject.__init__(self)
     Perspective.__init__(self, "fics", _("ICS"))
     self.dockLocation = addUserConfigPrefix("pydock-fics.xml")
     self.first_run = True
Example #58
0
    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()
Example #59
0
        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()
Example #60
0
def game_ended(gamemodel, reason, gmwidg):
    log.debug("gamenanny.game_ended: reason=%s gmwidg=%s\ngamemodel=%s" %
              (reason, gmwidg, gamemodel))
    nameDic = {
        "white": gamemodel.players[WHITE],
        "black": gamemodel.players[BLACK],
        "mover": gamemodel.curplayer
    }
    if gamemodel.status == WHITEWON:
        nameDic["winner"] = gamemodel.players[WHITE]
        nameDic["loser"] = gamemodel.players[BLACK]
    elif gamemodel.status == BLACKWON:
        nameDic["winner"] = gamemodel.players[BLACK]
        nameDic["loser"] = gamemodel.players[WHITE]
    msg_one = reprResult_long[gamemodel.status] % nameDic
    msg_two = reprReason_long[reason] % nameDic
    if gamemodel.reason == WON_ADJUDICATION:
        color = BLACK if gamemodel.status == WHITEWON else WHITE
        invalid_move = gamemodel.players[color].invalid_move
        if invalid_move:
            msg_two += _(" invalid engine move: %s" % invalid_move)

    content = InfoBar.get_message_content(msg_one, msg_two,
                                          Gtk.STOCK_DIALOG_INFO)
    message = InfoBarMessage(Gtk.MessageType.INFO, content, None)

    callback = None
    if isinstance(gamemodel, ICGameModel):
        if gamemodel.hasLocalPlayer() and not gamemodel.examined:

            def status_changed(player, prop, message):
                make_sensitive_if_available(message.buttons[0], player)
                make_sensitive_if_playing(message.buttons[1], player)

            def callback(infobar, response, message):
                if response == 0:
                    gamemodel.remote_player.offerRematch()
                elif response == 1:
                    gamemodel.remote_player.observe()
                return False
            gmwidg.cids[gamemodel.remote_ficsplayer] = \
                gamemodel.remote_ficsplayer.connect("notify::status", status_changed, message)
            message.add_button(InfoBarMessageButton(_("Offer Rematch"), 0))
            message.add_button(
                InfoBarMessageButton(
                    _("Observe %s" % gamemodel.remote_ficsplayer.name), 1))
            status_changed(gamemodel.remote_ficsplayer, None, message)

        else:

            def status_changed(player, prop, button):
                make_sensitive_if_playing(button, player)

            def callback(infobar, response, message):
                if response in (0, 1):
                    gamemodel.players[response].observe()
                return False

            for i, player in enumerate(gamemodel.ficsplayers):
                button = InfoBarMessageButton(_("Observe %s" % player.name), i)
                message.add_button(button)
                gmwidg.cids[player] = player.connect("notify::status",
                                                     status_changed, button)
                status_changed(player, None, button)

    elif gamemodel.hasLocalPlayer():

        def callback(infobar, response, message):
            if response == 1:
                # newGameDialog uses ionest uses gamenanny uses newGameDialog...
                from pychess.widgets.newGameDialog import createRematch
                createRematch(gamemodel)
            elif response == 2:
                if gamemodel.ply > 1:
                    offer = Offer(TAKEBACK_OFFER, gamemodel.ply - 2)
                else:
                    offer = Offer(TAKEBACK_OFFER, gamemodel.ply - 1)
                if gamemodel.players[0].__type__ == LOCAL:
                    gamemodel.players[0].emit("offer", offer)
                else:
                    gamemodel.players[1].emit("offer", offer)
            return False

        if not gamemodel.isLoadedGame():
            message.add_button(InfoBarMessageButton(_("Play Rematch"), 1))
        if gamemodel.status in UNDOABLE_STATES and gamemodel.reason in UNDOABLE_REASONS:
            if gamemodel.ply == 1:
                message.add_button(InfoBarMessageButton(_("Undo one move"), 2))
            elif gamemodel.ply > 1:
                message.add_button(InfoBarMessageButton(
                    _("Undo two moves"), 2))

    message.callback = callback
    gmwidg.game_ended_message = message

    if len(key2gmwidg) > 0:
        gmwidg.replaceMessages(message)
        gmwidg.status("%s %s." % (msg_one, msg_two[0].lower() + msg_two[1:]))

    if reason == WHITE_ENGINE_DIED:
        engineDead(gamemodel.players[0], gmwidg)
    elif reason == BLACK_ENGINE_DIED:
        engineDead(gamemodel.players[1], gmwidg)

    if (isinstance(gamemodel, ICGameModel) and not gamemodel.isObservationGame()) or \
            gamemodel.isEngine2EngineGame():
        gamemodel.restart_analyzer(HINT)
        gamemodel.restart_analyzer(SPY)
        if not conf.get("hint_mode", False):
            gamemodel.pause_analyzer(HINT)
        if not conf.get("spy_mode", False):
            gamemodel.pause_analyzer(SPY)

    return False