// Constructor. Map and source are necessarily passed. The influence function can be made to // have a default value. public InfluenceSourceMap(Map currentMap, Coords source, InfluenceSpreadFunction f) { this._currentMap = currentMap; this._source = source; this._f = f; // zero our the floats this._influenceMap = new float[_currentMap.BoundX, _currentMap.BoundY]; }
/// <summary> /// Generates the influence map. /// Uses a silly recursive algorithm. /// Stopping conditions: Let's use two, to avoid stupid infinite loops. /// One is a distance threshold check. /// Second is a min influence threshold check. /// </summary> public float[,] GenerateInfluenceMap(UInt16 sizex, UInt16 sizey, Coords source, InfluenceSpreadFunction f) { float[,] influenceMap = new float[sizex, sizey]; // boolean array to keep note of which tiles have been processed BitArray[] takenCareOf = new BitArray[sizex]; for (int i = 0; i < sizex; ++i) { takenCareOf[i] = new BitArray(sizey); } takenCareOf[source.X][source.Y] = true; // sets up two queues - one for the current pass, one for the next one // distance increments by one at each pass // if too slow, the process should be broken up so it does a number of passes each tick Queue <Coords> currentQueue = new Queue <Coords>(); Queue <Coords> nextQueue = new Queue <Coords>(); currentQueue.Enqueue(source); UInt32 currentDistance = 0; // main loop // Stopping conditions: the two queues are exhausted, OR InfluenceMapMaxDistance is reached while ( ((currentQueue.Count > 0) & (nextQueue.Count > 0)) | (currentDistance < Constants.InfluenceMapMaxDistance) ) { // Checks if it's time to start the next pass if (currentQueue.Count == 0) { currentQueue = nextQueue; nextQueue = new Queue <Coords>(); currentDistance++; continue; } Coords currentCoords = currentQueue.Peek(); // Analyzes the neighbors of the current Tile for possible additions to nextQueue for (byte i = 0; i < 8; i++) { Direction currentDir = (Direction)i; Coords toCheck = StaticMathFunctions.CoordsNeighboringInDirection(currentCoords, currentDir); if (toCheck.X >= 0 && toCheck.X < sizex && toCheck.Y >= 0 && toCheck.Y < sizey) { if (!takenCareOf[toCheck.X][toCheck.Y]) { nextQueue.Enqueue(toCheck); takenCareOf[toCheck.X][toCheck.Y] = true; } } } float newVal = f(currentDistance); // Check to avert infnite / excessively deep loop if (newVal > Constants.InfluenceMapMinThreshold) { influenceMap[currentCoords.X, currentCoords.Y] = newVal; } currentQueue.Dequeue(); } return(influenceMap); }
public InfluenceSourceMap(Map currentMap, Coords source, InfluenceSpreadFunction f, float minTreshold, float maxRange) : this(currentMap, source, f) { _lowTreshold = minTreshold; _maxTreshold = maxRange; }