Package monopoly.model.game

Source Code of monopoly.model.game.GameModel

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package monopoly.model.game;

import external.HTMLColors;
import java.awt.Color;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import monopoly.model.events.GameModelEvent;
import monopoly.model.events.IGameModelListener;
import monopoly.model.game.Dice.DiceScore;
import monopoly.model.gamefield.CompanyCell;
import monopoly.model.gamefield.EmptyCell;
import monopoly.model.gamefield.GameField;
import monopoly.model.gamefield.GameFieldCellBase;
import monopoly.model.gamefield.GiftCell;
import monopoly.model.gamefield.PenaltyCell;
import monopoly.model.personality.Bank;
import monopoly.model.personality.ILandOwner;
import monopoly.model.personality.ILandSeller;
import monopoly.model.personality.Player;
import monopoly.model.resource.ILand;

/**
* Определяет модель игры.
* @author Роман
*/
public final class GameModel {

    /**
     * Игровое поле.
     */
    private final GameField _field;
    /**
     * Игровые кости.
     */
    private final Dice _dice;
    /**
     * Банк.
     */
    private final Bank _bank;
    /**
     * Стартовая ячейка игры.
     */
    private GameFieldCellBase _startCell;
    /**
     * Игроки, расположенные в порядке их игровой очереди.
     */
    private Queue<Player> _playersQueue;
    /**
     * Доступные цвета для игроков.
     */
    private List<Color> _availableColors;

    /**
     * Получить текущего игрока и перейти к следующему.
     * @return текущий игрок.
     */
    private Player nextPlayer() {
        if (_playersQueue.isEmpty()) {
            return null;
        }

        Player p = _playersQueue.poll();
        _playersQueue.offer(p);

        return p;
    }

    /**
     * Закончить игру для данного игрока.
     * @param p игрок.
     */
    private void finishGamePlayer(Player p) {
        _bank.doBankrupt(p);

        _field.removePlayer(p);
        _playersQueue.remove(p);

        GameModelEvent event = new GameModelEvent(this, p);
        firePlayerFinishedGame(event);
    }

    /**
     * Проверить на возможность окончания игры.
     */
    private void identifyGameOver() {
        if (_playersQueue.size() <= 1) {
            GameModelEvent event = new GameModelEvent(this, _playersQueue.peek());
            fireGameFinished(event);
        }
    }
    /**
     * Слушатели действий модели игры.
     */
    private final List<IGameModelListener> _listeners =
            new ArrayList<IGameModelListener>();

    /**
     * Запустить событие - игрок бросил игровые кости.
     * @param e аргументы события.
     */
    protected void firePlayerDroppedDice(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerDroppedDice(e);
        }
    }

    /**
     * Запустить событие - игрок переместился на игровом поле.
     * @param e аргументы события.
     */
    protected void firePlayerShiftedOnField(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerShiftedOnField(e);
        }
    }

    /**
     * Запустить событие - игрок начал выполнять действие.
     * @param e аргументы события.
     */
    protected void firePlayerStartedDoAction(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerStartedDoAction(e);
        }
    }

    /**
     * Запустить событие - игрок получил подарок.
     * @param e аргументы события.
     */
    protected void firePlayerReceivedGift(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerReceivedGift(e);
        }
    }

    /**
     * Запустить событие - игрок был оштрафован.
     * @param e аргументы события.
     */
    protected void firePlayerReceivedPenalty(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerReceivedPenalty(e);
        }
    }

    /**
     * Запустить событие - у земельного участка сменился владелец.
     * @param e аргументы события.
     */
    protected void fireLandChangedOwner(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gameLandChangedOwner(e);
        }
    }

    /**
     * Запустить событие - у игрока была конфискована земельная собственность.
     * @param e аргументы события.
     */
    protected void firePlayerLandsConfiscated(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerLandsConfiscated(e);
        }
    }

    /**
     * Запустить событие - игрок приобрел земельную собственность.
     * @param e аргументы события.
     */
    protected void firePlayerBoughtLand(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerBoughtLand(e);
        }
    }

    /**
     * Запустить событие - игрок уплатил ренту.
     * @param e аргументы события.
     */
    protected void firePlayerPaidRent(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerPaidRent(e);
        }
    }

    /**
     * Запустить событие - игрок закончил игру(банкрот).
     * @param e аргументы события.
     */
    protected void firePlayerFinishedGame(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gamePlayerFinishedGame(e);
        }
    }

    /**
     * Запустить событие - игра начата.
     * @param e аргументы события.
     */
    protected void fireGameStarted(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gameStarted(e);
        }
    }

    /**
     * Запустить событие - игра закончина и выявлен победитель.
     * @param e аргументы события.
     */
    protected void fireGameFinished(GameModelEvent e) {
        for (IGameModelListener listener : _listeners) {
            listener.gameFinished(e);
        }
    }

    /**
     * Добавить нового слушателя.
     * @param listener слушатель.
     */
    public void addGameModelListener(IGameModelListener listener) {
        _listeners.add(listener);
    }

    /**
     * Удалить указанного слушателя.
     * @param listener слушатель.
     */
    public void removeGameModelListener(IGameModelListener listener) {
        _listeners.remove(listener);
    }

    /**
     * Получить стартовую ячейку на игровом поле.
     * @return ячейка.
     */
    public GameFieldCellBase startCell() {
        return _startCell;
    }

    /**
     * Получить игровое поле.
     * @return игровое поле.
     */
    public GameField field() {
        return _field;
    }

    /**
     * Получить игроков.
     * @return список игроки.
     */
    public List<Player> players() {
        return _field.players();
    }

    /**
     * Получить банк.
     * @return банк.
     */
    public Bank bank() {
        return _bank;
    }

    /**
     * Получить игровые кости.
     * @return игровые кости.
     */
    public Dice dice() {
        return _dice;
    }

    /**
     * Начать игру.
     * @param playerCount количество игроков.
     */
    public void start(int playerCount) {
        _field.clear();

        _field.addCell(new EmptyCell());
        _field.addCell(new CompanyCell(
                "Bacardi", 16000, (int) (16000 * 0.6), 3500));
        _field.addCell(new PenaltyCell());
        _field.addCell(new CompanyCell(
                "Smirnoff", 16000, (int) (16000 * 0.6), 2500));
        _field.addCell(new PenaltyCell());
        _field.addCell(new CompanyCell(
                "Absolut Vodka", 16000, (int) (16000 * 0.6), 4000));
        _field.addCell(new GiftCell());
        _field.addCell(new CompanyCell(
                "Microsoft", 88000, (int) (88000 * 0.6), 38000));
        _field.addCell(new CompanyCell(
                "Marlboro", 20000, (int) (20000 * 0.6), 1500));
        _field.addCell(new EmptyCell());
        _field.addCell(new CompanyCell(
                "Kent", 20000, (int) (20000 * 0.6), 1500));
        _field.addCell(new CompanyCell(
                "Parlament", 20000, (int) (20000 * 0.6), 2000));
        _field.addCell(new CompanyCell(
                "Nike", 28000, (int) (28000 * 0.6), 4000));
        _field.addCell(new CompanyCell(
                "Adidas", 28000, (int) (28000 * 0.6), 6300));
        _field.addCell(new CompanyCell(
                "Puma", 28000, (int) (28000 * 0.6), 4900));
        _field.addCell(new GiftCell());
        _field.addCell(new CompanyCell(
                "IBM", 50000, (int) (50000 * 0.6), 15900));
        _field.addCell(new CompanyCell(
                "Scania", 35000, (int) (35000 * 0.6), 10000));
        _field.addCell(new EmptyCell());
        _field.addCell(new CompanyCell(
                "Man", 40000, (int) (40000 * 0.6), 12000));
        _field.addCell(new GiftCell());
        _field.addCell(new CompanyCell(
                "Nokia", 48000, (int) (48000 * 0.6), 16000));
        _field.addCell(new CompanyCell(
                "Samsung", 48000, (int) (48000 * 0.6), 17000));
        _field.addCell(new CompanyCell(
                "Panasonic", 48000, (int) (48000 * 0.6), 17000));
        _field.addCell(new CompanyCell(
                "Apple", 90000, (int) (90000 * 0.6), 40000));
        _field.addCell(new CompanyCell(
                "Beeline", 52000, (int) (52000 * 0.6), 25000));
        _field.addCell(new CompanyCell(
                "Megafon", 52000, (int) (52000 * 0.6), 27000));
        _field.addCell(new PenaltyCell());
        _field.addCell(new CompanyCell(
                "Gucci", 64000, (int) (64000 * 0.6), 29900));
        _field.addCell(new CompanyCell(
                "Cannel", 65000, (int) (65000 * 0.6), 28000));
        _field.addCell(new PenaltyCell());
        _field.addCell(new CompanyCell(
                "Dell", 68000, (int) (68000 * 0.6), 30000));
        _field.addCell(new GiftCell());
        _field.addCell(new CompanyCell(
                "Pepsi", 80000, (int) (80000 * 0.6), 36000));
        _field.addCell(new PenaltyCell());
        _field.addCell(new CompanyCell(
                "Coca-cola", 85000, (int) (85000 * 0.6), 38100));

        List<GameFieldCellBase> cells = _field.cells();
        for (int i = 0; i < cells.size() - 1; i++) {
            cells.get(i).setNext(cells.get(i + 1));
        }
        cells.get(cells.size() - 1).setNext(cells.get(0));
        _startCell = cells.get(0);

        for (GameFieldCellBase c : cells) {
            if (c instanceof CompanyCell) {
                _bank.addLand((CompanyCell) c);
            }
        }

        for (int i = 0; i < playerCount; i++) {
            _field.addPlayer(_startCell,
                    new Player("Игрок " + (i + 1),
                    _availableColors.get(i), 150000));
        }
        _playersQueue = new ArrayDeque(_field.players());
       
        GameModelEvent event = new GameModelEvent(this);
        this.fireGameStarted(event);
    }

    /**
     * Задать новую игру.
     */
    public GameModel() {
        _dice = new Dice();
        _bank = new Bank();
        _field = new GameField();

        _availableColors = new ArrayList<Color>();
        _availableColors.add(HTMLColors.red);
        _availableColors.add(HTMLColors.blue);
        _availableColors.add(HTMLColors.green);
        _availableColors.add(HTMLColors.gray);
        _availableColors.add(HTMLColors.yellow);
        _availableColors.add(HTMLColors.orange);
        _availableColors.add(HTMLColors.black);
        _availableColors.add(HTMLColors.purple);
        _availableColors.add(HTMLColors.lime);
        _availableColors.add(HTMLColors.olive);

        start(0);
    }

    /**
     * Выполнить очередной ход игры.
     * Свой ход делает следующий по очереди игрок. Игрок перемешается по ячейкам
     * игрового поля, в соответсвии с количеством очков выпавших на костях.
     * После того как игрок дойдет до целевой ячейки, он совершает действие
     * согласно игровой логике этой ячейки.
     */
    public void makeNextMove() {
        Player p = nextPlayer();
        if (p == null) {
            return;
        }

        DiceScore diceScore = p.dropDice(_dice);
        GameModelEvent event = new GameModelEvent(this, p, diceScore);
        firePlayerDroppedDice(event);

        GameFieldCellBase oldPosition = p.position();
        p.shiftOnField(diceScore.score());
        GameFieldCellBase newPosition = p.position();
        event = new GameModelEvent(this, p, oldPosition, newPosition);
        firePlayerShiftedOnField(event);

        event = new GameModelEvent(this, p);
        firePlayerStartedDoAction(event);
    }

    /**
     * Сделать игроку подарок в указанном размере в виде денежной суммы.
     * @param p игрок.
     * @param gift подарок в виде денежной суммы.
     */
    public void makePlayerGift(Player p, int gift) {
        if (_bank.giveMoney(p, gift)) {
            GameModelEvent event = new GameModelEvent(this, p, gift);
            firePlayerReceivedGift(event);
        }
    }

    /**
     * Оштрафовать игрока на указанную сумму.
     * @param p игрок.
     * @param penalty штраф в виде денежной суммы.
     */
    public void makePlayerPenalty(Player p, int penalty) {
        if (_bank.takeAwayMoney(p, penalty) == false) {
            List<ILand> confiscated = new ArrayList<ILand>();

            ILand lastLand = _bank.confiscateLand(p);
            while (lastLand != null) {
                GameModelEvent event = new GameModelEvent(this, lastLand,
                        p, _bank);
                fireLandChangedOwner(event);

                confiscated.add(lastLand);

                if (_bank.takeAwayMoney(p, penalty)) {
                    break;
                }

                lastLand = _bank.confiscateLand(p);
            }

            if (confiscated.isEmpty() == false) {
                GameModelEvent event = new GameModelEvent(this, p, confiscated);
                firePlayerLandsConfiscated(event);
            }

            if (lastLand == null) {
                finishGamePlayer(p);
            } else {
                GameModelEvent event = new GameModelEvent(this, p, penalty);
                firePlayerReceivedPenalty(event);
            }

        } else {
            GameModelEvent event = new GameModelEvent(this, p, penalty);
            firePlayerReceivedPenalty(event);
        }

        identifyGameOver();
    }

    /**
     * Заставить игрока заплатить арендную плату (ренту) за земельный участок.
     * @param p игрок.
     * @param land земельный участок.
     */
    public void makePlayerPayRent(Player p, ILand land) {
        if (land.owner() == _bank || land.owner() == p) {
            return;
        }

        if (p.payRent(land) == false) {
            List<ILand> confiscated = new ArrayList<ILand>();

            ILand lastLand = _bank.confiscateLand(p);
            while (lastLand != null) {
                GameModelEvent event = new GameModelEvent(this, lastLand,
                        p, _bank);
                fireLandChangedOwner(event);

                confiscated.add(lastLand);

                if (p.payRent(land)) {
                    break;
                }

                lastLand = _bank.confiscateLand(p);
            }

            if (confiscated.isEmpty() == false) {
                GameModelEvent event = new GameModelEvent(this, p, confiscated);
                firePlayerLandsConfiscated(event);
            }

            if (lastLand == null) {
                finishGamePlayer(p);
            } else {
                GameModelEvent event = new GameModelEvent(this, p, land);
                firePlayerPaidRent(event);
            }

        } else {
            GameModelEvent event = new GameModelEvent(this, p, land);
            firePlayerPaidRent(event);
        }

        identifyGameOver();
    }

    /**
     * Приобрести земельный участок за указанную цену игроку.
     * @param p игрок.
     * @param land покупаемый земельный участок.
     * @param amount сумма сделки.
     */
    public void makePlayerBuyLand(Player p, ILand land, int amount) {
        ILandOwner owner = land.owner();
        if (owner instanceof ILandSeller) {
            ILandSeller seller = (ILandSeller) owner;
            if (p.buyLand(seller, amount, land)) {

                GameModelEvent event = new GameModelEvent(this, land, seller, p);
                fireLandChangedOwner(event);

                event = new GameModelEvent(this, p, land, amount);
                firePlayerBoughtLand(event);
            }
        }
    }
}
TOP

Related Classes of monopoly.model.game.GameModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.