private List<Address> checkColumn(ColumnPortion cp, Address origin, Map map, Queue<ColumnPortion> queue, int octant, int range) { List<Address> result = new List<Address>(); DirectionVector topVector = cp.TopVector; DirectionVector bottomVector = cp.BottomVector; int x = cp.X; int topY; if (cp.X == 0) topY = 0; else { int quotient = (2 * cp.X + 1) * cp.TopVector.Y / (2 * cp.TopVector.X); int remainder = (2 * cp.X + 1) * cp.TopVector.Y % (2 * cp.TopVector.X); topY = quotient; if (remainder > cp.TopVector.X) topY = quotient++; } int bottomY; if (cp.X == 0) bottomY = 0; else { int quotient = (2 * cp.X - 1) * cp.BottomVector.Y / (2 * cp.BottomVector.X); int remainder = (2 * cp.X - 1) * cp.BottomVector.Y % (2 * cp.BottomVector.X); bottomY = quotient; if (remainder >= cp.BottomVector.X) bottomY = quotient++; } bool? wasLastCellOpaque = null; for (int y = topY; y >= bottomY; --y) { bool inRadius = IsInRadius(x, y, range); if (inRadius) { Address temp = TranslateOctant(new Address(x, y), octant); // The current cell is in the field of view. result.Add(new Address(origin.x + temp.x, origin.y + temp.y)); } // A cell that was too far away to be seen is effectively // an opaque cell; nothing "above" it is going to be visible // in the next column, so we might as well treat it as // an opaque cell and not scan the cells that are also too // far away in the next column. bool currentIsOpaque = !inRadius || isOpaque(map, origin, x, y, octant); if (wasLastCellOpaque != null) { if (currentIsOpaque) { // We've found a boundary from transparent to opaque. Make a note // of it and revisit it later. if (!wasLastCellOpaque.Value) { // The new bottom vector touches the upper left corner of // opaque cell that is below the transparent cell. queue.Enqueue(new ColumnPortion( x + 1, new DirectionVector(x * 2 - 1, y * 2 + 1), topVector)); } } else if (wasLastCellOpaque.Value) { // We've found a boundary from opaque to transparent. Adjust the // top vector so that when we find the next boundary or do // the bottom cell, we have the right top vector. // // The new top vector touches the lower right corner of the // opaque cell that is above the transparent cell, which is // the upper right corner of the current transparent cell. topVector = new DirectionVector(x * 2 + 1, y * 2 + 1); } } wasLastCellOpaque = currentIsOpaque; } // Make a note of the lowest opaque-->transparent transition, if there is one. if (wasLastCellOpaque != null && !wasLastCellOpaque.Value) queue.Enqueue(new ColumnPortion(x + 1, bottomVector, topVector)); return result; }
private static void computeFieldOfViewInOctantZero( byte octant, bool[] fovGrid, int fovGridMinX, int fovGridMinY, int fovGridWidth, bool[] oldFovGrid, int oldFovGridMinX, int oldFovGridMaxX, int oldFovGridMinY, int oldFovGridMaxY, int oldFovGridWidth, int radius, int r_r_4, int startX, int startY, int maxX, int maxY, bool[] viewBlockerCells, bool handleSeenAndCache, MapComponentSeenFog mapCompSeenFog, Faction faction, int[] factionShownCells, int targetX, int targetY, int x, int topVectorX, int topVectorY, int bottomVectorX, int bottomVectorY) { int topY; int bottomY; bool inRadius; bool currentIsOpaque; bool wasLastCellOpaque; bool lastCellCalcuated; int quotient; int remainder; int fogGridIdx; int oldFogGridIdx; int x2; int y2; int worldY = 0; int worldX = 0; bool firstIteration = true; while (firstIteration || !queue.Empty()) { if (!firstIteration) { ref ColumnPortion columnPortion = ref queue.Dequeue(); x = columnPortion.x; topVectorX = columnPortion.topVectorX; topVectorY = columnPortion.topVectorY; bottomVectorX = columnPortion.bottomVectorX; bottomVectorY = columnPortion.bottomVectorY; }