Ejemplo n.º 1
0
    def test1(self):
        """ From gbtami (player accepting a challenge) point of view """
        lines = [
            "Challenge: ggbtami (----) gbtami (1708) unrated blitz 5 0.",
            'You can "accept" or "decline", or propose different parameters.',
            "fics% ",
            "<pf> 7 w=ggbtami t=match p=ggbtami (----) gbtami (1708) unrated blitz 5 0",
            "fics% ", BLOCK_START + '52' + BLOCK_SEPARATOR + '11' +
            BLOCK_SEPARATOR, "You accept the match offer from ggbtami."
            "", "", "<pr> 7", "fics% ",
            "Creating: gbtami (1708) ggbtami (++++) unrated blitz 5 0",
            "{Game 107 (gbtami vs. ggbtami) Creating unrated blitz match.}"
            "", "",
            "<12> rnbqkbnr pppppppp -------- -------- -------- -------- PPPPPPPP RNBQKBNR W -1 1 1 1 1 0 107 gbtami ggbtami 1 5 0 39 39 300000 300000 1 none (0:00.000) none 0 0 0",
            ""
            ""
            "Game 107: A disconnection will be considered a forfeit.",
            BLOCK_END, "fics% '"
        ]

        me = self.connection.players.get('gbtami')
        me.ratings[TYPE_BLITZ] = 1708
        opponent = self.connection.players.get('ggbtami')
        opponent.ratings[TYPE_BLITZ] = 0
        game = FICSGame(me,
                        opponent,
                        gameno=107,
                        rated=False,
                        game_type=GAME_TYPES['blitz'],
                        private=False,
                        minutes=5,
                        inc=0,
                        board=FICSBoard(300000, 300000, fen=FEN_START))
        me.game = game
        opponent.game = game
        self.runAndAssertEquals("playGameCreated", lines, (game, ))

        lines = [
            BLOCK_START + '58' + BLOCK_SEPARATOR + '1' + BLOCK_SEPARATOR,
            "<12> rnbqkbnr pppppppp -------- -------- -------- -----P-- PPPPP-PP RNBQKBNR B -1 1 1 1 1 0 107 gbtami ggbtami -1 5 0 39 39 300000 300000 1 P/f2-f3 (0:00.000) f3 0 0 0",
            BLOCK_END, "fics% ",
            "<12> rnbqkbnr pppp-ppp -------- ----p--- -------- -----P-- PPPPP-PP RNBQKBNR W 4 1 1 1 1 0 107 gbtami ggbtami 1 5 0 39 39 300000 300000 2 P/e7-e5 (0:00.000) e5 0 1 0",
            "fics% ",
            BLOCK_START + '61' + BLOCK_SEPARATOR + '1' + BLOCK_SEPARATOR,
            "<12> rnbqkbnr pppp-ppp -------- ----p--- ------P- -----P-- PPPPP--P RNBQKBNR B 6 1 1 1 1 0 107 gbtami ggbtami -1 5 0 39 39 297338 300000 2 P/g2-g4 (0:02.662) g4 0 1 296",
            BLOCK_END, "fics% ",
            "<12> rnb-kbnr pppp-ppp -------- ----p--- ------Pq -----P-- PPPPP--P RNBQKBNR W -1 1 1 1 1 1 107 gbtami ggbtami 1 5 0 39 39 297338 295763 3 Q/d8-h4 (0:04.237) Qh4# 0 1 304",
            "fics% ", "{Game 107 (gbtami vs. ggbtami) gbtami checkmated} 0-1",
            "No ratings adjustment done.", "fics% "
        ]

        game = self.connection.games[game]

        def coro():
            yield from self.connection.process_lines(lines)

        self.loop.run_until_complete(coro())

        self.assertEqual(game.move_queue.qsize(), 4)
        self.assertEqual(game.reason, WON_MATE)
Ejemplo n.º 2
0
    def on_icc_spgn(self, data):
        if self.connection.query_game is None:
            return

        game = self.connection.query_game
        game.board = FICSBoard(0, 0, pgn=data)
        game = self.connection.games.get(game)

        self.emit("archiveGamePreview", game)
Ejemplo n.º 3
0
    def onPlayGameCreated(self, matchlist):
        log.debug(
            "'%s' '%s' '%s'" %
            (matchlist[0].string, matchlist[1].string, matchlist[-1].string),
            extra={"task": (self.connection.username, "BM.onPlayGameCreated")})
        wname, wrating, bname, brating, rated, match_type, minutes, inc = matchlist[
            0].groups()
        item = 2 if self.connection.USCN else 1
        gameno, wname, bname, rated, match_type = matchlist[item].groups()
        gameno = int(gameno)
        wrating = parseRating(wrating)
        brating = parseRating(brating)
        rated = rated == "rated"
        game_type = GAME_TYPES[match_type]

        wplayer = self.connection.players.get(wname)
        bplayer = self.connection.players.get(bname)
        for player, rating in ((wplayer, wrating), (bplayer, brating)):
            if game_type.rating_type in player.ratings and \
                    player.ratings[game_type.rating_type] != rating:
                player.ratings[game_type.rating_type] = rating
                player.emit("ratings_changed", game_type.rating_type, player)

        style12 = matchlist[-1].groups()[0]
        castleSigns = self.generateCastleSigns(style12, game_type)
        self.castleSigns[gameno] = castleSigns
        gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, fen = \
            self.parseStyle12(style12, castleSigns)

        game = FICSGame(wplayer,
                        bplayer,
                        gameno=gameno,
                        rated=rated,
                        game_type=game_type,
                        minutes=int(minutes),
                        inc=int(inc),
                        board=FICSBoard(wms, bms, fen=fen))

        game = self.connection.games.get(game)

        for player in (wplayer, bplayer):
            if player.status != IC_STATUS_PLAYING:
                player.status = IC_STATUS_PLAYING
            if player.game != game:
                player.game = game

        self.theGameImPlaying = game
        self.gamemodelStartedEvents[gameno] = threading.Event()
        self.connection.client.run_command("follow")
        self.emit("playGameCreated", game)
Ejemplo n.º 4
0
    def test3(self):
        """ Accepting a seek """

        loop = asyncio.get_event_loop()
        loop.set_debug(enabled=True)

        widgets = uistuff.GladeWidgets("PyChess.glade")
        gamewidget.setWidgets(widgets)
        perspective_manager.set_widgets(widgets)

        self.welcome_persp = Welcome()
        perspective_manager.add_perspective(self.welcome_persp)

        self.games_persp = Games()
        perspective_manager.add_perspective(self.games_persp)

        self.fics_persp = FICS()
        perspective_manager.add_perspective(self.fics_persp)
        self.fics_persp.create_toolbuttons()

        self.lounge = perspective_manager.get_perspective("fics")
        self.lounge.open_lounge(self.connection, self.connection,
                                "freechess.org")

        lines = [
            "<s> 11 w=WLTL ti=00 rt=2030  t=1 i=0 r=r tp=lightning c=? rr=0-9999 a=t f=f",
            "fics% ",
            BLOCK_START + "52" + BLOCK_SEPARATOR + "158" + BLOCK_SEPARATOR,
            "<sr> 11 16", "fics% ",
            "Creating: WLTL (2030) gbtami (1771) rated lightning 1 0",
            "{Game 85 (WLTL vs. gbtami) Creating rated lightning match.}", "",
            "<12> rnbqkbnr pppppppp -------- -------- -------- -------- PPPPPPPP RNBQKBNR W -1 1 1 1 1 0 85 WLTL gbtami -1 1 0 39 39 60000 60000 1 none (0:00.000) none 1 0 0\n\nGame 85: A disconnection will be considered a forfeit.",
            BLOCK_END, "fics% "
        ]

        me = self.connection.players.get('gbtami')
        me.ratings[TYPE_LIGHTNING] = 1771
        opponent = self.connection.players.get('WLTL')
        opponent.ratings[TYPE_LIGHTNING] = 2030
        game = FICSGame(opponent,
                        me,
                        gameno=85,
                        rated=True,
                        game_type=GAME_TYPES['lightning'],
                        private=False,
                        minutes=1,
                        inc=0,
                        board=FICSBoard(60000, 60000, fen=FEN_START))
        me.game = game
        opponent.game = game
        self.runAndAssertEquals("playGameCreated", lines, (game, ))

        gamemodel = self.games_persp.cur_gmwidg().gamemodel

        def on_game_started(game):
            p1 = gamemodel.players[1]
            p1.move_queue.put_nowait(Move(newMove(G8, F6)))

        gamemodel.connect("game_started", on_game_started)

        lines = [
            "<12> rnbqkbnr pppppppp -------- -------- -------- -P------ P-PPPPPP RNBQKBNR B -1 1 1 1 1 0 85 WLTL gbtami 1 1 0 39 39 60000 60000 1 P/b2-b3 (0:00.000) b3 1 0 0",
            "fics% "
        ]

        game = self.connection.games[game]

        def coro():
            yield from self.connection.process_lines(lines)

        self.loop.run_until_complete(coro())

        self.assertEqual(game.move_queue.qsize(), 0)

        lines = [
            BLOCK_START + "59" + BLOCK_SEPARATOR + "1" + BLOCK_SEPARATOR,
            "<12> rnbqkb-r pppppppp -----n-- -------- -------- -P------ P-PPPPPP RNBQKBNR W -1 1 1 1 1 1 85 WLTL gbtami -1 1 0 39 39 60000 60000 2 N/g8-f6 (0:00.000) Nf6 1 1 0",
            BLOCK_END, "fics% ",
            "<12> rnbqkb-r pppppppp -----n-- -------- -------- -P----P- P-PPPP-P RNBQKBNR B -1 1 1 1 1 0 85 WLTL gbtami 1 1 0 39 39 59900 60000 2 P/g2-g3 (0:00.100) g3 1 1 285",
            "fics% "
        ]

        def coro():
            yield from self.connection.process_lines(lines)

        self.loop.run_until_complete(coro())

        self.assertEqual(game.move_queue.qsize(), 0)
        self.assertEqual(gamemodel.ply, 3)
        print(gamemodel.boards[-1])
Ejemplo n.º 5
0
    def onObserveGameCreated(self, matchlist):
        log.debug("'%s'" % (matchlist[1].string),
                  extra={
                      "task":
                      (self.connection.username, "BM.onObserveGameCreated")
                  })
        if self.connection.USCN:
            # TODO? is this ok?
            game_type = GAME_TYPES["blitz"]
            castleSigns = ("k", "q")
        else:
            gameno, wname, wrating, bname, brating, rated, gametype, minutes, inc = matchlist[
                1].groups()
            wrating = parseRating(wrating)
            brating = parseRating(brating)
            game_type = GAME_TYPES[gametype]

        style12 = matchlist[-1].groups()[0]

        castleSigns = self.generateCastleSigns(style12, game_type)
        gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, fen = \
            self.parseStyle12(style12, castleSigns)
        gameno = int(gameno)
        self.castleSigns[gameno] = castleSigns

        wplayer = self.connection.players.get(wname)
        bplayer = self.connection.players.get(bname)

        if relation == IC_POS_OBSERVING_EXAMINATION:
            pgnHead = [("Event",
                        "FICS %s %s game" % (rated, game_type.fics_name)),
                       ("Site", "freechess.org"), ("White", wname),
                       ("Black", bname), ("Result", "*"), ("SetUp", "1"),
                       ("FEN", fen)]
            pgn = "\n".join(['[%s "%s"]' % line for line in pgnHead]) + "\n*\n"
            game = FICSGame(wplayer,
                            bplayer,
                            gameno=gameno,
                            rated=rated == "rated",
                            game_type=game_type,
                            minutes=int(minutes),
                            inc=int(inc),
                            board=FICSBoard(wms, bms, pgn=pgn),
                            relation=relation)
            game = self.connection.games.get(game)
            self.gamesImObserving[game] = wms, bms

            self.gamemodelStartedEvents[game.gameno] = threading.Event()
            self.emit("obsGameCreated", game)
            self.gamemodelStartedEvents[game.gameno].wait()
        else:
            game = FICSGame(wplayer,
                            bplayer,
                            gameno=gameno,
                            rated=rated == "rated",
                            game_type=game_type,
                            minutes=int(minutes),
                            inc=int(inc),
                            relation=relation)
            game = self.connection.games.get(game, emit=False)

            if not game.supported:
                log.warning("Trying to follow an unsupported type game %s" %
                            game.game_type)
                return

            if game.gameno in self.gamemodelStartedEvents:
                log.warning("%s already in gamemodelstartedevents" %
                            game.gameno)
                return

            self.gamesImObserving[game] = wms, bms
            self.queuedStyle12s[game.gameno] = []
            self.queuedEmits[game.gameno] = []
            self.gamemodelStartedEvents[game.gameno] = threading.Event()

            # FICS doesn't send the move list after 'observe' and 'follow' commands
            self.connection.client.run_command("moves %d" % game.gameno)
Ejemplo n.º 6
0
    def parseGame(self, matchlist, gameclass, in_progress=False, gameno=None):
        """
        Parses the header and movelist for an observed or stored game from its
        matchlist (an re.match object) into a gameclass (FICSGame or subclass
        of) object.

        in_progress - should be True for an observed game matchlist, and False
        for stored/adjourned games
        """
        # ################   observed game movelist example:
        #        Movelist for game 64:
        #
        #        Ajido (2281) vs. IMgooeyjim (2068) --- Thu Oct 14, 20:36 PDT 2010
        #        Rated standard match, initial time: 15 minutes, increment: 3 seconds.
        #
        #        Move  Ajido                   IMgooeyjim
        #        ----  ---------------------   ---------------------
        #          1.  d4      (0:00.000)      Nf6     (0:00.000)
        #          2.  c4      (0:04.061)      g6      (0:00.969)
        #          3.  Nc3     (0:13.280)      Bg7     (0:06.422)
        #              {Still in progress} *
        #
        # #################   stored game example:
        #        BwanaSlei (1137) vs. mgatto (1336) --- Wed Nov  5, 20:56 PST 2008
        #        Rated blitz match, initial time: 5 minutes, increment: 0 seconds.
        #
        #        Move  BwanaSlei               mgatto
        #        ----  ---------------------   ---------------------
        #        1.  e4      (0:00.000)      c5      (0:00.000)
        #        2.  d4      (0:05.750)      cxd4    (0:03.020)
        #        ...
        #        23.  Qxf3    (1:05.500)
        #             {White lost connection; game adjourned} *
        #
        # ################# stored wild/3 game with style12:
        #        kurushi (1626) vs. mgatto (1627) --- Thu Nov  4, 10:33 PDT 2010
        #        Rated wild/3 match, initial time: 3 minutes, increment: 0 seconds.
        #
        #        <12> nqbrknrn pppppppp -------- -------- -------- -------- PPPPPPPP NQBRKNRN W -1 0 0 0 0 0 17 kurushi mgatto -4 3 0 39 39 169403 45227 1 none (0:00.000) none 0 1 0
        #
        #        Move  kurushi                 mgatto
        #        ----  ---------------------   ---------------------
        #          1.  Nb3     (0:00.000)      d5      (0:00.000)
        #          2.  Nhg3    (0:00.386)      e5      (0:03.672)
        #         ...
        #         28.  Rxd5    (0:00.412)
        #              {Black lost connection; game adjourned} *
        #
        # #################  stored game movelist following stored game(s):
        #        Stored games for mgatto:
        #        C Opponent       On Type          Str  M    ECO Date
        #        1: W BabyLurking     Y [ br  5   0] 29-13 W27  D37 Fri Nov  5, 04:41 PDT 2010
        #        2: W gbtami          N [ wr  5   0] 32-34 W14  --- Thu Oct 21, 00:14 PDT 2010
        #
        #        mgatto (1233) vs. BabyLurking (1455) --- Fri Nov  5, 04:33 PDT 2010
        #        Rated blitz match, initial time: 5 minutes, increment: 0 seconds.
        #
        #        Move  mgatto             BabyLurking
        #        ----  ----------------   ----------------
        #        1.  Nf3     (0:00)     d5      (0:00)
        #        2.  d4      (0:03)     Nf6     (0:00)
        #        3.  c4      (0:03)     e6      (0:00)
        #        {White lost connection; game adjourned} *
        #
        # ################## stored game movelist following stored game(s):
        # ##   Note: A wild stored game in this format won't be parseable into a board because
        # ##   it doesn't come with a style12 that has the start position, so we warn and return
        # ##################
        #        Stored games for mgatto:
        #        C Opponent       On Type          Str  M    ECO Date
        #        1: W gbtami          N [ wr  5   0] 32-34 W14  --- Thu Oct 21, 00:14 PDT 2010
        #
        #        mgatto (1627) vs. gbtami (1881) --- Thu Oct 21, 00:10 PDT 2010
        #        Rated wild/fr match, initial time: 5 minutes, increment: 0 seconds.
        #
        #        Move  mgatto             gbtami
        #        ----  ----------------   ----------------
        #        1.  d4      (0:00)     b6      (0:00)
        #        2.  b3      (0:06)     d5      (0:03)
        #        3.  c4      (0:08)     e6      (0:03)
        #        4.  e3      (0:04)     dxc4    (0:02)
        #        5.  bxc4    (0:02)     g6      (0:09)
        #        6.  Nd3     (0:12)     Bg7     (0:02)
        #        7.  Nc3     (0:10)     Ne7     (0:03)
        #        8.  Be2     (0:08)     c5      (0:05)
        #        9.  a4      (0:07)     cxd4    (0:38)
        #        10.  exd4    (0:06)     Bxd4    (0:03)
        #        11.  O-O     (0:10)     Qc6     (0:06)
        #        12.  Bf3     (0:16)     Qxc4    (0:04)
        #        13.  Bxa8    (0:03)     Rxa8    (0:14)
        #        {White lost connection; game adjourned} *
        #
        # #################   other reasons the game could be stored/adjourned:
        #        Game courtesyadjourned by (Black|White)
        #        Still in progress                    # This one must be a FICS bug
        #        Game adjourned by mutual agreement
        #        (White|Black) lost connection; game adjourned
        #        Game adjourned by ((server shutdown)|(adjudication)|(simul holder))

        index = 0
        if in_progress:
            gameno = int(matchlist[index].groups()[0])
            index += 2
        header1 = matchlist[index] if isinstance(matchlist[index], str) \
            else matchlist[index].group()

        matches = moveListHeader1.match(header1).groups()
        wname, wrating, bname, brating = matches[:4]
        if self.connection.FatICS:
            year, month, day, hour, minute, timezone = matches[11:]
        else:
            weekday, month, day, hour, minute, timezone, year = matches[4:11]
            month = months.index(month) + 1

        wrating = parseRating(wrating)
        brating = parseRating(brating)
        rated, game_type, minutes, increment = \
            moveListHeader2.match(matchlist[index + 1]).groups()
        minutes = int(minutes)
        increment = int(increment)
        game_type = GAME_TYPES[game_type]

        reason = matchlist[-1].group().lower()
        if in_progress:
            result = None
            result_str = "*"
        elif "1-0" in reason:
            result = WHITEWON
            result_str = "1-0"
        elif "0-1" in reason:
            result = BLACKWON
            result_str = "0-1"
        elif "1/2-1/2" in reason:
            result = DRAW
            result_str = "1/2-1/2"
        else:
            result = ADJOURNED
            result_str = "*"
        result, reason = parse_reason(result, reason, wname=wname)

        index += 3
        if matchlist[index].startswith("<12>"):
            style12 = matchlist[index][5:]
            castleSigns = self.generateCastleSigns(style12, game_type)
            gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, \
                fen = self.parseStyle12(style12, castleSigns)
            initialfen = fen
            movesstart = index + 4
        else:
            if game_type.rating_type == TYPE_WILD:
                # we need a style12 start position to correctly parse a wild/* board
                log.error("BoardManager.parseGame: no style12 for %s board." %
                          game_type.fics_name)
                return None
            castleSigns = ("k", "q")
            initialfen = None
            movesstart = index + 2

        if in_progress:
            self.castleSigns[gameno] = castleSigns

        moves = {}
        times = {}
        wms = bms = minutes * 60 * 1000

        for line in matchlist[movesstart:-1]:
            if not moveListMoves.match(line):
                log.error("BoardManager.parseGame: unmatched line: \"%s\"" %
                          repr(line))
                raise Exception(
                    "BoardManager.parseGame: unmatched line: \"%s\"" %
                    repr(line))
            moveno, wmove, whour, wmin, wsec, wmsec, bmove, bhour, bmin, bsec, bmsec = \
                moveListMoves.match(line).groups()
            whour = 0 if whour is None else int(whour[0])
            bhour = 0 if bhour is None else int(bhour[0])
            ply = int(moveno) * 2 - 2
            if wmove:
                moves[ply] = wmove
                wms -= (int(whour) * 60 * 60 *
                        1000) + (int(wmin) * 60 * 1000) + (int(wsec) * 1000)
                if wmsec is not None:
                    wms -= int(wmsec)
                else:
                    wmsec = 0
                if increment > 0:
                    wms += (increment * 1000)
                times[ply] = "%01d:%02d:%02d.%03d" % (int(whour), int(wmin),
                                                      int(wsec), int(wmsec))
            if bmove:
                moves[ply + 1] = bmove
                bms -= (int(bhour) * 60 * 60 *
                        1000) + (int(bmin) * 60 * 1000) + (int(bsec) * 1000)
                if bmsec is not None:
                    bms -= int(bmsec)
                else:
                    bmsec = 0
                if increment > 0:
                    bms += (increment * 1000)
                times[ply +
                      1] = "%01d:%02d:%02d.%03d" % (int(bhour), int(bmin),
                                                    int(bsec), int(bmsec))

        if in_progress and gameno in self.queuedStyle12s:
            # Apply queued board updates
            for style12 in self.queuedStyle12s[gameno]:
                gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, fen = \
                    self.parseStyle12(style12, castleSigns)
                if lastmove is None:
                    continue
                moves[ply - 1] = lastmove
                # Updated the queuedMoves in case there has been a takeback
                for moveply in list(moves.keys()):
                    if moveply > ply - 1:
                        del moves[moveply]
            del self.queuedStyle12s[gameno]

        pgnHead = [
            ("Event",
             "FICS %s %s game" % (rated.lower(), game_type.fics_name)),
            ("Site", "freechess.org"),
            ("White", wname),
            ("Black", bname),
            ("TimeControl", "%d+%d" % (minutes * 60, increment)),
            ("Result", result_str),
            ("WhiteClock", msToClockTimeTag(wms)),
            ("BlackClock", msToClockTimeTag(bms)),
        ]
        if wrating != 0:
            pgnHead += [("WhiteElo", wrating)]
        if brating != 0:
            pgnHead += [("BlackElo", brating)]
        if year and month and day and hour and minute:
            pgnHead += [
                ("Date", "%04d.%02d.%02d" % (int(year), int(month), int(day))),
                ("Time", "%02d:%02d:00" % (int(hour), int(minute))),
            ]
        if initialfen:
            pgnHead += [("SetUp", "1"), ("FEN", initialfen)]
        if game_type.variant_type == FISCHERRANDOMCHESS:
            pgnHead += [("Variant", "Fischerandom")]
            # FR is the only variant used in this tag by the PGN generator @
            # ficsgames.org. They put all the other wild/* stuff only in the
            # "Event" header.
        elif game_type.variant_type == CRAZYHOUSECHESS:
            pgnHead += [("Variant", "Crazyhouse")]
        elif game_type.variant_type in (WILDCASTLECHESS,
                                        WILDCASTLESHUFFLECHESS):
            pgnHead += [("Variant", "Wildcastle")]
        elif game_type.variant_type == ATOMICCHESS:
            pgnHead += [("Variant", "Atomic")]
        elif game_type.variant_type == LOSERSCHESS:
            pgnHead += [("Variant", "Losers")]
        elif game_type.variant_type == SUICIDECHESS:
            pgnHead += [("Variant", "Suicide")]
        pgn = "\n".join(['[%s "%s"]' % line for line in pgnHead]) + "\n"

        moves = sorted(moves.items())
        for ply, move in moves:
            if ply % 2 == 0:
                pgn += "%d. " % (ply // 2 + 1)
            time = times[ply]
            pgn += "%s {[%%emt %s]} " % (move, time)
        pgn += "*\n"

        wplayer = self.connection.players.get(wname)
        bplayer = self.connection.players.get(bname)
        for player, rating in ((wplayer, wrating), (bplayer, brating)):
            if game_type.rating_type in player.ratings and \
                    player.ratings[game_type.rating_type] != rating:
                player.ratings[game_type.rating_type] = rating
                player.emit("ratings_changed", game_type.rating_type, player)
        game = gameclass(wplayer,
                         bplayer,
                         game_type=game_type,
                         result=result,
                         rated=(rated.lower() == "rated"),
                         minutes=minutes,
                         inc=increment,
                         board=FICSBoard(wms, bms, pgn=pgn))

        if in_progress:
            game.gameno = gameno
        else:
            if gameno is not None:
                game.gameno = gameno
            game.reason = reason
        game = self.connection.games.get(game, emit=False)

        return game
Ejemplo n.º 7
0
    def onStyle12(self, match):
        style12 = match.groups()[0]
        gameno = int(style12.split()[15])
        if gameno in self.queuedStyle12s:
            self.queuedStyle12s[gameno].append(style12)
            return

        try:
            self.gamemodelStartedEvents[gameno].wait()
        except KeyError:
            pass

        if gameno in self.castleSigns:
            castleSigns = self.castleSigns[gameno]
        else:
            castleSigns = ("k", "q")
        gameno, relation, curcol, ply, wname, bname, wms, bms, gain, lastmove, fen = \
            self.parseStyle12(style12, castleSigns)

        # examine starts with a <12> line only
        if lastmove is None and relation == IC_POS_EXAMINATING:
            pgnHead = [("Event", "FICS examined game"),
                       ("Site", "freechess.org"), ("White", wname),
                       ("Black", bname), ("Result", "*"), ("SetUp", "1"),
                       ("FEN", fen)]
            pgn = "\n".join(['[%s "%s"]' % line for line in pgnHead]) + "\n*\n"
            wplayer = self.connection.players.get(wname)
            bplayer = self.connection.players.get(bname)

            # examine from console or got mexamine in observed game
            if self.connection.examined_game is None:
                no_smoves = True
                game = FICSGame(wplayer,
                                bplayer,
                                gameno=int(gameno),
                                game_type=GAME_TYPES["examined"],
                                minutes=0,
                                inc=0,
                                board=FICSBoard(0, 0, pgn=pgn),
                                relation=relation)
                self.connection.examined_game = game
            else:
                # examine an archived game from GUI
                no_smoves = False
                game = self.connection.examined_game
                game.gameno = int(gameno)
                game.relation = relation
                # game.game_type = GAME_TYPES["examined"]
            game = self.connection.games.get(game)

            # don't start new game in puzzlebot/endgamebot when they just reuse gameno
            if game.relation == IC_POS_OBSERVING_EXAMINATION or \
                    (game.board is not None and game.board.pgn == pgn):
                self.emit("boardUpdate", gameno, ply, curcol, lastmove, fen,
                          wname, bname, wms, bms)
                return

            game.relation = relation
            game.board = FICSBoard(0, 0, pgn=pgn)
            self.gamesImObserving[game] = wms, bms

            # start a new game now or after smoves
            self.gamemodelStartedEvents[game.gameno] = threading.Event()
            if no_smoves:
                self.emit("exGameCreated", game)
                self.gamemodelStartedEvents[game.gameno].wait()
            else:
                if isinstance(game, FICSHistoryGame):
                    self.connection.client.run_command(
                        "smoves %s %s" %
                        (self.connection.history_owner, game.history_no))
                elif isinstance(game, FICSJournalGame):
                    self.connection.client.run_command(
                        "smoves %s %%%s" %
                        (self.connection.journal_owner, game.journal_no))
                elif isinstance(game, FICSAdjournedGame):
                    self.connection.client.run_command(
                        "smoves %s %s" %
                        (self.connection.stored_owner, game.opponent.name))
                self.connection.client.run_command("forward 999")
        else:
            self.emit("boardUpdate", gameno, ply, curcol, lastmove, fen, wname,
                      bname, wms, bms)
Ejemplo n.º 8
0
    def on_icc_send_moves(self, data):
        log.debug("DG_SEND_MOVES %s" % data)
        # gamenumber algebraic-move smith-move time clock
        send_moves = data
        gameno, san_move, alg_move, time, clock = send_moves.split()
        gameno = int(gameno)

        try:
            game = self.connection.games.get_game_by_gameno(gameno)
        except KeyError:
            log.debug("Game %s is not in self.connection.games" % gameno)
            return

        fen = ""

        if game == self.theGameImPlaying:
            curcol, ply, wms, bms = self.my_game_info
        else:
            curcol, ply, wms, bms = self.gamesImObserving[game]

        if curcol == WHITE:
            wms = int(clock) * 1000
        else:
            bms = int(clock) * 1000

        ply += 1
        curcol = 1 - curcol

        if game == self.theGameImPlaying:
            self.my_game_info = (curcol, ply, wms, bms)
        else:
            self.gamesImObserving[game] = (curcol, ply, wms, bms)

        if gameno in self.queued_send_moves:
            self.queued_send_moves[gameno].append(send_moves)
            if self.moves_to_go and len(
                    self.queued_send_moves[gameno]) < self.moves_to_go:
                return

        if self.moves_to_go == 0 or self.moves_to_go is None:
            log.debug("put san_move to move_queue %s" % san_move)
            game.move_queue.put_nowait(
                (gameno, ply, curcol, san_move, fen, game.wplayer.name,
                 game.bplayer.name, wms, bms))
            self.emit("timesUpdate", gameno, wms, bms)
        else:
            if game.gameno not in self.gamemodelStartedEvents:
                return
            if game.gameno not in self.queuedEmits:
                return

            pgnHead = [
                ("Event", "ICC %s %s game" %
                 (game.display_rated.lower(), game.game_type.fics_name)),
                ("Site", "chessclub.com"),
                ("White", game.wplayer.name),
                ("Black", game.bplayer.name),
                ("Result", "*"),
                ("TimeControl", "%d+%d" % (game.minutes * 60, game.inc)),
            ]
            wrating = game.wplayer.ratings[game.game_type.rating_type]
            brating = game.bplayer.ratings[game.game_type.rating_type]
            if wrating != 0:
                pgnHead += [("WhiteElo", wrating)]
            if brating != 0:
                pgnHead += [("BlackElo", brating)]

            pgn = "\n".join(['[%s "%s"]' % line for line in pgnHead]) + "\n"

            moves = self.queued_send_moves[gameno]
            ply = 0
            for send_moves in moves:
                gameno_, san_move, alg_move, time, clock = send_moves.split()
                if ply % 2 == 0:
                    pgn += "%d. " % (ply // 2 + 1)
                pgn += "%s {[%%emt %s]} " % (san_move, time)
                ply += 1
            pgn += "*\n"
            del self.queued_send_moves[gameno]
            self.moves_to_go = None

            wms = bms = 0
            game = FICSGame(game.wplayer,
                            game.bplayer,
                            game_type=game.game_type,
                            result=game.result,
                            rated=game.rated,
                            minutes=game.minutes,
                            inc=game.inc,
                            board=FICSBoard(wms, bms, pgn=pgn))
            in_progress = True
            if in_progress:
                game.gameno = gameno
            else:
                if gameno is not None:
                    game.gameno = gameno
                # game.reason = reason
            game = self.connection.games.get(game, emit=False)

            self.emit("obsGameCreated", game)
            try:
                self.gamemodelStartedEvents[game.gameno].wait()
            except KeyError:
                pass

            for emit in self.queuedEmits[game.gameno]:
                emit()
            del self.queuedEmits[game.gameno]

            curcol, ply, wms, bms = self.gamesImObserving[game]
            self.emit("timesUpdate", game.gameno, wms, bms)
Ejemplo n.º 9
0
    def on_icc_my_game_started(self, data):
        log.debug("DG_MY_GAME_STARTED %s" % data)
        # gamenumber whitename blackname wild-number rating-type rated
        # white-initial white-increment black-initial black-increment
        # played-game {ex-string} white-rating black-rating game-id
        # white-titles black-titles irregular-legality irregular-semantics
        # uses-plunkers fancy-timecontrol promote-to-king
        # 685 Salsicha MaxiBomb 0 Blitz 1 3 0 3 0 1 {} 2147 2197 1729752694 {} {} 0 0 0 {} 0
        # 259 Rikikilord ARMH 0 Blitz 1 2 12 2 12 0 {Ex: Rikikilord 0} 1532 1406 1729752286 {} {} 0 0 0 {} 0
        gameno, wname, bname, wild, rtype, rated, wmin, winc, bmin, binc, played_game, rest = data.split(
            " ", 11)

        parts = rest.split("}", 1)[1].split()
        wrating = int(parts[0])
        brating = int(parts[1])

        gameno = int(gameno)
        wplayer = self.connection.players.get(wname)
        bplayer = self.connection.players.get(bname)
        if int(wild) > 0:
            game_type = GAME_TYPES["w%s" % wild]
        else:
            game_type = GAME_TYPES[rtype.lower()]
        log.debug("DG_MY_GAME_STARTED game type is %s" % game_type)
        for player, rating in ((wplayer, wrating), (bplayer, brating)):
            try:
                if player.ratings[game_type.rating_type] != rating:
                    player.ratings[game_type.rating_type] = rating
                    player.emit("ratings_changed", game_type.rating_type,
                                player)
            except IndexError:
                log.debug(
                    "!!! game_type.rating_type %s is out of range in player.ratings %s"
                    % (game_type.rating_type, player.ratings))

        wms = bms = int(wmin) * 60 * 1000 + int(winc) * 1000
        # TODO: maybe use DG_POSITION_BEGIN2 and DG_PAST_MOVE ?
        fen = FEN_START

        game = FICSGame(wplayer,
                        bplayer,
                        gameno=gameno,
                        rated=rated == "1",
                        game_type=game_type,
                        minutes=int(wmin),
                        inc=int(winc),
                        board=FICSBoard(wms, bms, fen=fen))

        if self.connection.examined_game is not None:
            pgnHead = [("Event", "ICC examined game"),
                       ("Site", "chessclub.com"), ("White", wname),
                       ("Black", bname), ("Result", "*"), ("SetUp", "1"),
                       ("FEN", fen)]
            pgn = "\n".join(['[%s "%s"]' % line for line in pgnHead]) + "\n*\n"

            game.relation = IC_POS_EXAMINATING
            game.game_type = GAME_TYPES["examined"]
            game.board.pgn = pgn

        game = self.connection.games.get(game)

        for player in (wplayer, bplayer):
            if player.status != IC_STATUS_PLAYING:
                player.status = IC_STATUS_PLAYING
            if player.game != game:
                player.game = game

        self.theGameImPlaying = game
        self.my_game_info = (WHITE, 0, wms, bms)
        self.gamemodelStartedEvents[gameno] = asyncio.Event()
        self.connection.client.run_command("follow")

        if self.connection.examined_game is not None:
            self.emit("exGameCreated", game)
        else:
            if int(wild) in (1, 2, 3, 4, 20, 21, 22):
                # several wild variant (including loadfen/loadgame) need
                # a starting FEN coming in a DG_POSITION_BEGIN datgram
                log.debug("wild20 is waiting for a starting FEN...")
            else:
                self.emit("playGameCreated", game)