package useful;
import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.ListIterator;
import util.ChessfigureConstants;
/*
* Diese Klasse stellt Methoden zur Verfügung,
* um aus einer gegeben Schachspielfeldsituation,
* alle möglichen Folge-Schachfelder zu erstellen.
* @author Florian Hallensleben
*/
public class MoveGenerator implements Serializable
{
/**
* Generiert alle möglichen Folge-Schachfelder aus einem gegebenen Schachfeld.
*
* @param field das aktuelle Schachfeld
* @param colour Farbe des Spielers, der am Zug ist
* @return LinkedList aller möglichen Folge-Schachfelder.
*/
public LinkedList<HashMap<Integer, Byte>> generateMoves(HashMap<Integer, Byte> field, byte colour){
//Liste, in der alle Folge-Schachfelder gespeichert werden
LinkedList<HashMap<Integer, Byte>> nextMoves = new LinkedList<HashMap<Integer, Byte>>();
//Clonen des aktuellen Schachfelds
HashMap<Integer, Byte> b = new HashMap<Integer, Byte>();
b = (HashMap<Integer, Byte>)field.clone();
byte figureValue;
//alle Felder überprüfen
for(int i = 1; i <= 64; i++){
//falls Figur auf Feld steht
if(field.containsKey(i)){
//Wert der Figur zwischenspeichern
figureValue = field.get(i);
//falls Farbe der Figur gleich Spielerfarbe
if(getColour(figureValue) == colour){
//je nach Figurtyp muss die Figur anders gesetzt werden.
switch(getFigureType(figureValue)){
case 1:
nextMoves.addAll(movePawn(field, i, colour));
break;
case 2:
nextMoves.addAll(moveRook(field, i, colour));
break;
case 3:
nextMoves.addAll(moveKnight(field, i, colour));
break;
case 4:
nextMoves.addAll(moveBishop(field, i, colour));
break;
case 5:
nextMoves.addAll(moveQueen(field, i, colour));
break;
case 6:
nextMoves.addAll(moveKing(field, i , colour));
break;
default://throw NotAFigureException
break;
}//endswitch
}//endif
}//endif
}//endfor
return sortMoves(nextMoves);
}
//TODO: Bauernumwandlung
/**
* Liefert alle Folge-Schachfelder, die ein bestimmter Bauer auf dem übergebenen Feld ausführen kann.
* @param field zu betrachtendes Schachfeld
* @param key Key (= Feld) des zu bewegenden Bauerns in der HashMap
* @param colour Farbe des Spielers
* @return alle möglichen Folge-Schachfelder, die durch Bewegung des Bauerns enstehen können
*/
private LinkedList<HashMap<Integer, Byte>> movePawn(HashMap<Integer, Byte> field, int key, byte colour){
LinkedList<HashMap<Integer, Byte>> pawnMoves = new LinkedList<HashMap<Integer, Byte>>();
HashMap<Integer, Byte> newField = new HashMap<Integer, Byte>();
boolean change;// ein neues Feld nur hinzufügen, wenn sich etwas ändert
int sgn;
if(colour == ChessfigureConstants.WHITE){
sgn = 1;
}
else{
sgn = -1;
}
//zwei nach vorne, ein nach vorne und schlagen prüfen beachten
for(int a = 0; a < 4; a++){
change = false;
newField = (HashMap<Integer, Byte>)field.clone();
switch(a){
case 0://zwei Felder vor (noch nicht bewegt)
//Feld dazwischen frei und Zielfeld frei
if(!wasMoved(field.get(key))
&& !field.containsKey(key + sgn*16)
&& !field.containsKey(key + sgn* 8)){
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + sgn*16, setMoved(newField.remove(key)));
change = true;
}
break;
case 1://ein Feld vor, Zielfeld frei, Grenzen nicht überschritten
if(!field.containsKey(key + sgn*8)
&& 0 < key + sgn*8 && key + sgn*8 < 65){
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + sgn*8, setMoved(newField.remove(key)));
change = true;
}
break;
case 2://in Spielrichtung rechts schlagen
//Feldgrenzen werden überschritten
if((sgn == -1 && key % 8 == 1)
|| (sgn == 1 && key % 8 == 0)){
break;
}
//Zielfeld mit gegnerischer Figur besetzt
if(field.containsKey(key + sgn*9)
&& getColour(field.get(key + sgn*9)) != colour){
//gegnerische Figur entfernen
newField.remove(key + sgn*9);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + sgn*9, setMoved(newField.remove(key)));
change = true;
}
break;
case 3://in Spielrichtung links schlagen
//Feldgrenzen werden überschritten
if((sgn == -1 && key % 8 == 0)
|| (sgn == 1 && key % 8 == 1)){
break;
}
//Zielfeld mit gegnerischer Figur besetzt
if(field.containsKey(key + sgn*7)
&& getColour(field.get(key + sgn*7)) != colour){
//gegnerische Figur entfernen
newField.remove(key + sgn*7);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + sgn*7, setMoved(newField.remove(key)));
change = true;
}
break;
default:
break;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(change && !isCheck(newField, colour)){
pawnMoves.add(newField);
// System.out.println("added Pawn");
}
}
return pawnMoves;
}
/**
* Liefert alle Folge-Schachfelder, die ein bestimmter Turm auf dem übergebenen Feld ausführen kann.
* @param field zu betrachtendes Schachfeld
* @param key Key (= Feld) des zu bewegenden Turms in der HashMap
* @param colour Farbe des Spielers
* @return alle möglichen Folge-Schachfelder, die durch Bewegung des Turms enstehen können
*/
private LinkedList<HashMap<Integer, Byte>> moveRook(HashMap<Integer, Byte> field, int key, byte colour){
LinkedList<HashMap<Integer, Byte>> rookMoves = new LinkedList<HashMap<Integer, Byte>>();
HashMap<Integer, Byte> newField = new HashMap<Integer, Byte>();
boolean captured = false;
//Nach oben bewegen
for(int i = 1; i < 8; i++){
newField = (HashMap<Integer, Byte>)field.clone();
//Grenze nicht überschritten
if(key + 8*i > 64){
break;
}
//Feld frei
if(!field.containsKey(key + 8*i)){
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + 8*i, setMoved(newField.remove(key)));
}
//Feld mit eigener Figur belegt
else if(getColour(field.get(key + 8*i)) == colour){
break;
}
//Feld mit fremder Figur belegt
else if(getColour(field.get(key + 8*i)) != colour){
//gegnerische Figur entfernen
newField.remove(key + 8*i);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + 8*i, setMoved(newField.remove(key)));
//eine Figur wurde geschlagen
captured = true;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
rookMoves.add(newField);
// System.out.println("added Rook");
}
//falls Figur geschlagen wurde, darf Schlagende Figur nicht weiterziehen
if(captured){
break;
}
}
captured = false;
//Nach unten bewegen
for(int i = -1; i > -8; i--){
newField = (HashMap<Integer, Byte>)field.clone();
//Grenze nicht überschritten
if(key + 8*i < 1){
break;
}
//Feld frei
if(!field.containsKey(key + 8*i)){
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + 8*i, setMoved(newField.remove(key)));
}
//Feld mit eigener Figur belegt
else if(getColour(field.get(key + 8*i)) == colour){
break;
}
//Feld mit fremder Figur belegt
else if(getColour(field.get(key + 8*i)) != colour){
//gegnerische Figur entfernen
newField.remove(key + 8*i);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + 8*i, setMoved(newField.remove(key)));
captured = true;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
rookMoves.add(newField);
// System.out.println("added Rook");
}
//falls Figur geschlagen wurde, darf Schlagende Figur nicht weiterziehen
if(captured){
break;
}
}
captured = false;
//Nach rechts bewegen
for(int i = 1; i < 8; i++){
newField = (HashMap<Integer, Byte>)field.clone();
//Grenze nicht überschreiten
if((key + i) % 8 == 1){
break;
}
//Feld frei
if(!field.containsKey(key + i)){
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + i, setMoved(newField.remove(key)));
}
//Feld mit eigener Figur belegt
else if(getColour(field.get(key + i)) == colour){
break;
}
//Feld mit fremder Figur belegt
else if(getColour(field.get(key + i)) != colour){
//gegnerische Figur entfernen
newField.remove(key + i);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + i, setMoved(newField.remove(key)));
captured = true;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
rookMoves.add(newField);
// System.out.println("added Rook");
}
//falls Figur geschlagen wurde, darf Schlagende Figur nicht weiterziehen
if(captured){
break;
}
}
captured = false;
//Nach links bewegen
for(int i = -1; i > -8; i--){
newField = (HashMap<Integer, Byte>)field.clone();
//Grenze nicht überschreiten
if((key + i) % 8 == 0){
break;
}
//Feld frei
if(!field.containsKey(key + i)){
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + i, setMoved(newField.remove(key)));
}
//Feld mit eigener Figur belegt
else if(getColour(field.get(key + i)) == colour){
break;
}
//Feld mit fremder Figur belegt
else if(getColour(field.get(key + i)) != colour){
//gegnerische Figur entfernen
newField.remove(key + i);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + i, setMoved(newField.remove(key)));
captured = true;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
rookMoves.add(newField);
// System.out.println("added Rook");
}
//falls Figur geschlagen wurde, darf Schlagende Figur nicht weiterziehen
if(captured){
break;
}
}
return rookMoves;
}
/**
* Liefert alle Folge-Schachfelder, die ein bestimmter Springer auf dem übergebenen Feld ausführen kann.
* @param field zu betrachtendes Schachfeld
* @param key Key (= Feld) des zu bewegenden Springers in der HashMap
* @param colour Farbe des Spielers
* @return alle möglichen Folge-Schachfelder, die durch Bewegung des Springers enstehen können
*/
private LinkedList<HashMap<Integer, Byte>> moveKnight(HashMap<Integer, Byte> field, int key, byte colour){
LinkedList<HashMap<Integer, Byte>> knightMoves = new LinkedList<HashMap<Integer, Byte>>();
HashMap<Integer, Byte> newField = new HashMap<Integer, Byte>();
int change; //ein neues Feld nur hinzufügen, wenn sich etwas ändert
for(int a = 1; a < 9; a++){
change = -1;
newField = (HashMap<Integer, Byte>)field.clone();
switch(a){
case 1: //zwei links einen hoch(+6)
//Grenze überschritten, Zielfeld durch eigene Figur belegt
if((key - 1) % 8 < 2
|| key > 56
|| (field.containsKey(key + 6) && getColour(field.get(key + 6)) == colour)){
break;
}
change = 6;
break;
case 2: //zwei rechts einen runter(-6)
if((key - 1) % 8 > 5
|| key < 9
|| (field.containsKey(key - 6) && getColour(field.get(key - 6)) == colour)){
break;
}
change = -6;
break;
case 3: //zwei rechts einen hoch(+10)
if((key - 1) % 8 > 5
|| key > 56
|| (field.containsKey(key + 10) && getColour(field.get(key + 10)) == colour)){
break;
}
change = 10;
break;
case 4: //zwei links einen runter(-10)
if((key - 1) % 8 < 2
|| key < 9
|| (field.containsKey(key -10) && getColour(field.get(key -10)) == colour)){
break;
}
change = -10;
break;
case 5: //zwei hoch einen links(+15)
if(key % 8 == 1
|| key > 48
|| (field.containsKey(key + 15) && getColour(field.get(key + 15)) == colour)){
break;
}
change = 15;
break;
case 6: //zwei runter einen rechts(-15)
if(key % 8 == 0
|| key < 17
|| (field.containsKey(key - 15) && getColour(field.get(key - 15)) == colour)){
break;
}
change = -15;
break;
case 7: //zwei hoch einen rechts(+17)
if(key % 8 == 0
|| key > 48
|| (field.containsKey(key + 17) && getColour(field.get(key + 17)) == colour)){
break;
}
change = 17;
break;
case 8: //zwei runter einen links(-17)
if(key % 8 == 1
|| key < 17
|| (field.containsKey(key - 17) && getColour(field.get(key - 17)) == colour)){
break;
}
change = -17;
break;
default: //throw something went wrong exception
break;
}
//obige Bedingung erfüllt, Zielfeld frei
if(change != -1 && !field.containsKey(key + change)){
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + change, setMoved(newField.remove(key)));
}
else if(change != -1 && getColour(field.get(key + change)) != colour){
//gegnerische Figur entfernen
newField.remove(key + change);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + change, setMoved(newField.remove(key)));
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(change != -1 && !isCheck(newField, colour)){
knightMoves.add(newField);
// System.out.println("added Knight");
}
}
return knightMoves;
}
/**
* Liefert alle Folge-Schachfelder, die ein bestimmter Läufer auf dem übergebenen Feld ausführen kann.
* @param field zu betrachtendes Schachfeld
* @param key Key (= Feld) des zu bewegenden Läufers in der HashMap
* @param colour Farbe des Spielers
* @return alle möglichen Folge-Schachfelder, die durch Bewegung des Läufers enstehen können
*/
private LinkedList<HashMap<Integer, Byte>> moveBishop(HashMap<Integer, Byte> field, int key, byte colour){
LinkedList<HashMap<Integer, Byte>> bishopMoves = new LinkedList<HashMap<Integer, Byte>>();
HashMap<Integer, Byte> newField = new HashMap<Integer, Byte>();
boolean captured = false;
//Nach oben rechts bewegen
for(int i = 1; i < 8; i++){
newField = (HashMap<Integer, Byte>)field.clone();
//Grenze nicht überschritten
if(key + 9*i > 64
|| (key + 9*i) % 8 == 1){
break;
}
//Feld frei
if(!field.containsKey(key + 9*i)){
newField.put(key + 9*i, setMoved(newField.remove(key)));
}
//Feld mit eigener Figur belegt
else if(getColour(field.get(key + 9*i)) == colour){
break;
}
//Feld mit fremder Figur belegt
else if(getColour(field.get(key + 9*i)) != colour){
//gegnerische Figur entfernen
newField.remove(key + 9*i);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + 9*i, setMoved(newField.remove(key)));
captured = true;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
bishopMoves.add(newField);
// System.out.println("added Bishop");
}
//falls Figur geschlagen wurde, darf Schlagende Figur nicht weiterziehen
if(captured){
break;
}
}
captured = false;
//nach oben links bewegen
for(int i = 1; i < 8; i++){
newField = (HashMap<Integer, Byte>)field.clone();
//Grenze nicht überschritten
if(key + 7*i > 64
|| (key + 7*i) % 8 == 0){
break;
}
//Feld frei
if(!field.containsKey(key + 7*i)){
newField.put(key + 7*i, setMoved(newField.remove(key)));
}
//Feld mit eigener Figur belegt
else if(getColour(field.get(key + 7*i)) == colour){
break;
}
//Feld mit fremder Figur belegt
else if(getColour(field.get(key + 7*i)) != colour){
//gegnerische Figur entfernen
newField.remove(key + 7*i);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + 7*i, setMoved(newField.remove(key)));
captured = true;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
bishopMoves.add(newField);
// System.out.println("added Bishop");
}
//falls Figur geschlagen wurde, darf Schlagende Figur nicht weiterziehen
if(captured){
break;
}
}
captured = false;
//nach unten rechts bewegen
for(int i = 1; i < 8; i++){
newField = (HashMap<Integer, Byte>)field.clone();
//Grenze nicht überschritten
if(key - 7*i < 1
|| (key - 7*i) % 8 == 1){
break;
}
//Feld frei
if(!field.containsKey(key - 7*i)){
newField.put(key - 7*i, setMoved(newField.remove(key)));
}
//Feld mit eigener Figur belegt
else if(getColour(field.get(key - 7*i)) == colour){
break;
}
//Feld mit fremder Figur belegt
else if(getColour(field.get(key - 7*i)) != colour){
//gegnerische Figur entfernen
newField.remove(key - 7*i);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key - 7*i, setMoved(newField.remove(key)));
captured = true;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
bishopMoves.add(newField);
// System.out.println("added Bishop");
}
//falls Figur geschlagen wurde, darf Schlagende Figur nicht weiterziehen
if(captured){
break;
}
}
captured = false;
//nach unten links bewegen
for(int i = 1; i < 8; i++){
newField = (HashMap<Integer, Byte>)field.clone();
//Grenze nicht überschritten
if(key - 9*i < 1
|| (key - 9*i) % 8 == 0){
break;
}
//Feld frei
if(!field.containsKey(key - 9*i)){
newField.put(key - 9*i, setMoved(newField.remove(key)));
}
//Feld mit eigener Figur belegt
else if(getColour(field.get(key - 9*i)) == colour){
break;
}
//Feld mit fremder Figur belegt
else if(getColour(field.get(key - 9*i)) != colour){
//gegnerische Figur entfernen
newField.remove(key - 9*i);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key - 9*i, setMoved(newField.remove(key)));
captured = true;
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
bishopMoves.add(newField);
// System.out.println("added Bishop");
}
//falls Figur geschlagen wurde, darf Schlagende Figur nicht weiterziehen
if(captured){
break;
}
}
return bishopMoves;
}
/**
* Liefert alle Folge-Schachfelder, die die eigene Königin auf dem übergebenen Feld ausführen kann.
* @param field zu betrachtendes Schachfeld
* @param key Key (= Feld) der zu bewegenden Königin in der HashMap
* @param colour Farbe des Spielers
* @return alle möglichen Folge-Schachfelder, die durch Bewegung der Königin enstehen können
*/
private LinkedList<HashMap<Integer, Byte>> moveQueen(HashMap<Integer, Byte> field, int key, byte colour){
LinkedList<HashMap<Integer, Byte>> queenMoves = new LinkedList<HashMap<Integer, Byte>>();
//Königin kann solche Züge ausführen, die Turm und Läufer ausführen können
// System.out.println("<Queen begin>");
queenMoves.addAll(moveRook(field, key, colour));
queenMoves.addAll(moveBishop(field, key, colour));
// System.out.println("<Queen end>");
return queenMoves;
}
/**
* Liefert alle Folge-Schachfelder, die der eigene König auf dem übergebenen Feld ausführen kann.
* @param field zu betrachtendes Schachfeld
* @param key Key (=Feld) des zu bewegenden Königs in der HashMap
* @param colour Farbe des Spielers
* @return alle möglichen Folge-Schachfelder, die durch Bewegung des Königs enstehen können
*/
private LinkedList<HashMap<Integer, Byte>> moveKing(HashMap<Integer, Byte> field, int key, byte colour){
LinkedList<HashMap<Integer, Byte>> kingMoves = new LinkedList<HashMap<Integer, Byte>>();
HashMap<Integer, Byte> newField = new HashMap<Integer, Byte>();
int change; //ein neues Feld nur hinzufügen, wenn sich etwas ändert
for(int a = 1; a < 9; a++){
change = 0;
newField = (HashMap<Integer, Byte>)field.clone();
switch(a){
case 1: //nach oben
//Grenze überschritten, Zielfeld durch eigene Figur belegt
if((key + 8) > 64
|| (field.containsKey(key + 8) && getColour(field.get(key + 8)) == colour)){
break;
}
change = 8;
break;
case 2: //nach rechts nach oben
if((key + 9) > 64
|| (key % 8) == 0
|| (field.containsKey(key + 9) && getColour(field.get(key + 9)) == colour)){
break;
}
change = 9;
break;
case 3: //nach rechts
if((key % 8) == 0
|| (field.containsKey(key + 1) && getColour(field.get(key + 1)) == colour)){
break;
}
change = 1;
break;
case 4: //nach rechts unten
if((key - 7) < 1
|| (key % 8) == 0
|| (field.containsKey(key - 7) && getColour(field.get(key - 7)) == colour)){
break;
}
change = -7;
break;
case 5: //nach unten
if((key - 8) < 1
|| (field.containsKey(key - 8) && getColour(field.get(key - 8)) == colour)){
break;
}
change = -8;
break;
case 6: //nach links unten
if((key % 8) == 1
|| (key - 9) < 1
|| (field.containsKey(key - 9) && getColour(field.get(key - 9)) == colour)){
break;
}
change = -9;
break;
case 7: //nach links
if((key % 8) == 1
|| (field.containsKey(key - 1) && getColour(field.get(key - 1)) == colour)){
break;
}
change = -1;
break;
case 8: //nach links oben
if(key % 8 == 1
|| (key + 7) > 64
|| (field.containsKey(key + 7) && getColour(field.get(key + 7)) == colour)){
break;
}
change = 7;
break;
default: //throw something went wrong exception
break;
}
//obige Bedingung erfüllt, Zielfeld frei
if(change != 0 && !field.containsKey(key + change)){
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + change, setMoved(newField.remove(key)));
}
else if(change != 0 && getColour(field.get(key + change)) != colour){
//gegnerische Figur entfernen
newField.remove(key + change);
//alten Wert mit neuem Feld assozieren, gleichzeitig altes Feld löschen
newField.put(key + change, setMoved(newField.remove(key)));
}
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(change != 0 && !isCheck(newField, colour)){
kingMoves.add(newField);
// System.out.println("added King");
}
}
newField = (HashMap<Integer, Byte>)field.clone();
//Rochade rechtsseitig (kurze Rochade)
//König nicht im Schach, König und Turm nicht bewegt, Zwischenfelder frei
if(!isCheck(field, colour)
&& !wasMoved(field.get(key))
&& field.containsKey(key + 3)
&& getColour(field.get(key + 3)) == colour
&& !wasMoved(field.get(key + 3))
&& !field.containsKey(key + 1)
&& !field.containsKey(key + 2)){
newField.put(key + 1, newField.remove(key));
//vom König zu überquerendes Feld nicht bedroht
if(!isCheck(newField, colour)){
//König auf richtige Position setzen
newField.put(key + 2, newField.remove(key + 1));
newField.put(key + 1, newField.remove(key + 3));
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
kingMoves.add(newField);
// System.out.println("added kingSideCastling");
}
}
}
newField = (HashMap<Integer, Byte>)field.clone();
//Rochade linksseitig (lange Rochade)
//König nicht im Schach, König und Turm nicht bewegt, Zwischenfelder frei
if(!isCheck(field, colour)
&& !wasMoved(field.get(key))
&& field.containsKey(key - 4)
&& getColour(field.get(key - 4)) == colour
&& !wasMoved(field.get(key - 4))
&& !field.containsKey(key - 1)
&& !field.containsKey(key - 2)
&& !field.containsKey(key - 3)){
newField.put(key - 1, newField.remove(key));
//vom König zu überquerendes Feld nicht bedroht
if(!isCheck(newField, colour)){
//König auf richtige Position setzen
newField.put(key - 2, newField.remove(key - 1));
newField.put(key - 1, newField.remove(key - 4));
//neues Feld hinzufügen, falls dadurch nicht in Schach geraten
if(!isCheck(newField, colour)){
kingMoves.add(newField);
// System.out.println("added queenSideCastling");
}
}
}
return kingMoves;
}
/**
* Überprüft ein Spielfeld darauf, ob der König der übergebenen Farbe im Schach steht.
* @param field Schachfeld, dass auf eine Schachsituation geprüft werden soll
* @param colour Farbe des Spielers, der den letzten Zug gemacht hat
* @return true, falls der Spieler im Schach steht, false sonst
*/
private boolean isCheck(HashMap<Integer, Byte> field, byte colour){
byte kingValue;
int key = 0;
byte figType;
for(int i = 1; i < 65; i++){
//falls König der Spielerfarbe auf dem Feld steht, Key und Wert merken
if(field.containsKey(i)
&& getColour(field.get(i)) == colour
&& getFigureType(field.get(i)) == ChessfigureConstants.KING){
key = i;
kingValue = field.get(key);
}
}
//x-Achse prüfen
//nach links
for(int j = 1; (key - j) % 8 != 0; j++){
//wenn Feld leer, weitermachen
if(!field.containsKey(key - j)){
continue;
}
//wenn Feld eigene Figur enthält, aufhören Reihe zu prüfen
if(getColour(field.get(key - j)) == colour){
break;
}
figType = getFigureType(field.get(key - j));
//im Schach, wenn eine bestimmte Figur auf dem Feld steht
if(figType == ChessfigureConstants.QUEEN
|| figType == ChessfigureConstants.ROOK
|| (figType == ChessfigureConstants.KING && j == 1)){
return true;
}
else{
break;
}
}
//nach rechts
for(int j = 1; (key + j) % 8 != 1; j++){
//wenn Feld leer, weitermachen
if(!field.containsKey(key + j)){
continue;
}
//wenn Feld eigene Figur enthält, aufhören Reihe zu prüfen
if(getColour(field.get(key + j)) == colour){
break;
}
figType = getFigureType(field.get(key + j));
//im Schach, wenn eine bestimmte Figur auf dem Feld steht
if(figType == ChessfigureConstants.QUEEN
|| figType == ChessfigureConstants.ROOK
|| (figType == ChessfigureConstants.KING && j == 1)){
return true;
}
else{
break;
}
}
//y-Achse prüfen
//nach oben
for(int j = 1; key + 8*j < 65; j++){
//wenn Feld leer, weitermachen
if(!field.containsKey(key + 8*j)){
continue;
}
//wenn Feld eigene Figur enthält, aufhören Reihe zu prüfen
if(getColour(field.get(key + 8*j)) == colour){
break;
}
figType = getFigureType(field.get(key + 8*j));
//im Schach, wenn eine bestimmte Figur auf dem Feld steht
if(figType == ChessfigureConstants.QUEEN
|| figType == ChessfigureConstants.ROOK
|| (figType == ChessfigureConstants.KING && j == 1)){
return true;
}
else{
break;
}
}
//nach unten
for(int j = 1; key - 8*j > 0; j++){
//wenn Feld leer, weitermachen
if(!field.containsKey(key - 8*j)){
continue;
}
//wenn Feld eigene Figur enthält, aufhören Reihe zu prüfen
if(getColour(field.get(key - 8*j)) == colour){
break;
}
figType = getFigureType(field.get(key - 8*j));
//im Schach, wenn eine bestimmte Figur auf dem Feld steht
if(figType == ChessfigureConstants.QUEEN
|| figType == ChessfigureConstants.ROOK
|| (figType == ChessfigureConstants.KING && j == 1)){
return true;
}
else{
break;
}
}
//schräg prüfen
//nach rechts oben
for(int j = 1; key + 9*j < 65 && (key + 9*j) % 8 != 1; j++){
//wenn Feld leer, weitermachen
if(!field.containsKey(key + 9*j)){
continue;
}
//wenn Feld eigene Figur enthält, aufhören Reihe zu prüfen
if(getColour(field.get(key + 9*j)) == colour){
break;
}
figType = getFigureType(field.get(key + 9*j));
//im Schach, wenn eine bestimmte Figur auf dem Feld steht
if(figType == ChessfigureConstants.QUEEN
|| figType == ChessfigureConstants.BISHOP
|| (figType == ChessfigureConstants.KING && j == 1)
|| (figType == ChessfigureConstants.PAWN && j == 1
&& getColour(field.get(key + 9*j)) == ChessfigureConstants.BLACK)){
return true;
}
else{
break;
}
}
//nach rechts unten
for(int j = 1; key - 7*j > 0 && (key - 7*j) % 8 != 1; j++){
//wenn Feld leer, weitermachen
if(!field.containsKey(key - 7*j)){
continue;
}
//wenn Feld eigene Figur enthält, aufhören Reihe zu prüfen
if(getColour(field.get(key - 7*j)) == colour){
break;
}
figType = getFigureType(field.get(key - 7*j));
//im Schach, wenn eine bestimmte Figur auf dem Feld steht
if(figType == ChessfigureConstants.QUEEN
|| figType == ChessfigureConstants.BISHOP
|| (figType == ChessfigureConstants.KING && j == 1)
|| (figType == ChessfigureConstants.PAWN && j == 1
&& getColour(field.get(key - 7*j)) == ChessfigureConstants.WHITE)){
return true;
}
else{
break;
}
}
//nach links oben
for(int j = 1; key + 7*j < 65 && (key + 7*j) % 8 != 0; j++){
//wenn Feld leer, weitermachen
if(!field.containsKey(key + 7*j)){
continue;
}
//wenn Feld eigene Figur enthält, aufhören Reihe zu prüfen
if(getColour(field.get(key + 7*j)) == colour){
break;
}
figType = getFigureType(field.get(key + 7*j));
//im Schach, wenn eine bestimmte Figur auf dem Feld steht
if(figType == ChessfigureConstants.QUEEN
|| figType == ChessfigureConstants.BISHOP
|| (figType == ChessfigureConstants.KING && j == 1)
|| (figType == ChessfigureConstants.PAWN && j == 1
&& getColour(field.get(key + 7*j)) == ChessfigureConstants.BLACK)){
return true;
}
else{
break;
}
}
//nach links unten
for(int j = 1; key - 9*j > 0 && (key - 9*j) % 8 != 0; j++){
//wenn Feld leer, weitermachen
if(!field.containsKey(key - 9*j)){
continue;
}
//wenn Feld eigene Figur enthält, aufhören Reihe zu prüfen
if(getColour(field.get(key - 9*j)) == colour){
break;
}
figType = getFigureType(field.get(key - 9*j));
//im Schach, wenn eine bestimmte Figur auf dem Feld steht
if(figType == ChessfigureConstants.QUEEN
|| figType == ChessfigureConstants.BISHOP
|| (figType == ChessfigureConstants.KING && j == 1)
|| (figType == ChessfigureConstants.PAWN && j == 1
&& getColour(field.get(key - 9*j)) == ChessfigureConstants.WHITE)){
return true;
}
else{
break;
}
}
//Springer prüfen
int change;
for(int a = 1; a < 9; a++){
change = 0;
switch(a){
case 1: //zwei links einen hoch(+6)
//Grenze überschritten, Zielfeld durch eigene Figur belegt
if((key - 1) % 8 < 2
|| key > 56
|| (field.containsKey(key + 6) && getColour(field.get(key + 6)) == colour)){
break;
}
change = 6;
break;
case 2: //zwei rechts einen runter(-6)
if((key - 1) % 8 > 5
|| key < 9
|| (field.containsKey(key - 6) && getColour(field.get(key - 6)) == colour)){
break;
}
change = -6;
break;
case 3: //zwei rechts einen hoch(+10)
if((key - 1) % 8 > 5
|| key > 56
|| (field.containsKey(key + 10) && getColour(field.get(key + 10)) == colour)){
break;
}
change = 10;
break;
case 4: //zwei links einen runter(-10)
if((key - 1) % 8 < 2
|| key < 9
|| (field.containsKey(key -10) && getColour(field.get(key -10)) == colour)){
break;
}
change = -10;
break;
case 5: //zwei hoch einen links(+15)
if(key % 8 == 1
|| key > 48
|| (field.containsKey(key + 15) && getColour(field.get(key + 15)) == colour)){
break;
}
change = 15;
break;
case 6: //zwei runter einen rechts(-15)
if(key % 8 == 0
|| key < 17
|| (field.containsKey(key - 15) && getColour(field.get(key - 15)) == colour)){
break;
}
change = -15;
break;
case 7: //zwei hoch einen rechts(+17)
if(key % 8 == 0
|| key > 48
|| (field.containsKey(key + 17) && getColour(field.get(key + 17)) == colour)){
break;
}
change = 17;
break;
case 8: //zwei runter einen links(-17)
if(key % 8 == 1
|| key < 17
|| (field.containsKey(key - 17) && getColour(field.get(key - 17)) == colour)){
break;
}
change = -17;
break;
default: //throw something went wrong exception
break;
}
//wenn Springer auf der Position, Schach
if(change != 0
&& field.containsKey(key + change)
&& getFigureType(field.get(key + change)) == ChessfigureConstants.KNIGHT){
return true;
}
}
return false;
}
/**
* Extrahiert die Farbe aus dem Wert einer Figur.
* @param figureValue Wert der Figur, deren Farbe ermittelt werden soll
* @return Farbe der Figur (entsprechend ChessfigureConstants)
*/
private byte getColour(byte value){
return (byte)((value >> 3) % 2);
}
/**
* Extrahiert den Typ aus dem Wert einer Figur.
* @param value Wert der Figur, deren Typ ermittelt werden soll
* @return Typ der Figur (entsprechend ChessfigureConstants)
*/
private byte getFigureType(byte value){
return (byte)(value % 8);
}
/**
* Prüft, ob eine Figur bereits bewegt wurde.
* @param value Wert der Figur, die überprüft werden soll
* @return true, falls Figur bereits bewegt wurde, false sonst
*/
private boolean wasMoved(byte value){
return (value >> 4) == 1;
}
/**
* Setzt das Bit für bewegt bzw. nicht bewegt auf 1.
* @param value Wert der Figur, die bewegt wird.
* @return Wert der Figur mit "bewegt-Bit" auf 1
*/
private byte setMoved(byte value){
return (byte)((value % 16) + 16);
}
/**
* Sortiert die Folge-Schachfelder nach bestimmten Kriterien (momentan Anzahl der Figuren).
* @param moves vom MoveGenerator berechnete Folge-Schachfelder eines beliebigen Schachfelds
* @return sortierte Folge-Schachfelder
*/
public LinkedList<HashMap<Integer, Byte>> sortMoves(LinkedList<HashMap<Integer, Byte>> moves){
LinkedList<HashMap<Integer, Byte>> sortedMoves = new LinkedList<HashMap<Integer, Byte>>();
int max = 0;
if(!moves.isEmpty()){
max = moves.get(0).size();
}
for(int i = 0; i < moves.size(); i++){
//die Größe der zur Zeit größten HashMap merken;
if(moves.get(i).size() > max){
max = moves.get(i).size();
}
//Wenn Größe der HashMap kleiner ist als das Maximum, vorne einfügen
if(moves.get(i).size() < max){
sortedMoves.push(moves.get(i));
}
//sonst hinten anhängen
else{
sortedMoves.add(moves.get(i));
}
}
return sortedMoves;
}
public static void main(String[] args){
HashMap<Integer, Byte> test = new HashMap<Integer, Byte>();
test.put(1, (byte)2); //linker, weißer Turm
test.put(2, (byte)3); //linker, weißer Springer
test.put(3, (byte)4); //linker, weißer Läufer
test.put(4, (byte)5); //weiße Dame
test.put(5, (byte)6); //weißer König
test.put(6, (byte)4); //rechter, weißer Läufer
test.put(7, (byte)3); //rechter, weißer Springer
test.put(8, (byte)2); //rechter, weißer Turm
test.put(9, (byte)1); //weißer Bauer
test.put(10, (byte)1); //weißer Bauer
test.put(11, (byte)1); //weißer Bauer
test.put(12, (byte)1); //weißer Bauer
test.put(13, (byte)1); //weißer Bauer
test.put(14, (byte)1); //weißer Bauer
test.put(15, (byte)1); //weißer Bauer
test.put(16, (byte)1); //weißer Bauer
test.put(49, (byte)9); //schwarzer Bauer
test.put(50, (byte)9); //schwarzer Bauer
test.put(51, (byte)9); //schwarzer Bauer
test.put(52, (byte)9); //schwarzer Bauer
test.put(53, (byte)9); //schwarzer Bauer
test.put(54, (byte)9); //schwarzer Bauer
test.put(55, (byte)9); //schwarzer Bauer
test.put(56, (byte)9); //schwarzer Bauer
test.put(57, (byte)10); //rechter, schwarzer Turm
test.put(58, (byte)11); //rechter, schwarzer Springer
test.put(59, (byte)12); //rechter, schwarzer Läufer
test.put(60, (byte)13); //schwarze Dame
test.put(61, (byte)14); //schwarzer König
test.put(62, (byte)12); //linker, schwarzer Läufer
test.put(63, (byte)11); //linker, schwarzer Springer
test.put(64, (byte)10); //linker, schwarzer Turm
MoveGenerator toast = new MoveGenerator();
// System.out.println(s.fieldToString(test));
LinkedList<HashMap<Integer, Byte>> a = new LinkedList<HashMap<Integer, Byte>>();
LinkedList<HashMap<Integer, Byte>> b = new LinkedList<HashMap<Integer, Byte>>();
LinkedList<HashMap<Integer, Byte>> c = new LinkedList<HashMap<Integer, Byte>>();
LinkedList<HashMap<Integer, Byte>> d = new LinkedList<HashMap<Integer, Byte>>();
LinkedList<HashMap<Integer, Byte>> e = new LinkedList<HashMap<Integer, Byte>>();
LinkedList<HashMap<Integer, Byte>> f = new LinkedList<HashMap<Integer, Byte>>();
int v, w, x, y, z;
a = toast.generateMoves(test, (byte)1);
v = a.size();
long time = System.currentTimeMillis();
// for(int i = 1; i <= v; i++){
// b = toast.generateMoves(a.poll(), (byte)0);
// w = b.size();
//// System.out.println(System.currentTimeMillis() - time);
// for(int j = 1; j <= w; j++){
// c = toast.generateMoves(b.poll(), (byte)1);
// x = c.size();
//// System.out.println((System.currentTimeMillis() - time)/1000);
// for(int k = 1; k <= x; k++){
// d = toast.generateMoves(c.poll(), (byte)0);
// y = d.size();
//// System.out.println(System.currentTimeMillis() - time);
// for(int l = 1; l <= y; l++){
// e = toast.generateMoves(d.poll(), (byte)1);
// z = e.size();
//// System.out.println(z);
// for(int m = 1; m <= z; m++){
// f = toast.generateMoves(e.poll(), (byte)0);
//// System.out.println(System.currentTimeMillis() - time);
//// System.out.println(f.size());
//// System.out.println(m);
// }
// }
// }
// }
// }
// for(int i = 1; i <= x; i++){
// System.out.println("\n --------- \n");
// System.out.println(TextChessField.fieldToString(xyz.poll()));
// }
//
// ListIterator<HashMap<Integer, Byte>> itr = xyz.listIterator();
// while(itr.hasNext())
// {
// System.out.println(TextChessField.fieldToString(itr.next()));
// System.out.println("\n\n-----\n\n");
// }
}
}