Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Inspired by text adventures and classic terminal interfaces
- Special thanks to all contributors and testers# Weary Adventurer Terminal
A retro-styled, interactive terminal-based adventure game that simulates a tech hazing ritual. This project features a choice-based narrative, character stats, inventory system, and a functional terminal interface with API commands.
Experience the Weary Adventurer Terminal: https://fuck-out.com
- 🎮 Text-based adventure game with multiple branching paths
- 💻 Authentic terminal look and feel with typing animations
- 🧙♂️ Character stats and inventory system
- 🔄 Multiple themes (Dark, Light, Hacker)
- 🌐 Built-in API commands to interact with external services
- 📊 Dynamic user interface with stats sidebar
- 🖱️ Both clickable and keyboard-based interaction
- 🧩 Code challenges and puzzles
- 📱 Built with HTML5 for modularity and future extensibility
- A modern web browser (Chrome, Firefox, Safari, Edge)
- Basic knowledge of HTML, CSS, and JavaScript if you want to customize
- Clone this repository:
git clone https://github.com/yourusername/chooseAdventure.git
cd chooseAdventure-
Open the project in your code editor.
-
Launch the game by opening
index.htmlin your web browser, or use a local server:
# Using Python
python -m http.server
# Using Node.js with http-server
npx http-serverThis project is designed to be easily customizable. Here's how to make it your own:
The entire story is contained in js/story.js. Each scene is defined as an object in the scenes property:
const story = {
scenes: {
start: {
text: [
"Your welcome text here...",
"Additional paragraphs..."
],
npcDialogue: [
"NPC dialogue lines..."
],
actions: [
{ type: "askName" }
],
nextScene: "introduction"
},
// Additional scenes...
}
};Scene Structure:
text: Array of story paragraphsnpcDialogue: Array of character dialogue lineschoices: Array of options for the player to choose fromactions: Special actions to execute (modify stats, add inventory, etc.)nextScene: The ID of the next scene to transition to
The visual themes are defined in css/style.css. To add a new theme:
- Add a new theme class:
body.theme-yourtheme {
background-color: #your-bg-color;
color: #your-text-color;
}
body.theme-yourtheme .terminal-window {
background-color: #your-terminal-bg;
/* ... additional styling ... */
}- Add the theme option to the
/themecommand injs/game.js:
case '/theme':
if (params[0] === 'yourtheme') {
document.body.className = 'theme-yourtheme';
this.terminal.writeStory("Theme switched to your theme.");
}
// ... other themes ...To add new terminal commands, modify the handleCommand and handleSlashCommand methods in js/game.js:
handleSlashCommand(command) {
const [mainCommand, ...params] = command.split(' ');
switch (mainCommand) {
case '/yourcommand':
// Your command logic here
this.terminal.writeStory("Your command output");
break;
// ... other commands ...
}
}To add new API integrations, extend the handleApiCommand method in js/game.js:
async handleApiCommand(params) {
switch (params[0]) {
case 'yourapi':
try {
this.terminal.writeStory("Fetching data...");
const response = await this.makeApiRequest('https://your-api-url.com');
const data = await response.json();
this.terminal.writeStory("YOUR API RESULTS");
this.terminal.writeStory("-----------------");
this.terminal.writeStory(data.yourProperty);
} catch (error) {
this.terminal.writeStory(`Error: ${error.message}`);
}
break;
// ... other API commands ...
}
}Edit the initial stats in the Game constructor in js/game.js:
constructor() {
// ...
this.playerStats = {
HEALTH: 100,
MANA: 20,
YOUR_STAT: 5,
// ... other stats ...
};
// ...
}Update the URLs in the slash commands:
case '/about':
this.terminal.writeStory("Opening about page...");
window.open('https://your-website.com/about', '_blank');
break;weary-adventurer-terminal/
├── index.html # Main HTML file
├── css/
│ └── style.css # Styles and themes
├── js/
│ ├── game.js # Main game logic and commands
│ ├── terminal.js # Terminal UI functionality
│ ├── story.js # Story scenes and branches
│ └── fallback.js # Error handling
└── README.md # This file
Handles game state, scene transitions, and command processing.
Manages the terminal UI, typing effects, and user input.
Contains all story content, scenes, and branching logic.
You can create custom mini-games by adding new action types:
- Add a new action type in
processActionmethod ingame.js:
case 'yourgame':
this.startYourGame();
break;- Create the game handling method:
startYourGame() {
this.terminal.writeStory("Your game instructions");
this.waitingForGameInput = true;
}
handleYourGameInput(input) {
// Process game input and determine outcome
}- Update
handleCommandto route to your game handler:
if (this.waitingForGameInput) {
this.handleYourGameInput(command);
return;
}To add new characters that appear in the online users list:
this.onlineUsers = [
"YourCharacter1",
"YourCharacter2",
// ... other users ...
];To add save/load functionality, you could implement localStorage:
// Save game
saveGame() {
const saveData = {
playerName: this.playerName,
currentScene: this.currentScene,
playerStats: this.playerStats,
inventory: this.inventory
};
localStorage.setItem('wearyAdventurerSave', JSON.stringify(saveData));
}
// Load game
loadGame() {
const saveData = JSON.parse(localStorage.getItem('wearyAdventurerSave'));
if (saveData) {
this.playerName = saveData.playerName;
this.currentScene = saveData.currentScene;
this.playerStats = saveData.playerStats;
this.inventory = saveData.inventory;
this.updateStats();
this.updateInventory();
this.renderScene(this.currentScene);
}
}- Original concept and development: @KitBaroness
- Font: VT323 by Peter Hull
- APIs used:
- Open-Meteo for weather data
- Advice Slip for random advice
- Official Joke API for jokes
- Cat Facts for cat facts
- CoinCap for cryptocurrency data
This project is licensed under the MIT License - see the LICENSE file for details.
This project is built with HTML5 and designed with modularity in mind to facilitate future extensions and integrations:
The modular architecture makes it easy to integrate WebAssembly modules. To extend with WASM:
-
Compile your Rust/C/C++ code to WebAssembly
-
Add the WASM module to your project:
// In a new file, e.g., js/wasm-module.js const wasmInstance = await WebAssembly.instantiateStreaming( fetch('path/to/your/module.wasm'), importObject ); export const wasmFunctions = wasmInstance.instance.exports;
-
Import and use in your game:
import { wasmFunctions } from './wasm-module.js'; // Use in your game logic const result = wasmFunctions.yourFunction(param1, param2);
To add JWT authentication for user accounts or saved games:
-
Create an authentication service API endpoint
-
Implement JWT handling:
// In a new file, e.g., js/auth.js export function login(username, password) { return fetch('your-auth-endpoint', { method: 'POST', body: JSON.stringify({ username, password }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { localStorage.setItem('token', data.token); return data.user; }); } export function getAuthenticatedUser() { const token = localStorage.getItem('token'); if (!token) return null; // Parse JWT payload (for demo purposes - in production use proper JWT library) const payload = JSON.parse(atob(token.split('.')[1])); return payload; }
-
Use in your game for authenticated API calls:
import { getAuthenticatedUser } from './auth.js'; async makeAuthenticatedApiRequest(url) { const token = localStorage.getItem('token'); const response = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } }); // ...rest of request handling }
Rust can be integrated in two main ways:
-
Via WebAssembly: For high-performance game logic, physics, or procedural generation
// Example Rust function to be compiled to WASM #[no_mangle] pub extern "C" fn calculate_game_logic(input: u32) -> u32 { // Your complex game logic here input * 2 }
-
Server-side: For persistent game state, multiplayer features, or authentication
// Example Rust server endpoint using Rocket #[get("/game-state/<user_id>")] fn get_game_state(user_id: String) -> Json<GameState> { // Retrieve and return the user's game state Json(database.get_user_game_state(user_id)) }
The HTML5 foundation makes all these integrations possible without significant architecture changes.
