diff options
Diffstat (limited to 'html/text-world/js/game.js')
-rw-r--r-- | html/text-world/js/game.js | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/html/text-world/js/game.js b/html/text-world/js/game.js new file mode 100644 index 0000000..8f2d4d6 --- /dev/null +++ b/html/text-world/js/game.js @@ -0,0 +1,239 @@ +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(); +}); |