weiss-sim 0.1.2__tar.gz → 0.1.3__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.
Files changed (75) hide show
  1. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/Cargo.lock +2 -2
  2. weiss_sim-0.1.3/PKG-INFO +421 -0
  3. weiss_sim-0.1.3/README.md +394 -0
  4. weiss_sim-0.1.3/pyproject.toml +49 -0
  5. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/Cargo.toml +1 -1
  6. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_py/Cargo.toml +1 -1
  7. weiss_sim-0.1.2/PKG-INFO +0 -5
  8. weiss_sim-0.1.2/pyproject.toml +0 -25
  9. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/Cargo.toml +0 -0
  10. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/python/weiss_sim/__init__.py +0 -0
  11. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/python/weiss_sim/rl.py +0 -0
  12. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/benches/alloc_benches.rs +0 -0
  13. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/benches/core_benches.rs +0 -0
  14. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/bin/carddb_pack.rs +0 -0
  15. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/bin/replay_dump.rs +0 -0
  16. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/config.rs +0 -0
  17. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/db.rs +0 -0
  18. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/effects.rs +0 -0
  19. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/encode.rs +0 -0
  20. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/env/interaction.rs +0 -0
  21. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/env/modifiers.rs +0 -0
  22. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/env/movement.rs +0 -0
  23. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/env/phases.rs +0 -0
  24. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/env/tests.rs +0 -0
  25. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/env/visibility.rs +0 -0
  26. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/env.rs +0 -0
  27. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/events.rs +0 -0
  28. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/fingerprint.rs +0 -0
  29. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/legal.rs +0 -0
  30. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/lib.rs +0 -0
  31. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/pool.rs +0 -0
  32. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/replay.rs +0 -0
  33. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/rules.rs +0 -0
  34. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/state.rs +0 -0
  35. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/util.rs +0 -0
  36. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/src/visibility_policy.rs +0 -0
  37. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/ability_index_tests.rs +0 -0
  38. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/ability_template_expansion_tests.rs +0 -0
  39. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/action_space_reachability_tests.rs +0 -0
  40. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/attack_legality_tests.rs +0 -0
  41. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/auto_resolve_cap_tests.rs +0 -0
  42. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/choice_paging_tests.rs +0 -0
  43. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/combat_basic_tests.rs +0 -0
  44. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/combat_damage_tests.rs +0 -0
  45. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/combat_support.rs +0 -0
  46. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/concede_tests.rs +0 -0
  47. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/control_change_tests.rs +0 -0
  48. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/deck_support.rs +0 -0
  49. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/determinism_tests.rs +0 -0
  50. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/end_phase_trigger_tests.rs +0 -0
  51. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/engine_support.rs +0 -0
  52. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/event_damage_pipeline_tests.rs +0 -0
  53. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/fingerprint_tests.rs +0 -0
  54. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/illegal_action_tests.rs +0 -0
  55. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/level_encore_tests.rs +0 -0
  56. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/modifier_duration_tests.rs +0 -0
  57. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/obs_encoding_layout_tests.rs +0 -0
  58. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/obs_reason_bits_tests.rs +0 -0
  59. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/priority_action_tests.rs +0 -0
  60. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/priority_window_tests.rs +0 -0
  61. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/property_invariants_tests.rs +0 -0
  62. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/public_obs_invariance_tests.rs +0 -0
  63. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/replacement_layer_tests.rs +0 -0
  64. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/replay_bundle_support.rs +0 -0
  65. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/replay_io_tests.rs +0 -0
  66. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/stack_and_modifiers_tests.rs +0 -0
  67. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/targeting_tests.rs +0 -0
  68. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/trigger_order_tests.rs +0 -0
  69. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/trigger_refresh_tests.rs +0 -0
  70. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/trigger_resolution_tests.rs +0 -0
  71. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/turn_cycle_tests.rs +0 -0
  72. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/unification_coverage_tests.rs +0 -0
  73. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/wsdb_io_tests.rs +0 -0
  74. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_core/tests/zone_move_semantics_tests.rs +0 -0
  75. {weiss_sim-0.1.2 → weiss_sim-0.1.3}/weiss_py/src/lib.rs +0 -0
@@ -1395,7 +1395,7 @@ dependencies = [
1395
1395
 
1396
1396
  [[package]]
1397
1397
  name = "weiss_core"
1398
- version = "0.1.2"
1398
+ version = "0.1.3"
1399
1399
  dependencies = [
1400
1400
  "anyhow",
1401
1401
  "bitvec",
@@ -1417,7 +1417,7 @@ dependencies = [
1417
1417
 
1418
1418
  [[package]]
1419
1419
  name = "weiss_py"
1420
- version = "0.1.2"
1420
+ version = "0.1.3"
1421
1421
  dependencies = [
1422
1422
  "anyhow",
1423
1423
  "numpy",
@@ -0,0 +1,421 @@
1
+ Metadata-Version: 2.4
2
+ Name: weiss-sim
3
+ Version: 0.1.3
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: License :: OSI Approved :: Apache Software License
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Classifier: Programming Language :: Rust
12
+ Classifier: Topic :: Games/Entertainment
13
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
+ Requires-Dist: numpy>=1.23
15
+ Summary: Deterministic Weiss Schwarz simulator with a Rust core and Python bindings.
16
+ Keywords: weiss-schwarz,reinforcement-learning,simulation,pyo3,rl
17
+ Author: Lallan
18
+ License: MIT OR Apache-2.0
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
21
+ Project-URL: Homepage, https://github.com/victorwp288/weiss-schwarz-simulator
22
+ Project-URL: Repository, https://github.com/victorwp288/weiss-schwarz-simulator
23
+ Project-URL: Documentation, https://victorwp288.github.io/weiss-schwarz-simulator/rustdoc/
24
+ Project-URL: Issues, https://github.com/victorwp288/weiss-schwarz-simulator/issues
25
+ Project-URL: Changelog, https://github.com/victorwp288/weiss-schwarz-simulator/blob/main/CHANGELOG.md
26
+
27
+ # Weiss Schwarz Simulator (Rust core + Python bindings)
28
+
29
+ [![CI](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/ci.yml/badge.svg)](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/ci.yml)
30
+ [![Wheels](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/wheels.yml/badge.svg)](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/wheels.yml)
31
+ [![Benchmarks](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/benchmarks.yml/badge.svg)](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/benchmarks.yml)
32
+ [![Security](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/security.yml/badge.svg?branch=main)](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/security.yml)
33
+ [![Docs](https://img.shields.io/badge/docs-rustdoc-blue)](https://victorwp288.github.io/weiss-schwarz-simulator/rustdoc/)
34
+ [![PyPI](https://img.shields.io/pypi/v/weiss-sim.svg)](https://pypi.org/project/weiss-sim/)
35
+ [![Changelog](https://img.shields.io/badge/changelog-view-blue)](https://github.com/victorwp288/weiss-schwarz-simulator/blob/main/CHANGELOG.md)
36
+ [![Last Commit](https://img.shields.io/github/last-commit/victorwp288/weiss-schwarz-simulator.svg)](https://github.com/victorwp288/weiss-schwarz-simulator/commits/main)
37
+
38
+ Deterministic, RL-first Weiss Schwarz simulation: **Rust runs the hot loop**, advances until a **decision point**, and exposes a **fixed action space + mask** (and legal action ids) for efficient batched training. Python gets a thin `EnvPool` wrapper for stepping many environments in parallel.
39
+
40
+ ---
41
+
42
+ ## Why this exists
43
+
44
+ Weiss Schwarz has hidden information, branching, and timing windows. For RL you typically want:
45
+
46
+ - **Determinism**: reproduce episodes from a seed and action sequence.
47
+ - **Few boundary crossings**: avoid Python↔Rust overhead for micro-steps.
48
+ - **Stable action space**: fixed-size actions with legality masking.
49
+ - **Introspectability**: canonical action descriptions, replays, and event logs.
50
+
51
+ This repo is built around those constraints.
52
+
53
+ ---
54
+
55
+ ## Highlights
56
+
57
+ - **Advance-until-decision loop**: engine runs internally until a player must act.
58
+ - **Canonical legal actions**: `ActionDesc` list is the single truth source.
59
+ - **Fixed action id space + mask**: derived from canonical actions and **versioned** (`ACTION_ENCODING_VERSION`).
60
+ - **Legal action ids (fast)**: use ids to avoid Python-side mask scans in hot loops.
61
+ - **Fixed-length observations**: `int32` arrays, **versioned** (`OBS_ENCODING_VERSION`).
62
+ - **Multicore stepping**: `EnvPool` uses Rayon; Python binding releases the GIL.
63
+ - **Replays**: deterministic, versioned, optional event stream, public-safe sanitization when enabled.
64
+ - **Curriculum switches**: gate rules/features for training curricula.
65
+
66
+ Each environment is deterministic given its seed and action sequence. Parallel batch stepping does not change outcomes because envs are fully isolated.
67
+
68
+ ---
69
+
70
+ ## Automation & Benchmarks
71
+
72
+ - **CI** runs on every push/PR: Rust fmt/clippy/tests + Python ruff/pytest.
73
+ - **Wheels** build on pushes to `main` (artifacts), and tags `v*` publish to GitHub Releases + PyPI.
74
+ - **Benchmarks** run on pushes to `main`; history + charts are published via GitHub Pages.
75
+ - **Docs** are published to GitHub Pages on pushes to `main`.
76
+
77
+ Latest benchmark history and charts:
78
+ https://victorwp288.github.io/weiss-schwarz-simulator/benchmarks
79
+
80
+ Rust API docs:
81
+ https://victorwp288.github.io/weiss-schwarz-simulator/rustdoc/
82
+
83
+ Note: with only 1–2 benchmark runs, charts can look “empty” until more points exist.
84
+
85
+ ### Releases
86
+
87
+ Release automation is handled by Release Please. To ensure downstream workflows (like `Wheels`) run
88
+ automatically when a release tag is created, configure a fine-grained PAT as `RELEASE_PLEASE_TOKEN`
89
+ in GitHub Actions secrets; otherwise you can manually run the `Wheels` workflow for the release tag.
90
+
91
+ ### Benchmark Snapshot (main, top 12)
92
+
93
+ <!-- BENCHMARKS:START -->
94
+ _Last updated: 2026-01-05 00:44 UTC_
95
+
96
+ | Benchmark | Time |
97
+ | --- | --- |
98
+ | rust/advance_until_decision | 63280 ns/iter |
99
+ | rust/step_batch_64 | 26268 ns/iter |
100
+ | rust/step_batch_fast_256_priority_off | 111592 ns/iter |
101
+ | rust/step_batch_fast_256_priority_on | 109646 ns/iter |
102
+ | rust/legal_actions | 44 ns/iter |
103
+ | rust/legal_actions_forced | 43 ns/iter |
104
+ | rust/on_reverse_decision_frequency_on | 1534 ns/iter |
105
+ | rust/on_reverse_decision_frequency_off | 1540 ns/iter |
106
+ | rust/observation_encode | 228 ns/iter |
107
+ | rust/observation_encode_forced | 233 ns/iter |
108
+ | rust/mask_construction | 455 ns/iter |
109
+ | rust/mask_construction_forced | 412 ns/iter |
110
+ <!-- BENCHMARKS:END -->
111
+
112
+
113
+ ---
114
+
115
+ ## Repo layout
116
+
117
+ - `weiss_core/`: Rust simulator core (state machine, legality, encoding, replay, pool)
118
+ - `weiss_py/`: PyO3 extension module (`weiss_sim`) exposing `EnvPool`
119
+ - `python/weiss_sim/`: Python wrapper that re-exports the extension
120
+ - `python/tests/`: pytest smoke tests + fixture card DB
121
+
122
+ ---
123
+
124
+ ## Installation
125
+
126
+ ### Python (local build via `maturin`)
127
+
128
+ Prerequisites:
129
+ - **Python**: ≥ 3.10
130
+ - **Rust toolchain**: stable (`cargo`, `rustc`)
131
+ - **Bindings**: built with PyO3 0.24 + numpy 0.24 (Rust side)
132
+
133
+ Install (editable):
134
+
135
+ ```bash
136
+ python -m pip install -U pip
137
+ python -m pip install -U maturin
138
+ python -m pip install -e .
139
+ ```
140
+
141
+ Note (macOS/PyO3): if you build wheels locally, prefer an explicit interpreter to avoid linking errors
142
+ and unsupported system Pythons:
143
+
144
+ ```bash
145
+ maturin build --release --manifest-path weiss_py/Cargo.toml --interpreter .venv/bin/python -o dist
146
+ ```
147
+
148
+ Sanity check:
149
+
150
+ ```bash
151
+ python -c "import weiss_sim; print(weiss_sim.__version__, weiss_sim.EnvPool)"
152
+ ```
153
+
154
+ ### Rust (core only)
155
+
156
+ ```bash
157
+ cargo build -p weiss_core
158
+ cargo test -p weiss_core
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Quickstart (Python): step with a trivial policy
164
+
165
+ The environment exposes a **fixed action space** and an **action mask**. You can select any index where mask==1. For speed, use legal action ids instead of scanning the full mask.
166
+
167
+ ```python
168
+ from pathlib import Path
169
+ import numpy as np
170
+ import weiss_sim
171
+
172
+ fixture_dir = Path("python/tests/fixtures")
173
+ db_path = fixture_dir / "cards.wsdb"
174
+
175
+ pool = weiss_sim.EnvPool.new_rl_train(
176
+ 1,
177
+ str(db_path),
178
+ deck_lists=[[1] * 50, [2] * 50],
179
+ deck_ids=[1, 2],
180
+ max_decisions=200,
181
+ max_ticks=10_000,
182
+ seed=123,
183
+ num_threads=None, # set to an int to pin a dedicated Rayon pool
184
+ )
185
+
186
+ buf = weiss_sim.EnvPoolBuffers(pool)
187
+ buf.reset()
188
+
189
+ for _ in range(10):
190
+ ids_flat, offsets = buf.legal_action_ids()
191
+ start, end = int(offsets[0]), int(offsets[1])
192
+ action = int(ids_flat[start])
193
+ actions = np.array([action], dtype=np.uint32)
194
+ buf.step(actions)
195
+ ```
196
+
197
+ Debug print (very lightweight):
198
+
199
+ ```python
200
+ print(pool.render_ansi(env_index=0, perspective=0))
201
+ ```
202
+
203
+ Examples:
204
+
205
+ ```bash
206
+ python python/examples/sb3_maskable_ppo.py
207
+ python python/examples/cleanrl_maskable_ppo.py
208
+ python python/examples/bench_python_boundary.py --num-envs 256 --steps 5000 --mode both
209
+ ```
210
+
211
+ ---
212
+
213
+ ## Python API (what you get)
214
+
215
+ The extension module is `weiss_sim` and the package re-exports it as `import weiss_sim`.
216
+
217
+ ### `weiss_sim.EnvPool`
218
+
219
+ Constructors (classmethods):
220
+
221
+ ```python
222
+ EnvPool.new_rl_train(
223
+ num_envs: int,
224
+ db_path: str,
225
+ deck_lists: list[list[int]],
226
+ deck_ids: list[int] | None = None,
227
+ max_decisions: int = 10_000,
228
+ max_ticks: int = 100_000,
229
+ seed: int = 0,
230
+ reward_json: str | None = None,
231
+ num_threads: int | None = None,
232
+ )
233
+
234
+ EnvPool.new_rl_eval(...)
235
+ EnvPool.new_debug(...)
236
+ ```
237
+
238
+ Minimal RL stepping uses `BatchOutMinimal`:
239
+
240
+ ```python
241
+ out = weiss_sim.BatchOutMinimal(num_envs)
242
+ pool.reset_into(out)
243
+ pool.step_into(actions, out)
244
+ ```
245
+
246
+ Core methods:
247
+ - `reset_into(out: BatchOutMinimal) -> None`
248
+ - `reset_indices_into(indices: list[int], out: BatchOutMinimal) -> None`
249
+ - `reset_done_into(done_mask: np.ndarray[bool], out: BatchOutMinimal) -> None`
250
+ - `step_into(actions: np.ndarray[uint32], out: BatchOutMinimal) -> None`
251
+ - `step_debug_into(actions: np.ndarray[uint32], out: BatchOutDebug) -> None`
252
+ - `reset_debug_into(out: BatchOutDebug) -> None`
253
+ - `reset_indices_debug_into(indices: list[int], out: BatchOutDebug) -> None`
254
+ - `legal_action_ids_into(ids: np.ndarray[uint16], offsets: np.ndarray[uint32]) -> int`
255
+ - `auto_reset_on_error_codes_into(engine_status: np.ndarray[uint8], out: BatchOutMinimal) -> int`
256
+ - `engine_error_reset_count() -> int`
257
+ - `reset_engine_error_reset_count() -> None`
258
+
259
+ Debug helpers:
260
+ - `action_lookup_batch() -> list[list[dict | None]]`
261
+ - `describe_action_ids(action_ids: list[int]) -> list[dict | None]`
262
+ - `decision_info_batch() -> list[dict]`
263
+ - `state_fingerprint_batch() -> np.ndarray[uint64]`
264
+ - `events_fingerprint_batch() -> np.ndarray[uint64]`
265
+ - `render_ansi(env_index: int, perspective: int) -> str`
266
+
267
+ Convenience properties:
268
+ - `action_space: int`
269
+ - `obs_len: int`
270
+ - `num_envs: int`
271
+
272
+ Python helper:
273
+ - `EnvPoolBuffers(pool)` allocates persistent numpy buffers and exposes `reset()`, `step()`, and `legal_action_ids()`.
274
+ - `reset_rl(pool)` / `step_rl(pool, actions)` return a `RlStep` dataclass with named fields.
275
+ - `pass_action_id_for_decision_kind(decision_kind)` returns `PASS_ACTION_ID` for convenience.
276
+
277
+ ---
278
+
279
+ ## Encodings (stable + versioned)
280
+
281
+ Encodings are deterministic and **explicitly versioned**:
282
+
283
+ - `weiss_sim.OBS_ENCODING_VERSION` (currently 1)
284
+ - `weiss_sim.ACTION_ENCODING_VERSION` (currently 1)
285
+
286
+ ### Observation tensor
287
+
288
+ Observations are fixed-length `int32` arrays. Query the current length via:
289
+
290
+ - `weiss_sim.OBS_LEN` or `pool.obs_len`
291
+
292
+ Visibility modes (`observation_visibility`):
293
+ - `"public"`: opponent hidden zones are masked (filled with `-1`).
294
+ - `"full"`: opponent hidden zones are revealed.
295
+
296
+ The header includes active player, phase, decision kind/player, last action, attack context, and choice pagination metadata. After the per-player blocks (perspective player first), the encoder appends:
297
+
298
+ - **Reason bits**: public-safe flags for phase/resource/target gating.
299
+ - **Reveal history**: recent revealed card ids for the observing player.
300
+ - **Context bits**: priority/choice/stack/encore context.
301
+
302
+ Exact layout is defined in `weiss_core/src/encode.rs` and versioned by `OBS_ENCODING_VERSION`.
303
+
304
+ ### Action space
305
+
306
+ Actions are fixed to `ACTION_SPACE_SIZE` (`pool.action_space`). Families include:
307
+
308
+ - pass (contextual; `PASS_ACTION_ID`)
309
+ - mulligan confirm / mulligan select
310
+ - clock
311
+ - main play character/event/climax, moves, activated abilities
312
+ - attack / counter
313
+ - choice select + pagination
314
+ - level up / encore
315
+ - trigger order
316
+ - concede (only legal when `allow_concede=true`)
317
+
318
+ The legal-action **mask** is derived from the canonical `ActionDesc` list and mapped to ids in a versioned way (`ACTION_ENCODING_VERSION`).
319
+
320
+ ---
321
+
322
+
323
+ ## Performance & throughput
324
+
325
+ Rust core is already extremely fast; Python-side overhead can dominate.
326
+
327
+
328
+ Practical performance tips:
329
+ - Use into-buffer APIs (`reset_into`, `step_into`) with preallocated buffers.
330
+ - Prefer **legal action ids** over mask scans in Python.
331
+ - Pin `num_threads` if you want repeatable multicore behavior.
332
+
333
+ ---
334
+
335
+ ## RL-safe defaults (recommended)
336
+
337
+
338
+ - `EnvPool.new_rl_train(...)` for training and `EnvPool.new_rl_eval(...)` for eval.
339
+ - `observation_visibility = Public`
340
+ - `enable_visibility_policies = true`
341
+ - `allow_concede = false`
342
+ - `priority_allow_pass = true`
343
+ - `strict_priority_mode = false`
344
+ - `enable_priority_windows = false` unless you explicitly train with priority timing windows
345
+ - Treat timeouts as **truncations** (bootstrap value)
346
+
347
+ If you need to deviate, document the assumption and update the PPO guide.
348
+
349
+ ---
350
+
351
+ ## Replays (WSR1)
352
+
353
+ Replays are binary `WSR1` files written via `ReplayWriter` and serialized with `postcard`.
354
+
355
+ What gets recorded:
356
+ - **Header**: obs/action encoding versions, replay schema version, seed, starting player, deck ids, curriculum id, config hash
357
+ - **Body**: action sequence, per-step metadata (actor/decision kind/flags), optional event stream, final snapshot (terminal + state hash)
358
+
359
+ Replay sampling can be enabled from Rust (`EnvPool::enable_replay_sampling`). The Python
360
+ binding does not currently expose replay sampling toggles.
361
+
362
+ Tooling:
363
+
364
+ ```bash
365
+ cargo run -p weiss_core --bin replay_dump -- path/to/episode_00000000.wsr
366
+ ```
367
+
368
+ ---
369
+
370
+ ## Card database (WSDB)
371
+
372
+ The simulator loads a binary card DB:
373
+
374
+ - Magic: `WSDB`
375
+ - Schema version: `u32` little-endian (`WSDB_SCHEMA_VERSION = 1`)
376
+ - Payload: `postcard`-encoded `CardDb`
377
+
378
+ Pack JSON → WSDB:
379
+
380
+ ```bash
381
+ cargo run -p weiss_core --bin carddb_pack -- cards.json cards.wsdb
382
+ ```
383
+
384
+ See `weiss_core/src/db.rs` for the `CardStatic` schema and supported ability templates.
385
+
386
+ ### Scraper + converter pipeline (full card set)
387
+
388
+ The full EN card set is produced by the scraper + converter pipeline:
389
+
390
+ - Scrape: `scraper/scrape.py` → `scraper/out/cards.jsonl`
391
+ - Convert: `scraper/convert.py` → `scraper/out/cards.json` + `scraper/out/cards_raw.json`
392
+ - Pack: `carddb_pack` → `scraper/out/cards.wsdb`
393
+
394
+ Smoke check with Python:
395
+
396
+ ```bash
397
+ PYTHONPATH=python python python/wsdb_smoke.py
398
+ ```
399
+
400
+ ---
401
+
402
+ ## Project status (implemented vs simplified)
403
+
404
+ This is a simulator core built for RL training and determinism first. Some rule systems are intentionally simplified or diverge from the physical game.
405
+
406
+ Examples of current intentional simplifications/deviations:
407
+ - local priority/stack model; official check-timing/play-timing subtleties are not fully replicated
408
+ - card text is limited to implemented `AbilityTemplate` variants (no free-form text engine)
409
+ - trigger icon semantics are simplified :
410
+ - Draw is mandatory (not optional “may”)
411
+ - Shot resolves as immediate 1 damage (not delayed on cancel)
412
+ - Bounce returns a character from **your** stage (not opponent’s)
413
+ - deck-top search/reveal modeled as top‑N reveal to controller
414
+
415
+ ---
416
+
417
+
418
+ ## License
419
+
420
+ Dual-licensed under **MIT OR Apache-2.0** (see workspace metadata in `Cargo.toml`).
421
+
@@ -0,0 +1,394 @@
1
+ # Weiss Schwarz Simulator (Rust core + Python bindings)
2
+
3
+ [![CI](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/ci.yml/badge.svg)](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/ci.yml)
4
+ [![Wheels](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/wheels.yml/badge.svg)](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/wheels.yml)
5
+ [![Benchmarks](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/benchmarks.yml/badge.svg)](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/benchmarks.yml)
6
+ [![Security](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/security.yml/badge.svg?branch=main)](https://github.com/victorwp288/weiss-schwarz-simulator/actions/workflows/security.yml)
7
+ [![Docs](https://img.shields.io/badge/docs-rustdoc-blue)](https://victorwp288.github.io/weiss-schwarz-simulator/rustdoc/)
8
+ [![PyPI](https://img.shields.io/pypi/v/weiss-sim.svg)](https://pypi.org/project/weiss-sim/)
9
+ [![Changelog](https://img.shields.io/badge/changelog-view-blue)](https://github.com/victorwp288/weiss-schwarz-simulator/blob/main/CHANGELOG.md)
10
+ [![Last Commit](https://img.shields.io/github/last-commit/victorwp288/weiss-schwarz-simulator.svg)](https://github.com/victorwp288/weiss-schwarz-simulator/commits/main)
11
+
12
+ Deterministic, RL-first Weiss Schwarz simulation: **Rust runs the hot loop**, advances until a **decision point**, and exposes a **fixed action space + mask** (and legal action ids) for efficient batched training. Python gets a thin `EnvPool` wrapper for stepping many environments in parallel.
13
+
14
+ ---
15
+
16
+ ## Why this exists
17
+
18
+ Weiss Schwarz has hidden information, branching, and timing windows. For RL you typically want:
19
+
20
+ - **Determinism**: reproduce episodes from a seed and action sequence.
21
+ - **Few boundary crossings**: avoid Python↔Rust overhead for micro-steps.
22
+ - **Stable action space**: fixed-size actions with legality masking.
23
+ - **Introspectability**: canonical action descriptions, replays, and event logs.
24
+
25
+ This repo is built around those constraints.
26
+
27
+ ---
28
+
29
+ ## Highlights
30
+
31
+ - **Advance-until-decision loop**: engine runs internally until a player must act.
32
+ - **Canonical legal actions**: `ActionDesc` list is the single truth source.
33
+ - **Fixed action id space + mask**: derived from canonical actions and **versioned** (`ACTION_ENCODING_VERSION`).
34
+ - **Legal action ids (fast)**: use ids to avoid Python-side mask scans in hot loops.
35
+ - **Fixed-length observations**: `int32` arrays, **versioned** (`OBS_ENCODING_VERSION`).
36
+ - **Multicore stepping**: `EnvPool` uses Rayon; Python binding releases the GIL.
37
+ - **Replays**: deterministic, versioned, optional event stream, public-safe sanitization when enabled.
38
+ - **Curriculum switches**: gate rules/features for training curricula.
39
+
40
+ Each environment is deterministic given its seed and action sequence. Parallel batch stepping does not change outcomes because envs are fully isolated.
41
+
42
+ ---
43
+
44
+ ## Automation & Benchmarks
45
+
46
+ - **CI** runs on every push/PR: Rust fmt/clippy/tests + Python ruff/pytest.
47
+ - **Wheels** build on pushes to `main` (artifacts), and tags `v*` publish to GitHub Releases + PyPI.
48
+ - **Benchmarks** run on pushes to `main`; history + charts are published via GitHub Pages.
49
+ - **Docs** are published to GitHub Pages on pushes to `main`.
50
+
51
+ Latest benchmark history and charts:
52
+ https://victorwp288.github.io/weiss-schwarz-simulator/benchmarks
53
+
54
+ Rust API docs:
55
+ https://victorwp288.github.io/weiss-schwarz-simulator/rustdoc/
56
+
57
+ Note: with only 1–2 benchmark runs, charts can look “empty” until more points exist.
58
+
59
+ ### Releases
60
+
61
+ Release automation is handled by Release Please. To ensure downstream workflows (like `Wheels`) run
62
+ automatically when a release tag is created, configure a fine-grained PAT as `RELEASE_PLEASE_TOKEN`
63
+ in GitHub Actions secrets; otherwise you can manually run the `Wheels` workflow for the release tag.
64
+
65
+ ### Benchmark Snapshot (main, top 12)
66
+
67
+ <!-- BENCHMARKS:START -->
68
+ _Last updated: 2026-01-05 00:44 UTC_
69
+
70
+ | Benchmark | Time |
71
+ | --- | --- |
72
+ | rust/advance_until_decision | 63280 ns/iter |
73
+ | rust/step_batch_64 | 26268 ns/iter |
74
+ | rust/step_batch_fast_256_priority_off | 111592 ns/iter |
75
+ | rust/step_batch_fast_256_priority_on | 109646 ns/iter |
76
+ | rust/legal_actions | 44 ns/iter |
77
+ | rust/legal_actions_forced | 43 ns/iter |
78
+ | rust/on_reverse_decision_frequency_on | 1534 ns/iter |
79
+ | rust/on_reverse_decision_frequency_off | 1540 ns/iter |
80
+ | rust/observation_encode | 228 ns/iter |
81
+ | rust/observation_encode_forced | 233 ns/iter |
82
+ | rust/mask_construction | 455 ns/iter |
83
+ | rust/mask_construction_forced | 412 ns/iter |
84
+ <!-- BENCHMARKS:END -->
85
+
86
+
87
+ ---
88
+
89
+ ## Repo layout
90
+
91
+ - `weiss_core/`: Rust simulator core (state machine, legality, encoding, replay, pool)
92
+ - `weiss_py/`: PyO3 extension module (`weiss_sim`) exposing `EnvPool`
93
+ - `python/weiss_sim/`: Python wrapper that re-exports the extension
94
+ - `python/tests/`: pytest smoke tests + fixture card DB
95
+
96
+ ---
97
+
98
+ ## Installation
99
+
100
+ ### Python (local build via `maturin`)
101
+
102
+ Prerequisites:
103
+ - **Python**: ≥ 3.10
104
+ - **Rust toolchain**: stable (`cargo`, `rustc`)
105
+ - **Bindings**: built with PyO3 0.24 + numpy 0.24 (Rust side)
106
+
107
+ Install (editable):
108
+
109
+ ```bash
110
+ python -m pip install -U pip
111
+ python -m pip install -U maturin
112
+ python -m pip install -e .
113
+ ```
114
+
115
+ Note (macOS/PyO3): if you build wheels locally, prefer an explicit interpreter to avoid linking errors
116
+ and unsupported system Pythons:
117
+
118
+ ```bash
119
+ maturin build --release --manifest-path weiss_py/Cargo.toml --interpreter .venv/bin/python -o dist
120
+ ```
121
+
122
+ Sanity check:
123
+
124
+ ```bash
125
+ python -c "import weiss_sim; print(weiss_sim.__version__, weiss_sim.EnvPool)"
126
+ ```
127
+
128
+ ### Rust (core only)
129
+
130
+ ```bash
131
+ cargo build -p weiss_core
132
+ cargo test -p weiss_core
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Quickstart (Python): step with a trivial policy
138
+
139
+ The environment exposes a **fixed action space** and an **action mask**. You can select any index where mask==1. For speed, use legal action ids instead of scanning the full mask.
140
+
141
+ ```python
142
+ from pathlib import Path
143
+ import numpy as np
144
+ import weiss_sim
145
+
146
+ fixture_dir = Path("python/tests/fixtures")
147
+ db_path = fixture_dir / "cards.wsdb"
148
+
149
+ pool = weiss_sim.EnvPool.new_rl_train(
150
+ 1,
151
+ str(db_path),
152
+ deck_lists=[[1] * 50, [2] * 50],
153
+ deck_ids=[1, 2],
154
+ max_decisions=200,
155
+ max_ticks=10_000,
156
+ seed=123,
157
+ num_threads=None, # set to an int to pin a dedicated Rayon pool
158
+ )
159
+
160
+ buf = weiss_sim.EnvPoolBuffers(pool)
161
+ buf.reset()
162
+
163
+ for _ in range(10):
164
+ ids_flat, offsets = buf.legal_action_ids()
165
+ start, end = int(offsets[0]), int(offsets[1])
166
+ action = int(ids_flat[start])
167
+ actions = np.array([action], dtype=np.uint32)
168
+ buf.step(actions)
169
+ ```
170
+
171
+ Debug print (very lightweight):
172
+
173
+ ```python
174
+ print(pool.render_ansi(env_index=0, perspective=0))
175
+ ```
176
+
177
+ Examples:
178
+
179
+ ```bash
180
+ python python/examples/sb3_maskable_ppo.py
181
+ python python/examples/cleanrl_maskable_ppo.py
182
+ python python/examples/bench_python_boundary.py --num-envs 256 --steps 5000 --mode both
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Python API (what you get)
188
+
189
+ The extension module is `weiss_sim` and the package re-exports it as `import weiss_sim`.
190
+
191
+ ### `weiss_sim.EnvPool`
192
+
193
+ Constructors (classmethods):
194
+
195
+ ```python
196
+ EnvPool.new_rl_train(
197
+ num_envs: int,
198
+ db_path: str,
199
+ deck_lists: list[list[int]],
200
+ deck_ids: list[int] | None = None,
201
+ max_decisions: int = 10_000,
202
+ max_ticks: int = 100_000,
203
+ seed: int = 0,
204
+ reward_json: str | None = None,
205
+ num_threads: int | None = None,
206
+ )
207
+
208
+ EnvPool.new_rl_eval(...)
209
+ EnvPool.new_debug(...)
210
+ ```
211
+
212
+ Minimal RL stepping uses `BatchOutMinimal`:
213
+
214
+ ```python
215
+ out = weiss_sim.BatchOutMinimal(num_envs)
216
+ pool.reset_into(out)
217
+ pool.step_into(actions, out)
218
+ ```
219
+
220
+ Core methods:
221
+ - `reset_into(out: BatchOutMinimal) -> None`
222
+ - `reset_indices_into(indices: list[int], out: BatchOutMinimal) -> None`
223
+ - `reset_done_into(done_mask: np.ndarray[bool], out: BatchOutMinimal) -> None`
224
+ - `step_into(actions: np.ndarray[uint32], out: BatchOutMinimal) -> None`
225
+ - `step_debug_into(actions: np.ndarray[uint32], out: BatchOutDebug) -> None`
226
+ - `reset_debug_into(out: BatchOutDebug) -> None`
227
+ - `reset_indices_debug_into(indices: list[int], out: BatchOutDebug) -> None`
228
+ - `legal_action_ids_into(ids: np.ndarray[uint16], offsets: np.ndarray[uint32]) -> int`
229
+ - `auto_reset_on_error_codes_into(engine_status: np.ndarray[uint8], out: BatchOutMinimal) -> int`
230
+ - `engine_error_reset_count() -> int`
231
+ - `reset_engine_error_reset_count() -> None`
232
+
233
+ Debug helpers:
234
+ - `action_lookup_batch() -> list[list[dict | None]]`
235
+ - `describe_action_ids(action_ids: list[int]) -> list[dict | None]`
236
+ - `decision_info_batch() -> list[dict]`
237
+ - `state_fingerprint_batch() -> np.ndarray[uint64]`
238
+ - `events_fingerprint_batch() -> np.ndarray[uint64]`
239
+ - `render_ansi(env_index: int, perspective: int) -> str`
240
+
241
+ Convenience properties:
242
+ - `action_space: int`
243
+ - `obs_len: int`
244
+ - `num_envs: int`
245
+
246
+ Python helper:
247
+ - `EnvPoolBuffers(pool)` allocates persistent numpy buffers and exposes `reset()`, `step()`, and `legal_action_ids()`.
248
+ - `reset_rl(pool)` / `step_rl(pool, actions)` return a `RlStep` dataclass with named fields.
249
+ - `pass_action_id_for_decision_kind(decision_kind)` returns `PASS_ACTION_ID` for convenience.
250
+
251
+ ---
252
+
253
+ ## Encodings (stable + versioned)
254
+
255
+ Encodings are deterministic and **explicitly versioned**:
256
+
257
+ - `weiss_sim.OBS_ENCODING_VERSION` (currently 1)
258
+ - `weiss_sim.ACTION_ENCODING_VERSION` (currently 1)
259
+
260
+ ### Observation tensor
261
+
262
+ Observations are fixed-length `int32` arrays. Query the current length via:
263
+
264
+ - `weiss_sim.OBS_LEN` or `pool.obs_len`
265
+
266
+ Visibility modes (`observation_visibility`):
267
+ - `"public"`: opponent hidden zones are masked (filled with `-1`).
268
+ - `"full"`: opponent hidden zones are revealed.
269
+
270
+ The header includes active player, phase, decision kind/player, last action, attack context, and choice pagination metadata. After the per-player blocks (perspective player first), the encoder appends:
271
+
272
+ - **Reason bits**: public-safe flags for phase/resource/target gating.
273
+ - **Reveal history**: recent revealed card ids for the observing player.
274
+ - **Context bits**: priority/choice/stack/encore context.
275
+
276
+ Exact layout is defined in `weiss_core/src/encode.rs` and versioned by `OBS_ENCODING_VERSION`.
277
+
278
+ ### Action space
279
+
280
+ Actions are fixed to `ACTION_SPACE_SIZE` (`pool.action_space`). Families include:
281
+
282
+ - pass (contextual; `PASS_ACTION_ID`)
283
+ - mulligan confirm / mulligan select
284
+ - clock
285
+ - main play character/event/climax, moves, activated abilities
286
+ - attack / counter
287
+ - choice select + pagination
288
+ - level up / encore
289
+ - trigger order
290
+ - concede (only legal when `allow_concede=true`)
291
+
292
+ The legal-action **mask** is derived from the canonical `ActionDesc` list and mapped to ids in a versioned way (`ACTION_ENCODING_VERSION`).
293
+
294
+ ---
295
+
296
+
297
+ ## Performance & throughput
298
+
299
+ Rust core is already extremely fast; Python-side overhead can dominate.
300
+
301
+
302
+ Practical performance tips:
303
+ - Use into-buffer APIs (`reset_into`, `step_into`) with preallocated buffers.
304
+ - Prefer **legal action ids** over mask scans in Python.
305
+ - Pin `num_threads` if you want repeatable multicore behavior.
306
+
307
+ ---
308
+
309
+ ## RL-safe defaults (recommended)
310
+
311
+
312
+ - `EnvPool.new_rl_train(...)` for training and `EnvPool.new_rl_eval(...)` for eval.
313
+ - `observation_visibility = Public`
314
+ - `enable_visibility_policies = true`
315
+ - `allow_concede = false`
316
+ - `priority_allow_pass = true`
317
+ - `strict_priority_mode = false`
318
+ - `enable_priority_windows = false` unless you explicitly train with priority timing windows
319
+ - Treat timeouts as **truncations** (bootstrap value)
320
+
321
+ If you need to deviate, document the assumption and update the PPO guide.
322
+
323
+ ---
324
+
325
+ ## Replays (WSR1)
326
+
327
+ Replays are binary `WSR1` files written via `ReplayWriter` and serialized with `postcard`.
328
+
329
+ What gets recorded:
330
+ - **Header**: obs/action encoding versions, replay schema version, seed, starting player, deck ids, curriculum id, config hash
331
+ - **Body**: action sequence, per-step metadata (actor/decision kind/flags), optional event stream, final snapshot (terminal + state hash)
332
+
333
+ Replay sampling can be enabled from Rust (`EnvPool::enable_replay_sampling`). The Python
334
+ binding does not currently expose replay sampling toggles.
335
+
336
+ Tooling:
337
+
338
+ ```bash
339
+ cargo run -p weiss_core --bin replay_dump -- path/to/episode_00000000.wsr
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Card database (WSDB)
345
+
346
+ The simulator loads a binary card DB:
347
+
348
+ - Magic: `WSDB`
349
+ - Schema version: `u32` little-endian (`WSDB_SCHEMA_VERSION = 1`)
350
+ - Payload: `postcard`-encoded `CardDb`
351
+
352
+ Pack JSON → WSDB:
353
+
354
+ ```bash
355
+ cargo run -p weiss_core --bin carddb_pack -- cards.json cards.wsdb
356
+ ```
357
+
358
+ See `weiss_core/src/db.rs` for the `CardStatic` schema and supported ability templates.
359
+
360
+ ### Scraper + converter pipeline (full card set)
361
+
362
+ The full EN card set is produced by the scraper + converter pipeline:
363
+
364
+ - Scrape: `scraper/scrape.py` → `scraper/out/cards.jsonl`
365
+ - Convert: `scraper/convert.py` → `scraper/out/cards.json` + `scraper/out/cards_raw.json`
366
+ - Pack: `carddb_pack` → `scraper/out/cards.wsdb`
367
+
368
+ Smoke check with Python:
369
+
370
+ ```bash
371
+ PYTHONPATH=python python python/wsdb_smoke.py
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Project status (implemented vs simplified)
377
+
378
+ This is a simulator core built for RL training and determinism first. Some rule systems are intentionally simplified or diverge from the physical game.
379
+
380
+ Examples of current intentional simplifications/deviations:
381
+ - local priority/stack model; official check-timing/play-timing subtleties are not fully replicated
382
+ - card text is limited to implemented `AbilityTemplate` variants (no free-form text engine)
383
+ - trigger icon semantics are simplified :
384
+ - Draw is mandatory (not optional “may”)
385
+ - Shot resolves as immediate 1 damage (not delayed on cancel)
386
+ - Bounce returns a character from **your** stage (not opponent’s)
387
+ - deck-top search/reveal modeled as top‑N reveal to controller
388
+
389
+ ---
390
+
391
+
392
+ ## License
393
+
394
+ Dual-licensed under **MIT OR Apache-2.0** (see workspace metadata in `Cargo.toml`).
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.5"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "weiss-sim"
7
+ version = "0.1.3"
8
+ description = "Deterministic Weiss Schwarz simulator with a Rust core and Python bindings."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT OR Apache-2.0" }
12
+ authors = [{ name = "Lallan" }]
13
+ keywords = ["weiss-schwarz", "reinforcement-learning", "simulation", "pyo3", "rl"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "License :: OSI Approved :: Apache Software License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Rust",
23
+ "Topic :: Games/Entertainment",
24
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
25
+ ]
26
+ dependencies = [
27
+ "numpy>=1.23",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/victorwp288/weiss-schwarz-simulator"
32
+ Repository = "https://github.com/victorwp288/weiss-schwarz-simulator"
33
+ Documentation = "https://victorwp288.github.io/weiss-schwarz-simulator/rustdoc/"
34
+ Issues = "https://github.com/victorwp288/weiss-schwarz-simulator/issues"
35
+ Changelog = "https://github.com/victorwp288/weiss-schwarz-simulator/blob/main/CHANGELOG.md"
36
+
37
+ [tool.maturin]
38
+ manifest-path = "weiss_py/Cargo.toml"
39
+ python-source = "python"
40
+ module-name = "weiss_sim"
41
+
42
+ [tool.ruff]
43
+ target-version = "py310"
44
+ line-length = 100
45
+ extend-exclude = ["python/examples"]
46
+
47
+ [tool.ruff.lint]
48
+ select = ["E", "F"]
49
+ ignore = ["E501"]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "weiss_core"
3
- version = "0.1.2"
3
+ version = "0.1.3"
4
4
  edition = "2021"
5
5
  license = "MIT OR Apache-2.0"
6
6
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "weiss_py"
3
- version = "0.1.2"
3
+ version = "0.1.3"
4
4
  edition = "2021"
5
5
  license = "MIT OR Apache-2.0"
6
6
 
weiss_sim-0.1.2/PKG-INFO DELETED
@@ -1,5 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: weiss-sim
3
- Version: 0.1.2
4
- Requires-Dist: numpy>=1.23
5
- Requires-Python: >=3.10
@@ -1,25 +0,0 @@
1
- [build-system]
2
- requires = ["maturin>=1.5"]
3
- build-backend = "maturin"
4
-
5
- [project]
6
- name = "weiss-sim"
7
- version = "0.1.2"
8
- requires-python = ">=3.10"
9
- dependencies = [
10
- "numpy>=1.23",
11
- ]
12
-
13
- [tool.maturin]
14
- manifest-path = "weiss_py/Cargo.toml"
15
- python-source = "python"
16
- module-name = "weiss_sim"
17
-
18
- [tool.ruff]
19
- target-version = "py310"
20
- line-length = 100
21
- extend-exclude = ["python/examples"]
22
-
23
- [tool.ruff.lint]
24
- select = ["E", "F"]
25
- ignore = ["E501"]
File without changes
File without changes