-2

I keep receiving a null pointer exception when trying to run my chess engine. When I try to run my main method:

package com.chess.engine;

import com.chess.engine.board.Board;

public class JChess {
    public static void main(String[] args) {
        Board board = Board.setupBoard();
        
        System.out.println(board);
    }

}

I get this from the console:

Exception in thread "main" java.lang.NullPointerException
at com.chess.engine.piece.Rook.calculateLegalMoves(Rook.java:45)
at com.chess.engine.board.Board.calculateLegalMoves(Board.java:48)
at com.chess.engine.board.Board.<init>(Board.java:25)
at com.chess.engine.board.Board$Builder.build(Board.java:148)
at com.chess.engine.board.Board.setupBoard(Board.java:123)

at com.chess.engine.JChess.main([JChess.java:7](https://JChess.java:7))

Board Class

package com.chess.engine.board;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.chess.engine.Team;
import com.chess.engine.piece.*;
import com.google.common.collect.ImmutableList;

public class Board {

private final List<Tile> gameBoard;
private final Collection<Piece> whitePieces;
private final Collection<Piece> blackPieces;


private Board(Builder builder) {
    this.gameBoard = createGameBoard(builder);
    this.whitePieces = calculateActivePieces(this.gameBoard,Team.WHITE);
    this.blackPieces = calculateActivePieces(this.gameBoard,Team.BLACK);
    
    final Collection<Move> whiteStdLegalMoves = calculateLegalMoves(this.whitePieces);
    final Collection<Move> blackStdLegalMoves = calculateLegalMoves(this.blackPieces);

}

@Override
public String toString() {
    final StringBuilder builder = new StringBuilder();
    for(int i = 0; i < BoardUtils.NUM_TILES;i++) {
        final String tileText = this.gameBoard.get(i).toString();
        builder.append(String.format("%3s", tileText));
        if((i+1)% BoardUtils.NUM_TILES_PER_NOW == 0) {
            builder.append("\n");
        }
    }
    
    return builder.toString();
    
}
    
private  Collection<Move> calculateLegalMoves(Collection<Piece> pieces) {
    
    final List<Move> legalMoves = new ArrayList<>();
    
    for(final Piece piece: pieces) {
        legalMoves.addAll(piece.calculateLegalMoves(this));
    }
    
    return ImmutableList.copyOf(legalMoves);
}

private static Collection<Piece> calculateActivePieces(final List<Tile> gameBoard, Team team) {

    final List<Piece> activePieces = new ArrayList<>();
    
    for(final Tile tile : gameBoard) {
        if(tile.isTileOccupied()) {
            final Piece piece = tile.getPiece();
            if(piece.getPieceTeam() == team ) {
                activePieces.add(piece);
            }
        }
    }
    return ImmutableList.copyOf(activePieces);
}

public Tile getTile(final int tileCoordinate) {
    return null;
}

private static List<Tile> createGameBoard(final Builder builder){
    final Tile[] tiles = new Tile[BoardUtils.NUM_TILES];
    for(int i = 0; i < BoardUtils.NUM_TILES;i++) {
        tiles[i] = Tile.createTile(i, builder.boardConfig.get(i));
    }
    return ImmutableList.copyOf(tiles);
}
 
public static Board setupBoard() {
    final Builder builder = new Builder();
    
    //Blacks
    builder.setPiece(new Rook(Team.BLACK,0));
    builder.setPiece(new Knight(Team.BLACK,1));
    builder.setPiece(new Bishop(Team.BLACK,2));
    builder.setPiece(new Queen(Team.BLACK,3));
    builder.setPiece(new King(Team.BLACK,4));
    builder.setPiece(new Bishop(Team.BLACK,5));
    builder.setPiece(new Knight(Team.BLACK,6));
    builder.setPiece(new Rook(Team.BLACK,7));
    builder.setPiece(new Pawn(Team.BLACK,8));
    builder.setPiece(new Pawn(Team.BLACK,9));
    builder.setPiece(new Pawn(Team.BLACK,10));
    builder.setPiece(new Pawn(Team.BLACK,11));
    builder.setPiece(new Pawn(Team.BLACK,12));
    builder.setPiece(new Pawn(Team.BLACK,13));
    builder.setPiece(new Pawn(Team.BLACK,14));
    builder.setPiece(new Pawn(Team.BLACK,15));

    // Whites
    builder.setPiece(new Rook(Team.WHITE,48));
    builder.setPiece(new Knight(Team.WHITE,49));
    builder.setPiece(new Bishop(Team.WHITE,50));
    builder.setPiece(new Queen(Team.WHITE,51));
    builder.setPiece(new King(Team.WHITE,52));
    builder.setPiece(new Bishop(Team.WHITE,53));
    builder.setPiece(new Knight(Team.WHITE,54));
    builder.setPiece(new Rook(Team.WHITE,55));
    builder.setPiece(new Pawn(Team.WHITE,56));
    builder.setPiece(new Pawn(Team.WHITE,57));
    builder.setPiece(new Pawn(Team.WHITE,58));
    builder.setPiece(new Pawn(Team.WHITE,59));
    builder.setPiece(new Pawn(Team.WHITE,60));
    builder.setPiece(new Pawn(Team.WHITE,61));
    builder.setPiece(new Pawn(Team.WHITE,62));
    builder.setPiece(new Pawn(Team.WHITE,63));

    builder.setMoveMaker(Team.WHITE);
    
    
    return builder.build();
    
}

public static class Builder {
    
    Map<Integer,Piece> boardConfig;
    Team nextMoveMaker;
    
    public Builder() {
        this.boardConfig = new HashMap<>();
    }
    
    public Builder setPiece(final Piece piece) {
        this.boardConfig.put(piece.getPiecePosition(), piece);
        return this;
    }
    
    public Builder setMoveMaker(Team nextMoveMaker) {
        this.nextMoveMaker = nextMoveMaker;
        return this;
    }
    
    public Board build() {
        
        return new Board(this);
    }
}
}

I have been trying to figure out why I've been getting this error for hours. I checked the board constructor and the Builder class methods and constructor and have not been able to fix the error even after editing the code.

I really appreciate the help and thanks in advance.

All the code is at : https://github.com/XavierTheCreator/JavaChess

  • Stack trace points to [this line](https://github.com/XavierTheCreator/JavaChess/blob/7bb733065732165e0b0d0b7a3f715e8a5befb982/JavaChess/src/com/chess/engine/piece/Rook.java#L45), which would throw a NullPointerException when `board` is null. – dnault Jan 04 '21 at 21:03

3 Answers3

5

This is the very tippy top of your stack trace:

Exception in thread "main" java.lang.NullPointerException
at com.chess.engine.piece.Rook.calculateLegalMoves(Rook.java:45)

and yet you did not include the code for Rook.java.

I conclude that your real question is: "What is a stack trace, and how do I read it". Because surely if you know that, you wouldn't have asked this question, or you would have at least including line 45 of Rook.java!

A stack trace is to be read from top to bottom. The first line explains which exception occured (the type) and will include any message associated with it (there is no message here). Code works in a 'stack': When you write foo.someMethod(args);, then the someMethod is invoked, and when the someMethod is done, control goes back to where we left off. That means that there is a whole pile of locations in the middle of a sequence of methods that the code would jump back to every time a 'return' is printed.

That is what you are witnessing. Then, each line simply tells you where.

Thus, the NPE occurred on line 45 of Rook.java. We got to line 45 of Rook.java (which is in the calculateLegalMoves method), because line 48 of Board.java invoked that method. And so on.

If you did already know all of this, well, um, you forgot to include the only relevant line, and you did include a whole boatload of irrelevant code.

rzwitserloot
  • 65,603
  • 5
  • 38
  • 52
2

I don't see where Board.setupBoard method is being called prior to createGameBoard being called in the constructor. It appears that the former is needed in order to initialize your piece classes.

I suggest that you don't do any move calculation in a constructor. I'd move those calls to a separate method.

I tend to question using static unless the call is a pure function. But I don't know the general best practices here. I find that overuse of static, for me, tends to result in more confusing code than creating and using instances. Maybe it is fine here, IDK.

Phil Freihofner
  • 7,145
  • 1
  • 17
  • 38
0

I found where the error was happening. The code was returning null because i forgot to to return an actual value instead of null inside of the board class. As seen below:

public Tile getTile(final int tileCoordinate) {
    return null; 
}

This was located on line 69 of the board class. Thanks for your responses