예제 #1
0
        public void FloodFill()
        {
            Bitmap map = new Bitmap(new string[]
                                        {
                                            "111111111111111111",
                                            "100000000000001001",
                                            "100000000000001001",
                                            "100001111111001001",
                                            "100001010001001001",
                                            "100001000101001001",
                                            "100001111111000001",
                                            "111011000000001111",
                                            "100000001000010001",
                                            "100000001000010001",
                                            "111111111111111111"
                                        });

            Debug.WriteLine(map.ToString());

            Evaluator<LocationNode> eval = new Evaluator<LocationNode>();
            FloodFillStrategy strategy = new FloodFillStrategy(map, new VectorInt(2, 2));
            eval.Evaluate(strategy);

            Debug.WriteLine(strategy.Result.ToString());

            List<LocationNode> path = strategy.GetShortestPath(new VectorInt(9, 9));
            Assert.IsNotNull(path);

            Debug.WriteLine(StringHelper.Join(path, delegate(LocationNode node) { return node.Location.ToString(); }, ", "));

            Debug.WriteLine(map.ToString());

            // Expected value
            Assert.AreEqual(new VectorInt(9, 9), path[path.Count - 1].Location);
        }
예제 #2
0
 /// <summary>
 /// Strong Constructor. Start with the dead map including all walls.
 /// </summary>
 /// <param name="goalMap"></param>
 /// <param name="wallMap"></param>
 public DeadMapState(SolverNode currentNode, Bitmap goalMap, Bitmap wallMap, DeadMapAnalysis deadMapAnalysis)
     : this(goalMap, wallMap, deadMapAnalysis)
 {
     this.crateMap = currentNode.CrateMap;
     this.moveMap = currentNode.MoveMap;
     this.dynamicNode = currentNode;
 }
예제 #3
0
        /// <summary>
        /// Generate the move map for a current position
        /// </summary>
        /// <param name="boundryMap"></param>
        /// <param name="crateMap">May be null, assumes boundryMap is constraintmap</param>
        /// <param name="playerPosition"></param>
        /// <returns></returns>
        public static Bitmap GenerateMoveMap(Bitmap boundryMap, Bitmap crateMap, VectorInt playerPosition)
        {
            Bitmap constraints = boundryMap;
            if (crateMap != null) constraints = boundryMap.BitwiseOR(crateMap);

            // Flood fill from player position to remove any unreachable positions
            FloodFillStrategy floodFill = new FloodFillStrategy(constraints, playerPosition);
            Evaluator<LocationNode> eval = new Evaluator<LocationNode>();
            eval.Evaluate(floodFill);

            return floodFill.Result;
        }
예제 #4
0
        /// <summary>
        /// Strong Constructor. Start with the dead map including all walls.
        /// </summary>
        /// <param name="goalMap"></param>
        /// <param name="wallMap"></param>
        public DeadMapState(Bitmap goalMap, Bitmap wallMap, DeadMapAnalysis deadMapAnalysis)
            : base("Dead Map", wallMap.Size)
        {
            this.goalMap = goalMap;
            this.wallMap = wallMap;
            this.deadMapAnalysis = deadMapAnalysis;

            this.mapSize = wallMap.Size;

            if (goalMap == null) throw new ArgumentNullException("goalMap");
            if (wallMap == null) throw new ArgumentNullException("goalMap");
            if (deadMapAnalysis == null) throw new ArgumentNullException("deadMapAnalysis");
        }
예제 #5
0
        /// <summary>
        /// Find all recesses (goal and non-goal) in puzzle map
        /// </summary>
        /// <param name="staticAnalysis"></param>
        /// <param name="outRecesses"></param>
        /// <param name="outRecessMap"></param>
        public void FindRecesses(StaticAnalysis staticAnalysis, out List<Recess> outRecesses, out Bitmap outRecessMap)
        {
            outRecessMap = new Bitmap(staticAnalysis.WallMap.Size);
            outRecesses = new List<Recess>();

            foreach (VectorInt corner in staticAnalysis.CornerMap.TruePositions)
            {
                CheckRecessFromCorner(staticAnalysis, outRecesses, outRecessMap, corner, Direction.Up);
                CheckRecessFromCorner(staticAnalysis, outRecesses, outRecessMap, corner, Direction.Down);
                CheckRecessFromCorner(staticAnalysis, outRecesses, outRecessMap, corner, Direction.Left);
                CheckRecessFromCorner(staticAnalysis, outRecesses, outRecessMap, corner, Direction.Right);
            }
        }
예제 #6
0
 //##############################################################
 //##############################################################
 //##############################################################
 // Set operators
 /// <summary>
 /// Is the set a superset. Will return true is aSet==aSuperSet
 /// </summary>
 /// <param name="aSet"></param>
 /// <param name="aSuperSet"></param>
 /// <returns></returns>
 public bool isSuperSet(Bitmap aSuperSet)
 {
     // Unoptimised: Should be much faster to iterator through aSet until a single failure is found
     return (this.BitwiseAND(aSuperSet) == this);
 }
예제 #7
0
 /// <summary>
 /// Overload
 /// </summary>
 /// <param name="rhs"></param>
 /// <returns></returns>
 public Bitmap BitwiseOR(Bitmap rhs)
 {
     return BitwiseOR(this, rhs);
 }
예제 #8
0
 /// <summary>
 /// Overload
 /// </summary>
 /// <param name="rhs"></param>
 /// <returns></returns>
 public Bitmap BitwiseAND(Bitmap rhs)
 {
     return BitwiseAND(this, rhs);
 }
예제 #9
0
        //##############################################################
        //##############################################################
        //##############################################################
        // Bitwise Functions
        /// <summary>
        /// Perform a bitwize OR operation on the two maps
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        public static Bitmap BitwiseOR(Bitmap lhs, Bitmap rhs)
        {
            if (lhs.Size.X != rhs.Size.X && lhs.Size.Y != rhs.Size.Y)
                throw new InvalidOperationException(
                    string.Format("Bitmaps BitwiseOR may only be performed on identical sizes lhs:{0}; rhs:{1}",
                                  lhs.Size, rhs.Size));

            Bitmap result = new Bitmap(lhs.Size);

            for (int ccy = 0; ccy < lhs.Size.Y; ccy++)
            {
                result.map[ccy] = lhs.map[ccy] | rhs.map[ccy];
            }

            return result;
        }
예제 #10
0
        /// <summary>
        /// Perform a bitwize OR operation on the two maps
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        public static Bitmap BitwiseNOT(Bitmap lhs)
        {
            Bitmap result = new Bitmap(lhs.Size);

            for (int ccx = 0; ccx < lhs.Size.X; ccx++)
                for (int ccy = 0; ccy < lhs.Size.Y; ccy++)
                {
                    result[ccx, ccy] = !lhs[ccx, ccy];
                }

            return result;
        }
예제 #11
0
 /// <summary>
 /// Evluate a boolean result for each value in the Matrix creating a result boolean map
 /// </summary>
 /// <param name="boolAction"></param>
 /// <returns></returns>
 public Bitmap EvalBoolean(EvalBooleanDelegate boolAction)
 {
     Bitmap result = new Bitmap(Size);
     for (int ccx = 0; ccx < Width; ccx++)
         for (int ccy = 0; ccy < Height; ccy++)
         {
             result[ccx, ccy] = boolAction(values[ccx, ccy]);
         }
     return result;
 }
예제 #12
0
        /// <summary>
        /// Average the Matrix values in generations
        /// </summary>
        /// <returns></returns>
        public Matrix Average()
        {
            // Clone
            Matrix result = new Matrix(this);

            // Start will all set values
            Bitmap currentValues = result.BooleanNotZero();

            // Fill in the blanks
            bool valueSet = false;
            do
            {
                valueSet = false;

                Bitmap nextValues = new Bitmap(currentValues);

                for (int ccx = 0; ccx < Width; ccx++)
                for (int ccy = 0; ccy < Height; ccy++)
                {
                    if (currentValues[ccx,ccy] == false)
                    {
                        // Not set
                        float total = 0;
                        int count = 0;

                        // Left
                        if (ccx - 1 > 0 && currentValues[ccx - 1, ccy])
                        {
                            total += result[ccx - 1, ccy];
                        }
                        count++;

                        // Right
                        if (ccx+1 < Width && currentValues[ccx+1,ccy])
                        {
                            total += result[ccx + 1, ccy];
                        }
                        count++;

                        // Up
                        if (ccy - 1 > 0 && currentValues[ccx, ccy-1])
                        {
                            total += result[ccx, ccy - 1];
                        }
                        count++;

                        // Down
                        if (ccy + 1 < Height && currentValues[ccx, ccy+1])
                        {
                            total += result[ccx, ccy + 1];
                        }
                        count++;

                        if (total > 0)
                        {
                            valueSet = true;
                            result[ccx, ccy] = total/count;
                            nextValues[ccx, ccy] = true;
                        }
                    }
                }
                currentValues = nextValues;

            } while (valueSet);

            return result;
        }
예제 #13
0
        /// <summary>
        /// Generate a bitmap for a particular cell state
        /// </summary>
        /// <param name="cell">Search for</param>
        /// <returns></returns>
        public Bitmap ToBitmap(CellStates cell)
        {
            SizeInt size = Size;

            Bitmap result = new Bitmap(size);
            for (int cx = 0; cx < size.X; cx++)
                for (int cy = 0; cy < size.Y; cy++)
                {
                    if (this[cx, cy] == cell) result[cx, cy] = true;
                }

            return result;
        }
예제 #14
0
        /// <summary>
        /// Average the Matrix values in generations
        /// </summary>
        /// <param name="VoidCells">Positions that are not include (null/void/zero) in the average process</param>
        /// <returns></returns>
        public Matrix Average(Bitmap VoidCells)
        {
            // Clone
            Matrix result = new Matrix(this);

            // Start will all set values
            Bitmap currentValues = result.BooleanNotZero();

            // Fill in the blanks
            bool valueSet = false;
            do
            {
                valueSet = false;

                Bitmap nextValues = new Bitmap(currentValues);

                for (int ccx = 0; ccx < Width; ccx++)
                for (int ccy = 0; ccy < Height; ccy++)
                {
                    // Skip void cells
                    if (VoidCells[ccx, ccy]) continue;

                    if (currentValues[ccx,ccy] == false)
                    {
                        // Not set
                        float total = 0;
                        int count = 0;

                        // Left
                        if (ccx - 1 > 0 && currentValues[ccx - 1, ccy])
                        {
                            total += result[ccx - 1, ccy];
                            count++;
                        }

                        // Right
                        if (ccx+1 < Width && currentValues[ccx+1,ccy])
                        {
                            total += result[ccx + 1, ccy];
                            count++;
                        }

                        // Up
                        if (ccy - 1 > 0 && currentValues[ccx, ccy-1])
                        {
                            total += result[ccx, ccy - 1];
                            count++;
                        }

                        // Down
                        if (ccy + 1 < Height && currentValues[ccx, ccy+1])
                        {
                            total += result[ccx, ccy + 1];
                            count++;
                        }

                        if (false)
                        {
                            // Top Left
                            if (ccx - 1 > 0 && ccy - 1 > 0 && currentValues[ccx - 1, ccy - 1])
                            {
                                total += result[ccx - 1, ccy - 1];
                                count++;
                            }

                            // Top Right
                            if (ccx + 1 < Width && ccy - 1 > 0 && currentValues[ccx + 1, ccy - 1])
                            {
                                total += result[ccx + 1, ccy - 1];
                                count++;
                            }

                            // Bottom Left
                            if (ccx - 1 > 0 && ccy + 1 < Height && currentValues[ccx - 1, ccy + 1])
                            {
                                total += result[ccx - 1, ccy + 1];
                                count++;
                            }

                            // Bottom Right
                            if (ccx + 1 < Width && ccy + 1 < Height && currentValues[ccx + 1, ccy + 1])
                            {
                                total += result[ccx + 1, ccy + 1];
                                count++;
                            }
                        }

                        if (count > 0)
                        {
                            valueSet = true;
                            result[ccx, ccy] = total/count/3f;
                            nextValues[ccx, ccy] = true;
                        }
                    }
                }
                currentValues = nextValues;

            } while (valueSet);

            return result;
        }
예제 #15
0
        /// <summary>
        /// Moving in each direction try to find another non-goal corner
        /// </summary>
        private void CheckRecessFromCorner(StaticAnalysis staticAnalysis,  List<Recess> outRecesses, Bitmap outRecessMap, VectorInt CheckPos, Direction CheckDirection)
        {
            RectangleInt region = new RectangleInt(new VectorInt(0, 0), outRecessMap.Size.Subtract(1, 1));
            VectorInt pos = CheckPos;

            Direction sideA;
            Direction sideB;
            // Check Recess wall side
            if (CheckDirection == Direction.Up || CheckDirection == Direction.Down)
            {
                sideA = Direction.Left;
                sideB = Direction.Right;
            }
            else
            {
                sideA = Direction.Up;
                sideB = Direction.Down;
            }

            bool hasSideA = true;
            bool hasSideB = true;

            // Try to find another corner with SideA or SideB
            while (region.Contains(pos))
            {
                // Check Fail

                if (staticAnalysis.WallMap[pos]) return; // Wall in way- Fail

                if (hasSideA)
                {
                    if (!staticAnalysis.WallMap[pos.Offset(sideA)]) hasSideA = false;
                }

                if (hasSideB)
                {
                    if (!staticAnalysis.WallMap[pos.Offset(sideB)]) hasSideB = false;
                }

                if (!hasSideA && !hasSideB) return;

                // Check success
                // Don't check the first time
                if (pos != CheckPos)
                {
                    if (staticAnalysis.CornerMap[pos])
                    {
                        Recess newRecess = new Recess("Recess #"+(outRecesses.Count+1).ToString(), outRecessMap.Size);
                        outRecesses.Add(newRecess);
                        // Winner
                        // Mark all in path as corner
                        VectorInt setTrue = CheckPos;
                        while (setTrue != pos)
                        {
                            // Individual
                            newRecess[setTrue] = true;
                            // Master (all recesses)
                            outRecessMap[setTrue] = true;

                            // Next
                            setTrue = setTrue.Offset(CheckDirection);
                        }

                        // Do the final node
                        newRecess[pos] = true;
                        outRecessMap[pos] = true;

                        newRecess.GoalCount = newRecess.BitwiseAND(staticAnalysis.GoalMap).Count;
                        return;
                    }
                }

                // Next
                pos = pos.Offset(CheckDirection);
            }
        }