diff --git a/src/app.tsx b/src/app.tsx index 029a97e..119a18e 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,17 +1,18 @@ import * as React from 'react'; import { useEffect } from 'react'; +import { Action, Dispatch, Effect } from './core/action'; import { reduce } from './core/reduce'; -import { Action, Effect, GameState, MouseState, SceneState, mkSceneState } from './core/state'; +import { GameState, MouseState, SceneState, mkSceneState } from './core/state'; +import { Instructions } from './ui/instructions'; import { key } from './ui/key'; import { paint } from './ui/render'; import { CanvasInfo, useCanvas } from './ui/use-canvas'; import { useEffectfulReducer } from './ui/use-effectful-reducer'; +import { canvas_bds_in_canvas } from './ui/widget-helpers'; +import { DEBUG } from './util/debug'; import { relpos } from './util/dutil'; import { Point } from './util/types'; import { vint } from './util/vutil'; -import { canvas_bds_in_canvas } from './ui/widget-helpers'; - -type Dispatch = (action: Action) => void; export type GameProps = { state: GameState, @@ -23,27 +24,13 @@ type CanvasProps = { main: ForRenderState, }; - -function Instructions(props: { dispatch: Dispatch }): JSX.Element { - const { dispatch } = props; - function mouseDownListener(e: MouseEvent) { - dispatch({ t: 'setSceneState', state: { t: 'menu' } }); - e.preventDefault(); - e.stopPropagation(); - } - - useEffect(() => { - document.addEventListener('mousedown', mouseDownListener); - return () => { - document.removeEventListener('mousedown', mouseDownListener); - } - }); - return Instructions go here; -} - export function App(props: {}): JSX.Element { const [state, dispatch] = useEffectfulReducer(mkSceneState(), reduce, doEffect); + if (DEBUG.stateExporter) { + (window as any).state = () => { return state; } + } + switch (state.t) { case 'menu': { const style: React.CSSProperties = { diff --git a/src/core/action.ts b/src/core/action.ts new file mode 100644 index 0000000..cf42c17 --- /dev/null +++ b/src/core/action.ts @@ -0,0 +1,27 @@ +import { ViewData } from '../app'; +import { Point } from '../util/types'; +import { SceneState } from './state'; + +// There are UiActions, which might have different behavior depending +// on view state, and other GameActions, which should be treated +// uniformly. + +export type GameAction = { t: 'none'; } | + UiAction; +// I think I want to migrate some of these up to GameAction + +export type UiAction = { t: 'key'; code: string; } | +{ t: 'mouseDown'; button: number; p: Point; } | +{ t: 'mouseUp'; p: Point; } | +{ t: 'mouseMove'; p: Point; } | +{ t: 'wheel'; p: Point; delta: number; } | +{ t: 'repaint'; }; + +export type Action = { t: 'resize'; vd: ViewData; } | +{ t: 'newGame'; } | +{ t: 'setSceneState'; state: SceneState; } | + GameAction; + +export type Effect = { t: 'none'; }; + +export type Dispatch = (action: Action) => void; diff --git a/src/core/reduce.ts b/src/core/reduce.ts index bc6be3f..b3f9ca2 100644 --- a/src/core/reduce.ts +++ b/src/core/reduce.ts @@ -6,7 +6,8 @@ import { compose, composen, inverse, scale, translate } from '../util/se2'; import { Point } from '../util/types'; import { vequal, vm, vscale } from '../util/vutil'; import { getPanicFraction } from './clock'; -import { Action, Effect, GameAction, GameState, SceneState, mkGameSceneState, mkGameState } from './state'; +import { GameState, SceneState, mkGameSceneState, mkGameState } from './state'; +import { Action, Effect, GameAction } from './action'; import { checkValid, drawOfState, is_occupied, killTileOfState } from './state-helpers'; function resolveDrag(state: GameState): GameState { diff --git a/src/core/state.ts b/src/core/state.ts index a9d82e7..522b4f4 100644 --- a/src/core/state.ts +++ b/src/core/state.ts @@ -1,4 +1,3 @@ -import { ViewData } from '../app'; import { SE2 } from '../util/se2'; import { Point } from '../util/types'; import { Bonus, bonusGenerator } from './bonus'; @@ -7,35 +6,6 @@ import { Energies, initialEnergies } from './distribution'; import { Grid, LocatedWord, mkGrid, mkGridOf } from './grid'; import { Layer, Overlay, mkLayer, mkOverlay } from './layer'; -// There are UiActions, which might have different behavior depending -// on view state, and other GameActions, which should be treated -// uniformly. -export type GameAction = - | { t: 'none' } - | UiAction - ; - -// I think I want to migrate some of these up to GameAction -export type UiAction = - | { t: 'key', code: string } - | { t: 'mouseDown', button: number, p: Point } - | { t: 'mouseUp', p: Point } - | { t: 'mouseMove', p: Point } - | { t: 'wheel', p: Point, delta: number } - | { t: 'repaint' } - ; - -export type Action = - | { t: 'resize', vd: ViewData } - | { t: 'newGame' } - | { t: 'setSceneState', state: SceneState } - | GameAction - ; - -export type Effect = - | { t: 'none' } - ; - export type MouseState = | { t: 'up', p: Point } | { t: 'down', p: Point } diff --git a/src/ui/instructions.tsx b/src/ui/instructions.tsx new file mode 100644 index 0000000..837fec9 --- /dev/null +++ b/src/ui/instructions.tsx @@ -0,0 +1,141 @@ +import * as React from 'react'; +import { useEffect } from 'react'; +import { Dispatch } from '../core/action'; +import { bonusGenerator } from '../core/bonus'; +import { mkGridOf } from '../core/grid'; +import { mkLayer } from '../core/layer'; +import { SceneState } from '../core/state'; + +export function Instructions(props: { dispatch: Dispatch }): JSX.Element { + const { dispatch } = props; + function mouseDownListener(e: MouseEvent) { + dispatch({ t: 'setSceneState', state: { t: 'menu' } }); + e.preventDefault(); + e.stopPropagation(); + } + + useEffect(() => { + document.addEventListener('mousedown', mouseDownListener); + return () => { + document.removeEventListener('mousedown', mouseDownListener); + } + }); + return Instructions go here; +} + +const state: SceneState = { + t: "game", + gameState: { + invalidWords: [], + connectedSet: mkGridOf([]), + energies: [ + -0.20972339977922094, + 0.7840271889992784, + 1.3068528194400546, + 0.3068528194400547, + 0.5636791674230779, + 1.6534264097200273, + 0.3068528194400547, + 0.7840271889992784, + 0.6791654891096679, + 4, + 4, + 1.1041202653859723, + 0.7840271889992784, + 0.4602792291600821, + 0.4602792291600821, + 0.7840271889992784, + 4, + 0.4602792291600821, + -0.0047189562170500965, + -0.039720770839917874, + 0.79528104378295, + 1.6534264097200273, + 1.6534264097200273, + 4, + 1.6534264097200273, + 0 + ], + seed: 1533311107, + main_tiles: [ + { letter: "p", p_in_world_int: { x: 0, y: 0 }, used: true }, + { letter: "i", p_in_world_int: { x: 2, y: 2 }, used: true }, + { letter: "t", p_in_world_int: { x: 2, y: 0 }, used: true }, + { letter: "o", p_in_world_int: { x: 1, y: 0 }, used: true }, + { letter: "w", p_in_world_int: { x: 2, y: 1 }, used: true }, + { letter: "c", p_in_world_int: { x: 9, y: -3 }, used: true }, + { letter: "e", p_in_world_int: { x: 2, y: 4 }, used: true }, + { letter: "q", p_in_world_int: { x: 1, y: 2 }, used: true }, + { letter: "h", p_in_world_int: { x: 1, y: 4 }, used: true }, + { letter: "n", p_in_world_int: { x: 6, y: 2 }, used: true }, + { letter: "l", p_in_world_int: { x: 3, y: 4 }, used: true }, + { letter: "s", p_in_world_int: { x: 0, y: 4 }, used: true }, + { letter: "v", p_in_world_int: { x: 4, y: 4 }, used: true }, + { letter: "e", p_in_world_int: { x: 5, y: 4 }, used: true }, + { letter: "d", p_in_world_int: { x: 6, y: 4 }, used: true }, + { letter: "l", p_in_world_int: { x: 9, y: -1 }, used: true }, + { letter: "i", p_in_world_int: { x: 6, y: 1 }, used: true }, + { letter: "e", p_in_world_int: { x: 6, y: 3 }, used: true }, + { letter: "i", p_in_world_int: { x: 8, y: 4 }, used: true }, + { letter: "m", p_in_world_int: { x: 9, y: 0 }, used: true }, + { letter: "r", p_in_world_int: { x: 11, y: -2 }, used: true }, + { letter: "r", p_in_world_int: { x: 6, y: 0 }, used: true }, + { letter: "n", p_in_world_int: { x: 2, y: 3 }, used: true }, + { letter: "a", p_in_world_int: { x: 9, y: -2 }, used: true }, + { letter: "u", p_in_world_int: { x: 0, y: -1 }, used: true }, + { letter: "o", p_in_world_int: { x: 7, y: -1 }, used: true }, + { letter: "n", p_in_world_int: { x: 8, y: 5 }, used: true }, + { letter: "e", p_in_world_int: { x: 7, y: 3 }, used: true }, + { letter: "i", p_in_world_int: { x: 8, y: -1 }, used: true }, + { letter: "b", p_in_world_int: { x: 6, y: -1 }, used: true }, + { letter: "l", p_in_world_int: { x: 8, y: 3 }, used: true }, + { letter: "t", p_in_world_int: { x: 8, y: 6 }, used: true }, + { letter: "c", p_in_world_int: { x: 11, y: 0 }, used: true }, + { letter: "k", p_in_world_int: { x: 12, y: 0 }, used: true }, + { letter: "f", p_in_world_int: { x: 11, y: -4 }, used: true }, + { letter: "r", p_in_world_int: { x: 10, y: -3 }, used: true }, + { letter: "a", p_in_world_int: { x: 11, y: -3 }, used: true }, + { letter: "g", p_in_world_int: { x: 12, y: -3 }, used: true }, + { letter: "e", p_in_world_int: { x: 12, y: -2 }, used: true }, + { letter: "e", p_in_world_int: { x: 12, y: -1 }, used: true }, + { letter: "u", p_in_world_int: { x: 10, y: 0 }, used: true }, + { letter: "y", p_in_world_int: { x: 13, y: 0 }, used: true }, + { letter: "x", p_in_world_int: { x: 13, y: -2 }, used: true }, + { letter: "j", p_in_world_int: { x: 6, y: 6 }, used: true }, + { letter: "o", p_in_world_int: { x: 7, y: 6 }, used: true } + ], + hand_tiles: [], + canvas_from_world: { + scale: { + x: 39.6694214876033, + y: 39.6694214876033 + }, + translate: { + x: 50.80991735537191, + y: 215.56198347107437 + } + }, + mouseState: { + t: "up", + p: { + x: 962, + y: 88 + } + }, + bonusLayer: mkLayer(bonusGenerator), + bonusOverlay: { + cells: { + "5,6": "empty", + "7,1": "empty", + "5,1": "empty", + "8,0": "empty", + "9,-1": "empty", + "2,7": "empty", + "8,4": "empty" + } + }, + score: 7, + panic: undefined, + }, + revision: 0, +}; diff --git a/src/util/debug.ts b/src/util/debug.ts index e6d3825..2bec042 100644 --- a/src/util/debug.ts +++ b/src/util/debug.ts @@ -6,6 +6,7 @@ export const DEBUG = { produce: false, letterSample: false, words: false, + stateExporter: true, }; export type DebugLevel = keyof (typeof DEBUG);