class Game { constructor() { const generated = WorldGenerator.generate(); this.state = { world: generated.world, playerId: generated.playerId }; this.setupUI(); this.print("Welcome to the Text Adventure!"); this.describeCurrentLocation(); } setState(newState) { this.state = newState; } setupUI() { this.output = document.getElementById('output'); this.input = document.getElementById('input'); this.input.addEventListener('keypress', (e) => { if (e.key === 'Enter') { const command = this.input.value.toLowerCase(); this.input.value = ''; this.handleCommand(command); } }); } print(text) { const line = document.createElement('div'); line.textContent = text; this.output.appendChild(line); this.output.scrollTop = this.output.scrollHeight; } handleCommand(command) { this.print(`> ${command}`); if (command.match(/^(where am i|look around)$/)) { this.describeCurrentLocation(); } else if (command.startsWith('move ')) { const newState = this.handleMove(command.split(' ')[1]); if (newState) { this.setState(newState); this.describeCurrentLocation(); } } else if (command.startsWith('explore ') || command.startsWith('look at ')) { const target = command.replace(/^(explore|look at) /, ''); this.exploreTarget(target); } else if (command === 'phone') { this.checkMessages(); } else if (command === 'inventory') { this.checkInventory(); } else if (command.startsWith('get ') || command.startsWith('take ')) { const itemName = command.replace(/^(get|take) /, ''); const newState = this.collectItem(itemName); if (newState) { this.setState(newState); } } else { this.print("I don't understand that command."); } } getCurrentLocation() { const playerPos = World.getComponent(this.state.world, this.state.playerId, 'Position'); if (!playerPos) { console.error('Player position not found'); return null; } // Find the environment at the player's position const locationEntity = Array.from(this.state.world.entities.entries()).find(([entityId, _]) => { if (entityId === this.state.playerId) return false; const pos = World.getComponent(this.state.world, entityId, 'Position'); return pos && pos.x === playerPos.x && pos.y === playerPos.y; }); if (!locationEntity) return null; const [entityId, _] = locationEntity; const desc = World.getComponent(this.state.world, entityId, 'Description'); // Add items to the location description const items = this.getItemsAtLocation(playerPos); return { entityId, desc, items }; } getItemsAtLocation(pos) { return Array.from(this.state.world.entities.entries()) .filter(([entityId, _]) => { const itemPos = World.getComponent(this.state.world, entityId, 'Position'); const item = World.getComponent(this.state.world, entityId, 'Item'); return itemPos && item && itemPos.x === pos.x && itemPos.y === pos.y; }) .map(([entityId, _]) => ({ entityId, item: World.getComponent(this.state.world, entityId, 'Item') })); } describeCurrentLocation() { const location = this.getCurrentLocation(); if (location) { this.print(`You are in: ${location.desc.short}`); this.print(location.desc.long); if (location.items.length > 0) { this.print("\nYou can see:"); location.items.forEach(({ item }) => { this.print(`- ${item.name}`); }); } } } handleMove(direction) { const playerPos = World.getComponent(this.state.world, this.state.playerId, 'Position'); if (!playerPos) { console.error('Player position not found'); return null; } const moves = { 'north': { x: 0, y: -1 }, 'south': { x: 0, y: 1 }, 'east': { x: 1, y: 0 }, 'west': { x: -1, y: 0 } }; if (!moves[direction]) { this.print("Invalid direction. Use north, south, east, or west."); return null; } const newX = playerPos.x + moves[direction].x; const newY = playerPos.y + moves[direction].y; if (newX < 0 || newX >= 10 || newY < 0 || newY >= 10) { this.print("You can't go that way - you've reached the edge of the world."); return null; } const newWorld = World.addComponent( this.state.world, this.state.playerId, new Position(newX, newY) ); this.print(`You move ${direction}.`); return { ...this.state, world: newWorld }; } exploreTarget(target) { const location = this.getCurrentLocation(); if (location && location.desc.explorable[target]) { this.print(location.desc.explorable[target]); } else { this.print("There's nothing special about that."); } } checkMessages() { const messages = World.getComponent(this.state.world, this.state.playerId, 'Messages'); if (messages.messages.length === 0) { this.print("You have no messages."); } else { this.print("Your messages:"); messages.messages.forEach(msg => this.print(`- ${msg}`)); } } collectItem(itemName) { const playerPos = World.getComponent(this.state.world, this.state.playerId, 'Position'); const items = this.getItemsAtLocation(playerPos); const itemEntry = items.find(({ item }) => item.name.toLowerCase() === itemName.toLowerCase() ); if (!itemEntry) { this.print(`There is no ${itemName} here.`); return null; } if (!itemEntry.item.collectable) { this.print(`You can't take the ${itemName}.`); return null; } // Add to inventory const inventory = World.getComponent(this.state.world, this.state.playerId, 'Inventory'); const updatedInventory = new Inventory([...inventory.items, itemEntry.item]); // Remove from world and update inventory let newWorld = World.removeComponent(this.state.world, itemEntry.entityId, 'Position'); newWorld = World.addComponent(newWorld, this.state.playerId, updatedInventory); this.print(`You take the ${itemName}.`); return { ...this.state, world: newWorld }; } checkInventory() { const inventory = World.getComponent(this.state.world, this.state.playerId, 'Inventory'); if (inventory.items.length === 0) { this.print("Your inventory is empty."); } else { this.print("Your inventory contains:"); inventory.items.forEach(item => { this.print(`- ${item.name}`); }); } } } // Start the game when the page loads window.addEventListener('load', () => { window.game = new Game(); });