rshogi-py-avx2 0.2.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rshogi_py_avx2-0.2.0 → rshogi_py_avx2-0.4.0}/PKG-INFO +1 -1
- {rshogi_py_avx2-0.2.0 → rshogi_py_avx2-0.4.0}/pyproject.toml +4 -3
- rshogi_py_avx2-0.4.0/python/rshogi/__init__.py +51 -0
- rshogi_py_avx2-0.4.0/python/rshogi/book.py +25 -0
- rshogi_py_avx2-0.4.0/python/rshogi/core.py +5 -0
- rshogi_py_avx2-0.4.0/python/rshogi/initial_positions.py +21 -0
- rshogi_py_avx2-0.4.0/python/rshogi/io.py +106 -0
- rshogi_py_avx2-0.4.0/python/rshogi/numpy.py +14 -0
- rshogi_py_avx2-0.4.0/python/rshogi/record.py +19 -0
- rshogi_py_avx2-0.4.0/python/rshogi/serialization.py +5 -0
- rshogi_py_avx2-0.4.0/python/rshogi/svg.py +5 -0
- rshogi_py_avx2-0.4.0/python/rshogi/types.py +25 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/Cargo.toml +6 -3
- rshogi_py_avx2-0.4.0/rshogi/README.md +314 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/benches/apply_undo.rs +3 -3
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/build.rs +31 -36
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/bin/debug_mate1ply.rs +16 -9
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/bin/dump_keys.rs +3 -1
- rshogi_py_avx2-0.4.0/rshogi/src/bin/move_order_stats.rs +446 -0
- rshogi_py_avx2-0.4.0/rshogi/src/bin/pack_sbinpack_bench.rs +230 -0
- rshogi_py_avx2-0.4.0/rshogi/src/bin/perft_bench.rs +92 -0
- rshogi_py_avx2-0.4.0/rshogi/src/bin/sbinpack_kif_roundtrip.rs +182 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/bin/verify_mate3ply.rs +2 -0
- rshogi_py_avx2-0.4.0/rshogi/src/board/CLAUDE.md +17 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/attack_tables/tests/mod.rs +102 -105
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/attack_tables.rs +2 -3
- rshogi_py_avx2-0.4.0/rshogi/src/board/bitboard256.rs +206 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/bitboard_set.rs +5 -5
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/bona.rs +3 -6
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/eval_list.rs +9 -6
- rshogi_py_avx2-0.4.0/rshogi/src/board/initial_positions.rs +42 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/lookup.rs +37 -34
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/mate_constant.rs +3 -3
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/material.rs +6 -6
- rshogi_py_avx2-0.4.0/rshogi/src/board/mod.rs +141 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/move_list.rs +18 -18
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/checks.rs +60 -55
- rshogi_py_avx2-0.4.0/rshogi/src/board/movegen/drops.rs +248 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/evasions.rs +9 -6
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/generate.rs +66 -14
- rshogi_py_avx2-0.4.0/rshogi/src/board/movegen/mod.rs +321 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/pieces.rs +149 -107
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/promotions.rs +0 -3
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/drops.rs +5 -5
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/evasions.rs +5 -4
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/is_legal.rs +7 -5
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/piece_moves.rs +4 -4
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/promotion_rules.rs +2 -2
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/recaptures.rs +4 -6
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/parser.rs +8 -8
- rshogi_py_avx2-0.4.0/rshogi/src/board/perft.rs +539 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/piece_list.rs +23 -23
- rshogi_py_avx2-0.4.0/rshogi/src/board/position/CLAUDE.md +19 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/accessors.rs +81 -75
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/attacks.rs +91 -34
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/cache.rs +52 -30
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/constructors.rs +9 -9
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/eval_list.rs +7 -7
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/hash.rs +9 -9
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/legality.rs +29 -14
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/maintenance.rs +22 -22
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/mod.rs +121 -11
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/packed_sfen.rs +23 -23
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/parser.rs +16 -16
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/rules.rs +58 -58
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/see.rs +113 -114
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/basics.rs +21 -21
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/packed_sfen.rs +26 -28
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/piece_list.rs +10 -10
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/roundtrip.rs +5 -5
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/rules/discovered_checks.rs +2 -2
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/rules/drops.rs +4 -4
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/rules/repetition.rs +17 -17
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/sfen_parsing.rs +9 -9
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/undo.rs +30 -30
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/zobrist.rs +7 -7
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/types.rs +19 -9
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/updates.rs +271 -83
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/validation.rs +8 -8
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/state_info/tests/mod.rs +18 -20
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/state_info.rs +45 -59
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/test_support.rs +2 -2
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/tests/yaneuraou_compat.rs +34 -33
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/zobrist.rs +83 -47
- rshogi_py_avx2-0.4.0/rshogi/src/book/builder.rs +107 -0
- rshogi_py_avx2-0.4.0/rshogi/src/book/error.rs +28 -0
- rshogi_py_avx2-0.4.0/rshogi/src/book/memory.rs +60 -0
- rshogi_py_avx2-0.4.0/rshogi/src/book/mod.rs +107 -0
- rshogi_py_avx2-0.4.0/rshogi/src/book/static_book.rs +279 -0
- rshogi_py_avx2-0.4.0/rshogi/src/book/types.rs +59 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/lib.rs +27 -6
- rshogi_py_avx2-0.4.0/rshogi/src/mate/CLAUDE.md +15 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/mate/mod.rs +97 -25
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/mate/table.rs +71 -54
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/mate/yaneuraou.rs +138 -139
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/records/error.rs +0 -4
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/records/formats/common.rs +2 -2
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/records/formats/csa.rs +317 -34
- rshogi_py_avx2-0.4.0/rshogi/src/records/formats/jkf.rs +534 -0
- rshogi_py_avx2-0.4.0/rshogi/src/records/formats/kif.rs +2274 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/records/formats/mod.rs +4 -0
- rshogi_py_avx2-0.4.0/rshogi/src/records/formats/pack.rs +223 -0
- rshogi_py_avx2-0.4.0/rshogi/src/records/formats/sbinpack.rs +480 -0
- rshogi_py_avx2-0.4.0/rshogi/src/records/mod.rs +94 -0
- rshogi_py_avx2-0.4.0/rshogi/src/records/record.rs +522 -0
- rshogi_py_avx2-0.4.0/rshogi/src/records/time_control.rs +160 -0
- rshogi_py_avx2-0.4.0/rshogi/src/types/CLAUDE.md +7 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/bitboard.rs +119 -61
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/color.rs +72 -44
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/entering_king_rule.rs +3 -8
- rshogi_py_avx2-0.4.0/rshogi/src/types/eval.rs +68 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/file.rs +39 -9
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/game_result.rs +28 -14
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/hand.rs +59 -20
- rshogi_py_avx2-0.4.0/rshogi/src/types/mod.rs +91 -0
- rshogi_py_avx2-0.4.0/rshogi/src/types/moves.rs +1260 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/piece.rs +116 -135
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/rank.rs +43 -15
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/repetition_state.rs +2 -2
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/square.rs +162 -67
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/movegen_integration.rs +14 -4
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/movegen_pinned_pieces.rs +4 -3
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/perft.rs +27 -26
- rshogi_py_avx2-0.4.0/rshogi/tests/property_apply_move.proptest-regressions +7 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/property_apply_move.rs +13 -4
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/test_data/README.md +2 -2
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/yaneu_compatibility.rs +16 -16
- rshogi_py_avx2-0.4.0/rshogi-py/Cargo.lock +293 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi-py/Cargo.toml +1 -1
- rshogi_py_avx2-0.4.0/rshogi-py/README.md +63 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi-py/pyproject-avx2.toml +3 -2
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/__init__.py +51 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/book.py +25 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/core.py +5 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/initial_positions.py +21 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/io.py +106 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/numpy.py +14 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/record.py +19 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/serialization.py +5 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/svg.py +5 -0
- rshogi_py_avx2-0.4.0/rshogi-py/python/rshogi/types.py +25 -0
- rshogi_py_avx2-0.4.0/rshogi-py/src/lib.rs +1740 -0
- rshogi_py_avx2-0.4.0/rshogi-py/src/python_types.rs +871 -0
- rshogi_py_avx2-0.4.0/rshogi-py/src/svg.rs +256 -0
- rshogi_py_avx2-0.4.0/rshogi-py/uv.lock +8 -0
- rshogi_py_avx2-0.2.0/Cargo.lock +0 -831
- rshogi_py_avx2-0.2.0/Cargo.toml +0 -6
- rshogi_py_avx2-0.2.0/crates/rshogi/README.md +0 -28
- rshogi_py_avx2-0.2.0/crates/rshogi/src/board/mod.rs +0 -60
- rshogi_py_avx2-0.2.0/crates/rshogi/src/board/movegen/drops.rs +0 -205
- rshogi_py_avx2-0.2.0/crates/rshogi/src/board/movegen/mod.rs +0 -195
- rshogi_py_avx2-0.2.0/crates/rshogi/src/board/perft.rs +0 -306
- rshogi_py_avx2-0.2.0/crates/rshogi/src/records/formats/kif.rs +0 -853
- rshogi_py_avx2-0.2.0/crates/rshogi/src/records/formats/pack.rs +0 -190
- rshogi_py_avx2-0.2.0/crates/rshogi/src/records/mod.rs +0 -8
- rshogi_py_avx2-0.2.0/crates/rshogi/src/records/record.rs +0 -120
- rshogi_py_avx2-0.2.0/crates/rshogi/src/types/mod.rs +0 -38
- rshogi_py_avx2-0.2.0/crates/rshogi/src/types/moves.rs +0 -611
- rshogi_py_avx2-0.2.0/crates/rshogi-py/README.md +0 -28
- rshogi_py_avx2-0.2.0/crates/rshogi-py/src/lib.rs +0 -373
- {rshogi_py_avx2-0.2.0 → rshogi_py_avx2-0.4.0}/LICENSE +0 -0
- {rshogi_py_avx2-0.2.0 → rshogi_py_avx2-0.4.0}/README-avx2.md +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/LICENSE +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/README-avx2.md +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/benches/movegen.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/pyproject-avx2.toml +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/pyproject.toml +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/bitboard_pair.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/recaptures.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/basic.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/mod.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/pinned.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/promoted_pieces.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/tests/slider_moves.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/movegen/types.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/attacks.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/helpers.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/mod.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/rules/declaration_win.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/rules/helpers.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/rules/mod.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/position/tests/validation.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/board/tests/mod.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/records/formats/sfen.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/simd/mod.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/simd/u64x2_ops.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/simd/u64x4/avx2.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/simd/u64x4/mod.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/simd/u64x4/scalar.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/simd/u64x4/tests/mod.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/src/types/bitboard/tests/mod.rs +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/test_data/move_sequences.txt +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/test_data/perft_expectations.json +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/test_data/perft_results.txt +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/test_data/sfen_positions.txt +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi/tests/test_data/yaneuraou_legal_moves.json +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi-py/LICENSE +0 -0
- {rshogi_py_avx2-0.2.0/crates → rshogi_py_avx2-0.4.0}/rshogi-py/README-avx2.md +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rshogi-py-avx2"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Python bindings for the rshogi core library (AVX2 build)."
|
|
9
9
|
readme = "README-avx2.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -21,6 +21,7 @@ classifiers = [
|
|
|
21
21
|
urls = { "Repository" = "https://github.com/nyoki-mtl/rshogi" }
|
|
22
22
|
|
|
23
23
|
[tool.maturin]
|
|
24
|
-
module-name = "rshogi"
|
|
24
|
+
module-name = "rshogi._rshogi"
|
|
25
|
+
python-source = "python"
|
|
25
26
|
rustc-args = ["-C", "target-feature=+avx2"]
|
|
26
|
-
manifest-path = "
|
|
27
|
+
manifest-path = "rshogi-py/Cargo.toml"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""rshogi: Python bindings for shogi library.
|
|
2
|
+
|
|
3
|
+
This package provides structured imports through submodules:
|
|
4
|
+
|
|
5
|
+
Core primitives:
|
|
6
|
+
>>> from rshogi.core import Board, Move, Move16
|
|
7
|
+
|
|
8
|
+
Core primitives:
|
|
9
|
+
>>> from rshogi.core import Board, Move, Move16
|
|
10
|
+
|
|
11
|
+
Types and Constants:
|
|
12
|
+
>>> from rshogi.types import Color, Turn, PieceType, Piece, Square
|
|
13
|
+
|
|
14
|
+
Initial Positions:
|
|
15
|
+
>>> from rshogi.initial_positions import InitialPosition
|
|
16
|
+
|
|
17
|
+
Records:
|
|
18
|
+
>>> from rshogi.record import GameRecord, GameRecordMetadata, GameResult
|
|
19
|
+
|
|
20
|
+
Record conversion:
|
|
21
|
+
>>> record = GameRecord.from_kif(kif_text)
|
|
22
|
+
>>> kif_text = record.to_kif()
|
|
23
|
+
|
|
24
|
+
Record file I/O:
|
|
25
|
+
>>> record = GameRecord.read_kif("example.kif")
|
|
26
|
+
>>> record.write_kif("example_out.kif")
|
|
27
|
+
|
|
28
|
+
Book (Opening Book):
|
|
29
|
+
>>> from rshogi.book import StaticBook, MemoryBook, BookBuilder
|
|
30
|
+
>>> from rshogi.book import book_key_from_position, book_key_after
|
|
31
|
+
|
|
32
|
+
NumPy:
|
|
33
|
+
>>> from rshogi.numpy import PackedSfen, PackedSfenValue
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
# Import all submodules
|
|
37
|
+
from . import types, record, book, numpy, svg, core, initial_positions
|
|
38
|
+
|
|
39
|
+
# Version
|
|
40
|
+
__version__ = "0.4.0"
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
# Submodules
|
|
44
|
+
"types",
|
|
45
|
+
"core",
|
|
46
|
+
"record",
|
|
47
|
+
"book",
|
|
48
|
+
"numpy",
|
|
49
|
+
"svg",
|
|
50
|
+
"initial_positions",
|
|
51
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Book (opening book) types for shogi."""
|
|
2
|
+
|
|
3
|
+
from rshogi._rshogi import (
|
|
4
|
+
BookKey,
|
|
5
|
+
BookMove,
|
|
6
|
+
BookEntry,
|
|
7
|
+
MemoryBook,
|
|
8
|
+
StaticBook,
|
|
9
|
+
BookBuilder,
|
|
10
|
+
book_key_from_position,
|
|
11
|
+
book_key_after,
|
|
12
|
+
book_builder_from_game_record,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"BookKey",
|
|
17
|
+
"BookMove",
|
|
18
|
+
"BookEntry",
|
|
19
|
+
"MemoryBook",
|
|
20
|
+
"StaticBook",
|
|
21
|
+
"BookBuilder",
|
|
22
|
+
"book_key_from_position",
|
|
23
|
+
"book_key_after",
|
|
24
|
+
"book_builder_from_game_record",
|
|
25
|
+
]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Initial position SFEN definitions."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class InitialPosition(Enum):
|
|
7
|
+
STANDARD = "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"
|
|
8
|
+
EMPTY = "9/9/9/9/9/9/9/9/9 b - 1"
|
|
9
|
+
HANDICAP_LANCE = "lnsgkgsn1/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
10
|
+
HANDICAP_RIGHT_LANCE = "1nsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
11
|
+
HANDICAP_BISHOP = "lnsgkgsnl/1r7/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
12
|
+
HANDICAP_ROOK = "lnsgkgsnl/7b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
13
|
+
HANDICAP_ROOK_LANCE = "lnsgkgsn1/7b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
14
|
+
HANDICAP_2_PIECES = "lnsgkgsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
15
|
+
HANDICAP_4_PIECES = "1nsgkgsn1/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
16
|
+
HANDICAP_6_PIECES = "2sgkgs2/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
17
|
+
HANDICAP_8_PIECES = "3gkg3/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
18
|
+
HANDICAP_10_PIECES = "4k4/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__all__ = ["InitialPosition"]
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Parser and exporter functions for shogi game records."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from rshogi._rshogi import (
|
|
6
|
+
export_csa as _export_csa,
|
|
7
|
+
export_jkf as _export_jkf,
|
|
8
|
+
export_ki2 as _export_ki2,
|
|
9
|
+
export_kif as _export_kif,
|
|
10
|
+
parse_csa_str,
|
|
11
|
+
parse_kif_str,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _default_kif_encoding(path: Path) -> str:
|
|
16
|
+
suffix = path.suffix.lower()
|
|
17
|
+
if suffix == ".kifu":
|
|
18
|
+
return "utf-8"
|
|
19
|
+
return "shift_jis"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _default_ki2_encoding(path: Path) -> str:
|
|
23
|
+
suffix = path.suffix.lower()
|
|
24
|
+
if suffix == ".ki2":
|
|
25
|
+
return "shift_jis"
|
|
26
|
+
return "shift_jis"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def read_kif(path: str | Path, *, encoding: str | None = None):
|
|
30
|
+
"""Read a KIF file and return GameRecord."""
|
|
31
|
+
path = Path(path)
|
|
32
|
+
if encoding is None:
|
|
33
|
+
encoding = _default_kif_encoding(path)
|
|
34
|
+
text = path.read_text(encoding=encoding)
|
|
35
|
+
return parse_kif_str(text)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def read_csa(path: str | Path, *, encoding: str | None = "shift_jis"):
|
|
39
|
+
"""Read a CSA file and return GameRecord."""
|
|
40
|
+
text = Path(path).read_text(encoding=encoding)
|
|
41
|
+
return parse_csa_str(text)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def export_kif_str(record):
|
|
45
|
+
"""Export GameRecord to KIF string."""
|
|
46
|
+
return _export_kif(record)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def export_csa_str(record):
|
|
50
|
+
"""Export GameRecord to CSA string."""
|
|
51
|
+
return _export_csa(record)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def export_ki2_str(record):
|
|
55
|
+
"""Export GameRecord to KI2 string."""
|
|
56
|
+
return _export_ki2(record)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def export_jkf_str(record):
|
|
60
|
+
"""Export GameRecord to JKF string."""
|
|
61
|
+
return _export_jkf(record)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def write_kif(path: str | Path, record, *, encoding: str | None = None) -> None:
|
|
65
|
+
"""Write GameRecord as KIF file."""
|
|
66
|
+
path = Path(path)
|
|
67
|
+
if encoding is None:
|
|
68
|
+
encoding = _default_kif_encoding(path)
|
|
69
|
+
text = export_kif_str(record)
|
|
70
|
+
path.write_text(text, encoding=encoding)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def write_csa(path: str | Path, record, *, encoding: str | None = "shift_jis") -> None:
|
|
74
|
+
"""Write GameRecord as CSA file."""
|
|
75
|
+
text = export_csa_str(record)
|
|
76
|
+
Path(path).write_text(text, encoding=encoding)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def write_ki2(path: str | Path, record, *, encoding: str | None = None) -> None:
|
|
80
|
+
"""Write GameRecord as KI2 file."""
|
|
81
|
+
path = Path(path)
|
|
82
|
+
if encoding is None:
|
|
83
|
+
encoding = _default_ki2_encoding(path)
|
|
84
|
+
text = export_ki2_str(record)
|
|
85
|
+
path.write_text(text, encoding=encoding)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def write_jkf(path: str | Path, record, *, encoding: str | None = "utf-8") -> None:
|
|
89
|
+
"""Write GameRecord as JKF file."""
|
|
90
|
+
text = export_jkf_str(record)
|
|
91
|
+
Path(path).write_text(text, encoding=encoding)
|
|
92
|
+
|
|
93
|
+
__all__ = [
|
|
94
|
+
"read_kif",
|
|
95
|
+
"read_csa",
|
|
96
|
+
"parse_kif_str",
|
|
97
|
+
"parse_csa_str",
|
|
98
|
+
"export_kif_str",
|
|
99
|
+
"export_ki2_str",
|
|
100
|
+
"export_csa_str",
|
|
101
|
+
"export_jkf_str",
|
|
102
|
+
"write_kif",
|
|
103
|
+
"write_ki2",
|
|
104
|
+
"write_csa",
|
|
105
|
+
"write_jkf",
|
|
106
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""NumPy dtypes for packed SFEN and related data structures."""
|
|
2
|
+
|
|
3
|
+
from rshogi._rshogi import dtype
|
|
4
|
+
|
|
5
|
+
# Re-export the dtype module contents
|
|
6
|
+
__getattr__ = dtype.__getattr__
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
PackedSfen = dtype.PackedSfen
|
|
10
|
+
PackedSfenValue = dtype.PackedSfenValue
|
|
11
|
+
__all__ = ["PackedSfen", "PackedSfenValue"]
|
|
12
|
+
except (ImportError, AttributeError):
|
|
13
|
+
# numpy is not available
|
|
14
|
+
__all__ = []
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Game record types for shogi."""
|
|
2
|
+
|
|
3
|
+
from rshogi._rshogi import (
|
|
4
|
+
GameRecord,
|
|
5
|
+
GameRecordMetadata,
|
|
6
|
+
GameRecordResult,
|
|
7
|
+
MoveRecord,
|
|
8
|
+
TimeControl,
|
|
9
|
+
GameResult,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"GameRecord",
|
|
14
|
+
"GameRecordMetadata",
|
|
15
|
+
"GameRecordResult",
|
|
16
|
+
"MoveRecord",
|
|
17
|
+
"TimeControl",
|
|
18
|
+
"GameResult",
|
|
19
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Basic types and constants for shogi."""
|
|
2
|
+
|
|
3
|
+
from rshogi._rshogi import (
|
|
4
|
+
Color,
|
|
5
|
+
Turn,
|
|
6
|
+
PieceType,
|
|
7
|
+
Piece,
|
|
8
|
+
Square,
|
|
9
|
+
Bitboard,
|
|
10
|
+
Hand,
|
|
11
|
+
MoveType,
|
|
12
|
+
RepetitionState,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"Color",
|
|
17
|
+
"Turn",
|
|
18
|
+
"PieceType",
|
|
19
|
+
"Piece",
|
|
20
|
+
"Square",
|
|
21
|
+
"Bitboard",
|
|
22
|
+
"Hand",
|
|
23
|
+
"MoveType",
|
|
24
|
+
"RepetitionState",
|
|
25
|
+
]
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "rshogi"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
license = "MIT"
|
|
6
6
|
description = "Rust shogi library inspired by the Python cshogi API."
|
|
7
7
|
repository = "https://github.com/nyoki-mtl/rshogi"
|
|
8
|
+
keywords = ["shogi"]
|
|
9
|
+
categories = ["games"]
|
|
8
10
|
|
|
9
11
|
# We intend to publish only this crate to crates.io (B案).
|
|
10
12
|
# Python bindings are provided separately via crates/rshogi-py.
|
|
@@ -15,6 +17,9 @@ readme = "README.md"
|
|
|
15
17
|
thiserror = "1.0"
|
|
16
18
|
arrayvec = "0.7"
|
|
17
19
|
log = "0.4"
|
|
20
|
+
encoding_rs = "0.8"
|
|
21
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
22
|
+
serde_json = "1.0"
|
|
18
23
|
|
|
19
24
|
[features]
|
|
20
25
|
default = []
|
|
@@ -26,8 +31,6 @@ mate1ply-full = []
|
|
|
26
31
|
[dev-dependencies]
|
|
27
32
|
criterion = { version = "0.5", default-features = false, features = ["cargo_bench_support"] }
|
|
28
33
|
shogi_core = "0.1.5"
|
|
29
|
-
serde = { version = "1.0", features = ["derive"] }
|
|
30
|
-
serde_json = "1.0"
|
|
31
34
|
proptest = { version = "1.4", default-features = false, features = ["std"] }
|
|
32
35
|
|
|
33
36
|
[[bench]]
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# rshogi
|
|
2
|
+
|
|
3
|
+
Rust で実装された将棋ライブラリです。[YaneuraOu](https://github.com/yaneurao/YaneuraOu) の
|
|
4
|
+
Rust 版を目指し、高速かつ安全な将棋プリミティブを提供します。
|
|
5
|
+
|
|
6
|
+
Python バインディング ([rshogi-py](https://pypi.org/project/rshogi-py/)) は
|
|
7
|
+
[cshogi](https://github.com/TadaoYamaoka/cshogi) API にインスパイアされた設計です。
|
|
8
|
+
|
|
9
|
+
## 設計思想
|
|
10
|
+
|
|
11
|
+
### 1. 安全性優先
|
|
12
|
+
|
|
13
|
+
- `#![deny(unsafe_code)]` により unsafe Rust を禁止
|
|
14
|
+
- コンパイル時に検出可能なエラーは型システムで表現
|
|
15
|
+
- 実行時エラーは `Result` 型で明示的に扱う
|
|
16
|
+
|
|
17
|
+
### 2. 正確性
|
|
18
|
+
|
|
19
|
+
- YaneuraOu の合法手生成との互換性テストで正確性を担保
|
|
20
|
+
- Perft テストによる手生成の網羅的検証
|
|
21
|
+
- 千日手・入玉宣言勝ちなど将棋固有のルールを正しく実装
|
|
22
|
+
|
|
23
|
+
### 3. パフォーマンス
|
|
24
|
+
|
|
25
|
+
- ビットボードによる高速な盤面表現
|
|
26
|
+
- Magic Bitboard / PEXT による効率的なスライダー攻撃計算
|
|
27
|
+
- 差分更新による Zobrist ハッシュ計算
|
|
28
|
+
- SIMD 最適化(AVX2 対応)
|
|
29
|
+
|
|
30
|
+
### 4. 再利用性
|
|
31
|
+
|
|
32
|
+
- Rust と Python の両方から利用可能
|
|
33
|
+
- エンジンや評価関数とは分離し、純粋な局面管理に専念
|
|
34
|
+
- 明確な API 境界でダウンストリームプロジェクトに組み込みやすい
|
|
35
|
+
|
|
36
|
+
## アーキテクチャ
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
rshogi
|
|
40
|
+
├── types - 基本型(Color, Square, Move, Bitboard, Hand, ...)
|
|
41
|
+
├── board - 盤面管理と合法手生成
|
|
42
|
+
│ ├── Position - 盤面状態の管理
|
|
43
|
+
│ ├── movegen - 合法手生成
|
|
44
|
+
│ ├── attack_tables - 利きテーブル
|
|
45
|
+
│ └── ...
|
|
46
|
+
├── records - 棋譜フォーマット(KIF, CSA, JKF, SFEN, Pack, ...)
|
|
47
|
+
├── book - 定跡管理(MemoryBook, StaticBook)
|
|
48
|
+
└── mate - 詰み判定(1手詰め、3手詰め)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## クイックスタート
|
|
52
|
+
|
|
53
|
+
### 盤面操作
|
|
54
|
+
|
|
55
|
+
```rust
|
|
56
|
+
use rshogi::board::{self, Position};
|
|
57
|
+
use rshogi::types::Move16;
|
|
58
|
+
|
|
59
|
+
// 初期化(プログラム起動時に1回)
|
|
60
|
+
board::init();
|
|
61
|
+
|
|
62
|
+
// 平手初期局面
|
|
63
|
+
let mut pos = board::hirate_position();
|
|
64
|
+
|
|
65
|
+
// SFEN から局面を構築
|
|
66
|
+
let mut pos = board::position_from_sfen(
|
|
67
|
+
"lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"
|
|
68
|
+
).unwrap();
|
|
69
|
+
|
|
70
|
+
// 指し手の適用
|
|
71
|
+
let mv16 = Move16::from_usi("7g7f").unwrap();
|
|
72
|
+
let m = pos.to_move(mv16);
|
|
73
|
+
pos.apply_move(m);
|
|
74
|
+
|
|
75
|
+
// 指し手の取り消し
|
|
76
|
+
pos.undo_move(m);
|
|
77
|
+
|
|
78
|
+
// SFEN 出力
|
|
79
|
+
println!("{}", pos.to_sfen(None));
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 合法手生成
|
|
83
|
+
|
|
84
|
+
```rust
|
|
85
|
+
use rshogi::board::{self, Position, MoveList};
|
|
86
|
+
use rshogi::movegen::{Legal, generate_moves};
|
|
87
|
+
|
|
88
|
+
board::init();
|
|
89
|
+
let pos = board::hirate_position();
|
|
90
|
+
|
|
91
|
+
// 合法手を生成
|
|
92
|
+
let mut moves = MoveList::new();
|
|
93
|
+
generate_moves::<Legal>(&pos, &mut moves);
|
|
94
|
+
|
|
95
|
+
for m in moves.iter() {
|
|
96
|
+
println!("{}", m.to_usi());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 合法手の数
|
|
100
|
+
println!("合法手数: {}", moves.len());
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 棋譜の読み込み
|
|
104
|
+
|
|
105
|
+
```rust
|
|
106
|
+
use rshogi::records::formats::kif;
|
|
107
|
+
|
|
108
|
+
let kif_text = r#"
|
|
109
|
+
手合割:平手
|
|
110
|
+
手数----指手---------消費時間--
|
|
111
|
+
1 7六歩(77)
|
|
112
|
+
2 3四歩(33)
|
|
113
|
+
まで2手で中断
|
|
114
|
+
"#;
|
|
115
|
+
|
|
116
|
+
let record = kif::parse_kif_str(kif_text).unwrap();
|
|
117
|
+
println!("手数: {}", record.num_moves());
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 定跡の利用
|
|
121
|
+
|
|
122
|
+
```rust
|
|
123
|
+
use rshogi::board::{self, Position};
|
|
124
|
+
use rshogi::book::{Book, MemoryBook, BookBuilder, book_key_from_position};
|
|
125
|
+
|
|
126
|
+
board::init();
|
|
127
|
+
let pos = board::hirate_position();
|
|
128
|
+
|
|
129
|
+
// 定跡を構築(GameRecord から)
|
|
130
|
+
let mut builder = BookBuilder::default();
|
|
131
|
+
// builder.add_record(&record);
|
|
132
|
+
let book = builder.into_memory();
|
|
133
|
+
|
|
134
|
+
// 定跡を検索
|
|
135
|
+
let key = book_key_from_position(&pos);
|
|
136
|
+
if let Some(entry) = book.get(key) {
|
|
137
|
+
for mv in entry.moves() {
|
|
138
|
+
println!("{}: {}", mv.move16().to_usi(), mv.score());
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## モジュール詳細
|
|
144
|
+
|
|
145
|
+
### `types` - 基本型
|
|
146
|
+
|
|
147
|
+
将棋で使用する基本的な型を定義します。
|
|
148
|
+
|
|
149
|
+
| 型 | 説明 |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `Color` | 手番(先手 `BLACK` / 後手 `WHITE`) |
|
|
152
|
+
| `Square` | マス(0-80、9x9 盤面) |
|
|
153
|
+
| `File` | 筋(1-9) |
|
|
154
|
+
| `Rank` | 段(一-九) |
|
|
155
|
+
| `PieceType` | 駒種(歩、香、桂、銀、金、角、飛、玉、と、... ) |
|
|
156
|
+
| `Piece` | 駒(駒種 + 手番) |
|
|
157
|
+
| `Hand` | 持ち駒(各駒種の枚数をビットパック) |
|
|
158
|
+
| `Move` | 32bit 指し手(移動元・移動先・成り・駒打ちなど) |
|
|
159
|
+
| `Move16` | 16bit 指し手(コンパクト版) |
|
|
160
|
+
| `Bitboard` | 81bit ビットボード |
|
|
161
|
+
| `GameResult` | 対局結果(勝敗、千日手、入玉宣言など) |
|
|
162
|
+
|
|
163
|
+
### `board` - 盤面管理
|
|
164
|
+
|
|
165
|
+
`Position` 構造体で盤面状態を管理します。
|
|
166
|
+
|
|
167
|
+
**主要メソッド:**
|
|
168
|
+
|
|
169
|
+
| メソッド | 説明 |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `apply_move(m)` | 指し手を適用 |
|
|
172
|
+
| `undo_move(m)` | 指し手を取り消し |
|
|
173
|
+
| `is_legal(m)` | 合法手か判定 |
|
|
174
|
+
| `checkers()` | 王手している駒のビットボード |
|
|
175
|
+
| `in_check()` | 王手されているか |
|
|
176
|
+
| `is_mated()` | 詰んでいるか |
|
|
177
|
+
| `to_sfen(ply)` | SFEN 文字列を生成 |
|
|
178
|
+
| `key()` | Zobrist ハッシュキー |
|
|
179
|
+
|
|
180
|
+
### `board::movegen` - 合法手生成
|
|
181
|
+
|
|
182
|
+
ジェネリクスによる型安全な手生成 API を提供します。
|
|
183
|
+
|
|
184
|
+
```rust
|
|
185
|
+
use rshogi::board::{self, MoveList};
|
|
186
|
+
use rshogi::movegen::{generate_moves, Legal, Captures, Evasions};
|
|
187
|
+
|
|
188
|
+
board::init();
|
|
189
|
+
let pos = board::hirate_position();
|
|
190
|
+
let mut moves = MoveList::new();
|
|
191
|
+
|
|
192
|
+
// 全合法手
|
|
193
|
+
generate_moves::<Legal>(&pos, &mut moves);
|
|
194
|
+
|
|
195
|
+
// 駒を取る手のみ
|
|
196
|
+
generate_moves::<Captures>(&pos, &mut moves);
|
|
197
|
+
|
|
198
|
+
// 王手回避手(王手されている場合)
|
|
199
|
+
generate_moves::<Evasions>(&pos, &mut moves);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**手生成タイプ:**
|
|
203
|
+
|
|
204
|
+
| タイプ | 説明 |
|
|
205
|
+
|---|---|
|
|
206
|
+
| `Legal` | 全合法手 |
|
|
207
|
+
| `Captures` | 駒を取る手 |
|
|
208
|
+
| `Quiets` | 駒を取らない手 |
|
|
209
|
+
| `Evasions` | 王手回避手 |
|
|
210
|
+
| `Checks` | 王手をかける手 |
|
|
211
|
+
| `Recaptures` | 取り返し手 |
|
|
212
|
+
|
|
213
|
+
### `records` - 棋譜フォーマット
|
|
214
|
+
|
|
215
|
+
複数の棋譜フォーマットの読み書きをサポートします。
|
|
216
|
+
|
|
217
|
+
| フォーマット | パース | 出力 |
|
|
218
|
+
|---|:---:|:---:|
|
|
219
|
+
| KIF | ✅ | ✅ |
|
|
220
|
+
| KI2 | ✅ | ✅ |
|
|
221
|
+
| CSA | ✅ | ✅ |
|
|
222
|
+
| JKF | ❌ | ✅ |
|
|
223
|
+
| SFEN | ✅ | ✅ |
|
|
224
|
+
| Pack | ✅ | ✅ |
|
|
225
|
+
|
|
226
|
+
### `book` - 定跡
|
|
227
|
+
|
|
228
|
+
Zobrist ハッシュによる高速な定跡検索を提供します。
|
|
229
|
+
|
|
230
|
+
- `MemoryBook`: メモリ内で定跡を管理
|
|
231
|
+
- `StaticBook`: 静的にコンパイルされた定跡
|
|
232
|
+
- `BookBuilder`: `GameRecord` から定跡を構築
|
|
233
|
+
|
|
234
|
+
### `mate` - 詰み判定
|
|
235
|
+
|
|
236
|
+
高速な詰み判定ルーチンを提供します。
|
|
237
|
+
|
|
238
|
+
- `solve_mate_in_one()`: 1手詰め判定
|
|
239
|
+
- `solve_mate_in_three()`: 3手詰め判定
|
|
240
|
+
|
|
241
|
+
## 互換性
|
|
242
|
+
|
|
243
|
+
### YaneuraOu 互換
|
|
244
|
+
|
|
245
|
+
- 内部のビットボード表現、Zobrist ハッシュ、手のエンコーディングは YaneuraOu と互換
|
|
246
|
+
- `Move16` は YaneuraOu の `Move16` と同一のビットレイアウト
|
|
247
|
+
- Perft 結果が YaneuraOu と一致することを検証済み
|
|
248
|
+
|
|
249
|
+
### cshogi 互換
|
|
250
|
+
|
|
251
|
+
- Python バインディング (`rshogi-py`) は cshogi API を意識した設計
|
|
252
|
+
- `Board.apply_usi()`, `Board.legal_moves()` などの基本 API は cshogi と類似
|
|
253
|
+
|
|
254
|
+
## ベンチマーク(perft)
|
|
255
|
+
|
|
256
|
+
`data/bench/representative_positions.csv` の 4 局面で perft を計測します。\
|
|
257
|
+
スクリプトは `crates/rshogi/src/bin/perft_bench.rs` にあります(ネイティブ実行)。
|
|
258
|
+
|
|
259
|
+
### 実行方法(rshogi)
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
RUSTFLAGS="-C target-feature=+avx2" \
|
|
263
|
+
cargo run --release -p rshogi --bin perft_bench -- \
|
|
264
|
+
--depth 3 --positions data/bench/representative_positions.csv
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 参考: YaneuraOu(AVX2 / NNUE)
|
|
268
|
+
|
|
269
|
+
`_refs/YaneuraOu/build_outputs/` にバイナリを置き、`build_outputs/eval/nn.bin` を配置して実行しています。
|
|
270
|
+
|
|
271
|
+
### 計測結果(2026-02-03)
|
|
272
|
+
|
|
273
|
+
**環境**
|
|
274
|
+
|
|
275
|
+
- OS: Linux 6.6.87.2-microsoft-standard-WSL2
|
|
276
|
+
- CPU: x86_64 / AVX2
|
|
277
|
+
- depth=3
|
|
278
|
+
- 計測: `taskset -c 0` で単一コア固定、各エンジン 20 回の平均
|
|
279
|
+
|
|
280
|
+
**rshogi (AVX2 release)**
|
|
281
|
+
|
|
282
|
+
- total NPS(20回平均): **494,711,984**(≈ **494.7M**)
|
|
283
|
+
- median: 496.2M
|
|
284
|
+
- min/max: 461.3M / 509.7M
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
engine,rshogi
|
|
288
|
+
label,nodes,seconds,nps
|
|
289
|
+
position_1_early,37189,0.000402,92608779
|
|
290
|
+
position_2_advantage,1114656,0.003809,292642124
|
|
291
|
+
position_3_complex,8420492,0.015441,545319524
|
|
292
|
+
position_4_movegen_heavy,4809015,0.009270,518778784
|
|
293
|
+
total,14381352,0.028922,497249944.22
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**YaneuraOu NNUE (AVX2 release)**
|
|
297
|
+
|
|
298
|
+
- total NPS(20回平均): **484,928,355**(≈ **484.9M**)
|
|
299
|
+
- median: 495.9M
|
|
300
|
+
- min/max: 410.9M / 532.6M
|
|
301
|
+
|
|
302
|
+
```text
|
|
303
|
+
engine,yaneuraou_nnue
|
|
304
|
+
label,nodes,seconds,nps
|
|
305
|
+
position_1_early,37189,0.002000,18594500
|
|
306
|
+
position_2_advantage,1114656,0.005000,222931200
|
|
307
|
+
position_3_complex,8420492,0.013000,647730153
|
|
308
|
+
position_4_movegen_heavy,4809015,0.009000,534335000
|
|
309
|
+
total,14381352,0.029000,495908689.66
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## ライセンス
|
|
313
|
+
|
|
314
|
+
MIT License
|
|
@@ -11,7 +11,7 @@ fn bench_do_move(c: &mut Criterion) {
|
|
|
11
11
|
let to = Square::from_usi("7f").unwrap();
|
|
12
12
|
let piece = pos.piece_on(from);
|
|
13
13
|
let mv = Move::make(from, to, piece);
|
|
14
|
-
pos.
|
|
14
|
+
pos.apply_move(mv);
|
|
15
15
|
},
|
|
16
16
|
BatchSize::SmallInput,
|
|
17
17
|
);
|
|
@@ -27,8 +27,8 @@ fn bench_do_and_undo(c: &mut Criterion) {
|
|
|
27
27
|
},
|
|
28
28
|
|mut pos| {
|
|
29
29
|
let to = Square::from_usi("5e").unwrap();
|
|
30
|
-
let mv = Move::make_drop(PieceType::PAWN, to, pos.
|
|
31
|
-
pos.
|
|
30
|
+
let mv = Move::make_drop(PieceType::PAWN, to, pos.turn());
|
|
31
|
+
pos.apply_move(mv);
|
|
32
32
|
pos.undo_move(mv).unwrap();
|
|
33
33
|
},
|
|
34
34
|
BatchSize::SmallInput,
|