Пример #1
0
        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);
        }
Пример #2
0
    /*
     * 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);
             */
        }
    }
Пример #3
0
        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);
        }
Пример #4
0
        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 })