Exemplo n.º 1
0
def pgn(doc):
    variant = C2V[doc["v"]]
    mlist = decode_moves(doc["m"], variant)
    chess960 = bool(int(doc.get("z"))) if "z" in doc else False

    if variant[-5:] == "shogi":
        mlist = list(map(uci2usi, mlist))
    elif variant == "xiangqi" or variant == "grand" or variant == "grandhouse" or variant == "shako":
        mlist = list(map(zero2grand, mlist))

    fen = doc[
        "if"] if "if" in doc else SHOGI_FEN if variant == "shogi" else MINISHOGI_FEN if variant == "minishogi" else KYOTOSHOGI_FEN if variant == "kyotoshogi" else sf.start_fen(
            variant)
    mlist = sf.get_san_moves(variant, fen, mlist, chess960)

    moves = " ".join(
        (move if ind % 2 == 1 else "%s. %s" % (((ind + 1) // 2) + 1, move)
         for ind, move in enumerate(mlist)))
    no_setup = fen == STANDARD_FEN and not chess960
    return '[Event "{}"]\n[Site "{}"]\n[Date "{}"]\n[Round "-"]\n[White "{}"]\n[Black "{}"]\n[Result "{}"]\n[TimeControl "{}+{}"]\n[WhiteElo "{}"]\n[BlackElo "{}"]\n[Variant "{}"]\n{fen}{setup}\n{} {}\n'.format(
        "PyChess " + ("rated" if doc["y"] == 1 else "casual") + " game",
        URI + "/" + doc["_id"],
        doc["d"].strftime("%Y.%m.%d"),
        doc["us"][0],
        doc["us"][1],
        C2R[doc["r"]],
        doc["b"] * 60,
        doc["i"],
        doc["p0"]["e"],
        doc["p1"]["e"],
        variant.capitalize() if not chess960 else VARIANT_960_TO_PGN[variant],
        moves,
        C2R[doc["r"]],
        fen="" if no_setup else '[FEN "%s"]\n' % fen,
        setup="" if no_setup else '[SetUp "1"]\n')
Exemplo n.º 2
0
def pgn(doc):
    variant = C2V[doc["v"]]
    mlist = decode_moves(doc["m"], variant)
    chess960 = bool(int(doc.get("z"))) if "z" in doc else False

    if variant == "xiangqi" or variant == "grand" or variant == "grandhouse" or variant == "shako" or variant == "janggi":
        mlist = list(map(zero2grand, mlist))

    fen = doc["if"] if "if" in doc else sf.start_fen(variant)
    mlist = sf.get_san_moves(variant, fen, mlist, chess960)

    moves = " ".join(
        (move if ind % 2 == 1 else "%s. %s" % (((ind + 1) // 2) + 1, move)
         for ind, move in enumerate(mlist)))
    no_setup = fen == STANDARD_FEN and not chess960
    # Use lichess format for crazyhouse games to support easy import
    setup_fen = fen if variant != "crazyhouse" else fen.replace("[]", "")

    return '[Event "{}"]\n[Site "{}"]\n[Date "{}"]\n[Round "-"]\n[White "{}"]\n[Black "{}"]\n[Result "{}"]\n[TimeControl "{}+{}"]\n[WhiteElo "{}"]\n[BlackElo "{}"]\n[Variant "{}"]\n{fen}{setup}\n{} {}\n'.format(
        "PyChess " + ("rated" if "y" in doc and doc["y"] == 1 else "casual") +
        " game",
        URI + "/" + doc["_id"],
        doc["d"].strftime("%Y.%m.%d"),
        doc["us"][0],
        doc["us"][1],
        C2R[doc["r"]],
        doc["b"] * 60,
        doc["i"],
        doc["p0"]["e"] if "p0" in doc else "?",
        doc["p1"]["e"] if "p1" in doc else "?",
        variant.capitalize() if not chess960 else VARIANT_960_TO_PGN[variant],
        moves,
        C2R[doc["r"]],
        fen="" if no_setup else '[FEN "%s"]\n' % setup_fen,
        setup="" if no_setup else '[SetUp "1"]\n')
Exemplo n.º 3
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)
Exemplo n.º 4
0
async def load_game(app, game_id):
    """ Return Game object from app cache or from database """
    db = app["db"]
    games = app["games"]
    users = app["users"]
    if game_id in games:
        return games[game_id]

    doc = await db.game.find_one({"_id": game_id})

    if doc is None:
        return None

    wp, bp = doc["us"]
    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 = C2V[doc["v"]]

    initial_fen = doc.get("if")

    # Old USI Shogi games saved using usi2uci() need special handling
    usi_format = variant.endswith("shogi") and doc.get("uci") is None

    if usi_format:
        wplayer, bplayer = bplayer, wplayer
        if initial_fen:
            # print("load_game() USI SFEN was:", initial_fen)
            parts = initial_fen.split()
            if len(parts) > 3 and parts[1] in "wb":
                pockets = "[%s]" % parts[2] if parts[2] not in "-0" else ""
                initial_fen = parts[0] + pockets + (
                    " w" if parts[1] == "b" else " b") + " 0 " + parts[3]
            else:
                initial_fen = parts[0] + (" w"
                                          if parts[1] == "b" else " b") + " 0"
            # print("   changed to:", initial_fen)

    game = Game(app,
                game_id,
                variant,
                initial_fen,
                wplayer,
                bplayer,
                base=doc["b"],
                inc=doc["i"],
                byoyomi_period=int(bool(doc.get("bp"))),
                level=doc.get("x"),
                rated=bool(doc.get("y")),
                chess960=bool(doc.get("z")),
                create=False)

    mlist = decode_moves(doc["m"], variant)

    if mlist:
        game.saved = True

    if usi_format and variant == "shogi":
        mirror = mirror9
        mlist = map(mirror, mlist)

    elif usi_format and (variant == "minishogi" or variant == "kyotoshogi"):
        mirror = mirror5
        mlist = map(mirror, mlist)

    elif variant == "xiangqi" or variant == "grand" or variant == "grandhouse" or variant == "shako" or variant == "janggi":
        mlist = map(zero2grand, mlist)

    if "a" in doc:
        if usi_format and "m" in doc["a"][0]:
            doc["a"][0]["m"] = mirror(usi2uci(doc["a"][0]["m"]))
        game.steps[0]["analysis"] = doc["a"][0]

    if "mct" in doc:
        print(doc["mct"])
        manual_count_toggled = iter(doc["mct"])
        count_started = -1
        count_ended = -1

    for ply, move in enumerate(mlist):
        try:
            if "mct" in doc:
                # print("Ply", ply, "Move", move)
                if ply + 1 >= count_ended:
                    try:
                        game.board.count_started = -1
                        count_started, count_ended = next(manual_count_toggled)
                        # print("New count interval", (count_started, count_ended))
                    except StopIteration:
                        # print("Piece's honour counting started")
                        count_started = 0
                        count_ended = MAX_PLY + 1
                        game.board.count_started = 0
                if ply + 1 == count_started:
                    # print("Count started", count_started)
                    game.board.count_started = ply

            san = game.board.get_san(move)
            game.board.push(move)
            game.check = game.board.is_checked()
            turnColor = "black" if game.board.color == BLACK else "white"
            if usi_format:
                turnColor = "black" if turnColor == "white" else "white"
            game.steps.append({
                "fen": game.board.fen,
                "move": move,
                "san": san,
                "turnColor": turnColor,
                "check": game.check
            })

            if "a" in doc:
                if usi_format and "m" in doc["a"][ply + 1]:
                    doc["a"][ply + 1]["m"] = mirror(
                        usi2uci(doc["a"][ply + 1]["m"]))
                try:
                    game.steps[-1]["analysis"] = doc["a"][ply + 1]
                except IndexError:
                    print("IndexError", ply, move, san)

        except Exception:
            log.exception("ERROR: Exception in load_game() %s %s %s %s %s" %
                          (game_id, variant, doc.get("if"), move, list(mlist)))
            break

    if len(game.steps) > 1:
        move = game.steps[-1]["move"]
        game.lastmove = move

    level = doc.get("x")
    game.date = doc["d"]
    game.status = doc["s"]
    game.level = level if level is not None else 0
    game.result = C2R[doc["r"]]

    try:
        game.wrating = doc["p0"]["e"]
        game.wrdiff = doc["p0"]["d"]
        game.brating = doc["p1"]["e"]
        game.brdiff = doc["p1"]["d"]
    except KeyError:
        game.wrating = "1500?"
        game.wrdiff = "0"
        game.brating = "1500?"
        game.brdiff = "0"
    return game
Exemplo n.º 5
0
def pgn(doc):
    variant = C2V[doc["v"]]
    mlist = decode_moves(doc["m"], variant)
    if len(mlist) == 0:
        return None

    chess960 = bool(int(doc.get("z"))) if "z" in doc else False

    initial_fen = doc.get("if")
    usi_format = variant.endswith("shogi") and doc.get("uci") is None

    if usi_format:
        # wplayer, bplayer = bplayer, wplayer
        if initial_fen:
            # print("load_game() USI SFEN was:", initial_fen)
            parts = initial_fen.split()
            if len(parts) > 3 and parts[1] in "wb":
                pockets = "[%s]" % parts[2] if parts[2] not in "-0" else ""
                initial_fen = parts[0] + pockets + (
                    " w" if parts[1] == "b" else " b") + " 0 " + parts[3]
            else:
                initial_fen = parts[0] + (" w"
                                          if parts[1] == "b" else " b") + " 0"
            # print("   changed to:", initial_fen)

    if usi_format and variant == "shogi":
        mirror = mirror9
        mlist = list(map(mirror, mlist))

    elif usi_format and (variant == "minishogi" or variant == "kyotoshogi"):
        mirror = mirror5
        mlist = list(map(mirror, mlist))

    elif variant == "xiangqi" or variant == "grand" or variant == "grandhouse" or variant == "shako" or variant == "janggi":
        mlist = list(map(zero2grand, mlist))

    fen = initial_fen if initial_fen is not None else sf.start_fen(variant)
    # print(variant, fen, mlist)
    try:
        mlist = sf.get_san_moves(variant, fen, mlist, chess960)
    except Exception:
        try:
            mlist = sf.get_san_moves(variant, fen, mlist[:-1], chess960)
        except Exception:
            log.error("Movelist contains invalid move %s" % mlist)
            mlist = mlist[0]

    moves = " ".join(
        (move if ind % 2 == 1 else "%s. %s" % (((ind + 1) // 2) + 1, move)
         for ind, move in enumerate(mlist)))
    no_setup = fen == STANDARD_FEN and not chess960
    # Use lichess format for crazyhouse games to support easy import
    setup_fen = fen if variant != "crazyhouse" else fen.replace("[]", "")

    return '[Event "{}"]\n[Site "{}"]\n[Date "{}"]\n[Round "-"]\n[White "{}"]\n[Black "{}"]\n[Result "{}"]\n[TimeControl "{}+{}"]\n[WhiteElo "{}"]\n[BlackElo "{}"]\n[Variant "{}"]\n{fen}{setup}\n{} {}\n'.format(
        "PyChess " + ("rated" if "y" in doc and doc["y"] == 1 else "casual") +
        " game",
        URI + "/" + doc["_id"],
        doc["d"].strftime("%Y.%m.%d"),
        doc["us"][0],
        doc["us"][1],
        C2R[doc["r"]],
        doc["b"] * 60,
        doc["i"],
        doc["p0"]["e"] if "p0" in doc else "?",
        doc["p1"]["e"] if "p1" in doc else "?",
        variant.capitalize() if not chess960 else VARIANT_960_TO_PGN[variant],
        moves,
        C2R[doc["r"]],
        fen="" if no_setup else '[FEN "%s"]\n' % setup_fen,
        setup="" if no_setup else '[SetUp "1"]\n')
Exemplo n.º 6
0
async def load_game(app, game_id):
    db = app["db"]
    games = app["games"]
    users = app["users"]
    if game_id in games:
        return games[game_id]

    doc = await db.game.find_one({"_id": game_id})

    if doc is None:
        return None

    wp = doc["us"][0]
    if wp in users:
        wplayer = users[wp]
    else:
        wplayer = User(db=db, username=wp, anon=True)
        users[wp] = wplayer

    bp = doc["us"][1]
    if bp in users:
        bplayer = users[bp]
    else:
        bplayer = User(db=db, username=bp, anon=True)
        users[bp] = bplayer

    variant = C2V[doc["v"]]

    game = Game(app, game_id, variant, doc.get("if"), wplayer, bplayer,
                doc["b"], doc["i"], doc.get("x"), bool(doc.get("y")),
                bool(doc.get("z")))

    mlist = decode_moves(doc["m"], variant)

    if mlist:
        game.saved = True

    if variant[-5:] == "shogi":
        mlist = map(uci2usi, mlist)
    elif variant == "xiangqi" or variant == "grand" or variant == "grandhouse" or variant == "shako":
        mlist = map(zero2grand, mlist)

    if "a" in doc:
        game.steps[0]["analysis"] = doc["a"][0]

    for ply, move in enumerate(mlist):
        try:
            san = game.board.get_san(move)
            game.board.push(move)
            game.check = game.board.is_checked()
            game.steps.append({
                "fen":
                game.board.fen,
                "move":
                move,
                "san":
                san,
                "turnColor":
                "black" if game.board.color == BLACK else "white",
                "check":
                game.check
            })

            if "a" in doc:
                game.steps[-1]["analysis"] = doc["a"][ply + 1]

        except Exception:
            log.exception("ERROR: Exception in load_game() %s %s %s %s" %
                          (game_id, variant, doc.get("if"), mlist))
            break

    if len(game.steps) > 1:
        move = game.steps[-1]["move"]
        game.lastmove = move

    level = doc.get("x")
    game.date = doc["d"]
    game.status = doc["s"]
    game.level = level if level is not None else 0
    game.result = C2R[doc["r"]]
    game.random_move = ""
    try:
        game.wrating = doc["p0"]["e"]
        game.wrdiff = doc["p0"]["d"]
        game.brating = doc["p1"]["e"]
        game.brdiff = doc["p1"]["d"]
    except KeyError:
        game.wrating = "1500?"
        game.wrdiff = "0"
        game.brating = "1500?"
        game.brdiff = "0"
    return game
Exemplo n.º 7
0
async def get_user_games(request):
    users = request.app["users"]
    db = request.app["db"]
    profileId = request.match_info.get("profileId")

    if profileId is not None and profileId not in users:
        await asyncio.sleep(3)
        return web.json_response({})

    # Who made the request?
    session = await aiohttp_session.get_session(request)
    session_user = session.get("user_name")

    filter_cond = {}
    # print("URL", request.rel_url)
    level = request.rel_url.query.get("x")
    variant = request.path[request.path.rfind("/") + 1 :]

    if "/win" in request.path:
        filter_cond["$or"] = [
            {"r": "a", "us.0": profileId},
            {"r": "b", "us.1": profileId},
        ]
    elif "/loss" in request.path:
        # level8win requests Fairy-Stockfish lost games
        if level is not None:
            filter_cond["$and"] = [
                {"$or": [{"r": "a", "us.1": profileId}, {"r": "b", "us.0": profileId}]},
                {"x": int(level)},
                {"$or": [{"if": None}, {"v": "j"}]},  # Janggi games always have initial FEN!
                {
                    "$or": [
                        {"s": MATE},
                        {"s": VARIANTEND},
                        {"s": INVALIDMOVE},
                        {"s": CLAIM},
                    ]
                },
            ]
        else:
            filter_cond["$or"] = [
                {"r": "a", "us.1": profileId},
                {"r": "b", "us.0": profileId},
            ]
    elif "/rated" in request.path:
        filter_cond["$or"] = [{"y": 1, "us.1": profileId}, {"y": 1, "us.0": profileId}]
    elif "/import" in request.path:
        filter_cond["by"] = profileId
        filter_cond["y"] = 2
    elif "/perf" in request.path and variant in VARIANTS:
        if variant.endswith("960"):
            v = V2C[variant[:-3]]
            z = 1
        else:
            v = V2C[variant]
            z = 0
        filter_cond["$or"] = [
            {"v": v, "z": z, "us.1": profileId},
            {"v": v, "z": z, "us.0": profileId},
        ]
    elif "/me" in request.path:
        session = await aiohttp_session.get_session(request)
        session_user = session.get("user_name")
        filter_cond["$or"] = [
            {"us.0": session_user, "us.1": profileId},
            {"us.1": session_user, "us.0": profileId},
        ]
    else:
        filter_cond["us"] = profileId

    page_num = request.rel_url.query.get("p")
    if not page_num:
        page_num = 0

    game_doc_list = []
    if profileId is not None:
        # print("FILTER:", filter_cond)
        cursor = db.game.find(filter_cond)
        cursor.sort("d", -1).skip(int(page_num) * GAME_PAGE_SIZE).limit(GAME_PAGE_SIZE)
        async for doc in cursor:
            # filter out private games
            if (
                "p" in doc
                and doc["p"] == 1
                and session_user != doc["us"][0]
                and session_user != doc["us"][1]
            ):
                continue

            doc["v"] = C2V[doc["v"]]
            doc["r"] = C2R[doc["r"]]
            doc["wt"] = users[doc["us"][0]].title if doc["us"][0] in users else ""
            doc["bt"] = users[doc["us"][1]].title if doc["us"][1] in users else ""
            doc["lm"] = decode_moves((doc["m"][-1],), doc["v"])[-1] if len(doc["m"]) > 0 else ""
            if doc["v"] in GRANDS and doc["lm"] != "":
                doc["lm"] = zero2grand(doc["lm"])

            tournament_id = doc.get("tid")
            if tournament_id is not None:
                doc["tn"] = await get_tournament_name(request.app, tournament_id)

            game_doc_list.append(doc)

    return web.json_response(game_doc_list, dumps=partial(json.dumps, default=datetime.isoformat))
Exemplo n.º 8
0
async def load_game(app, game_id):
    """ Return Game object from app cache or from database """
    db = app["db"]
    games = app["games"]
    users = app["users"]
    if game_id in games:
        return games[game_id]

    doc = await db.game.find_one({"_id": game_id})

    if doc is None:
        return None

    wp, bp = doc["us"]
    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 = C2V[doc["v"]]

    initial_fen = doc.get("if")

    # Old USI Shogi games saved using usi2uci() need special handling
    usi_format = variant.endswith("shogi") and doc.get("uci") is None

    if usi_format:
        wplayer, bplayer = bplayer, wplayer
        if initial_fen:
            print("load_game() USI SFEN was:", initial_fen)
            parts = initial_fen.split()
            pockets = "[%s]" % parts[2]
            initial_fen = parts[0] + pockets + (" w" if parts[1] == " b" else " w") + " 0 " + parts[3]
            print("   changed to:", initial_fen)

    game = Game(app, game_id, variant, initial_fen, wplayer, bplayer, doc["b"], doc["i"], doc.get("x"), bool(doc.get("y")), bool(doc.get("z")), create=False)

    mlist = decode_moves(doc["m"], variant)

    if mlist:
        game.saved = True

    if usi_format and variant == "shogi":
        mirror = mirror9
        mlist = list(map(mirror, mlist))

    elif usi_format and (variant == "minishogi" or variant == "kyotoshogi"):
        mirror = mirror5
        mlist = list(map(mirror, mlist))

    elif variant == "xiangqi" or variant == "grand" or variant == "grandhouse" or variant == "shako":
        mlist = map(zero2grand, mlist)

    if "a" in doc:
        if usi_format and "m" in doc["a"][0]:
            doc["a"][0]["m"] = mirror(usi2uci(doc["a"][0]["m"]))
        game.steps[0]["analysis"] = doc["a"][0]

    for ply, move in enumerate(mlist):
        try:
            san = game.board.get_san(move)
            game.board.push(move)
            game.check = game.board.is_checked()
            game.steps.append({
                "fen": game.board.fen,
                "move": move,
                "san": san,
                "turnColor": "black" if game.board.color == BLACK else "white",
                "check": game.check}
            )

            if "a" in doc:
                if usi_format and "m" in doc["a"][ply + 1]:
                    doc["a"][ply + 1]["m"] = mirror(usi2uci(doc["a"][ply + 1]["m"]))
                game.steps[-1]["analysis"] = doc["a"][ply + 1]

        except Exception:
            log.exception("ERROR: Exception in load_game() %s %s %s %s" % (game_id, variant, doc.get("if"), mlist))
            break

    if len(game.steps) > 1:
        move = game.steps[-1]["move"]
        game.lastmove = move

    level = doc.get("x")
    game.date = doc["d"]
    game.status = doc["s"]
    game.level = level if level is not None else 0
    game.result = C2R[doc["r"]]
    game.random_move = ""
    try:
        game.wrating = doc["p0"]["e"]
        game.wrdiff = doc["p0"]["d"]
        game.brating = doc["p1"]["e"]
        game.brdiff = doc["p1"]["d"]
    except KeyError:
        game.wrating = "1500?"
        game.wrdiff = "0"
        game.brating = "1500?"
        game.brdiff = "0"
    return game