justinmathews87
asked on
How do I compile this source code...?
Could someone tell me how to compile this code in steps in jcreator. Since when I copy paste this into the jcreator window. I get an error when trying to run it...
"Exception in thread main". Something like that...New to java. Any help will be appreciated.
/*simplechess.java: a very simple chess playing applet.
made by Sieuwert van Otterloo, 1999.
smotterl@cs.uu.nl
Edited for Java 1.3 by Yves DebilloÎz
*/
import java.awt.*;
class chessboard
{
final static int OUT=8888,VOID=-1,PAWN=2,
ROOK=6,KNIGHT=8,BISSHOP=10 ,
QUEEN=12,KING=14,FRESHKING =114,FRESH ROOK=106;
int A[];
/*The core of a chessboard is the array A. A consists of 144 integers.
64 of them are a field of a chessboard, the rest have the value OUT. For the
numbering: see the image elsewhere.
A field can be empty: It then has the value VOID.
If a field contains a white pawn, it has the value PAWN+WHITE.
If it has a black knight, it's value is KNIGHT+BLACK. A FRESHKING
is displayed as a king, moves like a king, but has as special property
that it never moved, and that means it can castle. A KING cannot castle,
because it has moved. The same counts for the ROOK.*/
final static int ENPASSANT=3,CASTLE=5,CAAST LE=7;
/*Most moves are defined by their first and last field. However,
when a pawn reaches the last line, it can change into a rook, queen,
knight or bisshop. These are different moves, with the same from and
to field. Therefor a move as an extra attribute, a modifyer. It can be
zero by default, or KNIGHT, BISSHOP, ROOK, QUEEN by promotion.
Other values are ENPASSANT, CASTLE by castling with the A rook, or
CASTLE when castling with the H rook (long castling).*/
final static int WHITE=0,BLACK=1;
int oldmove[];
int undoinf[];
static int oldmovesize=64,maxlistsize =80;
int moves;
int status;
final static int CHECKMATE=0,CHECK=1,DRAW=2 ,OPEN=3;
chessview V;
final static int[] knightjump={-10,10,-14,14, -23,23,-25 ,25};
final static int[] kingjump={-1,1,-13,-12,-11 ,13,12,11} ;
final static int[] bisshopdir={13,-13,11,-11} ;
final static int[] rookdir={1,-1,12,-12};
final static int NULLMOVE=0;
/*
NOTES: a rook/king is fresh if it didn't move yet. Only
fresh pieces may castle.
ENPASSANT=3,CASTLE=5,CAAST LE=7 are different from any piece,
and can be used as newpieces in a move to indicate a special move.
(-1%2)=-1. [used for VOID in getside().]
*/
chessboard()
{
A=new int[144];
for(int i=0;i<144;i++)
A[i]=OUT;
setup();
oldmove= new int[oldmovesize];
undoinf= new int[oldmovesize];
}
void setview(chessview aview) {V=aview;}
chessboard(chessboard c)
//clones a chessboard. only the view is not cloned, because
//two chessboards cannot have the same view.
{
A=new int[144];
for(int i=0;i<144;i++)
A[i]=c.A[i];
oldmove= new int[oldmovesize];
undoinf= new int[oldmovesize];
for(int i=0;i<oldmovesize;i++)
{ oldmove[i]=c.oldmove[i];
undoinf[i]=c.undoinf[i];
}
moves=c.moves;
status=c.status;
}
void setup()
//brings the board in opening position
{
for(int x=2;x<10;x++)
{
for(int j=4;j<8;j++)
A[x+12*j]=VOID;
int[] line={FRESHROOK,KNIGHT,BIS SHOP,QUEEN ,
FRESHKING,BISSHOP,KNIGHT,F RESHROOK};
A[x+24]=line[x-2]+WHITE;
A[x+12*9]=line[x-2]+BLACK;
A[x+36]=PAWN+WHITE;
A[x+8*12]=PAWN+BLACK;
}
moves=0;
status=OPEN;
if(V!=null)
V.repaint();
}
void reset()
{
moves=0;
if(check(getside())) status=CHECK;
else status=OPEN;
if(V!=null)
V.repaint();
}
int getside() {return moves%2;}
/*The side that can move*/
int getking(int color)
/*the position of the king of that side. returns a field [0,143] or -1.*/
{
int value1=KING+color;
int value2=FRESHKING+color;
for(int i=0;i<144;i++)
if(A[i]==value1||A[i]==val ue2)
return i;
return -1;//should never happen.
}
boolean attack(int f,int side)
/*is field f attacked by side?*/
{
int x,i;
for(i=0;i<8;i++)
{x=f+knightjump[i];
if(inboard(x)&&getpiece(x) ==KNIGHT&& getside(x) ==side)
return true;
x=f+kingjump[i];
if(inboard(x)&&getpiece(x) ==KING&&ge tside(x)== side)
return true;
}
for(int d=0;d<4;d++)
{
x=f;
for(i=0;i<7;i++)
{
x+=rookdir[d];
if(!inboard(x))
break;
if(getside(x)!=VOID)
{
int p=getpiece(x);
if(getside(x)==side&&(p==R OOK||p==QU EEN))
return true;
else break;
}
}
x=f;
for(i=0;i<7;i++)
{
x+=bisshopdir[d];
if(!inboard(x))
break;
if(getside(x)!=VOID)
{
int p=getpiece(x);
if(getside(x)==side&&(p==B ISSHOP||p= =QUEEN))
return true;
else break;
}
}
}
int sign=(side==WHITE)? -1:1;
x=f+sign*11;
for(i=0;i<2;i++)
{if(inboard(x)&&getpiece(x )==PAWN&&g etside(x)= =side)
return true;
x=f+sign*13;
}
/*enpassant is ignored.*/
return false;
}
/*A move could be seen as an object:
class move
{int from;
int to;
int newpiece;
}
However, to keep speed we pack these three int in
one with the following methods:
*/
//packing:
static int newmove(int from,int to){return from+144*to;}
static int newmove(int from,int to, int newpiece)
{return from+144*(to+144*newpiece) ;}
//unpacking:
static int movefrom(int move) {return move%144;}
static int moveto(int move) {return (move/144)%144;}
static int movenewpiece(int move){return move/(144*144);}
boolean inboard(int f)
//is a field inside the board?
{
if(f<0||f>=144)
return false;
return A[f]!=OUT;
}
int getside(int field)
{
if(!inboard(field))
return WHITE;
return A[field]%2;
}
/*getside returns BLACK,WHITE or VOID.*/
int getpiece(int field) {return A[field]%100-A[field]%2;}
boolean getfresh(int field) {return A[field]>100;}
/*methods to do and undo moves.*/
void visualdomove(int move)
/*visual domove does the move, repaints the chessview, and sets the status
correctly. domove just does the move. During calculations, domove is used
because it is fast. Same for visualundomove.*/
{domove(move);
int[] movelist=listofmoves();
if(getlength(movelist)>0)
{
if(check(getside())) status=CHECK;
else status=OPEN;
}
else
{ if(check(getside())) status=CHECKMATE;
else status=DRAW;
}
if(V!=null)
V.repaint();
}
void visualundomove()
{undomove();
if(check(getside())) status=CHECK;
else status=OPEN;
if(V!=null)
V.repaint();
}
/*store and retrieve undo information.*/
/*Again we store both the captured piece v and the boolean
f in one integer.*/
void storemove(int m,int v,boolean f)
{ oldmove[moves%oldmovesize] =m;
if(f) undoinf[moves%oldmovesize] =v+8888;
else undoinf[moves%oldmovesize] =v;
}
int getstoredm(int m) {return oldmove[m%oldmovesize];}
int getstoredvictim()
/*Get the piece captured in the former move.*/
{int value=undoinf[moves%oldmov esize];
if(value<8000) return value;
return value-8888;
}
boolean getstoredfresh() {return (undoinf[moves%oldmovesize ]>8000);}
void domove(int m)
{
if(m==NULLMOVE)
{ storemove(m,VOID,false);
moves++;
return;
}
int from=movefrom(m);
int to=moveto(m);
int newpiece=movenewpiece(m);
boolean fresh=false;
if(A[from]>100)
{ fresh=true;
A[from]=A[from]-100;
}
int victim=A[to];
A[to]=A[from];
A[from]=VOID;
if(newpiece==ENPASSANT)
{//pawn moves diagonal to empty field: enpassant
A[to%12+12*(from/12)]=VOID ;//remove a pawn;
}
else if(newpiece==CASTLE)
{A[from-from%12+9]=VOID;
A[from-from%12+7]=ROOK+get side();
}
else if(newpiece==CAASTLE)
{A[from-from%12+2]=VOID;
A[from-from%12+5]=ROOK+get side();
}
else if(newpiece!=0)
A[to]=newpiece+getside();
storemove(m,victim,fresh);
moves++;
}
void undomove()
{
if(moves==0)
return;
moves--;
int m=getstoredm(moves);
if(m==NULLMOVE)
return;
int from=movefrom(m);
int to=moveto(m);
int newpiece=movenewpiece(m);
A[from]=A[to];
A[to]=getstoredvictim();
if(getstoredfresh()) A[from]+=100;
if(newpiece==ENPASSANT)
A[to%12+12*(from/12)]=PAWN +(1-getsid e());
else if(newpiece==CASTLE)
{A[from-from%12+7]=VOID;
A[from-from%12+9]=FRESHROO K+getside( );
}
else if(newpiece==CAASTLE)
{A[from-from%12+5]=VOID;
A[from-from%12+2]=FRESHROO K+getside( );
}
else if(newpiece!=0)
{
A[from]=PAWN+getside();
}
}
/*Methods for a list of moves.*/
/*A list is a special kind of array: the first element a[0]
is the number of stored items, a[1],a[2],... contain the items.
Adding is faster this way: we do not have to search the first empty
spot. The constant maxlistsize is the maximum size of the list. It must
be chosen large enough.*/
static int[] newlist()
{
int[] L=new int[maxlistsize+1];//maxsi ze
L[0]=0;
return L;
}
static int getlength(int[] L) {return L[0];}
static void add(int[] L,int i)
{
if(L[0]>=maxlistsize)
System.out.println("list overflow, raise maxlistsize.");
L[0]++;
L[L[0]]=i;
//System.out.println("add "+movefrom(i)+" "+moveto(i));
}
static void delete(int[] L,int index)
{
L[index]=L[L[0]];
L[0]--;
}
static void promotionadd(int[] l,int from,int to)
/*Add four pawn promotion moves.*/
{
int[] choice={QUEEN,KNIGHT,ROOK, BISSHOP};
for(int i=0;i<4;i++)
add(l,newmove(from,to,choi ce[i]));
}
/*The add*moves: add the moves for sch a * piece of side
standing on f.*/
void addpawnmoves(int[] list,int side,int f)
{int forward,firstline,lastline ;
if(side==WHITE)
{forward=12;
firstline=3;
lastline=8;
}
else
{forward=-12;
firstline=8;
lastline=3;
}
if(f/12==lastline)
{ if(getside(f+forward)==VOI D)
promotionadd(list,f,f+forw ard);
if(inboard(f+forward+1)&&g etside(f+f orward+1)= =1-side)
promotionadd(list,f,f+forw ard+1);
if(inboard(f+forward-1)&&g etside(f+f orward-1)= =1-side)
promotionadd(list,f,f+forw ard-1);
return;
}
if(getside(f+forward)==VOI D)
{add(list,newmove(f,f+forw ard));
if(f/12==firstline&&getsid e(f+2*forw ard)==VOID )
add(list,newmove(f,f+2*for ward));
}
if(inboard(f+forward+1)&&g etside(f+f orward+1)= =1-side)
add(list,newmove(f,f+forwa rd+1));
if(inboard(f+forward-1)&&g etside(f+f orward-1)= =1-side)
add(list,newmove(f,f+forwa rd-1));
}
void addjumpmoves(int[] list,int side,int f,int[] jump)
/*addknightmoves()=addjump moves(,,,k nightvecto r)
addkingmoves()=addjumpmove s(,,,kingv ector)
*/
{
for(int i=0;i<8;i++)
if(inboard(f+jump[i])&&get side(f+jum p[i])!=sid e)
add(list,newmove(f,f+jump[ i]));
}
void addslidemoves(int[] list,int side,int f,int dir)
/*addrookmoves= for each rookdir[] addslidemoves.
addbisshopmoves= for each bisshopdir[] addslidemoves.
addqueenmoves= for each rookdir and bisshopdir addslidemoves.*/
{
int x=f;
for(int i=0;i<7;i++)
{ x+=dir;
if(!inboard(x)||getside(x) ==side)
break;
add(list,newmove(f,x));
if(getside(x)==1-side)
break;
}
}
boolean check(int side)
//side is in check
{
int f=getking(side);
if(f==-1)
return false;
return attack(f,1-side);
}
boolean illmovedone()
/*for computerplayer, to filter ill pseudomoves.
This method checks wether the former player puts itself in check
*/
{return check(1-getside());}
int[] listofmoves()
/*return a list with all possible moves. It creates a list of
pseudomoves and filters out the illegal ones.*/
{int[] list=listofpseudomoves();
boolean c;
int m=1;
while(m<=list[0])
{domove(list[m]);
c=illmovedone();
undomove();
if(c)
delete(list,m);
else
m++;
}
return list;
}
int[] listofpseudomoves()
/*create all moves that are possible, without looking at
selfcheck. */
{
int[] list=newlist();
if(status!=OPEN&&status!=C HECK)
return list;
int side=getside();
for(int i=0;i<144;i++)
if(inboard(i)&&getside(i)= =getside() )
{switch(getpiece(i))
{case PAWN:addpawnmoves(list,sid e,i);break ;
case KNIGHT:addjumpmoves(list,s ide,i,knig htjump);br eak;
case KING:addjumpmoves(list,sid e,i,kingju mp);break;
case ROOK:
for(int d=0;d<4;d++) addslidemoves(list,side,i, rookdir[d] );
break;
case BISSHOP:
for(int d=0;d<4;d++) addslidemoves(list,side,i, bisshopdir [d]);
break;
case QUEEN:
for(int d=0;d<4;d++)
{addslidemoves(list,side,i ,rookdir[d ]);
addslidemoves(list,side,i, bisshopdir [d]);
}
break;
}
}
//castling:
int row=(side==WHITE)?2*12:9*1 2;
if(getfresh(row+6))//the king hasn't left it's place
{if( getfresh(row+2)
&&getside(row+3)==VOID
&&getside(row+4)==VOID
&&getside(row+5)==VOID
&&!attack(row+4,1-side)
&&!attack(row+5,1-side)
&&!attack(row+6,1-side))
add(list,newmove(row+6,row +4,CAASTLE ));
if( getfresh(row+9)
&&getside(row+7)==VOID
&&getside(row+8)==VOID
&&!attack(row+6,1-side)
&&!attack(row+7,1-side)
&&!attack(row+8,1-side))
add(list,newmove(row+6,row +8,CASTLE) );
}
if(moves!=0)
{//try enpassant
int forward= (side==WHITE)?12:-12;
int m=getstoredm(moves-1);
int to=moveto(m);
int from=movefrom(m);
if(getpiece(to)==PAWN&&fro m-to==2*fo rward)
{if(inboard(to+1)&&getside (to+1)==si de
&&getpiece(to+1)==PAWN&&ge tside(to+f orward)==V OID)
add(list,newmove(to+1,to+f orward,ENP ASSANT));
if(inboard(to-1)&&getside( to-1)==sid e
&&getpiece(to-1)==PAWN&&ge tside(to+f orward)==V OID)
add(list,newmove(to-1,to+f orward,ENP ASSANT));
}
}
return list;
}
}
class superdiagram extends Canvas
/*this is a superclass for 2 kinds of diagrams
It can be magnified by changing scale, and knows to draw pieces.
*/
{
int scale, ymax;
Color backColor[];
Color darkpieceColor[];// the colors used to paint the pieces
Color lightpieceColor[];
superdiagram()
{
backColor=new Color[2];
backColor[0]=new Color(100,128,100);//dark green
backColor[1]=new Color(128,160,128);//light green
darkpieceColor=new Color[2];
darkpieceColor[0]=new Color(255,255,255);//for WHITE
darkpieceColor[1]=new Color(0,0,128);//for BLACK
lightpieceColor=new Color[2];
lightpieceColor[0]=new Color(200,200,64);//for WHITE
lightpieceColor[1]=new Color(84,84,255);//for BLACK
}
void bar(int x,int y, int hSize, int vSize,Color c,Graphics g)
{//draw a bar (filled rectangle).
g.setColor(c);
g.fillRect( x*scale, ymax-(y+vSize)*scale,
hSize*scale,vSize*scale);
}
void paintfield(int fx,int fy, int piece,int side ,Graphics g)
/*paint a field. Size: 16*scale pixels.*/
{
int x=fx*16;
int y=fy*16;
bar(x,y,16,16,backColor[(f x+fy)%2],g );
if(side==chessboard.VOID) return;
switch(piece)
{case chessboard.PAWN:
bar(x+4,y+4,8,8,darkpieceC olor[side] ,g);
break;
case chessboard.ROOK:
bar(x+1,y+4,14,3,darkpiece Color[side ],g);
bar(x+4,y+1,3,14,lightpiec eColor[sid e],g);
bar(x+1,y+9,14,3,darkpiece Color[side ],g);
bar(x+9,y+1,3,3,lightpiece Color[side ],g);
bar(x+9,y+7,3,8,lightpiece Color[side ],g);
break;
case chessboard.KNIGHT:
bar(x+7,y+1,2,5,darkpieceC olor[side] ,g);
bar(x+4,y+6,8,4,darkpieceC olor[side] ,g);
bar(x+10,y+10,4,2,lightpie ceColor[si de],g);
break;
case chessboard.BISSHOP:
bar(x+3,y+1,10,4,darkpiece Color[side ],g);
bar(x+7,y+4,2,8,lightpiece Color[side ],g);
break;
case chessboard.KING:
bar(x+6,y+1,4,13,darkpiece Color[side ],g);
bar(x+3,y+8,10,3,lightpiec eColor[sid e],g);
break;
case chessboard.QUEEN:
bar(x+3,y+1,10,4,darkpiece Color[side ],g);
bar(x+7,y+5,2,6,lightpiece Color[side ],g);
bar(x+3,y+4,2,5,lightpiece Color[side ],g);
bar(x+11,y+4,2,5,lightpiec eColor[sid e],g);
break;
}
}
public void update(Graphics g){paint(g);}
}
class pieceselector extends superdiagram
/*a pieceselector displays all pieces, and when the user clicks a
piece the pieceselector notifies the applet*/
{int[] piece;
int[] side;
simplechess applet;
pieceselector(simplechess ds, int scalingfactor)
{
side= new int[14];
piece=new int[14];
applet=ds;
for(int j=0;j<12;j++)
side[j]=j%2;
for(int i=0;i<2;i++)
{
piece[i]=chessboard.PAWN;
piece[2+i]=chessboard.ROOK ;
piece[4+i]=chessboard.KNIG HT;
piece[6+i]=chessboard.BISS HOP;
piece[8+i]=chessboard.QUEE N;
piece[10+i]=chessboard.KIN G;
piece[12+i]=0;
side[12+i]=chessboard.VOID ;
}
scale(scalingfactor);
}
public boolean mouseDown(Event ev,int x,int y)
{
if(x<0||x>=32*scale||y<0|| y>=ymax)
return true;
x=x/(16*scale);
y=(ymax-y-1)/(16*scale);
applet.piececlicked(side[2 *y+x],piec e[2*y+x]);
return true;
}
public void paint(Graphics g)
{
for(int f=0;f<14;f++)
paintfield(f%2,f/2,piece[f ],side[f], g);
}
public void scale(int s)
{
if(s<1||s>5) s=2;
scale=s;
ymax=7*16*scale;
resize(32*scale,ymax);
}
}
class chessview extends superdiagram
/*can display a chessboard, and when a field is clicked, the applet
is notified.*/
{
chessboard board;
simplechess applet;
chessview(simplechess ds,chessboard b, int s)
{
applet=ds;
board=b;
scale(s);
}
public void scale(int s)
{if(s<1||s>5)
s=2;
scale=s;
ymax=8*16*scale;
resize(ymax,ymax+15);
}
public boolean mouseDown(Event ev,int x,int y)
{
if(x<0||x>=ymax||y<0||y>=y max)
return true;
x=x/(16*scale);
y=(ymax-y-1)/(16*scale);
applet.fieldclicked(12*(y+ 2)+x+2);
return true;
}
public void paint(Graphics g)
{int f;
for(int x=0;x<8;x++)
for(int y=0;y<8;y++)
paintfield(x,y, board.getpiece(x+2+12*(y+2 )),
board.getside(x+2+12*(y+2) ),g);
g.setColor(Color.black);
g.fillRect(0,ymax,ymax,15) ;
g.setColor(Color.white);
String s;
if(board.getside()==board. WHITE)
s="White to move.";
else
s="Black to move.";
if(board.status==board.CHE CKMATE)
s+=" Checkmate";
else if(board.status==board.CHE CK)
s+=" Check!";
else if(board.status==board.DRA W)
s+=" Game ends in draw.";
g.drawString(s,2,ymax+12);
}
}
public class simplechess extends java.applet.Applet
/*The applet displays a board and buttons. It listens
to the buttons and mouseclicks.*/
{
chessboard B;
chessview Bview;
pieceselector selector;
Button newgame,edit,undo;
int state;
final static int USERGRABPIECE=0,USERRELEAS EPIECE=1,
USERSELECTPROMOTION=2,PCMO VING=3,
EDITING=4,NOTHINGTODO=5;
int selectedfield1,selectedfie ld2;
Label message;
int[] list;
mover Sieuwert;
int pieceinhand;
public void init()
{
B=new chessboard();
Bview=new chessview(this,B,2);
B.setview(Bview);
selector=new pieceselector(this,2);
setLayout(new BorderLayout());
Panel buttonpanel=new Panel();//panel to keep buttons together
buttonpanel.setLayout(new GridLayout(1,3));
buttonpanel.add(newgame=ne w Button("new game"));
buttonpanel.add(edit=new Button("edit"));
buttonpanel.add(undo=new Button("undo"));
Panel controlpanel=new Panel();
controlpanel.setLayout(new GridLayout(2,1));
controlpanel.add(buttonpan el);
controlpanel.add(message=n ew Label());
Panel diagrampanel=new Panel();
diagrampanel.setLayout(new BorderLayout());
diagrampanel.add("West",Bv iew);
diagrampanel.add("East",se lector);
add("North",diagrampanel);
add("South", controlpanel);
state=USERGRABPIECE;
setmessage("welcome");
Sieuwert=new mover(B,this);
pieceinhand=B.PAWN+B.WHITE ;
}
void setmessage(String s)
/*The string s will be shown to the user.*/
{message.setText(s);}
int seek(int[] L,int from,int to)
/*seeks a move with that from and to in list. If not: -1*/
{
for(int i=L[0];i>0;i--)
if(chessboard.movefrom(L[i ])==from&&
chessboard.moveto(L[i])==t o)
return i;
return -1;
}
int seek(int[] L,int from,int to,int newpiece)
/*seeks the move with that from, that to and that newpiece.*/
{
for(int i=L[0];i>0;i--)
if(chessboard.movefrom(L[i ])==from&&
chessboard.moveto(L[i])==t o&&
chessboard.movenewpiece(L[ i])==newpi ece)
return i;
return -1;
}
public void fieldclicked(int f)
/*If the computer is thinking, we do nothing.
Else we try to do the user's move, and a computermove.*/
{
synchronized(this)
{if(state==PCMOVING) return;}
switch(state)
{case USERGRABPIECE:
if(B.getside(f)!=B.getside ())
{setmessage("You can't move that piece.");}
else
{selectedfield1=f;state=US ERRELEASEP IECE;
setmessage("You got piece "+f);
}
break;
case USERRELEASEPIECE:
{
if(list==null)
list=B.listofmoves();
int m=seek(list,selectedfield1 ,f);
if(m==-1)
{ setmessage("Your piece cannot go there.");
state=USERGRABPIECE;
break;
}
int mod=chessboard.movenewpiec e(list[m]) ;
if(mod==chessboard.QUEEN|| mod==chess board.ROOK ||
mod==chessboard.KNIGHT||mo d==chessbo ard.BISSHO P)
{ setmessage("Your pawn can promote to another piece.");
selectedfield2=f;
state=USERSELECTPROMOTION;
break;
}
else
{ B.visualdomove(list[m]);
list=null;
computermove(Sieuwert);
}
}
break;
case EDITING:
B.A[f]=pieceinhand;
Bview.repaint();
break;
case NOTHINGTODO:
setmessage("Press newgame for a rematch.");
break;
}
}
void piececlicked(int side,int piece)
{
if(state==USERSELECTPROMOT ION)
{
int index=seek(list,selectedfi eld1,selec tedfield2, piece);
if(index!=-1)
{B.visualdomove(list[index ]);
list=null;
computermove(Sieuwert);
}
}
else if(state==EDITING)
{
pieceinhand=side+piece;
}
}
void computermove(mover M)
{
if(B.status==B.CHECKMATE|| B.status== B.DRAW)
{
setmessage("Game over.");
state=NOTHINGTODO;
}
else
{
state=PCMOVING;
M.domove();
}
}
void catchamove(int m)
/*Some time after we ask the mover for a move,
he will call this method to give us his move. We will
do his move.*/
{
synchronized(this)
{
if(state==PCMOVING)
{B.visualdomove(m);
state=USERGRABPIECE;
}
}
}
void newgame()
{
B.setup();
if(state!=EDITING)
state=USERGRABPIECE;
}
void undo()
{
if(state!=EDITING)
{B.visualundomove();
setmessage("...");
}
}
void switchedit()
{
if(state==EDITING&&B.getki ng(B.WHITE )!=-1&&B.g etking(B.B LACK)!=-1)
{
B.reset();
setmessage("play.");
edit.setLabel("edit");
state=USERGRABPIECE;
}
else if(state==USERGRABPIECE)
{
setmessage("edit.");
edit.setLabel("play");
state=EDITING;
}
}
public boolean action(Event ev, Object O)
/*If a button was clicked, the browser calls this function.
If a computerplayer is thinking, we do nothing.
Else, we do the right action.
*/
{
synchronized(this)
{
if(state==PCMOVING)
return true;
else if(ev.target==newgame)
{newgame();}
else if(ev.target==undo)
{undo();}
else if(ev.target==edit)
{switchedit();}
}
return true;
}
}
class mover extends Thread
/*mover is a thread, because that makes it possible to return the method
do a move before doing the move. this is more convenient for many browsers:
the mouseclicks that ask for moves are returned fast, so the user can click
other buttons while the computer is calculating.
the result is given to the applet by applet.catchamove();
*/
{
chessboard original; //the chessboard to do moves on
chessboard b; // a copy to do calculations on
static int minlevel=2,maxlevel=6; //the maximum searchdepth
simplechess applet;
final static int HIGH=65534, SUPERHIGH=65535, ABOVEALL=65536;
/*HIGH is the highest possible score. superhigh is
a impossible score, that will act as a bottom
to start searching. ABOVEALL is a score that can be returned if
it is found out that an ill move was done.*/
static int pawnscore[];//good places for pawns
int nodes;
mover(chessboard bb,simplechess l)
//make a mover
{
makepawntable();
original=bb;
applet=l;
start(); //get running.
}
static void makepawntable()
{
if(pawnscore!=null)
return;
pawnscore=new int[144];
for(int i=0;i<144;i++)
pawnscore[i]=100+5*((i-2)/ 12);
for(int i=0;i<12;i++)
{
pawnscore[96+i]=240;
pawnscore[84+i]=160;
}
pawnscore[66]=pawnscore[65 ]=pawnscor e[78]=pawn score[77]= 180;
}
/*this trick intends to do the calculating in a second thread, so the
main thread can handle other clicks. This is necessary in UNIX, because
otherwise the applet would block all other applications from reading the mouse. In
Netscape, this trick is unstable: NN can crash. In internet explorer, it
works.*/
public void run()
/*the mover will get into sleep,
when woke up do a move, sleep,move,etc*/
{while(true)
{ this.suspend();
domove_2();
}
}
void domove()
//this wakes up the mover. It will do a move
{resume();}
void domove_2()
/*does a move on original. It tries all moves it can do, and
then does the move that gave the highest prognosis.*/
{
nodes=0;
b=new chessboard(original); //make a copy for calculations
int[] list=b.listofmoves();
int bestmoveindex=-1;
int alpha=-SUPERHIGH;
for(int c=1;c<=list[0];c++)
{
b.domove(list[c]);
int s=-fullsearch(-SUPERHIGH,- alpha,1);
b.undomove();
if(s>alpha)
{alpha=s;
bestmoveindex=c;
}
}
applet.catchamove(list[bes tmoveindex ]);
System.out.println("nodes "+nodes);
}
void swap(int[] l,int[] v, int i,int j)
/*swap the elements i and j in both l and v.*/
{
int dummy;
dummy=l[i];
l[i]=l[j];
l[j]=dummy;
dummy=v[i];
v[i]=v[j];
v[j]=dummy;
}
void sort(int[] l,int[] v) {quicksort(l,v,1,l[0]);}
/*sorts v, keeping the corresponding elements l[i]
and v[i] together. highest v first.*/
void quicksort(int[] l,int[] v,int p,int r)
//sort the interval [p,r] of v, like above
{
if(p<r)
{
int q=partition(l,v,p,r);
quicksort(l,v,p,q);
quicksort(l,v,q+1,r);
}
}
int partition(int[] l,int[] v,int p,int r)
/*split v (and l) in a high and low part.*/
{int x=v[p];
int i=p-1;
int j=r+1;
while(true)
{
do j--; while(!(v[j]>=x));
do i++; while(!(v[i]<=x));
if(i<j)
swap(l,v,i,j);
else
return j;
}
}
int[] estimates(int[] l)
/*returns the estimated benefits of a move.*/
{
int[] v=new int[l[0]+1];
int np;
v[0]=l[0];
for(int i=1;i<=l[0];i++)
{
if(l[i]==b.NULLMOVE)
v[i]=0;
else
{
np=b.movenewpiece(l[i]);
if(np==0)
v[i]=value(b.getpiece(b.mo veto(l[i]) ));
if(np==b.ENPASSANT)
v[i]=110;
else if(np==b.CASTLE)
v[i]=20;
else if(np==b.CAASTLE)
v[i]=16;
else v[i]=value(np);
}
}
return v;
}
int[] makefulllist()
/*make a list of moves to search.*/
{
int[] l=b.listofmoves();
int[] v=estimates(l);
sort(l,v);
return l;
}
int fullsearch(int alpha, int beta, int level)
/*Try to give a prognosis about how good the situation is for
the player to move on the chessboard b. It does that
by looking at the status(if the game is result),
by doing any move and calling prognosis,
by calling estimate (if it has called itself often enough)*/
{
if(level>=minlevel)
return justattacksearch(alpha,bet a,level);
nodes++;
/*try all moves and return the estimate
we get when doing the best move*/
int[] list=makefulllist();
if(list[0]==0)//no moves
{if(b.check(b.getside()))
return -HIGH;//we lost.
else return 0;//stalemate
}
for(int c=1;c<=list[0];c++)
{
b.domove(list[c]);
int s=-fullsearch(-beta,-alpha ,level+1);
b.undomove();
if(s>beta) return s;
if(s>alpha) alpha=s;
}
return alpha;
}
int[] makejustattacklist()
/*make a list for searching only attack moves.*/
{
int[] l=b.listofpseudomoves();
int[] v=estimates(l);
int i=1;
while(i<=l[0])
if(v[i]<50)
b.delete(l,i);
else
i++;
b.add(l,b.NULLMOVE);
return l;
}
int justattacksearch(int alpha, int beta, int level)
/*Try to give a prognosis about how good the situation is for
the player to move on the chessboard b. It does that
by looking at the status(if the game is result),
by doing any move and calling prognosis,
by calling estimate (if it has called itself often enough)*/
{
nodes++;
if(level>=maxlevel)
return justbacksearch(alpha,beta) ;
/*try all moves and return the estimate
we get when doing the best move*/
int[] list=makejustattacklist();
for(int c=1;c<=list[0];c++)
{
b.domove(list[c]);
int s=-justattacksearch(-beta, -alpha,lev el+1);
b.undomove();
if(s>beta) return s;
if(s>alpha) alpha=s;
}
return alpha;
}
int value(int piece)
/*The value of a piece.*/
{
switch(piece)
{
case 2: return 105;
case 8: return 300;
case 6: return 450;
case 12: return 850;
case 10:return 320;
case 14: return 3200;
case -1: return 0;
}
return 0;
}
int justbacksearch(int alpha,int beta)
//try to hit back, or use basicscore
{
if(b.illmovedone())
return ABOVEALL;
int to=b.moveto(b.getstoredm(b .moves-1)) ;
int s=basicscore();
if(s>beta) return s;
if(s>alpha) alpha=s;
if(b.attack(to,b.getside() ))
{
int[] list=hitbacklist();
for(int c=1;c<=list[0];c++)
{
b.domove(list[c]);
s=-justbacksearch(-beta,-a lpha);
b.undomove();
if(s>beta) return s;
if(s>alpha) alpha=s;
}
}
return alpha;
}
int[] hitbacklist()
{
int[] l=b.listofpseudomoves();
int to=b.moveto(b.getstoredm(b .moves-1)) ;
int i=1;
while(i<=l[0])
if(b.moveto(l[i])!=to)
b.delete(l,i);
else
i++;
b.add(l,b.NULLMOVE);
return l;
}
int basicscore()
/*calculate a score, non recursively*/
{int score[]=new int[2];
int pside;
for(int x=24;x<120;x+=12)
for(int field=x+2;field<x+10;field ++)
{
pside=b.getside(field);
if(pside!=chessboard.VOID)
{
switch(b.getpiece(field))
{case chessboard.PAWN:
if(pside==chessboard.WHITE )
score[pside]+=pawnscore[fi eld];
else
score[pside]+=pawnscore[14 4-field];
//mirror the table to get the black values
if(b.A[field+12]==chessboa rd.PAWN+ps ide)
score[pside]-=20;//double pawn
break;
case chessboard.KNIGHT:
score[pside]+=295;
break;
case chessboard.BISSHOP:
score[pside]+=300;
break;
case chessboard.ROOK:
score[pside]+=450;
break;
case chessboard.QUEEN:
score[pside]+=850;
break;
case chessboard.KING:
score[pside]+=3200;
break;
}
}
}
int whiteresult=score[chessboa rd.WHITE]- score[ches sboard.BLA CK];
return (b.getside()==chessboard.W HITE)?whit eresult:-w hiteresult ;
}
}
"Exception in thread main". Something like that...New to java. Any help will be appreciated.
/*simplechess.java: a very simple chess playing applet.
made by Sieuwert van Otterloo, 1999.
smotterl@cs.uu.nl
Edited for Java 1.3 by Yves DebilloÎz
*/
import java.awt.*;
class chessboard
{
final static int OUT=8888,VOID=-1,PAWN=2,
ROOK=6,KNIGHT=8,BISSHOP=10
QUEEN=12,KING=14,FRESHKING
int A[];
/*The core of a chessboard is the array A. A consists of 144 integers.
64 of them are a field of a chessboard, the rest have the value OUT. For the
numbering: see the image elsewhere.
A field can be empty: It then has the value VOID.
If a field contains a white pawn, it has the value PAWN+WHITE.
If it has a black knight, it's value is KNIGHT+BLACK. A FRESHKING
is displayed as a king, moves like a king, but has as special property
that it never moved, and that means it can castle. A KING cannot castle,
because it has moved. The same counts for the ROOK.*/
final static int ENPASSANT=3,CASTLE=5,CAAST
/*Most moves are defined by their first and last field. However,
when a pawn reaches the last line, it can change into a rook, queen,
knight or bisshop. These are different moves, with the same from and
to field. Therefor a move as an extra attribute, a modifyer. It can be
zero by default, or KNIGHT, BISSHOP, ROOK, QUEEN by promotion.
Other values are ENPASSANT, CASTLE by castling with the A rook, or
CASTLE when castling with the H rook (long castling).*/
final static int WHITE=0,BLACK=1;
int oldmove[];
int undoinf[];
static int oldmovesize=64,maxlistsize
int moves;
int status;
final static int CHECKMATE=0,CHECK=1,DRAW=2
chessview V;
final static int[] knightjump={-10,10,-14,14,
final static int[] kingjump={-1,1,-13,-12,-11
final static int[] bisshopdir={13,-13,11,-11}
final static int[] rookdir={1,-1,12,-12};
final static int NULLMOVE=0;
/*
NOTES: a rook/king is fresh if it didn't move yet. Only
fresh pieces may castle.
ENPASSANT=3,CASTLE=5,CAAST
and can be used as newpieces in a move to indicate a special move.
(-1%2)=-1. [used for VOID in getside().]
*/
chessboard()
{
A=new int[144];
for(int i=0;i<144;i++)
A[i]=OUT;
setup();
oldmove= new int[oldmovesize];
undoinf= new int[oldmovesize];
}
void setview(chessview aview) {V=aview;}
chessboard(chessboard c)
//clones a chessboard. only the view is not cloned, because
//two chessboards cannot have the same view.
{
A=new int[144];
for(int i=0;i<144;i++)
A[i]=c.A[i];
oldmove= new int[oldmovesize];
undoinf= new int[oldmovesize];
for(int i=0;i<oldmovesize;i++)
{ oldmove[i]=c.oldmove[i];
undoinf[i]=c.undoinf[i];
}
moves=c.moves;
status=c.status;
}
void setup()
//brings the board in opening position
{
for(int x=2;x<10;x++)
{
for(int j=4;j<8;j++)
A[x+12*j]=VOID;
int[] line={FRESHROOK,KNIGHT,BIS
FRESHKING,BISSHOP,KNIGHT,F
A[x+24]=line[x-2]+WHITE;
A[x+12*9]=line[x-2]+BLACK;
A[x+36]=PAWN+WHITE;
A[x+8*12]=PAWN+BLACK;
}
moves=0;
status=OPEN;
if(V!=null)
V.repaint();
}
void reset()
{
moves=0;
if(check(getside())) status=CHECK;
else status=OPEN;
if(V!=null)
V.repaint();
}
int getside() {return moves%2;}
/*The side that can move*/
int getking(int color)
/*the position of the king of that side. returns a field [0,143] or -1.*/
{
int value1=KING+color;
int value2=FRESHKING+color;
for(int i=0;i<144;i++)
if(A[i]==value1||A[i]==val
return i;
return -1;//should never happen.
}
boolean attack(int f,int side)
/*is field f attacked by side?*/
{
int x,i;
for(i=0;i<8;i++)
{x=f+knightjump[i];
if(inboard(x)&&getpiece(x)
return true;
x=f+kingjump[i];
if(inboard(x)&&getpiece(x)
return true;
}
for(int d=0;d<4;d++)
{
x=f;
for(i=0;i<7;i++)
{
x+=rookdir[d];
if(!inboard(x))
break;
if(getside(x)!=VOID)
{
int p=getpiece(x);
if(getside(x)==side&&(p==R
return true;
else break;
}
}
x=f;
for(i=0;i<7;i++)
{
x+=bisshopdir[d];
if(!inboard(x))
break;
if(getside(x)!=VOID)
{
int p=getpiece(x);
if(getside(x)==side&&(p==B
return true;
else break;
}
}
}
int sign=(side==WHITE)? -1:1;
x=f+sign*11;
for(i=0;i<2;i++)
{if(inboard(x)&&getpiece(x
return true;
x=f+sign*13;
}
/*enpassant is ignored.*/
return false;
}
/*A move could be seen as an object:
class move
{int from;
int to;
int newpiece;
}
However, to keep speed we pack these three int in
one with the following methods:
*/
//packing:
static int newmove(int from,int to){return from+144*to;}
static int newmove(int from,int to, int newpiece)
{return from+144*(to+144*newpiece)
//unpacking:
static int movefrom(int move) {return move%144;}
static int moveto(int move) {return (move/144)%144;}
static int movenewpiece(int move){return move/(144*144);}
boolean inboard(int f)
//is a field inside the board?
{
if(f<0||f>=144)
return false;
return A[f]!=OUT;
}
int getside(int field)
{
if(!inboard(field))
return WHITE;
return A[field]%2;
}
/*getside returns BLACK,WHITE or VOID.*/
int getpiece(int field) {return A[field]%100-A[field]%2;}
boolean getfresh(int field) {return A[field]>100;}
/*methods to do and undo moves.*/
void visualdomove(int move)
/*visual domove does the move, repaints the chessview, and sets the status
correctly. domove just does the move. During calculations, domove is used
because it is fast. Same for visualundomove.*/
{domove(move);
int[] movelist=listofmoves();
if(getlength(movelist)>0)
{
if(check(getside())) status=CHECK;
else status=OPEN;
}
else
{ if(check(getside())) status=CHECKMATE;
else status=DRAW;
}
if(V!=null)
V.repaint();
}
void visualundomove()
{undomove();
if(check(getside())) status=CHECK;
else status=OPEN;
if(V!=null)
V.repaint();
}
/*store and retrieve undo information.*/
/*Again we store both the captured piece v and the boolean
f in one integer.*/
void storemove(int m,int v,boolean f)
{ oldmove[moves%oldmovesize]
if(f) undoinf[moves%oldmovesize]
else undoinf[moves%oldmovesize]
}
int getstoredm(int m) {return oldmove[m%oldmovesize];}
int getstoredvictim()
/*Get the piece captured in the former move.*/
{int value=undoinf[moves%oldmov
if(value<8000) return value;
return value-8888;
}
boolean getstoredfresh() {return (undoinf[moves%oldmovesize
void domove(int m)
{
if(m==NULLMOVE)
{ storemove(m,VOID,false);
moves++;
return;
}
int from=movefrom(m);
int to=moveto(m);
int newpiece=movenewpiece(m);
boolean fresh=false;
if(A[from]>100)
{ fresh=true;
A[from]=A[from]-100;
}
int victim=A[to];
A[to]=A[from];
A[from]=VOID;
if(newpiece==ENPASSANT)
{//pawn moves diagonal to empty field: enpassant
A[to%12+12*(from/12)]=VOID
}
else if(newpiece==CASTLE)
{A[from-from%12+9]=VOID;
A[from-from%12+7]=ROOK+get
}
else if(newpiece==CAASTLE)
{A[from-from%12+2]=VOID;
A[from-from%12+5]=ROOK+get
}
else if(newpiece!=0)
A[to]=newpiece+getside();
storemove(m,victim,fresh);
moves++;
}
void undomove()
{
if(moves==0)
return;
moves--;
int m=getstoredm(moves);
if(m==NULLMOVE)
return;
int from=movefrom(m);
int to=moveto(m);
int newpiece=movenewpiece(m);
A[from]=A[to];
A[to]=getstoredvictim();
if(getstoredfresh()) A[from]+=100;
if(newpiece==ENPASSANT)
A[to%12+12*(from/12)]=PAWN
else if(newpiece==CASTLE)
{A[from-from%12+7]=VOID;
A[from-from%12+9]=FRESHROO
}
else if(newpiece==CAASTLE)
{A[from-from%12+5]=VOID;
A[from-from%12+2]=FRESHROO
}
else if(newpiece!=0)
{
A[from]=PAWN+getside();
}
}
/*Methods for a list of moves.*/
/*A list is a special kind of array: the first element a[0]
is the number of stored items, a[1],a[2],... contain the items.
Adding is faster this way: we do not have to search the first empty
spot. The constant maxlistsize is the maximum size of the list. It must
be chosen large enough.*/
static int[] newlist()
{
int[] L=new int[maxlistsize+1];//maxsi
L[0]=0;
return L;
}
static int getlength(int[] L) {return L[0];}
static void add(int[] L,int i)
{
if(L[0]>=maxlistsize)
System.out.println("list overflow, raise maxlistsize.");
L[0]++;
L[L[0]]=i;
//System.out.println("add "+movefrom(i)+" "+moveto(i));
}
static void delete(int[] L,int index)
{
L[index]=L[L[0]];
L[0]--;
}
static void promotionadd(int[] l,int from,int to)
/*Add four pawn promotion moves.*/
{
int[] choice={QUEEN,KNIGHT,ROOK,
for(int i=0;i<4;i++)
add(l,newmove(from,to,choi
}
/*The add*moves: add the moves for sch a * piece of side
standing on f.*/
void addpawnmoves(int[] list,int side,int f)
{int forward,firstline,lastline
if(side==WHITE)
{forward=12;
firstline=3;
lastline=8;
}
else
{forward=-12;
firstline=8;
lastline=3;
}
if(f/12==lastline)
{ if(getside(f+forward)==VOI
promotionadd(list,f,f+forw
if(inboard(f+forward+1)&&g
promotionadd(list,f,f+forw
if(inboard(f+forward-1)&&g
promotionadd(list,f,f+forw
return;
}
if(getside(f+forward)==VOI
{add(list,newmove(f,f+forw
if(f/12==firstline&&getsid
add(list,newmove(f,f+2*for
}
if(inboard(f+forward+1)&&g
add(list,newmove(f,f+forwa
if(inboard(f+forward-1)&&g
add(list,newmove(f,f+forwa
}
void addjumpmoves(int[] list,int side,int f,int[] jump)
/*addknightmoves()=addjump
addkingmoves()=addjumpmove
*/
{
for(int i=0;i<8;i++)
if(inboard(f+jump[i])&&get
add(list,newmove(f,f+jump[
}
void addslidemoves(int[] list,int side,int f,int dir)
/*addrookmoves= for each rookdir[] addslidemoves.
addbisshopmoves= for each bisshopdir[] addslidemoves.
addqueenmoves= for each rookdir and bisshopdir addslidemoves.*/
{
int x=f;
for(int i=0;i<7;i++)
{ x+=dir;
if(!inboard(x)||getside(x)
break;
add(list,newmove(f,x));
if(getside(x)==1-side)
break;
}
}
boolean check(int side)
//side is in check
{
int f=getking(side);
if(f==-1)
return false;
return attack(f,1-side);
}
boolean illmovedone()
/*for computerplayer, to filter ill pseudomoves.
This method checks wether the former player puts itself in check
*/
{return check(1-getside());}
int[] listofmoves()
/*return a list with all possible moves. It creates a list of
pseudomoves and filters out the illegal ones.*/
{int[] list=listofpseudomoves();
boolean c;
int m=1;
while(m<=list[0])
{domove(list[m]);
c=illmovedone();
undomove();
if(c)
delete(list,m);
else
m++;
}
return list;
}
int[] listofpseudomoves()
/*create all moves that are possible, without looking at
selfcheck. */
{
int[] list=newlist();
if(status!=OPEN&&status!=C
return list;
int side=getside();
for(int i=0;i<144;i++)
if(inboard(i)&&getside(i)=
{switch(getpiece(i))
{case PAWN:addpawnmoves(list,sid
case KNIGHT:addjumpmoves(list,s
case KING:addjumpmoves(list,sid
case ROOK:
for(int d=0;d<4;d++) addslidemoves(list,side,i,
break;
case BISSHOP:
for(int d=0;d<4;d++) addslidemoves(list,side,i,
break;
case QUEEN:
for(int d=0;d<4;d++)
{addslidemoves(list,side,i
addslidemoves(list,side,i,
}
break;
}
}
//castling:
int row=(side==WHITE)?2*12:9*1
if(getfresh(row+6))//the king hasn't left it's place
{if( getfresh(row+2)
&&getside(row+3)==VOID
&&getside(row+4)==VOID
&&getside(row+5)==VOID
&&!attack(row+4,1-side)
&&!attack(row+5,1-side)
&&!attack(row+6,1-side))
add(list,newmove(row+6,row
if( getfresh(row+9)
&&getside(row+7)==VOID
&&getside(row+8)==VOID
&&!attack(row+6,1-side)
&&!attack(row+7,1-side)
&&!attack(row+8,1-side))
add(list,newmove(row+6,row
}
if(moves!=0)
{//try enpassant
int forward= (side==WHITE)?12:-12;
int m=getstoredm(moves-1);
int to=moveto(m);
int from=movefrom(m);
if(getpiece(to)==PAWN&&fro
{if(inboard(to+1)&&getside
&&getpiece(to+1)==PAWN&&ge
add(list,newmove(to+1,to+f
if(inboard(to-1)&&getside(
&&getpiece(to-1)==PAWN&&ge
add(list,newmove(to-1,to+f
}
}
return list;
}
}
class superdiagram extends Canvas
/*this is a superclass for 2 kinds of diagrams
It can be magnified by changing scale, and knows to draw pieces.
*/
{
int scale, ymax;
Color backColor[];
Color darkpieceColor[];// the colors used to paint the pieces
Color lightpieceColor[];
superdiagram()
{
backColor=new Color[2];
backColor[0]=new Color(100,128,100);//dark green
backColor[1]=new Color(128,160,128);//light
darkpieceColor=new Color[2];
darkpieceColor[0]=new Color(255,255,255);//for WHITE
darkpieceColor[1]=new Color(0,0,128);//for BLACK
lightpieceColor=new Color[2];
lightpieceColor[0]=new Color(200,200,64);//for WHITE
lightpieceColor[1]=new Color(84,84,255);//for BLACK
}
void bar(int x,int y, int hSize, int vSize,Color c,Graphics g)
{//draw a bar (filled rectangle).
g.setColor(c);
g.fillRect( x*scale, ymax-(y+vSize)*scale,
hSize*scale,vSize*scale);
}
void paintfield(int fx,int fy, int piece,int side ,Graphics g)
/*paint a field. Size: 16*scale pixels.*/
{
int x=fx*16;
int y=fy*16;
bar(x,y,16,16,backColor[(f
if(side==chessboard.VOID) return;
switch(piece)
{case chessboard.PAWN:
bar(x+4,y+4,8,8,darkpieceC
break;
case chessboard.ROOK:
bar(x+1,y+4,14,3,darkpiece
bar(x+4,y+1,3,14,lightpiec
bar(x+1,y+9,14,3,darkpiece
bar(x+9,y+1,3,3,lightpiece
bar(x+9,y+7,3,8,lightpiece
break;
case chessboard.KNIGHT:
bar(x+7,y+1,2,5,darkpieceC
bar(x+4,y+6,8,4,darkpieceC
bar(x+10,y+10,4,2,lightpie
break;
case chessboard.BISSHOP:
bar(x+3,y+1,10,4,darkpiece
bar(x+7,y+4,2,8,lightpiece
break;
case chessboard.KING:
bar(x+6,y+1,4,13,darkpiece
bar(x+3,y+8,10,3,lightpiec
break;
case chessboard.QUEEN:
bar(x+3,y+1,10,4,darkpiece
bar(x+7,y+5,2,6,lightpiece
bar(x+3,y+4,2,5,lightpiece
bar(x+11,y+4,2,5,lightpiec
break;
}
}
public void update(Graphics g){paint(g);}
}
class pieceselector extends superdiagram
/*a pieceselector displays all pieces, and when the user clicks a
piece the pieceselector notifies the applet*/
{int[] piece;
int[] side;
simplechess applet;
pieceselector(simplechess ds, int scalingfactor)
{
side= new int[14];
piece=new int[14];
applet=ds;
for(int j=0;j<12;j++)
side[j]=j%2;
for(int i=0;i<2;i++)
{
piece[i]=chessboard.PAWN;
piece[2+i]=chessboard.ROOK
piece[4+i]=chessboard.KNIG
piece[6+i]=chessboard.BISS
piece[8+i]=chessboard.QUEE
piece[10+i]=chessboard.KIN
piece[12+i]=0;
side[12+i]=chessboard.VOID
}
scale(scalingfactor);
}
public boolean mouseDown(Event ev,int x,int y)
{
if(x<0||x>=32*scale||y<0||
return true;
x=x/(16*scale);
y=(ymax-y-1)/(16*scale);
applet.piececlicked(side[2
return true;
}
public void paint(Graphics g)
{
for(int f=0;f<14;f++)
paintfield(f%2,f/2,piece[f
}
public void scale(int s)
{
if(s<1||s>5) s=2;
scale=s;
ymax=7*16*scale;
resize(32*scale,ymax);
}
}
class chessview extends superdiagram
/*can display a chessboard, and when a field is clicked, the applet
is notified.*/
{
chessboard board;
simplechess applet;
chessview(simplechess ds,chessboard b, int s)
{
applet=ds;
board=b;
scale(s);
}
public void scale(int s)
{if(s<1||s>5)
s=2;
scale=s;
ymax=8*16*scale;
resize(ymax,ymax+15);
}
public boolean mouseDown(Event ev,int x,int y)
{
if(x<0||x>=ymax||y<0||y>=y
return true;
x=x/(16*scale);
y=(ymax-y-1)/(16*scale);
applet.fieldclicked(12*(y+
return true;
}
public void paint(Graphics g)
{int f;
for(int x=0;x<8;x++)
for(int y=0;y<8;y++)
paintfield(x,y, board.getpiece(x+2+12*(y+2
board.getside(x+2+12*(y+2)
g.setColor(Color.black);
g.fillRect(0,ymax,ymax,15)
g.setColor(Color.white);
String s;
if(board.getside()==board.
s="White to move.";
else
s="Black to move.";
if(board.status==board.CHE
s+=" Checkmate";
else if(board.status==board.CHE
s+=" Check!";
else if(board.status==board.DRA
s+=" Game ends in draw.";
g.drawString(s,2,ymax+12);
}
}
public class simplechess extends java.applet.Applet
/*The applet displays a board and buttons. It listens
to the buttons and mouseclicks.*/
{
chessboard B;
chessview Bview;
pieceselector selector;
Button newgame,edit,undo;
int state;
final static int USERGRABPIECE=0,USERRELEAS
USERSELECTPROMOTION=2,PCMO
EDITING=4,NOTHINGTODO=5;
int selectedfield1,selectedfie
Label message;
int[] list;
mover Sieuwert;
int pieceinhand;
public void init()
{
B=new chessboard();
Bview=new chessview(this,B,2);
B.setview(Bview);
selector=new pieceselector(this,2);
setLayout(new BorderLayout());
Panel buttonpanel=new Panel();//panel to keep buttons together
buttonpanel.setLayout(new GridLayout(1,3));
buttonpanel.add(newgame=ne
buttonpanel.add(edit=new Button("edit"));
buttonpanel.add(undo=new Button("undo"));
Panel controlpanel=new Panel();
controlpanel.setLayout(new
controlpanel.add(buttonpan
controlpanel.add(message=n
Panel diagrampanel=new Panel();
diagrampanel.setLayout(new
diagrampanel.add("West",Bv
diagrampanel.add("East",se
add("North",diagrampanel);
add("South", controlpanel);
state=USERGRABPIECE;
setmessage("welcome");
Sieuwert=new mover(B,this);
pieceinhand=B.PAWN+B.WHITE
}
void setmessage(String s)
/*The string s will be shown to the user.*/
{message.setText(s);}
int seek(int[] L,int from,int to)
/*seeks a move with that from and to in list. If not: -1*/
{
for(int i=L[0];i>0;i--)
if(chessboard.movefrom(L[i
chessboard.moveto(L[i])==t
return i;
return -1;
}
int seek(int[] L,int from,int to,int newpiece)
/*seeks the move with that from, that to and that newpiece.*/
{
for(int i=L[0];i>0;i--)
if(chessboard.movefrom(L[i
chessboard.moveto(L[i])==t
chessboard.movenewpiece(L[
return i;
return -1;
}
public void fieldclicked(int f)
/*If the computer is thinking, we do nothing.
Else we try to do the user's move, and a computermove.*/
{
synchronized(this)
{if(state==PCMOVING) return;}
switch(state)
{case USERGRABPIECE:
if(B.getside(f)!=B.getside
{setmessage("You can't move that piece.");}
else
{selectedfield1=f;state=US
setmessage("You got piece "+f);
}
break;
case USERRELEASEPIECE:
{
if(list==null)
list=B.listofmoves();
int m=seek(list,selectedfield1
if(m==-1)
{ setmessage("Your piece cannot go there.");
state=USERGRABPIECE;
break;
}
int mod=chessboard.movenewpiec
if(mod==chessboard.QUEEN||
mod==chessboard.KNIGHT||mo
{ setmessage("Your pawn can promote to another piece.");
selectedfield2=f;
state=USERSELECTPROMOTION;
break;
}
else
{ B.visualdomove(list[m]);
list=null;
computermove(Sieuwert);
}
}
break;
case EDITING:
B.A[f]=pieceinhand;
Bview.repaint();
break;
case NOTHINGTODO:
setmessage("Press newgame for a rematch.");
break;
}
}
void piececlicked(int side,int piece)
{
if(state==USERSELECTPROMOT
{
int index=seek(list,selectedfi
if(index!=-1)
{B.visualdomove(list[index
list=null;
computermove(Sieuwert);
}
}
else if(state==EDITING)
{
pieceinhand=side+piece;
}
}
void computermove(mover M)
{
if(B.status==B.CHECKMATE||
{
setmessage("Game over.");
state=NOTHINGTODO;
}
else
{
state=PCMOVING;
M.domove();
}
}
void catchamove(int m)
/*Some time after we ask the mover for a move,
he will call this method to give us his move. We will
do his move.*/
{
synchronized(this)
{
if(state==PCMOVING)
{B.visualdomove(m);
state=USERGRABPIECE;
}
}
}
void newgame()
{
B.setup();
if(state!=EDITING)
state=USERGRABPIECE;
}
void undo()
{
if(state!=EDITING)
{B.visualundomove();
setmessage("...");
}
}
void switchedit()
{
if(state==EDITING&&B.getki
{
B.reset();
setmessage("play.");
edit.setLabel("edit");
state=USERGRABPIECE;
}
else if(state==USERGRABPIECE)
{
setmessage("edit.");
edit.setLabel("play");
state=EDITING;
}
}
public boolean action(Event ev, Object O)
/*If a button was clicked, the browser calls this function.
If a computerplayer is thinking, we do nothing.
Else, we do the right action.
*/
{
synchronized(this)
{
if(state==PCMOVING)
return true;
else if(ev.target==newgame)
{newgame();}
else if(ev.target==undo)
{undo();}
else if(ev.target==edit)
{switchedit();}
}
return true;
}
}
class mover extends Thread
/*mover is a thread, because that makes it possible to return the method
do a move before doing the move. this is more convenient for many browsers:
the mouseclicks that ask for moves are returned fast, so the user can click
other buttons while the computer is calculating.
the result is given to the applet by applet.catchamove();
*/
{
chessboard original; //the chessboard to do moves on
chessboard b; // a copy to do calculations on
static int minlevel=2,maxlevel=6; //the maximum searchdepth
simplechess applet;
final static int HIGH=65534, SUPERHIGH=65535, ABOVEALL=65536;
/*HIGH is the highest possible score. superhigh is
a impossible score, that will act as a bottom
to start searching. ABOVEALL is a score that can be returned if
it is found out that an ill move was done.*/
static int pawnscore[];//good places for pawns
int nodes;
mover(chessboard bb,simplechess l)
//make a mover
{
makepawntable();
original=bb;
applet=l;
start(); //get running.
}
static void makepawntable()
{
if(pawnscore!=null)
return;
pawnscore=new int[144];
for(int i=0;i<144;i++)
pawnscore[i]=100+5*((i-2)/
for(int i=0;i<12;i++)
{
pawnscore[96+i]=240;
pawnscore[84+i]=160;
}
pawnscore[66]=pawnscore[65
}
/*this trick intends to do the calculating in a second thread, so the
main thread can handle other clicks. This is necessary in UNIX, because
otherwise the applet would block all other applications from reading the mouse. In
Netscape, this trick is unstable: NN can crash. In internet explorer, it
works.*/
public void run()
/*the mover will get into sleep,
when woke up do a move, sleep,move,etc*/
{while(true)
{ this.suspend();
domove_2();
}
}
void domove()
//this wakes up the mover. It will do a move
{resume();}
void domove_2()
/*does a move on original. It tries all moves it can do, and
then does the move that gave the highest prognosis.*/
{
nodes=0;
b=new chessboard(original); //make a copy for calculations
int[] list=b.listofmoves();
int bestmoveindex=-1;
int alpha=-SUPERHIGH;
for(int c=1;c<=list[0];c++)
{
b.domove(list[c]);
int s=-fullsearch(-SUPERHIGH,-
b.undomove();
if(s>alpha)
{alpha=s;
bestmoveindex=c;
}
}
applet.catchamove(list[bes
System.out.println("nodes "+nodes);
}
void swap(int[] l,int[] v, int i,int j)
/*swap the elements i and j in both l and v.*/
{
int dummy;
dummy=l[i];
l[i]=l[j];
l[j]=dummy;
dummy=v[i];
v[i]=v[j];
v[j]=dummy;
}
void sort(int[] l,int[] v) {quicksort(l,v,1,l[0]);}
/*sorts v, keeping the corresponding elements l[i]
and v[i] together. highest v first.*/
void quicksort(int[] l,int[] v,int p,int r)
//sort the interval [p,r] of v, like above
{
if(p<r)
{
int q=partition(l,v,p,r);
quicksort(l,v,p,q);
quicksort(l,v,q+1,r);
}
}
int partition(int[] l,int[] v,int p,int r)
/*split v (and l) in a high and low part.*/
{int x=v[p];
int i=p-1;
int j=r+1;
while(true)
{
do j--; while(!(v[j]>=x));
do i++; while(!(v[i]<=x));
if(i<j)
swap(l,v,i,j);
else
return j;
}
}
int[] estimates(int[] l)
/*returns the estimated benefits of a move.*/
{
int[] v=new int[l[0]+1];
int np;
v[0]=l[0];
for(int i=1;i<=l[0];i++)
{
if(l[i]==b.NULLMOVE)
v[i]=0;
else
{
np=b.movenewpiece(l[i]);
if(np==0)
v[i]=value(b.getpiece(b.mo
if(np==b.ENPASSANT)
v[i]=110;
else if(np==b.CASTLE)
v[i]=20;
else if(np==b.CAASTLE)
v[i]=16;
else v[i]=value(np);
}
}
return v;
}
int[] makefulllist()
/*make a list of moves to search.*/
{
int[] l=b.listofmoves();
int[] v=estimates(l);
sort(l,v);
return l;
}
int fullsearch(int alpha, int beta, int level)
/*Try to give a prognosis about how good the situation is for
the player to move on the chessboard b. It does that
by looking at the status(if the game is result),
by doing any move and calling prognosis,
by calling estimate (if it has called itself often enough)*/
{
if(level>=minlevel)
return justattacksearch(alpha,bet
nodes++;
/*try all moves and return the estimate
we get when doing the best move*/
int[] list=makefulllist();
if(list[0]==0)//no moves
{if(b.check(b.getside()))
return -HIGH;//we lost.
else return 0;//stalemate
}
for(int c=1;c<=list[0];c++)
{
b.domove(list[c]);
int s=-fullsearch(-beta,-alpha
b.undomove();
if(s>beta) return s;
if(s>alpha) alpha=s;
}
return alpha;
}
int[] makejustattacklist()
/*make a list for searching only attack moves.*/
{
int[] l=b.listofpseudomoves();
int[] v=estimates(l);
int i=1;
while(i<=l[0])
if(v[i]<50)
b.delete(l,i);
else
i++;
b.add(l,b.NULLMOVE);
return l;
}
int justattacksearch(int alpha, int beta, int level)
/*Try to give a prognosis about how good the situation is for
the player to move on the chessboard b. It does that
by looking at the status(if the game is result),
by doing any move and calling prognosis,
by calling estimate (if it has called itself often enough)*/
{
nodes++;
if(level>=maxlevel)
return justbacksearch(alpha,beta)
/*try all moves and return the estimate
we get when doing the best move*/
int[] list=makejustattacklist();
for(int c=1;c<=list[0];c++)
{
b.domove(list[c]);
int s=-justattacksearch(-beta,
b.undomove();
if(s>beta) return s;
if(s>alpha) alpha=s;
}
return alpha;
}
int value(int piece)
/*The value of a piece.*/
{
switch(piece)
{
case 2: return 105;
case 8: return 300;
case 6: return 450;
case 12: return 850;
case 10:return 320;
case 14: return 3200;
case -1: return 0;
}
return 0;
}
int justbacksearch(int alpha,int beta)
//try to hit back, or use basicscore
{
if(b.illmovedone())
return ABOVEALL;
int to=b.moveto(b.getstoredm(b
int s=basicscore();
if(s>beta) return s;
if(s>alpha) alpha=s;
if(b.attack(to,b.getside()
{
int[] list=hitbacklist();
for(int c=1;c<=list[0];c++)
{
b.domove(list[c]);
s=-justbacksearch(-beta,-a
b.undomove();
if(s>beta) return s;
if(s>alpha) alpha=s;
}
}
return alpha;
}
int[] hitbacklist()
{
int[] l=b.listofpseudomoves();
int to=b.moveto(b.getstoredm(b
int i=1;
while(i<=l[0])
if(b.moveto(l[i])!=to)
b.delete(l,i);
else
i++;
b.add(l,b.NULLMOVE);
return l;
}
int basicscore()
/*calculate a score, non recursively*/
{int score[]=new int[2];
int pside;
for(int x=24;x<120;x+=12)
for(int field=x+2;field<x+10;field
{
pside=b.getside(field);
if(pside!=chessboard.VOID)
{
switch(b.getpiece(field))
{case chessboard.PAWN:
if(pside==chessboard.WHITE
score[pside]+=pawnscore[fi
else
score[pside]+=pawnscore[14
//mirror the table to get the black values
if(b.A[field+12]==chessboa
score[pside]-=20;//double pawn
break;
case chessboard.KNIGHT:
score[pside]+=295;
break;
case chessboard.BISSHOP:
score[pside]+=300;
break;
case chessboard.ROOK:
score[pside]+=450;
break;
case chessboard.QUEEN:
score[pside]+=850;
break;
case chessboard.KING:
score[pside]+=3200;
break;
}
}
}
int whiteresult=score[chessboa
return (b.getside()==chessboard.W
}
}
Give us the exact exception.
ASKER
Ok i got to this link
http://users.telenet.be/artificialintelligence/download/simplechess.java
I save it on to my desktop right and I open it from there. The software on my desktop is Jcreator. When i compile it i get the message...
Note: C:\Documents and Settings\cjm32\Desktop\sim plechess.j ava uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Process completed.
When I try running it I get the message " Exception in thread "main" java.lang.NosuchmethodErro r: Main "
Since I'm new to Java i'm guessing i'm compiling it the wrong way. I copied source code online. So it should work. The output should be a chess program. Could someone give me steps on how to do this.
http://users.telenet.be/artificialintelligence/download/simplechess.java
I save it on to my desktop right and I open it from there. The software on my desktop is Jcreator. When i compile it i get the message...
Note: C:\Documents and Settings\cjm32\Desktop\sim
Note: Recompile with -Xlint:deprecation for details.
Process completed.
When I try running it I get the message " Exception in thread "main" java.lang.NosuchmethodErro
Since I'm new to Java i'm guessing i'm compiling it the wrong way. I copied source code online. So it should work. The output should be a chess program. Could someone give me steps on how to do this.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
You *could* do it that way, but that would be fairly confusing to understand (my applet is a webpage...?!?)
Cheers,
-Bill
Cheers,
-Bill