diff --git a/src/core/reduce.ts b/src/core/reduce.ts index 346d570..d6002b3 100644 --- a/src/core/reduce.ts +++ b/src/core/reduce.ts @@ -244,6 +244,9 @@ function reduceMouseDownInWorld(state: GameState, wp: WidgetPoint & { t: 'world' } function reduceMouseDownInHand(state: GameState, wp: WidgetPoint & { t: 'hand' }, button: number, mods: Set): GameState { + if (state.lost) + return vacuous_down(state, wp); + const p_in_hand_int = vm(wp.p_in_local, Math.floor); const tiles = get_hand_tiles(state); const tool = currentTool(state); @@ -326,7 +329,10 @@ function reduceGameAction(state: GameState, action: GameAction): effectful.Resul })); } case 'mouseDown': { - return gs(reduceMouseDown(state, getWidgetPoint(state, action.p), action.button, action.mods)); + const wp = getWidgetPoint(state, action.p); + if (state.lost && wp.t == 'pauseButton') + return { state: { t: 'menu' }, effects: [] }; + return gs(reduceMouseDown(state, wp, action.button, action.mods)); } case 'mouseUp': return gs(resolveMouseup(state)); case 'mouseMove': return gs(produce(state, s => { @@ -340,7 +346,9 @@ function reduceGameAction(state: GameState, action: GameAction): effectful.Resul }); if (state.panic !== undefined) { if (getPanicFraction(state.panic) > 1) { - return { state: { t: 'menu' }, effects: [] }; + return gs(produce(state, s => { + s.lost = true; + })); } return gs(produce(state, s => { s.panic!.currentTime = now; })); } diff --git a/src/core/state.ts b/src/core/state.ts index f3a29f0..bca0e50 100644 --- a/src/core/state.ts +++ b/src/core/state.ts @@ -88,6 +88,7 @@ export type GameState = { bonusOverlay: Overlay, selected?: SelectionState, score: number, + lost: boolean, panic: PanicData | undefined, paused: PauseData | undefined, }; @@ -121,6 +122,7 @@ export function mkGameState(seed?: number): GameState { bonusLayer: mkLayer(bonusGenerator), bonusOverlay: mkOverlay(), score: 0, + lost: false, panic: undefined, paused: undefined, }; diff --git a/src/core/tools.ts b/src/core/tools.ts index 4cf6700..69d276d 100644 --- a/src/core/tools.ts +++ b/src/core/tools.ts @@ -17,6 +17,9 @@ export function indexOfTool(tool: Tool): number { } export function currentTool(state: GameState): Tool { + if (state.lost) { + return 'hand'; + } // state should be responsible for maintaining the invariant that // tool index is always valid. Maybe instead I should store Tool in // state, not toolIndex, idk. diff --git a/src/ui/instructions.tsx b/src/ui/instructions.tsx index 011b220..8beb1d6 100644 --- a/src/ui/instructions.tsx +++ b/src/ui/instructions.tsx @@ -143,6 +143,7 @@ function exampleState(): GameState { } }, score: 7, + lost: false, panic: { currentTime: Date.now(), lastClear: Date.now() - PANIC_INTERVAL_MS / 3 }, paused: undefined, }; diff --git a/src/ui/render.ts b/src/ui/render.ts index e7b79c0..dd59e3c 100644 --- a/src/ui/render.ts +++ b/src/ui/render.ts @@ -189,10 +189,17 @@ export function rawPaint(ci: CanvasInfo, state: GameState) { { p: { x: 0, y: S * state.toolIndex }, sz: { x: S, y: S } } ); fillRect(d, rect_in_canvas, 'rgba(255, 255, 0, 0.5)'); + } + function drawPauseButton() { d.textAlign = 'center'; d.textBaseline = 'middle'; - fillText(d, "⏸", midpointOfRect(pause_button_bds_in_canvas), 'black', '48px sans-serif'); + if (!state.lost) { + fillText(d, "⏸", midpointOfRect(pause_button_bds_in_canvas), 'black', '48px sans-serif'); + } + else { + fillText(d, "⟳", midpointOfRect(pause_button_bds_in_canvas), 'black', '48px sans-serif'); + } } function drawHand() { @@ -280,11 +287,21 @@ export function rawPaint(ci: CanvasInfo, state: GameState) { }); } - drawToolbar(); + if (!state.lost) + drawToolbar(); + else { + fillRect(d, toolbar_bds_in_canvas, backgroundGray); + } + drawPauseButton(); drawWorld(); drawHand(); - drawOtherUi(); - drawAnimations(Date.now()); + if (!state.lost) { + drawOtherUi(); + drawAnimations(Date.now()); + } + else { + fillText(d, "You lost :(", midpointOfRect(canvas_bds_in_canvas), 'rgba(0,0,0,0.3)', '96px sans-serif'); + } } export class RenderPane {