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:
47
src/suicideChess/ComputerPlayer.java
Normal file
47
src/suicideChess/ComputerPlayer.java
Normal 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
118
src/suicideChess/XBoardProtocol.java
Normal file
118
src/suicideChess/XBoardProtocol.java
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package suicideChess;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to communicate with XBoard.
|
||||||
|
* @author Jean-Baptiste Hé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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user