Basic tray retrieval

This commit is contained in:
Joel Therrien 2023-08-05 18:59:30 -07:00
parent efeb2d4d0b
commit cb69ada00d
11 changed files with 141 additions and 13 deletions

View file

@ -10,4 +10,8 @@ crate-type = ["cdylib"]
csv = "1.2.2"
rand = {version = "0.8.5", features = ["small_rng"]}
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"

View file

@ -1,6 +1,7 @@
use std::collections::HashSet;
use std::fmt;
use std::fmt::{Formatter, Write};
use serde::{Deserialize, Serialize};
use crate::constants::{ALL_LETTERS_BONUS, GRID_LENGTH, TRAY_LENGTH};
use crate::dictionary::DictionaryImpl;
@ -48,7 +49,7 @@ impl Coordinates {
}
}
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Letter {
pub text: char,
pub points: u32,

67
src/game.rs Normal file
View 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
}
}

View file

@ -4,6 +4,8 @@ pub mod constants;
pub mod board;
pub mod dictionary;
pub mod player_interaction;
pub mod game;
pub mod wasm;
#[wasm_bindgen]
@ -16,3 +18,4 @@ extern {
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}

View file

@ -1,8 +1,10 @@
use serde::{Deserialize, Serialize};
use crate::board::Letter;
pub mod ai;
#[derive(Debug)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Tray {
pub letters: Vec<Option<Letter>>
}

View file

@ -0,0 +1,5 @@
pub struct Difficulty {
proportion: f64,
randomness: f64,
}

22
src/wasm.rs Normal file
View 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
View file

@ -5,14 +5,15 @@
"packages": {
"": {
"dependencies": {
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"word_grid": "file:../pkg"
},
"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": {
@ -1961,12 +1962,14 @@
"node_modules/@types/prop-types": {
"version": "15.7.5",
"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": {
"version": "18.2.18",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz",
"integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@ -1977,6 +1980,7 @@
"version": "18.2.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
"integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
@ -1984,7 +1988,8 @@
"node_modules/@types/scheduler": {
"version": "0.16.3",
"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": {
"version": "1.7.5",
@ -2330,7 +2335,8 @@
"node_modules/csstype": {
"version": "3.1.2",
"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": {
"version": "1.0.3",
@ -3182,6 +3188,15 @@
"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": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",

View file

@ -5,8 +5,9 @@
"word_grid": "file:../pkg"
},
"devDependencies": {
"parcel": "^2.9.3",
"@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"
}
}

View file

@ -6,6 +6,7 @@
</head>
<body>
<script src="./index.js" type="module"></script>
</body>
</html>

View file

@ -5,7 +5,7 @@
// will "boot" the module and make it ready to use. Currently browsers
// don't support natively imported WebAssembly as an ES module, but
// 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() {
// First up we need to actually load the wasm file, so we use the
@ -36,8 +36,15 @@
// modes
await init();
// And afterwards we can use all the functionality defined in wasm.
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();