Exemple #1
0
        private static double EvaluteMove(IBoard board, IPiece piece)
        {
            int pieceMinX;
            int pieceMinY;
            int pieceMaxX;
            int pieceMaxY;

            piece.GetAbsoluteBoundingRectangle(out pieceMinX, out pieceMinY, out pieceMaxX, out pieceMaxY);

            int totalHeight              = BoardHelper.GetTotalCellHeight(board);
            int completedRows            = BoardHelper.GetTotalCompletedRows(board);
            int totalHoles               = Enumerable.Range(1, board.Width).Aggregate(0, (i, i1) => i + BoardHelper.GetBuriedHolesForColumn(board, i1));
            int totalBlockades           = Enumerable.Range(1, board.Width).Aggregate(0, (i, i1) => i + BoardHelper.GetBlockadesForColumn(board, i1));
            int edgeTouchingAnotherBlock = 0; // TODO
            int edgeTouchingWall         = 0; // TODO
            int edgeTouchingFloor        = 0;

            //double rating = 0;
            //rating += -0.03 * totalHeight;
            //rating += -7.5 * totalHoles;
            //rating += -3.5 * totalBlockades;
            //rating += 8.0 * completedRows;
            //rating += 3.0 * edgeTouchingAnotherBlock;
            //rating += 2.5 * edgeTouchingWall;
            //rating += 5.0 * edgeTouchingFloor;
            //double rating = 0;
            //rating += -3.78 * totalHeight;
            //rating += -2.31 * totalHoles;
            //rating += -0.59 * totalBlockades;
            //rating += 1.6 * completedRows;
            //rating += 3.97 * edgeTouchingAnotherBlock;
            //rating += 6.52 * edgeTouchingWall;
            //rating += 0.65 * edgeTouchingFloor;
            double rating = 0;

            rating += -0.868099 * totalHeight;
            rating += -2.45402 * totalHoles;
            rating += -0.236702 * totalBlockades;
            rating += 3.59764 * completedRows;
            rating += 5.33378 * edgeTouchingAnotherBlock;
            rating += 8.20521 * edgeTouchingWall;
            rating += 0.00 * edgeTouchingFloor;

            return(rating);
        }
Exemple #2
0
        // The following evaluation function was adapted from Pascal code submitted by:
        // Pierre Dellacherie (France).  (E-mail : [email protected])
        //
        // This amazing one-piece algorithm completes an average of roughly 600 000
        // rows, and often attains 2 000 000 or 2 500 000 rows.  However, the algorithm
        // sometimes completes as few as 15 000 rows.  I am fairly certain that this
        // is NOT due to statistically abnormal patterns in the falling piece sequence.
        //
        // Pierre Dellacherie corresponded with me via e-mail to help me with the
        // conversion of his Pascal code to C++.
        //
        // WARNING:
        //     If there is a single board and piece combination with the highest
        //     'rating' value, it is the best combination.  However, among
        //     board and piece combinations with EQUAL 'rating' values,
        //     the highest 'priority' value wins.
        //
        //     So, the complete rating is: { rating, priority }.
        private static void EvaluteMove(IBoard board, IPiece piece, out double rating, out int priority)
        {
            int pieceMinX;
            int pieceMinY;
            int pieceMaxX;
            int pieceMaxY;

            piece.GetAbsoluteBoundingRectangle(out pieceMinX, out pieceMinY, out pieceMaxX, out pieceMaxY);

            // Landing Height (vertical midpoint)
            double landingHeight = 0.5 * (pieceMinY + pieceMaxY);

            //
            int completedRows          = BoardHelper.GetTotalCompletedRows(board);
            int erodedPieceCellsMetric = 0;

            if (completedRows > 0)
            {
                // Count piece cells eroded by completed rows before doing collapse on pile.
                int countPieceCellsEliminated = BoardHelper.CountPieceCellsEliminated(board, piece, true);

                // Now it's okay to collapse completed rows
                board.CollapseCompletedRows();

                // Weight eroded cells by completed rows
                erodedPieceCellsMetric = (completedRows * countPieceCellsEliminated);
            }

            //
            int pileHeight = BoardHelper.GetPileMaxHeight(board);

            // Each empty row (above pile height) has two (2) "transitions"
            // (We could call ref_Board.GetTransitionCountForRow( y ) for
            // these unoccupied rows, but this is an optimization.)
            int boardRowTransitions = 2 * (board.Height - pileHeight);

            // Only go up to the pile height, and later we'll account for the
            // remaining rows transitions (2 per empty row).
            for (int y = 1; y <= pileHeight; y++)
            {
                boardRowTransitions += BoardHelper.GetTransitionCountForRow(board, y);
            }

            //
            int boardColumnTransitions = 0;
            int boardBuriedHoles       = 0;
            int boardWells             = 0;

            for (int x = 1; x <= board.Width; x++)
            {
                boardColumnTransitions += BoardHelper.GetTransitionCountForColumn(board, x);
                boardBuriedHoles       += BoardHelper.GetBuriedHolesForColumn(board, x);
                boardWells             += BoardHelper.GetAllWellsForColumn(board, x);
            }

            // Final rating
            //   [1] Punish landing height
            //   [2] Reward eroded piece cells
            //   [3] Punish row    transitions
            //   [4] Punish column transitions
            //   [5] Punish buried holes (cellars)
            //   [6] Punish wells

            rating  = 0.0;
            rating += -1.0 * landingHeight;
            rating += 1.0 * erodedPieceCellsMetric;
            rating += -1.0 * boardRowTransitions;
            rating += -1.0 * boardColumnTransitions;
            rating += -4.0 * boardBuriedHoles;
            rating += -1.0 * boardWells;

            // PRIORITY:
            //   Priority is further differentiation between possible moves.
            //   We further rate moves accoding to the following:
            //            * Reward deviation from center of board
            //            * Reward pieces to the left of center of the board
            //            * Punish rotation
            //   Priority is less important than the rating, but among equal
            //   ratings we select the option with the greatest priority.
            //   In principle we could simply factor priority in to the rating,
            //   as long as the priority was less significant than the smallest
            //   variations in rating, but for large board widths (>100), the
            //   risk of loss of precision in the lowest bits of the rating
            //   is too much to tolerate.  So, this priority is stored in a
            //   separate variable.

            int absoluteDistanceX = Math.Abs(piece.PosX - board.PieceSpawnX);

            priority  = 0;
            priority += (100 * absoluteDistanceX);
            if (piece.PosX < board.PieceSpawnX)
            {
                priority += 10;
            }
            priority -= piece.Orientation - 1;
        }