Skip to content

Commit

Permalink
Save random seed for layer generation (#95)
Browse files Browse the repository at this point in the history
Save and restore is still buggy with respect to bonuses, not sure why.
Also tile id generation is outside of state, therefore does not work
with save and restore.
  • Loading branch information
jcreedcmu committed Nov 24, 2023
1 parent e43ca9f commit 89fa0af
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 15 deletions.
5 changes: 3 additions & 2 deletions src/core/bonus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,10 @@ export type BonusLayerId = string;
const _cachedBonusLayer: Record<BonusLayerId, Layer<Bonus>> = {};

const DETERMINISTIC_SEED = 46;
export function getBonusLayer(name: string): Layer<Bonus> {
export function getBonusLayer(seed: number = DETERMINISTIC_SEED): Layer<Bonus> {
const name = `game-${seed}`;
if (_cachedBonusLayer[name] == undefined) {
_cachedBonusLayer[name] = mkBonusLayer(name == 'game' ? Date.now() : DETERMINISTIC_SEED);
_cachedBonusLayer[name] = mkBonusLayer(seed);
}
return _cachedBonusLayer[name];
}
4 changes: 2 additions & 2 deletions src/core/reduce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function resolveMouseupInner(state: GameState): GameState {
});

const tgts = moves.map(x => x.p_in_world_int);
if (isCollision(remainingTiles, moves, state.coreState.bonusOverlay, getBonusLayer(state.coreState.bonusLayerName))) {
if (isCollision(remainingTiles, moves, state.coreState.bonusOverlay, getBonusLayer(state.coreState.bonusLayerSeed))) {
return state;
}

Expand Down Expand Up @@ -374,7 +374,7 @@ export function reduce(scState: SceneState, action: Action): effectful.Result<Sc
case 'resize': return { state: scState, effects: [] }; // XXX maybe stash viewdata this in state somewhere?
case 'newGame':
return {
state: mkGameSceneState(Date.now(), action.creative ?? false), effects: [],
state: mkGameSceneState(Date.now(), action.creative ?? false, Date.now()), effects: [],
};
case 'setSceneState':
return { state: action.state, effects: [] };
Expand Down
2 changes: 1 addition & 1 deletion src/core/state-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export function unpauseState(state: CoreState, pause: PauseData): CoreState {
}

export function bonusOfStatePoint(cs: CoreState, p: Point): Bonus {
return getOverlayLayer(cs.bonusOverlay, getBonusLayer(cs.bonusLayerName), p);
return getOverlayLayer(cs.bonusOverlay, getBonusLayer(cs.bonusLayerSeed), p);
}

export function tileFall(state: CoreState, ms: MouseState): Point {
Expand Down
12 changes: 6 additions & 6 deletions src/core/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export type CoreState = {
connectedSet: Grid<boolean>,
energies: Energies,
canvas_from_world: SE2,
seed: number,
seed: number, // changes during game play, determines which letters are drawn
bonusOverlay: Overlay<Bonus>,
selected?: SelectionState,
scoring: ScoreState,
Expand All @@ -103,7 +103,7 @@ export type CoreState = {
consonants: number,
copies: number,
}
bonusLayerName: string,
bonusLayerSeed: number, // immutable during game play
};

export type GameState = {
Expand All @@ -115,16 +115,16 @@ export function mkSceneState(): SceneState {
return { t: 'menu' };
}

export function mkGameSceneState(seed: number, creative: boolean): SceneState {
export function mkGameSceneState(seed: number, creative: boolean, bonusLayerSeed: number): SceneState {
return {
t: 'game',
gameState: mkGameState(seed, creative), revision: 0
gameState: mkGameState(seed, creative, bonusLayerSeed), revision: 0
};
}

const DEFAULT_SCALE = 48;

export function mkGameState(seed: number, creative: boolean): GameState {
export function mkGameState(seed: number, creative: boolean, bonusLayerSeed: number): GameState {
return {
coreState: {
animations: [],
Expand Down Expand Up @@ -153,7 +153,7 @@ export function mkGameState(seed: number, creative: boolean): GameState {
consonants: 0,
copies: 0,
},
bonusLayerName: 'game',
bonusLayerSeed,
},
mouseState: { t: 'up', p_in_canvas: { x: 0, y: 0 } },
};
Expand Down
2 changes: 1 addition & 1 deletion src/ui/instructions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ function render(ci: CanvasInfo, props: CanvasProps) {
function exampleState(): GameState {
const state: GameState = {
coreState: {
bonusLayerName: 'instructions',
animations: [],
currentTool: 'pointer',
invalidWords: [],
Expand Down Expand Up @@ -155,6 +154,7 @@ function exampleState(): GameState {
byClass: [0, 0,],
},
seed: 1533311107,
bonusLayerSeed: 46,
canvas_from_world: {
scale: {
x: 39.6694214876033,
Expand Down
6 changes: 3 additions & 3 deletions tests/test-state-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { produce } from "../src/util/produce";
const SEED = 12345678;

function twoTileState(): GameState {
let state = mkGameState(SEED, false);
let state = mkGameState(SEED, false, SEED);
state = produce(state, s => addWorldTile(s.coreState, { letter: 'A', p_in_world_int: { x: 0, y: 0 }, id: '1' }));
state = produce(state, s => addWorldTile(s.coreState, { letter: 'B', p_in_world_int: { x: 1, y: 0 }, id: '2' }));
return state;
Expand Down Expand Up @@ -45,7 +45,7 @@ describe('addWorldTile', () => {
});

test('should generate ids correctly', () => {
let state = mkGameState(SEED, false);
let state = mkGameState(SEED, false, SEED);
state = produce(state, s => addWorldTile(s.coreState, { letter: 'A', p_in_world_int: { x: 0, y: 0 } }));
state = produce(state, s => addWorldTile(s.coreState, { letter: 'B', p_in_world_int: { x: 1, y: 0 } }));
expect(Object.keys(state.coreState.tile_entities).length).toBe(2);
Expand Down Expand Up @@ -86,7 +86,7 @@ describe('moveTile', () => {

describe('removeTile', () => {
test('should work correctly', () => {
const state = withCoreState(mkGameState(SEED, false), cs => checkValid(addWorldTiles(cs, debugTiles())));
const state = withCoreState(mkGameState(SEED, false, SEED), cs => checkValid(addWorldTiles(cs, debugTiles())));
const state2 = removeTile(state.coreState, Object.keys(state.coreState.tile_entities)[0]);
expect(Object.keys(state2.tile_entities).length).toBe(Object.keys(state.coreState.tile_entities).length - 1);
});
Expand Down

0 comments on commit 89fa0af

Please sign in to comment.