diff --git a/Cargo.toml b/Cargo.toml
index 72e3f08..8730e14 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,4 +1,20 @@
[workspace]
resolver = "2"
-members = ["client_cli", "bot", "store", "spiel_bot", "client_web"]
+members = [
+ "store",
+ "clients/cli",
+ "clients/backbone-lib",
+ "clients/web-game",
+ "clients/web-user-portal",
+ "server/protocol",
+ "server/relay-server",
+ "bot",
+ "spiel_bot",
+]
+
+# For the server we will need opt-level='3'
+[profile.release]
+opt-level = 'z' # Minimum space
+lto = "fat" # Aggressive Link Time Optimization
+codegen-units = 1
diff --git a/README.md b/README.md
index e74fb69..1145c33 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,20 @@ Training of AI bots is the work in progress.
## Usage
-`cargo run --bin=client_cli -- --bot random`
+Install [devenv](https://devenv.sh/getting-started/), start a devenv shell `devenv shell`, and run the following commands.
+
+```bash
+# Run the relay server
+just build-relay
+just run-relay # listens on :8080
+
+# Run the game (separate terminal)
+just dev-game
+```
+
+Open two browser windows at `http://127.0.0.1:9091`. In one, create a room; in the other, join with the same room name.
+
+Playing with the cli against the 'random' bot: `cargo run --bin=client_cli -- --bot random`
## Roadmap
@@ -23,19 +36,102 @@ Training of AI bots is the work in progress.
## Code structure
- game rules and game state are implemented in the _store/_ folder.
-- the command-line application is implemented in _client_cli/_; it allows you to play against a bot, or to have two bots play against each other
+- the command-line application is implemented in _clients/cli/_; it allows you to play against a bot, or to have two bots play against each other
- the bots algorithms and the training of their models are implemented in the _bot/_ and _spiel_bot_ folders.
### _store_ package
The game state is defined by the `GameState` struct in _store/src/game.rs_. The `to_string_id()` method allows this state to be encoded compactly in a string (without the played moves history). For a more readable textual representation, the `fmt::Display` trait is implemented.
-### _client_cli_ package
+### _clients/cli_ package
-`client_cli/src/game_runner.rs` contains the logic to make two bots play against each other.
+`clients/cli/src/game_runner.rs` contains the logic to make two bots play against each other.
### _bot_ package
- `bot/src/strategy/default.rs` contains the code for a basic bot strategy: it determines the list of valid moves (using the `get_possible_moves_sequences` method of `store::MoveRules`) and simply executes the first move in the list.
- `bot/src/strategy/dqnburn.rs` is another bot strategy that uses a reinforcement learning trained model with the DQN algorithm via the burn library (
"Loading…"
}.into_any(), + Some(Err(e)) => view! {{ e }
}.into_any(), + Some(Ok(g)) => view! {+ "Started: " { started.clone() } " · Ended: " { ended } +
+ +| "Player" | +"Username" | +"Outcome" | +
|---|
+ { r.clone() }
+
+ "Loading…"
}.into_any(), + Some(Err(e)) => view! {{ e }
}.into_any(), + Some(Ok(p)) => view! {"Joined: " { joined }
+ +"Loading…"
}.into_any(), + Some(Err(e)) => view! {{ e }
}.into_any(), + Some(Ok(r)) => { + if r.games.is_empty() { + view! {"No games recorded yet."
}.into_any() + } else { + view! {| "Room" | +"Started" | +"Ended" | +"Outcome" | +"Detail" | +
|---|---|---|---|---|
| { g.room_code.clone() } | +{ started } | +{ ended } | +{ outcome_text } | ++ "View" + | +