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ö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;
}
}