Package hexenschach.player

Source Code of hexenschach.player.AiAlgorithm

package hexenschach.player;

import java.util.*;
import hexenschach.board.Board;
import hexenschach.board.TurnPossibility;
import hexenschach.figures.Figure;
import hexenschach.gameplay.TurnPossibilityList;
import hexenschach.gui.graphic.HexenschachPanel;

/**
* Enthält den Algorithmus der KI.
* Hier sind alle Prüfvorgänge der einzelnen Möglichkeiten implementiert.
* @author Sven Lochner, 558895
*/
public class AiAlgorithm {

    protected TurnPossibility currentTP;    // Referenz auf die Zugmöglichkeiten
    private Figure thisFigure;              // Referenz auf aktuell zu analysierende Spielfigur
    private String fieldCoord;              // Koordinate der gezogenen Figur
    int recursionCount;                     // Zähler der Rekursionsdurchläufe

    Ballancing ballance;
    List <String> ThreateningFigures;          // Liste zum Speichern der Koordinaten der bedrohenden Figuren
    public AiAlgorithm(){
        ballance = new Ballancing();
        ThreateningFigures = new LinkedList<String>();
        recursionCount = 1;
    }

    /**
     * Zählt die Punkte aus den analysierenden Methoden zusammen.<br />
     *
     * @param pPossibleMoves[], Array an den zu prüfenden Board-Objekten,
     * @param pCurrentPlayer, der aktive Spieler (1 = white, 2 = brown, 3 = black)
     * @param pPlayer, der aktive Spieler als Player-Objekt
     * @param pCurrentBoard, die aktuelle Spielfeldsituation
     * @return selectedMove, der nächste druchzuführende Spielzug
     */
    public TurnPossibility evaluate(TurnPossibilityList pTurnPossibilities, int pCurrentPlayer, Player pPlayer, Board pCurrentBoard, boolean pCheckStatus){
        /*
         * Logik:
         * Die Punkte der einzelnen Situationen werden in den dafür vorgesehenen Methoden zusammengerechnet und zurückgeliefert.
         *
         * Es wird eine Liste von Spielfeld-Objekten mit den dazugehörigen bedrohten Figuren, dem aktiven Spieler und dem
         * aktuellen Spielstand (Board-Objekt) angefordert.
         * Der Analysevorgang erfolgt durch das Zuweisen von Punkten für die jeweiligen Situationen.
         * Am Ende werden alle Punkte zusammengezählt und für jedes Brett in einer TreeMap gespeichert.
         *
         * Das Auswahlverfahren erfolgt je nach Schwierigkeitsstufe.
         * Am Ende der Methode wird ein ausgewähltes TurnPossibility-Objekt zurückgeliefert.
         */

        // Analysierte Spielbretter werden in einer Map gespeichert.
        TreeMap <Integer, TurnPossibility> analyzedBoards = new TreeMap <Integer, TurnPossibility> ();


        // Durchläuft alle Spielsituationen.
        for(int i = 0; i < pTurnPossibilities.getLength(); i++){

            currentTP = pTurnPossibilities.getTP(i);
            fieldCoord = currentTP.to;                   // Koordinate der gezogenen Figur setzen.
            Board currentBoard = currentTP.boardafter;   // Board-Objekt des TPs

            System.out.println("CurrentTP: "+currentTP);

            int points = 0;                              // Variable, die Punkte speichert.

            // Situationen durchprüfen und Punkte hinzuaddieren.
            points = evaluateSituationOf(points, pCurrentPlayer, currentBoard, pCheckStatus); // Zug bewerten
            if(points != -1000000)                                                            // Wenn Anti-Schach-Beseitigungsprüfung nicht angeschlagen hat:
                analyzedBoards.put(points, currentTP);                                        // Bewertung und Spielbrett sichern
            else                                                                              // Wenn ASBp angeschlagen hat:
                currentTP = null;                                                             // TurnPossibility-Objekt zerstören
        }
        // Wird nach Schwierigkeitsgrad ausgewählt
        int playerDifficulty = pPlayer.difficulty;              // Schwierigkeit des aktuellen Spielers
        int highestCount = analyzedBoards.lastKey();            // Höchste Punktzahl ausgeben (ohne Board)
       
        TurnPossibility selectedMove = null;                    // Der ausgewählte Spielzug, der an's Gameplay übermittelt wird

        if(playerDifficulty == 3)                               // Spieler ist "Schwer"
            selectedMove = analyzedBoards.get(highestCount);    // Bester Zug wird ausgewählt
        else if(playerDifficulty == 2)                          // Spieler ist "Mittel"
            selectedMove = Util.intermediatePlayer(highestCount, analyzedBoards);
        else{                                                   // Spieler ist "Leicht"
            System.out.println("Vorschläge insgesamt: "+analyzedBoards.entrySet());
            selectedMove = Util.easyPlayer(analyzedBoards);
        }

        return selectedMove;
    }

    /**
     * Analysiert und bewertet Züge nach diversen Situationen.
     * @return Punkte vom Zug.
     */
    private int evaluateSituationOf(int pPoints, int pCurrentPlayer, Board pCurrentBoard, boolean pCheckStatus){
        // Prüfvariable für bestimmte Situationen
        int cThrByEnemy = 0;
        int cProtecting = 0;

       
        // Anti-Schach-Beseitigungsprüfung: Prüft, ob das aktuelle TP ein bestehendes Schach aufhebt.
        // Wenn ja, darf es weiterleben. Wenn nein, wird es brutal zerstört.
        if(pCheckStatus == true){                                                       // Wenn eine Schachsituation vorherrscht
            int checkedPlayer[] = checked(pCurrentBoard);                               // Prüfe, ob die Situation nach dem aktuellen Zugvorschlag noch besteht
            if(checkedPlayer[pCurrentPlayer] == 1)                                      // Wenn der aktive Spieler immernoch im Schach ist
                return -1000000;                                                        // Punkte zurückliefern
        }

        // Prüfungen erste Ebene
        cThrByEnemy = threatenedByEnemy(pCurrentPlayer, pCurrentBoard, fieldCoord);
        if(!pCurrentBoard.getFigureType(currentTP.to).equals("king"))
            cProtecting = protecting(pCurrentPlayer, pCurrentBoard);
        System.out.println("Wert für cThrByEnemy: "+cThrByEnemy+".");
        System.out.println("Wert für cProtecting: "+cProtecting+".");
        if(cThrByEnemy >= 0 || cProtecting > cThrByEnemy)       // Wenn Bedrohung nicht besteht oder Wert der beschützenden Figuren größer ist als die der bedrohenden Figuren
            pPoints = pPoints + threatenedByMe(pCurrentPlayer, null);

        //pPoints = pPoints + Util.filterPointsOf(remis(pCurrentPlayer, pCurrentBoard));
        //points = points + castling();
        pPoints = pPoints + Util.hit(currentTP, pCurrentBoard, currentTP)*20;
        pPoints = pPoints + pawnTurn();

        pPoints = pPoints + cThrByEnemy;
        pPoints = pPoints + cProtecting;


        // Anfang zweite Prüfebene
        TurnPossibility possibleFigureMove[] = pCurrentBoard.calculateTurnPossibility(currentTP.to);
        System.out.println("------------- TPs generieren. -------------");

        if(possibleFigureMove != null){
            System.out.println("LÄNGE: "+possibleFigureMove.length);

            // Solange, wie Zugmöglichkeiten bestehen:
            for(int i = 0; i < possibleFigureMove.length; i++){
                fieldCoord = currentTP.to;                               // Koordinate der gezogenen Figur setzen.
                Board currentBoard = possibleFigureMove[i].boardafter;   // Board-Objekt des TPs
                System.out.println("------------- Evaluate 2 -------------");
                System.out.println("AKTUELLER TP: "+currentTP);
                System.out.println("ZÄHLER: "+i);

                // Prüfvariable für bestimmte Situationen
                cThrByEnemy = 0;
                cProtecting = 0;

                // Prüfungen durchlaufen
                cThrByEnemy = threatenedByEnemy(pCurrentPlayer, currentBoard, fieldCoord);
                System.out.println("Wert für cThrByEnemy: "+cThrByEnemy+".");
                System.out.println("Wert für cProtecting: "+cProtecting+".");
                if(cThrByEnemy >= 0 || cProtecting > cThrByEnemy)       // Wenn Bedrohung nicht besteht oder Wert der beschützenden Figuren größer ist als die der bedrohenden Figuren
                    pPoints = pPoints + threatenedByMe(pCurrentPlayer, currentBoard);

                //points = points + filterPointsOf(remis(pCurrentPlayer, currentBoard));
                //points = points + castling();
                pPoints = pPoints + Util.hit(currentTP, currentBoard, possibleFigureMove[i]);
                pPoints = pPoints + pawnTurn();

                pPoints = pPoints + cThrByEnemy;
                pPoints = pPoints + cProtecting;
            }

        }

        return pPoints;
    }

    /**
     * Findet die Figuren, die die eigene Spielfigur bedrohen und bewertet jede bedrohende Figur mit einem Minuspunkt.
     * @param pCurrentPlayer, der aktive Spieler
     * @param pCurrentBoard, das Brett mit der aktuellen Spielsituation
     * @param pField, die Koordinate des Feldes, auf dem sich die zu prüfende Figur befindet
     * @return points, die addierten Punkte der einzelnen Züge für diese Situation
     */
    protected int threatenedByEnemy(int pCurrentPlayer, Board pCurrentBoard, String pField){
        /*
         * Logik:
         * Pro Zugorschlag werden alle Felder des Spielbrettes (HashMap) durchgeprüft, ob Figuren auf ihnen
         * stehen.
         * Steht eine Figur auf einem Feld, wird erst mal geprüft, ob sie vom aktiven Spieler oder
         * feindlich ist.
         * Anschließend wird diese Figur, sofern sie nicht dem aktiven Spieler angehört, so oft gezogen,
         * bis alle Zugmöglichkeiten durch sind. Während dem Ziehen der Zugmöglichkeiten wird geprüft,
         * ob die Figur auf die Koordinate der zu analysierenden Spielfigur des aktiven Spielers gelangt.
         * Tut sie dies, wird der Zug als mögliche Bedrohung gewertet und Punkte werden der Gesamtwertung
         * abgezogen.
         * Dies gilt ebenso, wenn die Figur auf das Feld des Königs gelangt. Dann wird der Zug als Schach
         * gewertet.
         */

        int points = 0;                     // Gesamtpunktzahl, Startwert: 0
        int checkedPoints[] = new int[3];   // Schachpunktzahl, Indexe: 0 - Punkte, 1-2-3 - geschachte Spieler
        Board analyzedBoard;                // Das zu analysierende Spielbrett

        // Prüfen, ob ein Zugvorschlag oder das aktuelle Spielbrett überprüft werden soll.
        // Es wird beiden eine einheitliche Variable zugewiesen.
        if(pCurrentBoard == null)
            analyzedBoard = currentTP.boardafter;
        else
            analyzedBoard = pCurrentBoard;

       
        // Feldkoordinaten der Hashmap durchlaufen
        for(int coord = 0; coord < HexenschachPanel.FIELD_NAMES.length; coord++){
            // Zu analysierende Koordinate anfordern
            String analyzedCoord = HexenschachPanel.FIELD_NAMES[coord];

            // Prüfen, ob die Koordinate existiert
            if(analyzedBoard.boardHM.get(analyzedCoord) != null){

                // Prüfalgorithmus
                  if(analyzedBoard.getPlayer(analyzedCoord) != pCurrentPlayer){                             // Prüfe: Figur nicht vom aktiven Spieler?
                    Figure enemyFigure = analyzedBoard.getFigure(analyzedCoord);                            // Zu ziehende Gegnerfigur bestimmen
                    if(enemyFigure != null){                                                                // Wenn Figur auf dem Feld steht...

                        // Alle möglichen Züge der Figur anfordern und prüfen, ob Züge bestehen
                        TurnPossibility possibleFigureMove[] = analyzedBoard.calculateTurnPossibility(analyzedCoord);
                        if(possibleFigureMove != null){

                            for(int i = 0; i < possibleFigureMove.length; i++){                             //Zugmöglichkeiten Gegnerfigur durchlaufen

                                TurnPossibility currentMove = possibleFigureMove[i];                        // Aktueller Zug der zu analysierenden Figur
                                String currentMoveCoord = currentMove.to;                                   // Koordinate, zu der die Figur hingezogen ist

                                if(currentMoveCoord.equals(pField)){                                        // Kommt Gegnerfigur auf die Koordinate der gezogenen Figur im Zugvorschlag?
                                    points = points - Ballancing.valueOf(enemyFigure.getType())*2;          // Figurwert von Gesamtwertung abzeihen.
                                    if(analyzedBoard.getFigureType(pField).equals("king")){
                                        ThreateningFigures.add(currentMoveCoord);                           // Koordinate der Gegnerfigur für Schachmatterkennung speichern
                                    }
                                }

                                // Auf Schach prüfen
                                String enemyFigureStr = analyzedBoard.getFigureType(analyzedCoord);         // Gegnerfigur-Typ herausfinden
                                if(enemyFigureStr.equals("king")){                                          // prüfen, ob Figur ein König ist.
                                    checkedPoints = checked(analyzedBoard);                                 // Schach setzen
                                    points = points + checkedPoints[0];                                     // Punkte für Schach anrechnen.
                                }
                            }
                        }
                    }
                }
            }
        }
        return points;
    }

    /**
     * Findet die gegnerischen Figuren, die von der eigenen Figur bedroht werden.<br />
     * Berücksichtigt auch den Wert der Figur in der Punkteberechnung (je h&ouml;her, desto mehr Punkte)
     * @param pCurrentPlayer, der aktive Spieler
     * @param pCurrentBoard, das Brett mit der aktuellen Spielsituation
     * @return points, die addierten Punkte der einzelnen Züge für diese Situation
     */
    protected int threatenedByMe(int pCurrentPlayer, Board pCurrentBoard){
        /*
         * Logik:
         * Es wird nacheinander jeder mögliche Spielzug der Figur durchgezogen.
         * Bei jedem Zug erfolgt eine Prüfung, ob die Figur eine Gegnerische schlagen würde und ob
         * diese Figur ein König ist.
         * Wird eine Figur geschlagen, so wird der Zug bewertet, indem der Wert der eigenen
         * Figur abgezogen und der Wert der gegnerischen Figur angerechnet wird.
         * Die Bewertung erfolgt über die Variable Points, die anschließend, zusammen mit dem
         * Schach-Status in das Array situation[] geschrieben wird.
         */

        int points = 0;                                            // Gesamtpunktzahl, Startwert: 0
        int checkedPoints[] = new int[3];                          // Schachpunktzahl
        Board analyzedBoard = null;                                // Das zu analysierende Spielbrett

        if(pCurrentBoard == null)
            analyzedBoard = currentTP.boardafter;
        else
            analyzedBoard = pCurrentBoard;

        thisFigure = analyzedBoard.getFigure(fieldCoord);   // zu analysierende eigene Figur
        String enemyFigure;                                        // Typ der Gegnerfigur

        // Alle möglichen Züge der Figur anfordern
        TurnPossibility possibleFigureMove[] = analyzedBoard.calculateTurnPossibility(fieldCoord);
        if(possibleFigureMove != null){                                                             // Prüfen, ob Zugmöglichkeiten bestheen
            for(int i = 0; i < possibleFigureMove.length; i++){                                     // Solange die Figur eine Zugmöglichkeit hat...

                TurnPossibility currentMove = possibleFigureMove[i];                                // Aktueller Zug der zu analysierenden Figur
                String currentMoveCoord = currentMove.to;                                           // Koordinate, zu der die Figur hingezogen ist

                if(currentMove.wasHit == true){                                                     // Wurde bei dem Zug eine Figur geschlagen?
                                                                                                    // Was für eine?
                    // Schachprüfung durchführen
                    enemyFigure = analyzedBoard.getFigureType(currentMoveCoord);                    // Auslesen des Figurtyps vom Gegner.
                    if(enemyFigure.equals("king")){                                                 // prüfen, ob Figur ein König ist.
                        checkedPoints = checked(null);                                              // Schach setzen
                        points = points + checkedPoints[0];                                         // Punkte für Schach anrechnen.
                    }
                    else{
                        points = points - Ballancing.valueOf(thisFigure.getType());                 // Wert der eigenen Figur anrechnen
                        points = points + Ballancing.valueOf(enemyFigure);                          // Wert der gegnerischen Figur anrechnen.
                    }

                    // Wenn die eigene Figur nicht bedroht ist...
                    if(threatenedByEnemy(pCurrentPlayer, analyzedBoard, currentMoveCoord) >= 0){
                        points = points + Ballancing.valueOf(thisFigure.getType());                 // Wert der Figur den Punkten hinzuaddieren.
                    }
                }
            }
        }

        return points;
    }

    /**
     * Findet die eigenen Figuren, die die gezogene Spielfigur beschützen.<br />
     * @param pCurrentPlayer, der aktive Spieler
     * @param pCurrentBoard, das Brett mit der aktuellen Spielsituation
     * @return points, die addierten Punkte der einzelnen Züge für diese Situation
     */
    public int protecting(int pCurrentPlayer, Board pCurrentBoard){
        /*
         * Logik:
         * Es wird ein neues Board-Objekt, ohne die eigene Figur.
         * Auf diesem neuen Spielfeld werden alle eigenen Figuren gezogen und geprüft, ob sie auf
         * die nun leere Feldkoordinate der eigenen Figur gelangen.
         * Jede dieser Figuren wird mit Punkten bewertet. Die Wertmessung erfolgt durch... ka, auf jeden
         * Fall sollten die Figuren, je höher ihr Wert ist, umso niedriger bewertet werden.
         */

        int points = 0;                                            // Gesamtpunktzahl, Startwert: 0

        Board boardWithout = pCurrentBoard.without(fieldCoord);    // Zu analysierende Figur löschen, um Zug auf die Koordinate zu ermöglichen

        // Feldkoordinaten der Hashmap durchlaufen
        for(int coord = 0; coord < HexenschachPanel.FIELD_NAMES.length; coord++){
            // Zu analysierende Koordinate anfordern
            String analyzedCoord = HexenschachPanel.FIELD_NAMES[coord];

            // Prüfen, ob die Koordinate existiert
            if(pCurrentBoard.boardHM.get(analyzedCoord) != null){

                // Prüfalgorithmus
                if(pCurrentBoard.boardHM.get(analyzedCoord) != null){                       // Wenn Figur auf dem Feld steht...
                    if(pCurrentBoard.getPlayer(analyzedCoord) == pCurrentPlayer){           // Prüfe: Figur vom aktiven Spieler?

                        Figure ownFigure = pCurrentBoard.getFigure(analyzedCoord);          // Zu ziehende eigene Figur bestimmen

                        // Alle möglichen Züge der Figur anfordern
                        TurnPossibility possibleFigureMove[] = boardWithout.calculateTurnPossibility(fieldCoord);
                        if(possibleFigureMove != null){
                            for(int i = 0; i <  possibleFigureMove.length; i++){            // Solange die Figur eine Zugmöglichkeit hat...

                                TurnPossibility currentMove = possibleFigureMove[i];        // Aktueller Zug der zu analysierenden Figur
                                if(currentMove.to.equals(analyzedCoord)){                   // Wenn die Figur auf die zu analysierende Koordinate gelangt...
                                    points = points + Ballancing.valueOf(ownFigure.getType());// Punkte addieren.
                                }
                            }
                        }
                    }
                }
            }
        }
        return points;
    }

    /**
     * **
     * Liefert die Koordinaten der Könige aller Spieler in einem Array zurück.
     * @return kingCoords, Koordinaten der Spielerkönige. Indexe: 0 - Spieler1, 1 - Spieler2, 2 - Spieler3
     */
    public String[] findAllKings(Board pBoard){

        String kingCoords[] = new String[3];    // Array mit den Koordinaten

        // Feldkoordinaten der Hashmap durchlaufen
        for(int coord = 0; coord < HexenschachPanel.FIELD_NAMES.length; coord++){
            // Zu analysierende Koordinate anfordern
            String analyzedCoord = HexenschachPanel.FIELD_NAMES[coord];

            // Prüfen, ob Koordinate existiert
            if(pBoard.boardHM.get(analyzedCoord) != null){

                // Auf dem Feld steht ein König und dieser König gehört dem zu prüfenden Spieler
                if(pBoard.getFigureType(analyzedCoord).equals("king")){
                    int player = pBoard.getPlayer(analyzedCoord)-1;
                    kingCoords[player] = analyzedCoord;
                }
            }
        }
        return kingCoords;
    }

    /**
     * Liefert die Spieler zurück, für deren Könige keine Zugmöglichkeit besteht
     * @return kingRemis, Indexe: 0 = Spieler 1; 1 = Spieler2; 2 = Spieler3
     */
    protected int[] kingMovePossible(Board pBoard){
        int kingRemis[] = new int[3];           // 0 = König kann ziehen, 1 = König kann nicht ziehen
        String playerKings[] = new String[3];   // Koordinaten der Spielerkönige, 0 = Spieler1,...,2 = Spieler3

        playerKings = findAllKings(pBoard);           // Koordinaten aller Könige speichern

        // Spieler durchlaufen und Prüfungen durchführen
        for(int player = 1; player <= 3; player++){
            TurnPossibility kingTP[] = pBoard.calculateTurnPossibility(playerKings[player-1]);

            if(kingTP != null){                                     // Wenn Züge möglich sind
                for(int i = 0; i <  kingTP.length; i++){            // Solange noch Zugvorschläge bestehen
                    int checked[] = checked(kingTP[i].boardafter)// Schach-Status des Königs abfragen

                    // Prüfung auf Schach
                    if(checked[player] == 1)                        // Ist der Spieler im Schach?
                        kingRemis[player-1] = 1;
                    else{                                           // Wenn nicht:
                        kingRemis[player-1] = 0;
                        i = kingTP.length + 1;                      // Aus Schleife aussteigen, nächsten Spieler prüfen
                    }
                }
            }
            else{                                                   // Wenn keine Züge möglich sind
                kingRemis[player-1] = 1;                            // Spieler kann den König nicht bewegen
            }
        }

        return kingRemis;
    }

    /*
     * Liefert zurück, ob ein Remis vorherrscht und welcher Spieler sich im Remis befindet.
     * @param pCurrentTP, der zu analysierende Zugvorschlag
     * @param pCurrentPlayer, der aktive Spieler
     * @return remisPlayer, die Punkte und die Spieler im Remis. Indexe: 0 - Punkte, 1 - Spieler1, ..., 3 - Spieler3
     */
    public int[] remis(int pCurrentPlayer, Board pCurrentBoard){
        /*
         * Logik:
         * Nachdem in kingMovePossible() geprüft worden ist, ob sich die Könige noch bewegen können,
         * wird, im Falle des nicht-möglichen Königszugs, jede Spielerfigur auf eine Zugmöglichkeit
         * getestet.
         * Besteht keine, so ist dieser Spieler remis.
         */

        int points = 0;                                 // Punkte, die verteilt werden
        int remisPlayer[] = new int[3];                 // Spieler, die im Remis sind, Indexe: 0 - Punkte, 1 - Spieler1,..., 3 - Spieler3
        remisPlayer = kingMovePossible(pCurrentBoard)// Bewegungsmöglichkeiten der Könige anfordern

        int situation[] = new int[4];

        // Spieler durchlaufen
        for(int player = 1; player <= 3; player++){
            if(remisPlayer[player-1] != 0){             // Wenn der König vom Spieler nicht bewegt werden kann

                        // Feldkoordinaten der Hashmap durchlaufen
        for(int coord = 0; coord < HexenschachPanel.FIELD_NAMES.length; coord++){
            // Zu analysierende Koordinate anfordern
            String analyzedCoord = HexenschachPanel.FIELD_NAMES[coord];
           
            // Prüfen, ob die Koordinate existiert
            if(pCurrentBoard.boardHM.get(analyzedCoord) != null){                // Existiert Koordinate?
                if(pCurrentBoard.boardHM.get(analyzedCoord) != null){            // Wenn Figur auf dem Feld steht...
                    if(pCurrentBoard.getPlayer(analyzedCoord) == player){        // Prüfe: Figur vom aktiven Spieler?

                        // Kann die Figur bewegt werden?
                        if(pCurrentBoard.calculateTurnPossibility(analyzedCoord) != null){  // Kann die Figur bewegt werden?System.out.println("Figur-Koord: "+analyzedCoord);
                            remisPlayer[player-1] = 0;                            // Wenn ja, dann ist der Spieler nicht im Remis
                            coord = 99;                                           // Abbruchbedingung für Hashmap-Durchlauf
                        }
                        else{
                            System.out.println("Remis = 1");
                            remisPlayer[player-1] = 1;
                        }
                    }
                }
            }
                }
            }
            else
                remisPlayer[player-1] = 0;    // Kann man den König bewegen, so ist der Spieler nicht remis.
        }

        for(int d = 0; d < remisPlayer.length; d++){
            System.out.println("Index "+d+": "+remisPlayer[d]);
        }
        // Punkte für das Remis vergeben:
        for(int player = 0; player < remisPlayer.length;player++){
            if(remisPlayer[player] == 1){
                if(player == pCurrentPlayer)
                    points = points + Ballancing.valueOf("RemisSelf");    // Aktiver Spieler ist im Remis
                else
                    points = points + Ballancing.valueOf("Remis");        // Anderer Spieler ist im Remis
            }
        }
        situation[0] = points;
        situation[1] = remisPlayer[0];
        situation[2] = remisPlayer[1];
        situation[3] = remisPlayer[2];
        return situation;
    }

    /**
     * Schachprüfung, liefert pro Spieler, der sich im Schach befindet, einen Wert zurück.
     * @param pCurrentBoard, die zu überprüfende Spielfeldsituation. Ist null, wenn mit Zugvorschlägen gearbeitet wird.
     * @return situation[], Indexe: 0 - Punkte (0 Punkte bedeuten kein Schach), 1 - Spieler1,..., 3 - Spieler3
     */
    public int[] checked(Board pCurrentBoard){

        int situation[] = new int[4];   // Indexe: 0 - Punkte, 1 - Spieler1, 2 - Spieler2, 3 - Spieler3
        int points = 0;                 // Gesamtpunktzahl, Startwert: 0

        int currentPlayer;              // Spieler, zu dem die Figur gehört.
        Board analyzedBoard = null;

        // Prüfen, ob ein Zugvorschlag oder das aktuelle Spielbrett überprüft werden soll.
        // Es wird beiden eine einheitliche Variable zugewiesen.
        if(pCurrentBoard == null)
            analyzedBoard = currentTP.boardafter;
        else
            analyzedBoard = pCurrentBoard;

        // Feldkoordinaten der Hashmap durchlaufen
        for(int coord = 0; coord < HexenschachPanel.FIELD_NAMES.length; coord++){
            // Zu analysierende Koordinate anfordern
            String analyzedCoord = HexenschachPanel.FIELD_NAMES[coord];

            // Prüfen, ob die Koordinate existiert
            if(analyzedBoard.boardHM.get(analyzedCoord) != null){
                Figure currentFigure = null;

                // Figur auf der aktuellen Koordinate erfahren
                currentFigure = analyzedBoard.getFigure(analyzedCoord);

                if(currentFigure != null){                                                  // Prüfen, ob Figur auf dem Feld steht
                    currentPlayer = analyzedBoard.getPlayer(analyzedCoord);                 // Spieler, dem die Figur gehört.

                    // Alle möglichen Züge der Figur anfordern
                    TurnPossibility possibleFigureMove[] = analyzedBoard.calculateTurnPossibility(analyzedCoord);

                    if(possibleFigureMove != null){                                             // Prüfen, ob Zugmöglichkeiten zurückgegeben worden sind
                        for(int i = 0; i < possibleFigureMove.length; i++){                     // Solange die Figur eine Zugmöglichkeit hat...

                            TurnPossibility currentMove = possibleFigureMove[i];                // Aktueller Zug der zu analysierenden Figur
                            String currentMoveCoord = currentMove.to;                           // Koordinate, zu der die Figur hingezogen ist

                            // Spieler durchlaufen
                            for(int player = 1; player <= 3; player++){
                                if(currentMoveCoord.equals(Util.kingOf(player, analyzedBoard))){     // Figur steht auf Koordinate vom König des aktuellen Spielers
                                    situation[player] = 1;                                      // Spieler eintragen
                                    points = points + Ballancing.valueOf("Check");              // Punkte vergeben
                                }
                            }
                        }
                    }
                }
            }
        }
        // Punkte in's Array eintragen:
        situation[0] = points;

        return situation;
    }

    /**
     * Liefert die Spieler zurück, die schachmatt sind.
     * @param pCurrentPlayer, der aktive Spieler
     * @param pCurrentBoard, das aktuell zu analysierende Spielfeld
     * @return situationOf, 0 - Punkte, 1 - Spieler1, 2 - Spieler2, 3 - Spieler3
     */
    public int[] checkmate(int pCurrentPlayer, Board pCurrentBoard){
        /*
         * Logik:
         * Ist der König im Schach, wird geprüft, ob das Schach irgendwie aufgehoben werden kann.
         * Es gibt folgende Möglichkeiten:
         * 1. König kann aus dem Schach herausgezogen werden
         * 2. Eigene Figur kann die schachsetzende Gegnerfigur schlagen
         * 3. Eigene Figur kann sich in die Bahn der schachsetzende(n) Gegnerfigur(en) stellen.
         * Führen die Punkte 1-3 zu keinem Erfolg, so ist der Spieler matt.
         */

        // Situationsvariable
        int situationOf[] = new int[4];       // 0 - Punkte, 1 - Spieler1, 2 - Spieler2, 3 - Spieler3
        Board analyzedBoard = null;

        // Prüfen, ob ein Zugvorschlag oder das aktuelle Spielbrett überprüft werden soll.
        // Es wird beiden eine einheitliche Variable zugewiesen.
        if(pCurrentBoard == null)
            analyzedBoard = currentTP.boardafter;
        else
            analyzedBoard = pCurrentBoard;
       
        //*** Geschachte Spieler anfordern und deren Könige anfordern
        int checkedPlayer[] = checked(analyzedBoard);
        String kingCoord[] = findAllKings(analyzedBoard);

        // Spieler durchlaufen
        for(int player = 1; player <= 3; player++){
            if(checkedPlayer[player] == 1){                              // Ist aktueller Spieler im Schach?
                this.threatenedByEnemy(pCurrentPlayer, pCurrentBoard, kingCoord[player-1]); // Liste bilden

                int blockedKing[] = kingMovePossible(analyzedBoard);     // Bewegugnsmöglichkeiten vom König anfordern
                if(blockedKing[player-1] == 1){                          // Kann sich der König nicht bewegen?
                   
                    // Feldkoordinaten der Hashmap durchlaufen
                    for(int coord = 0; coord < HexenschachPanel.FIELD_NAMES.length; coord++){
                        // Zu analysierende Koordinate anfordern
                        String analyzedCoord = HexenschachPanel.FIELD_NAMES[coord];

                        // Prüfen, ob die Koordinate existiert
                        if(analyzedBoard.boardHM.get(analyzedCoord) != null){

                            // Sachprüfung durchführen
                            String currentFigurePlayer = analyzedBoard.getFigureType(analyzedCoord);
                            if(currentFigurePlayer != null){                                                // Wenn Figur auf dem Feld ist:
                                int playerOfFigure = analyzedBoard.getPlayer(analyzedCoord);                // Spieler, dem die Figur gehört, anfordern
                                if(playerOfFigure == pCurrentPlayer                                         // Wenn Spieler gleich dem aktiven Spieler...
                                || playerOfFigure == pCurrentPlayer++){                                     // ...oder gleich dem folgenden Spieler:

                                    // Zugmöglichkeiten der Figur anfordern und prüfen, ob welche existieren
                                    TurnPossibility possibleFigureMove[] = analyzedBoard.calculateTurnPossibility(analyzedCoord); // Alle möglichen Züge der Figur anfordern
                                    if(possibleFigureMove != null){
                                        for(int i = 0; i < possibleFigureMove.length; i++){
                                            //Figuren-Koordinaten, die König bedrohen anfordern
                                            int index = 0;
                                            Iterator <String> TFItr = ThreateningFigures.iterator();

                                            while(TFItr.hasNext()){                                             // Pro Figur, die den König bedroht
                                                String currentCoord = TFItr.next();
                                                playerOfFigure = analyzedBoard.getPlayer(currentCoord);         // Spieler anfordern, dem die Figur gehört
                                                if(playerOfFigure != pCurrentPlayer){                           // Wenn Figur nicht vom aktiven Spieler ist:
                                                    TurnPossibility possibleFigureMove2[] = analyzedBoard.calculateTurnPossibility(currentCoord); // Zugmöglichkeiten der Figur anfordern

                                                    if(possibleFigureMove2 != null){
                                                        for(int j = 0; j < possibleFigureMove2.length; j++){        // Zugmöglichkeiten durchgehen
                                                            Board analyzedBoard2 = possibleFigureMove2[j].boardafter;
                                                            if(analyzedBoard2.getPlayer(currentCoord) != player){   // Wenn Figur nicht vom aktuellen Spieler:
                                                                int checkCheck[] = checked(analyzedBoard2);         // Schach-Status des aktuellen Spielers anfordern
                                                                if(checkCheck[player] == 1)                         // Wenn Spieler im Schach ist
                                                                    situationOf[player] = 1;                        // Spieler Schachmatt setzen
                                                                else{                                               // Sonst:
                                                                    situationOf[player] = 0;                        // Spieler ist nicht matt
                                                                    j = possibleFigureMove2.length + 1;             // Abbruchbed. Züge
                                                                    ThreateningFigures.clear();                     // Koordinatenliste leeren
                                                                    i = possibleFigureMove.length + 1;              // Abbruchbed. Züge
                                                                    coord = 99;                                     // Abbruchbed. Hashmapdurchlauf
                                                                }
                                                            }
                                                        }
                                                    }

                                                    // Prüfen, ob sich der König bewegen lässt
                                                    int kingMoveOf[] = kingMovePossible(analyzedBoard);
                                                    if(kingMoveOf[player-1] == 1)                  // Wenn Nein:
                                                        situationOf[player] = 1;                   // Schachmatt
                                                    else{                                          // Wenn ja:
                                                        situationOf[player] = 0;                   // nicht matt + alle weiteren Prüfungen abbrechen
                                                        ThreateningFigures.clear();
                                                        i = possibleFigureMove.length + 1;
                                                        coord = 99;
                                                    }
                                                }
                                                index++;    // Index für Koordinatenliste der bedrohten Figuren hochzählen
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // Bewertung muss noch!
       

        return situationOf;
    }

    /**
     * Bewertet einen Bauerntausch
     */
    protected int pawnTurn(){
        /*if(currentTP.pawnTurn = true)
            return ballance.valueOf("PawnTurn");*/
        return 0;
    }

    /**
     * Generiert Eröffnungsmuster für das Spiel
     * @param pCurrentBoard, das aktuelle Spielfeld
     * @param pCurrentPlayer, der aktive Spieler
     * @return Der auszuführende Zugvorschlag
     */
    public TurnPossibility openGame(Board pCurrentBoard, int pCurrentPlayer){

        TurnPossibility[] pawnTP;

        if(pCurrentPlayer == 1){
            if(pCurrentBoard.getFigure("J9").hasMoved == false){
                pawnTP = pCurrentBoard.calculateTurnPossibility("J9");
                return pawnTP[1];
            }
        }
        else if(pCurrentPlayer == 2){
            if(pCurrentBoard.getFigure("J9").hasMoved == false){
                pawnTP = pCurrentBoard.calculateTurnPossibility("Q4");
                return pawnTP[1];
            }
        }
        else if(pCurrentPlayer == 3){
            if(pCurrentBoard.getFigure("J9").hasMoved == false){
                pawnTP = pCurrentBoard.calculateTurnPossibility("F3");
                return pawnTP[1];
            }
        }

        return null;
    }
}
TOP

Related Classes of hexenschach.player.AiAlgorithm

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.