mirror of
https://github.com/tcsenpai/shellquest.git
synced 2025-05-31 16:30:13 +00:00
qol and readmes
This commit is contained in:
parent
5c9be8fc79
commit
81cf69e1b0
@ -1,6 +1,4 @@
|
||||
You're right! Let's enhance the LEVELS.md guide with more detailed examples of how to implement complex level mechanics like file system navigation, process management, and other Linux-like features.
|
||||
|
||||
````markdown:LEVELS.md
|
||||
# LEVELS.md - Guide to Adding New Levels
|
||||
|
||||
## Introduction
|
||||
@ -641,7 +639,3 @@ Always test your level thoroughly to ensure:
|
||||
|
||||
Happy level creating!
|
||||
|
||||
```
|
||||
|
||||
This enhanced guide provides much more detailed examples of how to implement complex level mechanics like file system navigation, process management, permissions, and network configuration. It should help anyone who wants to create new levels with sophisticated Linux-like features.
|
||||
```
|
||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) [year] [fullname]
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
98
README.md
Normal file
98
README.md
Normal file
@ -0,0 +1,98 @@
|
||||
# Terminal Escape
|
||||
|
||||

|
||||
Terminal Escape is an interactive text-based escape room game that challenges players to solve puzzles using Linux terminal commands and concepts.
|
||||
|
||||
## Introduction
|
||||
|
||||
In Terminal Escape, you'll navigate through a series of increasingly difficult levels, each requiring you to use your knowledge of Linux commands and problem-solving skills. Whether you're a Linux expert or a beginner, the game provides an engaging way to learn and practice terminal skills in a fun, gamified environment.
|
||||
|
||||
## Features
|
||||
|
||||
- Multiple challenging levels with increasing difficulty
|
||||
- Linux terminal simulation with common commands
|
||||
- Player profiles and save system
|
||||
- Achievement system to track your progress
|
||||
- Helpful hints when you get stuck
|
||||
- Progress map to visualize your journey
|
||||
- Leaderboard to compare your performance
|
||||
|
||||
## Installation
|
||||
|
||||
1. Make sure you have [Bun](https://bun.sh/) installed on your system
|
||||
2. Clone this repository
|
||||
3. Run `bun install` to install dependencies
|
||||
4. Run `bun run dev` to start the game
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Start the game with `bun run dev`
|
||||
2. Create a new profile or load an existing one
|
||||
3. Follow the in-game instructions to begin your first level
|
||||
4. Use Linux commands to solve puzzles and progress through levels
|
||||
|
||||
## How to Play
|
||||
|
||||
- Use Linux commands to interact with the game environment
|
||||
- Type `/help` at any time to see available commands
|
||||
- Use `/hint` if you get stuck on a level
|
||||
- Use `/save` to save your progress
|
||||
- Use `/menu` to return to the main menu
|
||||
|
||||
## Save System
|
||||
|
||||
The game automatically saves your progress as you complete levels. Each player has their own profile that stores:
|
||||
- Current level progress
|
||||
- Achievements unlocked
|
||||
- Game statistics
|
||||
|
||||
You can have multiple profiles for different players on the same computer.
|
||||
|
||||
## Achievements
|
||||
|
||||
Unlock achievements by completing specific challenges:
|
||||
- Completing levels
|
||||
- Using specific commands
|
||||
- Finding hidden secrets
|
||||
- And more!
|
||||
|
||||
Check your achievements from the main menu to track your progress.
|
||||
|
||||
## Creating New Levels
|
||||
|
||||
Terminal Escape is designed to be easily expandable with new levels. If you're interested in creating your own levels, check out the [LEVELS.md](LEVELS.md) guide in the repository.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Game won't start**: Make sure Bun is installed correctly and you've run `bun install`
|
||||
- **Can't save progress**: Check that your user has write permissions to the saves directory
|
||||
- **Commands not working**: Make sure you're using the correct syntax for the level
|
||||
|
||||
## Game Structure
|
||||
|
||||
The game is organized into several core components:
|
||||
|
||||
- **Core System**: Game state management, level system, achievements
|
||||
- **UI**: Terminal interface, visual effects, menus
|
||||
- **Levels**: Individual puzzle challenges
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Feel free to:
|
||||
|
||||
- Create new levels
|
||||
- Fix bugs
|
||||
- Improve the UI
|
||||
- Add new features
|
||||
|
||||
Please follow the existing code style and structure when making contributions.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- Inspired by Linux terminal escape rooms and CTF challenges
|
||||
- Built with TypeScript and Bun
|
||||
- Special thanks to all contributors
|
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 580 KiB |
@ -40,45 +40,51 @@ export function createNewGame(playerName: string): GameState {
|
||||
setCurrentGameState(gameState);
|
||||
|
||||
// Save the initial game state
|
||||
saveGame(playerName);
|
||||
saveGame();
|
||||
|
||||
return gameState;
|
||||
}
|
||||
|
||||
export async function saveGame(saveName?: string): Promise<boolean> {
|
||||
export async function saveGame(): Promise<{ success: boolean, message: string }> {
|
||||
if (!currentGameState) {
|
||||
console.error('No active game to save');
|
||||
return false;
|
||||
return {
|
||||
success: false,
|
||||
message: 'No active game to save'
|
||||
};
|
||||
}
|
||||
|
||||
// Update save time
|
||||
currentGameState.lastSaveTime = Date.now();
|
||||
|
||||
// Use player name as save name if not specified
|
||||
const fileName = saveName || currentGameState.playerName;
|
||||
// Always use player name as save name
|
||||
const fileName = currentGameState.playerName;
|
||||
|
||||
try {
|
||||
await fs.writeFile(
|
||||
getSavePath(fileName),
|
||||
JSON.stringify(currentGameState, null, 2)
|
||||
);
|
||||
console.log(`Game saved as ${fileName}`);
|
||||
return true;
|
||||
return {
|
||||
success: true,
|
||||
message: `Game saved for ${fileName}`
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Failed to save game:', error);
|
||||
return false;
|
||||
return {
|
||||
success: false,
|
||||
message: `Failed to save game: ${error}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadGame(saveName: string): Promise<boolean> {
|
||||
export async function loadGame(playerName: string): Promise<boolean> {
|
||||
try {
|
||||
const saveData = await fs.readFile(getSavePath(saveName), 'utf-8');
|
||||
const saveData = await fs.readFile(getSavePath(playerName), 'utf-8');
|
||||
currentGameState = JSON.parse(saveData) as GameState;
|
||||
|
||||
// Make sure the profile exists
|
||||
await createOrLoadProfile(currentGameState.playerName);
|
||||
|
||||
console.log(`Game loaded: ${saveName}`);
|
||||
console.log(`Game loaded for ${playerName}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to load game:', error);
|
||||
@ -86,9 +92,9 @@ export async function loadGame(saveName: string): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function autoSave(): Promise<boolean> {
|
||||
if (!currentGameState) return false;
|
||||
return saveGame(`${currentGameState.playerName}_autosave`);
|
||||
// Autosave now just calls regular save
|
||||
export async function autoSave(): Promise<{ success: boolean, message: string }> {
|
||||
return saveGame();
|
||||
}
|
||||
|
||||
async function createOrLoadProfile(playerName: string): Promise<void> {
|
||||
|
41
src/core/gameUI.ts
Normal file
41
src/core/gameUI.ts
Normal file
@ -0,0 +1,41 @@
|
||||
// Add a status message system
|
||||
let statusMessage = '';
|
||||
let statusMessageTimeout: NodeJS.Timeout | null = null;
|
||||
|
||||
// Function to set a temporary status message
|
||||
function setStatusMessage(message: string, duration = 3000): void {
|
||||
statusMessage = message;
|
||||
|
||||
// Clear any existing timeout
|
||||
if (statusMessageTimeout) {
|
||||
clearTimeout(statusMessageTimeout);
|
||||
}
|
||||
|
||||
// Set a timeout to clear the message
|
||||
statusMessageTimeout = setTimeout(() => {
|
||||
statusMessage = '';
|
||||
// Redraw the UI if needed
|
||||
renderPrompt();
|
||||
}, duration);
|
||||
}
|
||||
|
||||
// Function to render the command prompt with status message
|
||||
function renderPrompt(): void {
|
||||
// Clear the current line
|
||||
process.stdout.write('\r\x1b[K');
|
||||
|
||||
// If there's a status message, show it above the prompt
|
||||
if (statusMessage) {
|
||||
console.log(statusMessage);
|
||||
statusMessage = ''; // Clear it after showing
|
||||
}
|
||||
|
||||
// Show the prompt
|
||||
process.stdout.write('> ');
|
||||
}
|
||||
|
||||
// Update the auto-save function call
|
||||
const saveResult = await autoSave();
|
||||
if (saveResult.success) {
|
||||
setStatusMessage(saveResult.message);
|
||||
}
|
@ -92,7 +92,7 @@ async function loadGameMenu(): Promise<boolean> {
|
||||
console.log(theme.accent('=== LOAD GAME ==='));
|
||||
console.log('');
|
||||
|
||||
// Get list of save files
|
||||
// Get list of save files (just player names)
|
||||
const saveFiles = await listSaves();
|
||||
|
||||
if (saveFiles.length === 0) {
|
||||
@ -101,24 +101,24 @@ async function loadGameMenu(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('Available saved games:');
|
||||
console.log('Available players:');
|
||||
saveFiles.forEach((save, index) => {
|
||||
console.log(`${index + 1}. ${theme.accent(save)}`);
|
||||
});
|
||||
console.log('');
|
||||
|
||||
const choice = await promptInput('Select a saved game (or 0 to cancel): ');
|
||||
const choice = await promptInput('Select a player (or 0 to cancel): ');
|
||||
const choiceNum = parseInt(choice);
|
||||
|
||||
if (choiceNum === 0 || isNaN(choiceNum) || choiceNum > saveFiles.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const saveName = saveFiles[choiceNum - 1];
|
||||
const playerName = saveFiles[choiceNum - 1];
|
||||
|
||||
// Try to load the save
|
||||
await loadingAnimation('Loading game...', 1000);
|
||||
const success = await loadGame(saveName);
|
||||
const success = await loadGame(playerName);
|
||||
|
||||
if (success) {
|
||||
await successAnimation('Game loaded successfully!');
|
||||
|
@ -70,8 +70,12 @@ export async function renderGameUI(): Promise<void> {
|
||||
}
|
||||
|
||||
if (command === 'save') {
|
||||
await saveGame();
|
||||
await successAnimation('Game saved successfully!');
|
||||
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...');
|
||||
continue;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user