Exemple #1
0
    def on_game_remove(self, match):
        gameno, wname, bname, comment, result = match.groups()
        result, reason = parse_reason(reprResult.index(result),
                                      comment,
                                      wname=wname)

        wplayer = FICSPlayer(wname)
        try:
            wplayer = self.connection.players.get(wplayer, create=False)
            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:
            pass
        bplayer = FICSPlayer(bname)
        try:
            bplayer = self.connection.players.get(bplayer, create=False)
            bplayer.restore_previous_status()
        except KeyError:
            pass

        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
Exemple #2
0
    def build_where_tags(self, tag_query):
        if tag_query is not None:
            tags = []
            if "white" in tag_query:
                if "ignore_tag_colors" in tag_query:
                    tags.append(
                        or_(pl1.c.name.startswith(tag_query["white"]),
                            pl2.c.name.startswith(tag_query["white"])))
                else:
                    tags.append(pl1.c.name.startswith(tag_query["white"]))

            if "black" in tag_query:
                if "ignore_tag_colors" in tag_query:
                    tags.append(
                        or_(pl1.c.name.startswith(tag_query["black"]),
                            pl2.c.name.startswith(tag_query["black"])))
                else:
                    tags.append(pl2.c.name.startswith(tag_query["black"]))

            if "event" in tag_query:
                tags.append(event.c.name.startswith(tag_query["event"])),

            if "site" in tag_query:
                tags.append(site.c.name.startswith(tag_query["site"])),

            if "eco_from" in tag_query:
                tags.append(game.c.eco >= tag_query["eco_from"])

            if "eco_to" in tag_query:
                tags.append(game.c.eco <= tag_query["eco_to"])

            if "annotator" in tag_query:
                tags.append(annotator.c.name.startswith(
                    tag_query["annotator"])),

            if "variant" in tag_query:
                tags.append(game.c.variant == int(tag_query["variant"])),

            if "result" in tag_query:
                tags.append(
                    game.c.result == reprResult.index(tag_query["result"])),

            if "year_from" in tag_query:
                tags.append(game.c.date_year >= tag_query["year_from"])

            if "year_to" in tag_query:
                tags.append(game.c.date_year <= tag_query["year_to"])

            if "elo_from" in tag_query:
                tags.append(game.c.white_elo >= tag_query["elo_from"])
                tags.append(game.c.black_elo >= tag_query["elo_from"])

            if "elo_to" in tag_query:
                tags.append(game.c.white_elo <= tag_query["elo_to"])
                tags.append(game.c.black_elo <= tag_query["elo_to"])

            self.where_tags = and_(*tags)
        else:
            self.where_tags = None
Exemple #3
0
    def build_where_tags(self, tag_query):
        if tag_query is not None:
            tags = []
            if "white" in tag_query:
                if "ignore_tag_colors" in tag_query:
                    tags.append(or_(pl1.c.name.startswith(tag_query["white"]),
                                    pl2.c.name.startswith(tag_query["white"])))
                else:
                    tags.append(pl1.c.name.startswith(tag_query["white"]))

            if "black" in tag_query:
                if "ignore_tag_colors" in tag_query:
                    tags.append(or_(pl1.c.name.startswith(tag_query["black"]),
                                    pl2.c.name.startswith(tag_query["black"])))
                else:
                    tags.append(pl2.c.name.startswith(tag_query["black"]))

            if "event" in tag_query:
                tags.append(event.c.name.startswith(tag_query["event"])),

            if "site" in tag_query:
                tags.append(site.c.name.startswith(tag_query["site"])),

            if "eco_from" in tag_query:
                tags.append(game.c.eco >= tag_query["eco_from"])

            if "eco_to" in tag_query:
                tags.append(game.c.eco <= tag_query["eco_to"])

            if "annotator" in tag_query:
                tags.append(annotator.c.name.startswith(tag_query["annotator"])),

            if "result" in tag_query:
                tags.append(game.c.result == reprResult.index(tag_query["result"])),

            if "year_from" in tag_query:
                tags.append(game.c.date_year >= tag_query["year_from"])

            if "year_to" in tag_query:
                tags.append(game.c.date_year <= tag_query["year_to"])

            if "elo_from" in tag_query:
                tags.append(game.c.white_elo >= tag_query["elo_from"])
                tags.append(game.c.black_elo >= tag_query["elo_from"])

            if "elo_to" in tag_query:
                tags.append(game.c.white_elo <= tag_query["elo_to"])
                tags.append(game.c.black_elo <= tag_query["elo_to"])

            self.where_tags = and_(*tags)
        else:
            self.where_tags = None
    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
Exemple #5
0
    def on_icc_my_game_result(self, 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:
            print("%s not in self.connections.players - creating" % wname)
            wplayer = FICSPlayer(wname)

        try:
            bplayer = self.connection.players.get(bname)
            bplayer.restore_previous_status()
        except KeyError:
            print("%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 __onJournalResponseYES(self, matchlist):
        # Journal for User:
        #     White         Rating  Black         Rating  Type         ECO End Result
        # %01: tentacle      2291    larsa         2050    [ lr  1   2] D35 Rep 1/2-1/2
        # %02: larsa         2045    tentacle      2296    [ lr  1   2] A46 Res 0-1
        journal = []
        self.connection.journal_owner = matchlist[0].groups()[0]
        for match in matchlist[2:]:
            # print(match.groups())
            journal_no = match.groups()[0]
            result = match.groups()[10]
            result = reprResult.index(result)
            white = match.groups()[1]
            wrating = match.groups()[2]
            black = match.groups()[3]
            brating = match.groups()[4]
            game_type = match.groups()[5]
            minutes, gain = match.groups()[6:8]
            reason = reasons_dict[match.groups()[9]]
            private = game_type[0] == "p"
            rated = game_type[2] == "r"
            gametype = GAME_TYPES_BY_SHORT_FICS_NAME[game_type[1]]
            minutes = int(minutes)
            gain = int(gain)

            wplayer = self.connection.players.get(
                FICSPlayer(white,
                           status=IC_STATUS_OFFLINE))
            bplayer = self.connection.players.get(
                FICSPlayer(black,
                           status=IC_STATUS_OFFLINE))
            game = FICSJournalGame(wplayer,
                                   bplayer,
                                   game_type=gametype,
                                   rated=rated,
                                   minutes=minutes,
                                   inc=gain,
                                   private=private,
                                   wrating=wrating,
                                   brating=brating,
                                   reason=reason,
                                   journal_no=journal_no,
                                   result=result)

            if game not in self.connection.games:
                game = self.connection.games.get(game, emit=False)
                self.emit("journalGameAdded", game)
            journal.append(game)

        self.emit("onJournalList", journal)
Exemple #7
0
    def on_game_remove(self, match):
        gameno, wname, bname, comment, result = match.groups()
        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:
            print("%s not in self.connections.players - creating" % wname)
            wplayer = FICSPlayer(wname)

        try:
            bplayer = self.connection.players.get(bname)
            bplayer.restore_previous_status()
        except KeyError:
            print("%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)

        # Our played/observed game ends are handled in main connection to prevent
        # removing them by helper connection before latest move(style12) comes from server
        if game == self.connection.bm.theGameImPlaying or \
           game in self.connection.bm.gamesImObserving:
            return

        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 on_game_remove(self, match):
        gameno, wname, bname, comment, result = match.groups()
        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:
            print("%s not in self.connections.players - creating" % wname)
            wplayer = FICSPlayer(wname)

        try:
            bplayer = self.connection.players.get(bname)
            bplayer.restore_previous_status()
        except KeyError:
            print("%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)

        # Our played/observed game ends are handled in main connection to prevent
        # removing them by helper connection before latest move(style12) comes from server
        if game == self.connection.bm.theGameImPlaying or \
           game in self.connection.bm.gamesImObserving:
            return

        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
Exemple #9
0
    def on_game_remove(self, match):
        gameno, wname, bname, comment, result = match.groups()
        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:
            print("%s not in self.connections.players - creating" % wname)
            wplayer = FICSPlayer(wname)

        try:
            bplayer = self.connection.players.get(bname)
            bplayer.restore_previous_status()
        except KeyError:
            print("%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
Exemple #10
0
    def build_where_tags(self, tag_query):
        if tag_query is not None:
            tags = []
            if "white" in tag_query:
                if "ignore_tag_colors" in tag_query:
                    tags.append(
                        or_(pl1.c.name.like("%%%s%%" % tag_query["white"]),
                            pl2.c.name.like("%%%s%%" % tag_query["white"])))
                else:
                    tags.append(pl1.c.name.like("%%%s%%" % tag_query["white"]))

            if "black" in tag_query:
                if "ignore_tag_colors" in tag_query:
                    tags.append(
                        or_(pl1.c.name.like("%%%s%%" % tag_query["black"]),
                            pl2.c.name.like("%%%s%%" % tag_query["black"])))
                else:
                    tags.append(pl2.c.name.like("%%%s%%" % tag_query["black"]))

            if "event" in tag_query:
                tags.append(event.c.name.like("%%%s%%" % tag_query["event"])),

            if "site" in tag_query:
                tags.append(site.c.name.like("%%%s%%" % tag_query["site"])),

            if "eco_from" in tag_query:
                tags.append(game.c.eco >= tag_query["eco_from"])

            if "eco_to" in tag_query:
                tags.append(game.c.eco <= tag_query["eco_to"])

            if "annotator" in tag_query:
                tags.append(
                    annotator.c.name.like("%%%s%%" % tag_query["annotator"])),

            if "variant" in tag_query:
                tags.append(game.c.variant == int(tag_query["variant"])),

            if "result" in tag_query:
                tags.append(
                    game.c.result == reprResult.index(tag_query["result"])),

            if "date_from" in tag_query:
                tags.append(game.c.date >= tag_query["date_from"])

            if "date_to" in tag_query:
                # When date_to is not given as full date we have to prepare
                # date_to filled with some "?" to get correct query results
                # because for example "2018.??.??" is greater than "2018"
                date_to = tag_query["date_to"]
                y, m, d = parseDateTag(date_to)
                y = "%04d" % y if y is not None else "????"
                m = "%02d" % m if m is not None else "??"
                d = "%02d" % d if d is not None else "??"
                date_to = "%s.%s.%s" % (y, m, d)

                tags.append(game.c.date <= date_to)

            if "elo_from" in tag_query:
                tags.append(game.c.white_elo >= tag_query["elo_from"])
                tags.append(game.c.black_elo >= tag_query["elo_from"])

            if "elo_to" in tag_query:
                tags.append(game.c.white_elo <= tag_query["elo_to"])
                tags.append(game.c.black_elo <= tag_query["elo_to"])

            self.where_tags = and_(*tags)
        else:
            self.where_tags = None
Exemple #11
0
    def build_where_tags(self, tag_query):
        if tag_query is not None:
            tags = []
            if "white" in tag_query:
                if "ignore_tag_colors" in tag_query:
                    tags.append(or_(pl1.c.name.like("%%%s%%" % tag_query["white"]),
                                    pl2.c.name.like("%%%s%%" % tag_query["white"])))
                else:
                    tags.append(pl1.c.name.like("%%%s%%" % tag_query["white"]))

            if "black" in tag_query:
                if "ignore_tag_colors" in tag_query:
                    tags.append(or_(pl1.c.name.like("%%%s%%" % tag_query["black"]),
                                    pl2.c.name.like("%%%s%%" % tag_query["black"])))
                else:
                    tags.append(pl2.c.name.like("%%%s%%" % tag_query["black"]))

            if "event" in tag_query:
                tags.append(event.c.name.like("%%%s%%" % tag_query["event"])),

            if "site" in tag_query:
                tags.append(site.c.name.like("%%%s%%" % tag_query["site"])),

            if "eco_from" in tag_query:
                tags.append(game.c.eco >= tag_query["eco_from"])

            if "eco_to" in tag_query:
                tags.append(game.c.eco <= tag_query["eco_to"])

            if "annotator" in tag_query:
                tags.append(annotator.c.name.like("%%%s%%" % tag_query["annotator"])),

            if "variant" in tag_query:
                tags.append(game.c.variant == int(tag_query["variant"])),

            if "result" in tag_query:
                tags.append(game.c.result == reprResult.index(tag_query["result"])),

            if "date_from" in tag_query:
                tags.append(game.c.date >= tag_query["date_from"])

            if "date_to" in tag_query:
                # When date_to is not given as full date we have to prepare
                # date_to filled with some "?" to get correct query results
                # because for example "2018.??.??" is greater than "2018"
                date_to = tag_query["date_to"]
                y, m, d = parseDateTag(date_to)
                y = "%04d" % y if y is not None else "????"
                m = "%02d" % m if m is not None else "??"
                d = "%02d" % d if d is not None else "??"
                date_to = "%s.%s.%s" % (y, m, d)

                tags.append(game.c.date <= date_to)

            if "elo_from" in tag_query:
                tags.append(game.c.white_elo >= tag_query["elo_from"])
                tags.append(game.c.black_elo >= tag_query["elo_from"])

                # white_elo and black_elo are String(4) in game table
                # we need to prevent selecting games where a player elo is 999 or 400
                # when tag_query["elo_from"] is for example was set to 2200
                tags.append(game.c.white_elo < "4")
                tags.append(game.c.black_elo < "4")

            if "elo_to" in tag_query:
                tags.append(game.c.white_elo <= tag_query["elo_to"])
                tags.append(game.c.black_elo <= tag_query["elo_to"])

            self.where_tags = and_(*tags)
        else:
            self.where_tags = None
Exemple #12
0
    def parse_string(self, string, board, position, variation=False):
        """Recursive parses a movelist part of one game.

           Arguments:
           srting - str (movelist)
           board - lboard (initial position)
           position - int (maximum ply to parse)
           variation- boolean (True if the string is a variation)"""

        boards = []
        boards_append = boards.append

        last_board = board
        if variation:
            # this board used only to hold initial variation comments
            boards_append(LBoard(board.variant))
        else:
            # initial game board
            boards_append(board)

        status = None
        parenthesis = 0
        v_string = ""
        for m in re.finditer(pattern, string):
            group, text = m.lastindex, m.group(m.lastindex)
            if parenthesis > 0:
                v_string += ' ' + text

            if group == VARIATION_END:
                parenthesis -= 1
                if parenthesis == 0:
                    v_last_board.children.append(
                        self.parse_string(v_string[:-1],
                                          last_board.prev,
                                          position,
                                          variation=True))
                    v_string = ""
                    continue

            elif group == VARIATION_START:
                parenthesis += 1
                if parenthesis == 1:
                    v_last_board = last_board

            if parenthesis == 0:
                if group == FULL_MOVE:
                    if not variation:
                        if position != -1 and last_board.plyCount >= position:
                            break

                    mstr = m.group(MOVE)
                    try:
                        lmove = parseSAN(last_board, mstr)
                    except ParsingError as err:
                        # TODO: save the rest as comment
                        # last_board.children.append(string[m.start():])
                        notation, reason, boardfen = err.args
                        ply = last_board.plyCount
                        if ply % 2 == 0:
                            moveno = "%d." % (ply // 2 + 1)
                        else:
                            moveno = "%d..." % (ply // 2 + 1)
                        errstr1 = _(
                            "The game can't be read to end, because of an error parsing move %(moveno)s '%(notation)s'."
                        ) % {
                            'moveno': moveno,
                            'notation': notation
                        }
                        errstr2 = _("The move failed because %s.") % reason
                        self.error = LoadingError(errstr1, errstr2)
                        break
                    except:
                        ply = last_board.plyCount
                        if ply % 2 == 0:
                            moveno = "%d." % (ply // 2 + 1)
                        else:
                            moveno = "%d..." % (ply // 2 + 1)
                        errstr1 = _(
                            "Error parsing move %(moveno)s %(mstr)s") % {
                                "moveno": moveno,
                                "mstr": mstr
                            }
                        self.error = LoadingError(errstr1, "")
                        break

                    new_board = last_board.clone()
                    new_board.applyMove(lmove)

                    if m.group(MOVE_COMMENT):
                        new_board.nags.append(symbol2nag(
                            m.group(MOVE_COMMENT)))

                    new_board.prev = last_board

                    # set last_board next, except starting a new variation
                    if variation and last_board == board:
                        boards[0].next = new_board
                    else:
                        last_board.next = new_board

                    boards_append(new_board)
                    last_board = new_board

                elif group == COMMENT_REST:
                    last_board.children.append(text[1:])

                elif group == COMMENT_BRACE:
                    comm = text.replace('{\r\n', '{').replace('\r\n}', '}')
                    comm = comm[1:-1].splitlines()
                    comment = ' '.join([line.strip() for line in comm])
                    if variation and last_board == board:
                        # initial variation comment
                        boards[0].children.append(comment)
                    else:
                        last_board.children.append(comment)

                elif group == COMMENT_NAG:
                    last_board.nags.append(text)

                elif group == RESULT:
                    if text == "1/2":
                        status = reprResult.index("1/2-1/2")
                    else:
                        status = reprResult.index(text)
                    break

                else:
                    print("Unknown:", text)

        return boards  #, status
Exemple #13
0
    def parse_string(self, string, board, position, variation=False):
        """Recursive parses a movelist part of one game.

           Arguments:
           srting - str (movelist)
           board - lboard (initial position)
           position - int (maximum ply to parse)
           variation- boolean (True if the string is a variation)"""

        boards = []
        boards_append = boards.append

        last_board = board
        if variation:
            # this board used only to hold initial variation comments
            boards_append(LBoard(board.variant))
        else:
            # initial game board
            boards_append(board)

        status = None
        parenthesis = 0
        v_string = ""
        for m in re.finditer(pattern, string):
            group, text = m.lastindex, m.group(m.lastindex)
            if parenthesis > 0:
                v_string += ' ' + text

            if group == VARIATION_END:
                parenthesis -= 1
                if parenthesis == 0:
                    v_last_board.children.append(
                        self.parse_string(v_string[:-1],
                                          last_board.prev,
                                          position,
                                          variation=True))
                    v_string = ""
                    continue

            elif group == VARIATION_START:
                parenthesis += 1
                if parenthesis == 1:
                    v_last_board = last_board

            if parenthesis == 0:
                if group == FULL_MOVE:
                    if not variation:
                        if position != -1 and last_board.plyCount >= position:
                            break

                    mstr = m.group(MOVE)
                    try:
                        lmove = parseSAN(last_board, mstr)
                    except ParsingError as err:
                        # TODO: save the rest as comment
                        # last_board.children.append(string[m.start():])
                        notation, reason, boardfen = err.args
                        ply = last_board.plyCount
                        if ply % 2 == 0:
                            moveno = "%d." % (ply // 2 + 1)
                        else:
                            moveno = "%d..." % (ply // 2 + 1)
                        errstr1 = _(
                            "The game can't be read to end, because of an error parsing move %(moveno)s '%(notation)s'.") % {
                                'moveno': moveno,
                                'notation': notation
                            }
                        errstr2 = _("The move failed because %s.") % reason
                        self.error = LoadingError(errstr1, errstr2)
                        break
                    except:
                        ply = last_board.plyCount
                        if ply % 2 == 0:
                            moveno = "%d." % (ply // 2 + 1)
                        else:
                            moveno = "%d..." % (ply // 2 + 1)
                        errstr1 = _(
                            "Error parsing move %(moveno)s %(mstr)s") % {
                                "moveno": moveno,
                                "mstr": mstr
                            }
                        self.error = LoadingError(errstr1, "")
                        break

                    new_board = last_board.clone()
                    new_board.applyMove(lmove)

                    if m.group(MOVE_COMMENT):
                        new_board.nags.append(symbol2nag(m.group(
                            MOVE_COMMENT)))

                    new_board.prev = last_board

                    # set last_board next, except starting a new variation
                    if variation and last_board == board:
                        boards[0].next = new_board
                    else:
                        last_board.next = new_board

                    boards_append(new_board)
                    last_board = new_board

                elif group == COMMENT_REST:
                    last_board.children.append(text[1:])

                elif group == COMMENT_BRACE:
                    comm = text.replace('{\r\n', '{').replace('\r\n}', '}')
                    comm = comm[1:-1].splitlines()
                    comment = ' '.join([line.strip() for line in comm])
                    if variation and last_board == board:
                        # initial variation comment
                        boards[0].children.append(comment)
                    else:
                        last_board.children.append(comment)

                elif group == COMMENT_NAG:
                    last_board.nags.append(text)

                elif group == RESULT:
                    if text == "1/2":
                        status = reprResult.index("1/2-1/2")
                    else:
                        status = reprResult.index(text)
                    break

                else:
                    print("Unknown:", text)

        return boards  #, status