===============
LIBRARY RULES
===============
From library maintainers:
- Because the end goal is an Android APK built via Capacitor, all interactive elements must prioritize touch events over mouse clicks and scale responsively across different screen sizes.
- Core logic modules, especially complex ones like GeneticsSystem or QuestSystem, require accompanying Jest unit tests for any new features or modifications before they are merged into the main branch.
- Any newly introduced game mechanic must be cross-checked against previously patched vulnerabilities. Context 7 should flag code that might reopen old doors to quest bypasses, scaling exploits, or infinite interact loops.
- Keep the game's core logic cleanly separated from the interface. MainScene and specific minigame scenes must handle the world and mechanics, while UIScene should strictly manage the UI overlays and menus.
- Keep all source code organized as ES modules within the js/ directory (or its respective subfolders like systems/ and utils/). Avoid polluting the global scope and keep configurations like Config.js separate from runtime logic.
- Absolutely no hardcoded pixel coordinates for UI elements (e.g., x: 300, y: 500). All positioning must be calculated dynamically using scene.cameras.main.width, scene.cameras.main.centerX, or percentage-based offsets to ensure nothing gets cut off on diff
- All interactable UI elements must adhere to a strict 5% padding margin from the edges of the screen. This prevents buttons from being clipped by device bezels, camera cutouts, or system navigation bars.
- To prevent overlapping menus, only one UI modal or popup can be active at a time. The system must automatically close or hide the currently active menu before sliding a new one onto the screen.
- Every button must clearly explain its function. If an icon isn't universally obvious, it must be accompanied by a brief text label or feature a long-press tooltip system. Never assume the player knows how to launch a minigame.
- All UI colors, stroke widths, and font styles must be referenced directly from a centralized theme object in Config.js. Jules is strictly forbidden from introducing "magic hex codes" directly into scene logic, ensuring high contrast and preventing ugly co
- Every touchable element must provide immediate visual feedback. When a button is tapped, it must scale down slightly, change tint, or play a sound via the SoundSynthesizer. If an action fails, the UI must display a clear error toast, not fail silently.
- No backend system or minigame can be considered "complete" or merged into the main branch unless its corresponding UI entry point is fully implemented, visible, and functional within the UIScene.
- Never instantiate and destroy frequently used objects (like debris, floating text, or projectile sprites) on the fly. You must use Phaser's Group or Pool systems to recycle these objects, preventing massive garbage collection stutters during gameplay.
- Every scene must have a shutdown or destroy event listener that explicitly removes custom event listeners, stops active tweens, and clears large temporary textures from memory before transitioning to a new scene. No ghost processes left behind.
- Systems should not continuously "check" if a condition is met (polling) within the update loop. Instead, utilize Phaser's event emitter to trigger functions only when specific actions occur
- When adding a new feature always verify the complete circuit before moving on. If a system is built but the player can't interact with it on screen, it shouldn't be merged yet.
### Install Project Dependencies
Source: https://github.com/mnemonice/nadagotchi/blob/main/README.md
Installs all necessary Node.js dependencies for the Nadagotchi project using npm. This command should be run after cloning the repository and navigating into the project directory.
```bash
npm install
```
--------------------------------
### JSDoc Example for Function Documentation
Source: https://github.com/mnemonice/nadagotchi/blob/main/AGENTS.md
This snippet demonstrates the mandatory JSDoc format for documenting new functions, methods, and classes. It includes essential tags like @param for input parameters and @returns for the output, along with a brief description of the function's purpose. This ensures code clarity and maintainability.
```javascript
/**
* Calculates the offspring's stats based on parents and environment.
* @param {Genome} parentGenome - The source genome.
* @param {object} environment - The current world state.
* @returns {Stats} The calculated base stats.
*/
function calculateOffspringStats(parentGenome, environment) {
// Function implementation here
}
```
--------------------------------
### Run Development Server
Source: https://github.com/mnemonice/nadagotchi/blob/main/README.md
Starts a local development server with hot-reloading capabilities using Vite. This allows for rapid development and testing of the game. The game can typically be accessed at http://localhost:5173.
```bash
npm run dev
```
--------------------------------
### Manage Quests with QuestSystem
Source: https://context7.com/mnemonice/nadagotchi/llms.txt
The QuestSystem class handles all aspects of quest management, including starting quests, checking requirements, advancing stages, and generating daily quests. It relies on the Nadagotchi class for context. Quest progression is tracked by stage.
```javascript
import { Nadagotchi } from './js/Nadagotchi.js';
const pet = new Nadagotchi('Nurturer');
// Start a main quest
pet.questSystem.startQuest('masterwork_crafting');
console.log(pet.quests); // { 'masterwork_crafting': { stage: 1, name: '...' } }
// Get quest state
const quest = pet.questSystem.getQuest('masterwork_crafting');
console.log(quest.stage); // 1
// Get current stage definition
const stageDef = pet.questSystem.getStageDefinition('masterwork_crafting');
console.log(stageDef.description); // Stage description
console.log(stageDef.requirements); // { items: {...}, flags: [...] }
// Check if requirements are met
if (pet.questSystem.checkRequirements('masterwork_crafting')) {
pet.questSystem.advanceQuest('masterwork_crafting');
}
// Set quest flags (for internal quest logic)
pet.questSystem.setQuestFlag('masterwork_crafting', 'hasCraftedChair', true);
// Generate daily quest based on season/weather
const dailyQuest = pet.questSystem.generateDailyQuest('Spring', 'Sunny');
console.log(pet.dailyQuest);
// { id: '...', npc: 'Grizzled Scout', type: 'FETCH', item: 'Berries', qty: 3, text: '...', completed: false }
// Complete daily quest (when requirements met)
if (pet.questSystem.completeDailyQuest()) {
console.log('Daily quest completed!');
// Rewards: +20 career XP, +20 happiness, +1 NPC relationship
}
// Check if NPC has new quests available (for UI indicator)
const hasQuest = pet.questSystem.hasNewQuest('Master Artisan');
```
--------------------------------
### Simulate Pet Lifecycle (JavaScript)
Source: https://github.com/mnemonice/nadagotchi/blob/main/README.md
Demonstrates how to instantiate and interact with the core Nadagotchi simulation logic independently of the Phaser game engine. It shows creating a pet, simulating a game tick with world state, and performing actions.
```javascript
import { Nadagotchi } from './js/Nadagotchi.js';
// Create a new pet with the 'Intellectual' archetype
const pet = new Nadagotchi('Intellectual');
// Simulate a game tick
// Pass in the current world state (Weather, Time, etc.)
pet.live({
weather: 'Rainy',
time: 'Day',
season: 'Autumn'
});
// Perform an action
pet.handleAction('STUDY');
console.log(`Current Mood: ${pet.mood}`); // e.g., 'happy'
console.log(`Logic Skill: ${pet.skills.logic}`);
```
--------------------------------
### Instantiate and Access Nadagotchi Pet Properties (JavaScript)
Source: https://context7.com/mnemonice/nadagotchi/llms.txt
Demonstrates how to create a new Nadagotchi instance with an initial archetype and access its core properties like name, archetype, stats, skills, mood, generation, and age. It also shows how to load pet data from persistence.
```javascript
import { Nadagotchi } from './js/Nadagotchi.js';
// Create a new pet with an initial archetype
const pet = new Nadagotchi('Intellectual');
// Access core properties
console.log(pet.name); // "Nadagotchi"
console.log(pet.dominantArchetype); // "Intellectual"
console.log(pet.stats); // { hunger: 100, energy: 100, happiness: 70 }
console.log(pet.skills); // { communication: 1, resilience: 1, navigation: 0, empathy: 0, logic: 0, focus: 0, crafting: 0, research: 0 }
console.log(pet.mood); // "neutral"
console.log(pet.generation); // 1
console.log(pet.age); // 0
// Load from saved data
const savedData = persistence.loadPet();
if (savedData) {
const loadedPet = new Nadagotchi(null, savedData);
console.log(loadedPet.name); // Restored pet name
}
```
--------------------------------
### Track Seasons and Time with Calendar (JavaScript)
Source: https://context7.com/mnemonice/nadagotchi/llms.txt
The Calendar tracks in-game days, seasons, and years, providing the foundation for seasonal events and festivals. It starts at Day 1, Spring, Year 1 by default or can be loaded from saved data. The year consists of 112 in-game days, with each season lasting 28 days.
```javascript
import { Calendar } from './js/Calendar.js';
// Create new calendar or load from save
const calendar = new Calendar(); // Starts Day 1, Spring, Year 1
// Or load from saved data
const savedCalendar = persistence.loadCalendar();
const calendar = new Calendar(savedCalendar);
// Get current date
const date = calendar.getDate();
console.log(date); // { day: 1, season: 'Spring', year: 1 }
// Advance day (called when WorldClock triggers new day)
calendar.advanceDay();
console.log(calendar.day); // 2
console.log(calendar.season); // 'Spring'
// After 28 days, season advances
// Spring -> Summer -> Autumn -> Winter -> Spring (increments year)
// Season order and duration:
// Spring: Days 1-28
// Summer: Days 1-28
// Autumn: Days 1-28
// Winter: Days 1-28
// Total year: 112 in-game days
```
--------------------------------
### Build Project for Production
Source: https://github.com/mnemonice/nadagotchi/blob/main/README.md
Generates optimized static assets for deployment in the 'dist/' folder. This command is used to prepare the game for a production environment.
```bash
npm run build
```
--------------------------------
### Render Chart with Labels and Datasets
Source: https://github.com/mnemonice/nadagotchi/blob/main/psagame.html
Renders a chart using provided labels and datasets. It configures chart type, data, colors, and options including cutout percentage and legend position. Assumes Chart.js and color palette constants are available.
```javascript
new Chart("myChart", { type: "doughnut", data: { labels: pLabels(['Adventurer Support', 'Nurturer Support', 'Mischievous Support', 'Intellectual Support', 'Recluse Support'], 16), datasets: [{ label: 'Conceptual Feature Focus', data: [22, 20, 18, 23, 17], backgroundColor: [PALETTE_CHART.terracotta, PALETTE_CHART.oliveGreen, PALETTE_CHART.softBlue, PALETTE_CHART.lightBeige, PALETTE_CHART.warmGray], borderColor: '#FFFFFF', borderWidth: 2, hoverOffset: 4 }] }, options: { ...commonChartOptions, cutout: '60%', plugins: { ...commonChartOptions.plugins, legend: { ...commonChartOptions.plugins.legend, position: 'bottom', } }, } });
```
--------------------------------
### Initialize Doughnut Chart with Chart.js
Source: https://github.com/mnemonice/nadagotchi/blob/main/psagame.html
This code initializes a doughnut chart using Chart.js. It configures the chart type, data, and options, including responsive settings and custom tooltip callbacks.
```javascript
const archetypeFocusCtx = document.getElementById('archetypeFocusChart');
if (archetypeFocusCtx) {
new Chart(archetypeFocusCtx.getContext('2d'), {
type: 'doughnut',
data: {
labels: wrapLabels([
'The Adventurer',
'The Nurturer',
'The Mischievous',
'The Intellectual',
'The Recluse'
], 15), // Example usage of wrapLabels
datasets: [
{
data: [15, 25, 20, 30, 10],
backgroundColor: [
PALETTE_CHART.terracotta,
PALETTE_CHART.oliveGreen,
PALETTE_CHART.softBlue,
PALETTE_CHART.lightBeige,
PALETTE_CHART.warmGray
],
hoverOffset: 4
}
]
},
options: {
...commonChartOptions,
cutout: '70%', // Example of a chart-specific option
plugins: {
...commonChartOptions.plugins,
legend: {
...commonChartOptions.plugins.legend,
position: 'bottom'
}
}
}
});
}
```
--------------------------------
### Initialize Phaser Game with Scenes
Source: https://context7.com/mnemonice/nadagotchi/llms.txt
Configures and initializes the Phaser game instance. It sets up game dimensions, rendering mode, parent container, scaling, and registers all necessary game scenes for the Nadagotchi simulation.
```javascript
// js/game.js - Phaser game configuration
import Phaser from 'phaser';
import { PreloaderScene } from './PreloaderScene.js';
import { StartScene } from './StartScene.js';
import { MainScene } from './MainScene.js';
import { UIScene } from './UIScene.js';
import { BreedingScene } from './BreedingScene.js';
// ... other scene imports
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'game-container',
scale: {
mode: Phaser.Scale.RESIZE,
autoCenter: Phaser.Scale.CENTER_BOTH
},
scene: [
PreloaderScene, // Asset loading
StartScene, // Main menu
MainScene, // Core gameplay
UIScene, // Dashboard overlay
BreedingScene, // Legacy/retirement
ShowcaseScene, // Hall of fame
GhostScene, // Ghost pet viewing
// Career minigames:
LogicPuzzleScene,
ScoutMinigameScene,
HealerMinigameScene,
ArtisanMinigameScene,
ExpeditionScene,
DanceMinigameScene,
StudyMinigameScene
],
pixelArt: true,
dom: { createContainer: true }
};
const game = new Phaser.Game(config);
```
--------------------------------
### Expedition System Unit Tests
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
Contains unit tests for the ExpeditionSystem class, verifying path generation, node filtering by season, and choice resolution based on pet skills. It uses a mock random number generator for predictable test outcomes.
```javascript
const { ExpeditionSystem } = require('../js/systems/ExpeditionSystem.js');
const { SeededRandom } = require('../js/utils/SeededRandom.js');
describe('ExpeditionSystem', () => {
let system;
let mockRng;
beforeEach(() => {
mockRng = new SeededRandom(12345);
system = new ExpeditionSystem(mockRng);
});
test('should generate a path of specified length', () => {
const path = system.generatePath('Spring', 'Sunny', 3);
expect(path).toHaveLength(3);
expect(path[0]).toHaveProperty('description');
expect(path[0]).toHaveProperty('choices');
});
test('should filter nodes by season', () => {
// FROZEN_POND is Winter only
const pathSpring = system.generatePath('Spring', 'Sunny', 20);
const hasWinterNodeInSpring = pathSpring.some(n => n.id === 'FROZEN_POND');
expect(hasWinterNodeInSpring).toBe(false);
});
test('should resolve choice success based on skill', () => {
// Mock pet
const pet = {
skills: { navigation: 10 }, // High skill
};
const choice = {
skill: 'navigation',
difficulty: 5,
success: { text: "Win" },
failure: { text: "Lose" }
};
// RNG range(0, 10) -> let's say it returns 0. 0 + 10 >= 5. Success.
const result = system.resolveChoice(choice, pet);
expect(result.outcome).toBe('success');
});
test('should resolve choice failure based on skill', () => {
const pet = {
skills: { navigation: 0 },
};
const choice = {
skill: 'navigation',
difficulty: 20, // Impossible
success: { text: "Win" },
failure: { text: "Lose" }
};
const result = system.resolveChoice(choice, pet);
expect(result.outcome).toBe('failure');
});
});
```
--------------------------------
### Render Archetype Cards with JavaScript
Source: https://github.com/mnemonice/nadagotchi/blob/main/psagame.html
This script iterates through archetype data and dynamically creates HTML cards for each archetype. It appends these cards to a specified container and adds click event listeners for toggling an 'open' class.
```javascript
const archetypesData = [
{
name: "The Adventurer",
icon: "🧭",
description: "Craves exploration, novelty, challenges. Becomes bored with routine.",
happy: "Discovering new areas, mastering new mini-games.",
sad: "Stuck in a rut, repetitive tasks.",
angry: "Exploration attempts blocked, repeated failures."
},
{
name: "The Nurturer",
icon: "❤️",
description: "Enjoys caring for others, building relationships, fostering growth.",
happy: "Strong relationships, virtual pets/characters well-cared for.",
sad: "Perceived neglect (even accidental), weakening social bonds.",
angry: "Perceived injustice, mistreatment of a 'friend'."
},
{
name: "The Mischievous",
icon: "😈",
description: "Likes to bend rules, cause harmless trouble, seeks playful chaos.",
happy: "Successfully pulling off a prank, surprising the player.",
sad: "Strictly disciplined, unable to express playful side.",
angry: "Thwarted by rigid rules/authority."
},
{
name: "The Intellectual",
icon: "💡",
description: "Driven by curiosity, problem-solving, learning.",
happy: "Gaining new knowledge, solving puzzles.",
sad: "Simple, repetitive tasks, no new stimuli.",
angry: "Faced with illogical situations, blatant misinformation."
},
{
name: "The Recluse",
icon: "🏠",
description: "Prefers solitude, quiet activities, needs personal space.",
happy: "Left alone for reasonable periods, engaging in quiet activities.",
sad: "Constantly pestered, forced into crowded situations.",
angry: "Repeated violation of personal boundaries."
}
];
const archetypeContainer = document.getElementById('archetypeContainer');
archetypesData.forEach(arch => {
const card = document.createElement('div');
card.className = 'archetype-card p-4 border-[#D8A373]/50 rounded-lg hover:shadow-md transition-shadow cursor-pointer bg-white';
card.innerHTML = `
${arch.icon}${arch.name}
${arch.description}
Happy: ${arch.happy}
Sad: ${arch.sad}
Angry: ${arch.angry}
`;
card.addEventListener('click', () => {
card.classList.toggle('open');
});
archetypeContainer.appendChild(card);
});
```
--------------------------------
### Run Project Tests
Source: https://github.com/mnemonice/nadagotchi/blob/main/README.md
Executes the test suite for the Nadagotchi project using Jest. This command is used to ensure the core logic and systems are functioning as expected.
```bash
npm test
```
--------------------------------
### Handling Web Audio API Not Supported in JavaScript
Source: https://github.com/mnemonice/nadagotchi/blob/main/test_output.txt
This JavaScript code demonstrates how to handle cases where the Web Audio API is not supported or blocked. It includes a try-catch block to log a warning and set the audio context to null if an error occurs. This is often seen in preloader scenes.
```javascript
try {
this.setVolume(Config.SETTINGS.DEFAULT_VOLUME);
} catch (e) {
console.warn('Web Audio API not supported or blocked.', e);
this.ctx = null;
}
```
--------------------------------
### Simulate Nadagotchi's Daily Life Cycle (JavaScript)
Source: https://context7.com/mnemonice/nadagotchi/llms.txt
Illustrates the usage of the `live()` method to simulate the passage of time for a Nadagotchi. This method updates stats, mood, and age based on provided world state parameters like weather, time, season, and active events. It supports both explicit delta time and legacy object-based updates.
```javascript
import { Nadagotchi } from './js/Nadagotchi.js';
const pet = new Nadagotchi('Adventurer');
// Simulate a game tick with world state
const worldState = {
weather: 'Sunny', // Sunny, Cloudy, Rainy, Stormy
time: 'Day', // Night, Dawn, Day, Dusk
season: 'Spring', // Spring, Summer, Autumn, Winter
activeEvent: null // null or { name: 'SpringEquinoxFestival', description: '...' }
};
// Call with delta time (ms since last update) and world state
pet.live(16, worldState); // 16ms for 60fps
// Check state changes
console.log(pet.stats.hunger); // Decayed based on metabolism
console.log(pet.stats.energy); // Affected by weather/time
console.log(pet.mood); // Calculated from stats
console.log(pet.age); // Incremented slightly
// Legacy mode (object only, defaults dt)
pet.live({ weather: 'Rainy', time: 'Night', season: 'Autumn' });
// Mood calculation thresholds:
// - angry: hunger < 10
// - sad: hunger < 30 OR energy < 20
// - happy: hunger > 80 AND energy > 80
// - neutral: otherwise
```
--------------------------------
### Add ExpeditionScene to Game Initialization (JavaScript)
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
Integrates the new `ExpeditionScene` into the Phaser game configuration. This makes the scene available for launching during gameplay.
```javascript
--- js/game.js
+++ js/game.js
@@ -13,6 +13,7 @@
import { ScoutMinigameScene } from './ScoutMinigameScene.js';
import { HealerMinigameScene } from './HealerMinigameScene.js';
import { ArtisanMinigameScene } from './ArtisanMinigameScene.js';
+import { ExpeditionScene } from './ExpeditionScene.js';
/**
* Phaser Game Configuration.
@@ -38,7 +39,8 @@
LogicPuzzleScene,
ScoutMinigameScene,
HealerMinigameScene,
- ArtisanMinigameScene
+ ArtisanMinigameScene,
+ ExpeditionScene
]
};
```
--------------------------------
### Integrate Expedition Action Handling (JavaScript)
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
Adds event listeners and logic to the `MainScene` to handle the `EventKeys.EXPLORE` action, launching the `ExpeditionScene` if the Nadagotchi has sufficient energy. It also updates the notification message for low energy.
```javascript
--- js/MainScene.js
+++ js/MainScene.js
@@ -142,6 +142,7 @@
this.game.events.on(EventKeys.UI_ACTION, this.handleUIAction, this);
this.game.events.on(EventKeys.UPDATE_SETTINGS, this.handleUpdateSettings, this);
this.game.events.on(EventKeys.WORK_RESULT, this.handleWorkResult, this);
+ this.game.events.on(EventKeys.SCENE_COMPLETE, this.handleSceneComplete, this);
this.scale.on('resize', this.resize, this);
// --- Final Setup ---
@@ -268,14 +269,14 @@
this.nadagotchi.handleAction(actionType, data);
break;
case EventKeys.EXPLORE:
- if (this.nadagotchi.stats.energy >= Config.ACTIONS.EXPLORE.ENERGY_COST) {
+ if (this.nadagotchi.stats.energy >= Config.ACTIONS.EXPEDITION.ENERGY_COST) {
this.scene.pause();
this.scene.launch('ExpeditionScene', {
nadagotchi: this.nadagotchi,
weather: this.worldState.weather
});
} else {
- this.showNotification("Too Tired to Explore", '#FF0000');
+ this.showNotification("Too Tired for Expedition", '#FF0000');
}
break;
default:
@@ -291,6 +292,20 @@
this.gameSettings = { ...this.gameSettings, ...newSettings };
this.persistence.saveSettings(this.gameSettings);
}
+
+ /**
+ * Handles the results from a completed work mini-game.
+ * @param {object} data - The result data from the mini-game scene.
+ * @param {boolean} data.success - Whether the mini-game was completed successfully.
+ * @param {string} data.career - The career associated with the mini-game.
+ * @param {string} [data.craftedItem] - The item that was crafted, if any.
+ */
+ handleSceneComplete(data) {
+ if (data.type === 'EXPEDITION') {
+ // Expedition logic is handled within the scene/system, we just need to ensure UI update
+ this.game.events.emit(EventKeys.UPDATE_STATS, { nadagotchi: this.nadagotchi, settings: this.gameSettings });
+ }
+ }
/**
* Handles the results from a completed work mini-game.
```
--------------------------------
### Manage Inventory and Crafting with InventorySystem
Source: https://context7.com/mnemonice/nadagotchi/llms.txt
The InventorySystem class manages the pet's inventory, including adding, removing, and consuming items. It also handles crafting recipes, foraging for new items, and applying home decorations. Dependencies include the Nadagotchi class.
```javascript
import { Nadagotchi } from './js/Nadagotchi.js';
const pet = new Nadagotchi('Recluse');
// Add items to inventory
pet.inventorySystem.addItem('Sticks', 5);
pet.inventorySystem.addItem('Shiny Stone', 2);
console.log(pet.inventory); // { 'Sticks': 5, 'Shiny Stone': 2 }
// Remove items
pet.inventorySystem.removeItem('Sticks', 2);
console.log(pet.inventory['Sticks']); // 3
// Craft an item (requires discovered recipe and materials)
pet.inventorySystem.craftItem('Fancy Bookshelf');
// Requires: materials defined in recipe, energy, discovered recipe
// Consume items (applies effects)
const result = pet.inventorySystem.consumeItem('Berries');
// Berries: +10 hunger, +2 energy
// Logic-Boosting Snack: +10 energy, +5 happiness, +0.5 logic
// Hot Cocoa: +15 energy, +15 happiness
// Stamina-Up Tea: +30 energy
// Clear Water: +5 energy, +2 happiness
// Metabolism-Slowing Tonic: Permanently reduces metabolism gene
// Forage for items
pet.inventorySystem.forage();
// Changes location to 'Forest', costs 10 energy
// Can find: Berries, Sticks, Shiny Stone
// Season-specific: Frostbloom (Winter), Muse Flower (Autumn)
// 2% rare artifact drop: Ancient Tome, Heart Amulet, Genetic Scanner
// Discover recipes
pet.inventorySystem.discoverRecipe('Masterwork Chair');
console.log(pet.discoveredRecipes); // ['Fancy Bookshelf', 'Masterwork Chair']
// Apply home decor
const decorResult = pet.inventorySystem.applyHomeDecor('Blue Wallpaper', 'Entryway');
console.log(decorResult); // { success: true, assetKey: '...', type: 'WALLPAPER', message: '...' }
```
--------------------------------
### Create Game UI Elements with Phaser
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
This snippet demonstrates creating and adding various UI elements to a Phaser game scene, including background rectangles, text for step counters and descriptions, and interactive buttons for choices. It utilizes the `add.rectangle` and `add.text` methods for visual elements and a `ButtonFactory` for interactive components.
```javascript
const bg = this.add.rectangle(0, 0, w, h, 0x2e3b2e).setStrokeStyle(2, 0x88DDAA);
this.contentContainer.add(bg);
// Step Counter
const counter = this.add.text(0, -h/2 + 30, `Step ${this.currentIndex + 1} / ${this.path.length}`, {
fontFamily: 'VT323, fontSize: '24px', color: '#AAAAAA'
}).setOrigin(0.5);
this.contentContainer.add(counter);
// Description
const desc = this.add.text(0, -50, node.description, {
fontFamily: 'VT323', fontSize: '32px', color: '#FFFFFF', align: 'center', wordWrap: { width: w - 40 }
}).setOrigin(0.5);
this.contentContainer.add(desc);
// Choices
let yPos = 80;
node.choices.forEach(choice => {
let label = choice.text;
if (choice.skill) {
const chance = this.pet.skills[choice.skill] || 0;
// Optional: Show hint about chance? " (Logic: 3)"
label += ` [${choice.skill}: ${Math.floor(chance)}]`;
}
const btn = ButtonFactory.createButton(this, 0, yPos, label, () => {
this.handleChoice(choice);
}, { width: 400, height: 50, color: 0x446644, fontSize: '24px' });
this.contentContainer.add(btn);
yPos += 70;
});
```
--------------------------------
### Display Game Summary Screen with Phaser
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
This JavaScript code snippet illustrates the creation of a summary screen at the end of a game session. It displays completion messages, accumulated loot, and experience points, updating the pet's inventory and stats accordingly. It uses Phaser's `add.rectangle` and `add.text` for UI elements.
```javascript
showSummary() {
this.contentContainer.removeAll(true);
const w = 600;
const h = 400;
const bg = this.add.rectangle(0, 0, w, h, 0x2e3b2e).setStrokeStyle(2, 0xFFD700);
this.contentContainer.add(bg);
this.add.text(0, -h/2 + 40, "EXPEDITION COMPLETE", {
fontFamily: 'VT323', fontSize: '40px', color: '#FFD700'
}).setOrigin(0.5).setScrollFactor(0).setDepth(1).addToDisplayList(this.contentContainer); // Helper to add to container? No, just add
const title = this.add.text(0, -h/2 + 40, "EXPEDITION COMPLETE", {
fontFamily: 'VT323', fontSize: '40px', color: '#FFD700'
}).setOrigin(0.5);
this.contentContainer.add(title);
let summaryText = "You returned home.\n\nLoot Gained:\n";
const items = Object.entries(this.loot);
if (items.length === 0) summaryText += "- Nothing...\n";
items.forEach(([item, qty]) => {
summaryText += `- ${item} x${qty}\n`;
// Actually add to pet inventory
this.pet.inventorySystem.addItem(item, qty);
});
// XP? Assuming general skill gain or just mechanic fun.
// Let's add the XP to Navigation skill for now as a catch-all
if (this.xpGained > 0) {
```
--------------------------------
### Implement Tabbed Interface Functionality with JavaScript
Source: https://github.com/mnemonice/nadagotchi/blob/main/psagame.html
This script handles the functionality for a tabbed interface. It adds click event listeners to tab buttons to switch between different content sections, managing active states and visibility.
```javascript
const skillTabsContainer = document.getElementById('skillTabsContainer');
if (skillTabsContainer) {
const tabButtons = skillTabsContainer.querySelectorAll('.tab-button');
const tabContents = skillTabsContainer.querySelectorAll('.tab-content');
tabButtons.forEach(button => {
button.addEventListener('click', () => {
tabButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
tabContents.forEach(content => content.classList.add('hidden'));
const activeTabContent = document.getElementById(button.dataset.tab);
if (activeTabContent) {
activeTabContent.classList.remove('hidden');
}
});
});
}
```
--------------------------------
### Genetics System Performance Benchmark
Source: https://github.com/mnemonice/nadagotchi/blob/main/test_output.txt
This console log indicates the performance of the 'GeneticsSystem.breed' function. It was executed 50,000 times with 200 items, completing in 1210ms. This benchmark helps in understanding the efficiency of the breeding algorithm.
```javascript
console.log(`[Benchmark] GeneticsSystem.breed x 50000 with 200 items: 1210ms`);
```
--------------------------------
### Configure Chart.js Defaults and Helper Functions
Source: https://github.com/mnemonice/nadagotchi/blob/main/psagame.html
This code sets global defaults for Chart.js, including font colors, grid colors, and a color palette. It also includes helper functions for wrapping long labels and formatting tooltip titles.
```javascript
const FONT_COLOR_CHART = '#4A4A4A';
const GRID_COLOR_CHART = '#E0E0E0';
const PALETTE_CHART = {
terracotta: '#D8A373',
oliveGreen: '#A3B8A2',
softBlue: '#9DB4C0',
lightBeige: '#F3EADA',
warmGray: '#BFBDBB'
};
Chart.defaults.font.family = 'Inter';
Chart.defaults.color = FONT_COLOR_CHART;
Chart.defaults.borderColor = GRID_COLOR_CHART;
function wrapLabels(labels, maxLength) {
return labels.map(label => {
if (typeof label === 'string' && label.length > maxLength) {
const words = label.split(' ');
let currentLine = '';
const lines = [];
for (const word of words) {
if ((currentLine + word).length > maxLength && currentLine.length > 0) {
lines.push(currentLine.trim());
currentLine = '';
}
currentLine += word + ' ';
}
if (currentLine.trim().length > 0) {
lines.push(currentLine.trim());
}
return lines.length > 0 ? lines : [label]; // Ensure it returns an array even if one line
}
return label;
});
}
const tooltipTitleCallback = (tooltipItems) => {
const item = tooltipItems[0];
if (!item || !item.chart || !item.chart.data || !item.chart.data.labels || typeof item.dataIndex === 'undefined') {
return '';
}
let label = item.chart.data.labels[item.dataIndex];
if (Array.isArray(label)) {
return label.join(' ');
}
return label;
};
const commonChartOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
labels: {
color: FONT_COLOR_CHART,
font: { size: 11 },
boxWidth: 15,
padding: 15
}
},
tooltip: {
callbacks: {
title: tooltipTitleCallback
},
backgroundColor: 'rgba(74, 74, 74, 0.9)',
titleColor: '#FFFFFF',
bodyColor: '#FFFFFF',
padding: 10,
cornerRadius: 4
}
},
scales: {
x: {
display: false,
ticks: {
color: FONT_COLOR_CHART,
font: {size: 10}
},
grid: {
display: false
}
},
y: {
display: false,
ticks: {
color: FONT_COLOR_CHART,
font: {size: 10}
},
grid: {
display: false
}
}
}
};
```
--------------------------------
### Expedition Scene Logic
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
Handles the logic for the expedition scene, including updating pet skills, displaying summary text, and managing navigation buttons. It emits an event upon scene completion.
```javascript
this.pet.skills.navigation += (this.xpGained * 0.01);
summaryText += `\nNavigation Skill +${(this.xpGained * 0.01).toFixed(2)}`;
const text = this.add.text(0, 0, summaryText, {
fontFamily: 'VT323', fontSize: '24px', color: '#FFFFFF', align: 'center'
}).setOrigin(0.5);
this.contentContainer.add(text);
const homeBtn = ButtonFactory.createButton(this, 0, 150, "Return Home", () => {
this.game.events.emit(EventKeys.SCENE_COMPLETE, { type: 'EXPEDITION' });
this.scene.stop();
this.scene.resume('MainScene');
}, { width: 200, height: 50, color: 0x4CAF50 });
this.contentContainer.add(homeBtn);
```
--------------------------------
### ExpeditionScene: Manage Expedition Minigame UI (JavaScript)
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
The ExpeditionScene class handles the visual presentation and user interaction for the expedition minigame. It initializes the ExpeditionSystem, generates an expedition path, and displays nodes and choices to the player. It manages the game state, including the current node index and collected loot.
```javascript
import { ButtonFactory } from './ButtonFactory.js';
import { ExpeditionSystem } from './systems/ExpeditionSystem.js';
import { EventKeys } from './EventKeys.js';
/**
* @class ExpeditionScene
* @extends Phaser.Scene
* @classdesc
* Handles the visual presentation and interaction of the "Expedition" minigame.
* Displays nodes, handles choices, and shows results.
*/
export class ExpeditionScene extends Phaser.Scene {
constructor() {
super({ key: 'ExpeditionScene' });
}
init(data) {
this.pet = data.nadagotchi; // Reference to the pet
this.season = this.pet.currentSeason || 'Spring';
this.weather = data.weather || 'Sunny';
// Initialize System
this.system = new ExpeditionSystem(this.pet.rng);
// Generate Path
this.path = this.system.generatePath(this.season, this.weather, 3);
this.currentIndex = 0;
this.loot = {};
this.xpGained = 0;
}
create() {
const width = this.cameras.main.width;
const height = this.cameras.main.height;
// Background (Darker overlay)
this.add.rectangle(0, 0, width, height, 0x1a2b1a).setOrigin(0);
// Header
this.add.text(width / 2, 50, "WILDERNESS EXPEDITION", {
fontFamily: 'VT323, monospace', fontSize: '48px', color: '#88DDAA'
}).setOrigin(0.5);
// Content Area Container
this.contentContainer = this.add.container(width / 2, height / 2);
// Start Logic
if (this.path.length === 0) {
this.showSummary(); // Should not happen usually
} else {
this.showNode(this.path[this.currentIndex]);
}
}
showNode(node) {
this.contentContainer.removeAll(true);
const w = 600;
const h = 400;
// Panel Background
```
--------------------------------
### Display Game Result Screen with Phaser
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
This snippet shows how to render a result screen after a player makes a choice. It dynamically displays success or failure messages, detailed text, and applies rewards such as items, experience points, and stat changes to the pet. It also includes a 'Continue' button to proceed in the game.
```javascript
showResult(details, outcome) {
this.contentContainer.removeAll(true);
const w = 600;
const h = 400;
const bg = this.add.rectangle(0, 0, w, h, 0x2e3b2e).setStrokeStyle(2, outcome === 'success' ? 0x00FF00 : 0xFF0000);
this.contentContainer.add(bg);
const title = this.add.text(0, -h/2 + 40, outcome === 'success' ? "SUCCESS!" : "FAILURE...", {
fontFamily: 'VT323', fontSize: '40px', color: outcome === 'success' ? '#00FF00' : '#FF0000'
}).setOrigin(0.5);
this.contentContainer.add(title);
const text = this.add.text(0, -20, details.text, {
fontFamily: 'VT323', fontSize: '28px', color: '#FFFFFF', align: 'center', wordWrap: { width: w - 40 }
}).setOrigin(0.5);
this.contentContainer.add(text);
// Apply Rewards Logic Temporary (Accumulate)
if (details.items) {
for (const [item, qty] of Object.entries(details.items)) {
this.loot[item] = (this.loot[item] || 0) + qty;
}
}
if (details.xp) {
this.xpGained += details.xp;
}
// Direct Stat Application (Instant for now)
if (details.stats) {
for (const [stat, val] of Object.entries(details.stats)) {
if (stat === 'happiness') this.pet.stats.happiness += val;
if (stat === 'energy') this.pet.stats.energy += val;
if (stat === 'cleanliness') { /* No cleanliness stat yet, ignore */ }
}
// Clamp stats
this.pet.stats.happiness = Math.max(0, Math.min(this.pet.maxStats.happiness, this.pet.stats.happiness));
this.pet.stats.energy = Math.max(0, Math.min(this.pet.maxStats.energy, this.pet.stats.energy));
}
const nextBtn = ButtonFactory.createButton(this, 0, 100, "Continue", () => {
this.currentIndex++;
if (this.currentIndex < this.path.length) {
this.showNode(this.path[this.currentIndex]);
} else {
this.showSummary();
}
}, { width: 200, height: 50, color: 0xD8A373 });
this.contentContainer.add(nextBtn);
}
```
--------------------------------
### Update Expedition Configuration (JavaScript)
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
Modifies the configuration file to include the ENERGY_COST for the new Expedition action. This ensures the game correctly tracks energy expenditure for expeditions.
```javascript
--- js/Config.js
+++ js/Config.js
@@ -125,7 +125,8 @@
SKILL_GAIN: 0.2
},
EXPEDITION: {
- LENGTH: 3
+ LENGTH: 3,
+ ENERGY_COST: 15
},
INTERACT_NPC: {
ENERGY_COST: 5,
```
--------------------------------
### PersistenceManager: Save and Load Game State (JavaScript)
Source: https://context7.com/mnemonice/nadagotchi/llms.txt
Handles game state persistence to localStorage, including integrity checks and legacy migration. It provides methods to save and load various game data like pet information, calendar, journal, recipes, furniture, settings, achievements, and a hall of fame. It also includes functions to clear active pet data or all game data.
```javascript
import { PersistenceManager } from './js/PersistenceManager.js';
import { Nadagotchi } from './js/Nadagotchi.js';
const persistence = new PersistenceManager();
// Save pet data (non-blocking, scheduled during idle time)
const pet = new Nadagotchi('Adventurer');
persistence.savePet(pet);
// Load pet data (returns null if no save or corrupted)
const savedPet = persistence.loadPet();
if (savedPet) {
const loadedPet = new Nadagotchi(null, savedPet);
}
// Save/load other game data
persistence.saveCalendar({ day: 5, season: 'Summer', year: 1 });
const calendar = persistence.loadCalendar();
persistence.saveJournal([{ date: '...', text: '...' }]);
const journal = persistence.loadJournal();
persistence.saveRecipes(['Fancy Bookshelf', 'Hot Cocoa']);
const recipes = persistence.loadRecipes();
persistence.saveFurniture({ 'Entryway': [{ name: 'Plant', x: 100, y: 200 }] });
const furniture = persistence.loadFurniture();
persistence.saveSettings({ volume: 0.5, speed: 1.0 });
const settings = persistence.loadSettings();
persistence.saveAchievements({ unlocked: ['first_steps'], progress: {} });
const achievements = persistence.loadAchievements();
// Hall of Fame (retired pets)
persistence.saveToHallOfFame(retiredPetData);
const hallOfFame = persistence.loadHallOfFame();
// Clear data
persistence.clearActivePet(); // Clear current pet save
persistence.clearAllData(); // Clear all game data (except settings/hall of fame)
```
--------------------------------
### ExpeditionSystem: Generate Procedural Expedition Paths (JavaScript)
Source: https://github.com/mnemonice/nadagotchi/blob/main/handover/expedition_diffs.txt
The ExpeditionSystem class generates procedural expedition paths. It filters available nodes based on season and weather, then randomly selects nodes to form a path. The selection logic is currently a simple random choice, but can be extended for weighted or unique node selection. It requires a seeded random number generator.
```javascript
import { ExpeditionNodes } from '../ExpeditionDefinitions.js';
import { Config } from '../Config.js';
/**
* @fileoverview System for generating procedural expeditions.
* Selects nodes based on environment (season, weather) and randomness.
*/
export class ExpeditionSystem {
/**
* @param {object} rng - The seeded random number generator.
*/
constructor(rng) {
this.rng = rng;
}
/**
* Generates a path of encounter nodes for an expedition.
* @param {string} season - The current season (Spring, Summer, Autumn, Winter).
* @param {string} weather - The current weather (Sunny, Rainy, etc).
* @param {number} length - Number of nodes in the path (default 3).
* @returns {Array