mirror of
https://github.com/tcsenpai/shellquest.git
synced 2025-05-31 16:30:13 +00:00
fixed level2 progression and initialization
This commit is contained in:
parent
4e532911af
commit
e98a416277
@ -1,248 +1,267 @@
|
||||
import { Level, LevelResult, registerLevel } from '../core/levelSystem';
|
||||
import { getCurrentGameState } from '../core/gameState';
|
||||
import { Level, LevelResult, registerLevel } from "../core/levelSystem";
|
||||
import { getCurrentGameState } from "../core/gameState";
|
||||
|
||||
interface Level2State {
|
||||
currentDir: string;
|
||||
fileSystem: {
|
||||
[key: string]: {
|
||||
type: "dir" | "file";
|
||||
contents?: string[];
|
||||
content?: string;
|
||||
};
|
||||
};
|
||||
foundKey?: boolean;
|
||||
}
|
||||
|
||||
const level: Level = {
|
||||
id: 2,
|
||||
name: 'File System Maze',
|
||||
description: 'Navigate through a virtual file system to find the key.',
|
||||
|
||||
name: "File System Maze",
|
||||
description: "Navigate through a virtual file system to find the key.",
|
||||
|
||||
async initialize() {
|
||||
const gameState = getCurrentGameState();
|
||||
if (!gameState) return;
|
||||
|
||||
|
||||
// Initialize level state if not already present
|
||||
if (!gameState.levelStates[this.id]) {
|
||||
gameState.levelStates[this.id] = {
|
||||
currentDir: '/home/user',
|
||||
foundKey: false,
|
||||
fileSystem: {
|
||||
'/home/user': {
|
||||
type: 'dir',
|
||||
contents: ['Documents', 'Pictures', '.hidden']
|
||||
},
|
||||
'/home/user/Documents': {
|
||||
type: 'dir',
|
||||
contents: ['notes.txt', 'secret']
|
||||
},
|
||||
'/home/user/Documents/notes.txt': {
|
||||
type: 'file',
|
||||
content: 'Remember to check hidden files. They start with a dot.'
|
||||
},
|
||||
'/home/user/Documents/secret': {
|
||||
type: 'dir',
|
||||
contents: ['decoy.key']
|
||||
},
|
||||
'/home/user/Documents/secret/decoy.key': {
|
||||
type: 'file',
|
||||
content: 'Nice try, but this is not the real key!'
|
||||
},
|
||||
'/home/user/Pictures': {
|
||||
type: 'dir',
|
||||
contents: ['vacation.jpg']
|
||||
},
|
||||
'/home/user/Pictures/vacation.jpg': {
|
||||
type: 'file',
|
||||
content: 'Just a picture of a beach. Nothing special here.'
|
||||
},
|
||||
'/home/user/.hidden': {
|
||||
type: 'dir',
|
||||
contents: ['system.key']
|
||||
},
|
||||
'/home/user/.hidden/system.key': {
|
||||
type: 'file',
|
||||
content: 'REAL_KEY_FOUND'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
//if (!gameState.levelStates[this.id]) {
|
||||
gameState.levelStates[this.id] = {
|
||||
currentDir: "/home/user",
|
||||
fileSystem: {
|
||||
"/home/user": {
|
||||
type: "dir",
|
||||
contents: ["Documents", "Pictures", ".hidden"],
|
||||
},
|
||||
"/home/user/Documents": {
|
||||
type: "dir",
|
||||
contents: ["notes.txt", "system.key"],
|
||||
},
|
||||
"/home/user/Documents/notes.txt": {
|
||||
type: "file",
|
||||
content: "The system key is hidden somewhere in this directory...",
|
||||
},
|
||||
"/home/user/Documents/system.key": {
|
||||
type: "file",
|
||||
content: "Congratulations! You found the system key: XK42-9Y7Z",
|
||||
},
|
||||
"/home/user/Pictures": {
|
||||
type: "dir",
|
||||
contents: ["vacation.jpg"],
|
||||
},
|
||||
"/home/user/Pictures/vacation.jpg": {
|
||||
type: "file",
|
||||
content: "Just a nice beach photo.",
|
||||
},
|
||||
"/home/user/.hidden": {
|
||||
type: "dir",
|
||||
contents: ["readme.md"],
|
||||
},
|
||||
"/home/user/.hidden/readme.md": {
|
||||
type: "file",
|
||||
content: "Nothing to see here...",
|
||||
},
|
||||
},
|
||||
};
|
||||
//}
|
||||
},
|
||||
|
||||
|
||||
async render() {
|
||||
const gameState = getCurrentGameState();
|
||||
if (!gameState) return;
|
||||
|
||||
|
||||
// Make sure level state is initialized
|
||||
if (!gameState.levelStates[this.id]) {
|
||||
await this.initialize();
|
||||
return; // Return here to ensure the state is available in the next render
|
||||
}
|
||||
|
||||
const levelState = gameState.levelStates[this.id];
|
||||
const currentDir = levelState.currentDir;
|
||||
const fileSystem = levelState.fileSystem;
|
||||
|
||||
console.log('You\'re in a virtual file system and need to find the system key.');
|
||||
console.log('');
|
||||
|
||||
const levelState = gameState.levelStates[this.id] as Level2State;
|
||||
if (!levelState || !levelState.currentDir || !levelState.fileSystem) {
|
||||
console.log("[DEBUG] Level state not properly initialized");
|
||||
console.log(JSON.stringify(levelState, null, 2));
|
||||
console.log("Error: Level state not properly initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
const { currentDir, fileSystem } = levelState;
|
||||
|
||||
console.log(
|
||||
"You're in a virtual file system and need to find the system key."
|
||||
);
|
||||
console.log("");
|
||||
console.log(`Current directory: ${currentDir}`);
|
||||
console.log('');
|
||||
|
||||
if (fileSystem[currentDir].type === 'dir') {
|
||||
console.log('Contents:');
|
||||
console.log("");
|
||||
|
||||
if (fileSystem[currentDir].type === "dir") {
|
||||
console.log("Contents:");
|
||||
if (fileSystem[currentDir].contents.length === 0) {
|
||||
console.log(' (empty directory)');
|
||||
console.log(" (empty directory)");
|
||||
} else {
|
||||
fileSystem[currentDir].contents.forEach(item => {
|
||||
fileSystem[currentDir].contents.forEach((item) => {
|
||||
const path = `${currentDir}/${item}`;
|
||||
const type = fileSystem[path].type === 'dir' ? 'Directory' : 'File';
|
||||
const type = fileSystem[path].type === "dir" ? "Directory" : "File";
|
||||
console.log(` ${item} (${type})`);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('File content:');
|
||||
console.log("File content:");
|
||||
console.log(fileSystem[currentDir].content);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('Commands: "ls", "cd [dir]", "cat [file]", "pwd", "find [name]"');
|
||||
|
||||
console.log("");
|
||||
console.log(
|
||||
'Commands: "ls", "cd [dir]", "cat [file]", "pwd", "find [name]"'
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
async handleInput(input: string): Promise<LevelResult> {
|
||||
const gameState = getCurrentGameState();
|
||||
if (!gameState) {
|
||||
return { completed: false };
|
||||
}
|
||||
|
||||
|
||||
// Make sure level state is initialized
|
||||
if (!gameState.levelStates[this.id]) {
|
||||
await this.initialize();
|
||||
}
|
||||
|
||||
|
||||
const levelState = gameState.levelStates[this.id];
|
||||
const fileSystem = levelState.fileSystem;
|
||||
const command = input.trim();
|
||||
|
||||
|
||||
// Split command into parts
|
||||
const parts = command.split(' ');
|
||||
const parts = command.split(" ");
|
||||
const cmd = parts[0].toLowerCase();
|
||||
|
||||
if (cmd === 'ls') {
|
||||
|
||||
if (cmd === "ls") {
|
||||
// List directory contents
|
||||
return {
|
||||
completed: false,
|
||||
message: fileSystem[levelState.currentDir].contents.join('\n')
|
||||
message: fileSystem[levelState.currentDir].contents.join("\n"),
|
||||
};
|
||||
}
|
||||
|
||||
if (cmd === 'pwd') {
|
||||
|
||||
if (cmd === "pwd") {
|
||||
// Print working directory
|
||||
return {
|
||||
completed: false,
|
||||
message: levelState.currentDir
|
||||
message: levelState.currentDir,
|
||||
};
|
||||
}
|
||||
|
||||
if (cmd === 'cd' && parts.length > 1) {
|
||||
|
||||
if (cmd === "cd" && parts.length > 1) {
|
||||
// Change directory
|
||||
const target = parts[1];
|
||||
|
||||
if (target === '..') {
|
||||
|
||||
if (target === "..") {
|
||||
// Go up one directory
|
||||
const pathParts = levelState.currentDir.split('/');
|
||||
if (pathParts.length > 2) { // Don't go above /home/user
|
||||
const pathParts = levelState.currentDir.split("/");
|
||||
if (pathParts.length > 2) {
|
||||
// Don't go above /home/user
|
||||
pathParts.pop();
|
||||
levelState.currentDir = pathParts.join('/');
|
||||
levelState.currentDir = pathParts.join("/");
|
||||
return {
|
||||
completed: false,
|
||||
message: `Changed directory to ${levelState.currentDir}`
|
||||
message: `Changed directory to ${levelState.currentDir}`,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
completed: false,
|
||||
message: 'Cannot go above the home directory.'
|
||||
message: "Cannot go above the home directory.",
|
||||
};
|
||||
}
|
||||
} else if (target === '.') {
|
||||
} else if (target === ".") {
|
||||
// Stay in current directory
|
||||
return {
|
||||
completed: false,
|
||||
message: `Still in ${levelState.currentDir}`
|
||||
message: `Still in ${levelState.currentDir}`,
|
||||
};
|
||||
} else {
|
||||
// Go to specified directory
|
||||
const newPath = `${levelState.currentDir}/${target}`;
|
||||
|
||||
if (fileSystem[newPath] && fileSystem[newPath].type === 'dir') {
|
||||
|
||||
if (fileSystem[newPath] && fileSystem[newPath].type === "dir") {
|
||||
levelState.currentDir = newPath;
|
||||
return {
|
||||
completed: false,
|
||||
message: `Changed directory to ${levelState.currentDir}`
|
||||
message: `Changed directory to ${levelState.currentDir}`,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
completed: false,
|
||||
message: `Cannot change to ${target}: No such directory`
|
||||
message: `Cannot change to ${target}: No such directory`,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd === 'cat' && parts.length > 1) {
|
||||
|
||||
if (cmd === "cat" && parts.length > 1) {
|
||||
// View file contents
|
||||
const target = parts[1];
|
||||
const filePath = `${levelState.currentDir}/${target}`;
|
||||
|
||||
if (fileSystem[filePath] && fileSystem[filePath].type === 'file') {
|
||||
|
||||
if (fileSystem[filePath] && fileSystem[filePath].type === "file") {
|
||||
const content = fileSystem[filePath].content;
|
||||
|
||||
|
||||
// Check if this is the key file
|
||||
if (filePath === '/home/user/.hidden/system.key') {
|
||||
if (filePath === "/home/user/Documents/system.key") {
|
||||
levelState.foundKey = true;
|
||||
return {
|
||||
completed: true,
|
||||
message: `You found the system key! The file contains: ${content}`,
|
||||
nextAction: 'next_level'
|
||||
nextAction: "next_level",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
completed: false,
|
||||
message: `File contents: ${content}`
|
||||
message: `File contents: ${content}`,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
completed: false,
|
||||
message: `Cannot read ${target}: No such file`
|
||||
message: `Cannot read ${target}: No such file`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd === 'find' && parts.length > 1) {
|
||||
|
||||
if (cmd === "find" && parts.length > 1) {
|
||||
// Simple find implementation
|
||||
const target = parts[1];
|
||||
const results: string[] = [];
|
||||
|
||||
|
||||
// Search through the file system
|
||||
Object.keys(fileSystem).forEach(path => {
|
||||
Object.keys(fileSystem).forEach((path) => {
|
||||
if (path.includes(target)) {
|
||||
results.push(path);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (results.length > 0) {
|
||||
return {
|
||||
completed: false,
|
||||
message: `Found matches:\n${results.join('\n')}`
|
||||
message: `Found matches:\n${results.join("\n")}`,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
completed: false,
|
||||
message: `No matches found for "${target}"`
|
||||
message: `No matches found for "${target}"`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
completed: false,
|
||||
message: 'Unknown command or invalid syntax.'
|
||||
message: "Unknown command or invalid syntax.",
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
hints: [
|
||||
'Try using basic Linux commands like "ls", "cd", and "cat".',
|
||||
'Remember that hidden files and directories start with a dot (.)',
|
||||
'Use "ls" to list files, "cd" to change directories, and "cat" to view file contents.'
|
||||
]
|
||||
"Remember that hidden files and directories start with a dot (.)",
|
||||
'Use "ls" to list files, "cd" to change directories, and "cat" to view file contents.',
|
||||
],
|
||||
};
|
||||
|
||||
export function registerLevel2() {
|
||||
registerLevel(level);
|
||||
}
|
||||
}
|
||||
|
221
src/ui/gameUI.ts
221
src/ui/gameUI.ts
@ -1,28 +1,38 @@
|
||||
import { getCurrentGameState, saveGame } from '../core/gameState';
|
||||
import { getLevelById, completeCurrentLevel, getAllLevels } from '../core/levelSystem';
|
||||
import { renderMainMenu } from './mainMenu';
|
||||
import { clearScreen, promptInput, styles, drawBox, drawTable } from './uiHelpers';
|
||||
import {
|
||||
getTheme,
|
||||
successAnimation,
|
||||
import { getCurrentGameState, saveGame } from "../core/gameState";
|
||||
import {
|
||||
getLevelById,
|
||||
completeCurrentLevel,
|
||||
getAllLevels,
|
||||
} from "../core/levelSystem";
|
||||
import { renderMainMenu } from "./mainMenu";
|
||||
import {
|
||||
clearScreen,
|
||||
promptInput,
|
||||
styles,
|
||||
drawBox,
|
||||
drawTable,
|
||||
} from "./uiHelpers";
|
||||
import {
|
||||
getTheme,
|
||||
successAnimation,
|
||||
typewriter,
|
||||
loadingAnimation
|
||||
} from './visualEffects';
|
||||
import { playSound } from './soundEffects';
|
||||
import { levelUI } from './levelRenderer';
|
||||
import { addToHistory } from './commandHistory';
|
||||
import { triggerAchievement } from '../core/achievements';
|
||||
loadingAnimation,
|
||||
} from "./visualEffects";
|
||||
import { playSound } from "./soundEffects";
|
||||
import { levelUI } from "./levelRenderer";
|
||||
import { addToHistory } from "./commandHistory";
|
||||
import { triggerAchievement } from "../core/achievements";
|
||||
|
||||
export async function renderGameUI(): Promise<void> {
|
||||
const gameState = getCurrentGameState();
|
||||
if (!gameState) {
|
||||
console.error(styles.error('No active game'));
|
||||
console.error(styles.error("No active game"));
|
||||
await renderMainMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const theme = getTheme();
|
||||
|
||||
|
||||
// Game loop
|
||||
while (true) {
|
||||
// Get the current level at the start of each loop iteration
|
||||
@ -32,161 +42,184 @@ export async function renderGameUI(): Promise<void> {
|
||||
await renderMainMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
clearScreen();
|
||||
|
||||
|
||||
// Display game header
|
||||
console.log(drawBox(
|
||||
`SHELLQUEST - ${theme.accent(currentLevel.name)}`,
|
||||
`Player: ${theme.accent(gameState.playerName)}\nLevel: ${gameState.currentLevel}/${getAllLevels().length}`
|
||||
));
|
||||
console.log('');
|
||||
|
||||
console.log(
|
||||
drawBox(
|
||||
`SHELLQUEST - ${theme.accent(currentLevel.name)}`,
|
||||
`Player: ${theme.accent(gameState.playerName)}\nLevel: ${
|
||||
gameState.currentLevel
|
||||
}/${getAllLevels().length}`
|
||||
)
|
||||
);
|
||||
console.log("");
|
||||
|
||||
// Render current level in a box
|
||||
await levelUI.levelContent(currentLevel.name, async () => {
|
||||
await currentLevel.render();
|
||||
});
|
||||
|
||||
console.log('');
|
||||
console.log(theme.secondary('Available commands:'));
|
||||
console.log(`${theme.accent('/help')} - Show help, ${theme.accent('/save')} - Save game, ${theme.accent('/menu')} - Main menu, ${theme.accent('/hint')} - Get a hint`);
|
||||
console.log('');
|
||||
|
||||
|
||||
console.log("");
|
||||
console.log(theme.secondary("Available commands:"));
|
||||
console.log(
|
||||
`${theme.accent("/help")} - Show help, ${theme.accent(
|
||||
"/save"
|
||||
)} - Save game, ${theme.accent("/menu")} - Main menu, ${theme.accent(
|
||||
"/hint"
|
||||
)} - Get a hint`
|
||||
);
|
||||
console.log("");
|
||||
|
||||
// Display input box and get player input
|
||||
levelUI.inputBox();
|
||||
const input = await promptInput('');
|
||||
|
||||
const input = await promptInput("");
|
||||
|
||||
if (input.trim()) {
|
||||
addToHistory(gameState.playerName, input);
|
||||
}
|
||||
|
||||
|
||||
// Handle special commands
|
||||
if (input.startsWith('/')) {
|
||||
if (input.startsWith("/")) {
|
||||
const command = input.slice(1).toLowerCase();
|
||||
|
||||
if (command === 'help') {
|
||||
|
||||
if (command === "help") {
|
||||
await showHelp();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command === 'save') {
|
||||
|
||||
if (command === "save") {
|
||||
const result = await saveGame();
|
||||
if (result.success) {
|
||||
console.log(theme.success(result.message));
|
||||
} else {
|
||||
console.log(theme.error(result.message));
|
||||
}
|
||||
await promptInput('Press Enter to continue...');
|
||||
await promptInput("Press Enter to continue...");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command === 'menu') {
|
||||
|
||||
if (command === "menu") {
|
||||
await renderMainMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
if (command === 'hint') {
|
||||
await triggerAchievement('hint_used');
|
||||
|
||||
if (command === "hint") {
|
||||
await triggerAchievement("hint_used");
|
||||
await showHint(currentLevel.hints);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Process level-specific input
|
||||
const result = await currentLevel.handleInput(input);
|
||||
|
||||
|
||||
if (result.message) {
|
||||
console.log('');
|
||||
console.log("");
|
||||
await typewriter(result.message, 5);
|
||||
await promptInput('Press Enter to continue...');
|
||||
await promptInput("Press Enter to continue...");
|
||||
}
|
||||
|
||||
|
||||
if (result.completed) {
|
||||
playSound('levelComplete');
|
||||
playSound("levelComplete");
|
||||
await completeCurrentLevel();
|
||||
|
||||
|
||||
// Trigger level completion achievement
|
||||
await triggerAchievement('level_completed', {
|
||||
await triggerAchievement("level_completed", {
|
||||
levelId: gameState.currentLevel,
|
||||
usedHint: gameState.levelStates[gameState.currentLevel]?.usedHint || false,
|
||||
timeSpent: gameState.levelStates[gameState.currentLevel]?.timeSpent || 0,
|
||||
allLevels: getAllLevels().length
|
||||
usedHint:
|
||||
gameState.levelStates[gameState.currentLevel]?.usedHint || false,
|
||||
timeSpent:
|
||||
gameState.levelStates[gameState.currentLevel]?.timeSpent || 0,
|
||||
allLevels: getAllLevels().length,
|
||||
});
|
||||
|
||||
await successAnimation('Level completed!');
|
||||
|
||||
if (result.nextAction === 'main_menu') {
|
||||
|
||||
await successAnimation("Level completed!");
|
||||
|
||||
if (result.nextAction === "main_menu") {
|
||||
await renderMainMenu();
|
||||
return;
|
||||
} else if (result.nextAction === 'next_level') {
|
||||
} else if (result.nextAction === "next_level") {
|
||||
const nextLevelId = gameState.currentLevel + 1;
|
||||
const nextLevel = getLevelById(nextLevelId);
|
||||
|
||||
|
||||
if (nextLevel) {
|
||||
gameState.currentLevel = nextLevelId;
|
||||
await loadingAnimation('Loading next level...', 1500);
|
||||
// Initialize the next level before loading it
|
||||
await nextLevel.initialize();
|
||||
await loadingAnimation("Loading next level...", 1500);
|
||||
} else {
|
||||
// Game completed
|
||||
clearScreen();
|
||||
console.log(theme.success('🎉 Congratulations! You have completed all levels! 🎉'));
|
||||
await typewriter('You have proven yourself to be a master of the terminal.', 20);
|
||||
await promptInput('Press Enter to return to the main menu...');
|
||||
console.log(
|
||||
theme.success(
|
||||
"🎉 Congratulations! You have completed all levels! 🎉"
|
||||
)
|
||||
);
|
||||
await typewriter(
|
||||
"You have proven yourself to be a master of the terminal.",
|
||||
20
|
||||
);
|
||||
await promptInput("Press Enter to return to the main menu...");
|
||||
await renderMainMenu();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// When using a command, track it for achievements
|
||||
await triggerAchievement('command_used', { command: input });
|
||||
await triggerAchievement("command_used", { command: input });
|
||||
}
|
||||
}
|
||||
|
||||
async function showHelp(): Promise<void> {
|
||||
const theme = getTheme();
|
||||
|
||||
|
||||
clearScreen();
|
||||
console.log(theme.accent('=== Help ==='));
|
||||
console.log('');
|
||||
console.log('ShellQuest is a puzzle game where you solve Linux-themed challenges.');
|
||||
console.log('');
|
||||
console.log(theme.secondary('Special Commands:'));
|
||||
console.log(`${theme.accent('/help')} - Show this help screen`);
|
||||
console.log(`${theme.accent('/save')} - Save your game`);
|
||||
console.log(`${theme.accent('/menu')} - Return to main menu`);
|
||||
console.log(`${theme.accent('/hint')} - Get a hint for the current level`);
|
||||
console.log('');
|
||||
console.log('Each level has its own commands and puzzles to solve.');
|
||||
console.log('');
|
||||
await promptInput('Press Enter to continue...');
|
||||
console.log(theme.accent("=== Help ==="));
|
||||
console.log("");
|
||||
console.log(
|
||||
"ShellQuest is a puzzle game where you solve Linux-themed challenges."
|
||||
);
|
||||
console.log("");
|
||||
console.log(theme.secondary("Special Commands:"));
|
||||
console.log(`${theme.accent("/help")} - Show this help screen`);
|
||||
console.log(`${theme.accent("/save")} - Save your game`);
|
||||
console.log(`${theme.accent("/menu")} - Return to main menu`);
|
||||
console.log(`${theme.accent("/hint")} - Get a hint for the current level`);
|
||||
console.log("");
|
||||
console.log("Each level has its own commands and puzzles to solve.");
|
||||
console.log("");
|
||||
await promptInput("Press Enter to continue...");
|
||||
}
|
||||
|
||||
async function showHint(hints: string[]): Promise<void> {
|
||||
const gameState = getCurrentGameState();
|
||||
if (!gameState) return;
|
||||
|
||||
|
||||
const theme = getTheme();
|
||||
|
||||
|
||||
// Get level state for hints
|
||||
const levelState = gameState.levelStates[gameState.currentLevel] || {};
|
||||
const hintIndex = levelState.hintIndex || 0;
|
||||
|
||||
|
||||
clearScreen();
|
||||
console.log(theme.accent('=== Hint ==='));
|
||||
console.log('');
|
||||
|
||||
console.log(theme.accent("=== Hint ==="));
|
||||
console.log("");
|
||||
|
||||
if (hintIndex < hints.length) {
|
||||
await typewriter(hints[hintIndex], 20);
|
||||
|
||||
|
||||
// Update hint index for next time
|
||||
gameState.levelStates[gameState.currentLevel] = {
|
||||
...levelState,
|
||||
hintIndex: hintIndex + 1
|
||||
hintIndex: hintIndex + 1,
|
||||
};
|
||||
} else {
|
||||
console.log(theme.warning('No more hints available for this level.'));
|
||||
console.log(theme.warning("No more hints available for this level."));
|
||||
}
|
||||
|
||||
console.log('');
|
||||
await promptInput('Press Enter to continue...');
|
||||
}
|
||||
|
||||
console.log("");
|
||||
await promptInput("Press Enter to continue...");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user