// deep copy constructor public PiecePositions(PiecePositions source) { _Pawns = source._Pawns; _Knights = source._Knights; _Bishops = source._Bishops; _Rooks = source.Rooks; _Queens = source._Queens; _Kings = source._Kings; Black = new Player(this); Black.All = source.Black.All; White = new Player(this); White.All = source.White.All; Black.Opponent = White; White.Opponent = Black; }
// create a board with a FEN string public Board(string fen) { Match Match = FenParser.Match(fen); if (!Match.Success) { throw new ArgumentException(string.Format("invalid FEN string \"{0}\"", fen)); } // piece placement string Field = Match.Groups[1].Value; string[] RankPlacement = Field.Split('/'); BoardAddress Location; int File; Pieces = new PiecePositions(); for (int rank = 0; rank < 8; rank++) { File = 0; foreach (char c in RankPlacement[7 - rank]) { Location = new BoardAddress((char)('a' + File), rank); switch (c) { case 'p': Pieces.Black.Pawns |= Location.Position; break; case 'P': Pieces.White.Pawns |= Location.Position; break; case 'n': Pieces.Black.Knights |= Location.Position; break; case 'N': Pieces.White.Knights |= Location.Position; break; case 'b': Pieces.Black.Bishops |= Location.Position; break; case 'B': Pieces.White.Bishops |= Location.Position; break; case 'r': Pieces.Black.Rooks |= Location.Position; break; case 'R': Pieces.White.Rooks |= Location.Position; break; case 'q': Pieces.Black.Queens |= Location.Position; break; case 'Q': Pieces.White.Queens |= Location.Position; break; case 'k': Pieces.Black.King |= Location.Position; break; case 'K': Pieces.White.King |= Location.Position; break; default: // num empty spaces if (!char.IsDigit(c)) { throw new ArgumentException(string.Format("invalid character \"{0}\" in piece placement field", c)); } File += c - '1'; // convert char to int break; } File++; } } // active color Field = Match.Groups[2].Value.ToLower(); if (Field == "w") { ActiveColorWhite = true; } else { ActiveColorWhite = false; } // castling availablity CastlingAvailability = new Castling(); Field = Match.Groups[3].Value; if (Field == "-") // not available { CastlingAvailability.White = Castling.Move.Disallowed; CastlingAvailability.Black = Castling.Move.Disallowed; } else // available to at least one player // check white { if (Field.Contains("K") && Field.Contains("Q")) { CastlingAvailability.White = Castling.Move.BothSides; } else if (Field.Contains("K")) { CastlingAvailability.White = Castling.Move.KingSide; } else if (Field.Contains("Q")) { CastlingAvailability.White = Castling.Move.QueenSide; } else { CastlingAvailability.White = Castling.Move.Disallowed; } // check black if (Field.Contains("k") && Field.Contains("q")) { CastlingAvailability.Black = Castling.Move.BothSides; } else if (Field.Contains("k")) { CastlingAvailability.Black = Castling.Move.KingSide; } else if (Field.Contains("q")) { CastlingAvailability.Black = Castling.Move.QueenSide; } else { CastlingAvailability.Black = Castling.Move.Disallowed; } } // enpassant location Field = Match.Groups[4].Value; if (Field == "-") { EnPassantTarget = 0; } else { EnPassantTarget = new BoardAddress(Field).Position; } // halfmove clock Field = Match.Groups[5].Value; if (!byte.TryParse(Field, out HalfMoveClock)) { throw new ArgumentException(string.Format("could not parse halfmove clock \"{0}\"", Field)); } // halfmove clock Field = Match.Groups[6].Value; if (!int.TryParse(Field, out FullMoveNumber)) { throw new ArgumentException(string.Format("could not parse full move number \"{0}\"", Field)); } }
public Player(PiecePositions p) { Parent = p; }
// create a move from ACN string and the piece positions public Move(string acn, PiecePositions pieces) { int Len = acn.Length; if (Len < 4 || Len > 5) { throw new ArgumentException(string.Format("ACN strings must be 4 or 5 characters long: \"{0}\"", acn)); } string f = acn.Substring(0, 2); string t = acn.Substring(2, 2); From = new BoardAddress(f); To = new BoardAddress(t); // determine the type of piece that is moving if ((pieces.Pawns & From.Position) != 0) { MoveType = PieceMoveType.Pawn; } else if ((pieces.Knights & From.Position) != 0) { MoveType = PieceMoveType.Knight; } else if ((pieces.Bishops & From.Position) != 0) { MoveType = PieceMoveType.Bishop; } else if ((pieces.Rooks & From.Position) != 0) { MoveType = PieceMoveType.Rook; } else if ((pieces.Queens & From.Position) != 0) { MoveType = PieceMoveType.Queen; } else if ((pieces.Kings & From.Position) != 0) { MoveType = PieceMoveType.King; } else { throw new ArgumentException(string.Format("move \"{0}\" invalid given current piece positions", acn)); } // promotion on this move? if (Len == 5) // yes { if (MoveType != PieceMoveType.Pawn) { throw new ArgumentException("tried to promote from a piece type other than pawn"); } char promo = char.ToLower(acn[4]); switch (promo) { case 'n': MoveType = PieceMoveType.PawnKnight; break; case 'b': MoveType = PieceMoveType.PawnBishop; break; case 'r': MoveType = PieceMoveType.PawnRook; break; case 'q': MoveType = PieceMoveType.PawnQueen; break; default: throw new ArgumentException(string.Format("ACN string contains invalid promotion character \"{0}\"", promo)); } } }