Basic tray retrieval
This commit is contained in:
parent
efeb2d4d0b
commit
cb69ada00d
11 changed files with 141 additions and 13 deletions
|
@ -10,4 +10,8 @@ crate-type = ["cdylib"]
|
||||||
csv = "1.2.2"
|
csv = "1.2.2"
|
||||||
rand = {version = "0.8.5", features = ["small_rng"]}
|
rand = {version = "0.8.5", features = ["small_rng"]}
|
||||||
getrandom = {version = "0.2", features = ["js"]}
|
getrandom = {version = "0.2", features = ["js"]}
|
||||||
wasm-bindgen = "0.2.87"
|
wasm-bindgen = { version = "0.2.87", features = ["serde-serialize"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
serde = { version = "1.0.181", features = ["derive"] }
|
||||||
|
serde-wasm-bindgen = "0.4"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Formatter, Write};
|
use std::fmt::{Formatter, Write};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::constants::{ALL_LETTERS_BONUS, GRID_LENGTH, TRAY_LENGTH};
|
use crate::constants::{ALL_LETTERS_BONUS, GRID_LENGTH, TRAY_LENGTH};
|
||||||
use crate::dictionary::DictionaryImpl;
|
use crate::dictionary::DictionaryImpl;
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ impl Coordinates {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub struct Letter {
|
pub struct Letter {
|
||||||
pub text: char,
|
pub text: char,
|
||||||
pub points: u32,
|
pub points: u32,
|
||||||
|
|
67
src/game.rs
Normal file
67
src/game.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use rand::rngs::SmallRng;
|
||||||
|
use rand::SeedableRng;
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
use crate::board::Letter;
|
||||||
|
use crate::constants::{standard_tile_pool, TRAY_LENGTH};
|
||||||
|
use crate::player_interaction::ai::Difficulty;
|
||||||
|
use crate::player_interaction::Tray;
|
||||||
|
|
||||||
|
pub enum Player {
|
||||||
|
Human(String),
|
||||||
|
AI{
|
||||||
|
name: String,
|
||||||
|
difficulty: Difficulty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PlayerState {
|
||||||
|
player: Player,
|
||||||
|
score: u32,
|
||||||
|
tray: Tray
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Game {
|
||||||
|
tiles: Vec<Letter>,
|
||||||
|
player: PlayerState,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Problem - I want to provide a UI to the player
|
||||||
|
// Ideally they would get some kind of 'tray' object with methods to use and run
|
||||||
|
// However I want the main game state to live in Rust, not in JS.
|
||||||
|
// Does this mean I provide Rc<RefCell<Tray>>?
|
||||||
|
|
||||||
|
// Other option - what if I just have one Game object that exposes all methods.
|
||||||
|
// At no point do they get a Tray reference that auto-updates, they need to handle that
|
||||||
|
// I just provide read-only JSON of everything, and they call the methods for updates
|
||||||
|
// This will later work out well when I build it out as an API for multiplayer.
|
||||||
|
|
||||||
|
impl Game {
|
||||||
|
pub fn new(seed: u64) -> Self {
|
||||||
|
let mut rng = SmallRng::seed_from_u64(seed);
|
||||||
|
|
||||||
|
let mut letters = standard_tile_pool(Some(&mut rng));
|
||||||
|
let mut tray = Tray::new(TRAY_LENGTH);
|
||||||
|
tray.fill(&mut letters);
|
||||||
|
|
||||||
|
|
||||||
|
let player = PlayerState {
|
||||||
|
player: Player::Human("Joel".to_string()),
|
||||||
|
score: 0,
|
||||||
|
tray,
|
||||||
|
};
|
||||||
|
|
||||||
|
Game {
|
||||||
|
tiles: letters,
|
||||||
|
player,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_tray(&self) -> &Tray {
|
||||||
|
&self.player.tray
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_tray_mut(&mut self) -> &mut Tray {
|
||||||
|
&mut self.player.tray
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,8 @@ pub mod constants;
|
||||||
pub mod board;
|
pub mod board;
|
||||||
pub mod dictionary;
|
pub mod dictionary;
|
||||||
pub mod player_interaction;
|
pub mod player_interaction;
|
||||||
|
pub mod game;
|
||||||
|
pub mod wasm;
|
||||||
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
|
@ -16,3 +18,4 @@ extern {
|
||||||
pub fn greet(name: &str) {
|
pub fn greet(name: &str) {
|
||||||
alert(&format!("Hello, {}!", name));
|
alert(&format!("Hello, {}!", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::board::Letter;
|
use crate::board::Letter;
|
||||||
|
|
||||||
|
|
||||||
pub mod ai;
|
pub mod ai;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Tray {
|
pub struct Tray {
|
||||||
pub letters: Vec<Option<Letter>>
|
pub letters: Vec<Option<Letter>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
pub struct Difficulty {
|
||||||
|
proportion: f64,
|
||||||
|
randomness: f64,
|
||||||
|
}
|
22
src/wasm.rs
Normal file
22
src/wasm.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
use serde_wasm_bindgen::Error;
|
||||||
|
use wasm_bindgen::JsValue;
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
use crate::game::Game;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct GameWasm(Game);
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl GameWasm {
|
||||||
|
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
pub fn new(seed: u64) -> GameWasm {
|
||||||
|
GameWasm(Game::new(seed))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_tray(&self) -> Result<JsValue, Error> {
|
||||||
|
let tray = self.0.get_tray();
|
||||||
|
|
||||||
|
serde_wasm_bindgen::to_value(tray)
|
||||||
|
}
|
||||||
|
}
|
27
ui/package-lock.json
generated
27
ui/package-lock.json
generated
|
@ -5,14 +5,15 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/react": "^18.2.18",
|
|
||||||
"@types/react-dom": "^18.2.7",
|
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"word_grid": "file:../pkg"
|
"word_grid": "file:../pkg"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"parcel": "^2.9.3"
|
"@types/react": "^18.2.18",
|
||||||
|
"@types/react-dom": "^18.2.7",
|
||||||
|
"parcel": "^2.9.3",
|
||||||
|
"process": "^0.11.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../pkg": {
|
"../pkg": {
|
||||||
|
@ -1961,12 +1962,14 @@
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
"version": "15.7.5",
|
"version": "15.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "18.2.18",
|
"version": "18.2.18",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz",
|
||||||
"integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==",
|
"integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
"@types/scheduler": "*",
|
"@types/scheduler": "*",
|
||||||
|
@ -1977,6 +1980,7 @@
|
||||||
"version": "18.2.7",
|
"version": "18.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
|
||||||
"integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
|
"integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
|
@ -1984,7 +1988,8 @@
|
||||||
"node_modules/@types/scheduler": {
|
"node_modules/@types/scheduler": {
|
||||||
"version": "0.16.3",
|
"version": "0.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
||||||
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
|
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/abortcontroller-polyfill": {
|
"node_modules/abortcontroller-polyfill": {
|
||||||
"version": "1.7.5",
|
"version": "1.7.5",
|
||||||
|
@ -2330,7 +2335,8 @@
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/detect-libc": {
|
"node_modules/detect-libc": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
|
@ -3182,6 +3188,15 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/process": {
|
||||||
|
"version": "0.11.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||||
|
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "18.2.0",
|
"version": "18.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
"word_grid": "file:../pkg"
|
"word_grid": "file:../pkg"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"parcel": "^2.9.3",
|
|
||||||
"@types/react": "^18.2.18",
|
"@types/react": "^18.2.18",
|
||||||
"@types/react-dom": "^18.2.7"
|
"@types/react-dom": "^18.2.7",
|
||||||
|
"parcel": "^2.9.3",
|
||||||
|
"process": "^0.11.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="./index.js" type="module"></script>
|
<script src="./index.js" type="module"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// will "boot" the module and make it ready to use. Currently browsers
|
// will "boot" the module and make it ready to use. Currently browsers
|
||||||
// don't support natively imported WebAssembly as an ES module, but
|
// don't support natively imported WebAssembly as an ES module, but
|
||||||
// eventually the manual initialization won't be required!
|
// eventually the manual initialization won't be required!
|
||||||
import init, { greet } from '../node_modules/word_grid/word_grid.js';
|
import init, { greet, GameWasm } from '../node_modules/word_grid/word_grid.js';
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
// First up we need to actually load the wasm file, so we use the
|
// First up we need to actually load the wasm file, so we use the
|
||||||
|
@ -36,8 +36,15 @@
|
||||||
// modes
|
// modes
|
||||||
await init();
|
await init();
|
||||||
|
|
||||||
// And afterwards we can use all the functionality defined in wasm.
|
|
||||||
greet("Heyo!");
|
greet("Heyo!");
|
||||||
|
|
||||||
|
let game = new GameWasm(1234n);
|
||||||
|
let tray = game.get_tray();
|
||||||
|
|
||||||
|
console.log({tray});
|
||||||
|
|
||||||
|
// And afterwards we can use all the functionality defined in wasm.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
Loading…
Reference in a new issue