class Game { constructor(containerId, gridSize = { width: 25, height: 25 }) { this.container = document.getElementById(containerId); this.grid = this.createGrid(gridSize.width, gridSize.height); this.currentTime = 0; this.player = new Player(this); this.isDay = true; this.cycleDuration = 10000; this.startDayCycle(); this.render(); } createGrid(width, height) { let grid = Array.from({ length: height }, () => Array.from({ length: width }, () => '.' )); grid = this.placeObstacles(grid, 'T', Math.floor(width * height * 0.05)); // 10% trees grid = this.placeObstacles(grid, 'S', Math.floor(width * height * 0.02)); // 5% stones return grid; } placeObstacles(grid, obstacle, count) { const width = grid[0].length; const height = grid.length; while (count > 0) { const x = Math.floor(Math.random() * width); const y = Math.floor(Math.random() * height); if (grid[y][x] === '.') { grid[y][x] = obstacle; count--; } } return grid; } render() { const darkness = this.calculateDarkness(); this.container.style.backgroundColor = `rgba(0, 0, 0, ${darkness})`; this.container.textContent = this.grid.map(row => row.join(' ')).join('\n'); } calculateDarkness() { const dayPercentage = Math.abs(this.currentTime % (2 * this.cycleDuration) - this.cycleDuration) / this.cycleDuration; if (dayPercentage == 0.6) { this.isDay = false; showNotification('Night is fast approaching...'); } else if (dayPercentage == 0.2) { this.isDay = true; showNotification('The sunlight breaks through, day has arrived'); } return 1 - Math.abs(dayPercentage - 0.5) * 2; } startDayCycle() { setInterval(() => { this.currentTime = (this.currentTime + 100) % (2 * this.cycleDuration); this.render(); }, this.cycleDuration); } } class Player { constructor(game) { this.game = game; this.x = Math.floor(Math.random() * this.game.grid[0].length); this.y = Math.floor(Math.random() * this.game.grid.length); this.sprite = '@'; this.game.grid[this.y][this.x] = this.sprite; } movePlayer(x, y) { const newX = this.x + x; const newY = this.y + y; if (this.isValidPosition(newX, newY)) { this.game.grid[this.y][this.x] = '.'; this.x = newX; this.y = newY; this.game.grid[this.y][this.x] = this.sprite; this.game.render(); } } isValidPosition(x, y) { return x >= 0 && x < this.game.grid[0].length && y >= 0 && y < this.game.grid.length && this.game.grid[y][x] === '.'; } } window.addEventListener('keydown', (event) => handleKeyPress(event)); function handleKeyPress(event) { switch (event.key) { case 'ArrowLeft': game.player.movePlayer(-1, 0); break; case 'ArrowRight': game.player.movePlayer(1, 0); break; case 'ArrowUp': game.player.movePlayer(0, -1); break; case 'ArrowDown': game.player.movePlayer(0, 1); break; default: break; } } const game = new Game('game-container'); game.render(); function showNotification(message) { const notifbar = document.getElementById('notifications-container'); notifbar.textContent = message; setTimeout(() => { notifbar.textContent = ''; }, 5000) }

This is the new code

class Grid {
    constructor(width, height) {
        this.width = width;
        this.height = height;
        this.cells = Array.from({ length: height }, () => Array.from({ length: width }, () => '.'));
    }

    placeObstacles(obstacle, count) {
        while (count > 0) {
            const x = Math.floor(Math.random() * this.width);
            const y = Math.floor(Math.random() * this.height);

            if (this.cells[y][x] === '.') {
                this.cells[y][x] = obstacle;
                count--;
            }
        }
    }

    isValidPosition(x, y) {
        return x >= 0 && x < this.width && y >= 0 && y < this.height && this.cells[y][x] === '.';
    }

    updateCell(x, y, value) {
        this.cells[y][x] = value;
    }

    toString() {
        return this.cells.map(row => row.join('  ')).join('\n');
    }
}

class Game {
    constructor(containerId, gridSize) {
        this.container = document.getElementById(containerId);

        this.grid = new Grid(gridSize.width, gridSize.height);
        this.player = new Player(this, gridSize.width / 2, gridSize.height / 2);

        this.dayNightCycle = new DayNightCycle();
        this.setupEventListeners();
        this.uiManager = new UIManager();
        this.dayNightCycle = new DayNightCycle(this.uiManager);

        this.grid.placeObstacles('T', Math.floor(this.grid.width * this.grid.height * 0.05));
        this.grid.placeObstacles('S', Math.floor(this.grid.width * this.grid.height * 0.02));

        this.render();
    }

    // … existing methods regarding rendering …

    setupEventListeners() {
        window.addEventListener('keydown', event => this.handleKeyPress(event));
    }

    handleKeyPress(event) {
        this.player.inputComponent.handleInput(event);
    }
}

class Player {
    constructor(game, initialX, initialY) {
        this.game = game;
        this.x = initialX;
        this.y = initialY;
        this.sprite = '@';
        this.inputComponent = new InputComponent(this);
        this.inventory = { trees: 0, stones: 0 };
        this.game.grid.updateCell(this.x, this.y, this.sprite);
        this.inputComponent = new InputComponent(this);
    }

    move(x, y) {
        if (this.game.grid.isValidPosition(this.x + x, this.y + y)) {
            this.game.grid.updateCell(this.x, this.y, '.');
            this.x += x;
            this.y += y;
            this.game.grid.updateCell(this.x, this.y, this.sprite);
            this.game.render();
        }
    }

    punch() {
        const cell = this.game.grid.cells[this.y][this.x];
        if (cell === 'T') {
            this.inventory.trees++;
            this.game.uiManager.updateInventory('trees', this.inventory.trees);
        } else if (cell === 'S') {
            this.inventory.stones++;
            this.game.uiManager.updateInventory('stones', this.inventory.stones);
        }
        this.game.render();
    }
}

class InputComponent {
    constructor(player) {
        this.player = player;
        this.commands = {
            'ArrowLeft': () => this.player.move(-1, 0),
            'ArrowRight': () => this.player.move(1, 0),
            'ArrowUp': () => this.player.move(0, -1),
            'ArrowDown': () => this.player.move(0, 1),
            ' ': () => this.player.punch()
        };
    }

    handleInput(event) {
        const command = this.commands[event.key];
        if (command) {
            command();
        }
    }
}

class DayNightCycle {
    constructor(uiManager) {
        this.isDay = true;
        this.time = 0;
        this.cycleDuration = 10000;
        this.uiManager = uiManager;
        this.startCycle();
    }

    startCycle() {
        setInterval(() => {
            this.time = (this.time + 100) % (2 * this.cycleDuration);
            this.checkCycle();
        }, this.cycleDuration);
    }

    checkCycle() {
        const dayPercentage = Math.abs(this.time % (2 * this.cycleDuration) - this.cycleDuration) / this.cycleDuration;

        if (dayPercentage === 0.6 && this.isDay) {
            this.isDay = false;
            this.uiManager.showNotification('Night is fast approaching…');
        } else if (dayPercentage === 0.2 && !this.isDay) {
            this.isDay = true;
            this.uiManager.showNotification('The sunlight breaks through, day has arrived');
        }
    }
}

class UIManager {
    constructor() {
        this.notifbar = document.getElementById('notifications-container');
    }

    showNotification(message) {
        this.notifbar.textContent = message;
        setTimeout(() => this.notifbar.textContent = '', 5000);
    }

    updateInventory() {
        // TODO: kjhfs
    }
}

const game = new Game('game-container', { width: 25, height: 25 });

Transfer the rendering methods from the old code into the new code