private bool IsMoveValid(int nextMatrixRow, int nextMatrixColumn, int color, bool isLastPoint, FlowPoint destination) { // outside of bounds if (destination == null || nextMatrixRow < 0 || nextMatrixRow >= nrOfRows || nextMatrixColumn < 0 || nextMatrixColumn >= nrOfColumns) { return(false); } FlowPoint point = flowMatrix[nextMatrixRow][nextMatrixColumn]; // not last move and crossing itself or another color if (!isLastPoint && point.color != 0 && (destination != point || point.color != color)) { return(false); } // is last move and does not end on the proper color if the destionation for that point is null or the color is different if (isLastPoint && (point.color != color || point.destination == null || point != destination)) { return(false); } // is valid return(true); }
/* * private void FromRiverSource(Vec2i source, Vec2i mainDir) * { * * int i = 0; * Vec2i end = null; * Vec2i current = source; * //Ray cast from the source to find the ocean point at this rivers end * while(end == null) * { * i++; * current += mainDir; * if(ChunkBases[current.x, current.z].Biome == ChunkBiome.ocean) * { * end = current; * } * if (i > World.WorldSize) * return; * * } * i = 0; * * Vec2i last = source; * * current = source + mainDir; * bool isDone = false; * * Vector2 lastDir = (end - current).AsVector2().normalized; * Vector2 exactCurrent = current.AsVector2(); * * List<Vec2i> river = new List<Vec2i>(); * * while (!isDone) * { * * * * i++; * // Vector2 currentFlow = FlowField[current.x, current.z]; * * float fx = PerlinNoise(current.x, current.z, 36)*2 - 1; * float fz = PerlinNoise(current.x, current.z, 37)*2 - 1; * Vector2 noiseFlow = new Vector2(fx, fz); * Vector2 flowField = FlowField[current.x, current.z]; * Vector2 targetFlow = (end - current).AsVector2().normalized; * * Vector2 flow = (noiseFlow + 4 * targetFlow + 3 * flowField).normalized; * exactCurrent += flow; * current = Vec2i.FromVector2(exactCurrent); * int check = Mathf.Min(river.Count, 5); * bool isValid = true; * for(int j=0; j< check; j++) * { * if (river[river.Count - j - 1] == current) * isValid = false; * } * if (!isValid) * { * current += mainDir; * exactCurrent = current.AsVector2(); * } * * * if (ChunkBases[current.x, current.z].Biome == ChunkBiome.ocean) * isDone = true; * ChunkBases[current.x, current.z].SetChunkFeature(new ChunkRiverNode()); * river.Add(current); * if (i > 2048) * return; * * } * * * }*/ private void ReverseFlowRiver(Vec2i start, int length, int distSinceFork = 0) { //Give rivers a slight biase towards the middle of the map Vector2 bias = -(new Vector2(World.WorldSize / 2, World.WorldSize / 2) - start.AsVector2()).normalized; Vec2i current = start; Vector2 fullCurrent = current.AsVector2(); Vec2i last = Vec2i.FromVector2(fullCurrent + bias); List <FlowPoint> inputFlowPoints = new List <FlowPoint>(5); for (int i = 0; i < length; i++) { distSinceFork++; inputFlowPoints.Clear(); //if this chunk is a river node already, we have reached the end of this river branch if (ChunkBases[current.x, current.z].ChunkFeature is ChunkRiverNode) { //return; } //Add a river node here ChunkBases[current.x, current.z].SetChunkFeature(new ChunkRiverNode(current)); //We iterate each of the near chunks foreach (Vec2i v in Vec2i.OCT_DIRDIR) { //Coordinate of point of interest Vec2i p = v + current; //If this is the point we just came from, ignore it if (last == p) { continue; } Vector2 vFlow = FlowField[p.x, p.z]; //Find the coordinate that this point flows into Vec2i pointFlowPos = Vec2i.FromVector2(p.AsVector2() + vFlow); //Check if this point flows into our current point if (pointFlowPos == current) { FlowPoint fp = new FlowPoint(); fp.Pos = p; fp.Dir = vFlow; inputFlowPoints.Add(fp); } } //If no points flow here, then the river has reached an end (add lakes?) if (inputFlowPoints.Count == 0) { Debug.Log("zero flow"); Vector2 currentToLast = (current - last).AsVector2(); fullCurrent = fullCurrent - currentToLast; //Debug.Log("zero error..."); //return; } else if (inputFlowPoints.Count == 1) { Debug.Log("single flow"); fullCurrent = fullCurrent - inputFlowPoints[0].Dir; } else { if (distSinceFork < 40) { fullCurrent = fullCurrent - GenRan.RandomFromList(inputFlowPoints).Dir; Debug.Log("No fork - dist"); } else { Debug.Log("fork"); //If we are over 40, then we can create a fork //only 2 forks maximum while (inputFlowPoints.Count > 2) { inputFlowPoints.RemoveAt(GenRan.RandomInt(0, inputFlowPoints.Count)); } ReverseFlowRiver(inputFlowPoints[0].Pos, length - i, 0); ReverseFlowRiver(inputFlowPoints[1].Pos, length - i, 0); Debug.Log("forks"); return; } } last = new Vec2i(current.x, current.z); current = Vec2i.FromVector2(fullCurrent); /* * //We iterate all directions * Vector2 grad = (FlowField[current.x, current.z] + 0.1f * bias).normalized; * fullCurrent = fullCurrent - grad; * current = Vec2i.FromVector2(fullCurrent); */ } }
public void CheckPaths(string[] data) { List <int> pathOutputs = new List <int>(); int startI = (numberOfPositions * 2) + 3; int numberOfPaths = Int32.Parse(data[startI]); startI++; //MatrixModel<FlowPoint> mat = new MatrixModel<FlowPoint>(); //mat.height = nrOfRows; //mat.width = nrOfColumns; //mat.matrixData = flowMatrix; //MatrixModel<FlowPoint>.LogOnScreen(mat); int i = startI; int pathsCounter = 0; while (pathsCounter < numberOfPaths) { int color = Int32.Parse(data[i]); PositionRowColumn rowAndColumn = PositionRowColumn.FromString(data[i + 1], nrOfColumns); int pathLength = Int32.Parse(data[i + 2]); FlowPoint currentPoint = flowMatrix[rowAndColumn.matrixRow][rowAndColumn.matrixColumn]; FlowPoint destination = currentPoint.destination; int index = 1; int j = i + 3; int pathEnd = i + pathLength + 3; bool pathIsValid = true; while (j < pathEnd && pathIsValid) { int nextRow = currentPoint.matrixRow; int nextColumn = currentPoint.matrixColumn; switch (data[j][0].ToString().ToLower()) { case "n": nextRow = nextRow - 1; break; case "e": nextColumn = nextColumn + 1; break; case "s": nextRow = nextRow + 1; break; case "w": nextColumn = nextColumn - 1; break; } if (IsMoveValid(nextRow, nextColumn, currentPoint.color, j + 1 == pathEnd, destination)) { flowMatrix[nextRow][nextColumn].color = currentPoint.color; currentPoint = flowMatrix[nextRow][nextColumn]; index++; j++; } else { pathIsValid = false; } } pathOutputs.Add(pathIsValid ? 1 : -1); pathOutputs.Add(pathIsValid ? index - 1 : index); i += pathEnd; pathsCounter++; } Console.WriteLine(string.Join(' ', pathOutputs)); Console.WriteLine(); //MatrixModel<FlowPoint>.LogOnScreen(mat); }
public FlowReachability(FlowPoint entry, ControlFlowGraph graph, OperationVisitor <None, bool> suspensionPoint) { this.graph = graph; if (!Belongs(entry)) { throw new ArgumentException("Entry not belongs to graph"); } reachable = new Lazy <HashSet <FlowPoint> >( () => { var visited = new HashSet <FlowPoint>(); var visitedRegions = new HashSet <ControlFlowRegion>(); var stack = new Stack <FlowPoint>(); stack.Push(entry); while (stack.Count > 0) { var point = stack.Pop(); if (!visited.Add(point)) { continue; } var region = point.Block.EnclosingRegion; if (visitedRegions.Add(region)) { var tries = region.Containing(ControlFlowRegionKind.Try).Take(1); foreach (var @try in tries) { var parent = @try.EnclosingRegion; if (parent.Kind == ControlFlowRegionKind.TryAndCatch) { if (visitedRegions.Add(parent)) { var catchRegion = parent.NestedRegions[1]; var @catch = new FlowPoint(graph.Blocks[catchRegion.FirstBlockOrdinal]); stack.Push(@catch); } } else if (parent.Kind == ControlFlowRegionKind.TryAndFinally) { if (visitedRegions.Add(parent)) { var finallyRegion = parent.NestedRegions[1]; var @finally = new FlowPoint(graph.Blocks[finallyRegion.FirstBlockOrdinal]); stack.Push(@finally); } } } } if (point.AtOperation) { var operation = point.Operation; if (!suspensionPoint.Visit(operation)) { stack.Push(point.Next); } continue; } if (point.Block.FallThroughSuccessor is { Destination: { } fallThrough }) { stack.Push(new FlowPoint(fallThrough)); } if (point.Block.ConditionalSuccessor is { Destination: { } conditional })