// This software is copyright (c) 1996-2005 by
// John Tromp
// Insulindeweg 908
// 1095 DX Amsterdam
// Netherlands
// E-mail: tromp@cwi.nl
//
// This notice must not be removed.
// This software must not be sold for profit.
// You may redistribute if your distributees have the
// same rights and restrictions.
import java.io.*;
import java.text.DecimalFormat;
public class SearchGame extends TransGame {
static final int BOOKPLY = 0; // full-width search up to this depth
static final int REPORTPLY = -1;
int history[][] = new int[2][SIZE1];
long nodes, msecs;
void inithistory()
{
for (int side=0; side<2; side++)
for (int i=0; i<(WIDTH+1)/2; i++)
for (int h=0; h<H1/2; h++)
history[side][H1*i+h] = history[side][H1*(WIDTH-1-i)+HEIGHT-1-h] =
history[side][H1*i+HEIGHT-1-h] = history[side][H1*(WIDTH-1-i)+h] =
4+Math.min(3,i) + Math.max(-1,Math.min(3,h)-Math.max(3-i,0))
+ Math.min(3,Math.min(i,h)) + Math.min(3,h);
}
int ab(int alpha, int beta)
{
nodes++;
if (nplies == SIZE-1) // one move left
return DRAW; // by assumption, player to move can't win
int side, otherside;
otherside = (side = nplies & 1) ^ 1;
long other = color[otherside];
int i,nav,av[] = new int[WIDTH];
long newbrd;
boolean winontop;
for (i = nav = 0; i < WIDTH; i++) {
newbrd = other | (1L << height[i]); // check opponent move
if (!islegal(newbrd))
continue;
winontop = islegalhaswon(other | (2L << height[i]));
if (haswon(newbrd)) { // immediate threat
if (winontop) // can't stop double threat
return LOSS;
nav = 0; // forced move
av[nav++] = i;
while (++i < WIDTH)
if (islegalhaswon(other | (1L << height[i])))
return LOSS;
break;
}
if (!winontop)
av[nav++] = i;
}
if (nav == 0)
return LOSS;
if (nplies == SIZE-2) // two moves left
return DRAW; // opponent has no win either
int score;
if (nav == 1) {
makemove(av[0]);
score = LOSSWIN-ab(LOSSWIN-beta,LOSSWIN-alpha);
backmove();
return score;
}
int ttscore = transpose();
if (ttscore != UNKNOWN) {
if (ttscore == DRAWLOSS) {
if ((beta = DRAW) <= alpha)
return ttscore;
} else if (ttscore == DRAWWIN) {
if ((alpha = DRAW) >= beta)
return ttscore;
} else return ttscore; // exact score
}
int hashindx = htindex;
int hashlock = lock;
long poscnt = posed;
int besti=0,j,l,sc;
int v,val;
score = LOSS;
for (i = 0; i < nav; i++) {
val = history[side][height[av[l = i]]];
for (j = i+1; j < nav; j++) {
v = history[side][height[av[j]]];
if (v > val) {
val = v; l = j;
}
}
for (j = av[l]; l>i; l--)
av[l] = av[l-1];
makemove(av[i] = j);
sc = LOSSWIN-ab(LOSSWIN-beta,LOSSWIN-alpha);
backmove();
if (sc > score) {
besti = i;
if ((score=sc) > alpha && nplies >= BOOKPLY && (alpha=sc) >= beta) {
if (score == DRAW && i < nav-1)
score = DRAWWIN;
if (besti > 0) {
for (i = 0; i < besti; i++)
history[side][height[av[i]]]--; // punish worse
history[side][height[av[besti]]] += besti;
}
break;
}
}
}
if (score == LOSSWIN-ttscore) // combine < and >
score = DRAW;
poscnt = posed - poscnt;
int work;
for (work=0; (poscnt>>=1) != 0; work++) ; // work=log #positions stored
transtore(hashindx, hashlock, score, work);
if (nplies <= REPORTPLY) {
System.out.println(toString() + "#-<=>+".charAt(score) + work);
}
return score;
}
int solve()
{
int i, side = nplies & 1, otherside = side ^ 1;
nodes = 0L;
msecs = 1L;
if (haswon(color[otherside]))
return LOSS;
for (i = 0; i < WIDTH; i++)
if (islegalhaswon(color[side] | (1L << height[i])))
return WIN;
inithistory();
msecs = System.currentTimeMillis();
int score = ab(LOSS, WIN);
msecs = System.currentTimeMillis() + 1 - msecs; // prevent division by 0
return score;
}
public static void main(String argv[])
{
System.out.println("Fhourstones 3.1 (Java)");
System.out.println("Boardsize = " + WIDTH + "x" + HEIGHT);
System.out.println("Using " + TRANSIZE + " transposition table entries.");
SearchGame c4 = new SearchGame();
BufferedReader dis = new BufferedReader(new InputStreamReader(System.in));
DecimalFormat df = new DecimalFormat("######.###");
for (;;) {
String line=null;
try {
line = dis.readLine();
} catch (IOException e) {
System.out.println(e);
System.exit(0);
}
if (line == null)
break;
c4.reset();
for (int i=0; i < line.length(); i++)
c4.makemove(line.charAt(i) - '1');
System.out.println("\nSolving " + c4.nplies + "-ply position after "
+ c4.toString() + " . . .");
c4.emptyTT();
int result = c4.solve();
long poscnt = c4.posed;
int work;
for (work=0; (poscnt>>=1) != 0; work++) ; //work = log #transpositions
System.out.println("score = " + result + " (" +
"#-<=>+".charAt(result) + ") work = " + work);
System.out.println("" + c4.nodes + " pos / " + c4.msecs +
" msec = " + df.format((double)c4.nodes/c4.msecs) + " Kpos/sec");
System.out.println(c4.htstat());
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1