Baier_Hendrik_AnhA.txt

/*
* Vier Gewinnt
* Version: 18.4.2006
*
* Hendrik Baier
*
*/

import java.io.*;
import java.lang.Math;
import java.util.BitSet;
import java.util.Random;


/*
* Die Klasse VierGewinnt führt das Spiel durch.
* Ihre wichtigsten Attribute sind die beiden Spieler white, black und das Spielfeld game,
* ihre zentrale Methode void playGame().
*/

public class VierGewinnt {

int whitemoves = 0;
int blackmoves = 0;
Position game;
Player white, black;
PrintWriter out;

/*
* Der Aufruf von main() erfolgt mit zwei oder drei Argumenten: ersterSpieler zweiterSpieler [Startposition],
* wobei ersterSpieler = c | m, zweiterSpieler = c | m (jeweils für Computerspieler oder menschlichen Spieler)
* und Startposition = Dateiname eines Textfiles mit der gewünschten Anfangsstellung des Spiels.
* Default:
* 0000000
* 0000000
* 0000000
* 0000000
* 0000000
* 0000000
* w
*/

public static void main(String args[]) throws java.io.IOException {

Position currentgame;
Player first;
Player second;

if(args.length == 3) {
currentgame = new Position(args[2]);
System.out.println(currentgame);
System.out.println();
} else {
currentgame = new Position();
System.out.println(currentgame);
System.out.println();
}

if(args[0].equals("c")) {
first = new ComputerPlayer(Position.WHITE, "Milton", true, false);
} else if(args[0].equals("m")) {
first = new HumanPlayer(Position.WHITE, "Mensch");
} else {
System.out.println("Bitte Mensch (m) oder Computer (c) als Player eins auswaehlen!");
return;
}
if(args[1].equals("c")) {
second = new ComputerPlayer(Position.BLACK, "Milton", true, false);
} else if(args[1].equals("m")) {
second = new HumanPlayer(Position.BLACK, "Mensch");
} else {
System.out.println("Bitte Mensch (m) oder Computer (c) als Player zwei auswaehlen!");
return;
}

VierGewinnt match = new VierGewinnt(first, second, currentgame);
match.playGame();

}

/*
* In game.txt schreibt VierGewinnt ein kurzes Protokoll jedes Spiels.
*/

public VierGewinnt(Player white, Player black, Position game) throws java.io.IOException {
this.black = black;
this.white = white;
this.game = game;
out = new PrintWriter(new FileWriter("game.txt", true), true);
}

private void playGame() throws IOException{

if(game.isWon(Position.WHITE) && game.isWon(Position.BLACK)) {
System.out.println("Diese Spiel ist bereits entschieden. Gewinner unklar.");
return;
}

if(game.isWon(Position.WHITE)) {
System.out.println("Diese Spiel ist bereits entschieden. Weiss gewinnt.");
return;
}

if(game.isWon(Position.BLACK)) {
System.out.println("Diese Spiel ist bereits entschieden. Schwarz gewinnt.");
return;
}

if(game.isDraw()) {
System.out.println("Diese Spiel ist unentschieden. Es ist kein weiterer Zug moeglich.");
return;
}

if(game.toMove==Position.WHITE && game.numberOfDiscs(game.toMove) != game.numberOfDiscs(!game.toMove)) {
System.out.println("Diese Position ist illegal. Weiss kann nicht am Zug sein.");
return;
}

if(game.toMove==Position.BLACK && game.numberOfDiscs(game.toMove) != (game.numberOfDiscs(!game.toMove)-1)) {
System.out.println("Diese Position ist illegal. Schwarz kann nicht am Zug sein.");
return;
}

MoveList zuege = new MoveList();

while (true) {

boolean toMove = game.toMove;
Player currentPlayer = toMove == Position.WHITE ? white : black;
Player otherPlayer = currentPlayer == white ? black : white;
if(currentPlayer == white) { whitemoves += 1; } else { blackmoves += 1; }

int move = currentPlayer.returnMove(game);

zuege.append(new MoveListElement(move));

if (move==-1) {
System.out.println();
System.out.println( currentPlayer + " gibt auf.");
System.out.println( otherPlayer + " gewinnt.");
System.out.println();
System.out.print("Spiel: "+ zuege);
System.out.println();
out.println();
out.println( currentPlayer + " gibt auf.");
out.println( otherPlayer + " gewinnt.");
out.print("Spiel: "+ zuege);
out.println();
} else if (!game.isLegalMove(move)) {
System.out.println();
System.out.println( currentPlayer + " macht einen illegalen Zug und wird disqualifiziert.");
System.out.println( otherPlayer + " gewinnt.");
System.out.println();
System.out.print("Spiel: "+ zuege);
System.out.println();
out.println();
out.println( currentPlayer + " macht einen illegalen Zug und wird disqualifiziert.");
out.println( otherPlayer + " gewinnt.");
out.print("Spiel: "+ zuege);
out.println();
}

System.out.println(currentPlayer + " zieht " + MovePrinter.printMove(move) + ".");

game.makeMove(move);

System.out.println();
System.out.println();
System.out.println(game);

if(game.isWon(currentPlayer.getColor())) {
System.out.println();
System.out.println( currentPlayer + " gewinnt.");
System.out.println();
System.out.print("Spiel: "+ zuege);
System.out.println();
out.println();
out.println( currentPlayer + " gewinnt.");
out.print("Spiel: "+ zuege);
out.println();
}
if(game.isDraw()) {
System.out.println();
System.out.println("Das Spiel endet unentschieden.");
System.out.println();
System.out.print("Spiel: "+ zuege);
System.out.println();
out.println();
out.println("Das Spiel endet unentschieden.");
out.print("Spiel: "+ zuege);
out.println();
break;
}

System.out.println();
System.out.println();

}

}

}

/*
* Das Spielfeld.
* Die Variablen whiteDiscs und blackDiscs speichern die gesetzten Scheiben beider Spieler,
* height[] speichert die Füllhöhe der einzelnen Spalten.
*/

class Position {

public final static boolean WHITE = true;
public final static boolean BLACK = false;
public long whiteDiscs;
public long blackDiscs;
public int height[];
public boolean toMove;

public Position() {
whiteDiscs = 0;
blackDiscs = 0;
height = new int[7];
for (int i = 0; i <= 6; i++) {
height[i] = 0;
}
toMove = WHITE;
}

public Position(Position p) {
whiteDiscs = p.whiteDiscs;
blackDiscs = p.blackDiscs;
height = new int[7];
for (int i = 0; i <= 6; i++) {
height[i] = p.height[i];
}
toMove = p.toMove;
}

public Position(String fileName) throws java.io.IOException {
whiteDiscs = 0;
blackDiscs = 0;
height = new int[7];
int corrector = 0;

File inputFile = new File(fileName);
InputStreamReader input = new InputStreamReader(new FileInputStream(inputFile));
System.out.println("Position wird eingelesen.");

for(int i=1;i<=54;i++) {
if(i%9==0 || (i+1)%9==0) {
input.read();
corrector += 1;
continue;
}
char x = (char)input.read();
if(x=='1' || x=='w' || x=='W') {
whiteDiscs = whiteDiscs | (1L<<(22+((5-((i-corrector-1)/7))*7+((i-corrector)%7==0 ? 6 : (((i-corrector)%7)-1)))));
}
if(x=='2' || x=='s' || x=='S') {
blackDiscs = blackDiscs | (1L<<(22+((5-((i-corrector-1)/7))*7+((i-corrector)%7==0 ? 6 : (((i-corrector)%7)-1)))));
}
}
toMove = (char)input.read()=='w' ? WHITE : BLACK;
input.close();
for (int i=0;i<=6;i++) {
height[i] = 6;
for(int j=5;j>=0;j--) {
if((whiteDiscs & (1L<<(22+(j*7+i))))==0 && (blackDiscs & (1L<<(22+(j*7+i))))==0) {
height[i] -= 1;
}
}
}
}

public static String colorToString(boolean color) {
return color == WHITE ? "weiss" : "schwarz";
}

public int numberOfDiscs(boolean c) {
int result = 0;
if(c==BLACK) {
for(int i=22;i<=63;i++) {
if((blackDiscs & (1L<<i))!=0) {
result += 1;
}
}
} else {
for(int i=22;i<=63;i++) {
if((whiteDiscs & (1L<<i))!=0) {
result += 1;
}
}
}
return result;
}

public int numberOfDiscs() {
int result = 0;
for(int i=0;i<7;i++) {
result += height[i];
}
return result;
}

public String toString() {
String s = new String();
for(int j=5;j>=0;j--) {
for(int i=0;i<=6;i++) {
if((whiteDiscs & (1L<<(22+(j*7+i))))!=0) {
s = s.concat("W ");
} else if((blackDiscs & (1L<<(22+(j*7+i))))!=0) {
s = s.concat("S ");
} else {
s = s.concat(". ");
}
}
s = s.concat("\n");
}
s = s.concat("am move: ");
s = toMove==WHITE ? s.concat("weiss\n") : s.concat("schwarz\n");
return s;
}

public boolean equals(Object o){
if (!(o instanceof Position))
return false;
Position p = (Position)o;
if(whiteDiscs != p.whiteDiscs) return false;
if(blackDiscs != p.blackDiscs) return false;
return true;
}

public void makeMove(int m) {
if(toMove==WHITE) {
whiteDiscs = whiteDiscs | (1L<<(22+m));
} else {
blackDiscs = blackDiscs | (1L<<(22+m));
}
height[m%7] += 1;
toMove = !toMove;
}

public void undoMove(int m) {
if(toMove==WHITE) {
blackDiscs = blackDiscs & ~(1L<<(22+m));
} else {
whiteDiscs = whiteDiscs & ~(1L<<(22+m));
}
height[m%7] -= 1;
toMove = !toMove;
}

public boolean isLegalMove(int m) {
if((whiteDiscs & (1L<<(22+m)))!=0) return false;
if((blackDiscs & (1L<<(22+m)))!=0) return false;
if(m>6) {
if((whiteDiscs & (1L<<(22+(m/7-1)*7+m%7)))==0
&& (blackDiscs & (1L<<(22+(m/7-1)*7+m%7)))==0) {
return false;
}
}
return true;
}

public boolean isWon(boolean s) {
long x = (s==WHITE ? whiteDiscs : blackDiscs);
long y = 0x0000081020400000L;
for(int i=0;i<21;i++) {
if((x & y)==y) return true;
y = y<<1;
}
y = 0x0000000003C00000L;
for(int i=0;i<12;i++) {
if(i==6) y = 0x0000404040400000L;
if(i==9) y = 0x0000082082000000L;
if((x & y)==y) return true;
y = y<<1;
if((x & y)==y) return true;
y = y<<1;
if((x & y)==y) return true;
y = y<<1;
if((x & y)==y) return true;
y = y<<4;
}
return false;
}

/*
* Überprüft, ob Spieler s mit Zug move gewonnen hat.
*/

public boolean isWon(boolean s, int move) {
long x = (s==WHITE ? whiteDiscs : blackDiscs);
switch(move) {
case 0:
if((x & 0x0000000003800000L)==0x0000000003800000L) return true;
if((x & 0x0000404040000000L)==0x0000404040000000L) return true;
break;
case 7:
if((x & 0x00000001C0000000L)==0x00000001C0000000L) return true;
if((x & 0x0020202000000000L)==0x0020202000000000L) return true;
break;
case 14:
if((x & 0x000000E000000000L)==0x000000E000000000L) return true;
if((x & 0x1010100000000000L)==0x1010100000000000L) return true;
break;
case 21:
if((x & 0x0000700000000000L)==0x0000700000000000L) return true;
if((x & 0x0000002082000000L)==0x0000002082000000L) return true;
if((x & 0x0000001020400000L)==0x0000001020400000L) return true;
break;
case 28:
if((x & 0x0038000000000000L)==0x0038000000000000L) return true;
if((x & 0x0000104100000000L)==0x0000104100000000L) return true;
if((x & 0x0000081020000000L)==0x0000081020000000L) return true;
break;
case 35:
if((x & 0x1C00000000000000L)==0x1C00000000000000L) return true;
if((x & 0x0008208000000000L)==0x0008208000000000L) return true;
if((x & 0x0004081000000000L)==0x0004081000000000L) return true;
break;
case 1:
if((x & 0x0000000003400000L)==0x0000000003400000L) return true;
if((x & 0x0000000007000000L)==0x0000000007000000L) return true;
if((x & 0x0000808080000000L)==0x0000808080000000L) return true;
break;
case 8:
if((x & 0x00000001A0000000L)==0x00000001A0000000L) return true;
if((x & 0x0000000380000000L)==0x0000000380000000L) return true;
if((x & 0x0000404000400000L)==0x0000404000400000L) return true;
if((x & 0x0040404000000000L)==0x0040404000000000L) return true;
break;
case 15:
if((x & 0x000000D000000000L)==0x000000D000000000L) return true;
if((x & 0x000001C000000000L)==0x000001C000000000L) return true;
if((x & 0x0020200020000000L)==0x0020200020000000L) return true;
if((x & 0x2020200000000000L)==0x2020200000000000L) return true;
if((x & 0x0000080082000000L)==0x0000080082000000L) return true;
break;
case 22:
if((x & 0x0000680000000000L)==0x0000680000000000L) return true;
if((x & 0x0000E00000000000L)==0x0000E00000000000L) return true;
if((x & 0x0000004104000000L)==0x0000004104000000L) return true;
if((x & 0x0004004100000000L)==0x0004004100000000L) return true;
if((x & 0x1010001000000000L)==0x1010001000000000L) return true;
if((x & 0x0000002040800000L)==0x0000002040800000L) return true;
break;
case 29:
if((x & 0x0034000000000000L)==0x0034000000000000L) return true;
if((x & 0x0070000000000000L)==0x0070000000000000L) return true;
if((x & 0x0000208200000000L)==0x0000208200000000L) return true;
if((x & 0x0200208000000000L)==0x0200208000000000L) return true;
if((x & 0x0000102040000000L)==0x0000102040000000L) return true;
break;
case 36:
if((x & 0x1A00000000000000L)==0x1A00000000000000L) return true;
if((x & 0x3800000000000000L)==0x3800000000000000L) return true;
if((x & 0x0010410000000000L)==0x0010410000000000L) return true;
if((x & 0x0008102000000000L)==0x0008102000000000L) return true;
break;
case 2:
if((x & 0x0000000002C00000L)==0x0000000002C00000L) return true;
if((x & 0x0000000006800000L)==0x0000000006800000L) return true;
if((x & 0x000000000E000000L)==0x000000000E000000L) return true;
if((x & 0x0001010100000000L)==0x0001010100000000L) return true;
break;
case 9:
if((x & 0x0000000160000000L)==0x0000000160000000L) return true;
if((x & 0x0000000340000000L)==0x0000000340000000L) return true;
if((x & 0x0000000700000000L)==0x0000000700000000L) return true;
if((x & 0x0000082002000000L)==0x0000082002000000L) return true;
if((x & 0x0000808000800000L)==0x0000808000800000L) return true;
if((x & 0x0080808000000000L)==0x0080808000000000L) return true;
break;
case 16:
if((x & 0x000000B000000000L)==0x000000B000000000L) return true;
if((x & 0x000001A000000000L)==0x000001A000000000L) return true;
if((x & 0x0000038000000000L)==0x0000038000000000L) return true;
if((x & 0x0000400040400000L)==0x0000400040400000L) return true;
if((x & 0x0040400040000000L)==0x0040400040000000L) return true;
if((x & 0x4040400000000000L)==0x4040400000000000L) return true;
if((x & 0x0000100104000000L)==0x0000100104000000L) return true;
if((x & 0x0004100100000000L)==0x0004100100000000L) return true;
break;
case 23:
if((x & 0x0000580000000000L)==0x0000580000000000L) return true;
if((x & 0x0000D00000000000L)==0x0000D00000000000L) return true;
if((x & 0x0001C00000000000L)==0x0001C00000000000L) return true;
if((x & 0x0020002020000000L)==0x0020002020000000L) return true;
if((x & 0x2020002000000000L)==0x2020002000000000L) return true;
if((x & 0x0000008208000000L)==0x0000008208000000L) return true;
if((x & 0x0008008200000000L)==0x0008008200000000L) return true;
if((x & 0x0208008000000000L)==0x0208008000000000L) return true;
if((x & 0x0000004081000000L)==0x0000004081000000L) return true;
break;
case 30:
if((x & 0x002C000000000000L)==0x002C000000000000L) return true;
if((x & 0x0068000000000000L)==0x0068000000000000L) return true;
if((x & 0x00E0000000000000L)==0x00E0000000000000L) return true;
if((x & 0x0000410400000000L)==0x0000410400000000L) return true;
if((x & 0x0400410000000000L)==0x0400410000000000L) return true;
if((x & 0x1000101000000000L)==0x1000101000000000L) return true;
if((x & 0x0000204080000000L)==0x0000204080000000L) return true;
break;
case 37:
if((x & 0x1600000000000000L)==0x1600000000000000L) return true;
if((x & 0x3400000000000000L)==0x3400000000000000L) return true;
if((x & 0x7000000000000000L)==0x7000000000000000L) return true;
if((x & 0x0020820000000000L)==0x0020820000000000L) return true;
if((x & 0x0010204000000000L)==0x0010204000000000L) return true;
break;
case 3:
if((x & 0x0000000001C00000L)==0x0000000001C00000L) return true;
if((x & 0x0000000005800000L)==0x0000000005800000L) return true;
if((x & 0x000000000D000000L)==0x000000000D000000L) return true;
if((x & 0x000000001C000000L)==0x000000001C000000L) return true;
if((x & 0x0000082080000000L)==0x0000082080000000L) return true;
if((x & 0x0002020200000000L)==0x0002020200000000L) return true;
break;
case 10:
if((x & 0x00000000E0000000L)==0x00000000E0000000L) return true;
if((x & 0x00000002C0000000L)==0x00000002C0000000L) return true;
if((x & 0x0000000680000000L)==0x0000000680000000L) return true;
if((x & 0x0000000E00000000L)==0x0000000E00000000L) return true;
if((x & 0x0000104004000000L)==0x0000104004000000L) return true;
if((x & 0x0004104000000000L)==0x0004104000000000L) return true;
if((x & 0x0001010001000000L)==0x0001010001000000L) return true;
if((x & 0x0101010000000000L)==0x0101010000000000L) return true;
break;
case 17:
if((x & 0x0000007000000000L)==0x0000007000000000L) return true;
if((x & 0x0000016000000000L)==0x0000016000000000L) return true;
if((x & 0x0000034000000000L)==0x0000034000000000L) return true;
if((x & 0x0000070000000000L)==0x0000070000000000L) return true;
if((x & 0x0000800080800000L)==0x0000800080800000L) return true;
if((x & 0x0080800080000000L)==0x0080800080000000L) return true;
if((x & 0x8080800000000000L)==0x8080800000000000L) return true;
if((x & 0x0000200208000000L)==0x0000200208000000L) return true;
if((x & 0x0008200200000000L)==0x0008200200000000L) return true;
if((x & 0x0208200000000000L)==0x0208200000000000L) return true;
break;
case 24:
if((x & 0x0000380000000000L)==0x0000380000000000L) return true;
if((x & 0x0000B00000000000L)==0x0000B00000000000L) return true;
if((x & 0x0001A00000000000L)==0x0001A00000000000L) return true;
if((x & 0x0003800000000000L)==0x0003800000000000L) return true;
if((x & 0x0000004040400000L)==0x0000004040400000L) return true;
if((x & 0x0040004040000000L)==0x0040004040000000L) return true;
if((x & 0x4040004000000000L)==0x4040004000000000L) return true;
if((x & 0x0000010410000000L)==0x0000010410000000L) return true;
if((x & 0x0010010400000000L)==0x0010010400000000L) return true;
if((x & 0x0410010000000000L)==0x0410010000000000L) return true;
if((x & 0x0000008102000000L)==0x0000008102000000L) return true;
break;
case 31:
if((x & 0x001C000000000000L)==0x001C000000000000L) return true;
if((x & 0x0058000000000000L)==0x0058000000000000L) return true;
if((x & 0x00D0000000000000L)==0x00D0000000000000L) return true;
if((x & 0x01C0000000000000L)==0x01C0000000000000L) return true;
if((x & 0x0000202020000000L)==0x0000202020000000L) return true;
if((x & 0x2000202000000000L)==0x2000202000000000L) return true;
if((x & 0x0000820800000000L)==0x0000820800000000L) return true;
if((x & 0x0800820000000000L)==0x0800820000000000L) return true;
if((x & 0x0000408100000000L)==0x0000408100000000L) return true;
break;
case 38:
if((x & 0x0E00000000000000L)==0x0E00000000000000L) return true;
if((x & 0x2C00000000000000L)==0x2C00000000000000L) return true;
if((x & 0x6800000000000000L)==0x6800000000000000L) return true;
if((x & 0xE000000000000000L)==0xE000000000000000L) return true;
if((x & 0x0010101000000000L)==0x0010101000000000L) return true;
if((x & 0x0041040000000000L)==0x0041040000000000L) return true;
if((x & 0x0020408000000000L)==0x0020408000000000L) return true;
break;
case 4:
if((x & 0x0000000003800000L)==0x0000000003800000L) return true;
if((x & 0x000000000B000000L)==0x000000000B000000L) return true;
if((x & 0x000000001A000000L)==0x000000001A000000L) return true;
if((x & 0x0000104100000000L)==0x0000104100000000L) return true;
break;
case 11:
if((x & 0x00000001C0000000L)==0x00000001C0000000L) return true;
if((x & 0x0000000580000000L)==0x0000000580000000L) return true;
if((x & 0x0000000D00000000L)==0x0000000D00000000L) return true;
if((x & 0x0002020002000000L)==0x0002020002000000L) return true;
if((x & 0x0000208008000000L)==0x0000208008000000L) return true;
if((x & 0x0008208000000000L)==0x0008208000000000L) return true;
break;
case 18:
if((x & 0x000000E000000000L)==0x000000E000000000L) return true;
if((x & 0x000002C000000000L)==0x000002C000000000L) return true;
if((x & 0x0000068000000000L)==0x0000068000000000L) return true;
if((x & 0x0001000101000000L)==0x0001000101000000L) return true;
if((x & 0x0101000100000000L)==0x0101000100000000L) return true;
if((x & 0x0000400410000000L)==0x0000400410000000L) return true;
if((x & 0x0010400400000000L)==0x0010400400000000L) return true;
if((x & 0x0410400000000000L)==0x0410400000000000L) return true;
break;
case 25:
if((x & 0x0000700000000000L)==0x0000700000000000L) return true;
if((x & 0x0001600000000000L)==0x0001600000000000L) return true;
if((x & 0x0003400000000000L)==0x0003400000000000L) return true;
if((x & 0x0000008080800000L)==0x0000008080800000L) return true;
if((x & 0x0080008080000000L)==0x0080008080000000L) return true;
if((x & 0x8080008000000000L)==0x8080008000000000L) return true;
if((x & 0x0020020800000000L)==0x0020020800000000L) return true;
if((x & 0x0820020000000000L)==0x0820020000000000L) return true;
if((x & 0x0000010204000000L)==0x0000010204000000L) return true;
break;
case 32:
if((x & 0x0038000000000000L)==0x0038000000000000L) return true;
if((x & 0x00B0000000000000L)==0x00B0000000000000L) return true;
if((x & 0x01A0000000000000L)==0x01A0000000000000L) return true;
if((x & 0x0000404040000000L)==0x0000404040000000L) return true;
if((x & 0x4000404000000000L)==0x4000404000000000L) return true;
if((x & 0x1001040000000000L)==0x1001040000000000L) return true;
if((x & 0x0000810200000000L)==0x0000810200000000L) return true;
break;
case 39:
if((x & 0x1C00000000000000L)==0x1C00000000000000L) return true;
if((x & 0x5800000000000000L)==0x5800000000000000L) return true;
if((x & 0xD000000000000000L)==0xD000000000000000L) return true;
if((x & 0x0020202000000000L)==0x0020202000000000L) return true;
if((x & 0x0040810000000000L)==0x0040810000000000L) return true;
break;
case 5:
if((x & 0x0000000007000000L)==0x0000000007000000L) return true;
if((x & 0x0000000016000000L)==0x0000000016000000L) return true;
if((x & 0x0000208200000000L)==0x0000208200000000L) return true;
break;
case 12:
if((x & 0x0000000380000000L)==0x0000000380000000L) return true;
if((x & 0x0000000B00000000L)==0x0000000B00000000L) return true;
if((x & 0x0000410010000000L)==0x0000410010000000L) return true;
if((x & 0x0010410000000000L)==0x0010410000000000L) return true;
break;
case 19:
if((x & 0x000001C000000000L)==0x000001C000000000L) return true;
if((x & 0x0000058000000000L)==0x0000058000000000L) return true;
if((x & 0x0002000202000000L)==0x0002000202000000L) return true;
if((x & 0x0020800800000000L)==0x0020800800000000L) return true;
if((x & 0x0820800000000000L)==0x0820800000000000L) return true;
break;
case 26:
if((x & 0x0000E00000000000L)==0x0000E00000000000L) return true;
if((x & 0x0002C00000000000L)==0x0002C00000000000L) return true;
if((x & 0x0000010101000000L)==0x0000010101000000L) return true;
if((x & 0x0100010100000000L)==0x0100010100000000L) return true;
if((x & 0x1040040000000000L)==0x1040040000000000L) return true;
if((x & 0x0000020408000000L)==0x0000020408000000L) return true;
break;
case 33:
if((x & 0x0070000000000000L)==0x0070000000000000L) return true;
if((x & 0x0160000000000000L)==0x0160000000000000L) return true;
if((x & 0x0000808080000000L)==0x0000808080000000L) return true;
if((x & 0x8000808000000000L)==0x8000808000000000L) return true;
if((x & 0x0001020400000000L)==0x0001020400000000L) return true;
break;
case 40:
if((x & 0x3800000000000000L)==0x3800000000000000L) return true;
if((x & 0xB000000000000000L)==0xB000000000000000L) return true;
if((x & 0x0040404000000000L)==0x0040404000000000L) return true;
if((x & 0x0081020000000000L)==0x0081020000000000L) return true;
break;
case 6:
if((x & 0x000000000E000000L)==0x000000000E000000L) return true;
if((x & 0x0000410400000000L)==0x0000410400000000L) return true;
break;
case 13:
if((x & 0x0000000700000000L)==0x0000000700000000L) return true;
if((x & 0x0020820000000000L)==0x0020820000000000L) return true;
break;
case 20:
if((x & 0x0000038000000000L)==0x0000038000000000L) return true;
if((x & 0x1041000000000000L)==0x1041000000000000L) return true;
break;
case 27:
if((x & 0x0001C00000000000L)==0x0001C00000000000L) return true;
if((x & 0x0000020202000000L)==0x0000020202000000L) return true;
if((x & 0x0000040810000000L)==0x0000040810000000L) return true;
break;
case 34:
if((x & 0x00E0000000000000L)==0x00E0000000000000L) return true;
if((x & 0x0001010100000000L)==0x0001010100000000L) return true;
if((x & 0x0002040800000000L)==0x0002040800000000L) return true;
break;
case 41:
if((x & 0x7000000000000000L)==0x7000000000000000L) return true;
if((x & 0x0080808000000000L)==0x0080808000000000L) return true;
if((x & 0x0102040000000000L)==0x0102040000000000L) return true;
break;
default:
break;
}
return false;
}

public boolean isDraw() {
for(int i=0;i<=6;i++) {
if(height[i]!=6) return false;
}
return true;
}

}


abstract class Player {

private String name;
private boolean color;

public Player(boolean color, String name) {
this.color = color;
this.name = name;
}

public String toString() {
return name + " (" + Position.colorToString(color) + ")";
}

public boolean getColor() {
return color;
}

public abstract int returnMove(Position p) throws IOException;

}


class HumanPlayer extends Player {

public HumanPlayer(boolean color, String name) {
super(color, name);
}

/*
* Es werden als Benutzereingabe Spaltennummern von eins bis sieben akzeptiert.
* Um aufzugeben und das Spiel zu beenden gibt man acht ein.
* TO DO: Eigentlich werden Spalten durch Buchstaben bezeichnet...
*/

public int returnMove(Position p) {
try {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
int move;
System.out.println("Geben Sie Ihren Zug ein!");
while(true) {
move = Integer.parseInt(input.readLine());
if(move < 1 || move > 8) {
System.out.println("Bitte eine Reihe (zwischen 1 und 7) oder 8 fuer Aufgabe eingeben.");
} else {
break;
}
}
return move < 8 ? convert(move,p) : -1;
} catch (java.io.IOException e) {
System.out.println("Fehler bei Benutzereingabe.");
return -1;
}
}

public int convert(int move, Position p) {
for(int i=0;i<6;i++) {
if((p.whiteDiscs & (1L<<(22+(i*7+(move-1)))))==0 && (p.blackDiscs & (1L<<(22+(i*7+(move-1)))))==0) {
return i*7+(move-1);
}
}
return move;
}

}

/*
* Eine einfach verkettete Liste von Zügen.
* Sie wird sowohl zum Protokollieren der Spiele als auch innerhalb des Alpha-Beta-Algorithmus für
* die Principal Variation benutzt.
*/

class MoveList {

public int length;
public MoveListElement first;
public MoveListElement last;

public MoveList() {
first = last = null;
length = 0;
}

public void append(MoveListElement ze) {
if(length==0) {
first = last = ze;
length = 1;
return;
}
last.next = ze;
last = ze;
length = length + 1;
}

public void setFirst(MoveListElement ze) {
if(length==0) {
first = last = ze;
length = 1;
return;
}
ze.next = first.next;
if(length==1) {
last = ze;
}
first = ze;
}

public void setRest(MoveList zl) {
if(length==0) {
first = zl.first;
last = zl.last;
length = zl.length;
return;
}
first.next = zl.first;
last = zl.last;
length = 1 + zl.length;
}

public int pop() {
if(first!=null) {
return first.value;
}
return 7;
}

public String toString() {
String s = new String();
MoveListElement cursor = first;
while(cursor != null) {
s = s.concat(cursor.toString());
s = s.concat(" ");
cursor = cursor.next;
}
return s;
}

}


class MoveListElement {

public int value;
public MoveListElement next;

public MoveListElement(int value) {
this.value = value;
next = null;
}

public MoveListElement(int value, MoveListElement ze) {
this.value = value;
next = ze;
}

public String toString() {
return MovePrinter.printMove(value);
}

}

/*
* Eintrag in den Hash Tables.
*/

class HashElement {

public long key;
public double depth;
public int flag;
public int value;
public int move;
public int overwritten;

public HashElement() {
key = flag = value = overwritten = 0;
depth = move = -1;
}

public void clear() {
key = flag = value = overwritten = 0;
depth = move = -1;
}

}


class ComputerPlayer extends Player {

// Zählvariablen
private final static int NODELIMIT = 1000000;
private int[] nodecount = {0,0,0};
private int searchDepth = 0;
private double evalDepthSum = 0;
private int maxDepth = 0;
private int savedSum = 0;
private long totalDuration = 0;
private int counterbookaccess = 0;
private int counterbookfailure = 0;
private int counterhashaccess = 0;
private int counterhashfailure = 0;
private int counterhashmove = 0;
private int counterrecognized = 0;
private int counterevaluated = 0;
private int counterhash1 = 0;
private int counterhash2 = 0;
private int counterhash3 = 0;
private int counterhorizon = 0;
private int counterwon = 0;
private int counterdraw = 0;

// Tabelle zur statischen Zugsortierung
private final static int[] table = {7,9,11,15,11,9,7,9,13,17,21,17,13,9,11,17,23,27,23,17,11,10,16,22,26,22,16,10,8,12,16,20,16,12,8,6,8,10,14,10,8,6};

// Eröffnungsbuch und Variablen zu dessen Sortierung und Aktivierung
private String[] book = new String[67557];
private static String[] b;
private boolean opening;
private boolean bookEnabled;

// aus Effizienzgründen aus AlphaBeta() ausgelagerte Deklarationen
private int value = 0;
private int firstFreeColumn = 0;
private int secondFreeColumn = 0;
private int freeColumns = 0;
private int hvalue = 0;
private int newalpha = 0;
private int newbeta = 0;
private int bestMove = -1;

// Zobrist Keys und Hash Tables sowie deren Flags
private long[][] zobristKeys = new long[42][2];
private final int HASHSIZE = 131072;
private HashElement[] HashTable1 = new HashElement[HASHSIZE];
private HashElement[] HashTable2 = new HashElement[HASHSIZE];
private HashElement[] HashTable3 = new HashElement[HASHSIZE];
private final static int HASHEXACT = 0;
private final static int HASHALPHA = 1;
private final static int HASHBETA = 2;

// aus Effizienzgründen aus sort() ausgelagert: Array für Zugwerte
private int[] tableValues = new int[7];

// aus Effizienzgründen aus evaluate() ausgelagert: Arrays für Drohungen
private boolean[][] whitethreats = new boolean[7][6];
private boolean[][] blackthreats = new boolean[7][6];

// für optionales ausführliches Logfile
private PrintWriter out;
boolean debug;

// Array für aktuell von AlphaBeta() betrachtete Züge im Spielbaum
int moves[][] = new int[42][8];

/*
* Das Eröffnungsbuch wird aus "connect-4.data.txt" eingelesen, die Zobrist Keys aus "zobristkeys.txt".
* "Log white.txt" und "Log black.txt" sind voreingestellt als Logfiles.
*/

public ComputerPlayer(boolean color, String name, boolean bookEnabled, boolean debug) throws java.io.IOException {
super(color, name);
this.bookEnabled = bookEnabled;
this.debug = debug;
out = new PrintWriter(new FileWriter(color ? ("Log white.txt") : ("Log black.txt"), true), true);

if(bookEnabled) {
readBook("connect-4.data.txt");
sortBook();
}

System.out.println("HashTable wird initialisiert.");
System.out.println();
for(int i=0;i<HASHSIZE;i++) {
HashTable1[i] = new HashElement();
HashTable2[i] = new HashElement();
HashTable3[i] = new HashElement();
}

BufferedReader input = new BufferedReader(new FileReader("zobristkeys.txt"));
char[] array;
long x;
int power;
for(int i=0;i<42;i=i+7) {
for(int k=0;k<2;k++) {
array = input.readLine().toCharArray();
x = 0;
power = 0;
if(array[0]=='0') {
for(int l=63;l>=1;l--) {
x = x + ((array[l]=='1' ? 1 : 0)*(long)(Math.pow(2.0,(double)power)));
power += 1;
}
}
if(array[0]=='1') {
x = (long)-Math.pow(2.0,63);
for(int l=63;l>=1;l--) {
x = x + ((array[l]=='1' ? 1 : 0)*(long)(Math.pow(2.0,(double)power)));
power += 1;
}
}
zobristKeys[i][k] = x;
}
if(i==41) { break; }
if(i>=35) { i = (i+8)%42-7; }
}
input.close();
System.out.println();
}


public void addHashEntries(long key, int index, double depth, int value, int flag, int move) {

if(debug) { out.println("EINTRAG ["+key+" "+index+" "+depth+" "+value+" "+flag+" "+move+"]"); }

if(debug) { out.println("[HashTable1]"); }
HashTable1[index].overwritten += 1;
HashTable1[index].value = value;
HashTable1[index].flag = flag;
HashTable1[index].depth = depth;
HashTable1[index].move = move;
HashTable1[index].key = key;

if(depth > HashTable2[index].depth) {
if(debug) { out.println("[HashTable2]"); }
HashTable2[index].overwritten += 1;
HashTable2[index].value = value;
HashTable2[index].flag = flag;
HashTable2[index].depth = depth;
HashTable2[index].move = move;
HashTable2[index].key = key;
}

if(flag==HASHEXACT && (value>600 || value<-600)) {
if(debug) { out.println("[HashTable3]"); }
HashTable3[index].overwritten += 1;
HashTable3[index].value = value;
HashTable3[index].move = move;
HashTable3[index].depth = depth;
HashTable3[index].key = key;
}

}


public void readBook(String fileName) throws java.io.IOException {
BufferedReader input = new BufferedReader(new FileReader(fileName));
System.out.println("Eroeffnungsbuch wird eingelesen.");
for(int i=0;i<67557;i++) {
book[i] = input.readLine();
}
input.close();
}


public void sortBook() {
System.out.println("Eroeffnungsbuch wird sortiert.");
int n = 67557;
b = new String[(n+1)/2];
mergeSort(0, n-1);
}


public void mergeSort(int lo, int hi) {
if (lo<hi) {
int m=(lo+hi)/2;
mergeSort(lo, m);
mergeSort(m+1, hi);
merge(lo, m, hi);
}
}


public void merge(int lo, int m, int hi) {

int i, j, k;
i=0;
j=lo;

while (j<=m) {
b[i++] = book[j++];
}

i=0;
k=lo;

while (k<j && j<=hi)
if (b[i].compareTo(book[j]) <= 0)
book[k++] = b[i++];
else
book[k++] = book[j++];

while (k<j)
book[k++] = b[i++];

}

/*
* Sucht eine Stellung im Eröffnungsbuch. Dazu muß die Position ggf. gespiegelt und erneut gesucht werden.
* Wenn die Stellung nicht gefunden wird, wird -1 zurückgegeben.
*/

public int searchBook(Position p) {

String s = new String();
for(int i=0;i<=6;i++) {
for(int j=0;j<=5;j++) {
if((p.whiteDiscs & (0x0000000000400000L<<(j*7+i)))==(0x0000000000400000L<<(j*7+i))) {
s = s.concat("x");
} else if((p.blackDiscs & (0x0000000000400000L<<(j*7+i)))==(0x0000000000400000L<<(j*7+i))) {
s = s.concat("o");
} else {
s = s.concat("b");
}
s = s.concat(",");
}
}
int result = binarySearch(s);
if(result != -1) { return result; }
s = new String();
for(int i=6;i>=0;i--) {
for(int j=0;j<=5;j++) {
if((p.whiteDiscs & (0x0000000000400000L<<(j*7+i)))==(0x0000000000400000L<<(j*7+i))) {
s = s.concat("x");
} else if((p.blackDiscs & (0x0000000000400000L<<(j*7+i)))==(0x0000000000400000L<<(j*7+i))) {
s = s.concat("o");
} else {
s = s.concat("b");
}
s = s.concat(",");
}
}
return binarySearch(s);

}

public int binarySearch(String s) {

boolean found = false;
int firstElement = 0;
int lastElement = 67557;
int middleElement = 0;

do {
middleElement = (firstElement + lastElement) / 2;
if (book[middleElement].substring(0,84).equals(s)) {
found = true;
break;
}
int comparison = s.compareTo(book[middleElement].substring(0,84));
if (comparison < 0) {
lastElement = middleElement - 1;
} else {
firstElement = middleElement + 1;
}
} while(found == false && firstElement <= lastElement && firstElement < 67557);

if (found == true) {
String t = book[middleElement].substring(84,85);
if(t.equals("w")) { return 920; }
else if(t.equals("d")) { return 0; }
else { return -920; }
} else {
return -1;
}

}

/*
* Hauptmethode des Computerspielers, die eine Position annimmt und einen Zug zurückgibt.
* Sie kapselt den Alpha-Beta-Algorithmus.
*/

public int returnMove(Position arg) throws IOException {

Position p = new Position(arg);
out.println(p);
out.println();

//Startwerte für das Iterative Deepening
nodecount[1] = savedSum;
int lastRoundMove = -1;
int lastRoundValue = -1000;
int bestFoundValue = 0;
searchDepth = 1;
int alpha = -10000;
int beta = 10000;
MoveList pv = new MoveList();
boolean repeated = false;

//Zobrist-Key erstellen
long Zkey = 0;
for(int i=0;i<42;i++) {
if((p.whiteDiscs & (0x0000000000400000L<<i))==(0x0000000000400000L<<i)) {
Zkey = Zkey^zobristKeys[i][0];
} else if((p.blackDiscs & (0x0000000000400000L<<i))==(0x0000000000400000L<<i)) {
Zkey = Zkey^zobristKeys[i][1];
}
}

//Hash Tables löschen
for(int i=0;i<HASHSIZE;i++) {
HashTable1[i].clear();
HashTable2[i].clear();
}

//feststellen, ob man sich noch in der Eröffnung befindet
if(bookEnabled && p.numberOfDiscs()<8) { opening = true; } else { opening = false; }

//Iterative-Deepening-Schleife
while(!(searchDepth>(42-p.numberOfDiscs()))) {

repeated = false;
nodecount[0] = 0;
evalDepthSum = 0;
maxDepth = 100;
counterbookaccess = 0;
counterbookfailure = 0;
counterhashaccess = 0;
counterhashfailure = 0;
counterhashmove = 0;
counterrecognized = 0;
counterevaluated = 0;
counterhash1 = 0;
counterhash2 = 0;
counterhash3 = 0;
counterhorizon = 0;
counterwon = 0;
counterdraw = 0;

pv = new MoveList();
long startTime = 0;
long duration = 0;

try {
//Aspiration Search verlangt ggf. mehrere Anläufe
while(true) {
System.out.println("Suchfenster: "+alpha+" bis "+beta);
out.println("Suchfenster: "+alpha+" bis "+beta);

startTime = System.currentTimeMillis();

bestFoundValue = StartAlphaBeta(p,searchDepth,alpha,beta,0,pv,Zkey);

duration = repeated? duration + System.currentTimeMillis() - startTime : System.currentTimeMillis() - startTime;

if(bestFoundValue<=alpha && !repeated) {
repeated = true;
alpha = -10000;
beta = bestFoundValue + 2;
continue;
}
if(bestFoundValue>=beta && !repeated) {
repeated = true;
beta = 10000;
alpha = bestFoundValue - 2;
continue;
}
if(repeated && (bestFoundValue<=alpha || bestFoundValue>=beta)) {
alpha = -10000;
beta = 10000;
continue;
}
if(bestFoundValue==0) {
alpha = bestFoundValue - 2;
beta = bestFoundValue + 2;
}
if(bestFoundValue>0 && bestFoundValue<600) {
alpha = bestFoundValue;
beta = bestFoundValue + 2;
}
if(bestFoundValue<0 && bestFoundValue>-600) {
alpha = bestFoundValue - 2;
beta = bestFoundValue;
}
if(bestFoundValue>600) {
alpha = bestFoundValue-1;
beta = bestFoundValue+1;
}
if(bestFoundValue<-600) {
alpha = bestFoundValue-1;
beta = bestFoundValue+1;
}
break;
}
} catch (TooManyNodesException t) {
duration = repeated? duration + System.currentTimeMillis() - startTime : System.currentTimeMillis() - startTime;
totalDuration = totalDuration + duration;
nodecount[2] = nodecount[2] + nodecount[0];
nodecount[1] = nodecount[1] + nodecount[0];
System.out.println("Dauer: "+duration);
System.out.println("Gesamtdauer: "+totalDuration);
out.println("Dauer: "+duration);
out.println("Gesamtdauer: "+totalDuration);
out.println();
out.println(lastRoundMove);
out.println();
return lastRoundMove;
}

lastRoundMove = pv.pop();
lastRoundValue = bestFoundValue;
totalDuration = totalDuration + duration;
nodecount[2] = nodecount[2] + nodecount[0];
nodecount[1] = nodecount[1] + nodecount[0];
int overwritten1 = 0;
int overwritten2 = 0;
int overwritten3 = 0;
for(int i=0;i<HASHSIZE;i++) {
if(HashTable1[i].depth != -1) { counterhash1 += 1; overwritten1 += HashTable1[i].overwritten; }
if(HashTable2[i].depth != -1) { counterhash2 += 1; overwritten2 += HashTable2[i].overwritten; }
if(HashTable3[i].depth != -1) { counterhash3 += 1; overwritten3 += HashTable3[i].overwritten; }
}

System.out.println("Bewertung in Tiefe "+searchDepth+": "+bestFoundValue);
System.out.println("Gesamtzahl Knoten: " + nodecount[2] + "; diese Runde: " + nodecount[0] + "; diesen Zug: "+ nodecount[1]);
System.out.println("Horizonttiefe: " + (searchDepth-(evalDepthSum/counterhorizon)));
System.out.println("Maximale Tiefe: " + (searchDepth-(maxDepth)));
System.out.println("PV: "+pv);
System.out.println("erfolgreiche Eroeffnungsbuchzugriffe: "+counterbookaccess);
System.out.println("erfolglose Eroeffnungsbuchzugriffe: "+counterbookfailure);
System.out.println("Wert in Hash gefunden: "+counterhashaccess);
System.out.println("besten Zug in Hash gefunden: "+counterhashmove);
System.out.println("erfolglose Hashzugriffe: "+counterhashfailure);
System.out.println("HashTable 1: "+((double)counterhash1*100/HASHSIZE)+"% gefuellt.");
System.out.println("HashTable 2: "+((double)counterhash2*100/HASHSIZE)+"% gefuellt.");
System.out.println("HashTable 3: "+((double)counterhash3*100/HASHSIZE)+"% gefuellt.");
System.out.println("HashTable 1: durchschnittlich "+((double)overwritten1/counterhash1)+" Mal beschrieben.");
System.out.println("HashTable 2: durchschnittlich "+((double)overwritten2/counterhash2)+" Mal beschrieben.");
System.out.println("HashTable 3: durchschnittlich "+((double)overwritten3/counterhash3)+" Mal beschrieben.");
System.out.println("Am Horizont angekommen: "+counterhorizon+" Mal.");
System.out.println("Dort Hashzugriff: "+counterhashaccess+" Mal.");
System.out.println("Dort gewonnen: "+counterwon+" Mal.");
System.out.println("Dort unentschieden: "+counterdraw+" Mal.");
System.out.println("Dort Buchzugriff: "+counterbookaccess+" Mal.");
System.out.println("Dort evaluiert durch Recognizer: "+counterrecognized+" Mal.");
System.out.println("Dort normal evaluiert: "+counterevaluated+" Mal.");

System.out.println("Dauer: "+duration);
System.out.println("Gesamtdauer: "+totalDuration);
System.out.println();

out.println("Bewertung in Tiefe "+searchDepth+": "+bestFoundValue);
out.println("Gesamtzahl Knoten: " + nodecount[2] + "; diese Runde: " + nodecount[0] + "; diesen Zug: "+ nodecount[1]);
out.println("Horizonttiefe: " + (searchDepth-(evalDepthSum/counterhorizon)));
out.println("Maximale Tiefe: " + (searchDepth-(maxDepth)));
out.println("PV: "+pv);
out.println("erfolgreiche Eroeffnungsbuchzugriffe: "+counterbookaccess);
out.println("erfolglose Eroeffnungsbuchzugriffe: "+counterbookfailure);
out.println("Wert in Hash gefunden: "+counterhashaccess);
out.println("besten Zug in Hash gefunden: "+counterhashmove);
out.println("erfolglose Hashzugriffe: "+counterhashfailure);
out.println("HashTable 1: "+((double)counterhash1*100/HASHSIZE)+"% gefuellt.");
out.println("HashTable 2: "+((double)counterhash2*100/HASHSIZE)+"% gefuellt.");
out.println("HashTable 3: "+((double)counterhash3*100/HASHSIZE)+"% gefuellt.");
out.println("HashTable 1: durchschnittlich "+((double)overwritten1/counterhash1)+" Mal beschrieben.");
out.println("HashTable 2: durchschnittlich "+((double)overwritten2/counterhash2)+" Mal beschrieben.");
out.println("HashTable 3: durchschnittlich "+((double)overwritten3/counterhash3)+" Mal beschrieben.");
out.println("Am Horizont angekommen: "+counterhorizon+" Mal.");
out.println("Dort Hashzugriff: "+counterhashaccess+" Mal.");
out.println("Dort gewonnen: "+counterwon+" Mal.");
out.println("Dort unentschieden: "+counterdraw+" Mal.");
out.println("Dort Buchzugriff: "+counterbookaccess+" Mal.");
out.println("Dort evaluiert durch Recognizer: "+counterrecognized+" Mal.");
out.println("Dort normal evaluiert: "+counterevaluated+" Mal.");

out.println("Dauer: "+duration);
out.println("Gesamtdauer: "+totalDuration);
out.println();

if(bestFoundValue>900 || bestFoundValue<-900) {
break;
}

searchDepth += 1;

}

if(bestFoundValue<-900) {
if(!opening) {
out.println(lastRoundMove);
out.println();
out.println();
return lastRoundMove;
} else {
//Wenn man in der Eröffnung in einer verlorenen Position ist, löscht man die Hash Tables und sucht ohne Eröffnungsbuch von vorne.
bookEnabled = false;
savedSum = nodecount[1];
for(int i=0;i<HASHSIZE;i++) {
HashTable3[i].clear();
}
int result = returnMove(p);
for(int i=0;i<HASHSIZE;i++) {
HashTable3[i].clear();
}
savedSum = 0;
bookEnabled = true;
out.println(result);
out.println();
out.println();
return result;
}
} else {
out.println(lastRoundMove);
out.println();
out.println();
return lastRoundMove;
}

}

/*
* Für den initialen Aufruf von AlphaBeta gibt es eine spezielle Funktion.
* a) Hier wird kein Wert aus den Hash Tables, aus dem Eröffnungsbuch oder aus einer Form von Evaluation übernommen,
* da man sonst 0 Level im Suchbaum und demzufolge keine PV, also auch keinen besten Zug erhält.
* b) Hier muß nicht auf gewonnene oder unentschiedene Positionen getestet werden, da playGame() solche Stellungen abfängt.
* c) Hier wird kein Zug-Argument übergeben. Diese Methode stellt stets den Wurzelknoten dar.
*/

public int StartAlphaBeta(Position p, int depth, int alpha, int beta, double extension, MoveList pv, long Zkey) throws IOException, TooManyNodesException {

if(debug) {
out.println("Startaufruf in Tiefe "+depth+", Extension "+extension +", alpha "+alpha+", beta "+beta);
out.println(p);
}

nodecount[0] += 1;
int hashflag = HASHALPHA;

//letzte Bits des Keys in Index umwandeln
int index = (int)Zkey&(HASHSIZE-1);
if(debug) {
out.print("Index "+index);
}

//Hashtables
bestMove = -1;
if(HashTable1[index].key == Zkey) {
bestMove = HashTable1[index].move;
}
if(HashTable2[index].key == Zkey) {
bestMove = HashTable2[index].move;
}
if(debug) {
out.println("nicht gesucht und nicht gefunden.");
out.println("Bester Zug: "+bestMove);
}

if(bestMove!=-1) {
counterhashmove += 1;
} else {
counterhashfailure += 1;
}

MoveList mypv = new MoveList();

int[] moves = generateMoves(p, searchDepth-depth);
sort(moves, p);
System.out.print("Moegliche Zuege: ");
for(int i=0;i<moves[7];i++) {
System.out.print(MovePrinter.printMove(moves[i])+" ");
}
System.out.println();
out.print("Moegliche Zuege: ");
for(int i=0;i<moves[7];i++) {
out.print(MovePrinter.printMove(moves[i])+" ");
}
out.println();

for(int i=0;i<moves[7];i++) {
Zkey = Zkey^(p.toMove == p.WHITE ? zobristKeys[moves[i]][0] : zobristKeys[moves[i]][1]);
value = -AlphaBeta(p, depth-1, -beta, -alpha, extension, mypv, Zkey, moves[i]);
p.undoMove(moves[i]);
Zkey = Zkey^(p.toMove == p.WHITE ? zobristKeys[moves[i]][0] : zobristKeys[moves[i]][1]);
if(value>=beta) {
addHashEntries(Zkey, index, depth+extension, value, HASHBETA, moves[i]);
if(debug) { out.println("Beta-Cutoff. "+beta+" als Betawert gespeichert in "+index+" mit Zug "+(moves[i])+" in Tiefe "+(moves[7]==1 ? (depth+extension-1):(depth+extension))); }
return beta;
}
if(value>alpha) {
hashflag = HASHEXACT;
alpha = value;
pv.setFirst(new MoveListElement(moves[i]));
if(mypv.length!=0) {
pv.setRest(mypv);
}
pv.length = mypv.length + 1;
}
}
addHashEntries(Zkey, index, depth+extension, alpha, hashflag, (hashflag == HASHEXACT ? pv.pop() : -1));
if(debug) {
out.println("Alpha-Update. "+alpha+" als "+(hashflag==HASHEXACT?"exakter Wert ":"Alphawert ")+"gespeichert in "+index+" mit Zug "+(hashflag == HASHEXACT ? pv.pop() : -1)+" in Tiefe "+(moves[7]==1 ? (depth+extension-1):(depth+extension)));
out.println();
out.println("---");
out.println();
}
return alpha;

}


public int AlphaBeta(Position p, int depth, int alpha, int beta, double extension, MoveList pv, long Zkey, int move) throws IOException, TooManyNodesException {

if(nodecount[1]+nodecount[0]>NODELIMIT) {
throw new TooManyNodesException();
}

if(depth < maxDepth) {
maxDepth = depth;
}

if(debug) {
out.println();
out.println("Aufruf in Tiefe "+depth+", Extension "+extension+", alpha "+alpha+", beta "+beta+", move "+move);
out.println(p);
}

p.makeMove(move);
nodecount[0] += 1;
int hashflag = HASHALPHA;

//letzte Bits des Keys in Index umwandeln
int index = (int)Zkey&(HASHSIZE-1);
if(debug) {
out.println("Index "+index);
}

//Hash Tables
hvalue = -1;
bestMove = -1;
newbeta = beta;
newalpha = alpha;
if(HashTable2[index].key == Zkey) {
if(debug) out.println("in 2 gefunden.");
if(HashTable2[index].depth >= (depth+extension)) {
if(debug) out.println("Ausreichend in 2: Benoetigte Tiefe "+(depth+extension)+", vorgefundene depth "+HashTable2[index].depth);
if(HashTable2[index].flag==HASHEXACT) {
if(debug) out.println("Exakter Wert in 1: "+HashTable2[index].value);
hvalue = HashTable2[index].value;
}
if(HashTable2[index].flag==HASHALPHA && HashTable2[index].value <= alpha) {
if(debug) out.println("Alphawert in 1: "+alpha);
hvalue = alpha;
}
if(HashTable2[index].flag==HASHALPHA && HashTable2[index].value < beta) {
newbeta = HashTable2[index].value;
if(debug) out.println("Beta-Update in 1: "+newbeta);
}
if(HashTable2[index].flag==HASHBETA && HashTable2[index].value >= beta) {
if(debug) out.println("Betawert in 1: "+beta);
hvalue = beta;
}
if(HashTable2[index].flag==HASHBETA && HashTable2[index].value > alpha) {
newalpha = HashTable2[index].value;
if(debug) out.println("Alpha-Update in 1: "+newalpha);
}
}
if(debug) out.println("Bester Zug in 2: "+HashTable2[index].move);
bestMove = HashTable2[index].move;
}
if(HashTable1[index].key == Zkey) {
if(debug) out.println("in 1 gefunden.");
if(HashTable1[index].depth >= (depth+extension)) {
if(debug) out.println("Ausreichend in 1: Benoetigte Tiefe "+(depth+extension)+", vorgefundene depth "+HashTable1[index].depth);
if(HashTable1[index].flag==HASHEXACT) {
if(debug) out.println("Exakter Wert in 1: "+HashTable1[index].value);
hvalue = HashTable1[index].value;
}
if(HashTable1[index].flag==HASHALPHA && HashTable1[index].value <= alpha) {
if(debug) out.println("Alphawert in 1: "+alpha);
hvalue = alpha;
}
if(HashTable1[index].flag==HASHALPHA && HashTable1[index].value < beta) {
newbeta = HashTable1[index].value;
if(debug) out.println("Beta-Update in 1: "+newbeta);
}
if(HashTable1[index].flag==HASHBETA && HashTable1[index].value >= beta) {
if(debug) out.println("Betawert in 1: "+beta);
hvalue = beta;
}
if(HashTable1[index].flag==HASHBETA && HashTable1[index].value > alpha) {
newalpha = HashTable1[index].value;
if(debug) out.println("Alpha-Update in 1: "+newalpha);
}
}
if(debug) out.println("Bester Zug in 1: "+HashTable1[index].move);
bestMove = HashTable1[index].move;
}
if(HashTable3[index].key == Zkey) {
if(debug) out.println("in 3 gefunden.");
if(debug) out.println("Exakter Wert in 3: "+HashTable3[index].value);
hvalue = HashTable3[index].value;
}
beta = newbeta;
alpha = newalpha;
if(hvalue != -1) {
if(debug) {
out.println("Wert "+hvalue+" wird zurueckgegeben.");
out.println();
}
counterhorizon += 1;
counterhashaccess += 1;
evalDepthSum += depth;
pv.length = 0;
return hvalue;
}
if(debug) {
out.println("Suche wird fortgesetzt.");
out.println("Bester Zug "+bestMove);
}

if(bestMove!=-1) {
counterhashmove += 1;
} else {
counterhashfailure += 1;
}

MoveList mypv = new MoveList();

//entschiedene Positionen
if(p.isWon(!p.toMove,move)) {
if(debug) out.println("Ist verloren, "+(-1000+p.numberOfDiscs())+" zurück und gespeichert in "+index+" in Tiefe "+(depth+extension));
counterhorizon += 1;
counterwon += 1;
evalDepthSum += depth;
pv.length = 0;
addHashEntries(Zkey, index, depth+extension, -1000+p.numberOfDiscs(), HASHEXACT, -1);
return -1000+p.numberOfDiscs();
}

if(p.isDraw()) {
if(debug) out.println("Ist unentschieden, 0 zurück und gespeichert in "+index+" in Tiefe "+(depth+extension));
counterhorizon += 1;
counterdraw += 1;
evalDepthSum += depth;
pv.length = 0;
addHashEntries(Zkey, index, depth+extension, 0, HASHEXACT, -1);
return 0;
}

//Eröffnungsbuchzugriff
if(opening) {
if(p.numberOfDiscs()==8) {
value = searchBook(p);
if(value != -1) {
if(debug) out.println("Ist in DB, "+value+" zurück und gespeichert in "+index+" in Tiefe "+(depth+extension));
counterbookaccess += 1;
counterhorizon += 1;
evalDepthSum += depth;
pv.length = 0;
addHashEntries(Zkey, index, depth+extension, value, HASHEXACT, -1);
return value;
}
counterbookfailure += 1;
}
}

//Interior Node Recognition
firstFreeColumn = -1;
secondFreeColumn = -1;
freeColumns = 0;
for(int i=0;i<7;i++) {
if(p.height[i]!=6) {
freeColumns += 1;
if(freeColumns==3)
break;
if(freeColumns==1)
firstFreeColumn = i;
if(freeColumns==2)
secondFreeColumn = i;
}
}

if(freeColumns==1 || (freeColumns==2 && (secondFreeColumn-firstFreeColumn>=4))) {
if(acuteThreat(p,p.toMove)==-1 && acuteThreat(p,!p.toMove)==-1) {
value = evaluate(p, true);
counterhorizon += 1;
evalDepthSum += depth;
pv.length = 0;
if(debug) out.println("Ist recognized, "+value+" zurück und gespeichert in "+index+" in Tiefe "+(depth+extension));
addHashEntries(Zkey, index, depth+extension, value, HASHEXACT, -1);
return value;
}
}


if(depth <= (0-extension)) {
int akut2 = acuteThreat(p, p.toMove);
if(akut2!=-1) {
if(debug) out.println("Horizont erreicht. Ist gewonnen im nächsten Zug, 1000 zurück und gespeichert in "+index+" in Tiefe "+(depth+extension));
evalDepthSum += depth;
counterhorizon += 1;
pv.length = 0;
addHashEntries(Zkey, index, depth+extension, 1000-p.numberOfDiscs()-1, HASHEXACT, -1);
return 1000-p.numberOfDiscs()-1;
}
int akut = acuteThreat(p, !p.toMove);
if(akut==-1) {
evalDepthSum += depth;
counterhorizon += 1;
pv.length = 0;
int val = evaluate(p, false);
addHashEntries(Zkey, index, depth+extension, val, HASHEXACT, -1);
if(debug) out.println("Horizont erreicht. Evaluiert, "+val+" zurück und gespeichert in "+index+" in Tiefe "+(depth+extension));
return val;
}
extension += 2;
Zkey = Zkey^(p.toMove ? zobristKeys[akut][0] : zobristKeys[akut][1]);
if(debug) out.println("Horizont erreicht. Suche wird vertieft");
int value = -AlphaBeta(p, depth-1, -beta, -alpha, extension, mypv, Zkey, akut);
p.undoMove(akut);
Zkey = Zkey^(p.toMove ? zobristKeys[akut][0] : zobristKeys[akut][1]);
if(value>=beta) {
addHashEntries(Zkey, index, depth+extension-2, beta, HASHBETA, -1);
if(debug) out.println("Beta-Cutoff. "+beta+" als Betavalue gespeichert in "+index+" in Tiefe "+(depth+extension-2));
return beta;
}
if(value>alpha) {
hashflag = HASHEXACT;
alpha = value;
pv.setFirst(new MoveListElement(akut));
if(mypv.length!=0) {
pv.setRest(mypv);
}
pv.length = mypv.length + 1;
}
addHashEntries(Zkey, index, depth+extension-2, alpha, hashflag, -1);
if(debug) out.println("Alpha-Update. "+alpha+" als "+(hashflag==HASHEXACT?"exakter Wert ":"Alphavalue ")+"gespeichert in "+index+" in Tiefe "+(depth+extension-2));
return alpha;
}

int[] moves = generateMoves(p, searchDepth-depth);
sort(moves, p);

//Suchvertiefung
for(int i=0;i<moves[7];i++) {
Zkey = Zkey^(p.toMove ? zobristKeys[moves[i]][0] : zobristKeys[moves[i]][1]);
value = -AlphaBeta(p, depth-1, -beta, -alpha, extension, mypv, Zkey, moves[i]);
p.undoMove(moves[i]);
Zkey = Zkey^(p.toMove ? zobristKeys[moves[i]][0] : zobristKeys[moves[i]][1]);
if(value>=beta) {
addHashEntries(Zkey, index, depth+extension, value, HASHBETA, moves[i]);
if(debug) out.println("Beta-Cutoff. "+beta+" als Betawert gespeichert in "+index+" mit Zug "+moves[i]+" in Tiefe "+(moves[7]==1 ? (depth+extension-1) : (depth+extension)));
return beta;
}
if(value>alpha) {
hashflag = HASHEXACT;
alpha = value;
pv.setFirst(new MoveListElement(moves[i]));
if(mypv.length!=0) {
pv.setRest(mypv);
}
pv.length = mypv.length + 1;
}
}
addHashEntries(Zkey, index, depth+extension, alpha, hashflag, (hashflag == HASHEXACT ? pv.pop() : -1));
if(debug) out.println("Alpha-Update. "+alpha+" als "+(hashflag==HASHEXACT?"exakter Wert ":"Alphawert ")+"gespeichert in "+index+" mit Zug "+(hashflag == HASHEXACT ? pv.pop() : -1)+" in Tiefe "+(moves[7]==1 ? (depth+extension-1) : (depth+extension)));
return alpha;

}

/*
* Sortiert Züge nach Feldgewichten und nach dem besten Zug aus den Hash Tables
*/

private void sort(int[] z, Position p) {

for(int i=0;i<z[7];i++) {
tableValues[i] = table[z[i]];
}

int swap;
for(int i=z[7]-2;i>=0;i--) {
for(int j=0;j<=i;j++) {
if(table[z[j+1]]>table[z[j]]) {
swap = z[j+1];
z[j+1] = z[j];
z[j] = swap;
swap = tableValues[j+1];
tableValues[j+1] = tableValues[j];
tableValues[j] = swap;
}
}
}

if(bestMove!=-1) {
for(int i=0;i<z[7];i++) {
if(z[i]==bestMove) {
if(i<1) { break; }
for(int j=i;i>0;i--) {
z[i] = z[i-1];
}
z[0] = bestMove;
break;
}
}
}

}

/*
* nur in Situationen anwendbar, in denen niemand gewonnen hat und kein unentschieden vorliegt
*/

private int evaluate(Position p, boolean recognized) {

if(recognized) {
counterrecognized += 1;
} else {
counterevaluated += 1;
}

//Threats ermitteln
getthreats(p, p.WHITE);
getthreats(p, p.BLACK);

//Array initialisieren
int[] height = new int[7];
int totalheight = 0;
outer: for(int i=0;i<7;i++) {
height[i] = 6;
for (int j=0;j<6;j++) {
if (blackthreats[i][j] || whitethreats[i][j]) {
height[i] = p.height[i];
totalheight += height[i];
continue outer;
}
}
totalheight += 6;
}
if(totalheight==42) {
return 0;
}

//Gewinner feststellen, falls auf restlichem Brett nichts passiert
boolean toMove = (totalheight%2 == 0) ? p.WHITE : p.BLACK;
boolean winner;
boolean found = true;

outer: while(found) {
found = false;

//eigenen Threat besetzen
for(int i=0;i<7;i++) {
if(height[i]<6 && (toMove == p.WHITE ? whitethreats[i][height[i]] : blackthreats[i][height[i]])) {
winner = toMove;
if(recognized) {
return (p.toMove==winner) ? (699-totalheight) : (-699+totalheight);
} else {
return (p.toMove==winner) ? (458+p.numberOfDiscs()) : (-458-p.numberOfDiscs());
}
}
}

//gegnerischen Threat besetzen
for(int i=0;i<7;i++) {
if(height[i]<6 && (toMove == p.WHITE ? blackthreats[i][height[i]] : whitethreats[i][height[i]])) {
height[i] += 1;
toMove = !toMove;
found = true;
continue outer;
}
}

//unkritisches Feld besetzen
for(int i=0;i<7;i++) {
if((height[i] == 5) || (height[i]<5 && !blackthreats[i][height[i]+1] && !whitethreats[i][height[i]+1])) {
height[i] += 1;
toMove = !toMove;
found = true;
continue outer;
}
}

//unter eigene Drohung ziehen, ungerade Anzahl freier Felder
for(int i=0;i<7;i++) {
if(height[i]<5 && (toMove == p.WHITE ? !blackthreats[i][height[i]+1] : !whitethreats[i][height[i]+1]) && ((6-height[i])%2==1)) {
height[i] += 1;
toMove = !toMove;
found = true;
continue outer;
}
}

//unter eigene Drohung ziehen, gerade Anzahl freier Felder
for(int i=0;i<7;i++) {
if(height[i]<5 && (toMove == p.WHITE ? !blackthreats[i][height[i]+1] : !whitethreats[i][height[i]+1])) {
height[i] += 1;
toMove = !toMove;
found = true;
continue outer;
}
}

//unter gegnerische Drohung ziehen
for(int i=0;i<7;i++) {
if(height[i]<5) {
height[i] += 1;
toMove = !toMove;
found = true;
continue outer;
}
}

break outer;
}

return 0;

}

/*
* Gibt -1 zurück, falls s keine akute Drohung in p hat, ansonsten die erste gefundene
*/

private int acuteThreat(Position p, boolean s) {

long x = (s==p.WHITE ? p.whiteDiscs : p.blackDiscs);

switch(p.height[0]) {
case 0:
if((x & 0x0000000003800000L)==0x0000000003800000L) return 0;
if((x & 0x0000404040000000L)==0x0000404040000000L) return 0;
break;
case 1:
if((x & 0x00000001C0000000L)==0x00000001C0000000L) return 7;
if((x & 0x0020202000000000L)==0x0020202000000000L) return 7;
break;
case 2:
if((x & 0x000000E000000000L)==0x000000E000000000L) return 14;
if((x & 0x1010100000000000L)==0x1010100000000000L) return 14;
break;
case 3:
if((x & 0x0000700000000000L)==0x0000700000000000L) return 21;
if((x & 0x0000002082000000L)==0x0000002082000000L) return 21;
if((x & 0x0000001020400000L)==0x0000001020400000L) return 21;
break;
case 4:
if((x & 0x0038000000000000L)==0x0038000000000000L) return 28;
if((x & 0x0000104100000000L)==0x0000104100000000L) return 28;
if((x & 0x0000081020000000L)==0x0000081020000000L) return 28;
break;
case 5:
if((x & 0x1C00000000000000L)==0x1C00000000000000L) return 35;
if((x & 0x0008208000000000L)==0x0008208000000000L) return 35;
if((x & 0x0004081000000000L)==0x0004081000000000L) return 35;
break;
default:
break;
}
switch(p.height[1]) {
case 0:
if((x & 0x0000000003400000L)==0x0000000003400000L) return 1;
if((x & 0x0000000007000000L)==0x0000000007000000L) return 1;
if((x & 0x0000808080000000L)==0x0000808080000000L) return 1;
break;
case 1:
if((x & 0x00000001A0000000L)==0x00000001A0000000L) return 8;
if((x & 0x0000000380000000L)==0x0000000380000000L) return 8;
if((x & 0x0000404000400000L)==0x0000404000400000L) return 8;
if((x & 0x0040404000000000L)==0x0040404000000000L) return 8;
break;
case 2:
if((x & 0x000000D000000000L)==0x000000D000000000L) return 15;
if((x & 0x000001C000000000L)==0x000001C000000000L) return 15;
if((x & 0x0020200020000000L)==0x0020200020000000L) return 15;
if((x & 0x2020200000000000L)==0x2020200000000000L) return 15;
if((x & 0x0000080082000000L)==0x0000080082000000L) return 15;
break;
case 3:
if((x & 0x0000680000000000L)==0x0000680000000000L) return 22;
if((x & 0x0000E00000000000L)==0x0000E00000000000L) return 22;
if((x & 0x0000004104000000L)==0x0000004104000000L) return 22;
if((x & 0x0004004100000000L)==0x0004004100000000L) return 22;
if((x & 0x1010001000000000L)==0x1010001000000000L) return 22;
if((x & 0x0000002040800000L)==0x0000002040800000L) return 22;
break;
case 4:
if((x & 0x0034000000000000L)==0x0034000000000000L) return 29;
if((x & 0x0070000000000000L)==0x0070000000000000L) return 29;
if((x & 0x0000208200000000L)==0x0000208200000000L) return 29;
if((x & 0x0200208000000000L)==0x0200208000000000L) return 29;
if((x & 0x0000102040000000L)==0x0000102040000000L) return 29;
break;
case 5:
if((x & 0x1A00000000000000L)==0x1A00000000000000L) return 36;
if((x & 0x3800000000000000L)==0x3800000000000000L) return 36;
if((x & 0x0010410000000000L)==0x0010410000000000L) return 36;
if((x & 0x0008102000000000L)==0x0008102000000000L) return 36;
break;
default:
break;
}
switch(p.height[2]) {
case 0:
if((x & 0x0000000002C00000L)==0x0000000002C00000L) return 2;
if((x & 0x0000000006800000L)==0x0000000006800000L) return 2;
if((x & 0x000000000E000000L)==0x000000000E000000L) return 2;
if((x & 0x0001010100000000L)==0x0001010100000000L) return 2;
break;
case 1:
if((x & 0x0000000160000000L)==0x0000000160000000L) return 9;
if((x & 0x0000000340000000L)==0x0000000340000000L) return 9;
if((x & 0x0000000700000000L)==0x0000000700000000L) return 9;
if((x & 0x0000082002000000L)==0x0000082002000000L) return 9;
if((x & 0x0000808000800000L)==0x0000808000800000L) return 9;
if((x & 0x0080808000000000L)==0x0080808000000000L) return 9;
break;
case 2:
if((x & 0x000000B000000000L)==0x000000B000000000L) return 16;
if((x & 0x000001A000000000L)==0x000001A000000000L) return 16;
if((x & 0x0000038000000000L)==0x0000038000000000L) return 16;
if((x & 0x0000400040400000L)==0x0000400040400000L) return 16;
if((x & 0x0040400040000000L)==0x0040400040000000L) return 16;
if((x & 0x4040400000000000L)==0x4040400000000000L) return 16;
if((x & 0x0000100104000000L)==0x0000100104000000L) return 16;
if((x & 0x0004100100000000L)==0x0004100100000000L) return 16;
break;
case 3:
if((x & 0x0000580000000000L)==0x0000580000000000L) return 23;
if((x & 0x0000D00000000000L)==0x0000D00000000000L) return 23;
if((x & 0x0001C00000000000L)==0x0001C00000000000L) return 23;
if((x & 0x0020002020000000L)==0x0020002020000000L) return 23;
if((x & 0x2020002000000000L)==0x2020002000000000L) return 23;
if((x & 0x0000008208000000L)==0x0000008208000000L) return 23;
if((x & 0x0008008200000000L)==0x0008008200000000L) return 23;
if((x & 0x0208008000000000L)==0x0208008000000000L) return 23;
if((x & 0x0000004081000000L)==0x0000004081000000L) return 23;
break;
case 4:
if((x & 0x002C000000000000L)==0x002C000000000000L) return 30;
if((x & 0x0068000000000000L)==0x0068000000000000L) return 30;
if((x & 0x00E0000000000000L)==0x00E0000000000000L) return 30;
if((x & 0x0000410400000000L)==0x0000410400000000L) return 30;
if((x & 0x0400410000000000L)==0x0400410000000000L) return 30;
if((x & 0x1000101000000000L)==0x1000101000000000L) return 30;
if((x & 0x0000204080000000L)==0x0000204080000000L) return 30;
break;
case 5:
if((x & 0x1600000000000000L)==0x1600000000000000L) return 37;
if((x & 0x3400000000000000L)==0x3400000000000000L) return 37;
if((x & 0x7000000000000000L)==0x7000000000000000L) return 37;
if((x & 0x0020820000000000L)==0x0020820000000000L) return 37;
if((x & 0x0010204000000000L)==0x0010204000000000L) return 37;
break;
default:
break;
}
switch(p.height[3]) {
case 0:
if((x & 0x0000000001C00000L)==0x0000000001C00000L) return 3;
if((x & 0x0000000005800000L)==0x0000000005800000L) return 3;
if((x & 0x000000000D000000L)==0x000000000D000000L) return 3;
if((x & 0x000000001C000000L)==0x000000001C000000L) return 3;
if((x & 0x0000082080000000L)==0x0000082080000000L) return 3;
if((x & 0x0002020200000000L)==0x0002020200000000L) return 3;
break;
case 1:
if((x & 0x00000000E0000000L)==0x00000000E0000000L) return 10;
if((x & 0x00000002C0000000L)==0x00000002C0000000L) return 10;
if((x & 0x0000000680000000L)==0x0000000680000000L) return 10;
if((x & 0x0000000E00000000L)==0x0000000E00000000L) return 10;
if((x & 0x0000104004000000L)==0x0000104004000000L) return 10;
if((x & 0x0004104000000000L)==0x0004104000000000L) return 10;
if((x & 0x0001010001000000L)==0x0001010001000000L) return 10;
if((x & 0x0101010000000000L)==0x0101010000000000L) return 10;
break;
case 2:
if((x & 0x0000007000000000L)==0x0000007000000000L) return 17;
if((x & 0x0000016000000000L)==0x0000016000000000L) return 17;
if((x & 0x0000034000000000L)==0x0000034000000000L) return 17;
if((x & 0x0000070000000000L)==0x0000070000000000L) return 17;
if((x & 0x0000800080800000L)==0x0000800080800000L) return 17;
if((x & 0x0080800080000000L)==0x0080800080000000L) return 17;
if((x & 0x8080800000000000L)==0x8080800000000000L) return 17;
if((x & 0x0000200208000000L)==0x0000200208000000L) return 17;
if((x & 0x0008200200000000L)==0x0008200200000000L) return 17;
if((x & 0x0208200000000000L)==0x0208200000000000L) return 17;
break;
case 3:
if((x & 0x0000380000000000L)==0x0000380000000000L) return 24;
if((x & 0x0000B00000000000L)==0x0000B00000000000L) return 24;
if((x & 0x0001A00000000000L)==0x0001A00000000000L) return 24;
if((x & 0x0003800000000000L)==0x0003800000000000L) return 24;
if((x & 0x0000004040400000L)==0x0000004040400000L) return 24;
if((x & 0x0040004040000000L)==0x0040004040000000L) return 24;
if((x & 0x4040004000000000L)==0x4040004000000000L) return 24;
if((x & 0x0000010410000000L)==0x0000010410000000L) return 24;
if((x & 0x0010010400000000L)==0x0010010400000000L) return 24;
if((x & 0x0410010000000000L)==0x0410010000000000L) return 24;
if((x & 0x0000008102000000L)==0x0000008102000000L) return 24;
break;
case 4:
if((x & 0x001C000000000000L)==0x001C000000000000L) return 31;
if((x & 0x0058000000000000L)==0x0058000000000000L) return 31;
if((x & 0x00D0000000000000L)==0x00D0000000000000L) return 31;
if((x & 0x01C0000000000000L)==0x01C0000000000000L) return 31;
if((x & 0x0000202020000000L)==0x0000202020000000L) return 31;
if((x & 0x2000202000000000L)==0x2000202000000000L) return 31;
if((x & 0x0000820800000000L)==0x0000820800000000L) return 31;
if((x & 0x0800820000000000L)==0x0800820000000000L) return 31;
if((x & 0x0000408100000000L)==0x0000408100000000L) return 31;
break;
case 5:
if((x & 0x0E00000000000000L)==0x0E00000000000000L) return 38;
if((x & 0x2C00000000000000L)==0x2C00000000000000L) return 38;
if((x & 0x6800000000000000L)==0x6800000000000000L) return 38;
if((x & 0xE000000000000000L)==0xE000000000000000L) return 38;
if((x & 0x0010101000000000L)==0x0010101000000000L) return 38;
if((x & 0x0041040000000000L)==0x0041040000000000L) return 38;
if((x & 0x0020408000000000L)==0x0020408000000000L) return 38;
break;
default:
break;
}
switch(p.height[4]) {
case 0:
if((x & 0x0000000003800000L)==0x0000000003800000L) return 4;
if((x & 0x000000000B000000L)==0x000000000B000000L) return 4;
if((x & 0x000000001A000000L)==0x000000001A000000L) return 4;
if((x & 0x0000104100000000L)==0x0000104100000000L) return 4;
break;
case 1:
if((x & 0x00000001C0000000L)==0x00000001C0000000L) return 11;
if((x & 0x0000000580000000L)==0x0000000580000000L) return 11;
if((x & 0x0000000D00000000L)==0x0000000D00000000L) return 11;
if((x & 0x0002020002000000L)==0x0002020002000000L) return 11;
if((x & 0x0000208008000000L)==0x0000208008000000L) return 11;
if((x & 0x0008208000000000L)==0x0008208000000000L) return 11;
break;
case 2:
if((x & 0x000000E000000000L)==0x000000E000000000L) return 18;
if((x & 0x000002C000000000L)==0x000002C000000000L) return 18;
if((x & 0x0000068000000000L)==0x0000068000000000L) return 18;
if((x & 0x0001000101000000L)==0x0001000101000000L) return 18;
if((x & 0x0101000100000000L)==0x0101000100000000L) return 18;
if((x & 0x0000400410000000L)==0x0000400410000000L) return 18;
if((x & 0x0010400400000000L)==0x0010400400000000L) return 18;
if((x & 0x0410400000000000L)==0x0410400000000000L) return 18;
break;
case 3:
if((x & 0x0000700000000000L)==0x0000700000000000L) return 25;
if((x & 0x0001600000000000L)==0x0001600000000000L) return 25;
if((x & 0x0003400000000000L)==0x0003400000000000L) return 25;
if((x & 0x0000008080800000L)==0x0000008080800000L) return 25;
if((x & 0x0080008080000000L)==0x0080008080000000L) return 25;
if((x & 0x8080008000000000L)==0x8080008000000000L) return 25;
if((x & 0x0020020800000000L)==0x0020020800000000L) return 25;
if((x & 0x0820020000000000L)==0x0820020000000000L) return 25;
if((x & 0x0000010204000000L)==0x0000010204000000L) return 25;
break;
case 4:
if((x & 0x0038000000000000L)==0x0038000000000000L) return 32;
if((x & 0x00B0000000000000L)==0x00B0000000000000L) return 32;
if((x & 0x01A0000000000000L)==0x01A0000000000000L) return 32;
if((x & 0x0000404040000000L)==0x0000404040000000L) return 32;
if((x & 0x4000404000000000L)==0x4000404000000000L) return 32;
if((x & 0x1001040000000000L)==0x1001040000000000L) return 32;
if((x & 0x0000810200000000L)==0x0000810200000000L) return 32;
break;
case 5:
if((x & 0x1C00000000000000L)==0x1C00000000000000L) return 39;
if((x & 0x5800000000000000L)==0x5800000000000000L) return 39;
if((x & 0xD000000000000000L)==0xD000000000000000L) return 39;
if((x & 0x0020202000000000L)==0x0020202000000000L) return 39;
if((x & 0x0040810000000000L)==0x0040810000000000L) return 39;
break;
default:
break;
}
switch(p.height[5]) {
case 0:
if((x & 0x0000000007000000L)==0x0000000007000000L) return 5;
if((x & 0x0000000016000000L)==0x0000000016000000L) return 5;
if((x & 0x0000208200000000L)==0x0000208200000000L) return 5;
break;
case 1:
if((x & 0x0000000380000000L)==0x0000000380000000L) return 12;
if((x & 0x0000000B00000000L)==0x0000000B00000000L) return 12;
if((x & 0x0000410010000000L)==0x0000410010000000L) return 12;
if((x & 0x0010410000000000L)==0x0010410000000000L) return 12;
break;
case 2:
if((x & 0x000001C000000000L)==0x000001C000000000L) return 19;
if((x & 0x0000058000000000L)==0x0000058000000000L) return 19;
if((x & 0x0002000202000000L)==0x0002000202000000L) return 19;
if((x & 0x0020800800000000L)==0x0020800800000000L) return 19;
if((x & 0x0820800000000000L)==0x0820800000000000L) return 19;
break;
case 3:
if((x & 0x0000E00000000000L)==0x0000E00000000000L) return 26;
if((x & 0x0002C00000000000L)==0x0002C00000000000L) return 26;
if((x & 0x0000010101000000L)==0x0000010101000000L) return 26;
if((x & 0x0100010100000000L)==0x0100010100000000L) return 26;
if((x & 0x1040040000000000L)==0x1040040000000000L) return 26;
if((x & 0x0000020408000000L)==0x0000020408000000L) return 26;
break;
case 4:
if((x & 0x0070000000000000L)==0x0070000000000000L) return 33;
if((x & 0x0160000000000000L)==0x0160000000000000L) return 33;
if((x & 0x0000808080000000L)==0x0000808080000000L) return 33;
if((x & 0x8000808000000000L)==0x8000808000000000L) return 33;
if((x & 0x0001020400000000L)==0x0001020400000000L) return 33;
break;
case 5:
if((x & 0x3800000000000000L)==0x3800000000000000L) return 40;
if((x & 0xB000000000000000L)==0xB000000000000000L) return 40;
if((x & 0x0040404000000000L)==0x0040404000000000L) return 40;
if((x & 0x0081020000000000L)==0x0081020000000000L) return 40;
break;
default:
break;
}
switch(p.height[6]) {
case 0:
if((x & 0x000000000E000000L)==0x000000000E000000L) return 6;
if((x & 0x0000410400000000L)==0x0000410400000000L) return 6;
break;
case 1:
if((x & 0x0000000700000000L)==0x0000000700000000L) return 13;
if((x & 0x0020820000000000L)==0x0020820000000000L) return 13;
break;
case 2:
if((x & 0x0000038000000000L)==0x0000038000000000L) return 20;
if((x & 0x1041000000000000L)==0x1041000000000000L) return 20;
break;
case 3:
if((x & 0x0001C00000000000L)==0x0001C00000000000L) return 27;
if((x & 0x0000020202000000L)==0x0000020202000000L) return 27;
if((x & 0x0000040810000000L)==0x0000040810000000L) return 27;
break;
case 4:
if((x & 0x00E0000000000000L)==0x00E0000000000000L) return 34;
if((x & 0x0001010100000000L)==0x0001010100000000L) return 34;
if((x & 0x0002040800000000L)==0x0002040800000000L) return 34;
break;
case 5:
if((x & 0x7000000000000000L)==0x7000000000000000L) return 41;
if((x & 0x0080808000000000L)==0x0080808000000000L) return 41;
if((x & 0x0102040000000000L)==0x0102040000000000L) return 41;
break;
default:
break;
}
return -1;
}

/*
* Stellt die aktuellen Drohungen von s in p fest und speichert sie in dem jeweiligen Threats-Array
*/

private void getthreats(Position p, boolean s) {

long x = (s==p.WHITE ? p.whiteDiscs : p.blackDiscs);
boolean[][] threats = (s==p.WHITE ? whitethreats : blackthreats);

switch(p.height[0]) {
case 0:
if((x & 0x0000000003800000L)==0x0000000003800000L) threats[0][0]=true;
else if((x & 0x0000404040000000L)==0x0000404040000000L) threats[0][0]=true;
else threats[0][0] = false;
case 1:
if((x & 0x00000001C0000000L)==0x00000001C0000000L) threats[0][1]=true;
else if((x & 0x0020202000000000L)==0x0020202000000000L) threats[0][1]=true;
else threats[0][1] = false;
case 2:
if((x & 0x000000E000000000L)==0x000000E000000000L) threats[0][2]=true;
else if((x & 0x1010100000000000L)==0x1010100000000000L) threats[0][2]=true;
else threats[0][2] = false;
case 3:
if((x & 0x0000700000000000L)==0x0000700000000000L) threats[0][3]=true;
else if((x & 0x0000002082000000L)==0x0000002082000000L) threats[0][3]=true;
else if((x & 0x0000001020400000L)==0x0000001020400000L) threats[0][3]=true;
else threats[0][3] = false;
case 4:
if((x & 0x0038000000000000L)==0x0038000000000000L) threats[0][4]=true;
else if((x & 0x0000104100000000L)==0x0000104100000000L) threats[0][4]=true;
else if((x & 0x0000081020000000L)==0x0000081020000000L) threats[0][4]=true;
else threats[0][4] = false;
case 5:
if((x & 0x1C00000000000000L)==0x1C00000000000000L) threats[0][5]=true;
else if((x & 0x0008208000000000L)==0x0008208000000000L) threats[0][5]=true;
else if((x & 0x0004081000000000L)==0x0004081000000000L) threats[0][5]=true;
else threats[0][5] = false;
default:
break;
}
switch(p.height[1]) {
case 0:
if((x & 0x0000000003400000L)==0x0000000003400000L) threats[1][0]=true;
else if((x & 0x0000000007000000L)==0x0000000007000000L) threats[1][0]=true;
else if((x & 0x0000808080000000L)==0x0000808080000000L) threats[1][0]=true;
else threats[1][0] = false;
case 1:
if((x & 0x00000001A0000000L)==0x00000001A0000000L) threats[1][1]=true;
else if((x & 0x0000000380000000L)==0x0000000380000000L) threats[1][1]=true;
else if((x & 0x0000404000400000L)==0x0000404000400000L) threats[1][1]=true;
else if((x & 0x0040404000000000L)==0x0040404000000000L) threats[1][1]=true;
else threats[1][1] = false;
case 2:
if((x & 0x000000D000000000L)==0x000000D000000000L) threats[1][2]=true;
else if((x & 0x000001C000000000L)==0x000001C000000000L) threats[1][2]=true;
else if((x & 0x0020200020000000L)==0x0020200020000000L) threats[1][2]=true;
else if((x & 0x2020200000000000L)==0x2020200000000000L) threats[1][2]=true;
else if((x & 0x0000080082000000L)==0x0000080082000000L) threats[1][2]=true;
else threats[1][2] = false;
case 3:
if((x & 0x0000680000000000L)==0x0000680000000000L) threats[1][3]=true;
else if((x & 0x0000E00000000000L)==0x0000E00000000000L) threats[1][3]=true;
else if((x & 0x0000004104000000L)==0x0000004104000000L) threats[1][3]=true;
else if((x & 0x0004004100000000L)==0x0004004100000000L) threats[1][3]=true;
else if((x & 0x1010001000000000L)==0x1010001000000000L) threats[1][3]=true;
else if((x & 0x0000002040800000L)==0x0000002040800000L) threats[1][3]=true;
else threats[1][3] = false;
case 4:
if((x & 0x0034000000000000L)==0x0034000000000000L) threats[1][4]=true;
else if((x & 0x0070000000000000L)==0x0070000000000000L) threats[1][4]=true;
else if((x & 0x0000208200000000L)==0x0000208200000000L) threats[1][4]=true;
else if((x & 0x0200208000000000L)==0x0200208000000000L) threats[1][4]=true;
else if((x & 0x0000102040000000L)==0x0000102040000000L) threats[1][4]=true;
else threats[1][4] = false;
case 5:
if((x & 0x1A00000000000000L)==0x1A00000000000000L) threats[1][5]=true;
else if((x & 0x3800000000000000L)==0x3800000000000000L) threats[1][5]=true;
else if((x & 0x0010410000000000L)==0x0010410000000000L) threats[1][5]=true;
else if((x & 0x0008102000000000L)==0x0008102000000000L) threats[1][5]=true;
else threats[1][5] = false;
default:
break;
}
switch(p.height[2]) {
case 0:
if((x & 0x0000000002C00000L)==0x0000000002C00000L) threats[2][0]=true;
else if((x & 0x0000000006800000L)==0x0000000006800000L) threats[2][0]=true;
else if((x & 0x000000000E000000L)==0x000000000E000000L) threats[2][0]=true;
else if((x & 0x0001010100000000L)==0x0001010100000000L) threats[2][0]=true;
else threats[2][0] = false;
case 1:
if((x & 0x0000000160000000L)==0x0000000160000000L) threats[2][1]=true;
else if((x & 0x0000000340000000L)==0x0000000340000000L) threats[2][1]=true;
else if((x & 0x0000000700000000L)==0x0000000700000000L) threats[2][1]=true;
else if((x & 0x0000082002000000L)==0x0000082002000000L) threats[2][1]=true;
else if((x & 0x0000808000800000L)==0x0000808000800000L) threats[2][1]=true;
else if((x & 0x0080808000000000L)==0x0080808000000000L) threats[2][1]=true;
else threats[2][1] = false;
case 2:
if((x & 0x000000B000000000L)==0x000000B000000000L) threats[2][2]=true;
else if((x & 0x000001A000000000L)==0x000001A000000000L) threats[2][2]=true;
else if((x & 0x0000038000000000L)==0x0000038000000000L) threats[2][2]=true;
else if((x & 0x0000400040400000L)==0x0000400040400000L) threats[2][2]=true;
else if((x & 0x0040400040000000L)==0x0040400040000000L) threats[2][2]=true;
else if((x & 0x4040400000000000L)==0x4040400000000000L) threats[2][2]=true;
else if((x & 0x0000100104000000L)==0x0000100104000000L) threats[2][2]=true;
else if((x & 0x0004100100000000L)==0x0004100100000000L) threats[2][2]=true;
else threats[2][2] = false;
case 3:
if((x & 0x0000580000000000L)==0x0000580000000000L) threats[2][3]=true;
else if((x & 0x0000D00000000000L)==0x0000D00000000000L) threats[2][3]=true;
else if((x & 0x0001C00000000000L)==0x0001C00000000000L) threats[2][3]=true;
else if((x & 0x0020002020000000L)==0x0020002020000000L) threats[2][3]=true;
else if((x & 0x2020002000000000L)==0x2020002000000000L) threats[2][3]=true;
else if((x & 0x0000008208000000L)==0x0000008208000000L) threats[2][3]=true;
else if((x & 0x0008008200000000L)==0x0008008200000000L) threats[2][3]=true;
else if((x & 0x0208008000000000L)==0x0208008000000000L) threats[2][3]=true;
else if((x & 0x0000004081000000L)==0x0000004081000000L) threats[2][3]=true;
else threats[2][3] = false;
case 4:
if((x & 0x002C000000000000L)==0x002C000000000000L) threats[2][4]=true;
else if((x & 0x0068000000000000L)==0x0068000000000000L) threats[2][4]=true;
else if((x & 0x00E0000000000000L)==0x00E0000000000000L) threats[2][4]=true;
else if((x & 0x0000410400000000L)==0x0000410400000000L) threats[2][4]=true;
else if((x & 0x0400410000000000L)==0x0400410000000000L) threats[2][4]=true;
else if((x & 0x1000101000000000L)==0x1000101000000000L) threats[2][4]=true;
else if((x & 0x0000204080000000L)==0x0000204080000000L) threats[2][4]=true;
else threats[2][4] = false;
case 5:
if((x & 0x1600000000000000L)==0x1600000000000000L) threats[2][5]=true;
else if((x & 0x3400000000000000L)==0x3400000000000000L) threats[2][5]=true;
else if((x & 0x7000000000000000L)==0x7000000000000000L) threats[2][5]=true;
else if((x & 0x0020820000000000L)==0x0020820000000000L) threats[2][5]=true;
else if((x & 0x0010204000000000L)==0x0010204000000000L) threats[2][5]=true;
else threats[2][5] = false;
default:
break;
}
switch(p.height[3]) {
case 0:
if((x & 0x0000000001C00000L)==0x0000000001C00000L) threats[3][0]=true;
else if((x & 0x0000000005800000L)==0x0000000005800000L) threats[3][0]=true;
else if((x & 0x000000000D000000L)==0x000000000D000000L) threats[3][0]=true;
else if((x & 0x000000001C000000L)==0x000000001C000000L) threats[3][0]=true;
else if((x & 0x0000082080000000L)==0x0000082080000000L) threats[3][0]=true;
else if((x & 0x0002020200000000L)==0x0002020200000000L) threats[3][0]=true;
else threats[3][0] = false;
case 1:
if((x & 0x00000000E0000000L)==0x00000000E0000000L) threats[3][1]=true;
else if((x & 0x00000002C0000000L)==0x00000002C0000000L) threats[3][1]=true;
else if((x & 0x0000000680000000L)==0x0000000680000000L) threats[3][1]=true;
else if((x & 0x0000000E00000000L)==0x0000000E00000000L) threats[3][1]=true;
else if((x & 0x0000104004000000L)==0x0000104004000000L) threats[3][1]=true;
else if((x & 0x0004104000000000L)==0x0004104000000000L) threats[3][1]=true;
else if((x & 0x0001010001000000L)==0x0001010001000000L) threats[3][1]=true;
else if((x & 0x0101010000000000L)==0x0101010000000000L) threats[3][1]=true;
else threats[3][1] = false;
case 2:
if((x & 0x0000007000000000L)==0x0000007000000000L) threats[3][2]=true;
else if((x & 0x0000016000000000L)==0x0000016000000000L) threats[3][2]=true;
else if((x & 0x0000034000000000L)==0x0000034000000000L) threats[3][2]=true;
else if((x & 0x0000070000000000L)==0x0000070000000000L) threats[3][2]=true;
else if((x & 0x0000800080800000L)==0x0000800080800000L) threats[3][2]=true;
else if((x & 0x0080800080000000L)==0x0080800080000000L) threats[3][2]=true;
else if((x & 0x8080800000000000L)==0x8080800000000000L) threats[3][2]=true;
else if((x & 0x0000200208000000L)==0x0000200208000000L) threats[3][2]=true;
else if((x & 0x0008200200000000L)==0x0008200200000000L) threats[3][2]=true;
else if((x & 0x0208200000000000L)==0x0208200000000000L) threats[3][2]=true;
else threats[3][2] = false;
case 3:
if((x & 0x0000380000000000L)==0x0000380000000000L) threats[3][3]=true;
else if((x & 0x0000B00000000000L)==0x0000B00000000000L) threats[3][3]=true;
else if((x & 0x0001A00000000000L)==0x0001A00000000000L) threats[3][3]=true;
else if((x & 0x0003800000000000L)==0x0003800000000000L) threats[3][3]=true;
else if((x & 0x0000004040400000L)==0x0000004040400000L) threats[3][3]=true;
else if((x & 0x0040004040000000L)==0x0040004040000000L) threats[3][3]=true;
else if((x & 0x4040004000000000L)==0x4040004000000000L) threats[3][3]=true;
else if((x & 0x0000010410000000L)==0x0000010410000000L) threats[3][3]=true;
else if((x & 0x0010010400000000L)==0x0010010400000000L) threats[3][3]=true;
else if((x & 0x0410010000000000L)==0x0410010000000000L) threats[3][3]=true;
else if((x & 0x0000008102000000L)==0x0000008102000000L) threats[3][3]=true;
else threats[3][3] = false;
case 4:
if((x & 0x001C000000000000L)==0x001C000000000000L) threats[3][4]=true;
else if((x & 0x0058000000000000L)==0x0058000000000000L) threats[3][4]=true;
else if((x & 0x00D0000000000000L)==0x00D0000000000000L) threats[3][4]=true;
else if((x & 0x01C0000000000000L)==0x01C0000000000000L) threats[3][4]=true;
else if((x & 0x0000202020000000L)==0x0000202020000000L) threats[3][4]=true;
else if((x & 0x2000202000000000L)==0x2000202000000000L) threats[3][4]=true;
else if((x & 0x0000820800000000L)==0x0000820800000000L) threats[3][4]=true;
else if((x & 0x0800820000000000L)==0x0800820000000000L) threats[3][4]=true;
else if((x & 0x0000408100000000L)==0x0000408100000000L) threats[3][4]=true;
else threats[3][4] = false;
case 5:
if((x & 0x0E00000000000000L)==0x0E00000000000000L) threats[3][5]=true;
else if((x & 0x2C00000000000000L)==0x2C00000000000000L) threats[3][5]=true;
else if((x & 0x6800000000000000L)==0x6800000000000000L) threats[3][5]=true;
else if((x & 0xE000000000000000L)==0xE000000000000000L) threats[3][5]=true;
else if((x & 0x0010101000000000L)==0x0010101000000000L) threats[3][5]=true;
else if((x & 0x0041040000000000L)==0x0041040000000000L) threats[3][5]=true;
else if((x & 0x0020408000000000L)==0x0020408000000000L) threats[3][5]=true;
else threats[3][5] = false;
default:
break;
}
switch(p.height[4]) {
case 0:
if((x & 0x0000000003800000L)==0x0000000003800000L) threats[4][0]=true;
else if((x & 0x000000000B000000L)==0x000000000B000000L) threats[4][0]=true;
else if((x & 0x000000001A000000L)==0x000000001A000000L) threats[4][0]=true;
else if((x & 0x0000104100000000L)==0x0000104100000000L) threats[4][0]=true;
else threats[4][0] = false;
case 1:
if((x & 0x00000001C0000000L)==0x00000001C0000000L) threats[4][1]=true;
else if((x & 0x0000000580000000L)==0x0000000580000000L) threats[4][1]=true;
else if((x & 0x0000000D00000000L)==0x0000000D00000000L) threats[4][1]=true;
else if((x & 0x0002020002000000L)==0x0002020002000000L) threats[4][1]=true;
else if((x & 0x0000208008000000L)==0x0000208008000000L) threats[4][1]=true;
else if((x & 0x0008208000000000L)==0x0008208000000000L) threats[4][1]=true;
else threats[4][1] = false;
case 2:
if((x & 0x000000E000000000L)==0x000000E000000000L) threats[4][2]=true;
else if((x & 0x000002C000000000L)==0x000002C000000000L) threats[4][2]=true;
else if((x & 0x0000068000000000L)==0x0000068000000000L) threats[4][2]=true;
else if((x & 0x0001000101000000L)==0x0001000101000000L) threats[4][2]=true;
else if((x & 0x0101000100000000L)==0x0101000100000000L) threats[4][2]=true;
else if((x & 0x0000400410000000L)==0x0000400410000000L) threats[4][2]=true;
else if((x & 0x0010400400000000L)==0x0010400400000000L) threats[4][2]=true;
else if((x & 0x0410400000000000L)==0x0410400000000000L) threats[4][2]=true;
else threats[4][2] = false;
case 3:
if((x & 0x0000700000000000L)==0x0000700000000000L) threats[4][3]=true;
else if((x & 0x0001600000000000L)==0x0001600000000000L) threats[4][3]=true;
else if((x & 0x0003400000000000L)==0x0003400000000000L) threats[4][3]=true;
else if((x & 0x0000008080800000L)==0x0000008080800000L) threats[4][3]=true;
else if((x & 0x0080008080000000L)==0x0080008080000000L) threats[4][3]=true;
else if((x & 0x8080008000000000L)==0x8080008000000000L) threats[4][3]=true;
else if((x & 0x0020020800000000L)==0x0020020800000000L) threats[4][3]=true;
else if((x & 0x0820020000000000L)==0x0820020000000000L) threats[4][3]=true;
else if((x & 0x0000010204000000L)==0x0000010204000000L) threats[4][3]=true;
else threats[4][3] = false;
case 4:
if((x & 0x0038000000000000L)==0x0038000000000000L) threats[4][4]=true;
else if((x & 0x00B0000000000000L)==0x00B0000000000000L) threats[4][4]=true;
else if((x & 0x01A0000000000000L)==0x01A0000000000000L) threats[4][4]=true;
else if((x & 0x0000404040000000L)==0x0000404040000000L) threats[4][4]=true;
else if((x & 0x4000404000000000L)==0x4000404000000000L) threats[4][4]=true;
else if((x & 0x1001040000000000L)==0x1001040000000000L) threats[4][4]=true;
else if((x & 0x0000810200000000L)==0x0000810200000000L) threats[4][4]=true;
else threats[4][4] = false;
case 5:
if((x & 0x1C00000000000000L)==0x1C00000000000000L) threats[4][5]=true;
else if((x & 0x5800000000000000L)==0x5800000000000000L) threats[4][5]=true;
else if((x & 0xD000000000000000L)==0xD000000000000000L) threats[4][5]=true;
else if((x & 0x0020202000000000L)==0x0020202000000000L) threats[4][5]=true;
else if((x & 0x0040810000000000L)==0x0040810000000000L) threats[4][5]=true;
else threats[4][5] = false;
default:
break;
}
switch(p.height[5]) {
case 0:
if((x & 0x0000000007000000L)==0x0000000007000000L) threats[5][0]=true;
else if((x & 0x0000000016000000L)==0x0000000016000000L) threats[5][0]=true;
else if((x & 0x0000208200000000L)==0x0000208200000000L) threats[5][0]=true;
else threats[5][0] = false;
case 1:
if((x & 0x0000000380000000L)==0x0000000380000000L) threats[5][1]=true;
else if((x & 0x0000000B00000000L)==0x0000000B00000000L) threats[5][1]=true;
else if((x & 0x0000410010000000L)==0x0000410010000000L) threats[5][1]=true;
else if((x & 0x0010410000000000L)==0x0010410000000000L) threats[5][1]=true;
else threats[5][1] = false;
case 2:
if((x & 0x000001C000000000L)==0x000001C000000000L) threats[5][2]=true;
else if((x & 0x0000058000000000L)==0x0000058000000000L) threats[5][2]=true;
else if((x & 0x0002000202000000L)==0x0002000202000000L) threats[5][2]=true;
else if((x & 0x0020800800000000L)==0x0020800800000000L) threats[5][2]=true;
else if((x & 0x0820800000000000L)==0x0820800000000000L) threats[5][2]=true;
else threats[5][2] = false;
case 3:
if((x & 0x0000E00000000000L)==0x0000E00000000000L) threats[5][3]=true;
else if((x & 0x0002C00000000000L)==0x0002C00000000000L) threats[5][3]=true;
else if((x & 0x0000010101000000L)==0x0000010101000000L) threats[5][3]=true;
else if((x & 0x0100010100000000L)==0x0100010100000000L) threats[5][3]=true;
else if((x & 0x1040040000000000L)==0x1040040000000000L) threats[5][3]=true;
else if((x & 0x0000020408000000L)==0x0000020408000000L) threats[5][3]=true;
else threats[5][3] = false;
case 4:
if((x & 0x0070000000000000L)==0x0070000000000000L) threats[5][4]=true;
else if((x & 0x0160000000000000L)==0x0160000000000000L) threats[5][4]=true;
else if((x & 0x0000808080000000L)==0x0000808080000000L) threats[5][4]=true;
else if((x & 0x8000808000000000L)==0x8000808000000000L) threats[5][4]=true;
else if((x & 0x0001020400000000L)==0x0001020400000000L) threats[5][4]=true;
else threats[5][4] = false;
case 5:
if((x & 0x3800000000000000L)==0x3800000000000000L) threats[5][5]=true;
else if((x & 0xB000000000000000L)==0xB000000000000000L) threats[5][5]=true;
else if((x & 0x0040404000000000L)==0x0040404000000000L) threats[5][5]=true;
else if((x & 0x0081020000000000L)==0x0081020000000000L) threats[5][5]=true;
else threats[5][5] = false;
default:
break;
}
switch(p.height[6]) {
case 0:
if((x & 0x000000000E000000L)==0x000000000E000000L) threats[6][0]=true;
else if((x & 0x0000410400000000L)==0x0000410400000000L) threats[6][0]=true;
else threats[6][0] = false;
case 1:
if((x & 0x0000000700000000L)==0x0000000700000000L) threats[6][1]=true;
else if((x & 0x0020820000000000L)==0x0020820000000000L) threats[6][1]=true;
else threats[6][1] = false;
case 2:
if((x & 0x0000038000000000L)==0x0000038000000000L) threats[6][2]=true;
else if((x & 0x1041000000000000L)==0x1041000000000000L) threats[6][2]=true;
else threats[6][2] = false;
case 3:
if((x & 0x0001C00000000000L)==0x0001C00000000000L) threats[6][3]=true;
else if((x & 0x0000020202000000L)==0x0000020202000000L) threats[6][3]=true;
else if((x & 0x0000040810000000L)==0x0000040810000000L) threats[6][3]=true;
else threats[6][3] = false;
case 4:
if((x & 0x00E0000000000000L)==0x00E0000000000000L) threats[6][4]=true;
else if((x & 0x0001010100000000L)==0x0001010100000000L) threats[6][4]=true;
else if((x & 0x0002040800000000L)==0x0002040800000000L) threats[6][4]=true;
else threats[6][4] = false;
case 5:
if((x & 0x7000000000000000L)==0x7000000000000000L) threats[6][5]=true;
else if((x & 0x0080808000000000L)==0x0080808000000000L) threats[6][5]=true;
else if((x & 0x0102040000000000L)==0x0102040000000000L) threats[6][5]=true;
else threats[6][5] = false;
default:
break;
}

for(int i=0;i<=6;i++) {
for(int j=0;j<p.height[i];j++) {
threats[i][j] = false;
}
}

}

/*
* Erzeugt alle Züge, es sei denn, einer der Spieler hat eine akute Drohung - dann nur einen Zug
*/

private int[] generateMoves(Position p, int depth) {
int b = acuteThreat(p, p.toMove);
if(b!=-1) {
moves[depth][7] = 1;
moves[depth][0] = b;
return moves[depth];
}
int a = acuteThreat(p, !p.toMove);
if(a!=-1) {
moves[depth][7] = 1;
moves[depth][0] = a;
return moves[depth];
}
int size = 0;
if(p.height[0]<6) {
moves[depth][size]=p.height[0]*7+0;
size += 1;
}
if(p.height[1]<6) {
moves[depth][size]=p.height[1]*7+1;
size += 1;
}
if(p.height[2]<6) {
moves[depth][size]=p.height[2]*7+2;
size += 1;
}
if(p.height[3]<6) {
moves[depth][size]=p.height[3]*7+3;
size += 1;
}
if(p.height[4]<6) {
moves[depth][size]=p.height[4]*7+4;
size += 1;
}
if(p.height[5]<6) {
moves[depth][size]=p.height[5]*7+5;
size += 1;
}
if(p.height[6]<6) {
moves[depth][size]=p.height[6]*7+6;
size += 1;
}
moves[depth][7] = size;
return moves[depth];
}

}

/*
* Zum Suchabbruch nach NODELIMIT Knoten
*/

class TooManyNodesException extends Exception {
}

/*
* Zur lesbaren Darstellung von Zügen (0-41) für den Benutzer (a1-g6)
*/

class MovePrinter {

public static String printMove(int m) {
String s = new String();
switch(m%7) {
case 0:
s = s.concat("a");
break;
case 1:
s = s.concat("b");
break;
case 2:
s = s.concat("c");
break;
case 3:
s = s.concat("d");
break;
case 4:
s = s.concat("e");
break;
case 5:
s = s.concat("f");
break;
case 6:
s = s.concat("g");
break;
default:
break;
}
s = s.concat(String.valueOf((m/7)+1));
return s;
}

}

A A A | Drucken | Impressum | Sitemap | Suche | Mobile Version
zum Seitenanfangzum Seitenanfang