gammonview 3.0.1__tar.gz → 3.2.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.
- {gammonview-3.0.1 → gammonview-3.2.0}/.github/workflows/publish.yml +1 -1
- {gammonview-3.0.1 → gammonview-3.2.0}/CHANGELOG.md +41 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/CONTRIBUTING.md +1 -1
- {gammonview-3.0.1 → gammonview-3.2.0}/PKG-INFO +8 -8
- {gammonview-3.0.1 → gammonview-3.2.0}/README.md +4 -4
- {gammonview-3.0.1 → gammonview-3.2.0}/docs/CLI.md +2 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/docs/OGXM_JSON_SPEC_GAMMONVIEW.md +11 -7
- {gammonview-3.0.1 → gammonview-3.2.0}/docs/OGXM_V2_PROFILE.md +1 -1
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/match.py +14 -4
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/position.py +87 -4
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/presets.py +1 -1
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/README.md +1 -1
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/package.json +3 -3
- gammonview-3.2.0/gvformat-js/test/fixtures/ogxm2/annos-docs.json +1 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/annos-sha256.json +4 -4
- {gammonview-3.0.1 → gammonview-3.2.0}/pyproject.toml +3 -3
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/fixtures.py +13 -0
- gammonview-3.2.0/tests/golden/3WNK_g1Z-PLsh_HyvQ5j4a.fast.gva +1 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/golden/3WNK_g1Z-PLsh_HyvQ5j4a.fast.gvab +0 -0
- gammonview-3.2.0/tests/golden/5nqfGw9bWG3deTaU.fast.gva +1 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/golden/5nqfGw9bWG3deTaU.fast.gvab +0 -0
- gammonview-3.2.0/tests/golden/B4_SrGcsKAQmoTyHlgJCbM.fast.gva +1 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/golden/B4_SrGcsKAQmoTyHlgJCbM.fast.gvab +0 -0
- gammonview-3.2.0/tests/golden/MYdvw1qGuyaRUH__.fast.gva +1 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/golden/MYdvw1qGuyaRUH__.fast.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/golden/PROVENANCE.json +1 -1
- gammonview-3.2.0/tests/golden/baR-U643iUDpvzTC.fast.gva +1 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/golden/baR-U643iUDpvzTC.fast.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/regen_golden.py +2 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_analyze_position.py +64 -1
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_blocks_analysis.py +2 -2
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm_pipeline.py +12 -1
- gammonview-3.0.1/gvformat-js/test/fixtures/ogxm2/annos-docs.json +0 -1
- gammonview-3.0.1/tests/golden/3WNK_g1Z-PLsh_HyvQ5j4a.fast.gva +0 -1
- gammonview-3.0.1/tests/golden/5nqfGw9bWG3deTaU.fast.gva +0 -1
- gammonview-3.0.1/tests/golden/B4_SrGcsKAQmoTyHlgJCbM.fast.gva +0 -1
- gammonview-3.0.1/tests/golden/MYdvw1qGuyaRUH__.fast.gva +0 -1
- gammonview-3.0.1/tests/golden/baR-U643iUDpvzTC.fast.gva +0 -1
- {gammonview-3.0.1 → gammonview-3.2.0}/.gitattributes +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/.github/workflows/ci.yml +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/.github/workflows/engine.yml +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/.gitignore +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/.python-version +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/CLAUDE.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/LICENSE +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/THIRD-PARTY-NOTICES.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/assets/logo.png +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/docs/METHODOLOGY.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/docs/OGXM_COMPUTED_FIELDS.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/docs/PRESET_ACCURACY.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/docs/upstream-bgsage.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/docs/v1/OGXM_FORMAT_SPEC_GAMMONVIEW.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/experiments/2026-09-16-checker-mid-tier.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/experiments/2026-09-17-checker-mid-tier-followup.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/experiments/2026-09-19-cross-machine-costs.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/experiments/2026-09-20-corpus-rerun.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/experiments/2026-10-21-wc2-corpus.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/experiments/bench.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/__init__.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/batch.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/checker_eval.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/compare_gva.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/game_eval.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/loader.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/luck.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/ogxm_reconstructor.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/parentwatch.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/progress.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/reconstruct_mat.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvanalysis/share.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/__init__.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/basefill.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/bgf.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/binary.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/export.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/game_reconstructor.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/legality.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/mat.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/mat_parser.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/merge.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/met.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/notation.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/ogid.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/ogxm2.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/ogxm2_passthrough.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/ogxm2_writer.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/place.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/reader.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/share.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/stats.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat/xg.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/.gitignore +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/LICENSE +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/THIRD-PARTY-NOTICES.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/cli/README.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/cli/bgf2gva.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/cli/mat2gva.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/cli/xg2gva.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/package-lock.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/basefill.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/bgf2gva.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/binary.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/constants.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/export.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/index.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/legality.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/mat2gva.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/merge.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/met.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/notation.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/og2gva.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/ogid.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/ogxm2.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/ogxm2_passthrough.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/ogxm2_writer.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/place.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/reader.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/sha256.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/share.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/stats.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/src/xg2gva.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/3WNK_g1Z-PLsh_HyvQ5j4a.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/5nqfGw9bWG3deTaU.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/B4_SrGcsKAQmoTyHlgJCbM.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/C07OQCKyw4Pe-CnjFiAMYO.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/MYdvw1qGuyaRUH__.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/Sz-2PgKnvb6aFls69-qFXg.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/UL-CV6F9jMM-E1Pu.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/XCu3RJ0UvDg_Tldl.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/baR-U643iUDpvzTC.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/eXBNG5wZHS5Alu3P.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/hQ8sVn2LbTdF4wRm.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/rK7pXm4TqLb9NzWd.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/mat/uwvEbd63UvdX7SDin5o_Iw.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/annos-edits-sha256.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/annos.expected.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/annos.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/bgf-writer-sha256.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/blocks-docs.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/blocks-sha256.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/blocks.expected.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/blocks.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/cube-on-two.expected.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/cube-on-two.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/fields-docs.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/fields-sha256.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/fields.expected.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/fields.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/foreign.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/gen.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/match.expected.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/match.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/passthrough-sha256.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/resign.expected.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/resign.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/set-up.expected.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/set-up.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/two-blocks.expected.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/two-blocks.ogxm +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/v1-chunks.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/fixtures/ogxm2/writer-sha256.json +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-alternative-move-steps.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-basefill.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-bgf-alternatives.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-bgf-embedded-cube.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-bgf-move-steps.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-chunk-passthrough.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-equity-loss.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-illegal-move.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-illegal-play-steps.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-legality.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-mat.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-merge.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-met.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-og.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-ogid.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-ogxm2-annos.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-ogxm2-blocks.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-ogxm2-fields.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-ogxm2-limits.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-ogxm2-passthrough.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-ogxm2-writer.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-ogxm2.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-place.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-robustness.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-roundtrip.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-share.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-stats.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-xg-cube.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-xg-eval-levels.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-xg-move-steps.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/gvformat-js/test/test-xg-zero-win-eval.js +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/README.md +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/3WNK_g1Z-PLsh_HyvQ5j4a.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/5nqfGw9bWG3deTaU.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/B4_SrGcsKAQmoTyHlgJCbM.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/C07OQCKyw4Pe-CnjFiAMYO.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/MYdvw1qGuyaRUH__.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/Sz-2PgKnvb6aFls69-qFXg.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/UL-CV6F9jMM-E1Pu.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/XCu3RJ0UvDg_Tldl.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/baR-U643iUDpvzTC.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/eXBNG5wZHS5Alu3P.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/bgf/uwvEbd63UvdX7SDin5o_Iw.bgf +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/3WNK_g1Z-PLsh_HyvQ5j4a.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/5nqfGw9bWG3deTaU.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/B4_SrGcsKAQmoTyHlgJCbM.gva +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/B4_SrGcsKAQmoTyHlgJCbM.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/C07OQCKyw4Pe-CnjFiAMYO.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/MYdvw1qGuyaRUH__.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/Sz-2PgKnvb6aFls69-qFXg.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/UL-CV6F9jMM-E1Pu.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/XCu3RJ0UvDg_Tldl.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/baR-U643iUDpvzTC.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/eXBNG5wZHS5Alu3P.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/gv/uwvEbd63UvdX7SDin5o_Iw.gvab +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/3WNK_g1Z-PLsh_HyvQ5j4a.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/5nqfGw9bWG3deTaU.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/B4_SrGcsKAQmoTyHlgJCbM.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/C07OQCKyw4Pe-CnjFiAMYO.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/MYdvw1qGuyaRUH__.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/Sz-2PgKnvb6aFls69-qFXg.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/UL-CV6F9jMM-E1Pu.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/XCu3RJ0UvDg_Tldl.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/baR-U643iUDpvzTC.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/eXBNG5wZHS5Alu3P.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/hQ8sVn2LbTdF4wRm.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/rK7pXm4TqLb9NzWd.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/mat/uwvEbd63UvdX7SDin5o_Iw.mat +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/3WNK_g1Z-PLsh_HyvQ5j4a.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/5nqfGw9bWG3deTaU.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/B4_SrGcsKAQmoTyHlgJCbM.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/C07OQCKyw4Pe-CnjFiAMYO.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/MYdvw1qGuyaRUH__.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/Sz-2PgKnvb6aFls69-qFXg.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/UL-CV6F9jMM-E1Pu.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/XCu3RJ0UvDg_Tldl.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/baR-U643iUDpvzTC.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/eXBNG5wZHS5Alu3P.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/hQ8sVn2LbTdF4wRm.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/rK7pXm4TqLb9NzWd.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/samples/xg/uwvEbd63UvdX7SDin5o_Iw.xg +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/audit_corpus.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/gen_js_v2_fixtures.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/gen_ogxm2_annos_fixtures.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/gen_ogxm2_blocks_fixtures.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/gen_ogxm2_fields_fixtures.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/gen_ogxm2_passthrough_fixtures.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/ogxm2_annos_cases.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/ogxm2_blocks_cases.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/ogxm2_fields_cases.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/ogxm2_oracle.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/passthrough_cases.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/run_all.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_alternative_move_steps.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_analysis_orientation.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_basefill.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_bgf_alternatives.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_bgf_cube_response.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_bgf_move_steps.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_chunk_passthrough.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_count_illegal.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_cube_tiers.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_docs_presets.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_equity_loss.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_gvab_writer.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_illegal_move.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_illegal_play_steps.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_legality.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_loader_formats.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_luck_fill.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_merge_resign.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_met.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_annos.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_blocks.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_fields.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_fields_analysis.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_limits.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_passthrough.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_reference.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm2_writer.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm_conformance.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm_export.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_ogxm_stats.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_parent_watch.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_position_id.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_presets.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_read_gvab.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_reconstruct_mat.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_resign_actor.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_resign_errors.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_restated_play_analysis.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_screened_checker.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_share_link.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_xg_cube.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_xg_eval_levels.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_xg_move_steps.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/tests/test_xg_zero_win_eval.py +0 -0
- {gammonview-3.0.1 → gammonview-3.2.0}/uv.lock +0 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# must be done before the first run, because the project does not exist yet:
|
|
8
8
|
#
|
|
9
9
|
# PyPI project name : gammonview
|
|
10
|
-
# Owner :
|
|
10
|
+
# Owner : gammonview
|
|
11
11
|
# Repository name : gammonview-analysis
|
|
12
12
|
# Workflow name : publish.yml
|
|
13
13
|
# Environment name : pypi
|
|
@@ -13,6 +13,47 @@ when the repository was opened; they are kept because they record why things
|
|
|
13
13
|
are the way they are — particularly the breaking changes and the measurements
|
|
14
14
|
behind several design decisions. Dates are the tag dates.
|
|
15
15
|
|
|
16
|
+
## 3.2.0 — 2026-11-04
|
|
17
|
+
|
|
18
|
+
**`analyze_position` takes the money rules: Jacoby and beavers** *(added)*
|
|
19
|
+
|
|
20
|
+
`analyze_position(..., jacoby=None, beaver=None)` and `gvan-position
|
|
21
|
+
--jacoby/--no-jacoby --beaver/--no-beaver`. Until now every money position was
|
|
22
|
+
analysed under bgsage's defaults, Jacoby on and beavers allowed, with no way to
|
|
23
|
+
ask otherwise. A bool chooses the rule; left unset it is the id's own. The reply
|
|
24
|
+
gains `jacoby` and `beaver`, the rules actually applied, both `False` at any
|
|
25
|
+
match score, where bgsage ignores them. With beavers allowed, a wrong double is
|
|
26
|
+
answered with a beaver and the cube's `double_take_equity` is the beaver's
|
|
27
|
+
(twice the take's), with `is_beaver` set, as it always was.
|
|
28
|
+
|
|
29
|
+
**A money XGID's rules field is read as the rules** *(fixed)*
|
|
30
|
+
|
|
31
|
+
At money, the XGID field that holds the Crawford flag in a match holds the
|
|
32
|
+
rules instead -- "Jacoby+2xBeaver", in XG's own spec (eXtreme Gammon 2 Help,
|
|
33
|
+
"XGID"), now quoted in `parse_xgid`'s docstring. It was read as Crawford in both
|
|
34
|
+
cases, so a money "1" claimed a Crawford game and the Jacoby rule it stated was
|
|
35
|
+
lost, and so was the beaver bit. `PositionState` gains `jacoby` and `beaver`
|
|
36
|
+
(None for an OGID, which cannot say, and at a match score). Behaviour change:
|
|
37
|
+
unset, both follow the XGID, so a money XGID with "0" there -- which states
|
|
38
|
+
"No Jacoby, no Beaver" -- is now analysed with neither, where it was analysed
|
|
39
|
+
with both. An OGID is still analysed with both.
|
|
40
|
+
|
|
41
|
+
## 3.1.0 — 2026-10-22
|
|
42
|
+
|
|
43
|
+
**`engine_build` names the gammonview version that ran the analysis** *(changed)*
|
|
44
|
+
|
|
45
|
+
It was bgsage's version, which `model_id` (`gv-bgsage/<version>`) already
|
|
46
|
+
states. v2 separates the model from the software running it — HedgeHog puts a
|
|
47
|
+
network's UUID in `model_id` and a git hash here — and so now do we:
|
|
48
|
+
`engine_build` is `gammonview/<version>`. The presets, the screening and the
|
|
49
|
+
judging of cubes and resignations are this package's, and a fix to them changes
|
|
50
|
+
results with bgsage unchanged, as 3.0.1's resignations did; until now a file
|
|
51
|
+
could not say which side of such a fix it was made on. It is v2's own field, so
|
|
52
|
+
every v2 reader sees it, and nothing in the format changed.
|
|
53
|
+
|
|
54
|
+
The goldens are written with `engine_build` pinned to `gammonview/golden`
|
|
55
|
+
(`tests/fixtures.py`), so a version bump does not move them.
|
|
56
|
+
|
|
16
57
|
## 3.0.1 — 2026-10-22
|
|
17
58
|
|
|
18
59
|
**Appending an analysis no longer fails on a resignation only one file records** *(fix)*
|
|
@@ -6,7 +6,7 @@ you need to know before sending one.
|
|
|
6
6
|
## Getting set up
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
git clone https://github.com/
|
|
9
|
+
git clone https://github.com/gammonview/gammonview-analysis
|
|
10
10
|
cd gammonview-analysis
|
|
11
11
|
uv sync # gvformat + gvanalysis + bgsage + everything the tests need
|
|
12
12
|
```
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: gammonview
|
|
3
|
-
Version: 3.0
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: Backgammon match analysis — the pure-Python OGXM/GVA codec (`gvformat`) plus bgsage-powered match and position analysis (`gvanalysis`).
|
|
5
|
-
Project-URL: Homepage, https://github.com/
|
|
6
|
-
Project-URL: Repository, https://github.com/
|
|
7
|
-
Project-URL: Issues, https://github.com/
|
|
5
|
+
Project-URL: Homepage, https://github.com/gammonview/gammonview-analysis
|
|
6
|
+
Project-URL: Repository, https://github.com/gammonview/gammonview-analysis
|
|
7
|
+
Project-URL: Issues, https://github.com/gammonview/gammonview-analysis/issues
|
|
8
8
|
Author: Nicholas Vlamis
|
|
9
9
|
License-Expression: MIT
|
|
10
10
|
License-File: LICENSE
|
|
@@ -28,15 +28,15 @@ Requires-Dist: pyyaml>=6.0.3; extra == 'engine'
|
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
29
29
|
|
|
30
30
|
<p align="center">
|
|
31
|
-
<img src="https://raw.githubusercontent.com/
|
|
31
|
+
<img src="https://raw.githubusercontent.com/gammonview/gammonview-analysis/main/assets/logo.png"
|
|
32
32
|
alt="" width="104" height="104">
|
|
33
33
|
</p>
|
|
34
34
|
|
|
35
35
|
<h1 align="center">GammonView</h1>
|
|
36
36
|
|
|
37
37
|
<p align="center">
|
|
38
|
-
<a href="https://github.com/
|
|
39
|
-
<a href="https://github.com/
|
|
38
|
+
<a href="https://github.com/gammonview/gammonview-analysis/actions/workflows/ci.yml"><img src="https://github.com/gammonview/gammonview-analysis/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
39
|
+
<a href="https://github.com/gammonview/gammonview-analysis/actions/workflows/engine.yml"><img src="https://github.com/gammonview/gammonview-analysis/actions/workflows/engine.yml/badge.svg" alt="engine"></a>
|
|
40
40
|
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+"></a>
|
|
41
41
|
<a href="LICENSE"><img src="https://img.shields.io/badge/licence-MIT-green.svg" alt="Licence: MIT"></a>
|
|
42
42
|
</p>
|
|
@@ -82,7 +82,7 @@ the environment — it installs both packages in editable mode, plus bgsage and
|
|
|
82
82
|
the test dependencies:
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
git clone https://github.com/
|
|
85
|
+
git clone https://github.com/gammonview/gammonview-analysis.git
|
|
86
86
|
cd gammonview-analysis
|
|
87
87
|
uv sync
|
|
88
88
|
uv run python tests/run_all.py --fast # ~3s, no engine needed
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/
|
|
2
|
+
<img src="https://raw.githubusercontent.com/gammonview/gammonview-analysis/main/assets/logo.png"
|
|
3
3
|
alt="" width="104" height="104">
|
|
4
4
|
</p>
|
|
5
5
|
|
|
6
6
|
<h1 align="center">GammonView</h1>
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
9
|
-
<a href="https://github.com/
|
|
10
|
-
<a href="https://github.com/
|
|
9
|
+
<a href="https://github.com/gammonview/gammonview-analysis/actions/workflows/ci.yml"><img src="https://github.com/gammonview/gammonview-analysis/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
10
|
+
<a href="https://github.com/gammonview/gammonview-analysis/actions/workflows/engine.yml"><img src="https://github.com/gammonview/gammonview-analysis/actions/workflows/engine.yml/badge.svg" alt="engine"></a>
|
|
11
11
|
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+"></a>
|
|
12
12
|
<a href="LICENSE"><img src="https://img.shields.io/badge/licence-MIT-green.svg" alt="Licence: MIT"></a>
|
|
13
13
|
</p>
|
|
@@ -53,7 +53,7 @@ the environment — it installs both packages in editable mode, plus bgsage and
|
|
|
53
53
|
the test dependencies:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
git clone https://github.com/
|
|
56
|
+
git clone https://github.com/gammonview/gammonview-analysis.git
|
|
57
57
|
cd gammonview-analysis
|
|
58
58
|
uv sync
|
|
59
59
|
uv run python tests/run_all.py --fast # ~3s, no engine needed
|
|
@@ -174,6 +174,8 @@ position shape is matched (an XGID never matches it).
|
|
|
174
174
|
| Flag | Effect |
|
|
175
175
|
|---|---|
|
|
176
176
|
| `--level LEVEL` | `1ply`, `2ply`, `3ply`, `4ply`, `truncated1/2/3`, `rollout`. Default `3ply`. |
|
|
177
|
+
| `--jacoby` / `--no-jacoby` | Money games: analyse with or without the Jacoby rule (gammons count single while the cube is centred). Default: what the id says — an XGID's field 8 — and on for an OGID, which has no field for it. Ignored at a match score. |
|
|
178
|
+
| `--beaver` / `--no-beaver` | Money games: allow or forbid beavers. Default as for `--jacoby`: the XGID's field 8, allowed for an OGID. Ignored at a match score. |
|
|
177
179
|
| `--no-progress` | Suppress the rollout progress bar. |
|
|
178
180
|
|
|
179
181
|
At a rollout level a progress bar is drawn on **stderr**, so piping the report
|
|
@@ -220,7 +220,7 @@ ply. See [Multiple analyses](#multiple-analyses).
|
|
|
220
220
|
"timestamp": 1768141380,
|
|
221
221
|
"analysis_id": "ea7ae02e-7c4a-8759-861b-eec0502be9b7",
|
|
222
222
|
"complete": true,
|
|
223
|
-
"engine_build": "
|
|
223
|
+
"engine_build": "gammonview/3.1.0"
|
|
224
224
|
}
|
|
225
225
|
```
|
|
226
226
|
|
|
@@ -233,7 +233,7 @@ ply. See [Multiple analyses](#multiple-analyses).
|
|
|
233
233
|
| `model_id` | string | Engine identifier, free-form: a label, not a key. Our analyses write `gv-bgsage/<bgsage version>`; the converters write the foreign engine's bare name (`"xg"`, `"bgblitz"`, `"gnubg"`); another producer's is its own (HedgeHog's is a UUID) | `model_id` |
|
|
234
234
|
| `model_name` | string | A display name. Show `model_name ?? model_id` | `model_name` |
|
|
235
235
|
| `model_digest` | string | 64 lower-case hex digits | `model_digest` |
|
|
236
|
-
| `engine_build` | string | The build that ran
|
|
236
|
+
| `engine_build` | string | The build that ran the model. Ours write `gammonview/<version>` (before 3.1.0, the bgsage version `model_id` already names); another producer's is its own (HedgeHog's is a git hash) | `engine_build` |
|
|
237
237
|
| `producer` | uint | 0 OGX, 1 eXtreme Gammon, 2 external engine, 3 BGBlitz, 4 human annotation | `producer` |
|
|
238
238
|
| `complete` | bool | The block analyzed the whole match. Absent = unstated | `complete` |
|
|
239
239
|
| `coverage` | `[game_index, ply_index]`[] | The plies the block attempted, which can be more than it holds a decision for. Ascending, no repeats; always includes every ply the block holds a decision for | `coverage` |
|
|
@@ -911,10 +911,14 @@ The v1 byte layout is frozen in
|
|
|
911
911
|
the engine name alone would overstate its share of the answer: the screening in
|
|
912
912
|
`gvanalysis/checker_eval.py` chooses which moves are evaluated at full depth,
|
|
913
913
|
and the preset's tiers choose that depth, so two files both reading `"bgsage"`
|
|
914
|
-
can hold different numbers from the same engine.
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
914
|
+
can hold different numbers from the same engine. It carries no gammonview
|
|
915
|
+
version: `model_id` names the model, as v2 means it.
|
|
916
|
+
- `gvanalysis` writes `engine_build = "gammonview/<version>"`, the build that ran
|
|
917
|
+
the model: the presets, the screening and the judging of cubes and
|
|
918
|
+
resignations are gammonview's, and a fix to them changes results with bgsage
|
|
919
|
+
unchanged. Until 3.1.0 it repeated the bgsage version. The regression corpus
|
|
920
|
+
is written with it pinned to `gammonview/golden` (`tests/fixtures.py`), which
|
|
921
|
+
keeps the bytes fixed by the match and the engine alone.
|
|
918
922
|
- A match is `White = alphabetically first player` unless the document is the
|
|
919
923
|
analysis of an existing one, in which case it keeps the document's White.
|
|
920
924
|
|
|
@@ -960,7 +964,7 @@ annotation to fall back on.
|
|
|
960
964
|
"duration_ms": 12300,
|
|
961
965
|
"analysis_id": "ea7ae02e-7c4a-8759-861b-eec0502be9b7",
|
|
962
966
|
"complete": true,
|
|
963
|
-
"engine_build": "
|
|
967
|
+
"engine_build": "gammonview/3.1.0"
|
|
964
968
|
},
|
|
965
969
|
"games": [
|
|
966
970
|
{
|
|
@@ -91,7 +91,7 @@ One `ANAL` + `DECS` per analysis block, primary first.
|
|
|
91
91
|
| `analysis_info.analysis_id` | `analysis_id`. A block without one gets a deterministic id: four CRC32s over the match and the block's identity, stamped as a UUIDv8 |
|
|
92
92
|
| `analysis_info.model_id`, `model_name` | `model_id`, `model_name`, each exactly as stated: HedgeHog's `model_id` is a UUID, ours `gv-bgsage/<version>`. Show `model_name ?? model_id` |
|
|
93
93
|
| `analysis_info.timestamp`, `duration_ms`, `completed_at` (ms) | `started_at`, `duration_ms`, `completed_at` |
|
|
94
|
-
| `analysis_info.producer`, `complete`, `model_digest` (hex), `engine_build`, `cube_efficiency`, `tables`, `dials`, `sources` | the same fields. Ours states `engine_build` (
|
|
94
|
+
| `analysis_info.producer`, `complete`, `model_digest` (hex), `engine_build`, `cube_efficiency`, `tables`, `dials`, `sources` | the same fields. Ours states `engine_build` (`gammonview/<version>`; `model_id` names bgsage) and `complete` |
|
|
95
95
|
| `analysis_info.coverage` | `coverage`, as `[game_index, ply_index]` pairs in the document's own plies |
|
|
96
96
|
| `analysis_info.currency` | `currency`, when it is not the match's default |
|
|
97
97
|
| `analysis_info.ply` | the block level's `checker_ply` |
|
|
@@ -116,11 +116,21 @@ def model_id() -> str:
|
|
|
116
116
|
|
|
117
117
|
|
|
118
118
|
def engine_build() -> str | None:
|
|
119
|
-
"""
|
|
120
|
-
|
|
121
|
-
the
|
|
119
|
+
"""``gammonview/<version>``, as v2's ``engine_build``: the build that ran.
|
|
120
|
+
|
|
121
|
+
v2 separates the model from the software running it -- HedgeHog states a
|
|
122
|
+
network's UUID in ``model_id`` and a git hash here -- and so do we:
|
|
123
|
+
``model_id`` names bgsage, whose networks ship inside its package, and
|
|
124
|
+
this names the code that drove it. The presets, the screening and the
|
|
125
|
+
judging of cubes and resignations are this package's, and a fix to them
|
|
126
|
+
(3.0.1's resignations) changes results with bgsage unchanged.
|
|
127
|
+
|
|
128
|
+
Until 3.1.0 this was bgsage's version again, which said nothing
|
|
129
|
+
``model_id`` did not. ``None`` where the distribution metadata is missing
|
|
130
|
+
(a source tree on ``sys.path``).
|
|
131
|
+
"""
|
|
122
132
|
try:
|
|
123
|
-
return _metadata.version("
|
|
133
|
+
return f"gammonview/{_metadata.version('gammonview')}"
|
|
124
134
|
except Exception:
|
|
125
135
|
return None
|
|
126
136
|
|
|
@@ -58,6 +58,12 @@ class PositionState:
|
|
|
58
58
|
#: perspective either way; this is what maps a move back to the absolute
|
|
59
59
|
#: point numbering the OGXM step form (and every consumer of it) uses.
|
|
60
60
|
mover_is_white: bool = True
|
|
61
|
+
#: The money-game Jacoby rule, when the id says: an XGID's rules field
|
|
62
|
+
#: does at money, an OGID never does (None). Always None at a match score.
|
|
63
|
+
jacoby: bool | None = None
|
|
64
|
+
#: Whether beavers are allowed, the other half of that field; None in the
|
|
65
|
+
#: same cases.
|
|
66
|
+
beaver: bool | None = None
|
|
61
67
|
|
|
62
68
|
|
|
63
69
|
#: Back-compat alias -- this was XGID-only before OGID input was added.
|
|
@@ -65,6 +71,32 @@ XGIDState = PositionState
|
|
|
65
71
|
|
|
66
72
|
|
|
67
73
|
def parse_xgid(xgid: str) -> PositionState:
|
|
74
|
+
"""Parse an XGID into the mover-perspective state bgsage analyses.
|
|
75
|
+
|
|
76
|
+
The XGID is eXtreme Gammon's, specified in its own help ("XGID", eXtreme
|
|
77
|
+
Gammon 2 Help rev. 1.01, 2011, pp. 145-146) as ten colon-separated fields:
|
|
78
|
+
|
|
79
|
+
1. Position 26 chars: the top player's bar, points 1-24 from the
|
|
80
|
+
bottom player's side, the bottom player's bar. '-' empty,
|
|
81
|
+
'A'-'P' 1-16 bottom-player checkers, 'a'-'p' top-player.
|
|
82
|
+
2. Cube the cube is 2**value.
|
|
83
|
+
3. Cube pos. 1 bottom player owns it, 0 centred, -1 top player.
|
|
84
|
+
4. Turn 1 the bottom player's turn, -1 the top player's.
|
|
85
|
+
5. Dice "00" to roll or double, "D" doubled (take or drop), "B"
|
|
86
|
+
beavered, "R" raccooned, or the two dice ("35").
|
|
87
|
+
6. Score 1 the bottom player's.
|
|
88
|
+
7. Score 2 the top player's.
|
|
89
|
+
8. Crawford, Jacoby
|
|
90
|
+
"Match play: 1 means the current game is Crawford, 0 means
|
|
91
|
+
the current game is not played with the Crawford rule.
|
|
92
|
+
Unlimited games: the value is a Jacoby+2xBeaver" --
|
|
93
|
+
0 none, 1 Jacoby, 2 beaver, 3 both.
|
|
94
|
+
9. Match length 0 for unlimited games (money).
|
|
95
|
+
10. Max cube 2**value.
|
|
96
|
+
|
|
97
|
+
(GNU Backgammon's ``SetXGID`` reads field 8 the same way.) Field 10 is
|
|
98
|
+
optional here, as it is in ids found in the wild.
|
|
99
|
+
"""
|
|
68
100
|
s = xgid.strip()
|
|
69
101
|
if s.upper().startswith("XGID="):
|
|
70
102
|
s = s[5:]
|
|
@@ -120,7 +152,13 @@ def parse_xgid(xgid: str) -> PositionState:
|
|
|
120
152
|
die2 = int(dice_str[1]) if len(dice_str) > 1 and dice_str[1].isdigit() else 0
|
|
121
153
|
|
|
122
154
|
match_len = int(parts[8]) if parts[8].lstrip("-").isdigit() else 0
|
|
123
|
-
|
|
155
|
+
# Field 8 is two fields in one (see the docstring): the Crawford flag in a
|
|
156
|
+
# match, Jacoby + 2 x Beaver at money -- so a money "1" is the Jacoby rule,
|
|
157
|
+
# not a Crawford game money cannot have.
|
|
158
|
+
rules = int(parts[7]) if parts[7].isdigit() else 0
|
|
159
|
+
is_crawford = match_len > 0 and rules == 1
|
|
160
|
+
jacoby = bool(rules & 1) if match_len <= 0 else None
|
|
161
|
+
beaver = bool(rules & 2) if match_len <= 0 else None
|
|
124
162
|
|
|
125
163
|
if match_len > 0:
|
|
126
164
|
# Scores are written player 1 (White) first; `away1` is the MOVER's.
|
|
@@ -141,7 +179,7 @@ def parse_xgid(xgid: str) -> PositionState:
|
|
|
141
179
|
|
|
142
180
|
return PositionState(
|
|
143
181
|
board, die1, die2, cube_value, cube_owner, away1, away2, is_crawford,
|
|
144
|
-
mover_is_white=mover_is_white,
|
|
182
|
+
mover_is_white=mover_is_white, jacoby=jacoby, beaver=beaver,
|
|
145
183
|
)
|
|
146
184
|
|
|
147
185
|
|
|
@@ -232,6 +270,8 @@ def analyze_position(
|
|
|
232
270
|
max_alternatives: int = MAX_ALTERNATIVES,
|
|
233
271
|
analyzer=None,
|
|
234
272
|
on_progress: "Callable[[int, int, str], None] | None" = None,
|
|
273
|
+
jacoby: bool | None = None,
|
|
274
|
+
beaver: bool | None = None,
|
|
235
275
|
) -> dict:
|
|
236
276
|
"""Analyze one position and return the result as an OGXM-shaped dict.
|
|
237
277
|
|
|
@@ -253,6 +293,22 @@ def analyze_position(
|
|
|
253
293
|
one costs ~40ms, worth reusing across requests); it must have been built at
|
|
254
294
|
``level``, which is reported back as ``eval_level``.
|
|
255
295
|
|
|
296
|
+
``jacoby`` is the money-game rule the position is played under: gammons
|
|
297
|
+
and backgammons count single while the cube is centred. Left as ``None``
|
|
298
|
+
it is the id's own: a money XGID states it in its rules field, and an OGID,
|
|
299
|
+
which cannot, is read under the rule (bgsage's own default). A bool
|
|
300
|
+
overrides the id. It means nothing at a match score, where bgsage ignores
|
|
301
|
+
it, and the reply's ``jacoby`` reports the rule actually applied -- so it
|
|
302
|
+
is ``False`` for every match position.
|
|
303
|
+
|
|
304
|
+
``beaver`` is the same for beavers: whether a player doubled may redouble
|
|
305
|
+
at once and keep the cube. Left as ``None`` it is the XGID's own beaver bit,
|
|
306
|
+
and allowed for an OGID (bgsage's default). Allowed, a wrong double --
|
|
307
|
+
double/take below zero -- is answered with a beaver, and the cube's
|
|
308
|
+
``double_take_equity`` is that beaver's (twice the take's), with
|
|
309
|
+
``is_beaver`` set. The reply's ``beaver`` is the rule applied, ``False`` at
|
|
310
|
+
a match score.
|
|
311
|
+
|
|
256
312
|
``on_progress(completed, total, phase)`` reports a rollout's progress; it is
|
|
257
313
|
never called at the full-width levels, which return too fast to report.
|
|
258
314
|
``phase`` is ``"trials"`` for the planned work and ``"finalizing"`` for the
|
|
@@ -280,6 +336,13 @@ def analyze_position(
|
|
|
280
336
|
away2=state.away2,
|
|
281
337
|
is_crawford=state.is_crawford,
|
|
282
338
|
)
|
|
339
|
+
money = not state.away1 and not state.away2
|
|
340
|
+
if jacoby is None:
|
|
341
|
+
jacoby = state.jacoby if state.jacoby is not None else True
|
|
342
|
+
if beaver is None:
|
|
343
|
+
beaver = state.beaver if state.beaver is not None else True
|
|
344
|
+
match_kwargs["jacoby"] = jacoby
|
|
345
|
+
match_kwargs["beaver"] = beaver
|
|
283
346
|
|
|
284
347
|
started = time.perf_counter()
|
|
285
348
|
result: dict = {
|
|
@@ -292,6 +355,8 @@ def analyze_position(
|
|
|
292
355
|
"away1": state.away1,
|
|
293
356
|
"away2": state.away2,
|
|
294
357
|
"is_crawford": state.is_crawford,
|
|
358
|
+
"jacoby": bool(jacoby) and money,
|
|
359
|
+
"beaver": bool(beaver) and money,
|
|
295
360
|
"dice": [state.die1, state.die2] if is_checker else None,
|
|
296
361
|
}
|
|
297
362
|
|
|
@@ -431,6 +496,17 @@ def main() -> None:
|
|
|
431
496
|
parser.add_argument(
|
|
432
497
|
"--level", default="3ply", choices=EVAL_LEVELS,
|
|
433
498
|
help="Eval level (default: 3ply)")
|
|
499
|
+
parser.add_argument(
|
|
500
|
+
"--jacoby", action=argparse.BooleanOptionalAction, default=None,
|
|
501
|
+
help="Money games: analyse with or without the Jacoby rule, gammons "
|
|
502
|
+
"counting single while the cube is centred. Default: what the id "
|
|
503
|
+
"says -- an XGID's rules field -- and on for an OGID, which cannot "
|
|
504
|
+
"say. Ignored at a match score")
|
|
505
|
+
parser.add_argument(
|
|
506
|
+
"--beaver", action=argparse.BooleanOptionalAction, default=None,
|
|
507
|
+
help="Money games: allow or forbid beavers. Default: what the id says "
|
|
508
|
+
"-- an XGID's rules field -- and allowed for an OGID. Ignored at a "
|
|
509
|
+
"match score")
|
|
434
510
|
parser.add_argument(
|
|
435
511
|
"--no-progress", action="store_true",
|
|
436
512
|
help="Suppress the rollout progress bar (it is stderr-only and already "
|
|
@@ -439,7 +515,13 @@ def main() -> None:
|
|
|
439
515
|
|
|
440
516
|
fmt = "OGID" if looks_like_ogid(args.position_id) else "XGID"
|
|
441
517
|
state = parse_position_id(args.position_id)
|
|
442
|
-
|
|
518
|
+
jacoby = args.jacoby if args.jacoby is not None else (
|
|
519
|
+
state.jacoby if state.jacoby is not None else True)
|
|
520
|
+
beaver = args.beaver if args.beaver is not None else (
|
|
521
|
+
state.beaver if state.beaver is not None else True)
|
|
522
|
+
context = ("money game, " + ("Jacoby" if jacoby else "no Jacoby")
|
|
523
|
+
+ (", beavers" if beaver else ", no beavers")
|
|
524
|
+
if state.away1 == 0 else f"match {state.away1}-away vs {state.away2}-away")
|
|
443
525
|
print(f"Position ({fmt}): cube={state.cube_value} ({state.cube_owner}) {context}"
|
|
444
526
|
+ (" [Crawford]" if state.is_crawford else ""))
|
|
445
527
|
|
|
@@ -468,7 +550,8 @@ def main() -> None:
|
|
|
468
550
|
|
|
469
551
|
try:
|
|
470
552
|
result = analyze_position(args.position_id, level=args.level,
|
|
471
|
-
on_progress=_progress
|
|
553
|
+
on_progress=_progress, jacoby=jacoby,
|
|
554
|
+
beaver=beaver)
|
|
472
555
|
finally:
|
|
473
556
|
if bar is not None:
|
|
474
557
|
bar.clear()
|
|
@@ -25,7 +25,7 @@ definition. A built-in's revision is bumped whenever anything that can move its
|
|
|
25
25
|
results changes -- its levels and thresholds, and the screening constants in
|
|
26
26
|
`checker_eval` -- and `_REVISIONS` pins the digest each revision stood for, so
|
|
27
27
|
`test_presets` fails if a definition changes without a new revision. Two
|
|
28
|
-
analyses with the same label and
|
|
28
|
+
analyses with the same label, `model_id` and `engine_build` were produced the same
|
|
29
29
|
way; a caller that needs that guarantee passes `name@revision` and is refused
|
|
30
30
|
if this install runs anything else. Resign errors are an analysis option, not a
|
|
31
31
|
preset's: an analysis that judged them is labelled `world_class@2+resign`.
|
|
@@ -7,7 +7,7 @@ OGIDs. **No engine, no WebAssembly, no build step.** One runtime
|
|
|
7
7
|
dependency (`pako`, for zlib).
|
|
8
8
|
|
|
9
9
|
This is the browser half of
|
|
10
|
-
[gammonview-analysis](https://github.com/
|
|
10
|
+
[gammonview-analysis](https://github.com/gammonview/gammonview-analysis): Python
|
|
11
11
|
writes `.gvab` server-side, this reads it client-side. It is an ESM mirror of the
|
|
12
12
|
Python `gvformat` package and **the definitive copy of the JavaScript** — the
|
|
13
13
|
port is maintained here, not downstream.
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
"description": "OGXM binary codec — read/write .gvab match files",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "git+https://github.com/
|
|
13
|
+
"url": "git+https://github.com/gammonview/gammonview-analysis.git",
|
|
14
14
|
"directory": "gvformat-js"
|
|
15
15
|
},
|
|
16
|
-
"homepage": "https://github.com/
|
|
16
|
+
"homepage": "https://github.com/gammonview/gammonview-analysis/tree/main/gvformat-js",
|
|
17
17
|
"bugs": {
|
|
18
|
-
"url": "https://github.com/
|
|
18
|
+
"url": "https://github.com/gammonview/gammonview-analysis/issues"
|
|
19
19
|
},
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|