package c4;
import java.io.Serializable;
import java.util.Random;
import java.util.concurrent.Semaphore;
import nTupleTD.TDSAgent;
import openingBook.BookSum;
/**
*
* This class is an implementation of a classical Alpha-Beta-Agent. It is recommended to
* use the implemented Methods by Agent. This Agent uses Transposition-Tables,
* Move-ordering, opening Books, symmetries and some other techniques to get
* fast results.
*
*
* Changes:
* 12.12.2011: alphaBetaStartP1 and alphaBetaStartP2 look for the most distant
* loss. This makes the search a little bit slower, but allows a better
* evaluation of the td-agent
*
* @author Markus Thill
*
*/
public class AlphaBetaAgent extends ConnectFour implements Agent, Serializable {
private static final long serialVersionUID = 5000820077350196867L;
private Random rand = new Random();
// Binary Semaphore, to prevent multiple access (e.g. by parallel threads)
private Semaphore mutex; // = new Semaphore(1);
// Transposition Table Constants
private static final int[] TRANSPOSSIZE = { 262144, 524288, 1048576,
2097152, 4194304, 8388608, 16777216, 33554432 };
public static final int[] TRANSPOSBYTES = { 262144 * 99 / 8,
524288 * 99 / 8, 1048576 * 99 / 8, 2097152 * 99 / 8,
4194304 * 99 / 8, 8388608 * 99 / 8, 16777216 * 99 / 8,
33554432 / 8 * 99 };
private int transPosSize = 4194304 / 2;
private int lTransPosSize = transPosSize / 8;
private static final byte TRANSPOSEXACT = 1;
private static final byte TRANSPOSUPPER = 2;
private static final byte TRANSPOSLOWER = 3;
// Random-Numbers for Zobrist Keys
private static final long rnd20[] = { 0L, 2704506115994628L,
886077597871704230L, 49389502572435258L, 82333996817139652L,
263967204879563328L, 81975673952415600L };
private static final long rnd21[] = { 0L, 73398886193708064L,
1595863713887220963L, 46261610206381440L, 58705059883690202L,
231696507446129885L, 22606427398883328L };
private static final long rnd22[] = { 0L, 12595346104058426L,
4097820997223100L, 101324622437045280L, 31779374605300125L,
35633797708573350L, 22416112427922675L };
private static final long rnd23[] = { 0L, 36363358841386824L,
4173667863902779612L, 9131869703157656L, 14138249969764235L,
214348955873908032L, 58547228054472360L };
private static final long rnd24[] = { 0L, 55740094356093127L,
1777939723684020L, 362858203316162568L, 28975890403315160L,
1242349240448115806L, 59601464106441712L };
private static final long rnd25[] = { 0L, 9110872168202946L,
10631234269963860L, 16888881020037981L, 1159792823631456L,
36205525950397736L, 47068546447093808L };
private static final long rnd26[] = { 0L, 375817237236357603L,
32189775283681470L, 1493718293429439L, 20793138156733824L,
101478045365676084L, 110552240521049760L };
private static final long rnd10[] = { 0L, 19298943901485610L,
6548220796761019L, 1777628907278452803L, 11891769178478592L,
3564258696970080L, 236708853179436288L };
private static final long rnd11[] = { 0L, 349182760342233125L,
429289086240375L, 121921717543355343L, 31495429917193824L,
5694462647075520L, 30758051047680284L };
private static final long rnd12[] = { 0L, 1365712501364505581L,
17363511325679223L, 119226791868480L, 6220173073409360L,
11647770880598424L, 24507207907919492L };
private static final long rnd13[] = { 0L, 551903736927872L,
2097977134396858L, 3108717381973636075L, 25389306976498643L,
254362479754036508L, 119080142037405540L };
private static final long rnd14[] = { 0L, 65628472867223040L,
116416206906490816L, 130703539652185785L, 1541174198942728362L,
37852277734190556L, 22426187114508354L };
private static final long rnd15[] = { 0L, 290694253237906321L,
3460150747465650L, 12108862858045894L, 124792798959719156L,
6572334569141376L, 2726416766762766L };
private static final long rnd16[] = { 0L, 378828340783306008L,
72087612995472200L, 113983283880328672L, 376285078915283L,
62397498210717124L, 1193066389676430L };
// Field-Masks for all Columns
private static final long fieldMask0[] = fieldMask[0];
private static final long fieldMask1[] = fieldMask[1];
private static final long fieldMask2[] = fieldMask[2];
private static final long fieldMask3[] = fieldMask[3];
private static final long fieldMask4[] = fieldMask[4];
private static final long fieldMask5[] = fieldMask[5];
private static final long fieldMask6[] = fieldMask[6];
// For Alpha-Beta-Search
private int movesTillFull = 0;
private int searchDepth = 100;
// Opening Book
private boolean useBook = false;
private boolean useDeepBook = false;
private boolean useDeepBookDist = true;
// Transposition Table for higher Search-Depths
private long key[] = new long[transPosSize];
private short value[] = new short[transPosSize];
private byte flag[] = new byte[transPosSize];
// Transposition Table for lower Search-Depths
private long lKey[] = new long[lTransPosSize];
private short lValue[] = new short[lTransPosSize];
private byte lFlag[] = new byte[lTransPosSize];
// If is already searching for a far loose: Don't Change!!!
private boolean seekFarLoose = false;
private int looseIntervall = 20;
// All opening Books
private BookSum books = null;
// Random Choice for a Move if more than one equal Value
private boolean randomizeEqualMoves = true;
// Random Choice for a Move, when more than one equal value
// For a loss make a complete random Move;
private boolean randomizeLosses = false;
private TDSAgent tds = null;
/**
* Generate an empty Board
*/
public AlphaBetaAgent(BookSum books) {
super();
this.books = books;
mutex = new Semaphore(1);
}
/**
* @param field
* a 7x6 Connect-Four Board: 1 -> Player 1 (Beginner) 2 -> Player
* 2
*/
public AlphaBetaAgent(int field[][], BookSum books) {
super(field);
this.books = books;
mutex = new Semaphore(1);
}
/**
* Create a new Board
*
* @param fieldP1
* BitBoard of Player1
* @param fieldP2
* BitBoard of Player2
*/
public AlphaBetaAgent(long fieldP1, long fieldP2, BookSum books) {
super(fieldP1, fieldP2);
this.books = books;
mutex = new Semaphore(1);
}
/**
* Init the Transposition-Table. All Values are set to ZERO
*/
public void initTranspositionTable() {
for (int i = 0; i < transPosSize; i++) {
key[i] = 0L;
value[i] = 0;
flag[i] = 0;
}
// Transposition Table for lower Search-Depths
for (int i = 0; i < lTransPosSize; i++) {
lKey[i] = 0L;
lValue[i] = 0;
lFlag[i] = 0;
}
}
/**
* The difficulty of the AlphaBeta-Player is distinguished by the search
* Depth
*
* @param searchDepth
*/
public void setDifficulty(int searchDepth) {
this.searchDepth = (searchDepth + (searchDepth % 2 == 0 ? 1 : 0));
}
/**
* This Method (the source) was generated with a C-program, because its
* source-code is very long.
* Find a field, in which player can create a threat.
*
* @param player
* @param startWithCol
* Column to start with search
* @return column for creating a threat, or else -1
*/
protected int findThreat(int player, int startWithCol) {
// Prüfen, ob eine Drohung erstellt werden kann
long temp = (player == PLAYER1 ? fieldP1 : fieldP2);
switch (startWithCol) {
case 0:
switch (colHeight[0]) {
case 0:
if ((temp & 0x808100000L) == 0x8100000L && colHeight[1] < 1) {
return 0;
}
if ((temp & 0x410100000L) == 0x400100000L && colHeight[2] < 2) {
return 0;
}
if ((temp & 0x408200000L) == 0x408000000L && colHeight[3] < 3) {
return 0;
}
break;
case 1:
if ((temp & 0x404080000L) == 0x4080000L && colHeight[1] < 2) {
return 0;
}
if ((temp & 0x208080000L) == 0x200080000L && colHeight[2] < 3) {
return 0;
}
if ((temp & 0x204100000L) == 0x204000000L && colHeight[3] < 4) {
return 0;
}
if ((temp & 0x810400000L) == 0x10400000L && colHeight[1] < 1) {
return 0;
}
if ((temp & 0x420400000L) == 0x400400000L && colHeight[2] < 1) {
return 0;
}
if ((temp & 0x410800000L) == 0x410000000L && colHeight[3] < 1) {
return 0;
}
break;
case 2:
if ((temp & 0x202040000L) == 0x2040000L && colHeight[1] < 3) {
return 0;
}
if ((temp & 0x104040000L) == 0x100040000L && colHeight[2] < 4) {
return 0;
}
if ((temp & 0x102080000L) == 0x102000000L && colHeight[3] < 5) {
return 0;
}
if ((temp & 0x408200000L) == 0x8200000L && colHeight[1] < 2) {
return 0;
}
if ((temp & 0x210200000L) == 0x200200000L && colHeight[2] < 2) {
return 0;
}
if ((temp & 0x208400000L) == 0x208000000L && colHeight[3] < 2) {
return 0;
}
break;
case 3:
if ((temp & 0x204100000L) == 0x4100000L && colHeight[1] < 3) {
return 0;
}
if ((temp & 0x108100000L) == 0x100100000L && colHeight[2] < 3) {
return 0;
}
if ((temp & 0x104200000L) == 0x104000000L && colHeight[3] < 3) {
return 0;
}
if ((temp & 0x410800000L) == 0x10800000L && colHeight[1] < 2) {
return 0;
}
if ((temp & 0x220800000L) == 0x200800000L && colHeight[2] < 1) {
return 0;
}
break;
case 4:
if ((temp & 0x102080000L) == 0x2080000L && colHeight[1] < 4) {
return 0;
}
if ((temp & 0x84080000L) == 0x80080000L && colHeight[2] < 4) {
return 0;
}
if ((temp & 0x82100000L) == 0x82000000L && colHeight[3] < 4) {
return 0;
}
if ((temp & 0x208400000L) == 0x8400000L && colHeight[1] < 3) {
return 0;
}
if ((temp & 0x110400000L) == 0x100400000L && colHeight[2] < 2) {
return 0;
}
if ((temp & 0x108800000L) == 0x108000000L && colHeight[3] < 1) {
return 0;
}
break;
case 5:
if ((temp & 0x81040000L) == 0x1040000L && colHeight[1] < 5) {
return 0;
}
if ((temp & 0x42040000L) == 0x40040000L && colHeight[2] < 5) {
return 0;
}
if ((temp & 0x41080000L) == 0x41000000L && colHeight[3] < 5) {
return 0;
}
if ((temp & 0x104200000L) == 0x4200000L && colHeight[1] < 4) {
return 0;
}
if ((temp & 0x88200000L) == 0x80200000L && colHeight[2] < 3) {
return 0;
}
if ((temp & 0x84400000L) == 0x84000000L && colHeight[3] < 2) {
return 0;
}
break;
default:
break;
}
case 1:
switch (colHeight[1]) {
case 0:
if ((temp & 0x204000L) == 0x204000L && colHeight[2] < 1) {
return 1;
}
if ((temp & 0x10004000L) == 0x10004000L && colHeight[3] < 2) {
return 1;
}
if ((temp & 0x10200000L) == 0x10200000L && colHeight[4] < 3) {
return 1;
}
break;
case 1:
if ((temp & 0x102000L) == 0x102000L && colHeight[2] < 2) {
return 1;
}
if ((temp & 0x8002000L) == 0x8002000L && colHeight[3] < 3) {
return 1;
}
if ((temp & 0x8100000L) == 0x8100000L && colHeight[4] < 4) {
return 1;
}
if ((temp & 0x20000100000L) == 0x20000100000L
&& colHeight[2] < 2) {
return 1;
}
if ((temp & 0x20008000000L) == 0x20008000000L
&& colHeight[3] < 3) {
return 1;
}
if ((temp & 0x10400000L) == 0x10400000L
&& (colHeight[0] < 1 || colHeight[4] < 1)) {
return 1;
}
if ((temp & 0x10000400000L) == 0x10000400000L
&& colHeight[2] < 1) {
return 1;
}
if ((temp & 0x10010000000L) == 0x10010000000L
&& colHeight[3] < 1) {
return 1;
}
if ((temp & 0x410000L) == 0x410000L && colHeight[2] < 1) {
return 1;
}
if ((temp & 0x10010000L) == 0x10010000L && colHeight[3] < 1) {
return 1;
}
break;
case 2:
if ((temp & 0x81000L) == 0x81000L && colHeight[2] < 3) {
return 1;
}
if ((temp & 0x4001000L) == 0x4001000L && colHeight[3] < 4) {
return 1;
}
if ((temp & 0x4080000L) == 0x4080000L
&& (colHeight[0] < 1 || colHeight[4] < 5)) {
return 1;
}
if ((temp & 0x10000080000L) == 0x10000080000L
&& colHeight[2] < 3) {
return 1;
}
if ((temp & 0x10004000000L) == 0x10004000000L
&& colHeight[3] < 4) {
return 1;
}
if ((temp & 0x8200000L) == 0x8200000L
&& (colHeight[0] < 2 || colHeight[4] < 2)) {
return 1;
}
if ((temp & 0x8000200000L) == 0x8000200000L && colHeight[2] < 2) {
return 1;
}
if ((temp & 0x8008000000L) == 0x8008000000L && colHeight[3] < 2) {
return 1;
}
if ((temp & 0x208000L) == 0x208000L && colHeight[2] < 2) {
return 1;
}
if ((temp & 0x8008000L) == 0x8008000L && colHeight[3] < 2) {
return 1;
}
if ((temp & 0x10800000L) == 0x10800000L && colHeight[0] < 3) {
return 1;
}
if ((temp & 0x4000800000L) == 0x4000800000L && colHeight[2] < 1) {
return 1;
}
break;
case 3:
if ((temp & 0x2040000L) == 0x2040000L && colHeight[0] < 2) {
return 1;
}
if ((temp & 0x8000040000L) == 0x8000040000L && colHeight[2] < 4) {
return 1;
}
if ((temp & 0x8002000000L) == 0x8002000000L && colHeight[3] < 5) {
return 1;
}
if ((temp & 0x4100000L) == 0x4100000L
&& (colHeight[0] < 3 || colHeight[4] < 3)) {
return 1;
}
if ((temp & 0x4000100000L) == 0x4000100000L && colHeight[2] < 3) {
return 1;
}
if ((temp & 0x4004000000L) == 0x4004000000L && colHeight[3] < 3) {
return 1;
}
if ((temp & 0x104000L) == 0x104000L && colHeight[2] < 3) {
return 1;
}
if ((temp & 0x4004000L) == 0x4004000L && colHeight[3] < 3) {
return 1;
}
if ((temp & 0x8400000L) == 0x8400000L && colHeight[0] < 4) {
return 1;
}
if ((temp & 0x2000400000L) == 0x2000400000L && colHeight[2] < 2) {
return 1;
}
if ((temp & 0x2008000000L) == 0x2008000000L && colHeight[3] < 1) {
return 1;
}
if ((temp & 0x420000L) == 0x420000L && colHeight[2] < 2) {
return 1;
}
if ((temp & 0x8020000L) == 0x8020000L && colHeight[3] < 1) {
return 1;
}
break;
case 4:
if ((temp & 0x2080000L) == 0x2080000L
&& (colHeight[0] < 4 || colHeight[4] < 4)) {
return 1;
}
if ((temp & 0x2000080000L) == 0x2000080000L && colHeight[2] < 4) {
return 1;
}
if ((temp & 0x2002000000L) == 0x2002000000L && colHeight[3] < 4) {
return 1;
}
if ((temp & 0x82000L) == 0x82000L && colHeight[2] < 4) {
return 1;
}
if ((temp & 0x2002000L) == 0x2002000L && colHeight[3] < 4) {
return 1;
}
if ((temp & 0x4200000L) == 0x4200000L
&& (colHeight[0] < 5 || colHeight[4] < 1)) {
return 1;
}
if ((temp & 0x1000200000L) == 0x1000200000L && colHeight[2] < 3) {
return 1;
}
if ((temp & 0x1004000000L) == 0x1004000000L && colHeight[3] < 2) {
return 1;
}
if ((temp & 0x210000L) == 0x210000L && colHeight[2] < 3) {
return 1;
}
if ((temp & 0x4010000L) == 0x4010000L && colHeight[3] < 2) {
return 1;
}
break;
case 5:
if ((temp & 0x1040000L) == 0x1040000L
&& (colHeight[0] < 5 || colHeight[4] < 5)) {
return 1;
}
if ((temp & 0x1000040000L) == 0x1000040000L && colHeight[2] < 5) {
return 1;
}
if ((temp & 0x1001000000L) == 0x1001000000L && colHeight[3] < 5) {
return 1;
}
if ((temp & 0x41000L) == 0x41000L && colHeight[2] < 5) {
return 1;
}
if ((temp & 0x1001000L) == 0x1001000L && colHeight[3] < 5) {
return 1;
}
if ((temp & 0x108000L) == 0x108000L && colHeight[2] < 4) {
return 1;
}
if ((temp & 0x2008000L) == 0x2008000L && colHeight[3] < 3) {
return 1;
}
if ((temp & 0x2100000L) == 0x2100000L && colHeight[4] < 2) {
return 1;
}
break;
default:
break;
}
case 2:
switch (colHeight[2]) {
case 0:
if ((temp & 0x8100L) == 0x8100L && colHeight[3] < 1) {
return 2;
}
if ((temp & 0x400100L) == 0x400100L && colHeight[4] < 2) {
return 2;
}
if ((temp & 0x408000L) == 0x408000L && colHeight[5] < 3) {
return 2;
}
break;
case 1:
if ((temp & 0x4080L) == 0x4080L && colHeight[3] < 2) {
return 2;
}
if ((temp & 0x200080L) == 0x200080L && colHeight[4] < 3) {
return 2;
}
if ((temp & 0x204000L) == 0x204000L && colHeight[5] < 4) {
return 2;
}
if ((temp & 0x200800000L) == 0x200800000L && colHeight[0] < 3) {
return 2;
}
if ((temp & 0x4000800000L) == 0x4000800000L && colHeight[1] < 2) {
return 2;
}
if ((temp & 0x800004000L) == 0x800004000L && colHeight[3] < 2) {
return 2;
}
if ((temp & 0x800200000L) == 0x800200000L && colHeight[4] < 3) {
return 2;
}
if ((temp & 0x400400000L) == 0x400400000L
&& (colHeight[0] < 1 || colHeight[4] < 1)) {
return 2;
}
if ((temp & 0x10000400000L) == 0x10000400000L
&& colHeight[1] < 1) {
return 2;
}
if ((temp & 0x10400000000L) == 0x10400000000L
&& colHeight[3] < 1) {
return 2;
}
if ((temp & 0x410000L) == 0x410000L
&& (colHeight[1] < 1 || colHeight[5] < 1)) {
return 2;
}
if ((temp & 0x400010000L) == 0x400010000L && colHeight[3] < 1) {
return 2;
}
if ((temp & 0x10400L) == 0x10400L && colHeight[3] < 1) {
return 2;
}
if ((temp & 0x400400L) == 0x400400L && colHeight[4] < 1) {
return 2;
}
break;
case 2:
if ((temp & 0x2040L) == 0x2040L && colHeight[3] < 3) {
return 2;
}
if ((temp & 0x100040L) == 0x100040L && colHeight[4] < 4) {
return 2;
}
if ((temp & 0x102000L) == 0x102000L
&& (colHeight[1] < 1 || colHeight[5] < 5)) {
return 2;
}
if ((temp & 0x100400000L) == 0x100400000L && colHeight[0] < 4) {
return 2;
}
if ((temp & 0x2000400000L) == 0x2000400000L && colHeight[1] < 3) {
return 2;
}
if ((temp & 0x2100000000L) == 0x2100000000L && colHeight[3] < 1) {
return 2;
}
if ((temp & 0x400002000L) == 0x400002000L && colHeight[3] < 3) {
return 2;
}
if ((temp & 0x400100000L) == 0x400100000L && colHeight[4] < 4) {
return 2;
}
if ((temp & 0x200200000L) == 0x200200000L
&& (colHeight[0] < 2 || colHeight[4] < 2)) {
return 2;
}
if ((temp & 0x8000200000L) == 0x8000200000L && colHeight[1] < 2) {
return 2;
}
if ((temp & 0x8200000000L) == 0x8200000000L && colHeight[3] < 2) {
return 2;
}
if ((temp & 0x208000L) == 0x208000L
&& (colHeight[1] < 2 || colHeight[5] < 2)) {
return 2;
}
if ((temp & 0x200008000L) == 0x200008000L && colHeight[3] < 2) {
return 2;
}
if ((temp & 0x8200L) == 0x8200L && colHeight[3] < 2) {
return 2;
}
if ((temp & 0x200200L) == 0x200200L && colHeight[4] < 2) {
return 2;
}
if ((temp & 0x420000L) == 0x420000L && colHeight[1] < 3) {
return 2;
}
if ((temp & 0x100020000L) == 0x100020000L && colHeight[3] < 1) {
return 2;
}
if ((temp & 0x20000100000L) == 0x20000100000L
&& colHeight[1] < 1) {
return 2;
}
if ((temp & 0x20400000000L) == 0x20400000000L
&& colHeight[3] < 3) {
return 2;
}
break;
case 3:
if ((temp & 0x80200000L) == 0x80200000L
&& (colHeight[0] < 5 || colHeight[4] < 1)) {
return 2;
}
if ((temp & 0x1000200000L) == 0x1000200000L && colHeight[1] < 4) {
return 2;
}
if ((temp & 0x1080000000L) == 0x1080000000L && colHeight[3] < 2) {
return 2;
}
if ((temp & 0x81000L) == 0x81000L && colHeight[1] < 2) {
return 2;
}
if ((temp & 0x200001000L) == 0x200001000L && colHeight[3] < 4) {
return 2;
}
if ((temp & 0x200080000L) == 0x200080000L
&& (colHeight[0] < 1 || colHeight[4] < 5)) {
return 2;
}
if ((temp & 0x100100000L) == 0x100100000L
&& (colHeight[0] < 3 || colHeight[4] < 3)) {
return 2;
}
if ((temp & 0x4000100000L) == 0x4000100000L && colHeight[1] < 3) {
return 2;
}
if ((temp & 0x4100000000L) == 0x4100000000L && colHeight[3] < 3) {
return 2;
}
if ((temp & 0x104000L) == 0x104000L
&& (colHeight[1] < 3 || colHeight[5] < 3)) {
return 2;
}
if ((temp & 0x100004000L) == 0x100004000L && colHeight[3] < 3) {
return 2;
}
if ((temp & 0x4100L) == 0x4100L && colHeight[3] < 3) {
return 2;
}
if ((temp & 0x100100L) == 0x100100L && colHeight[4] < 3) {
return 2;
}
if ((temp & 0x210000L) == 0x210000L && colHeight[1] < 4) {
return 2;
}
if ((temp & 0x80010000L) == 0x80010000L && colHeight[3] < 2) {
return 2;
}
if ((temp & 0x10000080000L) == 0x10000080000L
&& colHeight[1] < 2) {
return 2;
}
if ((temp & 0x10200000000L) == 0x10200000000L
&& colHeight[3] < 4) {
return 2;
}
if ((temp & 0x10800L) == 0x10800L && colHeight[3] < 2) {
return 2;
}
if ((temp & 0x200800L) == 0x200800L && colHeight[4] < 1) {
return 2;
}
break;
case 4:
if ((temp & 0x80080000L) == 0x80080000L
&& (colHeight[0] < 4 || colHeight[4] < 4)) {
return 2;
}
if ((temp & 0x2000080000L) == 0x2000080000L && colHeight[1] < 4) {
return 2;
}
if ((temp & 0x2080000000L) == 0x2080000000L && colHeight[3] < 4) {
return 2;
}
if ((temp & 0x82000L) == 0x82000L
&& (colHeight[1] < 4 || colHeight[5] < 4)) {
return 2;
}
if ((temp & 0x80002000L) == 0x80002000L && colHeight[3] < 4) {
return 2;
}
if ((temp & 0x2080L) == 0x2080L && colHeight[3] < 4) {
return 2;
}
if ((temp & 0x80080L) == 0x80080L && colHeight[4] < 4) {
return 2;
}
if ((temp & 0x108000L) == 0x108000L
&& (colHeight[1] < 5 || colHeight[5] < 1)) {
return 2;
}
if ((temp & 0x40008000L) == 0x40008000L && colHeight[3] < 3) {
return 2;
}
if ((temp & 0x40100000L) == 0x40100000L && colHeight[4] < 2) {
return 2;
}
if ((temp & 0x100040000L) == 0x100040000L && colHeight[0] < 2) {
return 2;
}
if ((temp & 0x8000040000L) == 0x8000040000L && colHeight[1] < 3) {
return 2;
}
if ((temp & 0x8100000000L) == 0x8100000000L && colHeight[3] < 5) {
return 2;
}
if ((temp & 0x8400L) == 0x8400L && colHeight[3] < 3) {
return 2;
}
if ((temp & 0x100400L) == 0x100400L && colHeight[4] < 2) {
return 2;
}
break;
case 5:
if ((temp & 0x40040000L) == 0x40040000L
&& (colHeight[0] < 5 || colHeight[4] < 5)) {
return 2;
}
if ((temp & 0x1000040000L) == 0x1000040000L && colHeight[1] < 5) {
return 2;
}
if ((temp & 0x1040000000L) == 0x1040000000L && colHeight[3] < 5) {
return 2;
}
if ((temp & 0x41000L) == 0x41000L
&& (colHeight[1] < 5 || colHeight[5] < 5)) {
return 2;
}
if ((temp & 0x40001000L) == 0x40001000L && colHeight[3] < 5) {
return 2;
}
if ((temp & 0x1040L) == 0x1040L && colHeight[3] < 5) {
return 2;
}
if ((temp & 0x40040L) == 0x40040L && colHeight[4] < 5) {
return 2;
}
if ((temp & 0x4200L) == 0x4200L && colHeight[3] < 4) {
return 2;
}
if ((temp & 0x80200L) == 0x80200L && colHeight[4] < 3) {
return 2;
}
if ((temp & 0x84000L) == 0x84000L && colHeight[5] < 2) {
return 2;
}
break;
default:
break;
}
case 3:
switch (colHeight[3]) {
case 0:
if ((temp & 0x210000000L) == 0x210000000L && colHeight[0] < 3) {
return 3;
}
if ((temp & 0x4010000000L) == 0x4010000000L && colHeight[1] < 2) {
return 3;
}
if ((temp & 0x4200000000L) == 0x4200000000L && colHeight[2] < 1) {
return 3;
}
if ((temp & 0x204L) == 0x204L && colHeight[4] < 1) {
return 3;
}
if ((temp & 0x10004L) == 0x10004L && colHeight[5] < 2) {
return 3;
}
if ((temp & 0x10200L) == 0x10200L && colHeight[6] < 3) {
return 3;
}
break;
case 1:
if ((temp & 0x108000000L) == 0x108000000L && colHeight[0] < 4) {
return 3;
}
if ((temp & 0x2008000000L) == 0x2008000000L && colHeight[1] < 3) {
return 3;
}
if ((temp & 0x2100000000L) == 0x2100000000L && colHeight[2] < 2) {
return 3;
}
if ((temp & 0x102L) == 0x102L && colHeight[4] < 2) {
return 3;
}
if ((temp & 0x8002L) == 0x8002L && colHeight[5] < 3) {
return 3;
}
if ((temp & 0x8100L) == 0x8100L && colHeight[6] < 4) {
return 3;
}
if ((temp & 0x8020000L) == 0x8020000L && colHeight[1] < 3) {
return 3;
}
if ((temp & 0x100020000L) == 0x100020000L && colHeight[2] < 2) {
return 3;
}
if ((temp & 0x20000100L) == 0x20000100L && colHeight[4] < 2) {
return 3;
}
if ((temp & 0x20008000L) == 0x20008000L && colHeight[5] < 3) {
return 3;
}
if ((temp & 0x410000000L) == 0x410000000L
&& (colHeight[0] < 1 || colHeight[4] < 1)) {
return 3;
}
if ((temp & 0x10010000000L) == 0x10010000000L
&& colHeight[1] < 1) {
return 3;
}
if ((temp & 0x10400000000L) == 0x10400000000L
&& colHeight[2] < 1) {
return 3;
}
if ((temp & 0x10010000L) == 0x10010000L
&& (colHeight[1] < 1 || colHeight[5] < 1)) {
return 3;
}
if ((temp & 0x400010000L) == 0x400010000L && colHeight[2] < 1) {
return 3;
}
if ((temp & 0x10400L) == 0x10400L
&& (colHeight[2] < 1 || colHeight[6] < 1)) {
return 3;
}
if ((temp & 0x10000400L) == 0x10000400L && colHeight[4] < 1) {
return 3;
}
if ((temp & 0x410L) == 0x410L && colHeight[4] < 1) {
return 3;
}
if ((temp & 0x10010L) == 0x10010L && colHeight[5] < 1) {
return 3;
}
break;
case 2:
if ((temp & 0x84000000L) == 0x84000000L
&& (colHeight[0] < 5 || colHeight[4] < 1)) {
return 3;
}
if ((temp & 0x1004000000L) == 0x1004000000L && colHeight[1] < 4) {
return 3;
}
if ((temp & 0x1080000000L) == 0x1080000000L && colHeight[2] < 3) {
return 3;
}
if ((temp & 0x81L) == 0x81L && colHeight[4] < 3) {
return 3;
}
if ((temp & 0x4001L) == 0x4001L && colHeight[5] < 4) {
return 3;
}
if ((temp & 0x4080L) == 0x4080L
&& (colHeight[2] < 1 || colHeight[6] < 5)) {
return 3;
}
if ((temp & 0x4010000L) == 0x4010000L && colHeight[1] < 4) {
return 3;
}
if ((temp & 0x80010000L) == 0x80010000L && colHeight[2] < 3) {
return 3;
}
if ((temp & 0x10000080L) == 0x10000080L && colHeight[4] < 3) {
return 3;
}
if ((temp & 0x10004000L) == 0x10004000L && colHeight[5] < 4) {
return 3;
}
if ((temp & 0x208000000L) == 0x208000000L
&& (colHeight[0] < 2 || colHeight[4] < 2)) {
return 3;
}
if ((temp & 0x8008000000L) == 0x8008000000L && colHeight[1] < 2) {
return 3;
}
if ((temp & 0x8200000000L) == 0x8200000000L && colHeight[2] < 2) {
return 3;
}
if ((temp & 0x8008000L) == 0x8008000L
&& (colHeight[1] < 2 || colHeight[5] < 2)) {
return 3;
}
if ((temp & 0x200008000L) == 0x200008000L && colHeight[2] < 2) {
return 3;
}
if ((temp & 0x8200L) == 0x8200L
&& (colHeight[2] < 2 || colHeight[6] < 2)) {
return 3;
}
if ((temp & 0x8000200L) == 0x8000200L && colHeight[4] < 2) {
return 3;
}
if ((temp & 0x208L) == 0x208L && colHeight[4] < 2) {
return 3;
}
if ((temp & 0x8008L) == 0x8008L && colHeight[5] < 2) {
return 3;
}
if ((temp & 0x10800L) == 0x10800L && colHeight[2] < 3) {
return 3;
}
if ((temp & 0x4000800L) == 0x4000800L && colHeight[4] < 1) {
return 3;
}
if ((temp & 0x800004000L) == 0x800004000L && colHeight[2] < 1) {
return 3;
}
if ((temp & 0x810000000L) == 0x810000000L && colHeight[4] < 3) {
return 3;
}
break;
case 3:
if ((temp & 0x2008000L) == 0x2008000L
&& (colHeight[1] < 5 || colHeight[5] < 1)) {
return 3;
}
if ((temp & 0x40008000L) == 0x40008000L && colHeight[2] < 4) {
return 3;
}
if ((temp & 0x42000000L) == 0x42000000L && colHeight[4] < 2) {
return 3;
}
if ((temp & 0x2040L) == 0x2040L && colHeight[2] < 2) {
return 3;
}
if ((temp & 0x8000040L) == 0x8000040L && colHeight[4] < 4) {
return 3;
}
if ((temp & 0x8002000L) == 0x8002000L
&& (colHeight[1] < 1 || colHeight[5] < 5)) {
return 3;
}
if ((temp & 0x104000000L) == 0x104000000L
&& (colHeight[0] < 3 || colHeight[4] < 3)) {
return 3;
}
if ((temp & 0x4004000000L) == 0x4004000000L && colHeight[1] < 3) {
return 3;
}
if ((temp & 0x4100000000L) == 0x4100000000L && colHeight[2] < 3) {
return 3;
}
if ((temp & 0x4004000L) == 0x4004000L
&& (colHeight[1] < 3 || colHeight[5] < 3)) {
return 3;
}
if ((temp & 0x100004000L) == 0x100004000L && colHeight[2] < 3) {
return 3;
}
if ((temp & 0x4100L) == 0x4100L
&& (colHeight[2] < 3 || colHeight[6] < 3)) {
return 3;
}
if ((temp & 0x4000100L) == 0x4000100L && colHeight[4] < 3) {
return 3;
}
if ((temp & 0x104L) == 0x104L && colHeight[4] < 3) {
return 3;
}
if ((temp & 0x4004L) == 0x4004L && colHeight[5] < 3) {
return 3;
}
if ((temp & 0x8400L) == 0x8400L && colHeight[2] < 4) {
return 3;
}
if ((temp & 0x2000400L) == 0x2000400L && colHeight[4] < 2) {
return 3;
}
if ((temp & 0x400002000L) == 0x400002000L && colHeight[2] < 2) {
return 3;
}
if ((temp & 0x408000000L) == 0x408000000L && colHeight[4] < 4) {
return 3;
}
if ((temp & 0x420L) == 0x420L && colHeight[4] < 2) {
return 3;
}
if ((temp & 0x8020L) == 0x8020L && colHeight[5] < 1) {
return 3;
}
if ((temp & 0x20008000000L) == 0x20008000000L
&& colHeight[1] < 1) {
return 3;
}
if ((temp & 0x20400000000L) == 0x20400000000L
&& colHeight[2] < 2) {
return 3;
}
break;
case 4:
if ((temp & 0x82000000L) == 0x82000000L
&& (colHeight[0] < 4 || colHeight[4] < 4)) {
return 3;
}
if ((temp & 0x2002000000L) == 0x2002000000L && colHeight[1] < 4) {
return 3;
}
if ((temp & 0x2080000000L) == 0x2080000000L && colHeight[2] < 4) {
return 3;
}
if ((temp & 0x2002000L) == 0x2002000L
&& (colHeight[1] < 4 || colHeight[5] < 4)) {
return 3;
}
if ((temp & 0x80002000L) == 0x80002000L && colHeight[2] < 4) {
return 3;
}
if ((temp & 0x2080L) == 0x2080L
&& (colHeight[2] < 4 || colHeight[6] < 4)) {
return 3;
}
if ((temp & 0x2000080L) == 0x2000080L && colHeight[4] < 4) {
return 3;
}
if ((temp & 0x82L) == 0x82L && colHeight[4] < 4) {
return 3;
}
if ((temp & 0x2002L) == 0x2002L && colHeight[5] < 4) {
return 3;
}
if ((temp & 0x4200L) == 0x4200L
&& (colHeight[2] < 5 || colHeight[6] < 1)) {
return 3;
}
if ((temp & 0x1000200L) == 0x1000200L && colHeight[4] < 3) {
return 3;
}
if ((temp & 0x1004000L) == 0x1004000L && colHeight[5] < 2) {
return 3;
}
if ((temp & 0x4001000L) == 0x4001000L && colHeight[1] < 2) {
return 3;
}
if ((temp & 0x200001000L) == 0x200001000L && colHeight[2] < 3) {
return 3;
}
if ((temp & 0x204000000L) == 0x204000000L
&& (colHeight[0] < 1 || colHeight[4] < 5)) {
return 3;
}
if ((temp & 0x210L) == 0x210L && colHeight[4] < 3) {
return 3;
}
if ((temp & 0x4010L) == 0x4010L && colHeight[5] < 2) {
return 3;
}
if ((temp & 0x10004000000L) == 0x10004000000L
&& colHeight[1] < 2) {
return 3;
}
if ((temp & 0x10200000000L) == 0x10200000000L
&& colHeight[2] < 3) {
return 3;
}
break;
case 5:
if ((temp & 0x41000000L) == 0x41000000L
&& (colHeight[0] < 5 || colHeight[4] < 5)) {
return 3;
}
if ((temp & 0x1001000000L) == 0x1001000000L && colHeight[1] < 5) {
return 3;
}
if ((temp & 0x1040000000L) == 0x1040000000L && colHeight[2] < 5) {
return 3;
}
if ((temp & 0x1001000L) == 0x1001000L
&& (colHeight[1] < 5 || colHeight[5] < 5)) {
return 3;
}
if ((temp & 0x40001000L) == 0x40001000L && colHeight[2] < 5) {
return 3;
}
if ((temp & 0x1040L) == 0x1040L
&& (colHeight[2] < 5 || colHeight[6] < 5)) {
return 3;
}
if ((temp & 0x1000040L) == 0x1000040L && colHeight[4] < 5) {
return 3;
}
if ((temp & 0x41L) == 0x41L && colHeight[4] < 5) {
return 3;
}
if ((temp & 0x1001L) == 0x1001L && colHeight[5] < 5) {
return 3;
}
if ((temp & 0x108L) == 0x108L && colHeight[4] < 4) {
return 3;
}
if ((temp & 0x2008L) == 0x2008L && colHeight[5] < 3) {
return 3;
}
if ((temp & 0x2100L) == 0x2100L && colHeight[6] < 2) {
return 3;
}
if ((temp & 0x102000000L) == 0x102000000L && colHeight[0] < 2) {
return 3;
}
if ((temp & 0x8002000000L) == 0x8002000000L && colHeight[1] < 3) {
return 3;
}
if ((temp & 0x8100000000L) == 0x8100000000L && colHeight[2] < 4) {
return 3;
}
break;
default:
break;
}
case 4:
switch (colHeight[4]) {
case 0:
if ((temp & 0x8400000L) == 0x8400000L && colHeight[1] < 3) {
return 4;
}
if ((temp & 0x100400000L) == 0x100400000L && colHeight[2] < 2) {
return 4;
}
if ((temp & 0x108000000L) == 0x108000000L && colHeight[3] < 1) {
return 4;
}
break;
case 1:
if ((temp & 0x4200000L) == 0x4200000L && colHeight[1] < 4) {
return 4;
}
if ((temp & 0x80200000L) == 0x80200000L && colHeight[2] < 3) {
return 4;
}
if ((temp & 0x84000000L) == 0x84000000L && colHeight[3] < 2) {
return 4;
}
if ((temp & 0x200800L) == 0x200800L && colHeight[2] < 3) {
return 4;
}
if ((temp & 0x4000800L) == 0x4000800L && colHeight[3] < 2) {
return 4;
}
if ((temp & 0x800004L) == 0x800004L && colHeight[5] < 2) {
return 4;
}
if ((temp & 0x800200L) == 0x800200L && colHeight[6] < 3) {
return 4;
}
if ((temp & 0x10400000L) == 0x10400000L
&& (colHeight[1] < 1 || colHeight[5] < 1)) {
return 4;
}
if ((temp & 0x400400000L) == 0x400400000L && colHeight[2] < 1) {
return 4;
}
if ((temp & 0x410000000L) == 0x410000000L && colHeight[3] < 1) {
return 4;
}
if ((temp & 0x400400L) == 0x400400L
&& (colHeight[2] < 1 || colHeight[6] < 1)) {
return 4;
}
if ((temp & 0x10000400L) == 0x10000400L && colHeight[3] < 1) {
return 4;
}
if ((temp & 0x410L) == 0x410L && colHeight[3] < 1) {
return 4;
}
if ((temp & 0x400010L) == 0x400010L && colHeight[5] < 1) {
return 4;
}
break;
case 2:
if ((temp & 0x2100000L) == 0x2100000L
&& (colHeight[1] < 5 || colHeight[5] < 1)) {
return 4;
}
if ((temp & 0x40100000L) == 0x40100000L && colHeight[2] < 4) {
return 4;
}
if ((temp & 0x42000000L) == 0x42000000L && colHeight[3] < 3) {
return 4;
}
if ((temp & 0x100400L) == 0x100400L && colHeight[2] < 4) {
return 4;
}
if ((temp & 0x2000400L) == 0x2000400L && colHeight[3] < 3) {
return 4;
}
if ((temp & 0x102L) == 0x102L && colHeight[3] < 1) {
return 4;
}
if ((temp & 0x400002L) == 0x400002L && colHeight[5] < 3) {
return 4;
}
if ((temp & 0x400100L) == 0x400100L && colHeight[6] < 4) {
return 4;
}
if ((temp & 0x8200000L) == 0x8200000L
&& (colHeight[1] < 2 || colHeight[5] < 2)) {
return 4;
}
if ((temp & 0x200200000L) == 0x200200000L && colHeight[2] < 2) {
return 4;
}
if ((temp & 0x208000000L) == 0x208000000L && colHeight[3] < 2) {
return 4;
}
if ((temp & 0x200200L) == 0x200200L
&& (colHeight[2] < 2 || colHeight[6] < 2)) {
return 4;
}
if ((temp & 0x8000200L) == 0x8000200L && colHeight[3] < 2) {
return 4;
}
if ((temp & 0x208L) == 0x208L && colHeight[3] < 2) {
return 4;
}
if ((temp & 0x200008L) == 0x200008L && colHeight[5] < 2) {
return 4;
}
if ((temp & 0x420L) == 0x420L && colHeight[3] < 3) {
return 4;
}
if ((temp & 0x100020L) == 0x100020L && colHeight[5] < 1) {
return 4;
}
if ((temp & 0x20000100L) == 0x20000100L && colHeight[3] < 1) {
return 4;
}
if ((temp & 0x20400000L) == 0x20400000L && colHeight[5] < 3) {
return 4;
}
break;
case 3:
if ((temp & 0x80200L) == 0x80200L
&& (colHeight[2] < 5 || colHeight[6] < 1)) {
return 4;
}
if ((temp & 0x1000200L) == 0x1000200L && colHeight[3] < 4) {
return 4;
}
if ((temp & 0x1080000L) == 0x1080000L && colHeight[5] < 2) {
return 4;
}
if ((temp & 0x81L) == 0x81L && colHeight[3] < 2) {
return 4;
}
if ((temp & 0x200001L) == 0x200001L && colHeight[5] < 4) {
return 4;
}
if ((temp & 0x200080L) == 0x200080L
&& (colHeight[2] < 1 || colHeight[6] < 5)) {
return 4;
}
if ((temp & 0x4100000L) == 0x4100000L
&& (colHeight[1] < 3 || colHeight[5] < 3)) {
return 4;
}
if ((temp & 0x100100000L) == 0x100100000L && colHeight[2] < 3) {
return 4;
}
if ((temp & 0x104000000L) == 0x104000000L && colHeight[3] < 3) {
return 4;
}
if ((temp & 0x100100L) == 0x100100L
&& (colHeight[2] < 3 || colHeight[6] < 3)) {
return 4;
}
if ((temp & 0x4000100L) == 0x4000100L && colHeight[3] < 3) {
return 4;
}
if ((temp & 0x104L) == 0x104L && colHeight[3] < 3) {
return 4;
}
if ((temp & 0x100004L) == 0x100004L && colHeight[5] < 3) {
return 4;
}
if ((temp & 0x210L) == 0x210L && colHeight[3] < 4) {
return 4;
}
if ((temp & 0x80010L) == 0x80010L && colHeight[5] < 2) {
return 4;
}
if ((temp & 0x10000080L) == 0x10000080L && colHeight[3] < 2) {
return 4;
}
if ((temp & 0x10200000L) == 0x10200000L && colHeight[5] < 4) {
return 4;
}
if ((temp & 0x800200000L) == 0x800200000L && colHeight[2] < 1) {
return 4;
}
if ((temp & 0x810000000L) == 0x810000000L && colHeight[3] < 2) {
return 4;
}
break;
case 4:
if ((temp & 0x2080000L) == 0x2080000L
&& (colHeight[1] < 4 || colHeight[5] < 4)) {
return 4;
}
if ((temp & 0x80080000L) == 0x80080000L && colHeight[2] < 4) {
return 4;
}
if ((temp & 0x82000000L) == 0x82000000L && colHeight[3] < 4) {
return 4;
}
if ((temp & 0x80080L) == 0x80080L
&& (colHeight[2] < 4 || colHeight[6] < 4)) {
return 4;
}
if ((temp & 0x2000080L) == 0x2000080L && colHeight[3] < 4) {
return 4;
}
if ((temp & 0x82L) == 0x82L && colHeight[3] < 4) {
return 4;
}
if ((temp & 0x80002L) == 0x80002L && colHeight[5] < 4) {
return 4;
}
if ((temp & 0x108L) == 0x108L && colHeight[3] < 5) {
return 4;
}
if ((temp & 0x40008L) == 0x40008L && colHeight[5] < 3) {
return 4;
}
if ((temp & 0x40100L) == 0x40100L && colHeight[6] < 2) {
return 4;
}
if ((temp & 0x100040L) == 0x100040L && colHeight[2] < 2) {
return 4;
}
if ((temp & 0x8000040L) == 0x8000040L && colHeight[3] < 3) {
return 4;
}
if ((temp & 0x8100000L) == 0x8100000L
&& (colHeight[1] < 1 || colHeight[5] < 5)) {
return 4;
}
if ((temp & 0x400100000L) == 0x400100000L && colHeight[2] < 2) {
return 4;
}
if ((temp & 0x408000000L) == 0x408000000L && colHeight[3] < 3) {
return 4;
}
break;
case 5:
if ((temp & 0x1040000L) == 0x1040000L
&& (colHeight[1] < 5 || colHeight[5] < 5)) {
return 4;
}
if ((temp & 0x40040000L) == 0x40040000L && colHeight[2] < 5) {
return 4;
}
if ((temp & 0x41000000L) == 0x41000000L && colHeight[3] < 5) {
return 4;
}
if ((temp & 0x40040L) == 0x40040L
&& (colHeight[2] < 5 || colHeight[6] < 5)) {
return 4;
}
if ((temp & 0x1000040L) == 0x1000040L && colHeight[3] < 5) {
return 4;
}
if ((temp & 0x41L) == 0x41L && colHeight[3] < 5) {
return 4;
}
if ((temp & 0x40001L) == 0x40001L && colHeight[5] < 5) {
return 4;
}
if ((temp & 0x4080000L) == 0x4080000L && colHeight[1] < 2) {
return 4;
}
if ((temp & 0x200080000L) == 0x200080000L && colHeight[2] < 3) {
return 4;
}
if ((temp & 0x204000000L) == 0x204000000L && colHeight[3] < 4) {
return 4;
}
break;
default:
break;
}
case 5:
switch (colHeight[5]) {
case 0:
if ((temp & 0x210000L) == 0x210000L && colHeight[2] < 3) {
return 5;
}
if ((temp & 0x4010000L) == 0x4010000L && colHeight[3] < 2) {
return 5;
}
if ((temp & 0x4200000L) == 0x4200000L && colHeight[4] < 1) {
return 5;
}
break;
case 1:
if ((temp & 0x108000L) == 0x108000L && colHeight[2] < 4) {
return 5;
}
if ((temp & 0x2008000L) == 0x2008000L && colHeight[3] < 3) {
return 5;
}
if ((temp & 0x2100000L) == 0x2100000L && colHeight[4] < 2) {
return 5;
}
if ((temp & 0x8020L) == 0x8020L && colHeight[3] < 3) {
return 5;
}
if ((temp & 0x100020L) == 0x100020L && colHeight[4] < 2) {
return 5;
}
if ((temp & 0x410000L) == 0x410000L
&& (colHeight[2] < 1 || colHeight[6] < 1)) {
return 5;
}
if ((temp & 0x10010000L) == 0x10010000L && colHeight[3] < 1) {
return 5;
}
if ((temp & 0x10400000L) == 0x10400000L && colHeight[4] < 1) {
return 5;
}
if ((temp & 0x10010L) == 0x10010L && colHeight[3] < 1) {
return 5;
}
if ((temp & 0x400010L) == 0x400010L && colHeight[4] < 1) {
return 5;
}
break;
case 2:
if ((temp & 0x84000L) == 0x84000L
&& (colHeight[2] < 5 || colHeight[6] < 1)) {
return 5;
}
if ((temp & 0x1004000L) == 0x1004000L && colHeight[3] < 4) {
return 5;
}
if ((temp & 0x1080000L) == 0x1080000L && colHeight[4] < 3) {
return 5;
}
if ((temp & 0x4010L) == 0x4010L && colHeight[3] < 4) {
return 5;
}
if ((temp & 0x80010L) == 0x80010L && colHeight[4] < 3) {
return 5;
}
if ((temp & 0x208000L) == 0x208000L
&& (colHeight[2] < 2 || colHeight[6] < 2)) {
return 5;
}
if ((temp & 0x8008000L) == 0x8008000L && colHeight[3] < 2) {
return 5;
}
if ((temp & 0x8200000L) == 0x8200000L && colHeight[4] < 2) {
return 5;
}
if ((temp & 0x8008L) == 0x8008L && colHeight[3] < 2) {
return 5;
}
if ((temp & 0x200008L) == 0x200008L && colHeight[4] < 2) {
return 5;
}
if ((temp & 0x800004L) == 0x800004L && colHeight[4] < 1) {
return 5;
}
if ((temp & 0x810000L) == 0x810000L && colHeight[6] < 3) {
return 5;
}
break;
case 3:
if ((temp & 0x2008L) == 0x2008L && colHeight[3] < 5) {
return 5;
}
if ((temp & 0x40008L) == 0x40008L && colHeight[4] < 4) {
return 5;
}
if ((temp & 0x42000L) == 0x42000L && colHeight[6] < 2) {
return 5;
}
if ((temp & 0x104000L) == 0x104000L
&& (colHeight[2] < 3 || colHeight[6] < 3)) {
return 5;
}
if ((temp & 0x4004000L) == 0x4004000L && colHeight[3] < 3) {
return 5;
}
if ((temp & 0x4100000L) == 0x4100000L && colHeight[4] < 3) {
return 5;
}
if ((temp & 0x4004L) == 0x4004L && colHeight[3] < 3) {
return 5;
}
if ((temp & 0x100004L) == 0x100004L && colHeight[4] < 3) {
return 5;
}
if ((temp & 0x8002L) == 0x8002L && colHeight[3] < 1) {
return 5;
}
if ((temp & 0x400002L) == 0x400002L && colHeight[4] < 2) {
return 5;
}
if ((temp & 0x408000L) == 0x408000L && colHeight[6] < 4) {
return 5;
}
if ((temp & 0x20008000L) == 0x20008000L && colHeight[3] < 1) {
return 5;
}
if ((temp & 0x20400000L) == 0x20400000L && colHeight[4] < 2) {
return 5;
}
break;
case 4:
if ((temp & 0x82000L) == 0x82000L
&& (colHeight[2] < 4 || colHeight[6] < 4)) {
return 5;
}
if ((temp & 0x2002000L) == 0x2002000L && colHeight[3] < 4) {
return 5;
}
if ((temp & 0x2080000L) == 0x2080000L && colHeight[4] < 4) {
return 5;
}
if ((temp & 0x2002L) == 0x2002L && colHeight[3] < 4) {
return 5;
}
if ((temp & 0x80002L) == 0x80002L && colHeight[4] < 4) {
return 5;
}
if ((temp & 0x4001L) == 0x4001L && colHeight[3] < 2) {
return 5;
}
if ((temp & 0x200001L) == 0x200001L && colHeight[4] < 3) {
return 5;
}
if ((temp & 0x204000L) == 0x204000L
&& (colHeight[2] < 1 || colHeight[6] < 5)) {
return 5;
}
if ((temp & 0x10004000L) == 0x10004000L && colHeight[3] < 2) {
return 5;
}
if ((temp & 0x10200000L) == 0x10200000L && colHeight[4] < 3) {
return 5;
}
break;
case 5:
if ((temp & 0x41000L) == 0x41000L
&& (colHeight[2] < 5 || colHeight[6] < 5)) {
return 5;
}
if ((temp & 0x1001000L) == 0x1001000L && colHeight[3] < 5) {
return 5;
}
if ((temp & 0x1040000L) == 0x1040000L && colHeight[4] < 5) {
return 5;
}
if ((temp & 0x1001L) == 0x1001L && colHeight[3] < 5) {
return 5;
}
if ((temp & 0x40001L) == 0x40001L && colHeight[4] < 5) {
return 5;
}
if ((temp & 0x102000L) == 0x102000L && colHeight[2] < 2) {
return 5;
}
if ((temp & 0x8002000L) == 0x8002000L && colHeight[3] < 3) {
return 5;
}
if ((temp & 0x8100000L) == 0x8100000L && colHeight[4] < 4) {
return 5;
}
break;
default:
break;
}
case 6:
switch (colHeight[6]) {
case 0:
if ((temp & 0x8400L) == 0x8400L && colHeight[3] < 3) {
return 6;
}
if ((temp & 0x100400L) == 0x100400L && colHeight[4] < 2) {
return 6;
}
if ((temp & 0x108000L) == 0x108000L && colHeight[5] < 1) {
return 6;
}
break;
case 1:
if ((temp & 0x4200L) == 0x4200L && colHeight[3] < 4) {
return 6;
}
if ((temp & 0x80200L) == 0x80200L && colHeight[4] < 3) {
return 6;
}
if ((temp & 0x84000L) == 0x84000L && colHeight[5] < 2) {
return 6;
}
if ((temp & 0x10400L) == 0x10400L && colHeight[3] < 1) {
return 6;
}
if ((temp & 0x400400L) == 0x400400L && colHeight[4] < 1) {
return 6;
}
if ((temp & 0x410000L) == 0x410000L && colHeight[5] < 1) {
return 6;
}
break;
case 2:
if ((temp & 0x2100L) == 0x2100L && colHeight[3] < 5) {
return 6;
}
if ((temp & 0x40100L) == 0x40100L && colHeight[4] < 4) {
return 6;
}
if ((temp & 0x42000L) == 0x42000L && colHeight[5] < 3) {
return 6;
}
if ((temp & 0x8200L) == 0x8200L && colHeight[3] < 2) {
return 6;
}
if ((temp & 0x200200L) == 0x200200L && colHeight[4] < 2) {
return 6;
}
if ((temp & 0x208000L) == 0x208000L && colHeight[5] < 2) {
return 6;
}
break;
case 3:
if ((temp & 0x4100L) == 0x4100L && colHeight[3] < 3) {
return 6;
}
if ((temp & 0x100100L) == 0x100100L && colHeight[4] < 3) {
return 6;
}
if ((temp & 0x104000L) == 0x104000L && colHeight[5] < 3) {
return 6;
}
if ((temp & 0x800200L) == 0x800200L && colHeight[4] < 1) {
return 6;
}
if ((temp & 0x810000L) == 0x810000L && colHeight[5] < 2) {
return 6;
}
break;
case 4:
if ((temp & 0x2080L) == 0x2080L && colHeight[3] < 4) {
return 6;
}
if ((temp & 0x80080L) == 0x80080L && colHeight[4] < 4) {
return 6;
}
if ((temp & 0x82000L) == 0x82000L && colHeight[5] < 4) {
return 6;
}
if ((temp & 0x8100L) == 0x8100L && colHeight[3] < 1) {
return 6;
}
if ((temp & 0x400100L) == 0x400100L && colHeight[4] < 2) {
return 6;
}
if ((temp & 0x408000L) == 0x408000L && colHeight[5] < 3) {
return 6;
}
break;
case 5:
if ((temp & 0x1040L) == 0x1040L && colHeight[3] < 5) {
return 6;
}
if ((temp & 0x40040L) == 0x40040L && colHeight[4] < 5) {
return 6;
}
if ((temp & 0x41000L) == 0x41000L && colHeight[5] < 5) {
return 6;
}
if ((temp & 0x4080L) == 0x4080L && colHeight[3] < 2) {
return 6;
}
if ((temp & 0x200080L) == 0x200080L && colHeight[4] < 3) {
return 6;
}
if ((temp & 0x204000L) == 0x204000L && colHeight[5] < 4) {
return 6;
}
break;
default:
break;
}
default:
break;
}
return (-1);
}
// This Method was generated with another Programm
/**
* This Method (the source) was generated with a C-program, because its
* source-code is very long. Can only be used for Player 1.
* Find a field, in which player 1 can create an odd threat.
*
* @param startWith
* Column to start with search
* @return column for creating a odd-threat, or else -1
*/
protected int findOddThreatP1(int startWith) {
// Diese Methode sucht nach ungeraden Drohung, JEDOCH nur für den
// Anziehenden
switch (startWith) {
case 0:
switch (colHeight[0]) {
case 0:
if ((fieldP1 & 0x410100000L) == 0x400100000L
&& colHeight[2] < 2) {
return 0;
}
break;
case 1:
if ((fieldP1 & 0x404080000L) == 0x4080000L && colHeight[1] < 2) {
return 0;
}
if ((fieldP1 & 0x204100000L) == 0x204000000L
&& colHeight[3] < 4) {
return 0;
}
break;
case 2:
if ((fieldP1 & 0x104040000L) == 0x100040000L
&& colHeight[2] < 4) {
return 0;
}
if ((fieldP1 & 0x408200000L) == 0x8200000L && colHeight[1] < 2) {
return 0;
}
if ((fieldP1 & 0x210200000L) == 0x200200000L
&& colHeight[2] < 2) {
return 0;
}
if ((fieldP1 & 0x208400000L) == 0x208000000L
&& colHeight[3] < 2) {
return 0;
}
break;
case 3:
if ((fieldP1 & 0x410800000L) == 0x10800000L && colHeight[1] < 2) {
return 0;
}
break;
case 4:
if ((fieldP1 & 0x102080000L) == 0x2080000L && colHeight[1] < 4) {
return 0;
}
if ((fieldP1 & 0x84080000L) == 0x80080000L && colHeight[2] < 4) {
return 0;
}
if ((fieldP1 & 0x82100000L) == 0x82000000L && colHeight[3] < 4) {
return 0;
}
if ((fieldP1 & 0x110400000L) == 0x100400000L
&& colHeight[2] < 2) {
return 0;
}
break;
case 5:
if ((fieldP1 & 0x104200000L) == 0x4200000L && colHeight[1] < 4) {
return 0;
}
if ((fieldP1 & 0x84400000L) == 0x84000000L && colHeight[3] < 2) {
return 0;
}
break;
default:
break;
}
case 1:
switch (colHeight[1]) {
case 0:
if ((fieldP1 & 0x10004000L) == 0x10004000L && colHeight[3] < 2) {
return 1;
}
break;
case 1:
if ((fieldP1 & 0x102000L) == 0x102000L && colHeight[2] < 2) {
return 1;
}
if ((fieldP1 & 0x8100000L) == 0x8100000L && colHeight[4] < 4) {
return 1;
}
if ((fieldP1 & 0x20000100000L) == 0x20000100000L
&& colHeight[2] < 2) {
return 1;
}
break;
case 2:
if ((fieldP1 & 0x4001000L) == 0x4001000L && colHeight[3] < 4) {
return 1;
}
if ((fieldP1 & 0x10004000000L) == 0x10004000000L
&& colHeight[3] < 4) {
return 1;
}
if ((fieldP1 & 0x8200000L) == 0x8200000L
&& (colHeight[0] < 2 || colHeight[4] < 2)) {
return 1;
}
if ((fieldP1 & 0x8000200000L) == 0x8000200000L
&& colHeight[2] < 2) {
return 1;
}
if ((fieldP1 & 0x8008000000L) == 0x8008000000L
&& colHeight[3] < 2) {
return 1;
}
if ((fieldP1 & 0x208000L) == 0x208000L && colHeight[2] < 2) {
return 1;
}
if ((fieldP1 & 0x8008000L) == 0x8008000L && colHeight[3] < 2) {
return 1;
}
break;
case 3:
if ((fieldP1 & 0x2040000L) == 0x2040000L && colHeight[0] < 2) {
return 1;
}
if ((fieldP1 & 0x8000040000L) == 0x8000040000L
&& colHeight[2] < 4) {
return 1;
}
if ((fieldP1 & 0x8400000L) == 0x8400000L && colHeight[0] < 4) {
return 1;
}
if ((fieldP1 & 0x2000400000L) == 0x2000400000L
&& colHeight[2] < 2) {
return 1;
}
if ((fieldP1 & 0x420000L) == 0x420000L && colHeight[2] < 2) {
return 1;
}
break;
case 4:
if ((fieldP1 & 0x2080000L) == 0x2080000L
&& (colHeight[0] < 4 || colHeight[4] < 4)) {
return 1;
}
if ((fieldP1 & 0x2000080000L) == 0x2000080000L
&& colHeight[2] < 4) {
return 1;
}
if ((fieldP1 & 0x2002000000L) == 0x2002000000L
&& colHeight[3] < 4) {
return 1;
}
if ((fieldP1 & 0x82000L) == 0x82000L && colHeight[2] < 4) {
return 1;
}
if ((fieldP1 & 0x2002000L) == 0x2002000L && colHeight[3] < 4) {
return 1;
}
if ((fieldP1 & 0x1004000000L) == 0x1004000000L
&& colHeight[3] < 2) {
return 1;
}
if ((fieldP1 & 0x4010000L) == 0x4010000L && colHeight[3] < 2) {
return 1;
}
break;
case 5:
if ((fieldP1 & 0x108000L) == 0x108000L && colHeight[2] < 4) {
return 1;
}
if ((fieldP1 & 0x2100000L) == 0x2100000L && colHeight[4] < 2) {
return 1;
}
break;
default:
break;
}
case 2:
switch (colHeight[2]) {
case 0:
if ((fieldP1 & 0x400100L) == 0x400100L && colHeight[4] < 2) {
return 2;
}
break;
case 1:
if ((fieldP1 & 0x4080L) == 0x4080L && colHeight[3] < 2) {
return 2;
}
if ((fieldP1 & 0x204000L) == 0x204000L && colHeight[5] < 4) {
return 2;
}
if ((fieldP1 & 0x4000800000L) == 0x4000800000L
&& colHeight[1] < 2) {
return 2;
}
if ((fieldP1 & 0x800004000L) == 0x800004000L
&& colHeight[3] < 2) {
return 2;
}
break;
case 2:
if ((fieldP1 & 0x100040L) == 0x100040L && colHeight[4] < 4) {
return 2;
}
if ((fieldP1 & 0x100400000L) == 0x100400000L
&& colHeight[0] < 4) {
return 2;
}
if ((fieldP1 & 0x400100000L) == 0x400100000L
&& colHeight[4] < 4) {
return 2;
}
if ((fieldP1 & 0x200200000L) == 0x200200000L
&& (colHeight[0] < 2 || colHeight[4] < 2)) {
return 2;
}
if ((fieldP1 & 0x8000200000L) == 0x8000200000L
&& colHeight[1] < 2) {
return 2;
}
if ((fieldP1 & 0x8200000000L) == 0x8200000000L
&& colHeight[3] < 2) {
return 2;
}
if ((fieldP1 & 0x208000L) == 0x208000L
&& (colHeight[1] < 2 || colHeight[5] < 2)) {
return 2;
}
if ((fieldP1 & 0x200008000L) == 0x200008000L
&& colHeight[3] < 2) {
return 2;
}
if ((fieldP1 & 0x8200L) == 0x8200L && colHeight[3] < 2) {
return 2;
}
if ((fieldP1 & 0x200200L) == 0x200200L && colHeight[4] < 2) {
return 2;
}
break;
case 3:
if ((fieldP1 & 0x1000200000L) == 0x1000200000L
&& colHeight[1] < 4) {
return 2;
}
if ((fieldP1 & 0x1080000000L) == 0x1080000000L
&& colHeight[3] < 2) {
return 2;
}
if ((fieldP1 & 0x81000L) == 0x81000L && colHeight[1] < 2) {
return 2;
}
if ((fieldP1 & 0x200001000L) == 0x200001000L
&& colHeight[3] < 4) {
return 2;
}
if ((fieldP1 & 0x210000L) == 0x210000L && colHeight[1] < 4) {
return 2;
}
if ((fieldP1 & 0x80010000L) == 0x80010000L && colHeight[3] < 2) {
return 2;
}
if ((fieldP1 & 0x10000080000L) == 0x10000080000L
&& colHeight[1] < 2) {
return 2;
}
if ((fieldP1 & 0x10200000000L) == 0x10200000000L
&& colHeight[3] < 4) {
return 2;
}
if ((fieldP1 & 0x10800L) == 0x10800L && colHeight[3] < 2) {
return 2;
}
break;
case 4:
if ((fieldP1 & 0x80080000L) == 0x80080000L
&& (colHeight[0] < 4 || colHeight[4] < 4)) {
return 2;
}
if ((fieldP1 & 0x2000080000L) == 0x2000080000L
&& colHeight[1] < 4) {
return 2;
}
if ((fieldP1 & 0x2080000000L) == 0x2080000000L
&& colHeight[3] < 4) {
return 2;
}
if ((fieldP1 & 0x82000L) == 0x82000L
&& (colHeight[1] < 4 || colHeight[5] < 4)) {
return 2;
}
if ((fieldP1 & 0x80002000L) == 0x80002000L && colHeight[3] < 4) {
return 2;
}
if ((fieldP1 & 0x2080L) == 0x2080L && colHeight[3] < 4) {
return 2;
}
if ((fieldP1 & 0x80080L) == 0x80080L && colHeight[4] < 4) {
return 2;
}
if ((fieldP1 & 0x40100000L) == 0x40100000L && colHeight[4] < 2) {
return 2;
}
if ((fieldP1 & 0x100040000L) == 0x100040000L
&& colHeight[0] < 2) {
return 2;
}
if ((fieldP1 & 0x100400L) == 0x100400L && colHeight[4] < 2) {
return 2;
}
break;
case 5:
if ((fieldP1 & 0x4200L) == 0x4200L && colHeight[3] < 4) {
return 2;
}
if ((fieldP1 & 0x84000L) == 0x84000L && colHeight[5] < 2) {
return 2;
}
break;
default:
break;
}
case 3:
switch (colHeight[3]) {
case 0:
if ((fieldP1 & 0x4010000000L) == 0x4010000000L
&& colHeight[1] < 2) {
return 3;
}
if ((fieldP1 & 0x10004L) == 0x10004L && colHeight[5] < 2) {
return 3;
}
break;
case 1:
if ((fieldP1 & 0x108000000L) == 0x108000000L
&& colHeight[0] < 4) {
return 3;
}
if ((fieldP1 & 0x2100000000L) == 0x2100000000L
&& colHeight[2] < 2) {
return 3;
}
if ((fieldP1 & 0x102L) == 0x102L && colHeight[4] < 2) {
return 3;
}
if ((fieldP1 & 0x8100L) == 0x8100L && colHeight[6] < 4) {
return 3;
}
if ((fieldP1 & 0x100020000L) == 0x100020000L
&& colHeight[2] < 2) {
return 3;
}
if ((fieldP1 & 0x20000100L) == 0x20000100L && colHeight[4] < 2) {
return 3;
}
break;
case 2:
if ((fieldP1 & 0x1004000000L) == 0x1004000000L
&& colHeight[1] < 4) {
return 3;
}
if ((fieldP1 & 0x4001L) == 0x4001L && colHeight[5] < 4) {
return 3;
}
if ((fieldP1 & 0x4010000L) == 0x4010000L && colHeight[1] < 4) {
return 3;
}
if ((fieldP1 & 0x10004000L) == 0x10004000L && colHeight[5] < 4) {
return 3;
}
if ((fieldP1 & 0x208000000L) == 0x208000000L
&& (colHeight[0] < 2 || colHeight[4] < 2)) {
return 3;
}
if ((fieldP1 & 0x8008000000L) == 0x8008000000L
&& colHeight[1] < 2) {
return 3;
}
if ((fieldP1 & 0x8200000000L) == 0x8200000000L
&& colHeight[2] < 2) {
return 3;
}
if ((fieldP1 & 0x8008000L) == 0x8008000L
&& (colHeight[1] < 2 || colHeight[5] < 2)) {
return 3;
}
if ((fieldP1 & 0x200008000L) == 0x200008000L
&& colHeight[2] < 2) {
return 3;
}
if ((fieldP1 & 0x8200L) == 0x8200L
&& (colHeight[2] < 2 || colHeight[6] < 2)) {
return 3;
}
if ((fieldP1 & 0x8000200L) == 0x8000200L && colHeight[4] < 2) {
return 3;
}
if ((fieldP1 & 0x208L) == 0x208L && colHeight[4] < 2) {
return 3;
}
if ((fieldP1 & 0x8008L) == 0x8008L && colHeight[5] < 2) {
return 3;
}
break;
case 3:
if ((fieldP1 & 0x40008000L) == 0x40008000L && colHeight[2] < 4) {
return 3;
}
if ((fieldP1 & 0x42000000L) == 0x42000000L && colHeight[4] < 2) {
return 3;
}
if ((fieldP1 & 0x2040L) == 0x2040L && colHeight[2] < 2) {
return 3;
}
if ((fieldP1 & 0x8000040L) == 0x8000040L && colHeight[4] < 4) {
return 3;
}
if ((fieldP1 & 0x8400L) == 0x8400L && colHeight[2] < 4) {
return 3;
}
if ((fieldP1 & 0x2000400L) == 0x2000400L && colHeight[4] < 2) {
return 3;
}
if ((fieldP1 & 0x400002000L) == 0x400002000L
&& colHeight[2] < 2) {
return 3;
}
if ((fieldP1 & 0x408000000L) == 0x408000000L
&& colHeight[4] < 4) {
return 3;
}
if ((fieldP1 & 0x420L) == 0x420L && colHeight[4] < 2) {
return 3;
}
if ((fieldP1 & 0x20400000000L) == 0x20400000000L
&& colHeight[2] < 2) {
return 3;
}
break;
case 4:
if ((fieldP1 & 0x82000000L) == 0x82000000L
&& (colHeight[0] < 4 || colHeight[4] < 4)) {
return 3;
}
if ((fieldP1 & 0x2002000000L) == 0x2002000000L
&& colHeight[1] < 4) {
return 3;
}
if ((fieldP1 & 0x2080000000L) == 0x2080000000L
&& colHeight[2] < 4) {
return 3;
}
if ((fieldP1 & 0x2002000L) == 0x2002000L
&& (colHeight[1] < 4 || colHeight[5] < 4)) {
return 3;
}
if ((fieldP1 & 0x80002000L) == 0x80002000L && colHeight[2] < 4) {
return 3;
}
if ((fieldP1 & 0x2080L) == 0x2080L
&& (colHeight[2] < 4 || colHeight[6] < 4)) {
return 3;
}
if ((fieldP1 & 0x2000080L) == 0x2000080L && colHeight[4] < 4) {
return 3;
}
if ((fieldP1 & 0x82L) == 0x82L && colHeight[4] < 4) {
return 3;
}
if ((fieldP1 & 0x2002L) == 0x2002L && colHeight[5] < 4) {
return 3;
}
if ((fieldP1 & 0x1004000L) == 0x1004000L && colHeight[5] < 2) {
return 3;
}
if ((fieldP1 & 0x4001000L) == 0x4001000L && colHeight[1] < 2) {
return 3;
}
if ((fieldP1 & 0x4010L) == 0x4010L && colHeight[5] < 2) {
return 3;
}
if ((fieldP1 & 0x10004000000L) == 0x10004000000L
&& colHeight[1] < 2) {
return 3;
}
break;
case 5:
if ((fieldP1 & 0x108L) == 0x108L && colHeight[4] < 4) {
return 3;
}
if ((fieldP1 & 0x2100L) == 0x2100L && colHeight[6] < 2) {
return 3;
}
if ((fieldP1 & 0x102000000L) == 0x102000000L
&& colHeight[0] < 2) {
return 3;
}
if ((fieldP1 & 0x8100000000L) == 0x8100000000L
&& colHeight[2] < 4) {
return 3;
}
break;
default:
break;
}
case 4:
switch (colHeight[4]) {
case 0:
if ((fieldP1 & 0x100400000L) == 0x100400000L
&& colHeight[2] < 2) {
return 4;
}
break;
case 1:
if ((fieldP1 & 0x4200000L) == 0x4200000L && colHeight[1] < 4) {
return 4;
}
if ((fieldP1 & 0x84000000L) == 0x84000000L && colHeight[3] < 2) {
return 4;
}
if ((fieldP1 & 0x4000800L) == 0x4000800L && colHeight[3] < 2) {
return 4;
}
if ((fieldP1 & 0x800004L) == 0x800004L && colHeight[5] < 2) {
return 4;
}
break;
case 2:
if ((fieldP1 & 0x40100000L) == 0x40100000L && colHeight[2] < 4) {
return 4;
}
if ((fieldP1 & 0x100400L) == 0x100400L && colHeight[2] < 4) {
return 4;
}
if ((fieldP1 & 0x400100L) == 0x400100L && colHeight[6] < 4) {
return 4;
}
if ((fieldP1 & 0x8200000L) == 0x8200000L
&& (colHeight[1] < 2 || colHeight[5] < 2)) {
return 4;
}
if ((fieldP1 & 0x200200000L) == 0x200200000L
&& colHeight[2] < 2) {
return 4;
}
if ((fieldP1 & 0x208000000L) == 0x208000000L
&& colHeight[3] < 2) {
return 4;
}
if ((fieldP1 & 0x200200L) == 0x200200L
&& (colHeight[2] < 2 || colHeight[6] < 2)) {
return 4;
}
if ((fieldP1 & 0x8000200L) == 0x8000200L && colHeight[3] < 2) {
return 4;
}
if ((fieldP1 & 0x208L) == 0x208L && colHeight[3] < 2) {
return 4;
}
if ((fieldP1 & 0x200008L) == 0x200008L && colHeight[5] < 2) {
return 4;
}
break;
case 3:
if ((fieldP1 & 0x1000200L) == 0x1000200L && colHeight[3] < 4) {
return 4;
}
if ((fieldP1 & 0x1080000L) == 0x1080000L && colHeight[5] < 2) {
return 4;
}
if ((fieldP1 & 0x81L) == 0x81L && colHeight[3] < 2) {
return 4;
}
if ((fieldP1 & 0x200001L) == 0x200001L && colHeight[5] < 4) {
return 4;
}
if ((fieldP1 & 0x210L) == 0x210L && colHeight[3] < 4) {
return 4;
}
if ((fieldP1 & 0x80010L) == 0x80010L && colHeight[5] < 2) {
return 4;
}
if ((fieldP1 & 0x10000080L) == 0x10000080L && colHeight[3] < 2) {
return 4;
}
if ((fieldP1 & 0x10200000L) == 0x10200000L && colHeight[5] < 4) {
return 4;
}
if ((fieldP1 & 0x810000000L) == 0x810000000L
&& colHeight[3] < 2) {
return 4;
}
break;
case 4:
if ((fieldP1 & 0x2080000L) == 0x2080000L
&& (colHeight[1] < 4 || colHeight[5] < 4)) {
return 4;
}
if ((fieldP1 & 0x80080000L) == 0x80080000L && colHeight[2] < 4) {
return 4;
}
if ((fieldP1 & 0x82000000L) == 0x82000000L && colHeight[3] < 4) {
return 4;
}
if ((fieldP1 & 0x80080L) == 0x80080L
&& (colHeight[2] < 4 || colHeight[6] < 4)) {
return 4;
}
if ((fieldP1 & 0x2000080L) == 0x2000080L && colHeight[3] < 4) {
return 4;
}
if ((fieldP1 & 0x82L) == 0x82L && colHeight[3] < 4) {
return 4;
}
if ((fieldP1 & 0x80002L) == 0x80002L && colHeight[5] < 4) {
return 4;
}
if ((fieldP1 & 0x40100L) == 0x40100L && colHeight[6] < 2) {
return 4;
}
if ((fieldP1 & 0x100040L) == 0x100040L && colHeight[2] < 2) {
return 4;
}
if ((fieldP1 & 0x400100000L) == 0x400100000L
&& colHeight[2] < 2) {
return 4;
}
break;
case 5:
if ((fieldP1 & 0x4080000L) == 0x4080000L && colHeight[1] < 2) {
return 4;
}
if ((fieldP1 & 0x204000000L) == 0x204000000L
&& colHeight[3] < 4) {
return 4;
}
break;
default:
break;
}
case 5:
switch (colHeight[5]) {
case 0:
if ((fieldP1 & 0x4010000L) == 0x4010000L && colHeight[3] < 2) {
return 5;
}
break;
case 1:
if ((fieldP1 & 0x108000L) == 0x108000L && colHeight[2] < 4) {
return 5;
}
if ((fieldP1 & 0x2100000L) == 0x2100000L && colHeight[4] < 2) {
return 5;
}
if ((fieldP1 & 0x100020L) == 0x100020L && colHeight[4] < 2) {
return 5;
}
break;
case 2:
if ((fieldP1 & 0x1004000L) == 0x1004000L && colHeight[3] < 4) {
return 5;
}
if ((fieldP1 & 0x4010L) == 0x4010L && colHeight[3] < 4) {
return 5;
}
if ((fieldP1 & 0x208000L) == 0x208000L
&& (colHeight[2] < 2 || colHeight[6] < 2)) {
return 5;
}
if ((fieldP1 & 0x8008000L) == 0x8008000L && colHeight[3] < 2) {
return 5;
}
if ((fieldP1 & 0x8200000L) == 0x8200000L && colHeight[4] < 2) {
return 5;
}
if ((fieldP1 & 0x8008L) == 0x8008L && colHeight[3] < 2) {
return 5;
}
if ((fieldP1 & 0x200008L) == 0x200008L && colHeight[4] < 2) {
return 5;
}
break;
case 3:
if ((fieldP1 & 0x40008L) == 0x40008L && colHeight[4] < 4) {
return 5;
}
if ((fieldP1 & 0x42000L) == 0x42000L && colHeight[6] < 2) {
return 5;
}
if ((fieldP1 & 0x400002L) == 0x400002L && colHeight[4] < 2) {
return 5;
}
if ((fieldP1 & 0x408000L) == 0x408000L && colHeight[6] < 4) {
return 5;
}
if ((fieldP1 & 0x20400000L) == 0x20400000L && colHeight[4] < 2) {
return 5;
}
break;
case 4:
if ((fieldP1 & 0x82000L) == 0x82000L
&& (colHeight[2] < 4 || colHeight[6] < 4)) {
return 5;
}
if ((fieldP1 & 0x2002000L) == 0x2002000L && colHeight[3] < 4) {
return 5;
}
if ((fieldP1 & 0x2080000L) == 0x2080000L && colHeight[4] < 4) {
return 5;
}
if ((fieldP1 & 0x2002L) == 0x2002L && colHeight[3] < 4) {
return 5;
}
if ((fieldP1 & 0x80002L) == 0x80002L && colHeight[4] < 4) {
return 5;
}
if ((fieldP1 & 0x4001L) == 0x4001L && colHeight[3] < 2) {
return 5;
}
if ((fieldP1 & 0x10004000L) == 0x10004000L && colHeight[3] < 2) {
return 5;
}
break;
case 5:
if ((fieldP1 & 0x102000L) == 0x102000L && colHeight[2] < 2) {
return 5;
}
if ((fieldP1 & 0x8100000L) == 0x8100000L && colHeight[4] < 4) {
return 5;
}
break;
default:
break;
}
case 6:
switch (colHeight[6]) {
case 0:
if ((fieldP1 & 0x100400L) == 0x100400L && colHeight[4] < 2) {
return 6;
}
break;
case 1:
if ((fieldP1 & 0x4200L) == 0x4200L && colHeight[3] < 4) {
return 6;
}
if ((fieldP1 & 0x84000L) == 0x84000L && colHeight[5] < 2) {
return 6;
}
break;
case 2:
if ((fieldP1 & 0x40100L) == 0x40100L && colHeight[4] < 4) {
return 6;
}
if ((fieldP1 & 0x8200L) == 0x8200L && colHeight[3] < 2) {
return 6;
}
if ((fieldP1 & 0x200200L) == 0x200200L && colHeight[4] < 2) {
return 6;
}
if ((fieldP1 & 0x208000L) == 0x208000L && colHeight[5] < 2) {
return 6;
}
break;
case 3:
if ((fieldP1 & 0x810000L) == 0x810000L && colHeight[5] < 2) {
return 6;
}
break;
case 4:
if ((fieldP1 & 0x2080L) == 0x2080L && colHeight[3] < 4) {
return 6;
}
if ((fieldP1 & 0x80080L) == 0x80080L && colHeight[4] < 4) {
return 6;
}
if ((fieldP1 & 0x82000L) == 0x82000L && colHeight[5] < 4) {
return 6;
}
if ((fieldP1 & 0x400100L) == 0x400100L && colHeight[4] < 2) {
return 6;
}
break;
case 5:
if ((fieldP1 & 0x4080L) == 0x4080L && colHeight[3] < 2) {
return 6;
}
if ((fieldP1 & 0x204000L) == 0x204000L && colHeight[5] < 4) {
return 6;
}
break;
default:
break;
}
default:
break;
}
return (-1);
}
/**
* Generate the zobrist-Key for a board
*
* @param f1
* BitBoard of Player1
* @param f2
* BitBoard of Player2
* @return
*/
public static long toZobrist(long f1, long f2) {
int i, j, stelle;
long temp;
long ZobristKey = 0L;
for (i = 0; i < 7; i++) {
for (j = 0; j < 6; j++) {
stelle = 41 - (i * 6 + j);
temp = (1L << stelle);
if ((f1 & temp) == temp)
ZobristKey ^= rnd[0][i * 6 + j];
else if ((f2 & temp) == temp)
ZobristKey ^= rnd[1][i * 6 + j];
else
break;
}
}
return ZobristKey;
}
/**
* Check, if the current board is symmetric
*
* @return
*/
private boolean isSymmetric() {
long fieldP1mirrored = getMirroredField(PLAYER1);
long fieldP2mirrored = getMirroredField(PLAYER2);
return (fieldP1mirrored == fieldP1 && fieldP2mirrored == fieldP2);
}
/**
* Check, if it is possible to create a symmetric board from the current one
*
* @return
*/
private boolean symPossible() {
long fieldP1mirrored = getMirroredField(PLAYER1);
long fieldP2mirrored = getMirroredField(PLAYER2);
return ((fieldP1mirrored & fieldP2) == 0L && (fieldP2mirrored & fieldP1) == 0L);
}
/**
* Root-node of the alpha-Beta-algorithm
*
* @param retValue
* true, if game-theoretic-value shall be returned
* @return best move for the current player, or game-theoretic-value for the
* current board
*/
protected int rootNode(boolean retValue) {
int moves[], x, y = 0, bestMove = -1, player;
int value = 0, alpha = -9999, beta = 9999;
// check, which players turn
player = (countPieces() % 2 == 0 ? PLAYER1 : PLAYER2);
// Number of moves until a draw is reached
movesTillFull = (42 - countPieces());
moves = generateMoves(player, true);
// look for a direct Win for the current player
if (hasWin(player)) {
if (!retValue)
for (x = 0; moves[x] != -1; x++) {
if (canWin(player, moves[x], colHeight[moves[x]])) {
return moves[x];
}
}
else {
return (player == 1 ? 1000 : -1000);
}
}
// If the board is symmetric, only one half has to be analyzed
if (isSymmetric()) {
int tmp[] = new int[8];
for (x = 0; moves[x] != -1; x++) {
if (moves[x] < 4)
tmp[y++] = moves[x];
}
for (x = 0; x < y; x++)
moves[x] = tmp[x];
moves[x] = -1;
}
// Try all moves for the current player
for (x = 0; moves[x] > -1; x++) {
putPiece(player, moves[x]);
if (player == PLAYER1)
value = alphaBetaStartP2(1, alpha, beta,
toZobrist(fieldP1, fieldP2), symPossible());
else
value = alphaBetaStartP1(1, alpha, beta,
toZobrist(fieldP1, fieldP2), symPossible());
removePiece(player, moves[x]);
if (player == PLAYER1) {
if (value > alpha) {
alpha = value;
bestMove = moves[x];
}
if (value == 1000) {
if (!retValue)
return bestMove;
return alpha;
}
} else if (player == PLAYER2) {
if (value < beta) {
beta = value;
bestMove = moves[x];
}
if (value == -1000) {
if (!retValue)
return bestMove;
return beta;
}
}
}
// if the board is a loose for the player, look for the most distant one
if (!seekFarLoose
&& !retValue
&& ((player == PLAYER1 && alpha < -500) || (player == PLAYER2 && beta > 500))
&& (countPieces() > 12 || useDeepBookDist)) {
initTranspositionTable();
boolean oldUsebook = useBook;
boolean oldUseDeepBook = useDeepBook;
boolean oldUseDeepBookDist = useDeepBookDist;
useBook = false;
useDeepBook = false;
useDeepBookDist = true;
seekFarLoose = true;
looseIntervall = 42 / countPieces() * 2;
int newBestMove = rootNode(false);
seekFarLoose = false;
looseIntervall = 20;
useBook = oldUsebook;
useDeepBook = oldUseDeepBook;
useDeepBookDist = oldUseDeepBookDist;
System.gc();
return newBestMove;
}
if (!retValue)
return bestMove;
return (player == 1 ? alpha : beta);
}
/**
* @param depth
* current search depth
* @param alpha
* @param beta
* @param zobr
* current Zobrist-Key
* @param symPos
* is a symmetry possible for the current board
* @return
*/
private int alphaBetaStartP1(int depth, int alpha, int beta, long zobr,
boolean symPos) {
// distance to win / loss
int distance = depth;// (seekFarLoose ? countPieces() / looseIntervall :
// 0);
// First, check for own Win (Player 1)
if (hasWin(PLAYER1))
return 1020 - distance;
// Check for draw
if (depth == movesTillFull) {
return 0;
}
// if search-horizon is reached
if (depth >= searchDepth) {
int eval = evaluate(PLAYER1, zobr); //Params actually not needed
if (eval != -1)
return eval;
// if evaluate doesn't get a proper value, then
// search a little deeper
}
// Normal Book
if (useBook && depth < 10 && countPieces() == 8 && books != null) {
// The params must be swapped, because the database uses a other
// representation
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
int value = books.getOpeningBook().getValue(codedPos,
codedPosMirrored);
if (value == 0) {
return 0;
} else if (value == 1) {
return -992;
} else {
return 992;
}
}
// Deep Book with Distance
if (useDeepBookDist && depth < 14 && countPieces() == 12
&& books != null) {
// The params must be swapped, because the database uses a other
// representation
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
return books.getOpeningBookDeepDist().getValue(codedPos,
codedPosMirrored);
}
// Deep Book
if (useDeepBook && depth < 14 && countPieces() == 12 && books != null) {
// The params must be swapped, because the database uses a other
// representation
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
int value = books.getOpeningBookDeep().getValue(codedPos,
codedPosMirrored);
if (value == 0) {
return 0;
} else if (value == 1) {
return -988;
} else {
return 988;
}
}
// Get index in Transposition-Table
// 32-Bit-Operation
int index = ((int) zobr & (lTransPosSize - 1));
// int transPosition = (unsigned long)zobr % lTransPosSize;
// should be equal to above operation (time)
// Check for Entry in Transposition-Table
if (lKey[index] == zobr) {
short v = lValue[index];
switch (lFlag[index]) {
case TRANSPOSEXACT:
return v;
case TRANSPOSLOWER:
if (v >= beta)
return v;
if (v > alpha)
alpha = v;
break;
case TRANSPOSUPPER:
if (v <= alpha)
return v;
if (v < beta)
beta = v;
break;
}
}
boolean isExactValue = false;
int x, y = 0, later = -1, z = -1, q = -1;
long t;
short value = 0;
int[] drlt = new int[1];
int anz;
int moves[];
// Mirror Board
long f1 = getMirroredField(PLAYER1);
long f2 = getMirroredField(PLAYER2);
if (tds != null && countPieces() <= 10)
moves = tds.getBestMoveList(fieldP1, fieldP2);
else
// dynamic move-ordering
moves = generateMoves(PLAYER1, true);
// Check, if symmetry is still possible. If current board is symmetric,
// only one half of the board must be evaluated
if (symPos)
if ((symPos = ((f1 & fieldP1) == 0L && (f2 & fieldP2) == 0L)))
if ((f1 == fieldP2 && f2 == fieldP1)) {
int tmp[] = new int[8];
for (x = 0; moves[x] != -1; x++) {
if (moves[x] < 4)
tmp[y++] = moves[x];
}
for (x = 0; x < y; x++)
moves[x] = tmp[x];
moves[x] = -1;
}
// Try to find mirrored board in Transposition-Table
if (depth < 16 /* && symPos */) { // scheint ohne das
// Auskommentiere schneller zu sein
long nZobr = toZobrist(f1, f2);
int transPositionN = ((int) nZobr & (lTransPosSize - 1));
if (lKey[transPositionN] == nZobr) {
short v = lValue[transPositionN];
switch (lFlag[transPositionN]) {
case TRANSPOSEXACT:
return v;
case TRANSPOSLOWER:
if (v >= beta)
return v;
if (v > alpha)
alpha = v;
break;
case TRANSPOSUPPER:
if (v <= alpha)
return v;
if (v < beta)
beta = v;
break;
}
}
}
// Some special tests, to get the GTV directly. Doesn't work all the
// time
if (depth < 14 && !hasWin(PLAYER2)) {
for (x = 0; moves[x] > -1; x++) {
t = fieldP1;
putPiece(PLAYER1, moves[x]);
if (canWin(PLAYER2, moves[x], colHeight[moves[x]])) {
fieldP1 = t;
colHeight[moves[x]]--;
continue;
}
anz = hasWin(PLAYER1, drlt);
// Check if current player has two direct threats -> immediate
// Win
if (anz > 1) {
fieldP1 = t;
colHeight[moves[x]]--;
lKey[index] = zobr;
lFlag[index] = TRANSPOSEXACT;
lValue[index] = (short) (1020 - distance);
return 1020 - distance;
} else if (anz != 0) {
// Check if current player has two threats on top of
// each-other -> direct Win
if (colHeight[drlt[0]] < 5
&& canWin(PLAYER1, drlt[0], colHeight[drlt[0]] + 1)) {
fieldP1 = t;
colHeight[moves[x]]--;
lKey[index] = zobr;
lFlag[index] = TRANSPOSEXACT;
lValue[index] = (short) (1020 - distance);
return 1020 - distance;
}
colHeight[drlt[0]]++;
// Check, if a threat can be forced
if (q == -1 && findOddThreatP1(0) != -1)
q = moves[x];
colHeight[drlt[0]]--;
}
fieldP1 = t;
colHeight[moves[x]]--;
}
} else {
// Search for threats, which are on top of each other
for (x = 0; moves[x] != -1; x++) {
if (colHeight[moves[x]] < 4) {
colHeight[moves[x]]++;
if (canWin(PLAYER1, moves[x], colHeight[moves[x]]))
if (canWin(PLAYER1, moves[x], colHeight[moves[x]] + 1)
&& !hasWin(PLAYER2)) { // direct win ->
colHeight[moves[x]]--;
return 1020 - distance;
}
colHeight[moves[x]]--;
}
}
}
// Check, if a Odd Threat can be created (only odd threats are from
// interest for the beginning player)
y = findOddThreatP1(0);
if (y > -1) {
// Look for another odd threat
z = findOddThreatP1(y);
if (z != -1 && colHeight[z] < colHeight[y]) {
x = z;
z = y;
y = x;
}
t = fieldP1;
fieldP1 |= fieldMask[y][colHeight[y]++];
value = (short) alphaBetaStartP2(depth + 1, alpha, beta, zobr
^ rnd[0][y * 6 - 1 + colHeight[y]], symPos);
fieldP1 = t;
colHeight[y]--;
if (value >= beta) {
lKey[index] = zobr;
lFlag[index] = TRANSPOSLOWER;
lValue[index] = value;
return value;
} else if (value > alpha) {
alpha = value;
isExactValue = true;
}
if (value >= 1000) {
lKey[index] = zobr;
lFlag[index] = (isExactValue ? TRANSPOSEXACT : TRANSPOSUPPER);
lValue[index] = value;
return value;
}
if (z > -1) {
t = fieldP1;
fieldP1 |= fieldMask[z][colHeight[z]++];
value = (short) alphaBetaStartP2(depth + 1, alpha, beta, zobr
^ rnd[0][z * 6 - 1 + colHeight[z]], symPos);
fieldP1 = t;
colHeight[z]--;
if (value >= beta) {
lKey[index] = zobr;
lFlag[index] = TRANSPOSLOWER;
lValue[index] = value;
return value;
} else if (value > alpha) {
alpha = value;
isExactValue = true;
}
if (value >= 1000) {
lKey[index] = zobr;
lFlag[index] = (isExactValue ? TRANSPOSEXACT
: TRANSPOSUPPER);
lValue[index] = value;
return value;
}
}
}
// Try to force a odd threat
if (q != -1) {
if (colHeight[q] < 4 && colHeight[q] % 2 != 0 && later == -1
&& canWin(PLAYER1, q, colHeight[q] + 1))
later = q;
else {
t = fieldP1;
fieldP1 |= fieldMask[q][colHeight[q]++];
value = (short) alphaBetaStartP2(depth + 1, alpha, beta, zobr
^ rnd[0][q * 6 - 1 + colHeight[q]], symPos);
fieldP1 = t;
colHeight[q]--;
if (value >= beta) {
lKey[index] = zobr;
lFlag[index] = TRANSPOSLOWER;
lValue[index] = value;
return value;
} else if (value > alpha) {
alpha = value;
isExactValue = true;
}
if (value >= 1000) {
lKey[index] = zobr;
lFlag[index] = (isExactValue ? TRANSPOSEXACT
: TRANSPOSUPPER);
lValue[index] = value;
return value;
}
}
}
// Try all legal Moves
for (x = 0; moves[x] > -1; x++) {
if (y == moves[x] || z == moves[x] || q == moves[x])
continue;
// Don't put a piece underneath a own threat -> threat would become
// worthless
if (colHeight[moves[x]] < 4 && colHeight[moves[x]] % 2 != 0
&& later == -1
&& canWin(PLAYER1, moves[x], colHeight[moves[x]] + 1))
later = moves[x];
else {
t = fieldP1;
fieldP1 |= fieldMask[moves[x]][colHeight[moves[x]]++];
value = (short) alphaBetaStartP2(depth + 1, alpha, beta, zobr
^ rnd[0][moves[x] * 6 - 1 + colHeight[moves[x]]],
symPos);
fieldP1 = t;
colHeight[moves[x]]--;
if (value >= beta) {
lKey[index] = zobr;
lFlag[index] = TRANSPOSLOWER;
lValue[index] = value;
return value;
} else if (value > alpha) {
alpha = value;
isExactValue = true;
}
if (value >= 1000) {
lKey[index] = zobr;
lFlag[index] = (isExactValue ? TRANSPOSEXACT
: TRANSPOSUPPER);
lValue[index] = value;
return value;
}
}
}
// Put a piece underneath a own threat
if (later > -1) {
t = fieldP1;
fieldP1 |= fieldMask[later][colHeight[later]++];
value = (short) alphaBetaStartP2(depth + 1, alpha, beta, zobr
^ rnd[0][later * 6 - 1 + colHeight[later]], symPos);
fieldP1 = t;
colHeight[later]--;
if (value >= beta) {
lKey[index] = zobr;
lFlag[index] = TRANSPOSLOWER;
lValue[index] = value;
return value;
} else if (value > alpha) {
alpha = value;
isExactValue = true;
}
}
if (isExactValue)
lFlag[index] = TRANSPOSEXACT;
else
// No move could be found, that was better than alpha
lFlag[index] = TRANSPOSUPPER;
lKey[index] = zobr;
lValue[index] = (short) alpha;
return alpha;
}
/**
* For comments, look at alphaBetaStartP1
*
* @param depth
* current searchDepth
* @param alpha
* @param beta
* @param zobr
* current Zobrist-Key
* @param symPos
* is a symmetry possible on the current board
* @return Value
*/
private int alphaBetaStartP2(int depth, int alpha, int beta, long zobr,
boolean symPos) {
int distance = depth;// (seekFarLoose ? countPieces() / looseIntervall :
// 0);
if (hasWin(PLAYER2))
return -1020 + distance;
int moves[];
int x;
long t;
int transPosition;
//if (tds != null && countPieces() <= 10)
// moves = tds.getBestMoveList(fieldP1, fieldP2);
//else
// dynamische Zugsortierung
moves = generateMoves(PLAYER2, true);
// Enhanced Transposition Cutoff
for (x = 0; moves[x] != (-1); x++) {
t = zobr ^ rnd[1][moves[x] * 6 + colHeight[moves[x]]];
long k;
short v;
byte f;
// Hash-Table ist in zwei Stufen unterteilt, daher die
// Unterscheidung
if (depth > 13) {
transPosition = ((int) t & (transPosSize - 1));
k = key[transPosition];
v = value[transPosition];
f = flag[transPosition];
} else {
transPosition = ((int) t & (lTransPosSize - 1));
k = lKey[transPosition];
v = lValue[transPosition];
f = lFlag[transPosition];
}
if (k == t && f != TRANSPOSLOWER && v <= alpha)
return v;
}
int y = 0, later = -1, z = -1, q = -1, anz;
int[] drlt = new int[1];
int value = 0;
if (symPos) // War beim letzten Zug eine symmetrische Stellung möglich
if ((symPos = symPossible())) // ist immer noch eine möglich
if (isSymmetric()) { // liegt eine echte Symmetrie vor
// Nur eine Seite des Spielfeldes muss ausprobiert werden
int tmp[] = new int[8];
for (x = 0; moves[x] != -1; x++) {
if (moves[x] < 4)
tmp[y++] = moves[x];
}
for (x = 0; x < y; x++)
moves[x] = tmp[x];
moves[x] = -1;
}
// Wenn Spieler 1 eine akute Drohung hat, dann lohnt es sich nicht,
// diese Stellung genauuer zu untersuchen
if (depth < 12 && !hasWin(PLAYER1)) {
for (x = 0; moves[x] > -1; x++) {
t = fieldP2;
fieldP2 |= fieldMask[moves[x]][colHeight[moves[x]]++];
// Wenn Spieler2 einen Zug macht und Spieler1 daraufhin gewinnt,
// dann abbrechen
if (canWin(PLAYER1, moves[x], colHeight[moves[x]])) {
fieldP2 = t;
colHeight[moves[x]]--;
continue;
}
anz = hasWin(PLAYER2, drlt);
if (anz > 1) {
fieldP2 = t;
colHeight[moves[x]]--;
return -1020 + distance;
} else if (anz != 0) {
// Wenn Spieler2 aber doch noch eine Drohung hatte
if (colHeight[drlt[0]] < 5
&& canWin(PLAYER2, drlt[0], colHeight[drlt[0]] + 1)) {
fieldP2 = t;
colHeight[moves[x]]--;
return -1020 + distance;
}
colHeight[drlt[0]]++;
// Kann eine Drohung erzwungen werden
if (q == -1 && findThreat(PLAYER2, 0) != -1)
q = moves[x];
colHeight[drlt[0]]--;
}
fieldP2 = t;
colHeight[moves[x]]--;
}
} else {
// Nach Doppeldrohungen suchen, die direkt übereinander sind
for (x = 0; moves[x] != -1; x++) {
if (colHeight[moves[x]] < 4) {
colHeight[moves[x]]++;
if (canWin(PLAYER2, moves[x], colHeight[moves[x]]))
if (canWin(PLAYER2, moves[x], colHeight[moves[x]] + 1)
&& !hasWin(PLAYER1)) {
colHeight[moves[x]]--;
return -1020 + distance;
}
colHeight[moves[x]]--;
}
}
}
y = findThreat(PLAYER2, 0);
if (y > -1) {
t = fieldP2;
fieldP2 |= fieldMask[y][colHeight[y]++];
if (depth > 13)
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd[1][y * 6 - 1 + colHeight[y]]);
else
value = alphaBetaStartP1(depth + 1, alpha, beta, zobr
^ rnd[1][y * 6 - 1 + colHeight[y]], symPos);
fieldP2 = t;
colHeight[y]--;
if (value <= alpha)
return value;
else if (value <= -1000) // Bei Sieg (eindeutig) abbrechen
return value;
else if (value < beta)
beta = value;
z = findThreat(PLAYER2, y);
if (z > -1) {
t = fieldP2;
fieldP2 |= fieldMask[z][colHeight[z]++];
if (depth > 13)
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd[1][z * 6 - 1 + colHeight[z]]);
else
value = alphaBetaStartP1(depth + 1, alpha, beta, zobr
^ rnd[1][z * 6 - 1 + colHeight[z]], symPos);
fieldP2 = t;
colHeight[z]--;
if (value <= alpha)
return value;
else if (value <= -1000)
return value;
else if (value < beta)
beta = value;
}
}
if (q != -1) {
if (colHeight[q] < 5 && colHeight[q] % 2 == 0 && later == -1
&& canWin(PLAYER2, q, colHeight[q] + 1))
later = q;
else {
t = fieldP2;
fieldP2 |= fieldMask[q][colHeight[q]++];
value = alphaBetaStartP1(depth + 1, alpha, beta, zobr
^ rnd[1][q * 6 - 1 + colHeight[q]], symPos);
fieldP2 = t;
colHeight[q]--;
if (value <= alpha)
return value;
else if (value <= -1000)
return value;
else if (value < beta)
beta = value;
}
}
for (x = 0; moves[x] > -1; x++) {
if (y == moves[x] || z == moves[x] || q == moves[x])
continue;
if (colHeight[moves[x]] < 5 && colHeight[moves[x]] % 2 == 0
&& later == -1
&& canWin(PLAYER2, moves[x], colHeight[moves[x]] + 1))
later = moves[x];
else {
t = fieldP2;
fieldP2 |= fieldMask[moves[x]][colHeight[moves[x]]++];
if (depth > 13)
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd[1][moves[x] * 6 - 1 + colHeight[moves[x]]]);
else
value = alphaBetaStartP1(depth + 1, alpha, beta, zobr
^ rnd[1][moves[x] * 6 - 1 + colHeight[moves[x]]],
symPos);
fieldP2 = t;
colHeight[moves[x]]--;
if (value <= alpha)
return value;
else if (value <= -1000)
return value;
else if (value < beta)
beta = value;
}
}
if (later > -1) {
t = fieldP2;
fieldP2 |= fieldMask[later][colHeight[later]++];
if (depth > 13)
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd[1][later * 6 - 1 + colHeight[later]]);
else
value = alphaBetaStartP1(depth + 1, alpha, beta, zobr
^ rnd[1][later * 6 - 1 + colHeight[later]], symPos);
fieldP2 = t;
colHeight[later]--;
if (value <= alpha)
return value;
else if (value <= -1000)
return value;
else if (value < beta)
beta = value;
}
return beta;
}
/**
* Faster Alpha-Beta-Search for more deep depths.
*
* @param depth
* current search-depth
* @param alpha
* @param beta
* @param zobr
* current Zobrist-Key
* @return Value
*/
private int alphaBetaP1(int depth, int alpha, int beta, long zobr) {
// Check for direct Win
if (hasWin(PLAYER1)) {
int distance = (seekFarLoose ? countPieces() / looseIntervall : 0);
return 1000 - distance;
}
// If only 2 free fields are left on the board, a exact value can be
// determined
if (depth == movesTillFull - 2) {
long f = (~(fieldP2 | fieldP1)) & TOPROW;
// Wenn beide leeren Felder in oberster Reihe sind
if ((f & (f - 1L)) != 0L) {
int v[] = new int[2], i = 0;
if (colHeight[0] != 6)
v[i++] = 0;
if (colHeight[6] != 6)
v[i++] = 6;
if (colHeight[1] != 6)
v[i++] = 1;
if (colHeight[5] != 6)
v[i++] = 5;
if (colHeight[2] != 6)
v[i++] = 2;
if (colHeight[4] != 6)
v[i++] = 4;
if (colHeight[3] != 6)
v[i] = 3;
if (canWin(PLAYER2, v[0], colHeight[v[0]])
&& canWin(PLAYER2, v[1], colHeight[v[1]]))
return -1000;
return 0;
} else {
short v = -1;
if (colHeight[0] != 6)
v = 0;
else if (colHeight[6] != 6)
v = 6;
else if (colHeight[1] != 6)
v = 1;
else if (colHeight[5] != 6)
v = 5;
else if (colHeight[2] != 6)
v = 2;
else if (colHeight[4] != 6)
v = 4;
else if (colHeight[3] != 6)
v = 3;
if (canWin(PLAYER2, v, colHeight[v] + 1))
return -1000;
return 0;
}
}
// Check for a draw
if (depth == movesTillFull) {
return 0;
}
// Evaluate, if search-horizon is reached
if (depth >= searchDepth) {
// TODO: Maybe this part should be put beneath the
// transposition-retrieval, so that the value of the evaluation
// can be stored in the transposition-table
int eval = evaluate(PLAYER1, zobr);
if (eval != -1)
return eval;
// if evaluate doesn't get a proper value, then
// search a little deeper
}
// Index of Transposition-Table
int index = ((int) zobr & (transPosSize - 1));
// Check, if current board is in Transposition-Table
if (key[index] == zobr) {
short v = value[index];
switch (flag[index]) {
case TRANSPOSEXACT:
return v;
case TRANSPOSLOWER:
if (v >= beta)
return v;
if (v > alpha)
alpha = v;
break;
case TRANSPOSUPPER:
if (v <= alpha)
return v;
if (v < beta)
beta = v;
break;
}
}
Boolean isValueExact = false;
int later = -1, x = -1, value;
long t;
// Look for odd Threats
if (depth < 24) {
x = findOddThreatP1(0);
if (x > -1) {
t = fieldP1;
fieldP1 |= fieldMask[x][colHeight[x]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd[0][x * 6 - 1 + colHeight[x]]);
fieldP1 = t;
colHeight[x]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
}
// Try Moves in all the columns
if (x != 3 && colHeight[3] < 6) {
if (colHeight[3] < 4 && colHeight[3] % 2 != 0
&& canWin(PLAYER1, 3, colHeight[3] + 1))
later = 3;
else {
t = fieldP1;
fieldP1 |= fieldMask3[colHeight[3]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd13[colHeight[3]]);
fieldP1 = t;
colHeight[3]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
}
if (x != 4 && colHeight[4] < 6) {
if (colHeight[4] < 4 && later == -1 && colHeight[4] % 2 != 0
&& canWin(PLAYER1, 4, colHeight[4] + 1))
later = 4;
else {
t = fieldP1;
fieldP1 |= fieldMask4[colHeight[4]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd14[colHeight[4]]);
fieldP1 = t;
colHeight[4]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
}
if (x != 2 && colHeight[2] < 6) {
if (later == -1 && colHeight[2] < 4 && colHeight[2] % 2 != 0
&& canWin(PLAYER1, 2, colHeight[2] + 1))
later = 2;
else {
t = fieldP1;
fieldP1 |= fieldMask2[colHeight[2]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd12[colHeight[2]]);
fieldP1 = t;
colHeight[2]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
}
if (x != 5 && colHeight[5] < 6) {
if (later == -1 && colHeight[5] < 4 && colHeight[5] % 2 != 0
&& canWin(PLAYER1, 5, colHeight[5] + 1))
later = 5;
else {
t = fieldP1;
fieldP1 |= fieldMask5[colHeight[5]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd15[colHeight[5]]);
fieldP1 = t;
colHeight[5]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
}
if (x != 1 && colHeight[1] < 6) {
if (later == -1 && colHeight[1] < 4 && colHeight[1] % 2 != 0
&& canWin(PLAYER1, 1, colHeight[1] + 1))
later = 1;
else {
t = fieldP1;
fieldP1 |= fieldMask1[colHeight[1]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd11[colHeight[1]]);
fieldP1 = t;
colHeight[1]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
}
if (x != 6 && colHeight[6] < 6) {
if (later == -1 && colHeight[6] < 4 && colHeight[6] % 2 != 0
&& canWin(PLAYER1, 6, colHeight[6] + 1))
later = 6;
else {
t = fieldP1;
fieldP1 |= fieldMask6[colHeight[6]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd16[colHeight[6]]);
fieldP1 = t;
colHeight[6]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
}
if (x != 0 && colHeight[0] < 6) {
t = fieldP1;
fieldP1 |= fieldMask0[colHeight[0]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd10[colHeight[0]]);
fieldP1 = t;
colHeight[0]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
// Put piece underneath own threat
if (later != (-1)) {
t = fieldP1;
fieldP1 |= fieldMask[later][colHeight[later]++];
value = alphaBetaP2(depth + 1, alpha, beta, zobr
^ rnd[0][later * 6 - 1 + colHeight[later]]);
fieldP1 = t;
colHeight[later]--;
if (value >= beta) {
key[index] = zobr;
this.value[index] = (short) value;
flag[index] = TRANSPOSLOWER;
return value;
} else if (value > alpha) {
alpha = value;
isValueExact = true;
}
}
key[index] = zobr;
this.value[index] = (short) alpha;
flag[index] = (isValueExact ? TRANSPOSEXACT : TRANSPOSUPPER);
return alpha;
}
/**
* For Comments, check the almost equal method above (alphaBetaP1)
*
* @param depth
* current search-depth
* @param alpha
* @param beta
* @param zobr
* current Zobrist-Key
* @return Value
*/
private int alphaBetaP2(int depth, int alpha, int beta, long zobr) {
if (hasWin(PLAYER2)) {
int pieceCount = (seekFarLoose ? countPieces() / looseIntervall : 0);
return -1000 + pieceCount;
}
int later = -1, x, value;
long t;
if (depth < 20)
for (x = 0; x < 7; x++) {
if (colHeight[x] != 6) {
t = zobr ^ rnd[1][x * 6 + colHeight[x]];
int transPosition = ((int) t & (transPosSize - 1));
long k = key[transPosition];
short v = this.value[transPosition];
byte f = flag[transPosition];
if (k == t && f != TRANSPOSLOWER && v <= alpha)
return v;
}
}
x = -1;
if (depth < 20) {
x = findThreat(PLAYER2, 0);
if (x > -1) {
t = fieldP2;
fieldP2 |= fieldMask[x][colHeight[x]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd[1][x * 6 - 1 + colHeight[x]]);
fieldP2 = t;
colHeight[x]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
}
if (x != 3 && colHeight[3] < 6) {
if (colHeight[3] < 5 && canWin(PLAYER2, 3, colHeight[3] + 1))
later = 3;
else {
t = fieldP2;
fieldP2 |= fieldMask3[colHeight[3]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd23[colHeight[3]]);
fieldP2 = t;
colHeight[3]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
}
if (x != 4 && colHeight[4] < 6) {
if (later == -1 && colHeight[4] < 5
&& canWin(PLAYER2, 4, colHeight[4] + 1))
later = 4;
else {
t = fieldP2;
fieldP2 |= fieldMask4[colHeight[4]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd24[colHeight[4]]);
fieldP2 = t;
colHeight[4]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
}
if (x != 2 && colHeight[2] < 6) {
if (later == -1 && colHeight[2] < 5
&& canWin(PLAYER2, 2, colHeight[2] + 1))
later = 2;
else {
t = fieldP2;
fieldP2 |= fieldMask2[colHeight[2]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd22[colHeight[2]]);
fieldP2 = t;
colHeight[2]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
}
if (x != 5 && colHeight[5] < 6) {
if (later == -1 && colHeight[5] < 5
&& canWin(PLAYER2, 5, colHeight[5] + 1))
later = 5;
else {
t = fieldP2;
fieldP2 |= fieldMask5[colHeight[5]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd25[colHeight[5]]);
fieldP2 = t;
colHeight[5]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
}
if (x != 1 && colHeight[1] < 6) {
if (later == -1 && colHeight[1] < 5
&& canWin(PLAYER2, 1, colHeight[1] + 1))
later = 1;
else {
t = fieldP2;
fieldP2 |= fieldMask1[colHeight[1]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd21[colHeight[1]]);
fieldP2 = t;
colHeight[1]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
}
if (x != 6 && colHeight[6] < 6) {
if (later == -1 && colHeight[6] < 5
&& canWin(PLAYER2, 6, colHeight[6] + 1))
later = 6;
else {
t = fieldP2;
fieldP2 |= fieldMask6[colHeight[6]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd26[colHeight[6]]);
fieldP2 = t;
colHeight[6]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
}
if (x != 0 && colHeight[0] < 6) {
t = fieldP2;
fieldP2 |= fieldMask0[colHeight[0]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd20[colHeight[0]]);
fieldP2 = t;
colHeight[0]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
if (later != (-1)) {
t = fieldP2;
fieldP2 |= fieldMask[later][colHeight[later]++];
value = alphaBetaP1(depth + 1, alpha, beta, zobr
^ rnd[1][later * 6 - 1 + colHeight[later]]);
fieldP2 = t;
colHeight[later]--;
if (value <= alpha)
return value;
else if (value < beta)
beta = value;
}
return beta;
}
/**
* This method currently only works for boards with not more than 2 threats
* (>70% of all boards)
*
* @return estimated Value for the current board
*/
public int evaluate(int curPlayer, long zobr) {
int numThreats = 0, threatsCol = 0, y;
long threatsP1 = 0L, threatsP2 = 0L;
// Ermittlung aller Drohungen beider Spieler!
// Außerdem Spalten markieren, in denen Drohungen
// vorhanden sind!
for (byte i = 0; i < COLCOUNT; i++) {
y = colHeight[i];
while (y < 6) {
if (canWin(PLAYER1, i, y)) {
threatsP1 |= fieldMask[i][y];
numThreats++;
// Markiert Spalte in der Drohung ist
threatsCol |= (1 << (6 - i));
break;
}
if (canWin(PLAYER2, i, y)) {
threatsP2 |= fieldMask[i][y];
numThreats++;
// Markiert Spalte in der Drohung ist
threatsCol |= (1 << (6 - i));
}
++y;
// Mehr Drohungen werden sowieso nicht untersucht
if (numThreats > 2)
return -1;
}
}
// Prüfen, wie viele Drohungen vorhanden sind
// und bei 0,1 oder 2 Drohungen Bewertung der
// Stellung ermitteln
switch (numThreats) {
case 0: // Wenn keiner eine Drohung hat
return 0;
case 1: // Wenn einer der beiden Spieler eine Drohung hat
if (threatsP2 != 0) {// Wenn Spieler2 die Drohung hat
// Wenn Spieler2 eine gerade Drohung hat
if ((threatsP2 & EVENROWS) != 0L)
return -500;
return 0;
}
// Wenn Spieler1 eine ungerade Drohung hat
if ((threatsP1 & ODDROWS) != 0L)
return 500;
return 0;
case 2: // Wenn insgesamt 2 Drohungen vorhanden sind
if (threatsP2 == 0L) { // Wenn Spieler2 keine Drohung hat
if ((threatsP1 & ODDROWS) != 0L)
return 500;
return 0;
}
if (threatsP1 == 0L) { // Wenn Spieler1 keine Drohung hat
// Wenn Spieler2 min. eine gerade Drohung hat
if ((threatsP2 & EVENROWS) != 0L)
return -500;
// Befinden sich die Drohungen von Spieler2 in unterschiedlichen
// spalten
if ((threatsCol & (threatsCol - 1)) != 0L)
// Wenn Spieler2 2 ungerade Drohungen hat
if ((threatsP2 & ODDROWS) == threatsP2)
return -500;
break;
}
// Wenn beide eine Drohung haben
// Wenn beide Drohungen in unterschiedlichen Spalten sind
if ((threatsCol & (threatsCol - 1)) != 0L) {
if ((threatsP1 & ODDROWS) != 0L)
if ((threatsP2 & ODDROWS) != 0L)
return 0; // Beide haben eine ungerade Drohung
else
// Spieler1 hat eine ungerade und Spieler2 eine gerade
// Drohung
return 500;
if ((threatsP1 & EVENROWS) != 0L)
return -500; // Spieler1 hat nur eine gerade Drohung
}
// Wenn beide Drohungen im gleichen Feld sind...
if ((threatsP1 & threatsP2) != 0L)
if ((threatsP1 & EVENROWS) != 0L)
// Spieler1 und Spieler2 haben eine gerade Drohung
return -500;
else
// Spieler1 und Spieler2 haben eine ungerade Drohung
return 500;
break;
}
return -1;
}
/**
* Find the best move for the current Player. If there are equal move,
* select randomly. If this board is a loss, make a completly random move.
* This method always rests the variable randomizeLosses.
*
* @param table
* @return best move (random choice)
*/
private int getBestMoveRandLoss(int[][] table) {
double[] vals = getNextVTable(table, false);
int sign = (countPieces() % 2 == 0 ? 1 : -1);
double bestVal = Double.NEGATIVE_INFINITY;
int bestMove = -1;
int countEqual = 1;
for (int i = 0; i < COLCOUNT; i++) {
if (vals[i] != Double.NaN) {
double curVal = vals[i] * sign;
if (curVal < 0 && curVal > -1000)
curVal = -10;
if (curVal > bestVal) {
bestMove = i;
bestVal = curVal;
countEqual = 1;
} else if (curVal == bestVal) {
countEqual++;
if (rand.nextDouble() < 1.0 / countEqual)
bestMove = i;
}
}
}
if (bestVal <= -1000 /* && countPieces() <= 10 */) {
boolean oldVal = randomizeEqualMoves;
randomizeLosses = false;
randomizeEqualMoves = false;
int x = getBestMove(table);
randomizeEqualMoves = oldVal;
randomizeLosses = true;
return x;
} else if (bestVal < 0 && countPieces() > 10) {
// Search most distant loss after opening-phase
boolean oldVal = randomizeEqualMoves;
randomizeLosses = false;
randomizeEqualMoves = false;
int x = getBestMove(table);
randomizeEqualMoves = oldVal;
randomizeLosses = true;
return x;
}
return bestMove;
}
// private int getBestMoveRandLoss(int[][] table) {
// double[] vals = getNextVTable(table, false);
// int sign = (countPieces() % 2 == 0 ? 1 : -1);
// double bestVal = Double.NEGATIVE_INFINITY;
// int bestMove = -1;
// int countEqual = 1;
// for (int i = 0; i < COLCOUNT; i++) {
// if (vals[i] != Double.NaN) {
// double curVal = vals[i] * sign;
// if (curVal < 0 && curVal > -1000)
// curVal = -10;
// if (curVal > bestVal) {
// bestMove = i;
// bestVal = curVal;
// countEqual = 1;
// } else if (curVal == bestVal) {
// countEqual++;
// if (rand.nextDouble() < 1.0 / countEqual)
// bestMove = i;
// }
// }
// }
//
// if (bestVal <= -1000) {
// boolean oldVal = randomizeEqualMoves;
// randomizeLosses = false;
// randomizeEqualMoves = false;
// int x = getBestMove(table);
// randomizeEqualMoves = oldVal;
// randomizeLosses = true;
// return x;
//
// } else if (bestVal < 0 && countPieces() >= 6) {
// // Search most distant loss after opening-phase
// boolean oldVal = randomizeEqualMoves;
// randomizeLosses = false;
// randomizeEqualMoves = false;
// useBook = false;
// int x = getBestMove(table);
// useBook=true;
// randomizeEqualMoves = oldVal;
// randomizeLosses = true;
// return x;
// }
// return bestMove;
// }
/**
* Find the best move for the current Player. If there are equal move,
* select randomly
*
* @param table
* @return best move (random choice)
*/
private int getBestMoveRand(int[][] table) {
double[] vals = getNextVTable(table, false);
int sign = (countPieces() % 2 == 0 ? 1 : -1);
double bestVal = Double.NEGATIVE_INFINITY;
int bestMove = -1;
int countEqual = 1;
for (int i = 0; i < COLCOUNT; i++) {
if (vals[i] != Double.NaN) {
double curVal = vals[i] * sign;
if (curVal > bestVal) {
bestMove = i;
bestVal = curVal;
countEqual = 1;
} else if (curVal == bestVal) {
countEqual++;
if (rand.nextDouble() < 1.0 / countEqual)
bestMove = i;
}
}
}
if (bestVal < 0) {
randomizeEqualMoves = false;
int x = getBestMove(table);
randomizeEqualMoves = true;
return x;
}
return bestMove;
}
/**
* Set Size of the Transposition Table
*
* @param index
* index in the Table of possible Values
*/
public void setTransPosSize(int index) {
// index in the array of possible values
transPosSize = TRANSPOSSIZE[index];
lTransPosSize = transPosSize / 8;
// Transposition Table for higher Search-Depths
key = new long[transPosSize];
value = new short[transPosSize];
flag = new byte[transPosSize];
// Transposition Table for lower Search-Depths
lKey = new long[lTransPosSize];
lValue = new short[lTransPosSize];
lFlag = new byte[lTransPosSize];
System.gc();
}
/**
* @param useNormalBook
* true, if normal book shall be used
* @param useDeepBook
* true, if deep book shall be used
* @param useDeepBookDist
* true, if normal deep book with exact distances shall be used
*/
public void setBooks(boolean useNormalBook, boolean useDeepBook,
boolean useDeepBookDist) {
useBook = useNormalBook;
this.useDeepBook = useDeepBook;
this.useDeepBookDist = useDeepBookDist;
}
/**
* Choose, if random move is made when more than one move has the same value
*
* @param randomize
*/
public void randomizeEqualMoves(boolean randomize) {
randomizeEqualMoves = randomize;
}
/**
* Find the best move for the current Player in method getBestMove(). If
* there are equal moves, select randomly. If a board is a loss, make a
* almost completly random move.
*/
public void randomizeLosses(boolean value) {
randomizeLosses = value;
}
/*
* (non-Javadoc)
*
* @see c4.PlayAgent#getBestMove(int[][])
*/
public int getBestMove(int[][] table) {
if (randomizeLosses)
return getBestMoveRandLoss(table);
if (randomizeEqualMoves)
return getBestMoveRand(table);
semOpDown();
setBoard(table);
int val = rootNode(false);
semOpUp();
return val;
}
/*
* (non-Javadoc)
*
* @see c4.PlayAgent#getScore(int[][], boolean)
*/
public double getScore(int[][] table, boolean useSigmoid) {
semOpDown();
setBoard(table);
double score = 0.1;
if (useBook && countPieces() == 8) {
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
int value = books.getOpeningBook().getValue(codedPos,
codedPosMirrored);
if (value == 0) {
score = 0;
} else if (value == 1) {
score = -992;
} else {
score = 992;
}
}
// Deep Book with Distance
else if (useDeepBookDist && countPieces() == 12 && books != null) {
// The params must be swapped, because the database uses a other
// representation
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
score = books.getOpeningBookDeepDist().getValue(codedPos,
codedPosMirrored);
}
// Deep Book
else if (useDeepBook && countPieces() == 12 && books != null) {
// The params must be swapped, because the database uses a other
// representation
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
int value = books.getOpeningBookDeep().getValue(codedPos,
codedPosMirrored);
if (value == 0) {
score = 0;
} else if (value == 1) {
score = -988;
} else {
score = 988;
}
} else
score = rootNode(true);
semOpUp();
if (!useSigmoid)
return score;
return Math.tanh(score);
}
/*
* (non-Javadoc)
*
* @see c4.PlayAgent#getNextVTable(int[][], boolean)
*/
@Override
public double[] getNextVTable(int[][] table, boolean useSigmoid) {
semOpDown();
setBoard(table);
double[] values = new double[7];
int player = (countPieces() % 2 == 0 ? PLAYER1 : PLAYER2);
int otherPlayer = (player == PLAYER1 ? PLAYER2 : PLAYER1);
int x;
for (x = 0; x < COLCOUNT; x++) {
if (colHeight[x] < ROWCOUNT) {
if (canWin(player, x, colHeight[x])) {
values[x] = (player == PLAYER1 ? 1001 : -1001);
if (useSigmoid)
values[x] = Math.tanh(values[x]);
continue;
}
putPiece(player, x);
double score = 0.1;
if (hasWin(otherPlayer))
score = (otherPlayer == PLAYER1 ? 1001 : -1001);
else if (useBook && countPieces() == 8) {
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(
getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
int value = books.getOpeningBook().getValue(codedPos,
codedPosMirrored);
if (value == 0) {
score = 0;
} else if (value == 1) {
score = -992;
} else {
score = 992;
}
} else if ((useDeepBook) && countPieces() == 12) {
// Die Parameter muessen vertauscht werden, da Spieler2 der
// Anziehende in der Datenbank ist
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(
getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
int value = books.getOpeningBookDeep().getValue(codedPos,
codedPosMirrored);
if (value == 0) {
score = 0;
} else if (value == 1) {
score = -988;
} else {
score = 988;
}
} else if (useDeepBookDist && countPieces() == 12) {
// Die Parameter muessen vertauscht werden, da Spieler2 der
// Anziehende in der Datenbank ist
int codedPos = fieldToHuffman(fieldP2, fieldP1, false);
int codedPosMirrored = fieldToHuffman(
getMirroredField(PLAYER2),
getMirroredField(PLAYER1), true);
score = books.getOpeningBookDeepDist().getValue(codedPos,
codedPosMirrored);
} else
score = rootNode(true);
values[x] = score;
if (useSigmoid)
values[x] = Math.tanh(values[x]);
removePiece(player, x);
} else
values[x] = Double.NaN;
}
semOpUp();
return values;
}
/*
* (non-Javadoc)
*
* @see c4.PlayAgent#getName()
*/
public String getName() {
return new String("Alpha-Beta-Agent");
}
/*
* (non-Javadoc)
*
* @see c4.Agent#semOpDown()
*/
@Override
public void semOpDown() {
try {
mutex.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*
* (non-Javadoc)
*
* @see c4.Agent#semOpUp()
*/
@Override
public void semOpUp() {
mutex.release();
}
public void setTDAgent(TDSAgent td) {
tds = td;
}
@Override
public AgentState getAgentState() {
// TODO Auto-generated method stub
return null;
}
}