mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-19 22:09:37 +00:00
feat(adventure): add state management, tags, and prestige
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
75
apps/architecture-adventure/src/state/gameState.ts
Normal file
75
apps/architecture-adventure/src/state/gameState.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import type { CurrentRun, Layer, SaveState } from '@/types'
|
||||
|
||||
const STORAGE_KEY = 'codebase-caverns-v2'
|
||||
const SAVE_VERSION = 1
|
||||
|
||||
function createFreshRun(layer: Layer): CurrentRun {
|
||||
return {
|
||||
layer,
|
||||
path: [],
|
||||
resolvedChallenges: {},
|
||||
conceptTags: [],
|
||||
insightEarned: 0,
|
||||
currentRoom: 'entry'
|
||||
}
|
||||
}
|
||||
|
||||
function createDefaultSave(): SaveState {
|
||||
return {
|
||||
version: SAVE_VERSION,
|
||||
currentRun: createFreshRun(1),
|
||||
history: [],
|
||||
persistent: {
|
||||
totalInsight: 0,
|
||||
currentLayer: 1,
|
||||
achievements: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadSave(): SaveState {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY)
|
||||
if (!raw) return createDefaultSave()
|
||||
|
||||
const parsed: unknown = JSON.parse(raw)
|
||||
if (
|
||||
typeof parsed === 'object' &&
|
||||
parsed !== null &&
|
||||
'version' in parsed &&
|
||||
(parsed as SaveState).version === SAVE_VERSION
|
||||
) {
|
||||
return parsed as SaveState
|
||||
}
|
||||
return createDefaultSave()
|
||||
} catch {
|
||||
return createDefaultSave()
|
||||
}
|
||||
}
|
||||
|
||||
function persistSave(save: SaveState): void {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(save))
|
||||
}
|
||||
|
||||
function clearSave(): void {
|
||||
localStorage.removeItem(STORAGE_KEY)
|
||||
}
|
||||
|
||||
function isV1Save(): boolean {
|
||||
try {
|
||||
const raw = localStorage.getItem('codebase-caverns')
|
||||
return raw !== null
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
clearSave,
|
||||
createDefaultSave,
|
||||
createFreshRun,
|
||||
isV1Save,
|
||||
loadSave,
|
||||
persistSave,
|
||||
SAVE_VERSION
|
||||
}
|
||||
36
apps/architecture-adventure/src/state/prestige.ts
Normal file
36
apps/architecture-adventure/src/state/prestige.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { Layer, RunRecord, SaveState } from '@/types'
|
||||
import { createFreshRun } from '@/state/gameState'
|
||||
|
||||
function finalizeRun(save: SaveState, narrativeSummary: string): RunRecord {
|
||||
return {
|
||||
layer: save.currentRun.layer,
|
||||
path: save.currentRun.path,
|
||||
challenges: { ...save.currentRun.resolvedChallenges },
|
||||
conceptTags: [...save.currentRun.conceptTags],
|
||||
insightEarned: save.currentRun.insightEarned,
|
||||
narrativeSummary
|
||||
}
|
||||
}
|
||||
|
||||
function canPrestige(save: SaveState): boolean {
|
||||
return save.persistent.currentLayer < 3
|
||||
}
|
||||
|
||||
function prestige(save: SaveState, narrativeSummary: string): SaveState {
|
||||
const record = finalizeRun(save, narrativeSummary)
|
||||
const nextLayer = Math.min(save.persistent.currentLayer + 1, 3) as Layer
|
||||
|
||||
return {
|
||||
...save,
|
||||
currentRun: createFreshRun(nextLayer),
|
||||
history: [...save.history, record],
|
||||
persistent: {
|
||||
...save.persistent,
|
||||
totalInsight:
|
||||
save.persistent.totalInsight + save.currentRun.insightEarned,
|
||||
currentLayer: nextLayer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { canPrestige, finalizeRun, prestige }
|
||||
34
apps/architecture-adventure/src/state/tags.ts
Normal file
34
apps/architecture-adventure/src/state/tags.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { RoomDefinition, SaveState } from '@/types'
|
||||
|
||||
function hasAllPrerequisites(
|
||||
room: RoomDefinition,
|
||||
earnedTags: string[]
|
||||
): boolean {
|
||||
return room.prerequisites.every((tag) => earnedTags.includes(tag))
|
||||
}
|
||||
|
||||
function getUnmetPrerequisites(
|
||||
room: RoomDefinition,
|
||||
earnedTags: string[]
|
||||
): string[] {
|
||||
return room.prerequisites.filter((tag) => !earnedTags.includes(tag))
|
||||
}
|
||||
|
||||
function canEnterRoom(room: RoomDefinition, save: SaveState): boolean {
|
||||
return hasAllPrerequisites(room, save.currentRun.conceptTags)
|
||||
}
|
||||
|
||||
function grantTags(save: SaveState, tags: string[]): SaveState {
|
||||
const newTags = tags.filter((t) => !save.currentRun.conceptTags.includes(t))
|
||||
if (newTags.length === 0) return save
|
||||
|
||||
return {
|
||||
...save,
|
||||
currentRun: {
|
||||
...save.currentRun,
|
||||
conceptTags: [...save.currentRun.conceptTags, ...newTags]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { canEnterRoom, getUnmetPrerequisites, grantTags, hasAllPrerequisites }
|
||||
Reference in New Issue
Block a user