Package hexenschach.gameplay

Source Code of hexenschach.gameplay.Gameplay

package hexenschach.gameplay;

import hexenschach.board.Board;
import hexenschach.board.TurnPossibility;
import hexenschach.gui.UserInterfaceAPI;
import hexenschach.gui.FieldHighlightStatus;
import hexenschach.player.Player;
import hexenschach.player.AiAlgorithm;
import hexenschach.gui.graphic.HexenschachPanel;
import hexenschach.gui.Dictionary;


/**
* Die Klasse leitet Spiele indem sie die im Spiel befindlichen Spieler verwaltet,
* Eingaben vom GUI verarbeitet, mit dem Spielbrett kommuniziert und Methoden zum
* Rückgängigmachen und Wiederherstellen eines Zuges bietet.
*
* @author Andreas Lorig
* @date 11.05.2010
*/
public class Gameplay
{
    // true wenn das Spiel vorbei ist
    private boolean isOver = false;

    // Der aktuelle GameContext
    private GameContext currentContext;

    // Die 3 beteiligten Spieler
    private Player player1;
    private Player player2;
    private Player player3;

    // Der Spieler der gerade am Zug ist
    private int currentPlayer;

    // Die Interface API
    private UserInterfaceAPI interfaceAPI;

    // Aktuelles Spielbrett
    private Board board;

    // Array von TurnPossibilities
    private TurnPossibility []turn;

    private TurnPossibility tp;
    // Der Status wird als int dargestellt
    private int status;

    // Liste in der GameContext Objekte verwaltet werden
    private UndoRedo undoRedo;

    private AiAlgorithm aiAlg;
    private boolean eroeffnungsZug;

    /**
     * Konstruktor der Klasse Gameplay, welchem 3 Spielerobjekte und das Interface
     * "UserInterfaceAPI" übergeben werden. Dieser Konstruktor wird für die Funktion
     * "neues Spiel" benutzt.
     *
     * @param newPlayer1 Spieler 1
     * @param newPlayer2 Spieler 2
     * @param newPlayer3 Spieler 3
     * @param newInterfaceAPI die zu benutzende InterfaceAPI
     */
    public Gameplay (Player newPlayer1, Player newPlayer2, Player newPlayer3, UserInterfaceAPI newInterfaceAPI)
    {
        player1 = newPlayer1;
        player2 = newPlayer2;
        player3 = newPlayer3;
       
        interfaceAPI = newInterfaceAPI;
       
        // Default: first currentPlayer = player1
        currentPlayer = 1;
       
        // Am Anfang eines Spieles wird ein neues Board erzeugt
        board = new Board();
       
        // setzen des ersten GameContextes
        currentContext = new GameContext (board, player1, player2, player3, currentPlayer);

        // Neue UndoRedo Liste wird erzeugt
        undoRedo = new UndoRedo();
        // der Kontext wird in die UndoRedo liste eingefügt
        undoRedo.appendToEnd(currentContext);

        // Von Anfang an ist keine Figur ausgewählt
        status = 1;

        // Zeichnen der Figuren
        this.drawFigures();

        // Anzeigen das eine neue Runde gestartet wurde
        interfaceAPI.setDirectHelp(Dictionary.NewGameMessage);

        // Anzeigen das der erste Spieler am Zug ist
        this.informCurrentPlayer(status);

        // Situation -> für schachcheck
        aiAlg = new AiAlgorithm ();
        eroeffnungsZug = true;
    }

    /**
     * Konstruktor, dem 3 Spielerobjekte, die InterfaceAPI, der Aktuelle Spieler
     * und ein Brett übergeben werden. Benutzt wird dieser Konstruktor für das
     * Laden von Spielständen.
     *
     * @param newPlayer1 der erste Spieler
     * @param newPlayer2 der zweite Spieler
     * @param newPlayer3 der dritte Spieler
     * @param newInterfaceAPI die InterfaceAPI
     * @param newCurrentPlayer der aktuelle Spieler
     * @param newBoard das neue Brett
     */
    public Gameplay (Player newPlayer1, Player newPlayer2, Player newPlayer3, UserInterfaceAPI newInterfaceAPI,
                        int newCurrentPlayer, Board newBoard)
    {
        player1 = newPlayer1;
        player2 = newPlayer2;
        player3 = newPlayer3;

        interfaceAPI = newInterfaceAPI;

        // Das Board wird übergeben
        board = newBoard;

        // Der aktuelle Spieler wird übergeben
        currentPlayer = newCurrentPlayer;
       
        // setzen des ersten GameContextes
        currentContext = new GameContext (board, player1, player2, player3, currentPlayer);

        // Neue UndoRedo Liste wird erzeugt
        undoRedo = new UndoRedo();
        // der Kontext wird in die UndoRedo liste eingefügt
        undoRedo.appendToEnd(currentContext);

        // Von Anfang an ist keine Figur ausgewählt
        status = 1;

        // Zeichnen der Figuren
        this.drawFigures();

        // Anzeigen das eine neue Runde gestartet wurde
        interfaceAPI.setDirectHelp(Dictionary.LoadedGameMessage);

        // Anzeigen welcher Spieler am Zug ist
        this.informCurrentPlayer(currentPlayer);

        // Situation -> für schachcheck
        aiAlg = new AiAlgorithm ();

        eroeffnungsZug = true;
    }

    /**
     * Verarbeitet die Eingabe eines Feldes, welche durch einen Klick, aber auch
     * durch Tastatureingabe erfolgt sein kann. Die Methode wird nach besagten
     * Ereignissen vom GUI aufgerufen.
     *
     * @param field String der ein Feld auf dem Spielfeld beschreibt.
     */
    public void processFieldInput (String selectedField)
    {
        if (!isOver())  // Wenn das Spiel noch nicht vorbei ist
        {
        // 1. Menschlicher oder Computerspieler?
        if (getPlayer (currentPlayer).isComputer) // boolean
        {
            this.computersTurn ();
        } else this.playersTurn (selectedField);
        }else
        {
            interfaceAPI.setDirectHelp(Dictionary.GameIsOver);
            if (this.getPlayerColor(currentPlayer).equals("white"))
            {
                interfaceAPI.setDirectHelp(Dictionary.WhiteHasWon);
            } else if (this.getPlayerColor(currentPlayer).equals("brown"))
                interfaceAPI.setDirectHelp(Dictionary.BrownHasWon);
            else interfaceAPI.setDirectHelp(Dictionary.BlackHasWon);
            interfaceAPI.gameFinished();
        }

       
    }

    /**
     * Verarbeitet Klicke auf das Spielfeld, wenn zu dem Zeitpunkt noch keine Felder hervorgehoben sind.
     *
     * @param field das Feld der Figur deren mögliche Züge hervorgehoben werden sollen.
     * @param die zuvor berechneten Spielzugsmöglichkeiten.
     */
    private void noSelectedFigure (String field, TurnPossibility [] turnPo)
    {
       
        // Das Highlighting zurücksetzen
        interfaceAPI.resetHighlight();
        // Vergleich ob die Figur vom Spieler ist der dran ist
        if (board.getPlayer(field) == currentPlayer)
        {
            // Highlighten des Feldes auf dem die ausgewählte Figur steht
            interfaceAPI.highlightField (turnPo[0].from, FieldHighlightStatus.SELECT);
            // Schleife die das Array durchläuft und die anderen Felder "highlighted"
            for (int i = 0; i < turnPo.length; i++)
               interfaceAPI.highlightField (turnPo[i].to, this.calculateStatus(turnPo[i].wasHit));

            // Übergang in einen anderen Status
            status = 2;
        }
    }

    /**
     * Verarbeitet Klicke auf das Spielfeld, wenn zu dem Zeitpunkt Felder hervorgehoben sind.
     *
     * @param field auf dieses Feld wurde geklickt.
     * @param turnPo die zuvor berechneten Spielzugsmöglichkeiten.
     */
    private void figureIsSelected (String field, TurnPossibility [] turnPo)
    {
        // Vorraussetzung: Auf dem Feld ist keine Figur des Spielers, der dort hin ziehen möchte.
        if (board.getPlayer(field) != currentPlayer)
        {
            // In den Zugmöglichkeiten suchen ob der gewünschte Zug durchgeführt werden kann.
            for (int i = 0; i < turnPo.length; i++)
            {
                if (turnPo[i].to.equals (field))
                {
                    // Wird ein König geschlagen?
                    if (board.getFigureType(turnPo[i].to).equals ("king"))
                    {
                        String deadPlayer = getPlayerColor(board.getPlayer(turnPo[i].to));
                        int playerNum = board.getPlayer(turnPo[i].to);
                        // Ist es der König des weißen Spielers?
                        if (deadPlayer.equals("white"))
                        {
                            this.playerIsGameOver(playerNum);
                            // Wurde das Spiel dadurch entschieden?
                            if (isOver)
                            {
                                interfaceAPI.setDirectHelp(Dictionary.GameIsOver);
                                if (this.getPlayerColor(currentPlayer).equals("white"))
                                {
                                    interfaceAPI.setDirectHelp(Dictionary.WhiteHasWon);
                                } else if (this.getPlayerColor(currentPlayer).equals("brown"))
                                {
                                    interfaceAPI.setDirectHelp(Dictionary.BrownHasWon);
                                }
                                else {
                                    interfaceAPI.setDirectHelp(Dictionary.BlackHasWon);
                                    interfaceAPI.gameFinished();
                                    }
                            } else {
                                    interfaceAPI.setDirectHelp(Dictionary.WhiteKingDied);
                                    interfaceAPI.setDirectHelp(Dictionary.RemainingPlayersContinue);
                                    }
                        } else
                            // ist es der König des braunen Spielers?
                            if (deadPlayer.equals("brown"))
                            {
                                this.playerIsGameOver(playerNum);
                            if (isOver)
                            {
                                interfaceAPI.setDirectHelp(Dictionary.GameIsOver);
                                if (this.getPlayerColor(currentPlayer).equals("white"))
                                {
                                    interfaceAPI.setDirectHelp(Dictionary.WhiteHasWon);
                                } else if (this.getPlayerColor(currentPlayer).equals("brown"))
                                    interfaceAPI.setDirectHelp(Dictionary.BrownHasWon);
                                else {
                                    interfaceAPI.setDirectHelp(Dictionary.BlackHasWon);
                                    interfaceAPI.gameFinished();
                                    }
                            } else {
                                interfaceAPI.setDirectHelp (Dictionary.BrownKingDied);
                                interfaceAPI.setDirectHelp(Dictionary.RemainingPlayersContinue);
                            }
                            } else
                            {
                            this.playerIsGameOver(playerNum);
                            if (isOver)
                            {
                            interfaceAPI.setDirectHelp(Dictionary.GameIsOver);
                            if (this.getPlayerColor(currentPlayer).equals("white"))
                            {
                             interfaceAPI.setDirectHelp(Dictionary.WhiteHasWon);
                            } else if (this.getPlayerColor(currentPlayer).equals("brown"))
                             interfaceAPI.setDirectHelp(Dictionary.BrownHasWon);
                            else interfaceAPI.setDirectHelp(Dictionary.BlackHasWon);
                            interfaceAPI.gameFinished();
                            } else {
                                    interfaceAPI.setDirectHelp(Dictionary.BlackKingDied);
                                    interfaceAPI.setDirectHelp(Dictionary.RemainingPlayersContinue);
                            }
                        }
                    }
                    // Figur auf das neue Feld setzen
                    interfaceAPI.moveFigure(turnPo[i].from, turnPo[i].to);

                    interfaceAPI.resetHighlight ();

                   
                    // Neue Situation als aktuelles Board speichern.
                    board = turnPo[i].boardafter;

                    // Der Zug ist vorrüber und jetzt ist wieder keine Figur selektiert
                    status = 1;
                    if (checkMateCheck())
                    {
                        interfaceAPI.setDirectHelp ("Spieler " + currentPlayer + " ist Schachmatt gesetzt.");
                        // Die Referenz auf den aktuellen Spieler (der ja im schach steht) wird auf null gesetzt
                        playerIsGameOver (currentPlayer);
                    }
                   
                   
                    // Der nächste Spieler ist dran
                    this.nextPlayer();
                    // Anhängen des aktuellen GameContext in die UndoRedo Liste
                    undoRedo.appendToEnd(currentContext = new GameContext(board, player1, player2, player3, currentPlayer));

                    // Anzeigen wer als nächstes am Zug ist
                    this.informCurrentPlayer(currentPlayer);

                    // Steht er im schach?
                    if (checkCheck())
                    {
                        interfaceAPI.setDirectHelp (Dictionary.CheckWarning);
                    }
                } else interfaceAPI.resetHighlight ();
            }
        } else
        {
            // Ist auf dem angeklickten Feld eine Figur des Spielers der am Zug ist, wird diese ausgewählt.
            status = 1;
            this.processFieldInput(field);
        }
    }

    /**
     * Gibt zurück ob ein Spiel vorbei ist.
     *
     * @return true wenn ein Spiel vorbei ist.
     */
    public boolean isOver ()
    {
        if ((player1 == null && player2 == null) || (player2 == null && player3 == null) || (player1 == null && player3 == null))
            isOver = true;
        return isOver;
    }

    /**
     * Der jeweilige Spieler ist game over
     * @param num der Spieler der auf null gesetzt wird
     */
    private void playerIsGameOver (int num)
    {
        if (num == 1)
            player1 = null;
        else if (num == 2)
            player2 = null;
        else player3 = null;
    }

    /**
     * Setzt die aktuelle Spielsituation auf die vorherige zurück.
     */
    public void undo ()
    {
        undoRedo.undo();
        currentContext = undoRedo.getCurrentContext();
        this.loadContext();
        this.informCurrentPlayer(currentPlayer);
        this.drawFigures();
        status = 1;
        interfaceAPI.resetHighlight();
    }

    /**
     * Macht die Verwendung eines zuvor genutzten Undos wieder Rückgängig.
     */
    public void redo ()
    {
        undoRedo.redo();
        currentContext = undoRedo.getCurrentContext();
        this.loadContext();
        this.informCurrentPlayer(currentPlayer);
        this.drawFigures();
        status = 1;
        interfaceAPI.resetHighlight();
    }

    /**
     * Lässt die KI einen Zug des Spielers übernehmen.
     */
    public void autoMove ()
    {
        TurnPossibilityList tpl = getAllPossibilities ();
        boolean checked = this.checkCheck();
        // Zwischenspeichern der TurnPossibility
        tp = getPlayer (currentPlayer).evaluate(tpl, currentPlayer, getPlayer(currentPlayer), board, checked);
        // Figur auf das neue Feld setzen
        interfaceAPI.moveFigure(tp.from, tp.to);

        interfaceAPI.resetHighlight ();

        this.nextPlayer();
        // Neue Situation als aktuelles Board speichern.
        board = tp.boardafter;
        // Anhängen des aktuellen GameContext in die UndoRedo Liste
        undoRedo.appendToEnd(currentContext = new GameContext(board, player1, player2, player3, currentPlayer));
       
        this.informCurrentPlayer(currentPlayer);
    }

    /**
     * Der nächste Spieler ist am Zug
     */
    private void nextPlayer ()
    {
        switch (currentPlayer)
        {
                case 1: if (getPlayer(2) != null)
                {
                    currentPlayer = 2;
                } else currentPlayer = 3; break;

                case 2: if (getPlayer(3) != null)
                {
                    currentPlayer = 3;
                } else currentPlayer = 1; break;

                case 3: if (getPlayer(1) != null)
                {
                    currentPlayer = 1;
                } else currentPlayer = 2; break;
        }
    }
   
    /**
     * Gibt für ein PlayerEnum den jeweiligen Spieler zurück.
     *
     * @param num Die Zahl die den Spieler repräsentiert
     * @return der zugehörige Spieler
     */
    private Player getPlayer (int num)
    {
        if (num == 1)
            return player1;
        else
            if (num == 2)
                return player2;
        else
            return player3;
    }

    /**
     * Gibt für ein PlayerEnum die Farbe des jeweiligen Spielers zurück.
     *
     * @param num die Zahl die den Spieler repräsentiert.
     * @return die Farbe des zugehörigen Spielers
     */
    private String getPlayerColor (int num)
    {
        String color = getPlayer(num).playerColor;

        return color;
    }

    /**
     * Zeigt auf der Direkthilfe an, welcher Spieler am Zug ist.
     *
     * @param num die Zahl die den Spieler repräsentiert
     */
    private void informCurrentPlayer (int num)
    {
        if (getPlayer (currentPlayer).isComputer == true)
        {
            interfaceAPI.setDirectHelp(Dictionary.NextPlayerIsPC);
            interfaceAPI.setDirectHelp(Dictionary.PleaseClick);
        } else {
        String color = getPlayerColor(num);
        if (color.equals ("white"))
            interfaceAPI.setDirectHelp(Dictionary.WhitePlayerTurn);
        else if (color.equals("black"))
            interfaceAPI.setDirectHelp(Dictionary.BlackPlayerTurn);
        else
            interfaceAPI.setDirectHelp(Dictionary.BrownPlayerTurn);
        }
    }

    /**
     * Setzt das Spiel auf den Stand eines GameContextes
     */
    private void loadContext ()
    {
        currentPlayer = currentContext.activePlayer;
        board = currentContext.board;
        player1 = currentContext.getPlayer(0);
        player2 = currentContext.getPlayer(1);
        player3 = currentContext.getPlayer(2);
    }

    /**
     * Gibt den aktuellen GameContext zurück
     * @return der aktuelle Kontext
     */
    public GameContext getGameContext ()
    {
        return currentContext;
    }

    /**
     * Der Zug eines Menschlichen Spielers
     *
     * @param field
     */
    private void playersTurn (String field)
    {
        // Unterscheidung ob schon eine Figur ausgewählt ist oder nicht.
        switch (status)
        {
            // Keine Figur ist "selektiert"
            case 1: // zwischenspeichern der Zugmöglichkeiten der Figur für dieses Feld
                turn = board.calculateTurnPossibility (field);
                if (turn != null)
                {
                    // Highlighten
                    noSelectedFigure (field, turn);
                } else
                    if (board.getFigure(field) != null)
                    {
                        // Sollten keine Zugmöglichkeiten für eine Figur bestehen, so wird dieser darauf hingewiesen.
                        interfaceAPI.setDirectHelp (Dictionary.FigureCantMove);
                        // Das Highlighting wird zurück gesetzt
                        interfaceAPI.resetHighlight();
                    } else
                    {
                        // Ist keine Figur auf diesem Feld wird der Spieler darauf hingewiesen.
                        interfaceAPI.setDirectHelp(Dictionary.ChooseYourOwn);
                        // Das Highlighting wird zurück gesetzt
                        interfaceAPI.resetHighlight();
                    }
                break;

            // Es ist bereits eine Figur selektiert.
            case 2:
                // Zug der Figur
                figureIsSelected (field, turn);
                break;
        }
    }

    /**
     * Setzt die Figuren zu Spielbeginn aufs Spielfeld.
     */
    void drawFigures ()
    {
        // In diesem String-Array sind alle Koordinaten des Spielfeldes enthalten.
        String [] coords = HexenschachPanel.FIELD_NAMES;

        // Die Schleife durchläuft alle Einträge der Hashmap
        for(int i = 0; i < coords.length; i++)
        {
            if (board.boardHM.get(coords[i]) != null)
            {
            // Die jeweilige Figur wird gesetzt
            interfaceAPI.setFigure(coords[i], board.getFigure(coords[i]));
            }
        }
    }
    /**
     * Der Zug eines Computer gesteuerten Spielers.
     *
     */
    private void computersTurn ()
    {
       if (eroeffnungsZug == true)
       {
           tp = aiAlg.openGame(board, currentPlayer);
           eroeffnungsZug = false;
       } else {
       TurnPossibilityList tpl = getAllPossibilities ();
       boolean checked = this.checkCheck();
       // Zwischenspeichern der TurnPossibility
       tp = getPlayer (currentPlayer).evaluate(tpl, currentPlayer, getPlayer(currentPlayer), board, checked);
       }
       // Figur auf das neue Feld setzen
       interfaceAPI.moveFigure(tp.from, tp.to);
       interfaceAPI.resetHighlight ();

       this.nextPlayer();
       // Neue Situation als aktuelles Board speichern.
       board = tp.boardafter;
       // Anhängen des aktuellen GameContext in die UndoRedo Liste
       undoRedo.appendToEnd(currentContext = new GameContext(board, player1, player2, player3, currentPlayer));

       this.informCurrentPlayer(currentPlayer);

    }

    /**
     * Testet ob Figuren im Schach stehen
     */
    private boolean checkCheck ()
    {
        int [] intArray = aiAlg.checked(board);
        if (intArray[currentPlayer] == 1)
            return true;
        else return false;
    }

    /**
     * Schachmatterkennung
     */
    private boolean checkMateCheck ()
    {
        int [] intArray = aiAlg.checkmate(currentPlayer, board);
        if (intArray[currentPlayer] == 1)
            return true;
        else return false;
    }

    /**
     * Berechnet den Status eines Feldes abhängig davon ob dort ein Gegner steht oder nicht.
     * Ausgewählt/Frei/Belegt vom Gegner/
     *
     * @paran enemy true wenn dort eine gegnerische Figur steht
     */
    private FieldHighlightStatus calculateStatus (boolean enemy)
    {
        if (enemy)
            return FieldHighlightStatus.CAPTURE;
        else
            return FieldHighlightStatus.POSSIBLE;
    }

    /**
     * Gibt alle Turnpossibilities für alle Figuren zurück
     */
    private TurnPossibilityList getAllPossibilities ()
    {
        // Eine TurnPossibilityList wird erzeugt
        TurnPossibilityList turnPoList = new TurnPossibilityList ();
        // Die Schleife durchläuft alle Einträge der Hashmap
        for(char x = 'A'; x <= 'U'; x++)
        {
            for(int y = 1; y <= 11; y++)
            {
                // Setzt die Koordinate für das Board zusammen
                String coord = "" + x + y;
                if ((board.boardHM.get(coord) != null) && (board.getPlayer (coord) == currentPlayer))
                {
                    // Die Zugmöglichkeiten der Figur werden berechnet und zwischengespeichert
                    TurnPossibility [] turnPo = board.calculateTurnPossibility (coord);
                    // Das Array aus Turn Possibilities wird durchlaufen und jede Possibility wird in die Liste eingefügt
                    if (turnPo != null)
                    {
                    for (int i = 0; i < turnPo.length; i++)
                    {
                        turnPoList.addTP(turnPo[i]);
                    }
                    }
                }
            }
        }
        return turnPoList;
    }
}
TOP

Related Classes of hexenschach.gameplay.Gameplay

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.