public Bitboard GetCapturesMoveBoard(Bitboard notblockers, Bitboard enemies, Square? enpassant) { if (enpassant != null) enemies &= new Bitboard().And((Square)enpassant); var bleft = Locations.Except(new File(0)).Shift(1, -1).Intersect(enemies); var bright = Locations.Except(new File(7)).Shift(1, 1).Intersect(enemies); return bleft | bright; }
public IEnumerable<Move> GetAllMoves( Bitboard notblockers, Bitboard enemies, Square? enpassant ) { return GetMovesOneSquareForward(notblockers) .Union(GetMovesTwoSquaresForward(notblockers)) .Union(GetCaptures(enemies, enpassant)); }
public Bitboard GetMoveBoard(Square from, Bitboard friends, Bitboard enemies) { var allpieces = friends.And(enemies); var result = Bitboard.Empty.And(from.File, from.Rank); return result.Except(from, friends, from.RayTo.N.Intersect(allpieces).LowestSquare.RayTo.N, from.RayTo.E.Intersect(allpieces).LowestSquare.RayTo.E, from.RayTo.S.Intersect(allpieces).HighestSquare.RayTo.S, from.RayTo.W.Intersect(allpieces).HighestSquare.RayTo.W); }
public IEnumerable<Move> GetCaptures(Bitboard enemies, Bitboard filterFrom, Bitboard filterTo, Square? enpassant = null) { if (enpassant != null) enemies |= new Bitboard().And((Square) enpassant); enemies &= filterTo; Bitboard l = Locations.Intersect(filterFrom); Bitboard bleft = l.Except(new File(7)).Shift(-1, +1).Intersect(enemies); Bitboard bright = l.Except(new File(0)).Shift(-1, -1).Intersect(enemies); return GetMoves(bleft, 7).Union(GetMoves(bright, 9)); }
public Bitboard GetMoveBoard(Bitboard notblockers, Bitboard enemies, Square? enpassant) { ulong onesquarforward = (Locations >> 8 & notblockers); Bitboard twosquaresforward = Locations .Intersect(new Rank(6)) .Shift(-1, 0).Intersect(notblockers) .Shift(-1, 0).Intersect(notblockers); return onesquarforward | twosquaresforward | GetCapturesMoveBoard(notblockers, enemies, enpassant); }
public Bitboard Get(Square from, Bitboard friends, Bitboard enemies ) { var allpieces = friends.And(enemies); var result = Bitboard.Empty.And(from.DiagonalNW, from.DiagonalNE); return result.Except(from, friends, from.RayTo.NE.Intersect(allpieces).LowestSquare.RayTo.NE, from.RayTo.NW.Intersect(allpieces).LowestSquare.RayTo.NW, from.RayTo.SE.Intersect(allpieces).HighestSquare.RayTo.SE, from.RayTo.SW.Intersect(allpieces).HighestSquare.RayTo.SW); }
public static bool checkBB(Bitboard samebb, Bitboard dirbb, Square sq) => (dirbb.IsSet(sq) && (samebb & dirbb).IsOne());
public BlackPawns(Bitboard locations) : this() { Locations = locations; }
/// <summary> /// Calculates move specified in the derived class. /// </summary> /// <param name="bitboard">The bitboard.</param> public abstract void CalculateMove(Bitboard bitboard);
private BoardBuilder(Bitboard board, bool inverted) : this() { this.result = board; this.inverted = inverted; }
internal static Bitboard RstFile(ref Bitboard bb, SquareE sqr) { return(bb &= ~FileMask(sqr)); }
/// <summary> /// Helper method for derived classes, calculates move with the specified parameters. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="pieceType">The piece type.</param> /// <param name="from">The piece source position.</param> /// <param name="to">The piece destination position.</param> protected void CalculatePieceMove(Bitboard bitboard, PieceType pieceType, ulong from, ulong to) { CalculatePieceMove(bitboard, pieceType, from, pieceType, to); }
public InternalCastlingInfo2(GameMove2 kingMove, Bitboard expectedEmptySquares) { KingMove = kingMove; ExpectedEmptySquares = expectedEmptySquares; }
/// <summary> /// KIF/KI2形式の指し手を与えて、Moveに変換する。指し手の合法性のチェックはここでは行わない。 /// 変換に失敗したときはMove.NONEが返る。 /// </summary> /// <param name="pos"></param> /// <param name="kifMove"></param> /// <returns></returns> public static Move FromKif(this Position pos, string kifMove) { // match.Group[1]: ([▲△▼▽☗☖⛊⛉]?) // match.Group[2]: ([1-9123456789一二三四五六七八九]{2}同?) // match.Group[3]: (同) // match.Group[4]: ([歩香桂銀金角飛玉王と杏圭全馬竜龍]|成[香桂銀]) // match.Group[5]: ([右左]?[上寄引]?|直) // match.Group[6]: (成|不成|打)? // match.Group[7]: (\([1-9]{2}\))? Match match = new Regex(@"([▲△▼▽☗☖⛊⛉]?)(?:([1-9123456789一二三四五六七八九]{2}同?)|(同))[ ]*([歩香桂銀金角飛玉王と杏圭全馬竜龍]|成[香桂銀])(直|[右左]?[上寄引]?)(成|不成|打)?(\([1-9]{2}\))?").Match(kifMove); if (!match.Success) { return(Move.NONE); } Color c0 = pos.sideToMove; Color c1 = FromColor(match.Groups[1].Value); Square sq0; Square sq1 = match.Groups[3].Value == "同" ? pos.State().lastMove.To() : FromSquare(match.Groups[2].Value); if (sq1 == Square.NB) { return(Move.NONE); } Piece pt1 = FromKifPieceType(match.Groups[4].Value); // 駒打ち if (match.Groups[6].Value == "打") { return(Util.MakeMoveDrop(pt1, sq1)); } // 成チェック bool isPromote = (match.Groups[6].Value == "成"); // KIF形式で元座標が示されている場合 if (match.Groups[7].Value.Length == 4) { sq0 = FromSquare(match.Groups[7].Value.Substring(1, 2)); return(isPromote ? Util.MakeMovePromote(sq0, sq1) : Util.MakeMove(sq0, sq1)); } // KI2棋譜用処理 // 駒の移動範囲を調べるため、着手前の駒を求める Piece pt0 = isPromote ? pt1.RawPieceType() : pt1; Bitboard sameBB = pos.AttackersTo(c0, sq1) & pos.Pieces(c0, pt0); if (sameBB.IsZero()) { return(Move.NONE); } if (sameBB.IsOne()) { sq0 = sameBB.Pop(); return(isPromote ? Util.MakeMovePromote(sq0, sq1) : Util.MakeMove(sq0, sq1)); } Bitboard bb; switch (match.Groups[5].Value) { case "右": sq0 = rightMost(c0, sameBB); break; case "左": sq0 = leftMost(c0, sameBB); break; case "直": bb = (KifUtil.lineDirBB(c0, sq1, Direct.D) & sameBB); if (!bb.IsOne()) { return(Move.NONE); } sq0 = bb.Pop(); break; case "上": bb = (KifUtil.dirBB(c0, sq1, Direct.D) & sameBB); if (!bb.IsOne()) { return(Move.NONE); } sq0 = bb.Pop(); break; case "引": bb = (KifUtil.dirBB(c0, sq1, Direct.U) & sameBB); if (!bb.IsOne()) { return(Move.NONE); } sq0 = bb.Pop(); break; case "寄": bb = (Bitboard.RankBB(sq1.ToRank()) & sameBB); if (!bb.IsOne()) { return(Move.NONE); } sq0 = bb.Pop(); break; case "右上": bb = (KifUtil.dirBB(c0, sq1, Direct.D) & sameBB); sq0 = rightMost(c0, bb); break; case "左上": bb = (KifUtil.dirBB(c0, sq1, Direct.D) & sameBB); sq0 = leftMost(c0, bb); break; case "右引": bb = (KifUtil.dirBB(c0, sq1, Direct.U) & sameBB); sq0 = rightMost(c0, bb); break; case "左引": bb = (KifUtil.dirBB(c0, sq1, Direct.U) & sameBB); sq0 = leftMost(c0, bb); break; case "右寄": bb = (Bitboard.RankBB(sq1.ToRank()) & sameBB); sq0 = rightMost(c0, bb); break; case "左寄": bb = (Bitboard.RankBB(sq1.ToRank()) & sameBB); sq0 = leftMost(c0, bb); break; default: return(Move.NONE); } if (sq0 == Square.NB) { return(Move.NONE); } return(isPromote ? Util.MakeMovePromote(sq0, sq1) : Util.MakeMove(sq0, sq1)); }
public void GeneratePawnMoves( [NotNull] ICollection <GameMoveData> resultMoves, GameSide side, GeneratedMoveTypes moveTypes, Bitboard enPassantCaptureTarget, Bitboard target) { if (resultMoves is null) { throw new ArgumentNullException(nameof(resultMoves)); } var pawnPiece = side.ToPiece(PieceType.Pawn); var pawns = PiecePosition[pawnPiece]; if (pawns.IsNone) { return; } var rank8 = side == GameSide.White ? Bitboards.Rank8 : Bitboards.Rank1; if (moveTypes.IsAnySet(GeneratedMoveTypes.Quiet)) { var forwardDirection = side == GameSide.White ? ShiftDirection.North : ShiftDirection.South; var emptySquares = PiecePosition[Piece.None]; var pushes = pawns.Shift(forwardDirection) & emptySquares; var targetPushes = pushes & target; if (targetPushes.IsAny) { var nonPromotionPushes = targetPushes & ~rank8; PopulatePawnMoves(resultMoves, nonPromotionPushes, (int)forwardDirection, GameMoveFlags.None); var promotionPushes = targetPushes & rank8; PopulatePawnMoves( resultMoves, promotionPushes, (int)forwardDirection, GameMoveFlags.IsPawnPromotion); } if (pushes.IsAny) { var rank3 = side == GameSide.White ? Bitboards.Rank3 : Bitboards.Rank6; var doublePushes = (pushes & rank3).Shift(forwardDirection) & emptySquares & target; PopulatePawnMoves( resultMoves, doublePushes, (int)forwardDirection << 1, GameMoveFlags.None); } } //// ReSharper disable once InvertIf if (moveTypes.IsAnySet(GeneratedMoveTypes.Capture)) { var enemies = PiecePosition[side.Invert()]; var enemyTargets = enemies & target; var leftCaptureOffset = side == GameSide.White ? ShiftDirection.NorthWest : ShiftDirection.SouthEast; PopulatePawnCaptures(resultMoves, pawns, enemyTargets, leftCaptureOffset, rank8, enPassantCaptureTarget); var rightCaptureOffset = side == GameSide.White ? ShiftDirection.NorthEast : ShiftDirection.SouthWest; PopulatePawnCaptures(resultMoves, pawns, enemyTargets, rightCaptureOffset, rank8, enPassantCaptureTarget); } }
public void GenerateKnightMoves( [NotNull] ICollection <GameMoveData> resultMoves, GameSide side, GeneratedMoveTypes moveTypes, Bitboard target) { if (resultMoves is null) { throw new ArgumentNullException(nameof(resultMoves)); } var emptySquares = PiecePosition[Piece.None]; var enemies = PiecePosition[side.Invert()]; var internalTarget = Bitboard.None; if (moveTypes.IsAnySet(GeneratedMoveTypes.Quiet)) { internalTarget |= emptySquares; } if (moveTypes.IsAnySet(GeneratedMoveTypes.Capture)) { internalTarget |= enemies; } var actualTarget = target & internalTarget; if (actualTarget.IsNone) { return; } var knightPiece = side.ToPiece(PieceType.Knight); var knights = PiecePosition[knightPiece]; while (knights.IsAny) { var sourceSquareIndex = Bitboard.PopFirstSquareIndex(ref knights); var moves = KnightAttacksOrMoves[sourceSquareIndex]; var movesOnTarget = moves & actualTarget; if (movesOnTarget.IsNone) { continue; } var sourceSquare = new Square(sourceSquareIndex); if (moveTypes.IsAnySet(GeneratedMoveTypes.Capture)) { var captures = movesOnTarget & enemies; PopulateSimpleMoves(resultMoves, sourceSquare, captures, GameMoveFlags.IsRegularCapture); } //// ReSharper disable once InvertIf if (moveTypes.IsAnySet(GeneratedMoveTypes.Quiet)) { var nonCaptures = movesOnTarget & emptySquares; PopulateSimpleMoves(resultMoves, sourceSquare, nonCaptures, GameMoveFlags.None); } } }
private Bitboard GetAttackersInternal( Square targetSquare, GameSide attackingSide, bool findFirstAttackOnly) { var result = new Bitboard(); var targetBitboard = targetSquare.Bitboard; var targetSquareIndex = targetSquare.SquareIndex; var opponentPawns = PiecePosition[attackingSide.ToPiece(PieceType.Pawn)]; if (opponentPawns.IsAny) { ShiftDirection left; ShiftDirection right; if (attackingSide == GameSide.White) { left = ShiftDirection.SouthEast; right = ShiftDirection.SouthWest; } else { left = ShiftDirection.NorthWest; right = ShiftDirection.NorthEast; } var attackingPawns = (targetBitboard.Shift(left) | targetBitboard.Shift(right)) & opponentPawns; result |= attackingPawns; if (findFirstAttackOnly && result.IsAny) { return(result); } } var opponentKnights = PiecePosition[attackingSide.ToPiece(PieceType.Knight)]; if (opponentKnights.IsAny) { var knightAttacks = KnightAttacksOrMoves[targetSquareIndex]; var attackingKnights = knightAttacks & opponentKnights; result |= attackingKnights; if (findFirstAttackOnly && result.IsAny) { return(result); } } var opponentKings = PiecePosition[attackingSide.ToPiece(PieceType.King)]; if (opponentKings.IsAny) { var kingAttacks = KingAttacksOrMoves[targetSquareIndex]; var attackingKings = kingAttacks & opponentKings; result |= attackingKings; if (findFirstAttackOnly && result.IsAny) { return(result); } } var emptySquareBitboard = PiecePosition[Piece.None]; var opponentQueens = PiecePosition[attackingSide.ToPiece(PieceType.Queen)]; var opponentRooks = PiecePosition[attackingSide.ToPiece(PieceType.Rook)]; var opponentSlidingStraightPieces = opponentQueens | opponentRooks; var slidingStraightAttackers = GetSlidingAttackers( targetSquareIndex, opponentSlidingStraightPieces, StraightSlidingAttacks, emptySquareBitboard, findFirstAttackOnly); result |= slidingStraightAttackers; if (findFirstAttackOnly && result.IsAny) { return(result); } var opponentBishops = PiecePosition[attackingSide.ToPiece(PieceType.Bishop)]; var opponentSlidingDiagonallyPieces = opponentQueens | opponentBishops; var slidingDiagonallyAttackers = GetSlidingAttackers( targetSquareIndex, opponentSlidingDiagonallyPieces, DiagonallySlidingAttacks, emptySquareBitboard, findFirstAttackOnly); result |= slidingDiagonallyAttackers; return(result); }
/// <summary> /// 仲間を支えていた駒が離れたら真だぜ☆(^▽^)www /// /// 利きテーブルをいじっているが、更新したいわけではないので、使い終わったら元に戻すぜ☆(^~^) /// </summary> /// <param name="out_ret"></param> /// <param name="ms_t0">移動元</param> /// <param name="ms_t1">移動先</param> /// <returns></returns> public static bool IsMisuteruUgoki() { // 升にある駒種類 Komasyurui ks_t0; if (PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.ExistsKoma(PureMemory.kifu_teban, PureMemory.ssss_ugoki_ms_src, out ks_t0)) { } Piece km_t0 = Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks_t0, PureMemory.kifu_teban); Piece km_t1 = km_t0; //FIXME:成りを考慮してないぜ☆(>_<) int sasaeBeforeMove = 0; // 移動前に、動こうとしている駒を支えている味方の数 int sasaeAfterMove = 0; // 移動後の、動いた駒を支えている味方の数 // 移動前の駒の動き(2個作っておく) Bitboard bbConst_kiki0 = BitboardsOmatome.KomanoUgokikataYk00.Clone_Merge(km_t0, PureMemory.ssss_ugoki_ms_src); Bitboard bbVar_kiki = bbConst_kiki0.Clone(); if (!bbConst_kiki0.IsEmpty()) { // 移動する前の、利き先の 利きの数を数えておこうぜ☆(^▽^) Masu ms_kiki; while (bbVar_kiki.Ref_PopNTZ(out ms_kiki)) { // 0以上なら駒の取り合いで勝つぜ☆(^▽^) // 利き重ね = 自分の利き数 - 相手の利き数 int kasaneGake = PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_teban, ms_kiki) - PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_aiteban, ms_kiki); if (0 < kasaneGake) { sasaeBeforeMove++; } } //──────────────────────────────────────── // 駒は動かさず、移動前の利きを消す(減らす)ぜ☆(^▽^) //──────────────────────────────────────── bbVar_kiki.Set(bbConst_kiki0); //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.TorinozokuKiki(km_t0, bbVar_kiki); } // 移動先での駒の動き Bitboard bbConst_kiki1 = BitboardsOmatome.KomanoUgokikataYk00.Clone_Merge(km_t1, PureMemory.ssss_ugoki_ms_dst); if (!bbConst_kiki1.IsEmpty()) { // 駒を移動させた想定で、利きの数を増やすぜ☆(^▽^) bbVar_kiki.Set(bbConst_kiki1); //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.OkuKiki(km_t1, bbVar_kiki); // 移動した後の、利き先の 利きの数を数えておこうぜ☆(^▽^) bbVar_kiki.Set(bbConst_kiki1); Masu ms_kiki; while (bbVar_kiki.Ref_PopNTZ(out ms_kiki)) { // 0以上なら駒の取り合いで勝つぜ☆(^▽^) // 利き重ね = 自分の利き数 - 相手の利き数 int kasaneGake = PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_teban, ms_kiki) - PureMemory.gky_ky.shogiban.kikiBan.yomiKikiBan.CountKikisuZenbu(PureMemory.kifu_aiteban, ms_kiki); if (0 < kasaneGake) { sasaeAfterMove++; } } } //──────────────────────────────────────── // 利き数表をいじったんで、元に戻しておこうぜ☆(^▽^) //──────────────────────────────────────── { bbVar_kiki.Set(bbConst_kiki1); if (!bbVar_kiki.IsEmpty()) { // 増やした分の重ね利きを減らして、元に戻すぜ☆(^▽^) //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.TorinozokuKiki(km_t1, bbVar_kiki); } } { bbVar_kiki.Set(bbConst_kiki0); // 減らした分の重ね利きを増やして、元に戻すぜ☆(^▽^) //ビットボード使い回し PureMemory.gky_ky.shogiban.kikiBan.OkuKiki(km_t0, bbVar_kiki); } return(sasaeBeforeMove - sasaeAfterMove < 0); }
static GenerateMove03() { bbTmp_nifu = new Bitboard(); }
public string format(Position pos, Move move, Move lastMove) { StringBuilder kif = new StringBuilder(); kif.Append(format(pos.sideToMove)); switch (move) { case Move.NONE: return(kif.Append("エラー").ToString()); case Move.NULL: return(kif.Append("パス").ToString()); case Move.RESIGN: return(kif.Append("投了").ToString()); case Move.WIN: return(kif.Append("勝ち宣言").ToString()); } // 普通の指し手 // 着手元の駒種 Piece fromPiece = pos.PieceOn(move.From()); Piece fromPieceType = fromPiece.PieceType(); if (lastMove.IsOk() && lastMove.To() == move.To()) { // 一つ前の指し手の移動先と、今回の移動先が同じ場合、"同"金のように表示する。 switch (sameposFmt) { case SamePosFormat.NONE: break; case SamePosFormat.SHORT: kif.Append("同"); break; // KIF形式では"同"の後に全角空白 case SamePosFormat.KIFsp: kif.Append("同 "); break; // KI2形式では成香・成桂・成銀・成り動作での空白は入らない case SamePosFormat.KI2sp: if ( move.IsPromote() || fromPieceType == Piece.PRO_LANCE || fromPieceType == Piece.PRO_KNIGHT || fromPieceType == Piece.PRO_SILVER ) { kif.Append("同"); break; } else { kif.Append("同 "); break; } // 座標 + "同" case SamePosFormat.Verbose: kif.Append(format(move.To())).Append("同"); break; default: throw new ConverterException(); } } else { kif.Append(format(move.To())); } kif.Append(PIECE_KIF[pos.PieceOn(move.From()).ToInt()]); switch (fromsqFmt) { case FromSqFormat.NONE: break; case FromSqFormat.KIF: { if (move.IsDrop()) { // KIF形式では持駒からの着手は必ず"打"と表記する kif.Append("打"); } else { if (move.IsPromote()) { kif.Append("成"); } else if ( !fromPiece.IsPromote() && fromPieceType != Piece.GOLD && fromPieceType != Piece.KING && (Util.CanPromote(pos.sideToMove, move.To()) || Util.CanPromote(pos.sideToMove, move.From())) ) { kif.Append("不成"); } Square fromSquare = move.From(); kif.AppendFormat("({0}{1})", HW_NUMBER[move.From().ToFile().ToInt()], HW_NUMBER[move.From().ToRank().ToInt()] ); } break; } case FromSqFormat.KI2: { if (move.IsDrop()) { // KI2では紛らわしくない場合、"打"と表記しない。 Bitboard sameBB = pos.AttackersTo(pos.sideToMove, move.To()) & pos.Pieces(pos.sideToMove, move.DroppedPiece()); if (!sameBB.IsZero()) { kif.Append("打"); } break; } kif.Append(fromSqFormat_KI2(pos, move)); if (move.IsPromote()) { kif.Append("成"); break; } if ( !fromPiece.IsPromote() && fromPieceType != Piece.GOLD && fromPieceType != Piece.KING && (Util.CanPromote(pos.sideToMove, move.To()) || Util.CanPromote(pos.sideToMove, move.From())) ) { kif.Append("不成"); } break; } default: throw new ConverterException(); } return(kif.ToString()); }
private bool IsLegal() { ColorE color; Bitboard occupy; #region Pieces Count for (color = ColorE.White; color <= ColorE.Black; ++color) { occupy = Occupies[(byte)color]; // check too many total pieces if (BitBoard.CountSets(occupy) > 16) { return(false); } // check if the number of Pawns plus the number of extra Queens, Rooks, Bishops, Knights // (which can result only by promotion) exceeds 8 // check too many color pieces if (PieceCount[(byte)color, (byte)PieceE.Pawn] + Math.Max(PieceCount[(byte)color, (byte)PieceE.Queen] - 1, 0) + Math.Max(PieceCount[(byte)color, (byte)PieceE.Rook] - 2, 0) + Math.Max(PieceCount[(byte)color, (byte)PieceE.Bishop] - 2, 0) + Math.Max(PieceCount[(byte)color, (byte)PieceE.Knight] - 2, 0) > 8 ) { return(false); } if (PieceCount[(byte)color, (byte)PieceE.Bishop] > 1) { Bitboard bishops = occupy & Pieces[(byte)PieceE.Bishop]; byte[] bishopCount = new byte[Color.Colors]; //SquareE[] square = BitBoard.GetSquares(occupy & board.Pieces[ (byte) PieceE.Bishop ]); //foreach( SquareE sqr in square ) // ++bishopCount[ (byte) Square._Color(sqr) ]; bishopCount[(byte)ColorE.White] = BitBoard.CountSets(BitBoard.LightSquares & bishops); bishopCount[(byte)ColorE.Black] = BitBoard.CountSets(BitBoard.DarkSquares & bishops); if (PieceCount[(byte)color, (byte)PieceE.Pawn] + Math.Max(bishopCount[(byte)ColorE.White] - 1, 0) + Math.Max(bishopCount[(byte)ColorE.Black] - 1, 0) > 8) { Debug.Assert(false, "Illegal FEN format", "Too many Promotion Bishop of same color of " + color); return(false); } } // check for King byte king = PieceCount[(byte)color, (byte)PieceE.King]; if (king != 1) //Illegal King { return(false); } } // if ((Pieces[(byte)PieceE.Pawn] & (BitBoard.Rank_1 | BitBoard.Rank_8)) != 0) {//Pawn rank one or eight return(false); } #endregion #region Overlapping Bitboard occupied = Occupied; if ((Occupies[(byte)ColorE.White] ^ Occupies[(byte)ColorE.Black]) != occupied) { return(false); } if ((Pieces[(byte)PieceE.Pawn] ^ Pieces[(byte)PieceE.Knight] ^ Pieces[(byte)PieceE.Bishop] ^ Pieces[(byte)PieceE.Rook] ^ Pieces[(byte)PieceE.Queen] ^ Pieces[(byte)PieceE.King]) != occupied) { return(false); } #endregion #region Castling color = ColorE.White; occupy = Occupies[(byte)color]; // check the white King is in place for castle if (Castle[(byte)color].AnyCastle) { if (BitBoard.GetSquare(occupy & Pieces[(byte)PieceE.King], SquareE.E1)) { Bitboard rooks = occupy & Pieces[(byte)PieceE.Rook]; // check the white Rook is in place for castle if (Castle[(byte)color].ShortCastle && !BitBoard.GetSquare(rooks, SquareE.H1)) { //Illegal WhiteShortCastle return(false); } if (Castle[(byte)color].LongCastle && !BitBoard.GetSquare(rooks, SquareE.A1)) { //Illegal WhiteLongCastle return(false); } } else //Illegal WhiteCastle { return(false); } } color = ColorE.Black; occupy = Occupies[(byte)color]; // check the black King is in place for castle if (Castle[(byte)color].AnyCastle) { if (BitBoard.GetSquare(occupy & Pieces[(byte)PieceE.King], SquareE.E8)) { Bitboard rooks = occupy & Pieces[(byte)PieceE.Rook]; // check the black Rook is in place for castle if (Castle[(byte)color].ShortCastle && !BitBoard.GetSquare(rooks, SquareE.H8)) { //Illegal BlackShortCastle return(false); } if (Castle[(byte)color].LongCastle && !BitBoard.GetSquare(rooks, SquareE.A8)) { //Illegal BlackLongCastle return(false); } } else //Illegal BlackCastle { return(false); } } #endregion #region EnPassant if (EnPassant != SquareE.NoSquare) { if (!Square.IsValid(EnPassant)) { return(false); } if (OnMove == ColorE.White && (Square._Rank(EnPassant) != RankE.Rank_6 || !BitBoard.GetSquare(Occupies[(byte)ColorE.Black] & Pieces[(byte)PieceE.Pawn], (SquareE)(EnPassant - 8))) || OnMove == ColorE.Black && (Square._Rank(EnPassant) != RankE.Rank_3 || !BitBoard.GetSquare(Occupies[(byte)ColorE.White] & Pieces[(byte)PieceE.Pawn], (SquareE)(EnPassant + 8)))) { return(false); } } #endregion #region Move if ( //0 < HalfMove || HalfMoveClock > 100) { return(false); } //if( MoveCount < 0 ) return false; #endregion #region KingCheck And Move /* * // check if the side which is not to move is in check * if( * (board.Status.WhiteTurn && board.IsBlackKingInCheck) || (board.Status.BlackTurn && board.IsWhiteKingInCheck) ||) ||{ || throw new ArgumentException(Resources.NoSideNotToMoveCheckMsg, "Board"); ||} */ #endregion return(true); }
public static void Init() { Zobrist.Init(); Bitboard.Init(); }
// TODO:: //internal Bitboard AttacksTo( Bitboard occupied, SquareE sqr, ColorE side ) //{ // //Bitboard knights, kings, bishopsQueens, rooksQueens; // //knights = pieceBB[ nWhiteKnight ] | pieceBB[ nBlackKnight ]; // //kings = pieceBB[ nWhiteKing ] | pieceBB[ nBlackKing ]; // //rooksQueens = // //bishopsQueens = pieceBB[ nWhiteQueen ] | pieceBB[ nBlackQueen ]; // //rooksQueens |= pieceBB[ nWhiteRook ] | pieceBB[ nBlackRook ]; // //bishopsQueens |= pieceBB[ nWhiteBishop ] | pieceBB[ nBlackBishop ]; // //return (arrPawnAttacks[ nWhite ][ sqr ] & pieceBB[ nBlackPawn ]) // // | (arrPawnAttacks[ nBlack ][ sqr ] & pieceBB[ nWhitePawn ]) // // | (arrKnightAttacks[ sqr ] & knights) // // | (arrKingAttacks[ sqr ] & kings) // // | (bishopAttacks(occupied, sqr) & bishopsQueens) // // | (rookAttacks(occupied, sqr) & rooksQueens) // // ; // ColorE oppside = ColorE.NoColor; // if( side == ColorE.White ) // { // oppside = ColorE.Black; // } // else if( side == ColorE.Black ) // { // oppside = ColorE.White; // } // Bitboard sideOccupied = Occupies[ (byte) side ]; // Bitboard rooksQueens = Pieces[ (byte) PieceE.Rook ] | Pieces[ (byte) PieceE.Queen ]; // Bitboard bishopsQueens = Pieces[ (byte) PieceE.Bishop ] | Pieces[ (byte) PieceE.Queen ]; // return (MoveAttack._PawnAttacks[ (byte) sqr, (byte) side ] & (Pieces[ (byte) PieceE.Pawn ] & Occupies[ (byte) oppside ])) // | (MoveAttack._PawnAttacks[ (byte) sqr, (byte) oppside ] & (Pieces[ (byte) PieceE.Pawn ] & Occupies[ (byte) side ])) // | (MoveAttack._KnightMoves[ (byte) sqr ] & Pieces[ (byte) PieceE.Knight ]) // | (MoveAttack._KingMoves[ (byte) sqr ] & Pieces[ (byte) PieceE.King ]) // | (MoveAttack._RookMoves[ (byte) sqr ] & rooksQueens) // | (MoveAttack._BishopMoves[ (byte) sqr ] & bishopsQueens); //} public override string ToString() { StringBuilder sboard = new StringBuilder(); sboard.AppendLine(" +-+-+-+-+-+-+-+-+"); //SquareE begSqr = SquareE.A8; //SquareE endSqr = SquareE.H1; //for( SquareE sqr = begSqr; ; Square.BackwardInc(ref sqr) ) //{ // if( (byte) sqr % File.Files == 0 ) // { // if( sqr != begSqr ) sboard.AppendLine(); // sboard.Append(Rank.mapRank[ (byte) sqr / File.Files ]); // } // bool isPiece = false; // sboard.Append(" "); // for( ColorE color = ColorE.White; color <= ColorE.Black; ++color ) // { // Bitboard occupy = Occupies[ (byte) color ]; // for( PieceE type = PieceE.Pawn; type <= PieceE.King; ++type ) // { // Bitboard piece = Pieces[ (byte) type ]; // if( BitBoard.GetSquare(occupy & piece, sqr) ) // { // //if( isPiece ) sboard.Append('x'); // '*' // isPiece = true; // sboard.Append(Piece.mapPiece[ (byte) color, (byte) type ]); // break; // } // } // } // if( !isPiece ) // sboard.Append("."); // if( sqr == endSqr ) // break; //} for (RankE rank = RankE.Rank_8; ; --rank) { sboard.Append(Rank.mapRank[(byte)rank]); for (FileE file = FileE.File_A; file <= FileE.File_H; ++file) { bool isPiece = false; sboard.Append(" "); for (ColorE color = ColorE.White; color <= ColorE.Black; ++color) { Bitboard occupy = Occupies[(byte)color]; SquareE sqr = Square._Square(file, rank); if (BitBoard.GetSquare(occupy, sqr)) { for (PieceE type = PieceE.Pawn; type <= PieceE.King; ++type) { Bitboard piece = Pieces[(byte)type]; if (BitBoard.GetSquare(piece, sqr)) // occupy & piece { //if( isPiece ) sboard.Append('x'); // '*' isPiece = true; sboard.Append(Piece.mapPiece[(byte)color, (byte)type]); break; } } } } if (!isPiece) { sboard.Append("."); } } if (rank == RankE.Rank_1) { break; } sboard.AppendLine(); } sboard.AppendLine().Append(" +-+-+-+-+-+-+-+-+").AppendLine(); sboard.Append(" "); foreach (char file in File.mapFile) { sboard.Append(" " + file); } return(sboard.ToString()); }
public Bitboard Get(Square from, Bitboard friends, Bitboard enemies) { return Cache[from].Except(friends); }
private static int CalculatePawnScores(ChessBoard cb) { var score = 0; // penalty for doubled pawns for (var i = 0; i < 8; i++) { if (BitOperations.PopCount((ulong)(cb.Pieces[White][Pawn] & Bitboard.Files[i])) > 1) { score -= EvalConstants.PawnScores[EvalConstants.IxPawnDouble]; } if (BitOperations.PopCount((ulong)(cb.Pieces[Black][Pawn] & Bitboard.Files[i])) > 1) { score += EvalConstants.PawnScores[EvalConstants.IxPawnDouble]; } } // bonus for connected pawns var pawns = Bitboard.GetWhitePawnAttacks(cb.Pieces[White][Pawn]) & cb.Pieces[White][Pawn]; while (pawns != 0) { score += EvalConstants.PawnConnected[BitOperations.TrailingZeroCount(pawns) / 8]; pawns &= pawns - 1; } pawns = Bitboard.GetBlackPawnAttacks(cb.Pieces[Black][Pawn]) & cb.Pieces[Black][Pawn]; while (pawns != 0) { score -= EvalConstants.PawnConnected[7 - BitOperations.TrailingZeroCount(pawns) / 8]; pawns &= pawns - 1; } // bonus for neighbour pawns pawns = Bitboard.GetPawnNeighbours(cb.Pieces[White][Pawn]) & cb.Pieces[White][Pawn]; while (pawns != 0) { score += EvalConstants.PawnNeighbour[BitOperations.TrailingZeroCount(pawns) / 8]; pawns &= pawns - 1; } pawns = Bitboard.GetPawnNeighbours(cb.Pieces[Black][Pawn]) & cb.Pieces[Black][Pawn]; while (pawns != 0) { score -= EvalConstants.PawnNeighbour[7 - BitOperations.TrailingZeroCount(pawns) / 8]; pawns &= pawns - 1; } // set outposts cb.PassedPawnsAndOutposts = 0; pawns = Bitboard.GetWhitePawnAttacks(cb.Pieces[White][Pawn]) & ~cb.Pieces[White][Pawn] & ~cb.Pieces[Black][Pawn]; while (pawns != 0) { if ((Bitboard.GetWhiteAdjacentMask(BitOperations.TrailingZeroCount(pawns)) & cb.Pieces[Black][Pawn]) == 0) { cb.PassedPawnsAndOutposts |= pawns & -pawns; } pawns &= pawns - 1; } pawns = Bitboard.GetBlackPawnAttacks(cb.Pieces[Black][Pawn]) & ~cb.Pieces[White][Pawn] & ~cb.Pieces[Black][Pawn]; while (pawns != 0) { if ((Bitboard.GetBlackAdjacentMask(BitOperations.TrailingZeroCount(pawns)) & cb.Pieces[White][Pawn]) == 0) { cb.PassedPawnsAndOutposts |= pawns & -pawns; } pawns &= pawns - 1; } int index; // white pawns = cb.Pieces[White][Pawn]; while (pawns != 0) { index = BitOperations.TrailingZeroCount(pawns); // isolated pawns if ((Bitboard.FilesAdjacent[index & 7] & cb.Pieces[White][Pawn]) == 0) { score -= EvalConstants.PawnScores[EvalConstants.IxPawnIsolated]; } // backward pawns else if ((Bitboard.GetBlackAdjacentMask(index + 8) & cb.Pieces[White][Pawn]) == 0) { if ((StaticMoves.PawnAttacks[White][index + 8] & cb.Pieces[Black][Pawn]) != 0) { if ((Bitboard.Files[index & 7] & cb.Pieces[Black][Pawn]) == 0) { score -= EvalConstants.PawnScores[EvalConstants.IxPawnBackward]; } } } // pawn defending 2 pawns if (BitOperations.PopCount((ulong)(StaticMoves.PawnAttacks[White][index] & cb.Pieces[White][Pawn])) == 2) { score -= EvalConstants.PawnScores[EvalConstants.IxPawnInverse]; } // set passed pawns if ((Bitboard.GetWhitePassedPawnMask(index) & cb.Pieces[Black][Pawn]) == 0) { cb.PassedPawnsAndOutposts |= pawns & -pawns; } // candidate passed pawns (no pawns in front, more friendly pawns behind and adjacent than enemy pawns) else if (63 - BitOperations.LeadingZeroCount( (ulong)((cb.Pieces[White][Pawn] | cb.Pieces[Black][Pawn]) & Bitboard.Files[index & 7])) == index) { if (BitOperations.PopCount((ulong)(cb.Pieces[White][Pawn] & Bitboard.GetBlackPassedPawnMask(index + 8))) >= BitOperations.PopCount( (ulong)(cb.Pieces[Black][Pawn] & Bitboard.GetWhitePassedPawnMask(index)))) { score += EvalConstants.PassedCandidate[index / 8]; } } pawns &= pawns - 1; } // black pawns = cb.Pieces[Black][Pawn]; while (pawns != 0) { index = BitOperations.TrailingZeroCount(pawns); // isolated pawns if ((Bitboard.FilesAdjacent[index & 7] & cb.Pieces[Black][Pawn]) == 0) { score += EvalConstants.PawnScores[EvalConstants.IxPawnIsolated]; } // backward pawns else if ((Bitboard.GetWhiteAdjacentMask(index - 8) & cb.Pieces[Black][Pawn]) == 0) { if ((StaticMoves.PawnAttacks[Black][index - 8] & cb.Pieces[White][Pawn]) != 0) { if ((Bitboard.Files[index & 7] & cb.Pieces[White][Pawn]) == 0) { score += EvalConstants.PawnScores[EvalConstants.IxPawnBackward]; } } } // pawn defending 2 pawns if (BitOperations.PopCount((ulong)(StaticMoves.PawnAttacks[Black][index] & cb.Pieces[Black][Pawn])) == 2) { score += EvalConstants.PawnScores[EvalConstants.IxPawnInverse]; } // set passed pawns if ((Bitboard.GetBlackPassedPawnMask(index) & cb.Pieces[White][Pawn]) == 0) { cb.PassedPawnsAndOutposts |= pawns & -pawns; } // candidate passers else if (BitOperations.TrailingZeroCount((cb.Pieces[White][Pawn] | cb.Pieces[Black][Pawn]) & Bitboard.Files[index & 7]) == index) { if (BitOperations.PopCount((ulong)(cb.Pieces[Black][Pawn] & Bitboard.GetWhitePassedPawnMask(index - 8))) >= BitOperations.PopCount( (ulong)(cb.Pieces[White][Pawn] & Bitboard.GetBlackPassedPawnMask(index)))) { score -= EvalConstants.PassedCandidate[7 - index / 8]; } } pawns &= pawns - 1; } return(score); }
static PureMemory() { int taiLn = Conv_Taikyokusya.itiran.Length; #region 被王手判定 // ビットボード hot_bb_checkerAr = new Bitboard[taiLn]; hot_bb_raion8KinboAr = new Bitboard[taiLn]; hot_bb_nigemitiWoFusaideiruAiteNoKomaAr = new Bitboard[taiLn]; hot_bb_nigereruAr = new Bitboard[taiLn]; hot_bb_nigeroAr = new Bitboard[taiLn]; for (int iTai = 0; iTai < taiLn; iTai++) { hot_bb_checkerAr[iTai] = new Bitboard(); hot_bb_raion8KinboAr[iTai] = new Bitboard(); hot_bb_nigemitiWoFusaideiruAiteNoKomaAr[iTai] = new Bitboard(); hot_bb_nigereruAr[iTai] = new Bitboard(); hot_bb_nigeroAr[iTai] = new Bitboard(); } hot_ms_raionAr = new Masu[taiLn]; hot_outeKomasCountAr = new int[taiLn]; hot_isNigerarenaiCheckerAr = new bool[taiLn]; hot_raionCatchChosaAr = new bool[taiLn]; #endregion #region 指し手生成(シングルスレッドを想定) ssss_moveList = new MoveList[PureMemory.MaxMoveDepth]; ssss_moveListBad = new MoveList[PureMemory.MaxMoveDepth]; ssss_bbVar_idosaki_narazu = new Bitboard(); ssss_bbVar_idosaki_nari = new Bitboard(); ssssTmp_bbVar_ibasho = new Bitboard(); ssss_bbBase_idosaki01_checker = new Bitboard(); ssss_bbBase_idosaki02_raionCatch = new Bitboard(); ssss_bbBase_idosaki03_nigeroTe = new Bitboard(); ssss_bbBase_idosaki04_try = new Bitboard(); ssss_bbBase_idosaki05_komaWoToruTe = new Bitboard(); ssss_bbBase_idosaki06_himodukiOteZasi = new Bitboard(); ssss_bbBase_idosaki07_suteOteZasi = new Bitboard(); ssss_bbBase_idosaki08_suteOteDa = new Bitboard(); ssss_bbBase_idosaki09_himodukiOteDa = new Bitboard(); ssss_bbBase_idosaki10_himodukiKanmanDa = new Bitboard(); ssss_bbBase_idosaki11_himodukiKanmanZasi = new Bitboard(); ssss_bbBase_idosaki12_bottiKanmanZasi = new Bitboard(); ssss_bbBase_idosaki13_bottiKanmanDa = new Bitboard(); ssss_bbBase_idosaki14_suteKanmanZasi = new Bitboard(); ssss_bbBase_idosaki15_suteKanmanDa = new Bitboard(); ssss_movePickerWoNuketaBasho1 = ""; for (int iFukasa = 0; iFukasa < PureMemory.MaxMoveDepth; iFukasa++) { ssss_moveList[iFukasa] = new MoveList(); ssss_moveListBad[iFukasa] = new MoveList(); } #endregion #region ムーブス mvs_ssAr = new Move[KIFU_SIZE]; #endregion #region 棋譜(コンピューター・プレイヤー同時に1つまで) kifu_syokiKyokumenFen = ""; kifu_toraretaKsAr = new Komasyurui[KIFU_SIZE]; kifu_moveArray = new Move[KIFU_SIZE]; kifu_moveTypeArray = new MoveType[KIFU_SIZE]; // 手番☆(^~^) kifu_tebanAr_ = new Taikyokusya[KIFU_SIZE]; kifu_aitebanAr_ = new Taikyokusya[KIFU_SIZE]; kifu_nTebanAr_ = new int[KIFU_SIZE]; kifu_nAitebanAr_ = new int[KIFU_SIZE]; // 初期局面手番を未設定にしておいて、ResetTebanArray( ) すれば、手番配列の初期値が入るぜ☆(^~^) kifu_syokikyokumenTeban = Taikyokusya.Yososu; ResetTebanArray(Taikyokusya.T1); // 配列等の初期化が終わったあとで、手目をリセット ClearTeme( //kifu_syokikyokumenTeban ); #endregion #region 現局面(棋譜カーソルが指している局面)(コンピューター・プレイヤー同時に1つまで) gky_kekka = TaikyokuKekka.Karappo; gky_ky = new Kyokumen(); gky_hyokati = new Hyokati(); Util_Control.UpdateRule( #if DEBUG "static PureMemory" #endif ); #endregion #region 探索(tnsk) tnsk_kohoMove = Move.Toryo; #endregion }
public static int CalculateThreats(ChessBoard cb) { var score = 0; var whites = cb.Pieces[White][All]; var whitePawns = cb.Pieces[White][Pawn]; var blacks = cb.Pieces[Black][All]; var blackPawns = cb.Pieces[Black][Pawn]; var whiteAttacks = cb.Attacks[White][All]; var whitePawnAttacks = cb.Attacks[White][Pawn]; var whiteMinorAttacks = cb.Attacks[White][Knight] | cb.Attacks[White][Bishop]; var blackAttacks = cb.Attacks[Black][All]; var blackPawnAttacks = cb.Attacks[Black][Pawn]; var blackMinorAttacks = cb.Attacks[Black][Knight] | cb.Attacks[Black][Bishop]; // double attacked pieces var piece = cb.DoubleAttacks[White] & blacks; while (piece != 0) { score += EvalConstants.DoubleAttacked[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]]; piece &= piece - 1; } piece = cb.DoubleAttacks[Black] & whites; while (piece != 0) { score -= EvalConstants.DoubleAttacked[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]]; piece &= piece - 1; } if (MaterialUtil.HasPawns(cb.MaterialKey)) { // unused outposts score += BitOperations.PopCount((ulong)(cb.PassedPawnsAndOutposts & cb.EmptySpaces & whiteMinorAttacks & whitePawnAttacks)) * EvalConstants.Threats[EvalConstants.IxUnusedOutpost]; score -= BitOperations.PopCount((ulong)(cb.PassedPawnsAndOutposts & cb.EmptySpaces & blackMinorAttacks & blackPawnAttacks)) * EvalConstants.Threats[EvalConstants.IxUnusedOutpost]; // pawn push threat piece = (whitePawns << 8) & cb.EmptySpaces & ~blackAttacks; score += BitOperations.PopCount((ulong)(Bitboard.GetWhitePawnAttacks(piece) & blacks)) * EvalConstants.Threats[EvalConstants.IxPawnPushThreat]; piece = Util.RightTripleShift(blackPawns, 8) & cb.EmptySpaces & ~whiteAttacks; score -= BitOperations.PopCount((ulong)(Bitboard.GetBlackPawnAttacks(piece) & whites)) * EvalConstants.Threats[EvalConstants.IxPawnPushThreat]; // piece attacked by pawn score += BitOperations.PopCount((ulong)(whitePawnAttacks & blacks & ~blackPawns)) * EvalConstants.Threats[EvalConstants.IxPawnAttacks]; score -= BitOperations.PopCount((ulong)(blackPawnAttacks & whites & ~whitePawns)) * EvalConstants.Threats[EvalConstants.IxPawnAttacks]; // multiple pawn attacks possible if (BitOperations.PopCount((ulong)(whitePawnAttacks & blacks)) > 1) { score += EvalConstants.Threats[EvalConstants.IxMultiplePawnAttacks]; } if (BitOperations.PopCount((ulong)(blackPawnAttacks & whites)) > 1) { score -= EvalConstants.Threats[EvalConstants.IxMultiplePawnAttacks]; } // pawn attacked score += BitOperations.PopCount((ulong)(whiteAttacks & blackPawns)) * EvalConstants.Threats[EvalConstants.IxPawnAttacked]; score -= BitOperations.PopCount((ulong)(blackAttacks & whitePawns)) * EvalConstants.Threats[EvalConstants.IxPawnAttacked]; } // minors attacked and not defended by a pawn score += BitOperations.PopCount((ulong)(whiteAttacks & (cb.Pieces[Black][Knight] | (cb.Pieces[Black][Bishop] & ~blackAttacks)))) * EvalConstants.Threats[EvalConstants.IxMajorAttacked]; score -= BitOperations.PopCount((ulong)(blackAttacks & (cb.Pieces[White][Knight] | (cb.Pieces[White][Bishop] & ~whiteAttacks)))) * EvalConstants.Threats[EvalConstants.IxMajorAttacked]; if (cb.Pieces[Black][Queen] != 0) { // queen attacked by rook score += BitOperations.PopCount((ulong)(cb.Attacks[White][Rook] & cb.Pieces[Black][Queen])) * EvalConstants.Threats[EvalConstants.IxQueenAttacked]; // queen attacked by minors score += BitOperations.PopCount((ulong)(whiteMinorAttacks & cb.Pieces[Black][Queen])) * EvalConstants.Threats[EvalConstants.IxQueenAttackedMinor]; } if (cb.Pieces[White][Queen] != 0) { // queen attacked by rook score -= BitOperations.PopCount((ulong)(cb.Attacks[Black][Rook] & cb.Pieces[White][Queen])) * EvalConstants.Threats[EvalConstants.IxQueenAttacked]; // queen attacked by minors score -= BitOperations.PopCount((ulong)(blackMinorAttacks & cb.Pieces[White][Queen])) * EvalConstants.Threats[EvalConstants.IxQueenAttackedMinor]; } // rook attacked by minors score += BitOperations.PopCount((ulong)(whiteMinorAttacks & cb.Pieces[Black][Rook])) * EvalConstants.Threats[EvalConstants.IxRookAttacked]; score -= BitOperations.PopCount((ulong)(blackMinorAttacks & cb.Pieces[White][Rook])) * EvalConstants.Threats[EvalConstants.IxRookAttacked]; return(score); }
/// <summary> /// Does move (specified by the derived class). /// </summary> /// <param name="bitboard">The bitboard.</param> public void Do(Bitboard bitboard) { CalculateMove(bitboard); CalculateCastling(bitboard); }
public static int CalculateOthers(ChessBoard cb) { var score = 0; long piece; var whites = cb.Pieces[White][All]; var whitePawns = cb.Pieces[White][Pawn]; var blacks = cb.Pieces[Black][All]; var blackPawns = cb.Pieces[Black][Pawn]; var whitePawnAttacks = cb.Attacks[White][Pawn]; var blackPawnAttacks = cb.Attacks[Black][Pawn]; // side to move score += ColorFactor[cb.ColorToMove] * EvalConstants.SideToMoveBonus; // WHITE ROOK if (cb.Pieces[White][Rook] != 0) { piece = cb.Pieces[White][Rook]; // rook battery (same file) if (BitOperations.PopCount((ulong)piece) == 2) { if ((BitOperations.TrailingZeroCount(piece) & 7) == ((63 - BitOperations.LeadingZeroCount((ulong)piece)) & 7)) { score += EvalConstants.OtherScores[EvalConstants.IxRookBattery]; } } // rook on 7th, king on 8th if (cb.KingIndex[Black] >= 56 && (piece & Bitboard.Rank7) != 0) { score += BitOperations.PopCount((ulong)(piece & Bitboard.Rank7)) * EvalConstants.OtherScores[EvalConstants.IxRook7ThRank]; } // prison if ((piece & Bitboard.Rank1) != 0) { var trapped = piece & EvalConstants.RookPrison[cb.KingIndex[White]]; if (trapped != 0) { if ((((trapped << 8) | (trapped << 16)) & whitePawns) != 0) { score += EvalConstants.OtherScores[EvalConstants.IxRookTrapped]; } } } // rook on open-file (no pawns) and semi-open-file (no friendly pawns) while (piece != 0) { if ((whitePawns & Bitboard.GetFile(piece)) == 0) { if ((blackPawns & Bitboard.GetFile(piece)) == 0) { score += EvalConstants.OtherScores[EvalConstants.IxRookFileOpen]; } else if ((blackPawns & blackPawnAttacks & Bitboard.GetFile(piece)) == 0) { score += EvalConstants.OtherScores[EvalConstants.IxRookFileSemiOpenIsolated]; } else { score += EvalConstants.OtherScores[EvalConstants.IxRookFileSemiOpen]; } } piece &= piece - 1; } } // BLACK ROOK if (cb.Pieces[Black][Rook] != 0) { piece = cb.Pieces[Black][Rook]; // rook battery (same file) if (BitOperations.PopCount((ulong)piece) == 2) { if ((BitOperations.TrailingZeroCount(piece) & 7) == ((63 - BitOperations.LeadingZeroCount((ulong)piece)) & 7)) { score -= EvalConstants.OtherScores[EvalConstants.IxRookBattery]; } } // rook on 2nd, king on 1st if (cb.KingIndex[White] <= 7 && (piece & Bitboard.Rank2) != 0) { score -= BitOperations.PopCount((ulong)(piece & Bitboard.Rank2)) * EvalConstants.OtherScores[EvalConstants.IxRook7ThRank]; } // prison if ((piece & Bitboard.Rank8) != 0) { var trapped = piece & EvalConstants.RookPrison[cb.KingIndex[Black]]; if (trapped != 0) { if (((Util.RightTripleShift(trapped, 8) | Util.RightTripleShift(trapped, 16)) & blackPawns) != 0) { score -= EvalConstants.OtherScores[EvalConstants.IxRookTrapped]; } } } // rook on open-file (no pawns) and semi-open-file (no friendly pawns) while (piece != 0) { // TODO JITWatch unpredictable branch if ((blackPawns & Bitboard.GetFile(piece)) == 0) { if ((whitePawns & Bitboard.GetFile(piece)) == 0) { score -= EvalConstants.OtherScores[EvalConstants.IxRookFileOpen]; } else if ((whitePawns & whitePawnAttacks & Bitboard.GetFile(piece)) == 0) { score -= EvalConstants.OtherScores[EvalConstants.IxRookFileSemiOpenIsolated]; } else { score -= EvalConstants.OtherScores[EvalConstants.IxRookFileSemiOpen]; } } piece &= piece - 1; } } // WHITE BISHOP if (cb.Pieces[White][Bishop] != 0) { // bishop outpost: protected by a pawn, cannot be attacked by enemy pawns piece = cb.Pieces[White][Bishop] & cb.PassedPawnsAndOutposts & whitePawnAttacks; if (piece != 0) { score += BitOperations.PopCount((ulong)piece) * EvalConstants.OtherScores[EvalConstants.IxOutpost]; } piece = cb.Pieces[White][Bishop]; if ((piece & Bitboard.WhiteSquares) != 0) { // pawns on same color as bishop score += EvalConstants.BishopPawn[ BitOperations.PopCount((ulong)(whitePawns & Bitboard.WhiteSquares))]; // attacking center squares if (BitOperations.PopCount((ulong)(cb.Attacks[White][Bishop] & Bitboard.E4D5)) == 2) { score += EvalConstants.OtherScores[EvalConstants.IxBishopLong]; } } if ((piece & Bitboard.BlackSquares) != 0) { // pawns on same color as bishop score += EvalConstants.BishopPawn[ BitOperations.PopCount((ulong)(whitePawns & Bitboard.BlackSquares))]; // attacking center squares if (BitOperations.PopCount((ulong)(cb.Attacks[White][Bishop] & Bitboard.D4E5)) == 2) { score += EvalConstants.OtherScores[EvalConstants.IxBishopLong]; } } // prison piece &= Bitboard.Rank2; while (piece != 0) { if (BitOperations.PopCount( (ulong)(EvalConstants.BishopPrison[BitOperations.TrailingZeroCount(piece)] & blackPawns)) == 2) { score += EvalConstants.OtherScores[EvalConstants.IxBishopPrison]; } piece &= piece - 1; } } // BLACK BISHOP if (cb.Pieces[Black][Bishop] != 0) { // bishop outpost: protected by a pawn, cannot be attacked by enemy pawns piece = cb.Pieces[Black][Bishop] & cb.PassedPawnsAndOutposts & blackPawnAttacks; if (piece != 0) { score -= BitOperations.PopCount((ulong)piece) * EvalConstants.OtherScores[EvalConstants.IxOutpost]; } piece = cb.Pieces[Black][Bishop]; if ((piece & Bitboard.WhiteSquares) != 0) { // penalty for many pawns on same color as bishop score -= EvalConstants.BishopPawn[ BitOperations.PopCount((ulong)(blackPawns & Bitboard.WhiteSquares))]; // bonus for attacking center squares if (BitOperations.PopCount((ulong)(cb.Attacks[Black][Bishop] & Bitboard.E4D5)) == 2) { score -= EvalConstants.OtherScores[EvalConstants.IxBishopLong]; } } if ((piece & Bitboard.BlackSquares) != 0) { // penalty for many pawns on same color as bishop score -= EvalConstants.BishopPawn[ BitOperations.PopCount((ulong)(blackPawns & Bitboard.BlackSquares))]; // bonus for attacking center squares if (BitOperations.PopCount((ulong)(cb.Attacks[Black][Bishop] & Bitboard.D4E5)) == 2) { score -= EvalConstants.OtherScores[EvalConstants.IxBishopLong]; } } // prison piece &= Bitboard.Rank7; while (piece != 0) { if (BitOperations.PopCount( (ulong)(EvalConstants.BishopPrison[BitOperations.TrailingZeroCount(piece)] & whitePawns)) == 2) { score -= EvalConstants.OtherScores[EvalConstants.IxBishopPrison]; } piece &= piece - 1; } } // pieces supporting our pawns piece = (whitePawns << 8) & whites; while (piece != 0) { score += EvalConstants.PawnBlockage[Util.RightTripleShift(BitOperations.TrailingZeroCount(piece), 3)]; piece &= piece - 1; } piece = Util.RightTripleShift(blackPawns, 8) & blacks; while (piece != 0) { score -= EvalConstants.PawnBlockage[7 - BitOperations.TrailingZeroCount(piece) / 8]; piece &= piece - 1; } // knight outpost: protected by a pawn, cannot be attacked by enemy pawns piece = cb.Pieces[White][Knight] & cb.PassedPawnsAndOutposts & whitePawnAttacks; if (piece != 0) { score += BitOperations.PopCount((ulong)piece) * EvalConstants.OtherScores[EvalConstants.IxOutpost]; } piece = cb.Pieces[Black][Knight] & cb.PassedPawnsAndOutposts & blackPawnAttacks; if (piece != 0) { score -= BitOperations.PopCount((ulong)piece) * EvalConstants.OtherScores[EvalConstants.IxOutpost]; } // pinned-pieces if (cb.PinnedPieces != 0) { piece = cb.PinnedPieces & whites; while (piece != 0) { score += EvalConstants.Pinned[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]]; piece &= piece - 1; } piece = cb.PinnedPieces & blacks; while (piece != 0) { score -= EvalConstants.Pinned[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]]; piece &= piece - 1; } } // discovered-pieces if (cb.DiscoveredPieces != 0) { piece = cb.DiscoveredPieces & whites; while (piece != 0) { score += EvalConstants.Discovered[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]]; piece &= piece - 1; } piece = cb.DiscoveredPieces & blacks; while (piece != 0) { score -= EvalConstants.Discovered[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]]; piece &= piece - 1; } } if (cb.CastlingRights == 0) { return(score); } score += BitOperations.PopCount((ulong)(cb.CastlingRights & 12)) * EvalConstants.OtherScores[EvalConstants.IxCastling]; score -= BitOperations.PopCount((ulong)(cb.CastlingRights & 3)) * EvalConstants.OtherScores[EvalConstants.IxCastling]; return(score); }
/// <summary> /// Calculates a mobility evaluation result for the specified player by adding number of possible /// moves for every piece with the specified color. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="color">The player color.</param> /// <returns>The mobility evaluation result for the specified player.</returns> private int GetMobilityValue(Bitboard bitboard, Color color) { return(BitOperations.Count(bitboard.AttacksSummary[(int)color])); }
private BoardBuilder(Bitboard board, bool inverted) : this() { resultField = board; invertedField = inverted; }
public Bitboard GetMoveBoard(Square from, Bitboard friends) { return GetMoveBoard(from, friends, 0); }
public WhitePawns(Bitboard locations) : this() { this.Locations = locations; }
public IEnumerable<Move> GetMovesOneSquareForward(Bitboard notblockers, Bitboard filterFrom, Bitboard filterTo) { Bitboard b = (Locations.Intersect(filterFrom) >> 8 & notblockers); return GetMoves(b.Intersect(filterTo), 8); }
public IEnumerable<Move> GetMovesTwoSquaresForward(Bitboard notblockers) { return GetMovesTwoSquaresForward(notblockers, Bitboard.Full, Bitboard.Full); }
static string fromSqFormat_KI2(Position pos, Move move) { Color c = pos.sideToMove; Square fromSq = move.From(), toSq = move.To(); Piece p = pos.PieceOn(fromSq), pt = p.PieceType(); Bitboard sameBB = pos.AttackersTo(c, toSq) & pos.Pieces(c, pt); if (!sameBB.IsSet(fromSq)) { return(""); } if (sameBB.IsOne()) { return(""); } if (KifUtil.checkBB(sameBB, Bitboard.RankBB(toSq.ToRank()), fromSq)) { return("寄"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.D), fromSq)) { return("上"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.U), fromSq)) { return("引"); } if (KifUtil.checkBB(sameBB, KifUtil.lineDirBB(c, toSq, Direct.D), fromSq) && ( pt == Piece.SILVER || pt == Piece.GOLD || pt == Piece.PRO_PAWN || pt == Piece.PRO_LANCE || pt == Piece.PRO_KNIGHT || pt == Piece.PRO_SILVER )) { return("直"); } if (KifUtil.checkBB(sameBB, KifUtil.dirOrBB(c, fromSq, Direct.L), fromSq)) { return("左"); } if (KifUtil.checkBB(sameBB, KifUtil.dirOrBB(c, fromSq, Direct.R), fromSq)) { return("右"); } if (KifUtil.checkBB(sameBB, KifUtil.lineDirOrBB(c, fromSq, Direct.L) & Bitboard.RankBB(toSq.ToRank()), fromSq)) { return("左寄"); } if (KifUtil.checkBB(sameBB, KifUtil.lineDirOrBB(c, fromSq, Direct.R) & Bitboard.RankBB(toSq.ToRank()), fromSq)) { return("右寄"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.D) & KifUtil.dirOrBB(c, fromSq, Direct.L), fromSq)) { return("左上"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.D) & KifUtil.dirOrBB(c, fromSq, Direct.R), fromSq)) { return("右上"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.U) & KifUtil.dirOrBB(c, fromSq, Direct.L), fromSq)) { return("左引"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.U) & KifUtil.dirOrBB(c, fromSq, Direct.R), fromSq)) { return("右引"); } // 正常な局面・指し手でここに到達する筈は無い return(""); }
private IEnumerable<Move> GetMoves(Bitboard b, int offsetFrom) { foreach (var to in b.Squares) { Square from = to - offsetFrom; b = b.Except(to); if (to >= 56) { yield return new Move(from, to, MoveTypes.PawnToQueenPromotion); yield return new Move(from, to, MoveTypes.PawnToRookPromotion); yield return new Move(from, to, MoveTypes.PawnToBishopPromotion); yield return new Move(from, to, MoveTypes.PawnToKnightPromotion); } else { yield return new Move(from, to); } } }
protected override Bitboard AdditionalMoveProcessing(Bitboard movesForCurrentPosition) { // For pawns, extra moves would constitute: // 1. Normal attack // 2. En passant // Normal attack // Check the row ahead for opponent locations int rowToCheck; Side sideToCheck; if (this.side == Side.Black) { rowToCheck = this.GetCurrentPosition().GetRow() - 1; sideToCheck = Side.White; } else { rowToCheck = this.GetCurrentPosition().GetRow() + 1; sideToCheck = Side.Black; } Bitboard friendlyLocations = this.chessBoard.GetPieceLocations(this.side); Bitboard opponentLocations = this.chessBoard.GetPieceLocations(sideToCheck); // First, remove any moves that go through friendly or opponent movesForCurrentPosition = movesForCurrentPosition.ComputeRayIntersections(friendlyLocations, this.GetCurrentPosition(), false); movesForCurrentPosition = movesForCurrentPosition.ComputeRayIntersections(opponentLocations, this.GetCurrentPosition(), false); if (this.GetCurrentPosition().GetColumn() > Position.min) { if (opponentLocations.ValueAtPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, rowToCheck)) > 0) { movesForCurrentPosition.FlipPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, rowToCheck)); } } if (this.GetCurrentPosition().GetColumn() < Position.max) { if (opponentLocations.ValueAtPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, rowToCheck)) > 0) { movesForCurrentPosition.FlipPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, rowToCheck)); } } // En passant rowToCheck = this.GetCurrentPosition().GetRow(); if (this.GetCurrentPosition().GetColumn() > Position.min) { if (opponentLocations.ValueAtPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, rowToCheck)) > 0) { // Also check if the piece at this location is a pawn which has just performed a double jump AbstractPiece passedPiece = this.chessBoard.GetPieceAtPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, rowToCheck)); if (passedPiece != null && passedPiece.GetType().Name.CompareTo(this.GetType().Name) == 0 && ((Pawn)passedPiece).allowEnPassantCapture) { int attackPoint = rowToCheck; if (this.side == Side.Black) { attackPoint--; } else { attackPoint++; } movesForCurrentPosition.FlipPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, attackPoint)); } } } if (this.GetCurrentPosition().GetColumn() < Position.max) { if (opponentLocations.ValueAtPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, rowToCheck)) > 0) { AbstractPiece passedPiece = this.chessBoard.GetPieceAtPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, rowToCheck)); if (passedPiece != null && passedPiece.GetType().Name.CompareTo(this.GetType().Name) == 0 && ((Pawn)passedPiece).allowEnPassantCapture) { int attackPoint = rowToCheck; if (this.side == Side.Black) { attackPoint--; } else { attackPoint++; } movesForCurrentPosition.FlipPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, attackPoint)); } } } return(movesForCurrentPosition); }
public static void Test1() { Piece p = Piece.GOLD; Console.WriteLine(p.Pretty()); Console.WriteLine(p.ToUsi()); Piece p2 = Shogi.Core.Util.MakePiecePromote(Color.WHITE, p); Console.WriteLine(p2.ToUsi()); #if false // Squareのテスト Square sq = Square.SQ_56; //Console.WriteLine(sq.ToFile().ToUSI() + sq.ToRank().ToUSI()); Console.WriteLine(sq.ToUsi()); Console.WriteLine(sq.Pretty()); #endif Move m = Shogi.Core.Util.MakeMove(Square.SQ_56, Square.SQ_45); Console.WriteLine(m.ToUsi()); Move m2 = Shogi.Core.Util.MakeMoveDrop(Piece.SILVER, Square.SQ_45); Console.WriteLine(m2.ToUsi()); Move m3 = Shogi.Core.Util.MakeMovePromote(Square.SQ_84, Square.SQ_83); Console.WriteLine(m3.ToUsi()); Move m4 = Shogi.Core.Util.FromUsiMove("8h2b+"); Console.WriteLine(m4.Pretty()); Move m5 = Shogi.Core.Util.FromUsiMove("G*3b"); Console.WriteLine(m5.Pretty()); Move m6 = Shogi.Core.Util.FromUsiMove("7g7f"); Hand h = Hand.ZERO; h.Add(Piece.PAWN, 5); h.Add(Piece.KNIGHT, 1); Console.WriteLine(h.Pretty()); Console.WriteLine(h.ToUsi(Color.BLACK)); Console.WriteLine(h.ToUsi(Color.WHITE)); var pos = new Position(); //pos.UsiPositionCmd("startpos moves 7g7f 3c3d 8h3c+"); pos.InitBoard(BoardType.NoHandicap); MoveGen.GenTest(pos); pos.UsiPositionCmd("sfen lnsgkgsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1 moves 5a6b 7g7f 3a3b"); Console.WriteLine(pos.Pretty()); #if false // UndoMove()のテスト pos.UndoMove(); Console.WriteLine(pos.Pretty()); pos.UndoMove(); Console.WriteLine(pos.Pretty()); pos.UndoMove(); Console.WriteLine(pos.Pretty()); Console.WriteLine(pos.PrettyPieceNo()); #endif // 駒番号のテスト //Console.WriteLine(pos.PrettyPieceNo()); // Console.WriteLine(pos.Pieces().Pretty()); // Console.WriteLine(pos.Pieces(Color.BLACK).Pretty()); #if false // Bitboard(Square)のテスト for (Square sq = Square.ZERO; sq < Square.NB; ++sq) { Console.WriteLine("sq = " + sq.Pretty()); Bitboard b = new Bitboard(sq); Console.WriteLine(b.Pretty()); } #endif #if false // 角・馬の利きのテスト Bitboard occupied = new Bitboard(Square.SQ_33); Console.WriteLine(occupied.Pretty()); Bitboard bb = Bitboard.BishopEffect(Square.SQ_55, occupied); Console.WriteLine(bb.Pretty()); Bitboard bb2 = Bitboard.BishopStepEffect(Square.SQ_56); Console.WriteLine(bb2.Pretty()); Bitboard bb3 = Bitboard.BishopEffect(Square.SQ_56, Bitboard.AllBB()); Console.WriteLine(bb3.Pretty()); Bitboard bb4 = Bitboard.HorseEffect(Square.SQ_55, occupied); Console.WriteLine(bb4.Pretty()); #endif #if false // 飛車・龍の利きのテスト Bitboard occupied = new Bitboard(Square.SQ_53); Console.WriteLine(occupied.Pretty()); Bitboard bb = Bitboard.RookEffect(Square.SQ_55, occupied); Console.WriteLine(bb.Pretty()); Bitboard bb2 = Bitboard.RookStepEffect(Square.SQ_56); Console.WriteLine(bb2.Pretty()); Bitboard bb3 = Bitboard.RookEffect(Square.SQ_56, Bitboard.AllBB()); Console.WriteLine(bb3.Pretty()); Bitboard bb4 = Bitboard.DragonEffect(Square.SQ_55, occupied); Console.WriteLine(bb4.Pretty()); #endif #if false // 香りの利きのテスト Bitboard occupied = new Bitboard(Square.SQ_53); Bitboard bb = Bitboard.LanceEffect(Color.BLACK, Square.SQ_55, occupied); Console.WriteLine(bb.Pretty()); Bitboard bb3 = Bitboard.LanceStepEffect(Color.BLACK, Square.SQ_56); Console.WriteLine(bb3.Pretty()); #endif #if false // 歩、桂、銀、金、玉の利きのテスト Bitboard bb = Bitboard.PawnEffect(Color.BLACK, Square.SQ_55); Console.WriteLine(bb.Pretty()); Bitboard bb2 = Bitboard.KnightEffect(Color.BLACK, Square.SQ_55); Console.WriteLine(bb2.Pretty()); Bitboard bb3 = Bitboard.SilverEffect(Color.BLACK, Square.SQ_55); Console.WriteLine(bb3.Pretty()); Bitboard bb4 = Bitboard.GoldEffect(Color.BLACK, Square.SQ_55); Console.WriteLine(bb4.Pretty()); Bitboard bb5 = Bitboard.KingEffect(Square.SQ_55); Console.WriteLine(bb5.Pretty()); #endif #if false // EffectsFrom()のテスト var bb = Bitboard.EffectsFrom(Piece.W_DRAGON, Square.SQ_54, pos.Pieces()); Console.WriteLine(bb.Pretty()); var bb2 = Bitboard.EffectsFrom(Piece.W_GOLD, Square.SQ_54, pos.Pieces()); Console.WriteLine(bb2.Pretty()); #endif #if false // BitboardのPop()のテスト for (Square sq = Square.ZERO; sq < Square.NB; ++sq) { Console.Write("sq = " + sq.Pretty() + " "); Bitboard b = new Bitboard(sq); Square r = b.Pop(); Console.WriteLine(r.Pretty()); } #endif #if false // 駒落ちの局面のテスト pos.InitBoard(BoardType.Handicap2); // 2枚落ち Console.WriteLine(pos.Pretty()); pos.InitBoard(BoardType.Handicap10); // 10枚落ち Console.WriteLine(pos.Pretty()); #endif #if false pos.SetSfen(Position.SFEN_HIRATE); Console.WriteLine(pos.ToSfen()); Console.WriteLine(pos.Pretty()); pos.DoMove(m6); Console.WriteLine(pos.Pretty()); #endif #if false // sfen化して、setしてhash keyが変わらないかのテスト //pos.SetSfen(pos.ToSfen()); //Console.WriteLine(pos.Pretty()); #endif #if false // 指し手生成祭りの局面 pos.SetSfen("l6nl/5+P1gk/2np1S3/p1p4Pp/3P2Sp1/1PPb2P1P/P5GS1/R8/LN4bKL w RGgsn5p 1"); Console.WriteLine(pos.ToSfen()); Console.WriteLine(pos.Pretty()); #endif #if false // 駒番号のデバッグ Console.WriteLine(pos.PrettyPieceNo()); // Console.WriteLine(pos.Pieces().Pretty()); // Console.WriteLine(pos.Pieces(Color.BLACK).Pretty()); #endif #if false // BitweenBB()のテスト var bb = Bitboard.BetweenBB(Square.SQ_77, Square.SQ_33); Console.WriteLine(bb.Pretty()); var bb2 = Bitboard.BetweenBB(Square.SQ_58, Square.SQ_52); Console.WriteLine(bb2.Pretty()); #endif #if false // 乱数テスト var rand = new PRNG(1234); Console.WriteLine(rand.Rand()); Console.WriteLine(rand.Rand()); Console.WriteLine(rand.Rand()); var key_side = Zobrist.Side; Console.WriteLine(key_side.ToString()); #endif #if false // serialization test var csa = new Model.CsaConnectData(); var serializer = new DataContractJsonSerializer(typeof(Model.CsaConnectData)); var ms = new MemoryStream(); serializer.WriteObject(ms, csa); var json = Encoding.UTF8.GetString(ms.ToArray()); MessageBox.Show(json); #endif #if false // UsiPositionCmdのテスト。非合法手が混じっているパターン var pos2 = new Position(); try { pos2.UsiPositionCmd("startpos moves 7g7f 3c4d 2g2f "); // 2手目が非合法手 } catch (Exception e) { Console.WriteLine(e.Message); } #endif #if false { // 千日手の引き分けのテスト var pos2 = new Position(); pos.UsiPositionCmd("startpos moves"); var moves = new[] { Util.MakeMove(Square.SQ_59, Square.SQ_58), Util.MakeMove(Square.SQ_51, Square.SQ_52), Util.MakeMove(Square.SQ_58, Square.SQ_59), Util.MakeMove(Square.SQ_52, Square.SQ_51), }; int ply = 0; for (int j = 0; j < 5; ++j) { for (int i = 0; i < moves.Length; ++i) { pos.DoMove(moves[i]); var rep = pos.IsRepetition(); ply++; Console.WriteLine(string.Format("ply = {0} , rep = {1} ", ply, rep.ToString())); // 16手目を指した局面(17手目)が先手番で千日手引き分けの局面になるはず } } } #endif #if false { // 連続王手の千日手の負けのテスト var pos2 = new Position(); pos.UsiPositionCmd("startpos moves 7g7f 5c5d 8h3c 5a6b"); var moves = new[] { Util.MakeMove(Square.SQ_33, Square.SQ_44), Util.MakeMove(Square.SQ_62, Square.SQ_51), Util.MakeMove(Square.SQ_44, Square.SQ_33), Util.MakeMove(Square.SQ_51, Square.SQ_62), }; int ply = 4; for (int j = 0; j < 5; ++j) { for (int i = 0; i < moves.Length; ++i) { pos.DoMove(moves[i]); //Console.WriteLine(pos.Pretty()); //Console.WriteLine(pos.State().checkersBB.Pretty()); var rep = pos.IsRepetition(); ply++; Console.WriteLine(string.Format("ply = {0} , rep = {1} ", ply, rep.ToString())); // 19手目の局面(を指した直後の局面=20手目,後手番)で、ここで後手勝ちになるはず。 } } } #endif #if false // UndoMove()でcapture,promoteが戻るかのテスト var pos2 = new Position(); pos2.UsiPositionCmd("startpos moves 7g7f 3c3d 8h2b+"); Console.WriteLine(pos2.Pretty()); pos2.UndoMove(); Console.WriteLine(pos2.Pretty()); pos2.UndoMove(); Console.WriteLine(pos2.Pretty()); pos2.UndoMove(); Console.WriteLine(pos2.Pretty()); Console.WriteLine(pos2.PrettyPieceNo()); #endif #if true { // -- 局面の合法性のチェック // 平手 pos.SetSfen("lnsgkgsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); // 先手2歩 pos.SetSfen("lnsgkgsnl/9/9/P8/9/9/P8/1B5R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); // 後手2歩 pos.SetSfen("lnsgkgsnl/9/8p/8p/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); // 玉なし pos.SetSfen("lnsg1gsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSG1GSNL b - 1"); Console.WriteLine(pos.IsValid()); // 片玉 pos.SetSfen("lnsg1gsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); // 片玉(詰将棋時) これは合法 pos.SetSfen("lnsg1gsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"); Console.WriteLine("詰将棋片玉 : " + pos.IsValid(true)); // 先手玉が2枚 pos.SetSfen("lnsgKgsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); // 玉3枚 pos.SetSfen("lnsgkksnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); // 非手番側に王手 pos.SetSfen("lnsgkgsnl/9/ppppppBpp/9/9/9/PPPPPPPPP/25R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); // 行き場の無い駒 pos.SetSfen("Lnsgkgsnl/9/pppppp1pp/9/9/9/PPPPPPPPP/25R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); pos.SetSfen("l1sgkgsnl/N8/pppppp1pp/9/9/9/PPPPPPPPP/25R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); pos.SetSfen("P1sgkgsnl/9/pppppp1pp/9/9/9/9/25R1/LNSGKGSNL b - 1"); Console.WriteLine(pos.IsValid()); pos.SetSfen("2sgkgsnl/9/9/9/9/9/9/25R1/LNSGKGSNp b - 1"); Console.WriteLine(pos.IsValid()); } #endif }
public IEnumerable<Move> GetMovesOneSquareForward(Bitboard notblockers) { Bitboard b = (this.Locations << 8 & notblockers); return GetMoves(b, 8); }
public static void PopLsb(ref Bitboard bitboard) { bitboard &= (bitboard - 1); }
public IEnumerable<Move> GetMovesOneSquareForward(Bitboard notblockers, Bitboard filterFrom, Bitboard filterTo) { Bitboard l = this.Locations & filterFrom; Bitboard b = (l << 8 & notblockers); b &= filterTo; return GetMoves(b, 8); }
public static int BitScanForward(this Bitboard bitboard) { Debug.Assert(bitboard != 0); return(MultiplyDeBruijnBitPosition[((ulong)((long)bitboard & -(long)bitboard) * DeBruijnSequence) >> 58]); }
public IEnumerable<Move> GetMovesTwoSquaresForward(Bitboard notblockers, Bitboard filterFrom, Bitboard filterTo) { var b = Locations.Intersect(new Rank(1)).Intersect(filterFrom); b = b.Shift(1, 0).Intersect(notblockers); b = b.Shift(1, 0).Intersect(notblockers); b = b.Intersect(filterTo); foreach(var to in b.Squares) { Square from = to - 16; b = b.Except(to); yield return new Move(from, to); } }
public static void TestPawnMoves(bool captureFunc, string fen, Move[] expectedMoves, int color, Bitboard destinationBitboard = 0) { Position board = Position.FromFen(fen); MoveList actualMoves = new MoveList(); if (destinationBitboard == 0) { destinationBitboard = ~board.GetPieceBitboard(color, Position.ALL_PIECES); } if (captureFunc) { board.GetAllPawnCaptureMoves(actualMoves, color, destinationBitboard); } else { board.GetAllPawnPushMoves(actualMoves, color, destinationBitboard); } TestArrayEquality(expectedMoves, actualMoves.ToArray()); }
public IEnumerable<Move> GetCaptures(Bitboard enemies, Square? enpassant = null) { return GetCaptures(enemies, Bitboard.Full, Bitboard.Full, enpassant); }
public Bitboard GetMoveBoard(Square from, Bitboard friends, Bitboard enemies) { return rook.GetMoveBoard(from, friends, enemies).And( bishop.GetMoveBoard(from, friends, enemies)); }
public Bitboard GetMoveBoard(Bitboard notblockers, Bitboard enemies, Square? enpassant) { var onesquarforward = (this.Locations << 8 & notblockers); var twosquaresforward = Locations .Intersect(new Rank(1)) .Shift(1, 0).Intersect(notblockers) .Shift(1, 0).Intersect(notblockers); return onesquarforward | twosquaresforward | GetCapturesMoveBoard(notblockers, enemies, enpassant); }
static Util_TryRule() { m_trySakiBB_ = new Bitboard(); }
/// <summary> /// トライできる先。 /// </summary> /// <param name="ky">局面</param> /// <param name="kikiBB">手番らいおんの利きビットボード</param> /// <param name="tb">手番</param> /// <param name="ms1">手番らいおんがいる升</param> /// <returns></returns> public static Bitboard GetTrySaki(Bitboard kikiBB, Masu ms1) { #if DEBUG Util_Test.AppendLine("テスト: トライルール", Pure.Sc.dbgMojiretu); #endif m_trySakiBB_.Clear(); // 自分はN段目にいる☆ int dan = Conv_Masu.ToDanO1_JibunSiten(PureMemory.kifu_teban, ms1); bool nidanme = 2 == dan; #if DEBUG Util_Test.AppendLine($"2段目にいるか☆?[{nidanme}] わたしは[{dan}]段目にいるぜ☆", Pure.Sc.dbgMojiretu); #endif if (!nidanme) { #if DEBUG Util_Test.AppendLine("むりだぜ☆", Pure.Sc.dbgMojiretu); //Util_Test.Flush(reigai1); #endif return(m_trySakiBB_); } // 1段目に移動できる升☆ m_trySakiBB_.Set(kikiBB); m_trySakiBB_.Siborikomi(BitboardsOmatome.bb_try[PureMemory.kifu_nTeban]); #if DEBUG Interproject.project.Dbg_TryRule1(kikiBB, m_trySakiBB_); #endif // 味方の駒がないところ☆ Bitboard spaceBB = new Bitboard(); spaceBB.Set(BitboardsOmatome.bb_boardArea); PureMemory.gky_ky.shogiban.ibashoBan_yk00.yomiIbashoBan.ToSitdown_KomaZenbu(PureMemory.kifu_teban, spaceBB); m_trySakiBB_.Siborikomi(spaceBB); #if DEBUG Interproject.project.Dbg_TryRule2(spaceBB, m_trySakiBB_); #endif if (m_trySakiBB_.IsEmpty()) { #if DEBUG Util_Test.AppendLine("むりだぜ☆", Pure.Sc.dbgMojiretu); //Util_Test.Flush(reigai1); #endif return(m_trySakiBB_); } // 相手の利きが届いていないところ☆ Bitboard safeBB = new Bitboard(); safeBB.Set(BitboardsOmatome.bb_boardArea); PureMemory.gky_ky.yomiKy.yomiShogiban.yomiKikiBan.ToSitdown_BBKikiZenbu(PureMemory.kifu_aiteban, safeBB); m_trySakiBB_.Siborikomi(safeBB); #if DEBUG Interproject.project.Dbg_TryRule3(safeBB, m_trySakiBB_); #endif if (m_trySakiBB_.IsEmpty()) { #if DEBUG Util_Test.AppendLine("むりだぜ☆", Pure.Sc.dbgMojiretu); //Util_Test.Flush(reigai1); #endif return(m_trySakiBB_); } #if DEBUG Util_Test.AppendLine("トライできるぜ☆", Pure.Sc.dbgMojiretu); //Util_Test.Flush(reigai1); #endif return(m_trySakiBB_); }
internal static Bitboard ExcludeSquares(ref Bitboard bb, Bitboard exclude) { return(bb &= ~exclude); }