示例#1
0
        public PawnPosition GetPXP(Position position)
        {
            PXPMemo.Counts.GetReads++;
            var qHashPawn = position.HashPawn;
            var found     = PXPMemo[qHashPawn];

#if PawnPositionByValue
            var bDefault = (found.BlackPRP & PRPFlags.IsValid) == 0;
#else
            var bDefault = found == default(PawnPosition);
#endif
            if (!bDefault && found.HashPawn == qHashPawn)
            {
                PXPMemo.Counts.GetHits++; // Match, a.k.a. Get Hit
                return(found);
            }

            //
            // Position instance contains the specific Pawn configuration.
            //
            // Passer weight could be optimized out where PawnFeature Delta
            // is much less than the StaticDelta returned by staticEval().
            //
            // Wrong Bishops will be determined by Passed Rook Pawns.
            //
            var uBlackCount = position.CountPawnFeatures(Black, out Plane qpBlackPassers, out PRPFlags fBlackPRP);
            var uWhiteCount = position.CountPawnFeatures(White, out Plane qpWhitePassers, out PRPFlags fWhitePRP);
#if PawnPositionByValue
            if (bDefault)
            {
                PXPMemo.Counts.Added++; // Non-Match Case: Add new PawnPosition
            }
            found = new PawnPosition(qHashPawn, fBlackPRP, fWhitePRP,
                                     uBlackCount, uWhiteCount,
                                     qpBlackPassers, qpWhitePassers);
            PXPMemo[qHashPawn] = found;
            return(found);
#else                                   // PawnPositionByValue
            if (bDefault)
            {
                PXPMemo.Counts.Added++; // Non-Match Case: Add new PawnPosition
                found = new PawnPosition(qHashPawn, fBlackPRP, fWhitePRP,
                                         uBlackCount, uWhiteCount,
                                         qpBlackPassers, qpWhitePassers);
                PXPMemo[qHashPawn] = found;
                return(found);
            }
            else
            {
                found.Recycle(qHashPawn, fBlackPRP, fWhitePRP,
                              uBlackCount, uWhiteCount,
                              qpBlackPassers, qpWhitePassers);
                return(found);
            }
#endif
        }
示例#2
0
        //
        //[ToDo]Add evaluation of practical Draws where helpmate is possible:
        //
        // KKNN or KNKNN
        // KBKB opposite color
        // KNKBN, KBKBN. KBKBB pair [Note: KNKBB pair can be won; but perhaps not in 50 moves]
        //
        // More Complex Draws, assuming weaker side in time to defend:
        //
        // KKP if weaker side maintains opposition
        // Distant Opposition vs. Key/Critical Squares vs Corresponding or Relative Squares!?
        //
        // KBKBP of opposite color
        // KPKQ if P to queen on ACFH-file and sronger K too far to help
        //

        //
        // Development [initial move per piece, delaying heavy pieces]
        // Control of the Center by Pawns
        // Control of Squares around King
        // Castling and King Safety [Corner Squares] vs King Activity in the Endgame
        //
        // Rooks on Open Files
        // Rook or Queen on 7th [or 2nd] Rank
        // Protected Piece and Connected Rook Bonus
        // Knight Scope and Outpost [free of Pawn harrassment]
        // Bishop Scope [and Bad Bishop Detection]
        //
        // Bonus for Bishop with color of Promotion Square for any Passed Pawns, especially
        // Rook Pawns.  Applies to defense and Passed Opposing Pawns, as well as to offense.
        //
        // Attack Pawn Chains at the base
        // Bonus for Passed Pawn Couples
        //
        // Piece Values depending on Opening, Middle, End Game Phase and Relative Advantage:
        // Stronger side favors [vice versa Weaker side is averse to]
        // Bishops of Opposite Colors in Middle Game; and Bishops of Same Color in Endgame.
        //

        //
        // Technical and Tablebase Draws:
        // KRKRP if weaker side can attain Philidor Position
        //
        // EGTB Alternatives: Syzygy by Ronald de Man, Gaviota EGTB by Miguel A. Ballicora,
        // Nalimov by Eugene Nalimov.  Syzygy is preferred by Houdini.  It is compact; but
        // does not provide Distance to Mate (DTM).  They provide Wind-Draw-Loss (WDL) and
        // Distance to Zero (DTZ).
        //
        // The Syzygy 6-man EGTB is available at http://tablebase.sesse.net/syzygy, where
        // the (290) 3-4-5-men files require 938 MB; and (730) 6-men files require 149 GB.
        //
        protected Eval staticEval(out PawnPosition pp)  //[New]~9.666 MHz vs ~13.333 MHz w/o EvalRookBehindPasser
        {
            pp = default;
            if (IsInsufficient())
            {
                return(contempt());
            }

            GameState.AtomicIncrement(ref State.TotalEvals); // vs. FullEvaluations

            setEndGameFlags();

            if (EvalUndefined < StaticDelta)
            {
                return(StaticDelta);
            }

            //
            // Retrieve material balance from the Composition:
            //
            getValue(out Eval mDelta, out Eval mTotal);

            if (Pawn != 0)              // Else PawnHash == default(Hashcode)
            {
                pp = State.GetPXP(this);

                mDelta += pp.Delta;
                mTotal += pp.Total;
#if EvalWrongBishop
                if (punishWrongBishop(pp.BlackPRP & PRPFlags.Both, Side[Black].FlagsHi))
                {
                    mDelta += mWrongBishopWeight; // Black has Wrong Bishop
                }
                if (punishWrongBishop(pp.WhitePRP & PRPFlags.Both, Side[White].FlagsHi))
                {
                    mDelta -= mWrongBishopWeight; // White has Wrong Bishop
                }
#endif
            }
#if TradePieces
            if (mTotal > 0)
            {
                //
                // The following provides an incentive for the stronger
                // side to exchange material and for the weaker side to
                // avoid such exchanges.  The value is Zero in an equal
                // position, and grows to a maximum of one centipawn if
                // the weaker side has been stripped of all material.
                //
                // Intuitively: Exchanges reduce the Total material but
                // leave the Delta unaffected; and Delta can range from
                // Zero to the Total.  Thus, their quotient ranges from
                // Zero to One.
                //
                //[Note]A refinement is needed to prefer trading Pieces
                // over Pawns in the endgame.
                //
                var mIncentive = (Eval)(mPawnWeight * mDelta / mTotal);
                mDelta += mIncentive;
            }
#endif
            //
            //[Note]staticEval() prepares StaticTotal for any isEndgame() tests
            //
            StaticTotal = mTotal;       // Update for isEndgame()
            StaticDelta = mDelta;
            return(mDelta);
        }
示例#3
0
        public async Task Move(Client client, Room room, PawnPosition @from, PawnPosition target)
        {
            var clientRoomsResult = await this.RoomService.Status(client);

            var clientRooms = clientRoomsResult.Match(x => x, e => throw e);

            if (clientRooms.FirstOrDefault(r => r.Name == room.Name) is Room r)
            {
                var actualGame = this.ApplicationDbContext.Games.FirstOrDefault(x => x.State == GameState.InPlay && x.RoomId == room.Id);
                if (actualGame == null)
                {
                    var items = new List <MoveJsonEntity>();
                    actualGame = new GameEntity
                    {
                        PlayerOneId = client.Id,
                        State       = GameState.InPlay,
                        RoomId      = r.Id,
                        Moves       = items
                    };
                    this.ApplicationDbContext.Add(actualGame);
                    try
                    {
                        await this.ApplicationDbContext.SaveChangesAsync();
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
                var player = actualGame.PlayerOneId == client.Id ? Player.One : actualGame.PlayerTwoId == client.Id ? Player.Two : throw new Exception("Player can be matched");
                var board  = Map(actualGame);
                var mje    = new MoveJsonEntity
                {
                    From = new PositionEntity
                    {
                        Column = @from.Col,
                        Row    = @from.Row
                    },
                    To = new PositionEntity
                    {
                        Column = target.Col,
                        Row    = target.Row
                    },
                    Player = (Data.Player)((int)player)
                };
                board = UpdatePosition(board, mje);
                actualGame.Moves.Add(mje);
                actualGame.Moves = actualGame.Moves;

                if (board.Board.Values.Count(x => x is King) < 2)
                {
                    actualGame.State = GameState.Finished;
                }

                await this.ApplicationDbContext.SaveChangesAsync();
            }
            else
            {
                throw new Exception("Client hadn't subscribed current room.");
            }
        }