A fully working version of the game.

Works with XBoard only (not eboard).

The program plays the first legal move.
This commit is contained in:
2006-01-17 15:18:53 +00:00
parent 42e56fde4f
commit dbfd428710
6 changed files with 356 additions and 139 deletions

View File

@ -0,0 +1,47 @@
package suicideChess;
import java.util.ArrayList;
import suicideChess.Square.NotAValidSquare;
/**
* This class will contain all the AI.
* @author Jean-Baptiste Hétier
* @version $LastChangedRevision: 33 $, $LastChangedDate: 2006-01-13 17:03:06 +0000 (Fri, 13 Jan 2006) $
*/
public class ComputerPlayer {
private int color;
/**
* This constructor creates a computer that plays with the given color
* @param color An integer representing the color. (See {@link Piece})
* @see Piece
*/
public ComputerPlayer(int color) {
this.color = color;
}
/**
* This asks the computer to compute a move
* @param bitboard The current status of the {@link Board}
* @return move A {@link Move}
* @throws NotAValidSquare
* @see Board
* @see Move
*/
public Move doMove(Board bitboard) throws NotAValidSquare {
Rules.legalMovesForPlayer(bitboard,color);
ArrayList<Move> allLegalMoves = Rules.getLegalMovesCapture();
if (allLegalMoves.size()==0) {
allLegalMoves = Rules.getLegalMovesNonCapture();
}
if (allLegalMoves.size()!=0) {
return allLegalMoves.get(0);
}
throw new RuntimeException();
}
}

View File

@ -302,7 +302,10 @@ public class Move {
* @return String * @return String
*/ */
public String toString() { public String toString() {
return fromSquare.toString()+toSquare+promotionPiece; if (isPromotion) {
return fromSquare.toString()+toSquare+promotionPiece.toString();
}
return fromSquare.toString()+toSquare;
} }

View File

@ -158,6 +158,6 @@ public class Piece {
case KNIGHT: case KNIGHT:
return Character.toString(KNIGHT_CHAR); return Character.toString(KNIGHT_CHAR);
} }
return "**Error**"; return "**Warning** in Piece.java";
} }
} }

View File

@ -300,7 +300,7 @@ public class Rules {
* You need to call legalMovesFromSquare before calling this function. * You need to call legalMovesFromSquare before calling this function.
* @return ArrayList<Move> * @return ArrayList<Move>
*/ */
public ArrayList<Move> getLegalMovesNonCapture() { public static ArrayList<Move> getLegalMovesNonCapture() {
return legalMovesNonCapture; return legalMovesNonCapture;
} }
@ -310,7 +310,7 @@ public class Rules {
* You need to call legalMovesFromSquare before calling this function. * You need to call legalMovesFromSquare before calling this function.
* @return ArrayList<Move> * @return ArrayList<Move>
*/ */
public ArrayList<Move> getLegalMovesCapture() { public static ArrayList<Move> getLegalMovesCapture() {
return legalMovesCapture; return legalMovesCapture;
} }

View File

@ -4,6 +4,7 @@ import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.ArrayList; import java.util.ArrayList;
import suicideChess.Move.NotAValidMoveException; import suicideChess.Move.NotAValidMoveException;
import suicideChess.Square.NotAValidSquare; import suicideChess.Square.NotAValidSquare;
@ -25,79 +26,86 @@ public class SuicideChess {
*/ */
public static final boolean BITBOARD_REMOVEPIECE_CHECK_REMOVE = true; public static final boolean BITBOARD_REMOVEPIECE_CHECK_REMOVE = true;
/** /**
* does Square.class checks if the strings are valid (is "z9" a valid square ? * does Square.class checks if the strings are valid (is "z9" a valid square ?)
*/ */
public static final boolean SQUARE_CHECK_INVALID = true; public static final boolean SQUARE_CHECK_INVALID = true;
private static final int MAIN_VERSION_NUMBER = 0; /**
private static final int REVISION_NUMBER = 19; * The name to be displayed
*/
public static final String NAME = "djib's SuicideChess v0.1.9";
/**
* Displays informations in the console.
*/
public static final boolean ASCII_GAME = false;
/** /**
* The main function * The main function
* @param args No parameters should be transmitted to this function. * @param args No parameters should be transmitted to this function.
*/ */
public static void main(String[] args) { public static void main(String[] args) {
System.out.println(" Welcome to SuicideChess v"+MAIN_VERSION_NUMBER+"."+REVISION_NUMBER+"!");
System.out.println();
BufferedReader moveInput = new BufferedReader(new InputStreamReader(System.in));
try { try {
Board bitboard = new Board();
bitboard.display();
int playerColor = Piece.WHITE; BufferedReader moveInput = new BufferedReader(new InputStreamReader(System.in));
Board bitboard = new Board();
if (ASCII_GAME)
bitboard.display();
int currentPlayerColor = Piece.WHITE;
if (ASCII_GAME)
System.out.println("White: "); System.out.println("White: ");
ComputerPlayer computer = new ComputerPlayer(Piece.BLACK);
while (true) { boolean playing = true;
while (playing) {
try { try {
String whatMove= moveInput.readLine(); String whatMove= moveInput.readLine();
boolean playedALegalMove = false; boolean playedALegalMove = false;
if (whatMove.startsWith("quit")) { int xBoardCommand = XBoardProtocol.getCommand(whatMove);
System.out.println("Goodbye!");
switch (xBoardCommand) {
case XBoardProtocol.XBOARD:
break; break;
} case XBoardProtocol.PROTOVER:
XBoardProtocol.initialise();
break;
case XBoardProtocol.NOT_ACCEPTED_SUICIDE:
System.out.println("tellusererror \"This game only plays suicide chess.\"");
playing=false;
break;
case XBoardProtocol.NOT_ACCEPTED_USERMOVE:
System.out.println("tellusererror \"XBoard must send moves starting with 'usermove'\"");
playing=false;
break;
case XBoardProtocol.NOPROTOVER:
System.out.println("tellusererror \"You must use an engine with XBoard protocol 2 or higher.\"");
playing=false;
break;
case XBoardProtocol.QUIT:
System.out.println("Goodbye!");
playing=false;
break;
case XBoardProtocol.NEW:
System.out.println("variant suicide");
break;
case XBoardProtocol.UNKNOWN:
System.out.println("Error (unknown command): "+whatMove);
break;
case XBoardProtocol.MOVE:
Move theMove = new Move(whatMove.substring(9), bitboard);
if (whatMove.startsWith("hint")) {
Rules rules = new Rules();
rules.legalMovesForPlayer(bitboard,playerColor);
ArrayList<Move> allLegalMoves = rules.getLegalMovesCapture();
if (allLegalMoves.size()==0) {
allLegalMoves = rules.getLegalMovesNonCapture();
}
for(int i = 0; i<allLegalMoves.size(); i++) {
if(allLegalMoves.get(i).isPromotionMove()) {
System.out.println(allLegalMoves.get(i).fromSquare().toString() +
allLegalMoves.get(i).toSquare().toString() +
allLegalMoves.get(i).getPromotionPiece().toString());
} else {
System.out.println(allLegalMoves.get(i).fromSquare().toString() +
allLegalMoves.get(i).toSquare().toString());
}
}
continue;
}
if (whatMove.startsWith("force")) {
Move theMove = new Move(whatMove.substring(6,10), bitboard);
theMove.display();
bitboard.doMove(theMove);
bitboard.display();
continue;
}
Move theMove = new Move(whatMove, bitboard);
Rules rules = new Rules();
boolean needToCapture = false; boolean needToCapture = false;
int foundMoveIndex = -1; int foundMoveIndex = -1;
if(theMove.getMovingPiece().getColor() == playerColor) { if(theMove.getMovingPiece().getColor() == currentPlayerColor) {
rules.legalMovesForPlayer(bitboard,playerColor); Rules.legalMovesForPlayer(bitboard,currentPlayerColor);
ArrayList<Move> allLegalMoves = rules.getLegalMovesCapture(); ArrayList<Move> allLegalMoves = Rules.getLegalMovesCapture();
if (allLegalMoves.size()==0) { if (allLegalMoves.size()==0) {
allLegalMoves = rules.getLegalMovesNonCapture(); allLegalMoves = Rules.getLegalMovesNonCapture();
} else { } else {
needToCapture = true; needToCapture = true;
} }
@ -113,29 +121,70 @@ public class SuicideChess {
} }
if (foundMoveIndex == -1) { if (foundMoveIndex == -1) {
if (needToCapture) { if (needToCapture) {
if (ASCII_GAME)
System.out.println("Capturing is mandatory."); System.out.println("Capturing is mandatory.");
} }
System.out.println("This move is not valid. Please type 'hint' to see list of legal moves."); System.out.println("Illegal move: "+theMove.toString());
} else { } else {
allLegalMoves.get(foundMoveIndex).display();
bitboard.doMove(allLegalMoves.get(foundMoveIndex)); bitboard.doMove(allLegalMoves.get(foundMoveIndex));
if (ASCII_GAME) {
allLegalMoves.get(foundMoveIndex).display();
bitboard.display(); bitboard.display();
}
playedALegalMove=true; playedALegalMove=true;
} }
} else { } else {
if (ASCII_GAME)
System.out.println("Please play a piece of the right color."); System.out.println("Please play a piece of the right color.");
System.out.println("Illegal move: "+theMove.toString());
} }
if (playedALegalMove) { if (playedALegalMove) {
if (playerColor == Piece.WHITE) { currentPlayerColor = Piece.BLACK;
playerColor = Piece.BLACK; Move computerMove = computer.doMove(bitboard);
System.out.println("Black: "); bitboard.doMove(computerMove);
} else { XBoardProtocol.doMove(computerMove);
playerColor = Piece.WHITE; if (ASCII_GAME) {
computerMove.display();
bitboard.display();
}
currentPlayerColor = Piece.WHITE;
if (ASCII_GAME)
System.out.println("White: "); System.out.println("White: ");
} }
break;
} }
// if (whatMove.startsWith("hint")) {
// Rules rules = new Rules();
// rules.legalMovesForPlayer(bitboard,currentPlayerColor);
// ArrayList<Move> allLegalMoves = rules.getLegalMovesCapture();
// if (allLegalMoves.size()==0) {
// allLegalMoves = rules.getLegalMovesNonCapture();
// }
// for(int i = 0; i<allLegalMoves.size(); i++) {
// if(allLegalMoves.get(i).isPromotionMove()) {
// System.out.println(allLegalMoves.get(i).fromSquare().toString() +
// allLegalMoves.get(i).toSquare().toString() +
// allLegalMoves.get(i).getPromotionPiece().toString());
// } else {
// System.out.println(allLegalMoves.get(i).fromSquare().toString() +
// allLegalMoves.get(i).toSquare().toString());
// }
//
// }
// continue;
// }
// if (whatMove.startsWith("force")) {
// Move theMove = new Move(whatMove.substring(6,10), bitboard);
// theMove.display();
// bitboard.doMove(theMove);
// bitboard.display();
// continue;
// }
} catch (NotAValidMoveException err) { } catch (NotAValidMoveException err) {
System.out.println(err); System.out.println(err);
continue; continue;

View File

@ -0,0 +1,118 @@
/**
*
*/
package suicideChess;
import java.io.IOException;
/**
* Class used to communicate with XBoard.
* @author Jean-Baptiste H&eacute;tier
* @version $LastChangedRevision: 33 $, $LastChangedDate: 2006-01-13 17:03:06 +0000 (Fri, 13 Jan 2006) $
*/
public class XBoardProtocol {
//Constants
/**
* Received 'xboard' command
*/
public static final int XBOARD = 0;
/**
* Received a 'protover' >= 2
*/
public static final int PROTOVER = 1;
/**
* Received a 'protover' < 2
*/
public static final int NOPROTOVER = 2;
/**
* Reveived command 'new'
*/
public static final int NEW = 3;
/**
* Reveiced command 'quit'
*/
public static final int QUIT = 4;
/**
* Received a move
*/
public static final int MOVE = 5;
/**
* Received an invalid move
*/
public static final int INVALID = 6;
/**
* XBoard did not accept sending moves with usermove
*/
public static final int NOT_ACCEPTED_USERMOVE = 9;
/**
* XBoard did not accept variant suicide chess
*/
public static final int NOT_ACCEPTED_SUICIDE = 10;
/**
* Unknown command
*/
public static final int UNKNOWN = -1;
/**
* This function initialises the communications with XBoard.
* @throws IOException If SuicideChess.XBOARDPROTOCOL_CREATES_LOGFILE is true then the initialisation
* will create a logfile.
*/
public static void initialise() throws IOException {
//done=1 is here to tell that the program has finish requesting features
if (SuicideChess.ASCII_GAME) {
System.out.println("Welcome to SuicideChess "+SuicideChess.NAME+"!");
System.out.println("This game was not designed to be played in console. Please use it with XBoard, WinBoard or any compatible program.");
System.out.println();
}
System.out.println("feature myname=\"djib's Suicide Chess\"");
System.out.println("feature sigint=0 sigterm=0");
System.out.println("feature usermove=1"); //sends moves like 'usermove e2e4'
System.out.println("feature variants=\"suicide\"");
System.out.println("feature time=0 draw=0 reuse=0 analyse=0");
System.out.println("feature done=1");
if (SuicideChess.ASCII_GAME)
System.out.println();
}
/**
* Sends a move message to XBoard
* @param move The {@link Move} to be made
* @see Move
*/
public static void doMove(Move move) {
System.out.println("move "+move.toString());
}
/**
* Interprets XBoard Commands
* @param command The command to be interpreted
* @return a integer reprenting the command (se constants defined in XBoardProtocol.java
*/
public static int getCommand(String command) {
if (command.equals("xboard")) {
return XBOARD;
} else if (command.startsWith("protover")) {
if (Integer.parseInt(command.substring(9))>=2)
return PROTOVER;
return NOPROTOVER;
} else if (command.equals("new")) {
return NEW;
} else if (command.equals("quit")) {
return QUIT;
} else if (command.startsWith("usermove")) {
return MOVE;
} else if (command.equals("rejected variants")) {
return NOT_ACCEPTED_SUICIDE;
} else if (command.equals("rejected usermove")) {
return NOT_ACCEPTED_USERMOVE;
}
return UNKNOWN;
}
}