The Chess Variant Pages

Pixelpusher - sourcecode


// Copyright by Hans Bodlaender and Eli Bachmutsk (c) 1998.
// Non-commercial or educational use permitted. 

import java.awt.*;
import java.net.*;

public class ChessCanvas extends  java.applet.Applet 
{
  // 0     = empty square  
  // 1,2   = white & black king         3,4   = white & black queen
  // 5,6   = white & black rook         7,8   = white & black knight
  // 9,10  = white & black bishop       11,12 = white & black pawn
  Image img[] = new Image[13];   // Piece images - null as default
  int board [][]; // position (i,j)  (a1 = 0,0; b3= 2,3; h8 = 7,7, etc.)
  ChessMoveChecker control;
  int sqsize = 32;               // square size in pixels
  int rows = 8, columns = 8 ;    // Number of rows and columns on the board 
  int rowClicked, colClicked;    // Clicked row & column,-1 if not clicked
  int computercolor = 1;         // Computer always played black
  int moveNumber;
  String setup = "rnbqkbnr/pppppppp/////PPPPPPPP/RNBQKBNR" ; // Board setup
  Panel links;
  MediaTracker tracker = new MediaTracker(this);
  String version = "PIXELPUSHER V0.3";
  TextField ta = new TextField(50);

  public void init()
  {
    reset();
    resize  (sqsize*columns, sqsize*rows+40); // + TextArea on south
    links   = new Panel();
    links.setLayout( new BorderLayout ());
    setLayout( new BorderLayout ());
    add ("West", links);
    LoadImages();
          // Area for messages
    ta.setFont( new Font ("Helvetica", Font.BOLD, 12)); 
    ta.setEditable(false);  
    ta.setBackground( Color.white);  
    add("South", ta);
  }
 public void reset ()
  {     moveNumber = 0;
        rowClicked = -1;
        board   = new int [columns][rows];         // default is 0 - empty
        ForsytheToBoard();
        control =  new ChessMoveChecker(this);
        ta.setText(version);
  }
 public void setText (String text) { ta.setText(moveNumber+". "+text);}
 public boolean mouseDown (Event e, int x, int y) 
  {     
        if (e.modifiers != 0)       // right mouse button - reset 
              reset();
         else 
              clickProcessing ( x/sqsize, rows - y/sqsize - 1);
        repaint();
        return true;
 }
 void clickProcessing (int i, int j)    // i - column, j - row
 {
  if (rowClicked == -1) // First click : from where the player should move ?
   {
     if ( (board[i][j] > 0) &&  control.RightPlayer(i,j)) // not empty and ...
       { colClicked = i;
         rowClicked = j;
       }
   }else // Second click : to which squre player should move
   {
     if (i == colClicked && j == rowClicked)
          rowClicked = -1; // if clicked on same square, clicking undone
     else if ( control.LegalMove   (colClicked,rowClicked,i,j) &&
               control.RightPlayer (colClicked,rowClicked) )
        { 
          control.DoMove (colClicked,rowClicked,i,j);
          rowClicked = -1;
	  MakeComputerMove();
        }
   }
 }
 public void paint (Graphics g)
 {
    for (int i = 0; i-1) {board[x][y]=" KkQqRrNnBbPp".indexOf(c);x++;}
   }
 }
 public void MakeComputerMove()
 {
  moveNumber++;
  setText("Black move");
  Move computermove = ComputerPlayer.findmove(control,computercolor);
  if (!computermove.isvoid())	    control.DoMove(computermove);

 if(control.Mated(1-computercolor))          setText("BLACK WIN: MATE!!!");
 else if(control.InCheck(1-computercolor))   setText("White in check!!!"); 
 else if(control.Stalemated(1-computercolor))setText("STALEMATE !!!");
 else if(control.Mated(computercolor))       setText("WHITE WIN: MATE!!!"); 
 else if(control.Stalemated(computercolor))  setText("STALEMATE  !!!");
 else                                        setText("White move");
 }
}
///////////////////////////////////////////////////////////////////////
class Move
{
  public int startrow, endrow, startcol, endcol;
  Move()
  {  startrow = endrow = startcol = endcol = 0; }
  Move(int k1, int r1, int k2, int r2)
  {  startcol = k1; startrow = r1; endcol = k2; endrow = r2;  }
  boolean isvoid()   // Return true if void move (all zeros)
  {  return (startrow+endrow+startcol+endcol)==0 ?  true : false; }
}
///////////////////////////////////////////////////////////////////////
class ComputerPlayer
{
 static int plydepth=2;
 // Overloading: findmove tries to find the best move for given position
 // ChessMoveChecker and Move: evaluate how good this particular move is.
 public static Move findmove (ChessMoveChecker position, int player)
 {
  Move themove = new Move();
  int bestmove = -50000;
  for (int i1=0; i1< position.columns; i1++)
   for (int j1=0; j1 <  position.rows; j1++)
    if (!position.EmptySquare(i1,j1))
     if (position.PieceOwner(i1,j1)==player)
      for (int i2=0; i2< position.columns; i2++)
       for (int j2=0; j2< position.rows; j2++)
	if (position.SemiLegalMove(i1,j1,i2,j2))
	{
          ChessMoveChecker aftermove = new ChessMoveChecker(position);
          aftermove.DoMove(i1,j1,i2,j2);
          if ( aftermove.InCheck(player) ) continue;
          int tryevaluate = Evaluate(aftermove,plydepth -1);
          if (tryevaluate > bestmove)
          {   themove = new Move(i1,j1,i2,j2); 
              bestmove = tryevaluate;
          }
        }
  return themove;
 }
 // This one gives a value for the player that moved to this position.
 static int Evaluate (ChessMoveChecker position, int plies)
 {
  if (plies <=0) return Evaluate(position);
  int otherplayer = 1-position.lastplayermoved;
    // what is the best move for the other player?
  int bestmove = -50000;
  for (int i1=0; i1 bestmove)
              bestmove = tryevaluate;
        }
  return 1-bestmove;
 }
 static int Evaluate (ChessMoveChecker position)
 {
   int otherplayer = 1- position.lastplayermoved;
   if (position.Mated(otherplayer))      return 50000; // Mate : value is high
   if (position.Stalemated(otherplayer)) return 0; // Stalemate : draw is zero
       //compute the difference in value of the pieces
   int totvalue = diffvalueofpieces(position,1-otherplayer);
   int ran = 1+ (int) (Math.random() * 10);  // Random from 1 to 10
   return ran + 10*totvalue;
 }
 // what is the value of the pieces of player minus the value of its opponent?
 static int diffvalueofpieces (ChessMoveChecker position, int player)
 {
   int totvalue = 0;
   for (int k=0; k0; i--)
    if (!EmptySquare(i,0) || Attacked(1,i,0))    return false;
  return whitelongcastling;
}
boolean LegalBlackLongCastling()   // is it legal for black to castle long?
{
  if (InCheck(1)) return false;
  for (int i= kingcol - 1; i >0; i--)
    if ( !EmptySquare(i,rows-1) || Attacked(0,i,rows-1) )  return false;
  return blacklongcastling;
}
boolean LegalBlackShortCastling()  // is it legal for black to castle short?
{
  if (InCheck(1)) return false;
  for (int i= kingcol + 1; i < columns -1; i++)
    if (!EmptySquare(i,rows-1) || Attacked(0,i,rows-1))   return false;
  return blackshortcastling;
}
// Determine if the move is a pawn promotion.
boolean DeterminePawnPromotion (int k1, int r1, int k2, int r2)
{
  if (board[k1][r1]==11 && r2 == rows-1)  return true;
  if (board[k1][r1]==12 && r2 == 0)       return true;
  return false;
}
public void SetLastPlayerMoved(int i)
{ 
  lastplayermoved = i;
}
// returns the owner of the piece on square (k,r)
public int PieceOwner(int k, int r)
{
   return 1- (board[k][r] %2) ; // 0 if white owns the piece,1-if black
}
// checks if the right player wants to make a move
public boolean RightPlayer(int k1, int r1)
{
   return (PieceOwner(k1,r1) != lastplayermoved);
}
// Checks if player is in check
boolean InCheck (int player)
{     // first find the king piece of the player.
  int kingpiece = 1 + player;
  for (int k=0; k< columns; k++)
    for (int r=0; r < rows; r++)
       if (board[k][r]==kingpiece)
	 // crude: check if any piece could move to the kings position
	 for (int k2=0; k22) || (Math.abs(k1-k2)<2)) ? false : true;
   boolean whiteenpassant = LegalWhitePawnEnPassantCapture (k1, r1, k2, r2);
   boolean blackenpassant = LegalBlackPawnEnPassantCapture (k1, r1, k2, r2);
     // update status
   lastmove = new Move (k1,r1, k2, r2);
   SetLastPlayerMoved(PieceOwner(k1,r1));
   ChangeCastlingStatus(k1,r1,k2,r2);
     // do the move
   board[k2][r2] = board[k1][r1];
   board[k1][r1]=0;
     // additional work if promotion, castling, enpassant
   if (promotion)       board[k2][r2] = DeterminePromotionPiece(k2,r2);
   if (castled)         HandleCastling(k1,r1,k2,r2);
   if (whiteenpassant)  board[k2][r2-1]=0;  // remove captured pawn
   if (blackenpassant)  board[k2][r2+1]=0;  // remove captured pawn
}

void HandleCastling(int k1,int r1,int k2,int r2)
{
   if (k1 > k2)                           // castling to left of board
   { board[k2+1][r2] = board[0][r2];
     board[0][r2] = 0;
   }  else                                // castling to right of board
   { board[k2-1][r2] = board[columns -1][r2];
     board[columns-1][r2]=0;
   }
}
// Determinate pawn promoted piece (always queen at this stage)
int DeterminePromotionPiece (int k, int r) 
{
  return 3+PieceOwner(k,r);    // Promoted to queen 
}
boolean Mated(int player)
{
  if (lastplayermoved != player)
    if (InCheck(player))
      return (!HasALegalMove(player));
  return false;
}
boolean Stalemated(int player)
{
  if (lastplayermoved != player)
    if (!InCheck(player))
      return (!HasALegalMove(player));
  return false;
}
boolean HasALegalMove(int player)
{
  for (int k=0; k


WWW page by Hans Bodlaender. Programming by Hans Bodlaender and Eli Bachmupsky.
WWW page created: April 3, 1998.
On the Chess Variant Pages Home page of Hans Bodlaender Feedback: hansb@cs.ruu.nl
This WWW-space is provided by: [Dept. of Computer Science]