Version 6.9

===========
Now detects draw (50 moves only)
Displays time to find move
Can read a library of problems from a file
Each problem can be selected independently or all can be
  played in succession and then the result is displayed.
This commit is contained in:
2006-07-01 15:06:24 +00:00
parent 74206376a7
commit 1b500b4421
5 changed files with 369 additions and 161 deletions

View File

@ -1,5 +1,6 @@
package suicideChess;
import suicideChess.Square.NotAValidSquare;
/**
@ -32,8 +33,11 @@ public class Board {
private static final int NB_OF_BITBOARDS = 14;
//with less than that many pawns on one side, the computer will enter endgame mode
public static final int ENDGAME = 3;
public static final int ENDGAME_PAWNS = 3;
//with less than that many pieces on one side, the computer will enter endgame mode
public static final int ENDGAME_PIECES = 6;
@SuppressWarnings("serial")
public class NoPieceOnSquare extends Exception {
NoPieceOnSquare(String s) { super(s); };
@ -61,9 +65,12 @@ public class Board {
* Value representing the minimum value possible for the evaluation function
*/
public static final int MIN_VALUE = BLACK_WINS-1;
/**
* Value representing the value of a draw position
*/
public static final int DRAW_BOARD = 0;
/*======*
* DATA *
*======*/
@ -94,6 +101,11 @@ public class Board {
private int boardValue = 0; //evaluation of the board value
private int currentPlayer; //color of the current player.
//starts at 1 and increment after each of black's move
private int fullmoveNumber;
//this variable holds the number of Moves since last capture or last pawn move
private int halfmoveClock;
/*=============*
* CONSTRUCTOR *
@ -108,6 +120,9 @@ public class Board {
//the following line makes sure that enPassantSquare is defined at some point.
enPassantSquare = new Square("a1");
fullmoveNumber = 1;
halfmoveClock = 0;
numberOfPieces = new int[Piece.MAX_PIECE_NUMBER+1];
for (int i=0; i<=Piece.MAX_PIECE_NUMBER; i++) {
numberOfPieces[i]=0;
@ -163,6 +178,9 @@ public class Board {
this.numberOfPieces[i] = bitboard.numberOfPieces[i];
}
this.fullmoveNumber = bitboard.fullmoveNumber;
this.halfmoveClock = bitboard.halfmoveClock;
this.boardValue = bitboard.boardValue;
this.bitBoards = new long[NB_OF_BITBOARDS];
for (int i=0; i<NB_OF_BITBOARDS; i++) {
@ -214,9 +232,16 @@ public class Board {
enPassant = false;
enPassantSquare = new Square("a1"); //otherwise it is null
}
try {
fullmoveNumber = Integer.parseInt(result[12]);
halfmoveClock = Integer.parseInt(result[11]);
} catch (NumberFormatException e) {
System.out.println("Error (impossible to parse clock): "+command);
fullmoveNumber = 1;
halfmoveClock = 0;
}
numberOfPieces = new int[Piece.MAX_PIECE_NUMBER];
numberOfPieces = new int[Piece.MAX_PIECE_NUMBER+1];
for(int split=0; split < 8; split++) {
int offset=0;
@ -262,12 +287,14 @@ public class Board {
*/
public void doMove(Move move) throws NoPieceOnSquare, NotAValidSquare {
if (move.isCaptureMove()) {
halfmoveClock++;
if (move.isCaptureMove()) {
if (move.isEnPassant()) {
removePiece(move.getEnPassantSquare(), move.getCapturedPiece());
} else {
removePiece(move.toSquare(), move.getCapturedPiece());
}
halfmoveClock=0; //reinitialise halfmoveClock since there has been a capture
}
removePiece(move.fromSquare(), move.getMovingPiece());
if (move.isPromotionMove()) {
@ -275,6 +302,9 @@ public class Board {
} else {
addPiece(move.toSquare(), move.getMovingPiece());
}
if(move.getMovingPiece().getPieceNumber()==Piece.PAWN) {
halfmoveClock = 0; //a pawn has been moved
}
this.enPassant=false;
if (move.enablesEnPassant()) {
@ -287,11 +317,12 @@ public class Board {
//if (SuicideChess.ASCII_GAME)
// System.out.println("Black: ");
} else {
fullmoveNumber++; //black has just played
currentPlayer=Piece.WHITE;
//if (SuicideChess.ASCII_GAME)
// System.out.println("White: ");
}
evaluateNewBoardValue(move);
}
@ -396,6 +427,24 @@ public class Board {
return boardValue;
}
/**
* This function tells if the board is in a draw status
*/
public boolean isADraw() {
if(halfmoveClock>=Rules.NUMBER_OF_MOVES_BEFORE_DRAW) {
return true;
}
return false;
}
/**
* Used to get the halfmoveClock.
* @return the number of halfmoves since the last capture or pawn movement
*/
public int getHalfmoveClock() {
return halfmoveClock;
}
/**
* This function returns the current player color
* @return Integer
@ -543,13 +592,14 @@ public class Board {
//this is a very very basic evaluation function that will be changed.
//boardValue = numberOfBlackPieces - numberOfWhitePieces;
boardValue = 0;
if((numberOfPieces[Piece.BLACK_PAWN] <= ENDGAME) || (numberOfPieces[Piece.WHITE_PAWN] <= ENDGAME)) {
System.out.println("Playing endgame");
if((numberOfPieces[Piece.BLACK_PAWN] <= ENDGAME_PAWNS) || (numberOfPieces[Piece.WHITE_PAWN] <= ENDGAME_PAWNS)
|| (numberOfPieces[Piece.BLACK_PIECES] <= ENDGAME_PIECES) || (numberOfPieces[Piece.WHITE_PIECES] <= ENDGAME_PIECES) ) {
//System.out.println("Playing endgame");
for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) {
boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_ENDGAME[i];
}
} else {
System.out.println("Playing midgame");
//System.out.println("Playing midgame");
for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) {
boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_MIDDLEGAME[i];
}

View File

@ -1,6 +1,7 @@
package suicideChess;
import java.util.ArrayList;
import java.util.Date;
import java.util.Random;
import suicideChess.Board.NoPieceOnSquare;
@ -138,9 +139,11 @@ public class ComputerPlayer {
public static Move doAlphaBetaMove(Board bitboard) throws NotAValidSquare, NoPieceOnSquare {
bestMove = null;
nodesSearched = 0;
ReturnWrapper bestScore = AlphaBeta(bitboard, 0, Board.BLACK_WINS-1, Board.WHITE_WINS+1);
Date thinkingBeginingTime = new Date();
ReturnWrapper bestScore = AlphaBeta(bitboard, 0, Board.BLACK_WINS-1, Board.WHITE_WINS+1);
Date thinkingEndTime = new Date();
//select one of the best moves randomly
Random generator = new Random();
//if (currentDepth == 0) { System.out.println(bestMoveIndex.size()); }
@ -149,7 +152,9 @@ public class ComputerPlayer {
System.out.println("Found "+bestMoves.size()+" good moves.");
if (SuicideChess.postThinkingOutput()) {
System.out.println(SuicideChess.PLY_DEPTH+" "+bestScore.getAlphaBeta()*100+" 0 "+nodesSearched+" "+bestMove);
System.out.println(SuicideChess.PLY_DEPTH+" "+bestScore.getAlphaBeta()*100+
" "+((int)(thinkingEndTime.getTime()-thinkingBeginingTime.getTime())/10)+ //search time in centiseconds
" "+nodesSearched+" "+bestMove);
}
return bestMove;
@ -172,6 +177,10 @@ public class ComputerPlayer {
};
private static ReturnWrapper AlphaBeta(Board bitboard, int currentDepth, int alpha, int beta) throws NotAValidSquare, NoPieceOnSquare {
nodesSearched++;
if(bitboard.isADraw()) {
return new ReturnWrapper(Board.DRAW_BOARD,Board.DRAW_BOARD);
}
if (currentDepth >= SuicideChess.PLY_DEPTH) {
//System.out.println("'-> Evaluate: "+bitboard.getBoardValue());
return new ReturnWrapper(bitboard.getBoardValue(),bitboard.getBoardValue());
@ -202,7 +211,7 @@ public class ComputerPlayer {
//System.out.println("Analysing "+currentDepth+":"+allLegalMoves.get(i));
ReturnWrapper returnValue = AlphaBeta(boardCopy,currentDepth+1,alpha,beta);
ReturnWrapper returnValue = AlphaBeta(boardCopy,currentDepth+1,Board.MIN_VALUE,beta);
currentScore = returnValue.getBranchValue();
currentAlphaBeta = returnValue.getAlphaBeta();
@ -229,7 +238,7 @@ public class ComputerPlayer {
}
if(beta<alpha) {
//System.out.println("Pruning "+Integer.toString(allLegalMoves.size()-i)+" alternatives at depth "+ currentDepth);
//if(currentDepth!=SuicideChess.PLY_DEPTH-1) System.out.println("Pruning "+Integer.toString(allLegalMoves.size()-i)+" alternatives at depth "+ currentDepth);
return new ReturnWrapper(alpha,bestScoreSoFar); //pruning
}
}
@ -242,7 +251,7 @@ public class ComputerPlayer {
//System.out.println("Analysing "+currentDepth+":"+allLegalMoves.get(i));
ReturnWrapper returnValue = AlphaBeta(boardCopy,currentDepth+1,alpha,beta);
ReturnWrapper returnValue = AlphaBeta(boardCopy,currentDepth+1,alpha,Board.MAX_VALUE);
currentScore = returnValue.getBranchValue();
currentAlphaBeta = returnValue.getAlphaBeta();
@ -269,7 +278,7 @@ public class ComputerPlayer {
}
if(alpha>beta) {
//System.out.println("Pruning "+Integer.toString(allLegalMoves.size()-i)+" alternatives at depth "+ currentDepth);
//if(currentDepth!=SuicideChess.PLY_DEPTH-1) System.out.println("Pruning "+Integer.toString(allLegalMoves.size()-i)+" alternatives at depth "+ currentDepth);
return new ReturnWrapper(beta,bestScoreSoFar); //pruning
}
}

View File

@ -12,6 +12,11 @@ import suicideChess.Square.NotAValidSquare;
*/
public class Rules {
/**
* Number of moves without a piece being capture or a pawn being moved before the game becomes a draw
*/
public static int NUMBER_OF_MOVES_BEFORE_DRAW=50;
private static ArrayList<Move> legalMovesNonCapture;
private static ArrayList<Move> legalMovesCapture;

View File

@ -5,8 +5,11 @@ import java.io.InputStreamReader;
import java.util.ArrayList;
import suicideChess.Board.NoPieceOnSquare;
import suicideChess.Board.UnableToParseFENStringException;
import suicideChess.Move.NotAValidMoveException;
import suicideChess.Square.NotAValidSquare;
import suicideChess.SuicideProblems.NoSuchSuicideProblem;
/**
* Main file (the game in itself)
@ -33,7 +36,7 @@ public class SuicideChess {
/**
* The name to be displayed
*/
public static final String NAME = "djib's SuShi v0.5.5";
public static final String NAME = "djib's SuShi v0.6.9";
/**
* Displays informations in the console.
@ -51,13 +54,16 @@ public class SuicideChess {
* @return True or False
*/
private static boolean testWinningPosition (Board bitboard) {
private static boolean testAndDisplayIfWinningOrDrawPosition (Board bitboard) {
if (bitboard.getBoardValue()==Board.BLACK_WINS) {
System.out.println("0-1 {Black mates}");
return true;
} else if (bitboard.getBoardValue()==Board.WHITE_WINS) {
System.out.println("1-0 {White mates}");
return true;
} else if (bitboard.isADraw()) {
System.out.println("1/2-1/2 {Draw}");
return true;
}
return false;
}
@ -134,164 +140,184 @@ public class SuicideChess {
try {
String whatMove= moveInput.readLine();
boolean playedALegalMove = false;
int xBoardCommand = XBoardProtocol.getCommand(whatMove);
switch (xBoardCommand) {
case XBoardProtocol.XBOARD:
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.ACCEPTED_USERMOVE:
acceptedUsermove=true;
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.HINT:
System.out.println("Hint: "+ComputerPlayer.doRandomMove(bitboard));
break;
case XBoardProtocol.FORCE:
computerPlaying = false;
break;
case XBoardProtocol.PING:
System.out.println("pong "+whatMove.substring(5));
break;
case XBoardProtocol.REMOVE:
removePlayedPosition();
//no break here
case XBoardProtocol.UNDO:
bitboard=new Board(removePlayedPosition());
if (ASCII_GAME) {
bitboard.display();
}
break;
case XBoardProtocol.POST:
post=true;
break;
case XBoardProtocol.NOPOST:
post=false;
break;
case XBoardProtocol.SETBOARD:
bitboard=new Board(whatMove.substring(9));
if(ASCII_GAME)
bitboard.display();
break;
case XBoardProtocol.UNKNOWN:
if (acceptedUsermove) {
System.out.println("Error (unknown command): "+whatMove);
break;
}
//if XBoard did not accept usermove command we try and interpret every unknown command
//as a move.
case XBoardProtocol.MOVE:
Move theMove;
if (acceptedUsermove) {
theMove = new Move(whatMove.substring(9), bitboard);
if (whatMove.startsWith("problem")) { //special case for problems
if(whatMove.length()==7) {
System.out.println("There are "+SuicideProblems.numberOfProblems()+" problems.");
} else if (whatMove.substring(8).equals("auto")) {
autoProblem();
} else if ((whatMove.length()>=12)&&(whatMove.substring(8,12).equals("load"))) {
SuicideProblems.suicideProblemsLoad(whatMove.substring(13));
} else {
theMove = new Move(whatMove, bitboard);
try {
int problemNb = Integer.parseInt(whatMove.substring(8));
bitboard=new Board(SuicideProblems.getProblemNumber(problemNb));
if(ASCII_GAME)
bitboard.display();
} catch (NumberFormatException e) {
System.out.println("Not a valid number: "+ whatMove.substring(8));
}
}
} else {
int xBoardCommand = XBoardProtocol.getCommand(whatMove);
if (testWinningPosition(bitboard)) {
//if board was set in an illegal position
System.out.println("Illegal move: "+theMove.toString());
switch (xBoardCommand) {
case XBoardProtocol.XBOARD:
break;
}
boolean needToCapture = false;
int foundMoveIndex = -1;
if(theMove.getMovingPiece().getColor() == bitboard.getCurrentPlayer()) {
Rules.legalMovesForPlayer(bitboard);
ArrayList<Move> allLegalMoves = Rules.getLegalMovesCapture();
if (allLegalMoves.size()==0) {
allLegalMoves = Rules.getLegalMovesNonCapture();
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.ACCEPTED_USERMOVE:
acceptedUsermove=true;
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.HINT:
System.out.println("Hint: "+ComputerPlayer.doRandomMove(bitboard));
break;
case XBoardProtocol.FORCE:
computerPlaying = false;
break;
case XBoardProtocol.PING:
System.out.println("pong "+whatMove.substring(5));
break;
case XBoardProtocol.REMOVE:
removePlayedPosition();
//no break here
case XBoardProtocol.UNDO:
bitboard=new Board(removePlayedPosition());
if (ASCII_GAME) {
bitboard.display();
}
break;
case XBoardProtocol.POST:
post=true;
break;
case XBoardProtocol.NOPOST:
post=false;
break;
case XBoardProtocol.SETBOARD:
bitboard=new Board(whatMove.substring(9));
if(ASCII_GAME)
bitboard.display();
break;
case XBoardProtocol.UNKNOWN:
if (acceptedUsermove) {
System.out.println("Error (unknown command): "+whatMove);
break;
}
//if XBoard did not accept usermove command we try and interpret every unknown command
//as a move.
case XBoardProtocol.MOVE:
Move theMove;
if (acceptedUsermove) {
theMove = new Move(whatMove.substring(9), bitboard);
} else {
needToCapture = true;
theMove = new Move(whatMove, bitboard);
}
for (int moveIndex = 0; moveIndex < allLegalMoves.size(); moveIndex++) {
if (allLegalMoves.get(moveIndex).isSimpleEqual(theMove)) {
if(theMove.isPromotionMove()&&
theMove.getPromotionPiece().getPieceNumber()!=allLegalMoves.get(moveIndex).getPromotionPiece().getPieceNumber()) {
continue;
}
foundMoveIndex=moveIndex;
break;
}
}
if (foundMoveIndex == -1) {
if (needToCapture) {
if (ASCII_GAME)
System.out.println("Capturing is mandatory.");
}
if (testAndDisplayIfWinningOrDrawPosition(bitboard)) {
//if board was set in an illegal position
System.out.println("Illegal move: "+theMove.toString());
break;
}
boolean needToCapture = false;
int foundMoveIndex = -1;
if(theMove.getMovingPiece().getColor() == bitboard.getCurrentPlayer()) {
Rules.legalMovesForPlayer(bitboard);
ArrayList<Move> allLegalMoves = Rules.getLegalMovesCapture();
if (allLegalMoves.size()==0) {
allLegalMoves = Rules.getLegalMovesNonCapture();
} else {
needToCapture = true;
}
for (int moveIndex = 0; moveIndex < allLegalMoves.size(); moveIndex++) {
if (allLegalMoves.get(moveIndex).isSimpleEqual(theMove)) {
if(theMove.isPromotionMove()&&
theMove.getPromotionPiece().getPieceNumber()!=allLegalMoves.get(moveIndex).getPromotionPiece().getPieceNumber()) {
continue;
}
foundMoveIndex=moveIndex;
break;
}
}
if (foundMoveIndex == -1) {
if (needToCapture) {
if (ASCII_GAME)
System.out.println("Capturing is mandatory.");
}
System.out.println("Illegal move: "+theMove.toString());
} else {
bitboard.doMove(allLegalMoves.get(foundMoveIndex));
addPlayedPosition(bitboard);
if (ASCII_GAME) {
allLegalMoves.get(foundMoveIndex).display();
System.out.println("Board value: "+bitboard.getBoardValue());
bitboard.display();
}
playedALegalMove=true;
}
} else {
bitboard.doMove(allLegalMoves.get(foundMoveIndex));
addPlayedPosition(bitboard);
if (ASCII_GAME)
System.out.println("Please play a piece of the right color.");
System.out.println("Illegal move: "+theMove.toString());
}
if (testAndDisplayIfWinningOrDrawPosition(bitboard)) {
computerPlaying=false;
}
if (!playedALegalMove) {
break;
}
//No break statement here on purpose.
case XBoardProtocol.GO:
//this is not really nice but it avoids having to write twice the code
//I check if I did really receive a XBoardProtocol.GO or it I just got there
//because there is no break statement.
if (xBoardCommand==XBoardProtocol.GO)
computerPlaying = true;
if (testAndDisplayIfWinningOrDrawPosition(bitboard)) {
//in case an illegal position have been sent
computerPlaying=false;
break;
}
if (computerPlaying) {
Move computerMove = ComputerPlayer.doAlphaBetaMove(bitboard);
bitboard.doMove(computerMove);
addPlayedPosition(bitboard);
XBoardProtocol.doMove(computerMove);
if (ASCII_GAME) {
allLegalMoves.get(foundMoveIndex).display();
computerMove.display();
System.out.println("Board value: "+bitboard.getBoardValue());
bitboard.display();
}
playedALegalMove=true;
}
if (testAndDisplayIfWinningOrDrawPosition(bitboard)) {
computerPlaying=false;
}
} else {
if (ASCII_GAME)
System.out.println("Please play a piece of the right color.");
System.out.println("Illegal move: "+theMove.toString());
}
if (testWinningPosition(bitboard)) {
computerPlaying=false;
}
if (!playedALegalMove) {
break;
}
//No break statement here on purpose.
case XBoardProtocol.GO:
//this is not really nice but it avoids having to write twice the code
//I check if I did really receive a XBoardProtocol.GO or it I just got there
//because there is no break statement.
if (xBoardCommand==XBoardProtocol.GO)
computerPlaying = true;
if (testWinningPosition(bitboard)) {
//in case an illegal position have been sent
computerPlaying=false;
break;
}
if (computerPlaying) {
Move computerMove = ComputerPlayer.doAlphaBetaMove(bitboard);
bitboard.doMove(computerMove);
addPlayedPosition(bitboard);
XBoardProtocol.doMove(computerMove);
if (ASCII_GAME) {
computerMove.display();
System.out.println("Board value: "+bitboard.getBoardValue());
bitboard.display();
}
}
if (testWinningPosition(bitboard)) {
computerPlaying=false;
}
break;
}
// if (whatMove.startsWith("hint")) {
@ -330,10 +356,39 @@ public class SuicideChess {
} catch (NotAValidSquare err) {
System.out.println(err);
continue;
} catch (NoSuchSuicideProblem err) {
System.out.println(err);
continue;
} catch (Exception e) {
e.printStackTrace();
break;
}
}
}
}
//lets the computer try every problem and stop on error.
//in the end it says what games where lost by white.
private static void autoProblem() throws NotAValidSquare, UnableToParseFENStringException, NoPieceOnSquare, NoSuchSuicideProblem {
Board bitboard;
boolean[] result=new boolean[SuicideProblems.numberOfProblems()];
for(int i=1; i<=SuicideProblems.numberOfProblems(); i++) {
System.out.println("\n\nProblem "+i);
bitboard=new Board(SuicideProblems.getProblemNumber(i));
while(!testAndDisplayIfWinningOrDrawPosition(bitboard)) {
Move computerMove = ComputerPlayer.doAlphaBetaMove(bitboard);
bitboard.doMove(computerMove);
}
if (bitboard.getCurrentPlayer()==Piece.BLACK) {
result[i-1]=false;
} else {
result[i-1]=true;
}
}
System.out.println("\n\nLost following games:\n========begin========");
for(int i=1; i<=SuicideProblems.numberOfProblems(); i++) {
if (!result[i-1])
System.out.println("Problem "+i+" lost !");
}
System.out.println("=========end=========");
}
}

View File

@ -0,0 +1,89 @@
package suicideChess;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class SuicideProblems {
/**
* This class is used to load problems from a file
*
* @author Jean-Baptiste H&eacute;tier
* @version $LastChangedRevision$, $LastChangedDate$
*
*/
@SuppressWarnings("serial")
public static class NoSuchSuicideProblem extends Exception {
NoSuchSuicideProblem(String s) { super(s); };
}
//This array can hold setup for different problems.
private static String[] suicideProblems;
static { suicideProblemsLoad("problems"); } //initialise with file 'problems' if found in current directory
/**
* How many problems are loaded
*/
public static int numberOfProblems() {
if (suicideProblems[0].equals("")) {
return 0;
} else {
return suicideProblems.length;
}
}
/**
* Return FEN notation string for given problem number
* @param problemNb
* @throws NoSuchSuicideProblem
*/
public static String getProblemNumber(int problemNb) throws NoSuchSuicideProblem {
if ((problemNb > numberOfProblems())||(problemNb<1)) {
throw new NoSuchSuicideProblem("*** Invalid Entry: "+problemNb+" ***");
}
return suicideProblems[problemNb-1];
}
/**
* This function is used to load other problem files
* @param file
*/
public static void suicideProblemsLoad(String file) {
StringBuffer problemBuffer = new StringBuffer();
//declared here only to make visible to finally clause
BufferedReader problemReader = null;
try {
problemReader = new BufferedReader(new FileReader(file));
String line = null; //not declared within while loop
while ((line = problemReader.readLine()) != null) {
if (!line.startsWith("#")) { //ignore lines starting with # (comments)
problemBuffer.append(line);
problemBuffer.append("\n"); //I will then use this symbol to break the buffer in an array
}
}
}
catch (FileNotFoundException e) {
System.out.println("File '"+file+"' not found. Problems won't be available.");
}
catch (IOException e){
System.out.println("Error reading file '"+file+"'.");
}
finally {
try {
if (problemReader!= null) {
problemReader.close();
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
suicideProblems = problemBuffer.toString().split("\n");
System.out.println(numberOfProblems()+" loaded");
}
}