diff --git a/Cargo.lock b/Cargo.lock index 8e5595a..54d57f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,6 +396,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + [[package]] name = "inout" version = "0.1.3" @@ -490,6 +496,15 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "merge" version = "0.1.0" @@ -550,6 +565,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a74f2cda724d43a0a63140af89836d4e7db6138ef67c9f96d3a0f0150d05000" +[[package]] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -602,6 +623,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -651,6 +678,69 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pyo3" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fe09249128b3173d092de9523eaa75136bf7ba85e0d69eca241c7939c933cc" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd3927b5a78757a0d71aa9dff669f903b1eb64b54142a9bd9f757f8fde65fd7" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab6bb2102bd8f991e7749f130a70d05dd557613e39ed2deeee8e9ca0c4d548d" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91871864b353fd5ffcb3f91f2f703a22a9797c91b9ab497b1acac7b07ae509c7" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43abc3b80bc20f3facd86cd3c60beed58c3e2aa26213f3cda368de39c60a27e4" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config", + "quote", + "syn 2.0.79", +] + [[package]] name = "quote" version = "1.0.37" @@ -871,6 +961,7 @@ dependencies = [ "base64", "log", "merge", + "pyo3", "rand", "serde", "transpose", @@ -932,6 +1023,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "termcolor" version = "1.3.0" @@ -998,6 +1095,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" + [[package]] name = "universal-hash" version = "0.5.1" diff --git a/devenv.nix b/devenv.nix index 93db791..4315390 100644 --- a/devenv.nix +++ b/devenv.nix @@ -1,14 +1,20 @@ { pkgs, ... }: { - # https://devenv.sh/basics/ - # env.GREET = "devenv"; packages = [ # dev tools pkgs.samply # code profiler + # generate python classes from rust code (for AI training) + pkgs.maturin + # required to manually install generated python module in local venv + pkgs.python312Packages.pip + + # required by python numpy (for AI training) + pkgs.libz + # for bevy pkgs.alsaLib pkgs.udev @@ -38,14 +44,26 @@ ]; - # enterShell = '' - # hello - # git --version - # ''; + enterShell = '' + PYTHONPATH=$PYTHONPATH:$PWD/.devenv/state/venv/lib/python3.12/site-packages + ''; # https://devenv.sh/languages/ languages.rust.enable = true; + + # for AI training + languages.python = { + enable = true; + uv.enable = true; + venv.enable = true; + venv.requirements = " + gym + numpy + stable-baselines3 + "; + }; + # https://devenv.sh/scripts/ # scripts.hello.exec = "echo hello from $GREET"; diff --git a/justfile b/justfile index 8fe5fb7..caf5ef5 100644 --- a/justfile +++ b/justfile @@ -14,3 +14,6 @@ profile: echo '1' | sudo tee /proc/sys/kernel/perf_event_paranoid cargo build --profile profiling samply record ./target/profiling/client_cli --bot dummy,dummy +pythonlib: + maturin build -m store/Cargo.toml --release + pip install --no-deps --force-reinstall --prefix .devenv/state/venv target/wheels/*.whl diff --git a/store/Cargo.toml b/store/Cargo.toml index e0e6195..9951a03 100644 --- a/store/Cargo.toml +++ b/store/Cargo.toml @@ -5,11 +5,18 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "trictrac" +# "cdylib" is necessary to produce a shared library for Python to import from. +crate-type = ["cdylib"] + [dependencies] base64 = "0.21.7" # provides macros for creating log messages to be used by a logger (for example env_logger) log = "0.4.20" merge = "0.1.0" +# generate python lib to be used in AI training +pyo3 = { version = "0.23", features = ["extension-module", "abi3-py38"] } rand = "0.8.5" serde = { version = "1.0", features = ["derive"] } transpose = "0.2.2" diff --git a/store/pyproject.toml b/store/pyproject.toml new file mode 100644 index 0000000..55c3aff --- /dev/null +++ b/store/pyproject.toml @@ -0,0 +1,10 @@ + +[build-system] +requires = ["maturin>=1.0,<2.0"] +build-backend = "maturin" + +[tool.maturin] +# "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so) +features = ["pyo3/extension-module"] +# python-source = "python" +# module-name = "trictrac.game" diff --git a/store/python/test.py b/store/python/test.py new file mode 100644 index 0000000..f300392 --- /dev/null +++ b/store/python/test.py @@ -0,0 +1,9 @@ +import trictrac + +game = trictrac.TricTrac() +print(game.get_state()) # "Initial state" + +moves = game.get_available_moves() +print(moves) # [(0, 5), (3, 8)] + +game.play_move(0, 5) diff --git a/store/src/engine.rs b/store/src/engine.rs new file mode 100644 index 0000000..6c45d50 --- /dev/null +++ b/store/src/engine.rs @@ -0,0 +1,42 @@ +//! # Expose trictrac game state and rules in a python module +use pyo3::prelude::*; +use pyo3::types::PyTuple; + +#[pyclass] +struct TricTrac { + state: String, // Remplace par ta structure d'état du jeu +} + +#[pymethods] +impl TricTrac { + #[new] + fn new() -> Self { + TricTrac { + state: "Initial state".to_string(), + } + } + + fn get_state(&self) -> String { + self.state.clone() + } + + fn get_available_moves(&self) -> Vec<(i32, i32)> { + vec![(0, 5), (3, 8)] // Remplace par ta logique de génération de coups + } + + fn play_move(&mut self, from_pos: i32, to_pos: i32) -> bool { + // Ajoute la logique du jeu ici + println!("Move... from {} to {}", from_pos, to_pos); + true + } +} + +/// A Python module implemented in Rust. The name of this function must match +/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to +/// import the module. +#[pymodule] +fn trictrac(m: &Bound<'_, PyModule>) -> PyResult<()> { + m.add_class::()?; + + Ok(()) +} diff --git a/store/src/lib.rs b/store/src/lib.rs index 58a5727..03b85a7 100644 --- a/store/src/lib.rs +++ b/store/src/lib.rs @@ -16,3 +16,6 @@ pub use board::CheckerMove; mod dice; pub use dice::{Dice, DiceRoller}; + +// python interface "trictrac_engine" (for AI training..) +mod engine;