From ae815e49f5675328608dde39d6f277acf69ffcb0 Mon Sep 17 00:00:00 2001 From: yaneurao Date: Wed, 10 Jan 2024 16:50:56 +0900 Subject: [PATCH] =?UTF-8?q?-=20PackedSfen=E3=81=AE=E9=A7=92=E8=90=BD?= =?UTF-8?q?=E3=81=A1=E3=80=81cshogi=E3=81=AE=E5=87=BA=E5=8A=9B=E3=81=A8?= =?UTF-8?q?=E5=AE=8C=E5=85=A8=E3=81=AB=E3=83=90=E3=82=A4=E3=83=8A=E3=83=AA?= =?UTF-8?q?=E4=BA=92=E6=8F=9B=E3=81=AB=E3=81=AA=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E8=AA=BF=E6=95=B4=E3=81=97=E3=81=9F=E3=80=82=20=20=20?= =?UTF-8?q?-=20UnitTest=E3=81=ABPackedSfen=E3=81=AE=E3=83=90=E3=82=A4?= =?UTF-8?q?=E3=83=8A=E3=83=AA=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/extra/sfen_packer.cpp | 30 ++++++++--------- source/position.cpp | 64 ++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 15 deletions(-) diff --git a/source/extra/sfen_packer.cpp b/source/extra/sfen_packer.cpp index 34c2e2f95..57bd51b87 100644 --- a/source/extra/sfen_packer.cpp +++ b/source/extra/sfen_packer.cpp @@ -186,6 +186,10 @@ struct SfenPacker { // cout << pos; + // 以下の書き出し順が、GOLD,BISHOP,ROOKの順になるように調整しておく。 + // (cshogiの変換例とバイナリレベルで一致させたいため) + constexpr PieceType to_apery_pieces[] = { NO_PIECE_TYPE , PAWN, LANCE, KNIGHT, SILVER, GOLD, BISHOP , ROOK }; + // 駒箱枚数 // 最終、余った駒を駒箱として出力する必要がある。 int32_t hp_count[8] = @@ -222,24 +226,29 @@ struct SfenPacker for (auto c : COLOR) for (PieceType pr = PAWN; pr < KING; ++pr) { - int n = hand_count(pos.hand_of(c), pr); + // Aperyの手駒の並び順で列挙するように変更する。 + PieceType pr2 = to_apery_pieces[pr]; + + int n = hand_count(pos.hand_of(c), pr2); // この駒、n枚持ってるよ for (int i = 0; i < n; ++i) - write_hand_piece_to_stream(make_piece(c, pr)); + write_hand_piece_to_stream(make_piece(c, pr2)); // 駒箱から減らす - hp_count[pr] -= n; + hp_count[pr2] -= n; } // 最後に駒箱の分を出力 for (PieceType pr = PAWN ; pr < KING ; ++pr) { - int n = hp_count[pr]; + PieceType pr2 = to_apery_pieces[pr]; + + int n = hp_count[pr2]; // この駒、n枚駒箱にあるよ for (int i = 0; i < n ; ++i) - write_piecebox_piece_to_stream(pr); + write_piecebox_piece_to_stream(pr2); } // 綺麗に書けた..気がする。 @@ -249,17 +258,8 @@ struct SfenPacker } // data[32]をsfen化して返す。 - string unpack() + std::string unpack() { - // 駒箱枚数 - // 最終、余った駒を駒箱として出力する必要がある。 - int32_t hp_count[8] = - { - 0, - 18/*PAWN*/, 4/*LANCE*/, 4/*KNIGHT*/, 4/*SILVER*/, - 2/*BISHOP*/, 2/*ROOK*/, 4/*GOLD*/ - }; - stream.set_data(data); // 盤上の81升 diff --git a/source/position.cpp b/source/position.cpp index f265216ec..9c1faeac0 100644 --- a/source/position.cpp +++ b/source/position.cpp @@ -3051,6 +3051,70 @@ void Position::UnitTest(Test::UnitTester& tester) tester.test("pos_is_ok()",pos.pos_is_ok()); } + { + // packed sfenのテスト + auto section = tester.section("PackedSfen"); + + vector test_sfens = { + "lnsgkgsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w -", + "lns1kgsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w -", + "lnsgkgsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGK4 w -", + "lnsgk4/9/ppppppppp/9/9/9/PPPPPPPPP/9/LNSGK4 w GBRgbr", + }; + + // packed by cshogi + /* + board = cshogi.Board() + psfen = np.zeros(32, dtype=np.uint8) + board.set_sfen(sfen) + board.to_psfen(psfen) + print(np.array2string(psfen, separator=', ')) + */ + vector packed_sfens = + { + { + 89, 164, 81, 34, 12, 171, 68, 252, 44, 167, 68, 56, 94, 137, 240, + 72, 132, 87, 34, 60, 167, 68, 56, 86, 137, 248, 88, 70, 137, 48, + 188, 126 + }, + { + 89, 164, 81, 34, 12, 171, 68, 252, 44, 167, 68, 56, 94, 137, 240, + 72, 4, 18, 225, 57, 37, 194, 177, 74, 196, 199, 50, 74, 132, 97, + 191, 126 + }, + { + 89, 164, 81, 34, 88, 37, 226, 199, 41, 17, 188, 18, 129, 68, 120, + 37, 194, 115, 74, 132, 99, 149, 136, 143, 101, 148, 8, 67, 106, 107, + 191, 126 + }, + { + 89, 36, 18, 1, 137, 128, 68, 64, 34, 144, 8, 175, 68, 120, 78, + 137, 112, 172, 18, 97, 25, 37, 194, 112, 30, 159, 251, 252, 166, 212, + 218, 90 + } + }; + + bool success = true; + for(size_t i = 0 ; i < test_sfens.size() ; ++i) + { + auto sfen = test_sfens[i]; + auto &packed_sfen = packed_sfens[i]; + + StateInfo si; + pos.set(sfen, &si, Threads.main()); + + PackedSfen ps; + pos.sfen_pack(ps); + + // バイナリ列として一致するか。 + success &= ps == packed_sfen; + + // decodeで元のsfenになることは、このあとのランダムプレイヤーのテストで散々やっているから + // ここでやる必要なし。 + } + tester.test("handicapped sfen",success); + } + { // それ以外のテスト auto section = tester.section("misc");