1
\$\begingroup\$

I'm coding a checkers game and I encountered a problem and I'm 99% sure is about how the move is done and taken back. The structure of my game data is:

  • an 8x8 array containing my board squares. Every square knows if it's occupied by a pawn.
  • an ArrayList with 24 pawns, that are removed when jumped by another pawn.
  • an array with legalMoves of a single player. The function that fills this array is called every change of turn.

The problem pops out only when playing with the IA, that is a simple negamax function with static evaluation (but I'm pretty sure the IA algorithm is correct).

Sometimes (not always), when player1 or CPU can make kings, the negamax algorithm begin to loop infinitelly. The output for the score of the evaluated move is illogically high. I think this is due to the make and take move I wrote, something concerning the setBusy of the board, because it happens also that I cannot move a piece on a free square.

Is it a problem with creating and destroying kings? I can't figure it out.

Here's my code for move handling:

public void makeMove(Move move, ArrayList<Pawn> pawns, Board[][]board) {
    if(move.getIntermediatePos().isEmpty()){
        makeMove(move.getxInit(), move.getyInit(), move.getxDest(), move.getyDest(), pawns, board);
    } else {
        for(int[] i: move.getIntermediatePos()){
            Move tempMove = new Move(move);
            makeMove(tempMove.getxInit(), tempMove.getyInit(), i[0], i[1], pawns, board);
            tempMove.setxInit(i[0]);
            tempMove.setyInit(i[1]);
            tempMove.getIntermediatePos().remove(0);
            makeMove(tempMove, pawns, board);
        }
    }
}
//If the move is a jump (single or multiple), the method getIntermediatePos returns all the squares 
//the pawn has been on, so I can keep track of eaten pawns; i[0] is the x, i[1] is the y

public void takeMove(Move move, ArrayList<Panw> pawns, Board[][] board){

    if(move.getIntermediatePos().isEmpty()){
        takeMove(move.getxDest(), move.getyDest(), move.getxInit(), move.getyInit(), pawns, board);
    } else {
        for(int[] i: move.getIntermediatePos()){
            Move tempMove = new Move(move);
            takeMove(tempMove.getxDest(), tempMove.getyDest(), i[0], i[1], pawns, board);
            tempMove.setxDest(i[0]);
            tempMove.setyDest(i[1]);
            tempMove.getIntermediatePos().remove(0);
            takeMove(tempMove, pawns, board);
        }
    }
}

public void takeMove(int x1, int y1, int x2, int y2, ArrayList<Pawn> pawns, Board[][] board) {

    Pawn movingPawn = getPawn(x1, y1, pawns);

    if (y1 == 0 && getPawn(x1, y1, pawns).getPlayer() == PLAYER1){
        pawns.remove(movingPawn);
        movingPawn = new Pawn(x1, y1, Color.white, PLAYER1);
        pawns.add(movingPawn);
    }
    if (y1 == 7 && getPawn(x1, y1, pawns).getPlayer() == PLAYER2){
        pawns.remove(movingPawn);
        movingPawn = new Pawn(x1, y1, Color.black, PLAYER2);
        pawns.add(movingPawn);
    }

    movingPawn.setX(x2);
    movingPawn.setY(y2);

    board[x1][y1].setBusy(false);
    board[x2][y2].setBusy(true);

    if (y1 - y2 == 2 || y1 - y2 == -2) {
        int jumpy = (y1 + y2) / 2;  
        int jumpx = (x1 + x2) / 2;  
        pawns.add(new Pawn(jumpx, jumpy, movingPawn.getPlayer() == 1 ? Color.black : Color.white, movingPawn.getPlayer() == 1 ? 2 : 1));
        board[jumpx][jumpy].setBusy(true); 
    } 
}

public void makeMove(int x1, int y1, int x2, int y2, ArrayList<Pawn> pawns, Board board[][] board) {

    Pawn movingPawn = getPawn(x1, y1, pawns);
    movingPawn.setX(x2);
    movingPawn.setY(y2);

    board[x1][y1].setBusy(false);
    board[x2][y2].setBusy(true);

    if (y1 - y2 == 2 || y1 - y2 == -2) {
        // The move is a jump.  Remove the jumped piece from the board.
        int jumpy = (y1 + y2) / 2;  
        int jumpx = (x1 + x2) / 2;  
        pawns.remove(getPawn(jumpx, jumpy, pawns));
        board[jumpx][jumpy].setBusy(false);

    }
    if (y2 == 0 && getPawn(x2, y2, pawns).getPlayer() == PLAYER1){
        pawns.remove(movingPawn);
        pawns.add(new King(x2, y2, Color.white, PLAYER1));
    }
    if (y2 == 7 && getPawn(x2, y2, pawns).getPlayer() == PLAYER2){
        pawns.remove(movingPawn);
        pawns.add(new King(x2, y2, Color.black, PLAYER2));
    }
}

EDIT: Passing as argument also the board seems to fix the problem of having some moves the player can't do because a false-occupied square.

\$\endgroup\$
  • \$\begingroup\$ Not a direct response to your 'takeMove', but your structures themselves seem a little bit suspect to me, and the interface to your functions only reemphasize that. You're passing around the list of Pawns, but not the game board itself; at the very least, the entirety of your board state (both the array, and the list of pieces if you feel you need that list) should be passed around to these functions, for encapsulation purposes. But I'd question whether you need to 'take back' moves at all; instead, just maintain a stack of board positions. Then 'taking back' a move is just popping stack. \$\endgroup\$ – Steven Stadnicki Apr 22 '14 at 23:10
  • \$\begingroup\$ Your suggestion of having the board passed as argument fixed only having false-positive squares on which a pawn could not be moved on. The real problem now is that I think my negamax algorithm does not recognize properly created kings, because scores are strange in that case. I dunno if this is an issue with the negamax function or the make-and-take-move thing. Tried also with a stack of Board positions to keep track of movements but with no luck. \$\endgroup\$ – spellz Apr 23 '14 at 11:38
  • \$\begingroup\$ Could you help me to implement the stack thing? \$\endgroup\$ – spellz Apr 25 '14 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.