Search code examples
javaenumsbit-manipulationchess

Bitwise operations on Java Enumerations; RE: Chess E.G


If I were keeping an array in C representing a chess board, I might fill it with enumed items that roughly look like:

enum CHESSPIECE {
  none  = 0,
  pawn, knight, bishop, rook, queen, king,
  type_mask = 7,
  white = 8,
  white_pawn, white_knight, white_bishop, white_rook, white_queen, white_king,
  black = 16,
  black_pawn, black_kight, black_bishop, black_rook, black_queen, black_king,
  color_mask = 24
} chessPiece;

Thus allowing logic that looks like:

if (board[i][j] & color_mask == currentColor)
{
  impossibleMove = true; // or some-such
}

In Java, I'd just find that bitwise & operations on enums are not supported, and that further, the fairly awesome EnumSet doesn't easily apply since a piece can't be black AND white AND a rook AND a king.

So what I'm thinking looks like:

public enum ChessPieceId {
    None            (null, null),
    Pawn            (null, null),
    Knight          (null, null),
    Bishop          (null, null),
    Rook            (null, null),
    Queen           (null, null),
    King            (null, null),
    Type_Mask       (null, null),
    White           (null, null),
    White_Pawn      (ChessPieceId.White, ChessPieceId.Pawn),
    White_Knight    (ChessPieceId.White, ChessPieceId.Knight),
    White_Bishop    (ChessPieceId.White, ChessPieceId.Bishop),
    White_Rook      (ChessPieceId.White, ChessPieceId.Rook),
    White_Queen     (ChessPieceId.White, ChessPieceId.Queen),
    White_King      (ChessPieceId.White, ChessPieceId.King),
    SkipA           (null, null),
    Black           (null, null),
    Black_Pawn      (ChessPieceId.Black, ChessPieceId.Pawn),
    Black_Knight    (ChessPieceId.Black, ChessPieceId.Knight),
    Black_Bishop    (ChessPieceId.Black, ChessPieceId.Bishop),
    Black_Rook      (ChessPieceId.Black, ChessPieceId.Rook),
    Black_Queen     (ChessPieceId.Black, ChessPieceId.Queen),
    Black_King      (ChessPieceId.Black, ChessPieceId.King),
    SkipB           (null, null),
    Color_Mask      (null, null);

    private final ChessPieceId color;
    private final ChessPieceId type;

    ChessPieceId(ChessPieceId pColor, ChessPieceId pType){
        this.color = pColor;
        this.type = pType;
    }

    ChessPieceId color() { return color; }
    ChessPieceId type() { return type; }

    // & operator should be built in. I considered an EnumSet but...
    ChessPieceId and(ChessPieceId pSecond) {
        switch(ChessPieceId.this.ordinal() & pSecond.ordinal()) {
        case 0: //None.ordinal() etc. [if only Java were smarter]
            return None;
        case 1:  return Pawn;
        case 2:  return Knight;
        case 3:  return Bishop;
        case 4:  return Rook;
        case 5:  return Queen;
        case 6:  return King;
        case 7:  return Type_Mask;
        case 8:  return White;
        case 9:  return White_Pawn;
        case 10: return White_Knight;
        case 11: return White_Rook;
        case 12: return White_Bishop;
        case 13: return White_Queen;
        case 14: return White_King;
        //case 15: return SkipA;
        case 16: return Black;
        case 17: return Black_Pawn;
        case 18: return Black_Knight;
        case 19: return Black_Rook;
        case 20: return Black_Bishop;
        case 21: return Black_Queen;
        case 22: return Black_King;
        //case 23: return SkipB;
        case 24: return Color_Mask;
        default:
            return None;
        }
    }
}

Clearly I only need one or the other (the and operation, or the initialized values). Also it sure would be great if I could use an enum type in it's own definition, but I can't. So lines like:

    Bishop          (null, ChessPieceId.Bishop),
    ...
    White           (ChessPieceId.White, null),

Are out.

What was my question? Is there a better way that I'm missing. Also can I parse an int of the ordinal into an enum defined value, avoiding that whole case statement?


Solution

  • In the Card example in the Sun tutorial on Enums, they represent a deck of cards as two Enums - Rank and Suit. This is isomorphic to your problem. See http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html.

    Note that you can augment an Enum with any extra values you like by defining an appropriate constructor, so you are not bound to ordinal values, either.