예제 #1
0
        public static void AddNode(int x, int y, int tileIndex, int state, char type)
        {
            CaveStateNode node = new CaveStateNode();

            node.CaveTool  = state;
            node.TileX     = x;
            node.TileY     = y;
            node.TileIndex = tileIndex;
            node.TileType  = type;
            _allStates[state][tileIndex] = node;
        }
예제 #2
0
        public static int Distance(CaveStateNode tileA, CaveStateNode tileB)
        {
            int res = Math.Abs(tileA.TileX - tileB.TileY) + Math.Abs(tileA.TileX - tileB.TileY);

            if (tileA.CaveTool != tileB.CaveTool)
            {
                res += 7;
            }

            return(res);
        }
예제 #3
0
        private static void AddTransitionIfValid(CaveStateNode node, int p1, int p2, int p3)
        {
            CaveStateNode target = GetNode(p1, p2, p3);

            if (target != null && target != node && target.IsValidState(node.CaveTool))
            {
                if (node.CaveTool != target.CaveTool)
                {
                    node.AddTransition(target, _toolChangeCost);
                }
                else
                {
                    node.AddTransition(target, _advancementCost);
                }
            }
        }
예제 #4
0
        public static void Solve()
        {
            int targetX = 5;
            int targetY = 746;
            int depth   = 4002;
            int sumRisk = 0;

            _maxX          = (targetX + _buffer);
            _maxY          = (targetY + _buffer);
            _erosionLevels = new int[_maxX * _maxY];
            _base          = new CaveStateNode[_maxX * _maxY];
            //StringBuilder sb = new StringBuilder();
            for (int y = 0; y < _maxY; y++)
            {
                for (int x = 0; x < _maxX; x++)
                {
                    int index = Int32.MinValue;
                    if (y == 0 && x == 0)
                    {
                        index = 0;
                    }
                    else if (x == targetX && y == targetY)
                    {
                        index = 0;
                    }
                    else if (y == 0)
                    {
                        index = x * 16807;
                    }
                    else if (x == 0)
                    {
                        index = y * 48271;
                    }
                    else
                    {
                        index = _erosionLevels[GetTileIndex(x - 1, y)] * _erosionLevels[GetTileIndex(x, y - 1)];
                    }

                    int tileIndex = GetTileIndex(x, y);
                    int level     = (index + depth) % 20183;
                    _erosionLevels[tileIndex] = level;

                    CaveStateNode state = new CaveStateNode();
                    _base[tileIndex] = state;

                    state.TileX     = x;
                    state.TileY     = y;
                    state.TileIndex = tileIndex;
                    state.CaveTool  = CaveTools.None;
                    int typeMod = level % 3;

                    char c;
                    if (y == 0 && x == 0)
                    {
                        state.TileType = CaveStateNode.Mouth;
                    }
                    else if (x == targetX && y == targetY)
                    {
                        state.TileType = CaveStateNode.Target;
                    }
                    else if (typeMod == 0)
                    {
                        state.TileType = CaveStateNode.Rocky;
                    }
                    else if (typeMod == 1)
                    {
                        state.TileType  = CaveStateNode.Wet;
                        state.RiskLevel = CaveStateNode.WetRisk;
                    }
                    else
                    {
                        state.TileType  = CaveStateNode.Narrow;
                        state.RiskLevel = CaveStateNode.NarrowRisk;
                    }

                    if (state.TileX <= targetX && state.TileY <= targetY)
                    {
                        sumRisk += state.RiskLevel;
                    }
                }
            }

            _allStates[CaveTools.None]         = new CaveStateNode[_base.Length];
            _allStates[CaveTools.Torch]        = new CaveStateNode[_base.Length];
            _allStates[CaveTools.ClimbingGear] = new CaveStateNode[_base.Length];

            for (int y = 0; y < _maxY; y++)
            {
                for (int x = 0; x < _maxX; x++)
                {
                    for (int z = 0; z < 3; z++)
                    {
                        int           tileIndex = GetTileIndex(x, y);
                        CaveStateNode node      = _base[tileIndex];
                        if (node.IsValidState(z))
                        {
                            AddNode(x, y, tileIndex, z, node.TileType);
                        }
                    }
                }
            }

            List <CaveStateNode> _stateTransitions = new List <CaveStateNode>();

            for (int y = 0; y < _maxY; y++)
            {
                for (int x = 0; x < _maxX; x++)
                {
                    _stateTransitions.Clear();
                    for (int z = 0; z < 3; z++)
                    {
                        CaveStateNode node = GetNode(x, y, z);
                        if (node != null)
                        {
                            _stateTransitions.Add(node);
                            AddTransitionIfValid(node, x - 1, y, z);
                            AddTransitionIfValid(node, x + 1, y, z);
                            AddTransitionIfValid(node, x, y + 1, z);
                            AddTransitionIfValid(node, x, y - 1, z);
                        }
                    }

                    if (_stateTransitions.Count > 1)
                    {
                        foreach (var a in _stateTransitions)
                        {
                            foreach (var b in _stateTransitions)
                            {
                                if (a != b)
                                {
                                    AddTransitionIfValid(a, b.TileX, b.TileY, b.CaveTool);
                                }
                            }
                        }
                    }
                }
            }

            CaveStateNode start = _allStates[CaveTools.Torch][GetTileIndex(0, 0)];
            CaveStateNode end   = _allStates[CaveTools.Torch][GetTileIndex(targetX, targetY)];

            Log.WriteLine("Start Node");
            Log.WriteLine(start.DebugLog());
            Log.WriteLine(start.DescribeNeighbors());
            Log.WriteLine(Environment.NewLine);
            Log.WriteLine("Target Node");
            Log.WriteLine(end.DebugLog());
            Log.WriteLine(end.DescribeNeighbors());


            int totalCost = 0;
            List <CaveStateNode> bestPath = new List <CaveStateNode>();

            CaveStatePathSolver.RequestPathFromTile(start, end, bestPath, out totalCost);
            Log.WriteLine("Found a path that should take " + totalCost + " minutes");
        }
예제 #5
0
 public void AddTransition(CaveStateNode node, int cost)
 {
     Transitions[node] = cost;
 }
예제 #6
0
        public static bool RequestPathFromTile(CaveStateNode startTile, CaveStateNode targetTile, List <CaveStateNode> bestPath, out int totalCost)
        {
            // Clear our initial state
            _costs.Clear();
            _frontier.Clear();
            _pathInProgress.Clear();
            _scratch.Clear();
            bestPath.Clear();

            totalCost = Int32.MaxValue;
            _frontier.Enqueue(startTile, 0);
            _costs[startTile]          = 0;
            _pathInProgress[startTile] = null;

            do
            {
                /*
                 * _frontier.Sort(delegate(CaveStateNode tA, CaveStateNode tB)
                 * {
                 *
                 *
                 *  return (_costs[tA] + Distance(tA, targetTile)).CompareTo(_costs[tB] + Distance(tB, targetTile));
                 * });*/

                CaveStateNode currentTile = _frontier.Dequeue();
                if (currentTile == targetTile)
                {
                    break;
                }
                //_frontier.RemoveAt(0);

                Dictionary <CaveStateNode, int> transitions = currentTile.Transitions;
                foreach (var kvp in transitions)
                {
                    var neighbor        = kvp.Key;
                    int incrementalCost = kvp.Value;
                    int navCost         = 0;
                    _costs.TryGetValue(currentTile, out navCost);
                    navCost += incrementalCost;
                    int knownCost = 0;
                    if (!_costs.TryGetValue(neighbor, out knownCost))
                    {
                        knownCost = Int32.MaxValue;
                    }

                    if (navCost < knownCost)
                    {
                        _costs[neighbor]          = navCost;
                        _pathInProgress[neighbor] = currentTile;
                        _frontier.Enqueue(neighbor, navCost + Distance(neighbor, targetTile));
                    }
                }
            } while (_frontier.Count > 0);

            if (_pathInProgress.ContainsKey(targetTile))
            {
                var next = targetTile;
                while (next != startTile)
                {
                    bestPath.Add(next);
                    next = _pathInProgress[next];
                }
                bestPath.Reverse();
                totalCost = _costs[targetTile];
                return(true);
            }


            return(false);
        }