Improve tray handling

Fix bugs when the tray is not fully filled, and retain custom
user tray ordering between turns.
This commit is contained in:
Joel Therrien 2023-08-19 14:47:34 -07:00
parent b33007d3c4
commit 4c8d27b659
2 changed files with 51 additions and 9 deletions

View file

@ -2,6 +2,10 @@ import * as React from "react";
import {GameWasm, Letter as LetterData, MyResult, PlayedTile, PlayerAndScore, Tray, WordResult} from "word_grid"; import {GameWasm, Letter as LetterData, MyResult, PlayedTile, PlayerAndScore, Tray, WordResult} from "word_grid";
import {ChangeEvent, JSX, useEffect, useMemo, useReducer, useState} from "react"; import {ChangeEvent, JSX, useEffect, useMemo, useReducer, useState} from "react";
export interface Settings {
trayLength: number;
}
export enum LocationType { export enum LocationType {
GRID, GRID,
TRAY TRAY
@ -63,7 +67,7 @@ function matchCoordinate(playerLetters: PlayableLetterData[], coords: Coordinate
for (let i=0; i<playerLetters.length; i++){ for (let i=0; i<playerLetters.length; i++){
let letter = playerLetters[i]; let letter = playerLetters[i];
if (letter.location === coords.location && letter.index === coords.index) { if (letter !== undefined && letter.location === coords.location && letter.index === coords.index) {
return i; return i;
} }
} }
@ -86,7 +90,7 @@ function addLogInfo(existingLog: React.JSX.Element[], newItem: React.JSX.Element
return existingLog.slice(); return existingLog.slice();
} }
export function Game(props: {wasm: GameWasm}) { export function Game(props: {wasm: GameWasm, settings: Settings}) {
const cellTypes = useMemo(() => { const cellTypes = useMemo(() => {
return props.wasm.get_board_cell_types(); return props.wasm.get_board_cell_types();
@ -99,12 +103,46 @@ export function Game(props: {wasm: GameWasm}) {
if(update.action === TileDispatchActionType.RETRIEVE) { if(update.action === TileDispatchActionType.RETRIEVE) {
let tray: Tray = props.wasm.get_tray("Player"); let tray: Tray = props.wasm.get_tray("Player");
// we may need to check against the existing tray to retain whatever user reorderings there are
const freeSpots = new Array<number | null>();
for (let i = 0; i<props.settings.trayLength; i++) {
freeSpots.push(i);
}
playerLetters.filter((x) => {
return x !== undefined && x !== null;
}).forEach((x) => {
if (x.location === LocationType.TRAY) {
freeSpots[x.index] = null;
}
});
const firstNotNull = (): number => {
for (let i of freeSpots) {
if (i !== null) {
freeSpots[i] = null;
return i;
}
}
return null;
}
// initial state // initial state
let letters: PlayableLetterData[] = tray.letters.map((ld, i) => { let letters: PlayableLetterData[] = tray.letters.map((ld, i) => {
ld["location"] = LocationType.TRAY; if(ld !== undefined) {
ld["index"] = i; ld["location"] = LocationType.TRAY;
if (playerLetters[i] !== undefined && playerLetters[i] !== null && playerLetters[i].location === LocationType.TRAY) {
ld["index"] = playerLetters[i].index;
} else {
ld["index"] = firstNotNull();
}
}
return ld as PlayableLetterData; return ld as PlayableLetterData;
}) });
return letters; return letters;
} else if (update.action === TileDispatchActionType.MOVE) { } else if (update.action === TileDispatchActionType.MOVE) {
@ -175,7 +213,7 @@ export function Game(props: {wasm: GameWasm}) {
</div> </div>
</div> </div>
<TileTray letters={playerLetters} trayLength={7} dispatch={trayDispatch}/> <TileTray letters={playerLetters} trayLength={props.settings.trayLength} dispatch={trayDispatch}/>
<button onClick={(e) => { <button onClick={(e) => {
const playedTiles = playerLetters.map((i) => { const playedTiles = playerLetters.map((i) => {
if (i === undefined) { if (i === undefined) {
@ -322,7 +360,9 @@ export function TileTray(props: { letters: Array<PlayableLetterData>, trayLength
); );
} }
props.letters.forEach((letter, i) => { props.letters
.filter((x) => {return x !== undefined;})
.forEach((letter, i) => {
if (letter.location === LocationType.TRAY) { if (letter.location === LocationType.TRAY) {
elements[letter.index] = elements[letter.index] =
<TileSlot <TileSlot
@ -373,7 +413,9 @@ function Grid(props: {
</div>; </div>;
}); });
props.playerLetters.forEach((letter, i) => { props.playerLetters
.filter((letter) => {return letter !== undefined})
.forEach((letter, i) => {
if (letter.location === LocationType.GRID) { if (letter.location === LocationType.GRID) {
const ct = props.cellTypes[letter.index]; const ct = props.cellTypes[letter.index];
const {className, text} = cell_type_to_details(ct); const {className, text} = cell_type_to_details(ct);

View file

@ -53,7 +53,7 @@ async function run() {
console.log({cellTypes}); console.log({cellTypes});
const root = createRoot(document.getElementById("root")); const root = createRoot(document.getElementById("root"));
root.render(<Game wasm={game} />); root.render(<Game wasm={game} settings={{trayLength: 7}} />);
} }