LCOV - code coverage report
Current view: top level - maps/random/rmgen/placer/centered - ChainPlacer.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 2 52 3.8 %
Date: 2023-04-02 12:52:40 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /**
       2             :  * Generates a more random clump of points. It randomly creates circles around the edges of the current clump.s
       3             :  *
       4             :  * @param {number} minRadius - minimum radius of the circles.
       5             :  * @param {number} maxRadius - maximum radius of the circles.
       6             :  * @param {number} numCircles - number of circles.
       7             :  * @param {number} [failFraction] - Percentage of place attempts allowed to fail.
       8             :  * @param {Vector2D} [centerPosition]
       9             :  * @param {number} [maxDistance] - Farthest distance from the center.
      10             :  * @param {number[]} [queue] - When given, uses these radiuses for the first circles.
      11             :  */
      12             : function ChainPlacer(minRadius, maxRadius, numCircles, failFraction = 0, centerPosition = undefined, maxDistance = 0, queue = [])
      13             : {
      14           0 :         this.minRadius = minRadius;
      15           0 :         this.maxRadius = maxRadius;
      16           0 :         this.numCircles = numCircles;
      17           0 :         this.failFraction = failFraction;
      18           0 :         this.maxDistance = maxDistance;
      19           0 :         this.queue = queue.map(radius => Math.floor(radius));
      20           0 :         this.centerPosition = undefined;
      21             : 
      22           0 :         if (centerPosition)
      23           0 :                 this.setCenterPosition(centerPosition);
      24             : }
      25             : 
      26           6 : ChainPlacer.prototype.setCenterPosition = function(position)
      27             : {
      28           0 :         this.centerPosition = deepfreeze(position.clone().round());
      29             : };
      30             : 
      31           6 : ChainPlacer.prototype.place = function(constraint)
      32             : {
      33             :         // Preliminary bounds check
      34           0 :         if (!g_Map.inMapBounds(this.centerPosition) || !constraint.allows(this.centerPosition))
      35           0 :                 return undefined;
      36             : 
      37           0 :         let points = [];
      38           0 :         let size = g_Map.getSize();
      39           0 :         let failed = 0;
      40           0 :         let count = 0;
      41             : 
      42           0 :         let gotRet = new Array(size).fill(0).map(p => new Array(size).fill(-1));
      43           0 :         --size;
      44             : 
      45           0 :         this.minRadius = Math.min(this.maxRadius, Math.max(this.minRadius, 1));
      46             : 
      47           0 :         let edges = [this.centerPosition];
      48             : 
      49           0 :         for (let i = 0; i < this.numCircles; ++i)
      50             :         {
      51           0 :                 let chainPos = pickRandom(edges);
      52           0 :                 let radius = this.queue.length ? this.queue.pop() : randIntInclusive(this.minRadius, this.maxRadius);
      53           0 :                 let radius2 = Math.square(radius);
      54             : 
      55           0 :                 let bbox = getPointsInBoundingBox(getBoundingBox([
      56             :                         new Vector2D(Math.max(0, chainPos.x - radius), Math.max(0, chainPos.y - radius)),
      57             :                         new Vector2D(Math.min(chainPos.x + radius, size), Math.min(chainPos.y + radius, size))
      58             :                 ]));
      59             : 
      60           0 :                 for (let position of bbox)
      61             :                 {
      62           0 :                         if (position.distanceToSquared(chainPos) >= radius2)
      63           0 :                                 continue;
      64             : 
      65           0 :                         ++count;
      66             : 
      67           0 :                         if (!g_Map.inMapBounds(position) || !constraint.allows(position))
      68             :                         {
      69           0 :                                 ++failed;
      70           0 :                                 continue;
      71             :                         }
      72             : 
      73           0 :                         let state = gotRet[position.x][position.y];
      74           0 :                         if (state == -1)
      75             :                         {
      76           0 :                                 points.push(position);
      77           0 :                                 gotRet[position.x][position.y] = -2;
      78             :                         }
      79           0 :                         else if (state >= 0)
      80             :                         {
      81           0 :                                 edges.splice(state, 1);
      82           0 :                                 gotRet[position.x][position.y] = -2;
      83             : 
      84           0 :                                 for (let k = state; k < edges.length; ++k)
      85           0 :                                         --gotRet[edges[k].x][edges[k].y];
      86             :                         }
      87             :                 }
      88             : 
      89           0 :                 for (let pos of bbox)
      90             :                 {
      91           0 :                         if (this.maxDistance &&
      92             :                             (Math.abs(this.centerPosition.x - pos.x) > this.maxDistance ||
      93             :                              Math.abs(this.centerPosition.y - pos.y) > this.maxDistance))
      94           0 :                                 continue;
      95             : 
      96           0 :                         if (gotRet[pos.x][pos.y] != -2)
      97           0 :                                 continue;
      98             : 
      99           0 :                         if (pos.x > 0 && gotRet[pos.x - 1][pos.y] == -1 ||
     100             :                             pos.y > 0 && gotRet[pos.x][pos.y - 1] == -1 ||
     101             :                             pos.x < size && gotRet[pos.x + 1][pos.y] == -1 ||
     102             :                             pos.y < size && gotRet[pos.x][pos.y + 1] == -1)
     103             :                         {
     104           0 :                                 edges.push(pos);
     105           0 :                                 gotRet[pos.x][pos.y] = edges.length - 1;
     106             :                         }
     107             :                 }
     108             :         }
     109             : 
     110           0 :         return failed > count * this.failFraction ? undefined : points;
     111             : };

Generated by: LCOV version 1.14