Click here to Skip to main content
15,886,026 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
class LoaderSettings {
    constructor(param = {}) {
        this.loadTarget = param.loadTarget === undefined ? 'body' : param.loadTarget;
        this.gameDataURL = param.gameDataURL === undefined ? 'https://cdn.jsdelivr.net/gh/piriys/Monopoly.js@v1.0.1/gamedata.js' : param.gameDataURL;
        this.styleURL = param.styleURL === undefined ? 'https://cdn.jsdelivr.net/gh/piriys/Monopoly.js@v1.0.1/style.css' : param.styleURL;
    }
}
const Monopoly = {
    load: (param = {}) => {
        const loaderSettings = new LoaderSettings(param);
        console.clear();
        console.log(loaderSettings);

        // Load external files
        const styleDOM = document.createElement('link');
        styleDOM.setAttribute('rel', 'stylesheet');
        styleDOM.setAttribute('href', loaderSettings.styleURL);
        document.head.append(styleDOM);


        // TO DO: 
        // *Load game data here

        // Constants
        const settings = {
            goCollectAmount: 10,
            dieCount: 2,
            startingAmount: 500,
            movementStepDelay: 500,
            jailedTurn: 3,
            rentMultiplier: 2000, //For faster game
            taxMultiplier: 30 //For faster game
        };


        // Global
        let game;
        let board;
        let gameLoaderDOM;
        let gameDOM;

        document.addEventListener('DOMContentLoaded', () => {
            gameLoaderDOM = document.querySelector(loaderSettings.loadTarget);
            gameLoaderDOM.id = 'gameLoader';
            gameLoaderDOM.innerHTML = '';

            gameDOM = document.createElement('div');
            gameDOM.id = 'game';
            gameDOM.style.opacity = 0.0;

            const gameDataDOM = document.createElement('script');
            gameDataDOM.setAttribute('src', loaderSettings.gameDataURL);
            document.head.append(gameDataDOM);

            //Wait until data script is loaded
            gameDataDOM.addEventListener('load', () => {
                gameLoaderDOM.append(gameDOM);
                if (typeof (gameLoaderDOM) !== 'undefined' && gameLoaderDOM !== null) {
                    if (typeof (GameData) !== 'undefined' && GameData !== null) {
                        GameHelpers.setupGame();
                        GameHelpers.setupPlayers();
                        GameHelpers.setupEventListeners();
                        game.start();
                        game.currentPlayer.currentSpace.updateSpaceDetailDisplay();

                        window.setTimeout(() => {
                            GameHelpers.resizeBoard();
                            gameDOM.style.opacity = '';
                        }, 1000);
                    } else {
                        throw 'Game data not found.';
                    }
                } else {
                    throw 'Load target not found.';
                }
            });
        }, false);


        // Classes for helpers
        class Vector3D {
            constructor(x = 0, y = 0, z = 0) {
                this.x = x;
                this.y = y;
                this.z = z;
            }
        }

        class Option {
            constructor(name = 'accept', text = 'Ok') {
                this.name = name;
                this.text = text;
            }
        }

        // Helpers
        class MathHelpers {
            static randomInt(min, max) {
                return Math.floor(Math.random() * (max - min + 1)) + min;
            }
        }

        class UIHelpers {
            static menu(player, message, options = [new Option()], icon = '') {
                const buttons = new Map();
                return buttons;
            }
            static notice(player, message, icon) {
                board.inputDisplay.innerHTML = '';
                const header = document.createElement('h2');
                header.innerText = `${player.name}: ${message}`;
                board.inputDisplay.append(header);

                if (icon !== undefined) {
                    const dialogIcon = document.createElement('div');
                    dialogIcon.className = 'dialogIcon';
                    dialogIcon.innerText = icon;
                    board.inputDisplay.append(dialogIcon);
                }
            }
            static dialog(player, message, options = [new Option()], icon = '') {
                const buttons = new Map();

                if (icon === '') {
                    icon = player.icon;
                }

                board.inputDisplay.innerHTML = '';
                const header = document.createElement('h2');
                header.innerText = `${player.name}: ${message}`;
                board.inputDisplay.append(header);

                const dialogIcon = document.createElement('div');
                dialogIcon.className = 'dialogIcon';
                dialogIcon.innerText = icon;
                board.inputDisplay.append(dialogIcon);

                options.forEach((option) => {
                    const button = document.createElement('button');
                    button.innerText = option.text;
                    board.inputDisplay.append(button);
                    buttons.set(option.name, button);
                });

                return buttons;
            }
            static spaceDetail(space) {
                board.spaceDetailDisplay.innerHTML = '';

                const header = document.createElement('h2');
                if (space !== undefined) {
                    header.innerText = `${space.name}`;
                } else {
                    header.innerText = '[HOVER SPACE TO SEE DETAILS]';
                }
                board.spaceDetailDisplay.append(header);
            }
           
            static rollDice(player) {
                
                const message = `${player.name}'s Turn`;
                const button = this.dialog(player, message, [new Option('accept', 'Roll Dice')]).get('accept');

                return button;
            }

            static payTax(player, tax) {
                console.log(tax);
                const message = `Pay ${tax.name}`;
                const buttonText = `Pay \$${tax.amount}${settings.taxMultiplier !== 1 ? ` (x${settings.taxMultiplier})` : ''}`;
                const button = this.dialog(player, message, [new Option('accept', buttonText)], '💸').get('accept');

                return button;
            }

            static buyProperty(player, property) {
                const message = `Buy ${property.name}`;
                const options = [];
                options.push(new Option('accept', `Buy for \$${property.price}`));
                options.push(new Option('decline', 'Cancel'));

                const buttons = this.dialog(player, message, options);

                return buttons;
            }

            static upgradeProperty(player, property) {
                const message = `Upgrade ${property.name}`;
                const options = [];
                options.push(new Option('accept', `Upgrade for \$${property.currentUpgradeCost}`));
                options.push(new Option('decline', 'Cancel'));

                const buttons = this.dialog(player, message, options);

                return buttons;
            }

            static payRent(player, property) {
                const message = `Rent Due at ${property.name} to ${property.owner.name}`;
                const buttonText = `Pay \$${property.calculatedRent}${settings.rentMultiplier !== 1 ? ` ` : ''} to ${property.owner.name}`;
                const button = this.dialog(player, message, [new Option('accept', buttonText)]).get('accept');

                return button;
            }
        }


        // Game Assets
        class GameAsset {
            constructor(param) {
                this.transform = {
                    scale: 0,
                    rotate: new Vector3D(),
                    translate: new Vector3D(),
                };
            }
        }

        class Board extends GameAsset {
            constructor(param) {
                super(param);
                this.boardLayer;
                this.pieceLayer;
            }

            setup() {
                gameDOM.innerHTML = '';
                this.boardLayer = document.createElement('div');
                this.boardLayer.id = 'boardLayer';
                gameDOM.append(this.boardLayer);

                this.pieceLayer = document.createElement('div');
                this.pieceLayer.id = 'pieceLayer';
                gameDOM.append(this.pieceLayer);
            }
        }

        class MonopolyBoard extends Board {
            constructor(param) {
                super(param);

                this.statsDisplay;
                this.inputDisplay;
                this.spaceDetailDisplay;
            }
            setup() {
                super.setup();

                this.statsDisplay = document.createElement('div');
                this.statsDisplay.id = 'stats';
                this.statsDisplay.className = 'hud';
                this.boardLayer.append(this.statsDisplay);

                this.inputDisplay = document.createElement('div');
                this.inputDisplay.id = 'input';
                this.inputDisplay.className = 'hud';
                this.boardLayer.append(this.inputDisplay);

                this.spaceDetailDisplay = document.createElement('div');
                this.spaceDetailDisplay.id = 'spaceDetail';
                this.spaceDetailDisplay.className = 'hud';
                this.boardLayer.append(this.spaceDetailDisplay);

                this.settingsDisplay = document.createElement('div');
                this.settingsDisplay.id = 'settings';
                this.settingsDisplay.className = 'hud';

                const logo = document.createElement('h1');
                logo.className = 'logo';
                logo.innerText = 'MONOPOLY';
                this.settingsDisplay.append(logo);
                this.boardLayer.append(this.settingsDisplay);
            }
        }

        class Player extends GameAsset {
            constructor(param) {
                super(param);
                this.currentSpace = undefined;

                // Monopoly only
                this.name = param.name;
                this.icon = param.icon;
                this.money = param.money;
                this.state = 'playing';
                this.stateTurn = 0;

                this.playerStatsWrapper = document.createElement('div');
                this.playerStatsWrapper.className = 'playerStats';

                this.playerIconDOM = document.createElement('div');
                this.playerIconDOM.className = 'playerIcon';
                this.playerStatsWrapper.append(this.playerIconDOM);

                this.playerTextStatsWrapper = document.createElement('div');
                this.playerTextStatsWrapper.className = 'playerTextStats';
                this.playerStatsWrapper.append(this.playerTextStatsWrapper);

                this.playerNameDOM = document.createElement('h3');
                this.playerNameDOM.className = 'playerName';
                this.playerTextStatsWrapper.append(this.playerNameDOM);

                this.playerMoneyDOM = document.createElement('div');
                this.playerMoneyDOM.className = 'playerMoney';
                this.playerTextStatsWrapper.append(this.playerMoneyDOM);

                this.playerSpaceDOM = document.createElement('div');
                this.playerSpaceDOM.className = 'playerSpace';
                this.playerTextStatsWrapper.append(this.playerSpaceDOM);

                this.playerStateDOM = document.createElement('div');
                this.playerStateDOM.className = 'playerState';
                this.playerTextStatsWrapper.append(this.playerStateDOM);

                board.statsDisplay.append(this.playerStatsWrapper);

                this.playerPieceDOM = document.createElement('div');
                this.playerPieceDOM.className = 'piece';
                this.playerPieceDOM.innerText = this.icon;
                board.pieceLayer.append(this.playerPieceDOM);
            }

            updateDisplay() {
                this.updateStatsDisplay();
                this.updatePiece();
                this.currentSpace.updateSpaceDetailDisplay();
            }

            updateStatsDisplay() {
                this.playerIconDOM.innerText = `${this.icon}`;
                this.playerNameDOM.innerText = `Player: ${this.name}`;
                this.playerMoneyDOM.innerText = `Money: ${this.money}`;
                this.playerStateDOM.innerText = `[${this.state.toUpperCase()}${this.state === 'playing' || this.state === 'bankrupt' ? '' : ` (${this.stateTurn})`}]`;
                if (this.state === 'bankrupt') {
                    this.playerStatsWrapper.filter = 'grayscale(100%)';
                }
            }

            updatePiece() {
                this.playerPieceDOM.style.left = `${(this.currentSpace.column - 1) / 11 * 100}%`;
                this.playerPieceDOM.style.top = `${(this.currentSpace.row - 1) / 11 * 100}%`;
            }


            moveTo(nameId = 'start', resolveSpace = true, collectPassGo = false) {
                if (game.spaceMap.has(nameId)) {
                    UIHelpers.notice(this, 'Moving...');
                    this.currentSpace = game.spaceMap.get(nameId);

                    console.log(`${this.name} moves to [${this.currentSpace.name}]!`);

                    window.setTimeout(() => {
                        if (resolveSpace) {
                            this.currentSpace.resolve(this);
                        }

                        this.updateDisplay();
                    }, settings.movementStepDelay);
                } else {
                    throw 'nameId not found.';
                }
            }

            moveForward(steps = 1, resolveSpace = true, collectPassGo = true) {
                // Assume steps > 0
                UIHelpers.notice(this, 'Moving...');
                this.playerPieceDOM.style.animation = `bouncePlayerPiece ${(settings.movementStepDelay / 1000) / 2}s alternate infinite`;

                let i = 0;
                for (i = 0; i < steps; i++) {
                    window.setTimeout(() => {
                        this.currentSpace = game.spaceMap.get(this.currentSpace.nextId);
                        if (collectPassGo && this.currentSpace.nameId === 'start') {
                            console.log('collecting pass go');
                            this.deposit(settings.goCollectAmount);
                        }
                        this.updateDisplay();
                    }, settings.movementStepDelay * i);
                }

                window.setTimeout(() => {
                    console.log(`${this.name} landed on ${this.currentSpace.name}!`);
                    if (resolveSpace) {
                        this.currentSpace.resolve(this);
                    }
                    this.updateDisplay();
                    this.playerPieceDOM.style.animation = '';
                }, settings.movementStepDelay * i);
            }

            moveBackward(steps = 1, resolveSpace = true) {
                // Assume steps > 0
                UIHelpers.notice(this, 'Moving...');
                let i = 0;
                for (i = 0; i < steps; i++) {
                    window.setTimeout(() => {
                        this.currentSpace = game.spaceMap.get(this.currentSpace.prevId);
                        this.updateDisplay();
                    }, settings.movementStepDelay * i);
                }

                window.setTimeout(() => {
                    console.log(`${this.name} landed on ${this.currentSpace.name}!`);
                    if (resolveSpace) {
                        this.currentSpace.resolve(this);
                    }
                    this.updateDisplay();
                }, settings.movementStepDelay * i);
            }

            transfer(amount, player) {
                //Assume amount >= 0
                player.deposit(Math.min(amount, this.money));
                this.money -= amount;
                this.updateDisplay();
            }

            deposit(amount) {
                //Assume amount >= 0
                this.money += amount;
                this.updateDisplay();
            }

            withdraw(amount) {
                //Assume amount >= 0
                console.log(`withdrawing ${amount} from player[${this.name}]`);
                this.money -= amount;
                this.updateDisplay();
            }
        }

        class Space extends GameAsset {
            constructor(param) {
                super(param);
                this.name = param.name;

                this.nameId = param.nameId;
                this.nextId = param.nextId;
                this.prevId = param.prevId;

                this.type = param.type;
                this.column = param.column;
                this.row = param.row;
                this.icon = '';

                this.boardSpaceWrapper = document.createElement('div');
                this.boardSpaceWrapper.className = 'space';

                const spaceNumberDOM = document.createElement('div');
                spaceNumberDOM.className = 'spaceNumber';
                this.boardSpaceWrapper.append(spaceNumberDOM);

                this.spaceNameDOM = document.createElement('h3');
                this.spaceNameDOM.className = 'spaceName';
                this.boardSpaceWrapper.append(this.spaceNameDOM);

                this.boardSpaceWrapper.style['grid-column-start'] = this.column;
                this.boardSpaceWrapper.style['grid-row-start'] = this.row;
                this.boardSpaceWrapper.style.border = `1px solid yellowgreen`;

                board.boardLayer.append(this.boardSpaceWrapper);

                this.boardSpaceWrapper.addEventListener('mouseenter', () => {
                    this.updateSpaceDetailDisplay();
                });
                this.boardSpaceWrapper.addEventListener('mouseleave', () => {
                    game.currentPlayer.currentSpace.updateSpaceDetailDisplay();
                });
                this.updateSpaceDisplay();
            }

            updateSpaceDisplay() {
                this.spaceNameDOM.innerText = this.name;
            }

            updateSpaceDetailDisplay() {
                board.spaceDetailDisplay.innerHTML = '';

                const header = document.createElement('h2');
                header.innerText = `${this.name}`;
                board.spaceDetailDisplay.append(header);

                const iconContainer = document.createElement('div');
                iconContainer.className = 'detailIcon';
                iconContainer.style['border'] = `5px solid ${typeof (this.color) === 'undefined' ? 'white' : this.color}`;
                let detailIcon = '';

                switch (this.type.toLowerCase()) {
                    case 'start':
                        detailIcon = '🏁';
                        break;
                    case 'property':
                        detailIcon = '🏠';
                        break;
                    case 'tax':
                        detailIcon = '💸';
                        break;
                    case 'chest':
                        detailIcon = '🎁';
                        break;
                    case 'chance':
                        detailIcon = '';
                        break;
                    case 'jail':
                        detailIcon = '🚫';
                        break;
                    case 'gotojail':
                        detailIcon = '🚫';
                        break;
                    default:
                        detailIcon = '🅿';
                        break;
                }
                iconContainer.innerHTML = detailIcon;
                board.spaceDetailDisplay.append(iconContainer);
            }

            resolve() {
                console.log(`resolving action of ${this.name}`);
                game.finishTurn();
            }
        }

        class Tax extends Space {
            constructor(param) {
                super(param);
                this.amount = param.amount;
            }

            updateSpaceDetailDisplay() {
                super.updateSpaceDetailDisplay();
            }

            resolve(player) {
                const button = UIHelpers.payTax(player, this);
                button.addEventListener('click', () => {
                    player.withdraw(this.amount );
                    game.finishTurn();
                });
            }
        }
       
        class RandomAction extends Space {
            constructor(param) {
                super(param);
                this.deck = [];
                this.dialogMessage = '';
            }

            updateSpaceDetailDisplay() {
                super.updateSpaceDetailDisplay();
            }

            resolve(player) {
                console.log(`drawing card for ${player.name} from ${this.type}`);
                let message = '';
                switch (this.type.toLowerCase()) {
                    case 'chance':
                        this.deck = game.chanceCards;
                        message = 'Chance!';
                        this.icon = '';
                        break;
                    case 'chest':
                        this.deck = game.communityChestCards;
                        message = 'Community Chest';
                        this.icon = '🎁';
                        break;
                }

                const button = UIHelpers.dialog(player, message, [new Option('accept', 'Draw')], this.icon).get('accept');
                button.addEventListener('click', () => {
                    if (this.deck.length > 0) {
                        const randomCardIndex = MathHelpers.randomInt(0, this.deck.length - 1);
                        const card = this.deck[randomCardIndex];

                        let resolveButtonText = 'Ok';
                        let resolveFunction = () => {
                            game.finishTurn();
                        };

                        switch (card.type.toLowerCase()) {
                            // Change this so it looks up nameId instead 
                            case 'moveto':
                                const space = game.spaceMap.get(card.nameId);
                                resolveButtonText = `Move to ${space.name}`;
                                resolveFunction = () => {
                                    player.moveTo(card.nameId, card.resolveSpace, card.collectPassGo);
                                    game.finishTurn();
                                };
                                break;
                            case 'withdraw':
                                resolveButtonText = `Pay \$${card.amount}`;
                                resolveFunction = () => {
                                    player.withdraw(card.amount * settings.taxMultiplier);
                                    game.finishTurn();
                                };
                                break;
                            case 'deposit':
                                resolveButtonText = `Receive \$${card.amount}`;
                                resolveFunction = () => {
                                    player.deposit(card.amount);
                                    game.finishTurn();
                                };
                                break;
                        }

                        const resolveButton = UIHelpers.dialog(player, card.description, [new Option('accept', resolveButtonText)], card.icon).get('accept');
                        resolveButton.addEventListener('click', resolveFunction);
                    } else {
                        game.finishTurn();
                    }
                });
            }
        }

        class GoToJail extends Space {
            constructor(param) {
                super(param);
            }

            updateSpaceDetailDisplay() {
                super.updateSpaceDetailDisplay();
            }

            resolve(player) {
                const message = 'Move to Jail';
                const button = UIHelpers.dialog(player, message).get('accept');
                button.addEventListener('click', () => {
                    player.moveTo('jail');
                });
            }
        }

        class Jail extends Space {
            constructor(param) {
                super(param);
            }

            updateSpaceDetailDisplay() {
                super.updateSpaceDetailDisplay();
            }

            resolve(player) {
                console.log(`${player.name} is in jail`);
                player.state = 'jailed';
                player.stateTurn = settings.jailedTurn;
                const message = 'is in Jail';
                const button = UIHelpers.dialog(player, message).get('accept');
                button.addEventListener('click', () => {
                    game.finishTurn();
                });
            }
        }

        class Property extends Space {
            constructor(param) {
                super(param);
                this.color = param.color;
                this.price = param.price;
                this.rent = param.rent;
                this.upgradeCost = param.upgradeCost;
                this.upgradeIcons = ['🏠', '🏠🏠', '🏠🏠🏡', '🏠🏠🏡🏡', '🏠🏠🏡🏡🏨'];
                this.owner = undefined;
                this.upgradeLevel = 0;

                this.ownerDOM = document.createElement('span');
                this.ownerDOM.className = 'owner';
                this.boardSpaceWrapper.append(this.ownerDOM);

                this.upgradeDOM = document.createElement('span');
                this.upgradeDOM.className = 'upgrade';
                this.boardSpaceWrapper.append(this.upgradeDOM);

                this.priceDOM = document.createElement('span');
                this.priceDOM.className = 'price';
                this.boardSpaceWrapper.append(this.priceDOM);

                if (this.row === 1) {
                    this.boardSpaceWrapper.style['border-bottom'] = `5px solid ${this.color}`;
                }
                if (this.row === 11) {
                    this.boardSpaceWrapper.style['border-top'] = `5px solid ${this.color}`;
                }
                if (this.column === 1) {
                    this.boardSpaceWrapper.style['border-right'] = `5px solid ${this.color}`;
                }
                if (this.column === 11) {
                    this.boardSpaceWrapper.style['border-left'] = `5px solid ${this.color}`;
                }
                this.updatePropertyDisplay();
            }

            get calculatedRent() {
                return this.rent[this.upgradeLevel];
            }

            get currentUpgradeCost() {
                return this.upgradeCost[this.upgradeLevel];
            }

            updateDisplay() {
                this.updateSpaceDisplay();
                this.updatePropertyDisplay();
                this.updateSpaceDetailDisplay();
            }

            updatePropertyDisplay() {
                if (this.owner !== undefined) {
                    this.ownerDOM.innerText = `Owner: ${this.owner.icon}`;
                    this.priceDOM.innerText = `Rent: \$${this.calculatedRent}`;
                } else {
                    this.priceDOM.innerText = `Buy: \$${this.price}`;
                }
                if (this.upgradeLevel > 0) {
                    this.upgradeDOM.innerText = this.upgradeIcons[this.upgradeLevel - 1];
                }
            }

            updateSpaceDetailDisplay() {
                super.updateSpaceDetailDisplay();
                const detailsContainer = document.createElement('div');
                detailsContainer.className = 'details';
                detailsContainer.style.display = 'grid';
                detailsContainer.style['grid-template-columns'] = '5fr 2fr 2fr';

                ['Upgrade', 'Cost', 'Rent'].forEach((headerText) => {
                    const header = document.createElement('h3');
                    header.innerText = headerText;
                    detailsContainer.append(header);
                });

                for (let i = 0; i < this.rent.length; i++) {
                    const upgradeIconDOM = document.createElement('div');
                    const upgradeCostDOM = document.createElement('div');
                    const rentDOM = document.createElement('div');

                    if (i === 0) {
                        upgradeIconDOM.innerText = 'No Upgrade';
                        upgradeCostDOM.innerText = '-';

                    } else {
                        upgradeIconDOM.innerText = this.upgradeIcons[i - 1];
                        upgradeCostDOM.innerText = this.upgradeCost[i - 1];
                    }

                    rentDOM.innerHTML = this.rent[i];
                    detailsContainer.append(upgradeIconDOM);
                    detailsContainer.append(upgradeCostDOM);
                    detailsContainer.append(rentDOM);
                }

                board.spaceDetailDisplay.append(detailsContainer);
            }

            resolve(player) {
                
               
                // console.log('resolving action of property');
                if (typeof (this.owner) === 'undefined') {
                    console.log(`this property is not owned. prompt player to buy.`);
                    const buttons = UIHelpers.buyProperty(player, this);
                    buttons.get('accept').addEventListener('click', () => {
                        if (player.money >= this.price) {
                            player.withdraw(this.price);
                            this.owner = player;
                            console.log(`${this.name} is bought by ${player.name} for \$${this.price}`);
                            this.updateDisplay();
                        } else {
                            console.log(`insufficient funds!`);
                        }
                       
                        game.finishTurn();
                    });
                    buttons.get('decline').addEventListener('click', () => {
                        game.finishTurn();
                    });
                } else if (this.owner === player) {
                    console.log(`this property is owned by player. check if upgrade is available.`);
                    //check if player own all property in color group
                    let ownedAll = true;

                    for (const property of game.propertyGroups.get(this.color).value) {
                        if (property.owner !== player) {
                            ownedAll = false;
                            break;
                        }
                    }

                    //Utility property does not require ownership of all property in the group to upgrade
                    if ((this.color === 'black' || ownedAll) && this.upgradeLevel < this.rent.length - 1) {
                        const buttons = UIHelpers.upgradeProperty(player, this);
                        buttons.get('accept').addEventListener('click', () => {
                            if (player.money >= this.currentUpgradeCost) {
                                player.withdraw(this.currentUpgradeCost);
                                console.log(`${this.name} is upgraded by ${player.name} for \$${this.currentUpgradeCost}`);
                                this.upgradeLevel++;
                                this.updateDisplay();
                            } else {
                                console.log(`insufficient funds!`);
                            }
                            game.finishTurn();
                        });
                        buttons.get('decline').addEventListener('click', () => {
                            game.finishTurn();
                        });
                    } else {
                        console.log(`own all property in this color group to unlock upgrade.`);
                        game.finishTurn();
                    }
                } else {
                    console.log(`this property is owned by another player. transfer ${this.calculatedRent} to ${this.owner.name}`);
                    const button = UIHelpers.payRent(player, this);
                    button.addEventListener('click', () => {
                        player.transfer(this.calculatedRent, this.owner);
                        game.finishTurn();
                    });
                }
            }
        }

        class Game {
            constructor() {
                this.turnCount = 0;
                this.players = [];
                this.currentPlayerIndex = 0;

                this.spaceMap = new Map();
                this.startSpace = undefined;

                // Monopoly only
                this.propertyGroups = new Map();
                this.chanceCards = [];
                this.communityChestCards = [];
            }

            setup() {
                this.turnCount = 0;
                this.players = [];
                this.currentPlayerIndex = 0;

                this.spaceMap = new Map();

                this.chanceCards = [];
                this.communityChestCards = [];
            }

            addPlayer(param) {
                const newPlayer = new Player(param);
                this.players.push(newPlayer);
                newPlayer.moveTo('start');
                newPlayer.updateDisplay();
            }

            addSpace(param) {
                let newSpace;
                switch (param.type.toLowerCase()) {
                    case 'property':
                        newSpace = new Property(param);
                        if (!this.propertyGroups.has(newSpace.color)) {
                            this.propertyGroups.set(newSpace.color, { value: [] });
                        }
                        this.propertyGroups.get(newSpace.color).value.push(newSpace);
                        break;
                    case 'jail':
                        newSpace = new Jail(param);
                        break;
                    case 'gotojail':
                        newSpace = new GoToJail(param);
                        break;
                    case 'chance':
                        newSpace = new RandomAction(param);
                        break;
                    case 'chest':
                        newSpace = new RandomAction(param);
                        break;
                    case 'tax':
                        newSpace = new Tax(param);
                        break;
                    default:
                        newSpace = new Space(param);
                }
                this.spaceMap.set(newSpace.nameId, newSpace);
            }


            start() {
                this.play();
            }

            play() {
               
                  
                this.currentPlayer = this.players[this.currentPlayerIndex];
                const player = this.currentPlayer;
                
                if (player.state !== 'bankrupt') {
                    player.currentSpace.updateSpaceDetailDisplay();
                    if (player.state === 'playing') {
                        const button = UIHelpers.rollDice(player);
                        button.addEventListener('click', () => {
                            this.rollDice();

                        });
                    } else if (player.state === 'jailed') {
                        const message = player.stateTurn > 1 ? `${player.stateTurn} Turn${player.stateTurn > 1 ? 's' : ''} Remaining in Jail` : 'Last Turn in Jail';
                        const buttonText = player.stateTurn > 1 ? 'Skip Turn' : 'Get Out';
                        const button = UIHelpers.dialog(player, message, [new Option('accept', buttonText)]).get('accept');
                        
                        button.addEventListener('click', () => {
                            player.stateTurn--;
                            if (player.stateTurn === 0) {
                                player.state = 'playing';
                            }
                            

                            player.updateDisplay();
                            this.finishTurn();
                        });
                    }
                } else {
                    this.nextTurn();
                }
            }
            
           
            rollDice(count = settings.dieCount) {
               
               
                const player = this.players[this.currentPlayerIndex];
                const dieFaces = ['', '', '', '', '', ''];
                let totalRoll = 0;
                let icon = '';

                console.log(`roll dice, money: ${player.money}`);

                for (let i = 0; i < count; i++) {
                    const roll = MathHelpers.randomInt(1, 6);
                    console.log(`${player.name} rolls the dice! ${roll}!`);
                    totalRoll += roll;
                    icon += dieFaces[roll - 1];
                }

                const message = `Rolled ${totalRoll}`;
                const button = UIHelpers.dialog(player, message, [new Option('accept', 'Move')], icon).get('accept');
                button.addEventListener('click', () => {
                    player.moveForward(totalRoll);
                });
            }
              
           
            finishTurn() {
                const player = this.players[this.currentPlayerIndex];
                //Check if player is bankrupt
                if (player.money < 0) {
                    player.state = 'bankrupt';
                    player.playerStatsWrapper.style.filter = 'grayscale(100%)';
                    player.playerPieceDOM.style.filter = 'grayscale(100%)';
                    player.updateDisplay();
                    const message = 'GAME OVER';
                    const button = UIHelpers.dialog(player, message, [new Option('accept', 'Ok')]).get('accept');
                    button.addEventListener('click', () => {
                        this.nextTurn();
                    });
                } else {
                    this.nextTurn();
                }
            }

            nextTurn() {
                console.log(`turn ended for ${this.currentPlayer.name}`);
                console.log(`----------------`);

                const activePlayerCount = game.players.reduce((count, current) => count + ((current.state !== 'bankrupt') ? 1 : 0), 0);
                if (activePlayerCount > 1) {
                    this.currentPlayerIndex++;
                    this.currentPlayer = this.players[this.currentPlayerIndex];
                    if (this.currentPlayerIndex >= this.players.length) {
                        this.currentPlayerIndex = 0;
                    }

                    this.turnCount++;
                    this.play();
                } else {
                    this.end();
                }
            }

            end() {
                const player = game.players.find((current) => current.state !== 'bankrupt');
                const message = `${player.name} wins!`;
                const button = UIHelpers.dialog(player, message, [new Option('accept', 'Reset Game')], `🏆${player.icon}`).get('accept');

                button.addEventListener('click', () => {
                    GameHelpers.setupGame();
                    GameHelpers.setupPlayers();
                    GameHelpers.setupEventListeners();
                    game.start();
                    game.currentPlayer.currentSpace.updateSpaceDetailDisplay();
                    window.setTimeout(1000, () => {
                        GameHelpers.resizeBoard();
                    });
                });
            }
        }

        class GameHelpers {
            static setupGame() {
                board = new MonopolyBoard();
                board.setup();
                game = new Game();
                game.setup();

                GameData.spaces().forEach((space) => game.addSpace(space));
                game.startSpace = game.spaceMap.get('start');
                game.chanceCards = GameData.chanceCards();
                game.communityChestCards = GameData.communityChestCards();
            }
            static setupPlayers() {
                game.addPlayer({ name: 'P1', money: 2000, icon: '🚗' });
                game.addPlayer({ name: 'P2', money: 2000, icon: '🥾' });
                game.addPlayer({ name: 'P3', money: 2000, icon: '🐕' });
                game.addPlayer({ name: 'P4', money: 2000, icon: '🐈' });
            }
            static setupEventListeners() {
                window.removeEventListener('resize', this.resizeBoard);
                window.addEventListener('resize', this.resizeBoard);
            }
            static resizeBoard() {
                const windowWidth = window.innerWidth;
                const windowHeight = window.innerHeight;
                // Get width and height of board then set transform scale
                const boardWidth = board.boardLayer.offsetWidth;
                const boardHeight = board.boardLayer.offsetHeight;
                board.transform.scale = Math.min(
                    windowWidth / boardWidth,
                    windowHeight / boardHeight
                ) * 0.99;
                gameDOM.style['transform-origin'] = `${boardHeight / 2}px ${boardWidth / 2}px`;

                const rotate = `rotateX(${board.transform.rotate.x}deg) rotateY(${board.transform.rotate.y}deg) rotateZ(${board.transform.rotate.z}deg)`;
                const scale = `scale(${board.transform.scale})`;
                const translate = `translateX(${board.transform.translate.x}px) translateY(${board.transform.translate.y}px) translateZ(${board.transform.translate.z}px)`;
                gameDOM.style.transform = `${rotate} ${scale} ${translate}`;
                return board.transform;
            }
        }
    }
}


What I have tried:

class Question {
  constructor(question, options, correctAnswer) {
    this.question = question;
    this.options = options;
    this.correctAnswer = correctAnswer;
  }

  ask(player) {
    const button = UIHelpers.createButton(player, 'Ask question', () => {
      // Show the question to the player
      const userAnswer = prompt(`${this.question}\n\n${this.options.join('\n')}`);

      // Check if the player's answer is correct
      if (userAnswer === this.correctAnswer) {
        // Increase the player's money if the answer is correct
        player.money += 100;
        console.log("Correct! Your money has increased by 100.");
      } else {
        // Decrease the player's money if the answer is wrong
        player.money -= 200;
        console.log("Incorrect! Your money has decreased by 200.");
      }
    });
  }
}

const question = new Question("What is the capital of France?", ["Paris", "London", "New York"], "Paris");
question.ask(player);

```
I didn't know where to put the method and where I should call it. This is not my code I found this repository on github.
The question must be shown after the player roll the dice and move their pice. Thanks
Posted
Updated 8-Jan-23 2:54am
Comments
Richard MacCutchan 8-Jan-23 9:06am    
The code is for a Monopoly game, whereas all you want is a simple Q&A.

1 solution

The first thing to do is to learn that grabbing random code off the internet and assuming that it will do hat you want in a way that you want, and that you can modify it easily is probably doomed to failure.

If you want to use code, you have to learn how it works in order to understand how to change it in any realistic way - and so would we in order to tell you what alterations to make. And nobody is going to want to invest that much time to do your assignment for you - particularly when the starting point is such low quality student-grade code, and we have no idea when you might want this change to occur.

So either throw that lot away, and try writing your own code, or sit down and learn how it works before you even think of making change.
 
Share this answer
 
Comments
Mahmoud Baderaldin 8-Jan-23 9:26am    
I was in rush for the project and I didn't have much time to start a new one. So try not to gudge what you don't know. And I know nothing in JavaScript(I am JAVA student) but I was able to understand 80% of this code, I just don't know what to write and WHERE to write my codes. For a good JavaScript developer it would be an easy job and not time consuming as u said.
OriginalGriff 8-Jan-23 10:00am    
So you procrastinated and now the deadline is looming so you want someone else to put in the work and pull your nuts out of the fire?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900