コード例 #1
0
    def test_encode_decode(self):
        for idx, variant in enumerate(VARIANTS):
            print(idx, variant)
            variant = variant.rstrip("960")
            FEN = sf.start_fen(variant)
            # fill the pockets with possible pieces
            for empty_pocket in ("[]", "[-]"):
                if empty_pocket in FEN:
                    pocket = "".join([
                        i for i in set(FEN.split()[0])
                        if i in string.ascii_letters and i not in "Kk"
                    ])
                    parts = FEN.split(empty_pocket)
                    FEN = "%s[%s]%s" % (parts[0], pocket, parts[1])

            board = FairyBoard(variant, initial_fen=FEN)
            moves = board.legal_moves()

            saved_restored = decode_moves(encode_moves(moves, variant),
                                          variant)
            self.assertEqual(saved_restored, moves)
コード例 #2
0
    async def save_game(self, with_clocks=False):
        if self.saved:
            return

        self.stopwatch.kill()

        if self.board.ply > 0:
            self.app["g_cnt"] -= 1
            response = {"type": "g_cnt", "cnt": self.app["g_cnt"]}
            await lobby_broadcast(self.app["lobbysockets"], response)

        async def remove(keep_time):
            # Keep it in our games dict a little to let players get the last board
            # not to mention that BOT players want to abort games after 20 sec inactivity
            await asyncio.sleep(keep_time)

            try:
                del self.games[self.id]
            except KeyError:
                log.error("Failed to del %s from games" % self.id)

            if self.bot_game:
                try:
                    if self.wplayer.bot:
                        del self.wplayer.game_queues[self.id]
                    if self.bplayer.bot:
                        del self.bplayer.game_queues[self.id]
                except KeyError:
                    log.error("Failed to del %s from game_queues" % self.id)

        self.saved = True
        loop = asyncio.get_event_loop()
        loop.create_task(remove(KEEP_TIME))

        if self.board.ply < 3 and (self.db is not None):
            result = await self.db.game.delete_one({"_id": self.id})
            log.debug("Removed too short game %s from db. Deleted %s game." %
                      (self.id, result.deleted_count))
        else:
            if self.result != "*":
                if self.rated:
                    await self.update_ratings()
                if (not self.bot_game) and (not self.wplayer.anon) and (
                        not self.bplayer.anon):
                    await self.save_crosstable()

            # self.print_game()

            new_data = {
                "d":
                self.date,
                "f":
                self.board.fen,
                "s":
                self.status,
                "r":
                R2C[self.result],
                'm':
                encode_moves(
                    map(grand2zero, self.board.move_stack) if self.variant
                    in GRANDS else self.board.move_stack, self.variant)
            }

            if self.rated and self.result != "*":
                new_data["p0"] = self.p0
                new_data["p1"] = self.p1

            # Janggi game starts with a prelude phase to set up horses and elephants, so
            # initial FEN may be different compared to one we used when db game document was created
            if self.variant == "janggi":
                new_data["if"] = self.board.initial_fen

            if with_clocks:
                new_data["clocks"] = self.ply_clocks

            if self.manual_count:
                if self.board.count_started > 0:
                    self.manual_count_toggled.append(
                        (self.board.count_started, self.board.ply + 1))
                new_data["mct"] = self.manual_count_toggled

            if self.db is not None:
                await self.db.game.find_one_and_update({"_id": self.id},
                                                       {"$set": new_data})
コード例 #3
0
async def import_game(request):
    data = await request.post()
    app = request.app
    db = app["db"]
    users = app["users"]

    # print("---IMPORT GAME---")
    # print(data)
    # print("-----------------")

    wp = data["White"]
    bp = data["Black"]
    if wp in users:
        wplayer = users[wp]
    else:
        wplayer = User(app, username=wp, anon=True)
        users[wp] = wplayer

    if bp in users:
        bplayer = users[bp]
    else:
        bplayer = User(app, username=bp, anon=True)
        users[bp] = bplayer

    variant = data.get("Variant", "chess").lower()
    initial_fen = data.get("FEN", "")
    final_fen = data.get("final_fen", "")
    status = int(data.get("Status", UNKNOWNFINISH))
    result = data.get("Result", "*")
    try:
        date = data.get("Date", "")[0:10]
        date = map(int, date.split("." if "." in date else "/"))
        date = datetime(*date, tzinfo=timezone.utc)
    except Exception:
        log.exception("Date tag parsing failed")
        date = datetime.now(timezone.utc)

    try:
        minute = False
        tc = data.get("TimeControl", "").split("+")
        if tc[0][-1] == "分":
            minute = True
            tc[0] = tc[0][:-1]
        if tc[1][-1] == "秒":
            tc[1] = tc[1][:-1]
        tc = list(map(int, tc))
        base = int((tc[0] / 60) if not minute else tc[0])
        inc = int(tc[1])
    except Exception:
        log.exception("TimeControl tag parsing failed")
        base, inc = 0, 0

    move_stack = data.get("moves", "").split(" ")
    moves = encode_moves(
        map(grand2zero, move_stack) if variant in GRANDS
        else move_stack, variant)

    game_id = await new_id(None if db is None else db.game)
    existing = await db.game.find_one({'_id': {'$eq': game_id}})
    if existing:
        message = "Failed to create game. Game ID %s allready in mongodb." % game_id
        log.exception(message)
        return web.json_response({"error": message})

    try:
        print(game_id, variant, initial_fen, wplayer, bplayer)
        new_game = Game(app, game_id, variant, initial_fen, wplayer, bplayer, rated=IMPORTED, create=False)
    except Exception:
        message = "Creating new Game %s failed!" % game_id
        log.exception(message)
        return web.json_response({"error": message})

    document = {
        "_id": game_id,
        "us": [wplayer.username, bplayer.username],
        "v": V2C[variant],
        "b": base,
        "i": inc,
        "bp": new_game.byoyomi_period,
        "m": moves,
        "d": date,
        "f": final_fen,
        "s": status,
        "r": R2C[result],
        "x": new_game.level,
        "y": IMPORTED,
        "z": int(new_game.chess960),
        "by": data["username"],
    }

    if initial_fen or new_game.chess960:
        document["if"] = new_game.initial_fen

    if variant.endswith("shogi") or variant in ("dobutsu", "gorogoro", "gorogoroplus"):
        document["uci"] = 1

    wrating = data.get("WhiteElo")
    brating = data.get("BlackElo")
    if wrating:
        document["p0"] = {"e": wrating}
    if brating:
        document["p1"] = {"e": brating}

    print(document)
    result = await db.game.insert_one(document)
    print("db insert IMPORTED game result %s" % repr(result.inserted_id))

    return web.json_response({"gameId": game_id})
コード例 #4
0
ファイル: utils.py プロジェクト: colwem/pychess-variants
    async def save_game(self, analysis=False):
        self.stopwatch.kill()

        async def remove():
            # Keep it in our games dict a little to let players get the last board
            # not to mention that BOT players want to abort games after 20 sec inactivity
            await asyncio.sleep(60 * 10)

            try:
                del self.games[self.id]
            except KeyError:
                log.error("Failed to del %s from games" % self.id)

            if self.bot_game:
                try:
                    if self.wplayer.bot:
                        del self.wplayer.game_queues[self.id]
                    if self.bplayer.bot:
                        del self.bplayer.game_queues[self.id]
                except KeyError:
                    log.error("Failed to del %s from game_queues" % self.id)

        if self.saved:
            return

        self.saved = True
        loop = asyncio.get_event_loop()
        self.tasks.add(loop.create_task(remove()))

        if self.ply < 3:
            result = await self.db.game.delete_one({"_id": self.id})
            log.debug("Removed too short game %s from db. Deleted %s game." %
                      (self.id, result.deleted_count))
        else:
            self.print_game()

            if analysis:
                new_data = {"a": [step["analysis"] for step in self.steps]}
            else:
                new_data = {
                    "d":
                    self.date,
                    "f":
                    self.board.fen,
                    "s":
                    self.status,
                    "r":
                    R2C[self.result],
                    'm':
                    encode_moves(
                        map(usi2uci, self.board.move_stack)
                        if self.variant[-5:] == "shogi" else
                        map(grand2zero, self.board.move_stack)
                        if self.variant == "xiangqi" or self.variant == "grand"
                        or self.variant == "grandhouse"
                        or self.variant == "shako" else self.board.move_stack,
                        self.variant)
                }

                if self.rated and self.result != "*":
                    new_data["p0"] = self.p0
                    new_data["p1"] = self.p1

            await self.db.game.find_one_and_update({"_id": self.id},
                                                   {"$set": new_data})
コード例 #5
0
ファイル: game.py プロジェクト: sonivre/pychess-variants
    async def save_game(self):
        if self.saved:
            return

        self.stopwatch.kill()

        if self.ply > 0:
            self.app["g_cnt"] -= 1
            response = {"type": "g_cnt", "cnt": self.app["g_cnt"]}
            await lobby_broadcast(self.app["websockets"], response)

        async def remove(keep_time):
            # Keep it in our games dict a little to let players get the last board
            # not to mention that BOT players want to abort games after 20 sec inactivity
            await asyncio.sleep(keep_time)

            try:
                del self.games[self.id]
            except KeyError:
                log.error("Failed to del %s from games" % self.id)

            if self.bot_game:
                try:
                    if self.wplayer.bot:
                        del self.wplayer.game_queues[self.id]
                    if self.bplayer.bot:
                        del self.bplayer.game_queues[self.id]
                except KeyError:
                    log.error("Failed to del %s from game_queues" % self.id)

        self.saved = True
        loop = asyncio.get_event_loop()
        loop.create_task(remove(KEEP_TIME))

        if self.ply < 3 and (self.db is not None):
            result = await self.db.game.delete_one({"_id": self.id})
            log.debug("Removed too short game %s from db. Deleted %s game." %
                      (self.id, result.deleted_count))
        else:
            if self.result != "*":
                if self.rated:
                    await self.update_ratings()
                if (not self.bot_game) and (not self.wplayer.anon) and (
                        not self.bplayer.anon):
                    await self.save_crosstable()

            # self.print_game()

            new_data = {
                "d":
                self.date,
                "f":
                self.board.fen,
                "s":
                self.status,
                "r":
                R2C[self.result],
                'm':
                encode_moves(
                    map(grand2zero, self.board.move_stack)
                    if self.variant == "xiangqi" or self.variant == "grand"
                    or self.variant == "grandhouse" or self.variant == "shako"
                    else self.board.move_stack, self.variant)
            }

            if self.rated and self.result != "*":
                new_data["p0"] = self.p0
                new_data["p1"] = self.p1

            if self.db is not None:
                await self.db.game.find_one_and_update({"_id": self.id},
                                                       {"$set": new_data})
コード例 #6
0
ファイル: game.py プロジェクト: Fulmene/pychess-variants
    async def save_game(self):
        if self.saved:
            return
        self.saved = True

        if self.rated == IMPORTED:
            log.exception("Save IMPORTED game %s ???", self.id)
            return

        self.stopwatch.clock_task.cancel()
        try:
            await self.stopwatch.clock_task
        except asyncio.CancelledError:
            pass

        if self.board.ply > 0:
            self.app["g_cnt"][0] -= 1
            response = {"type": "g_cnt", "cnt": self.app["g_cnt"][0]}
            await lobby_broadcast(self.app["lobbysockets"], response)

        async def remove(keep_time):
            # Keep it in our games dict a little to let players get the last board
            # not to mention that BOT players want to abort games after 20 sec inactivity
            await asyncio.sleep(keep_time)

            try:
                del self.games[self.id]
            except KeyError:
                log.info("Failed to del %s from games", self.id)

            if self.bot_game:
                try:
                    if self.wplayer.bot:
                        del self.wplayer.game_queues[self.id]
                    if self.bplayer.bot:
                        del self.bplayer.game_queues[self.id]
                except KeyError:
                    log.info("Failed to del %s from game_queues", self.id)

        self.remove_task = asyncio.create_task(remove(KEEP_TIME))

        if self.board.ply < 3 and (self.db is not None) and (self.tournamentId
                                                             is None):
            result = await self.db.game.delete_one({"_id": self.id})
            log.debug(
                "Removed too short game %s from db. Deleted %s game.",
                self.id,
                result.deleted_count,
            )
        else:
            if self.result != "*":
                if self.rated == RATED:
                    await self.update_ratings()
                if (not self.bot_game) and (not self.wplayer.anon) and (
                        not self.bplayer.anon):
                    await self.save_crosstable()

            if self.tournamentId is not None:
                try:
                    await self.app["tournaments"][self.tournamentId
                                                  ].game_update(self)
                except Exception:
                    log.exception("Exception in tournament game_update()")

            new_data = {
                "d":
                self.date,
                "f":
                self.board.fen,
                "s":
                self.status,
                "r":
                R2C[self.result],
                "m":
                encode_moves(
                    map(grand2zero, self.board.move_stack)
                    if self.variant in GRANDS else self.board.move_stack,
                    self.variant,
                ),
            }

            if self.rated == RATED and self.result != "*":
                new_data["p0"] = self.p0
                new_data["p1"] = self.p1

            # Janggi game starts with a prelude phase to set up horses and elephants, so
            # initial FEN may be different compared to one we used when db game document was created
            if self.variant == "janggi":
                new_data["if"] = self.board.initial_fen

            if self.rated == RATED:
                new_data["t"] = [p["movetime"] for p in self.ply_clocks]

            if self.tournamentId is not None:
                new_data["wb"] = self.wberserk
                new_data["bb"] = self.bberserk

            if self.manual_count:
                if self.board.count_started > 0:
                    self.manual_count_toggled.append(
                        (self.board.count_started, self.board.ply + 1))
                new_data["mct"] = self.manual_count_toggled

            if self.db is not None:
                await self.db.game.find_one_and_update({"_id": self.id},
                                                       {"$set": new_data})