public final class Castling {

	public static final int WHITE_KINGSIDE = 1; // 1 << 0
	public static final int WHITE_QUEENSIDE = 1 << 1;
	public static final int BLACK_KINGSIDE = 1 << 2;
	public static final int BLACK_QUEENSIDE = 1 << 3;

	public static final int NOCASTLING = 0;

	public static final int VALUES_LENGTH = 16;

	private Castling() {
	}

	public static int valueOf(int color, int castlingtype) {
		switch (color) {
			case WHITE:
				switch (castlingtype) {
					case KINGSIDE:
						return WHITE_KINGSIDE;
					case QUEENSIDE:
						return WHITE_QUEENSIDE;
					default:
						throw new IllegalArgumentException();
				}
			case BLACK:
				switch (castlingtype) {
					case KINGSIDE:
						return BLACK_KINGSIDE;
					case QUEENSIDE:
						return BLACK_QUEENSIDE;
					default:
						throw new IllegalArgumentException();
				}
			default:
				throw new IllegalArgumentException();
		}
	}
} public final class CastlingType {

	public static final int KINGSIDE = 0;
	public static final int QUEENSIDE = 1;

	public static final int NOCASTLINGTYPE = 2;

	public static final int[] values = {
			KINGSIDE, QUEENSIDE
	};

	private CastlingType() {
	}
} public final class Color {

	public static final int WHITE = 0;
	public static final int BLACK = 1;

	public static final int NOCOLOR = 2;

	public static final int[] values = {
			WHITE, BLACK
	};

	private Color() {
	}

	public static int opposite(int color) {
		switch (color) {
			case WHITE:
				return BLACK;
			case BLACK:
				return WHITE;
			default:
				throw new IllegalArgumentException();
		}
	}
} public final class Square {

	public static final int MASK = 0x7F;

	public static final int a1 = 0, a2 = 16;
	public static final int b1 = 1, b2 = 17;
	public static final int c1 = 2, c2 = 18;
	public static final int d1 = 3, d2 = 19;
	public static final int e1 = 4, e2 = 20;
	public static final int f1 = 5, f2 = 21;
	public static final int g1 = 6, g2 = 22;
	public static final int h1 = 7, h2 = 23;

	public static final int a3 = 32, a4 = 48;
	public static final int b3 = 33, b4 = 49;
	public static final int c3 = 34, c4 = 50;
	public static final int d3 = 35, d4 = 51;
	public static final int e3 = 36, e4 = 52;
	public static final int f3 = 37, f4 = 53;
	public static final int g3 = 38, g4 = 54;
	public static final int h3 = 39, h4 = 55;

	public static final int a5 = 64, a6 = 80;
	public static final int b5 = 65, b6 = 81;
	public static final int c5 = 66, c6 = 82;
	public static final int d5 = 67, d6 = 83;
	public static final int e5 = 68, e6 = 84;
	public static final int f5 = 69, f6 = 85;
	public static final int g5 = 70, g6 = 86;
	public static final int h5 = 71, h6 = 87;

	public static final int a7 = 96, a8 = 112;
	public static final int b7 = 97, b8 = 113;
	public static final int c7 = 98, c8 = 114;
	public static final int d7 = 99, d8 = 115;
	public static final int e7 = 100, e8 = 116;
	public static final int f7 = 101, f8 = 117;
	public static final int g7 = 102, g8 = 118;
	public static final int h7 = 103, h8 = 119;

	public static final int NOSQUARE = 127;

	public static final int VALUES_LENGTH = 128;
	public static final int[] values = {
			a1, b1, c1, d1, e1, f1, g1, h1,
			a2, b2, c2, d2, e2, f2, g2, h2,
			a3, b3, c3, d3, e3, f3, g3, h3,
			a4, b4, c4, d4, e4, f4, g4, h4,
			a5, b5, c5, d5, e5, f5, g5, h5,
			a6, b6, c6, d6, e6, f6, g6, h6,
			a7, b7, c7, d7, e7, f7, g7, h7,
			a8, b8, c8, d8, e8, f8, g8, h8
	};

	// These are our move directions
	// N = north, E = east, S = south, W = west
	public static final int N = 16;
	public static final int E = 1;
	public static final int S = -16;
	public static final int W = -1;
	public static final int NE = N + E;
	public static final int SE = S + E;
	public static final int SW = S + W;
	public static final int NW = N + W;

	public static final int[][] pawnDirections = {
			{N, NE, NW}, // Color.WHITE
			{S, SE, SW}  // Color.BLACK
	};
	public static final int[] knightDirections = {
			N + N + E,
			N + N + W,
			N + E + E,
			N + W + W,
			S + S + E,
			S + S + W,
			S + E + E,
			S + W + W
	};
	public static final int[] bishopDirections = {
			NE, NW, SE, SW
	};
	public static final int[] rookDirections = {
			N, E, S, W
	};
	public static final int[] queenDirections = {
			N, E, S, W,
			NE, NW, SE, SW
	};
	public static final int[] kingDirections = {
			N, E, S, W,
			NE, NW, SE, SW
	};

	private Square() {
	}

	public static boolean isValid(int square) {
		return (square & 0x88) == 0;
	}

	public static int valueOf(int file, int rank) {
		return (rank << 4) + file;
	}

	public static int getFile(int square) {
		return square & 0xF;
	}

	public static int getRank(int square) {
		return square >>> 4;
	}
} public final class Castling {

	public static final int WHITE_KINGSIDE = 1; // 1 << 0
	public static final int WHITE_QUEENSIDE = 1 << 1;
	public static final int BLACK_KINGSIDE = 1 << 2;
	public static final int BLACK_QUEENSIDE = 1 << 3;

	public static final int NOCASTLING = 0;

	public static final int VALUES_LENGTH = 16;

	private Castling() {
	}

	public static int valueOf(int color, int castlingtype) {
		switch (color) {
			case WHITE:
				switch (castlingtype) {
					case KINGSIDE:
						return WHITE_KINGSIDE;
					case QUEENSIDE:
						return WHITE_QUEENSIDE;
					default:
						throw new IllegalArgumentException();
				}
			case BLACK:
				switch (castlingtype) {
					case KINGSIDE:
						return BLACK_KINGSIDE;
					case QUEENSIDE:
						return BLACK_QUEENSIDE;
					default:
						throw new IllegalArgumentException();
				}
			default:
				throw new IllegalArgumentException();
		}
	}
} public final class CastlingType {

	public static final int KINGSIDE = 0;
	public static final int QUEENSIDE = 1;

	public static final int NOCASTLINGTYPE = 2;

	public static final int[] values = {
			KINGSIDE, QUEENSIDE
	};

	private CastlingType() {
	}
} public final class Color {

	public static final int WHITE = 0;
	public static final int BLACK = 1;

	public static final int NOCOLOR = 2;

	public static final int[] values = {
			WHITE, BLACK
	};

	private Color() {
	}

	public static int opposite(int color) {
		switch (color) {
			case WHITE:
				return BLACK;
			case BLACK:
				return WHITE;
			default:
				throw new IllegalArgumentException();
		}
	}
} public final class File {

	public static final int a = 0;
	public static final int b = 1;
	public static final int c = 2;
	public static final int d = 3;
	public static final int e = 4;
	public static final int f = 5;
	public static final int g = 6;
	public static final int h = 7;

	public static final int NOFILE = 8;

	public static final int[] values = {
			a, b, c, d, e, f, g, h
	};

	private File() {
	}
} public final class Piece {

	public static final int MASK = 0x1F;

	public static final int WHITE_PAWN = 0;
	public static final int WHITE_KNIGHT = 1;
	public static final int WHITE_BISHOP = 2;
	public static final int WHITE_ROOK = 3;
	public static final int WHITE_QUEEN = 4;
	public static final int WHITE_KING = 5;
	public static final int BLACK_PAWN = 6;
	public static final int BLACK_KNIGHT = 7;
	public static final int BLACK_BISHOP = 8;
	public static final int BLACK_ROOK = 9;
	public static final int BLACK_QUEEN = 10;
	public static final int BLACK_KING = 11;

	public static final int NOPIECE = 12;

	public static final int[] values = {
			WHITE_PAWN, WHITE_KNIGHT, WHITE_BISHOP, WHITE_ROOK, WHITE_QUEEN, WHITE_KING,
			BLACK_PAWN, BLACK_KNIGHT, BLACK_BISHOP, BLACK_ROOK, BLACK_QUEEN, BLACK_KING
	};

	private Piece() {
	}

	public static boolean isValid(int piece) {
		switch (piece) {
			case WHITE_PAWN:
			case WHITE_KNIGHT:
			case WHITE_BISHOP:
			case WHITE_ROOK:
			case WHITE_QUEEN:
			case WHITE_KING:
			case BLACK_PAWN:
			case BLACK_KNIGHT:
			case BLACK_BISHOP:
			case BLACK_ROOK:
			case BLACK_QUEEN:
			case BLACK_KING:
				return true;
			default:
				return false;
		}
	}

	public static int valueOf(int color, int piecetype) {
		switch (color) {
			case WHITE:
				switch (piecetype) {
					case PAWN:
						return WHITE_PAWN;
					case KNIGHT:
						return WHITE_KNIGHT;
					case BISHOP:
						return WHITE_BISHOP;
					case ROOK:
						return WHITE_ROOK;
					case QUEEN:
						return WHITE_QUEEN;
					case KING:
						return WHITE_KING;
					default:
						throw new IllegalArgumentException();
				}
			case BLACK:
				switch (piecetype) {
					case PAWN:
						return BLACK_PAWN;
					case KNIGHT:
						return BLACK_KNIGHT;
					case BISHOP:
						return BLACK_BISHOP;
					case ROOK:
						return BLACK_ROOK;
					case QUEEN:
						return BLACK_QUEEN;
					case KING:
						return BLACK_KING;
					default:
						throw new IllegalArgumentException();
				}
			default:
				throw new IllegalArgumentException();
		}
	}

	public static int getType(int piece) {
		switch (piece) {
			case WHITE_PAWN:
			case BLACK_PAWN:
				return PAWN;
			case WHITE_KNIGHT:
			case BLACK_KNIGHT:
				return KNIGHT;
			case WHITE_BISHOP:
			case BLACK_BISHOP:
				return BISHOP;
			case WHITE_ROOK:
			case BLACK_ROOK:
				return ROOK;
			case WHITE_QUEEN:
			case BLACK_QUEEN:
				return QUEEN;
			case WHITE_KING:
			case BLACK_KING:
				return KING;
			default:
				throw new IllegalArgumentException();
		}
	}

	public static int getColor(int piece) {
		switch (piece) {
			case WHITE_PAWN:
			case WHITE_KNIGHT:
			case WHITE_BISHOP:
			case WHITE_ROOK:
			case WHITE_QUEEN:
			case WHITE_KING:
				return WHITE;
			case BLACK_PAWN:
			case BLACK_KNIGHT:
			case BLACK_BISHOP:
			case BLACK_ROOK:
			case BLACK_QUEEN:
			case BLACK_KING:
				return BLACK;
			default:
				throw new IllegalArgumentException();
		}
	}
} public final class PieceType {

	public static final int MASK = 0x7;

	public static final int PAWN = 0;
	public static final int KNIGHT = 1;
	public static final int BISHOP = 2;
	public static final int ROOK = 3;
	public static final int QUEEN = 4;
	public static final int KING = 5;

	public static final int NOPIECETYPE = 6;

	public static final int[] values = {
			PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING
	};

	// Piece values as defined by Larry Kaufman
	public static final int PAWN_VALUE = 100;
	public static final int KNIGHT_VALUE = 325;
	public static final int BISHOP_VALUE = 325;
	public static final int ROOK_VALUE = 500;
	public static final int QUEEN_VALUE = 975;
	public static final int KING_VALUE = 20000;

	private PieceType() {
	}

	public static boolean isValidPromotion(int piecetype) {
		switch (piecetype) {
			case KNIGHT:
			case BISHOP:
			case ROOK:
			case QUEEN:
				return true;
			default:
				return false;
		}
	}

	public static boolean isSliding(int piecetype) {
		switch (piecetype) {
			case BISHOP:
			case ROOK:
			case QUEEN:
				return true;
			case PAWN:
			case KNIGHT:
			case KING:
				return false;
			default:
				throw new IllegalArgumentException();
		}
	}

	public static int getValue(int piecetype) {
		switch (piecetype) {
			case PAWN:
				return PAWN_VALUE;
			case KNIGHT:
				return KNIGHT_VALUE;
			case BISHOP:
				return BISHOP_VALUE;
			case ROOK:
				return ROOK_VALUE;
			case QUEEN:
				return QUEEN_VALUE;
			case KING:
				return KING_VALUE;
			default:
				throw new IllegalArgumentException();
		}
	}
} public final class Rank {

	public static final int r1 = 0;
	public static final int r2 = 1;
	public static final int r3 = 2;
	public static final int r4 = 3;
	public static final int r5 = 4;
	public static final int r6 = 5;
	public static final int r7 = 6;
	public static final int r8 = 7;

	public static final int NORANK = 8;

	public static final int[] values = {
			r1, r2, r3, r4, r5, r6, r7, r8
	};

	private Rank() {
	}
} public static final int NOSQUARE = 127;
import com.fluxchess.jcpi.models.*;
import com.fluxchess.pulse.model.Castling;
import com.fluxchess.pulse.model.CastlingType;
import com.fluxchess.pulse.model.Color;
import com.fluxchess.pulse.model.Square;
import static com.fluxchess.pulse.model.Castling.*;
import static com.fluxchess.pulse.model.CastlingType.*;
import static com.fluxchess.pulse.model.Color.*;
import static com.fluxchess.pulse.model.File.*;
import static com.fluxchess.pulse.model.Piece.*;
import static com.fluxchess.pulse.model.PieceType.*;
import static com.fluxchess.pulse.model.Rank.*;
import static com.fluxchess.pulse.model.Square.NOSQUARE;
/*
 * Copyright 2013-2021 Phokham Nonava
 *
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */
package com.fluxchess.pulse;



final class Notation {

	static final String STANDARDPOSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";

	private Notation() {
	}

	static Position toPosition(String fen) {
		try {
			return toPosition(new GenericBoard(fen));
		} catch (IllegalNotationException e) {
			throw new IllegalArgumentException(e);
		}
	}

	static String fromPosition(Position position) {
		return toGenericBoard(position).toString();
	}

	static Position toPosition(GenericBoard genericBoard) {
		Position newPosition = new Position();

		// Initialize board
		for (int square : Square.values) {
			GenericPiece genericPiece = genericBoard.getPiece(fromSquare(square));
			if (genericPiece != null) {
				int piece = toPiece(genericPiece);
				newPosition.put(piece, square);
			}
		}

		// Initialize active color
		newPosition.setActiveColor(toColor(genericBoard.getActiveColor()));

		// Initialize castling
		for (int color : Color.values) {
			for (int castlingtype : CastlingType.values) {
				GenericFile genericFile = genericBoard.getCastling(
						fromColor(color), fromCastlingType(castlingtype)
				);
				if (genericFile != null) {
					newPosition.setCastlingRight(Castling.valueOf(color, castlingtype));
				}
			}
		}

		// Initialize en passant
		if (genericBoard.getEnPassant() != null) {
			newPosition.setEnPassantSquare(toSquare(genericBoard.getEnPassant()));
		}

		// Initialize half move clock
		newPosition.setHalfmoveClock(genericBoard.getHalfMoveClock());

		// Initialize the full move number
		newPosition.setFullmoveNumber(genericBoard.getFullMoveNumber());

		return newPosition;
	}

	static GenericBoard toGenericBoard(Position position) {
		GenericBoard genericBoard = new GenericBoard();

		// Set board
		for (int square : Square.values) {
			if (position.board[square] != NOPIECE) {
				genericBoard.setPiece(fromPiece(position.board[square]), fromSquare(square));
			}
		}

		// Set castling
		if ((position.castlingRights & WHITE_KINGSIDE) != NOCASTLING) {
			genericBoard.setCastling(
					fromColor(WHITE), fromCastlingType(KINGSIDE),
					fromFile(h)
			);
		}
		if ((position.castlingRights & WHITE_QUEENSIDE) != NOCASTLING) {
			genericBoard.setCastling(
					fromColor(WHITE), fromCastlingType(QUEENSIDE),
					fromFile(a)
			);
		}
		if ((position.castlingRights & BLACK_KINGSIDE) != NOCASTLING) {
			genericBoard.setCastling(
					fromColor(BLACK), fromCastlingType(KINGSIDE),
					fromFile(h)
			);
		}
		if ((position.castlingRights & BLACK_QUEENSIDE) != NOCASTLING) {
			genericBoard.setCastling(
					fromColor(BLACK), fromCastlingType(QUEENSIDE),
					fromFile(a)
			);
		}

		// Set en passant
		if (position.enPassantSquare != NOSQUARE) {