| [20336] | 1 | /**
|
|---|
| [20400] | 2 | * @file A Constraint decides if a tile satisfies a condition defined by the class.
|
|---|
| [20336] | 3 | */
|
|---|
| [9096] | 4 |
|
|---|
| [20336] | 5 | /**
|
|---|
| 6 | * The NullConstraint is always satisfied.
|
|---|
| 7 | */
|
|---|
| [9096] | 8 | function NullConstraint() {}
|
|---|
| 9 |
|
|---|
| [20978] | 10 | NullConstraint.prototype.allows = function(position)
|
|---|
| [9096] | 11 | {
|
|---|
| 12 | return true;
|
|---|
| 13 | };
|
|---|
| 14 |
|
|---|
| [20336] | 15 | /**
|
|---|
| 16 | * The AndConstraint is met if every given Constraint is satisfied by the tile.
|
|---|
| 17 | */
|
|---|
| [9096] | 18 | function AndConstraint(constraints)
|
|---|
| 19 | {
|
|---|
| [20861] | 20 | if (constraints instanceof Array)
|
|---|
| [22419] | 21 | this.constraints = constraints;
|
|---|
| [20861] | 22 | else if (!constraints)
|
|---|
| 23 | this.constraints = [];
|
|---|
| 24 | else
|
|---|
| 25 | this.constraints = [constraints];
|
|---|
| [9096] | 26 | }
|
|---|
| 27 |
|
|---|
| [20978] | 28 | AndConstraint.prototype.allows = function(position)
|
|---|
| [9096] | 29 | {
|
|---|
| [20978] | 30 | return this.constraints.every(constraint => constraint.allows(position));
|
|---|
| [9096] | 31 | };
|
|---|
| 32 |
|
|---|
| [20336] | 33 | /**
|
|---|
| [25681] | 34 | * The OrConstraint is met if any given Constraint is satisfied by the tile.
|
|---|
| 35 | */
|
|---|
| 36 | function OrConstraint(constraints)
|
|---|
| 37 | {
|
|---|
| 38 | if (constraints instanceof Array)
|
|---|
| 39 | this.constraints = constraints;
|
|---|
| 40 | else if (!constraints)
|
|---|
| 41 | this.constraints = [];
|
|---|
| 42 | else
|
|---|
| 43 | this.constraints = [constraints];
|
|---|
| 44 | }
|
|---|
| 45 |
|
|---|
| 46 | OrConstraint.prototype.allows = function(position)
|
|---|
| 47 | {
|
|---|
| 48 | return this.constraints.some(constraint => constraint.allows(position));
|
|---|
| 49 | };
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 | /**
|
|---|
| [21296] | 53 | * The StayAreasConstraint is met if some of the given Areas contains the point.
|
|---|
| 54 | */
|
|---|
| 55 | function StayAreasConstraint(areas)
|
|---|
| 56 | {
|
|---|
| 57 | this.areas = areas;
|
|---|
| 58 | }
|
|---|
| 59 |
|
|---|
| 60 | StayAreasConstraint.prototype.allows = function(position)
|
|---|
| 61 | {
|
|---|
| 62 | return this.areas.some(area => area.contains(position));
|
|---|
| 63 | };
|
|---|
| 64 |
|
|---|
| 65 | /**
|
|---|
| [21300] | 66 | * The StayAreasConstraint is met if the point is adjacent to one of the given Areas and not contained by that Area.
|
|---|
| 67 | */
|
|---|
| 68 | function AdjacentToAreaConstraint(areas)
|
|---|
| 69 | {
|
|---|
| 70 | this.areas = areas;
|
|---|
| 71 | }
|
|---|
| 72 |
|
|---|
| 73 | AdjacentToAreaConstraint.prototype.allows = function(position)
|
|---|
| 74 | {
|
|---|
| 75 | return this.areas.some(area =>
|
|---|
| 76 | !area.contains(position) &&
|
|---|
| 77 | g_Map.getAdjacentPoints(position).some(adjacentPosition => area.contains(adjacentPosition)));
|
|---|
| 78 | };
|
|---|
| 79 |
|
|---|
| 80 | /**
|
|---|
| [21296] | 81 | * The AvoidAreasConstraint is met if none of the given Areas contain the point.
|
|---|
| [20336] | 82 | */
|
|---|
| [21296] | 83 | function AvoidAreasConstraint(areas)
|
|---|
| [9096] | 84 | {
|
|---|
| [21296] | 85 | this.areas = areas;
|
|---|
| [9096] | 86 | }
|
|---|
| 87 |
|
|---|
| [21296] | 88 | AvoidAreasConstraint.prototype.allows = function(position)
|
|---|
| [9096] | 89 | {
|
|---|
| [22419] | 90 | return this.areas.every(area => !area.contains(position));
|
|---|
| [9096] | 91 | };
|
|---|
| 92 |
|
|---|
| [20336] | 93 | /**
|
|---|
| [21104] | 94 | * The StayTextureConstraint is met if the tile has the given texture.
|
|---|
| 95 | */
|
|---|
| 96 | function StayTextureConstraint(texture)
|
|---|
| 97 | {
|
|---|
| 98 | this.texture = texture;
|
|---|
| 99 | }
|
|---|
| 100 |
|
|---|
| 101 | StayTextureConstraint.prototype.allows = function(position)
|
|---|
| 102 | {
|
|---|
| 103 | return g_Map.getTexture(position) == this.texture;
|
|---|
| 104 | };
|
|---|
| 105 |
|
|---|
| 106 | /**
|
|---|
| [20336] | 107 | * The AvoidTextureConstraint is met if the terrain texture of the tile is different from the given texture.
|
|---|
| 108 | */
|
|---|
| [21104] | 109 | function AvoidTextureConstraint(texture)
|
|---|
| [9096] | 110 | {
|
|---|
| [21104] | 111 | this.texture = texture;
|
|---|
| [9096] | 112 | }
|
|---|
| 113 |
|
|---|
| [20978] | 114 | AvoidTextureConstraint.prototype.allows = function(position)
|
|---|
| [9096] | 115 | {
|
|---|
| [21104] | 116 | return g_Map.getTexture(position) != this.texture;
|
|---|
| [9096] | 117 | };
|
|---|
| 118 |
|
|---|
| [20336] | 119 | /**
|
|---|
| 120 | * The AvoidTileClassConstraint is met if there are no tiles marked with the given TileClass within the given radius of the tile.
|
|---|
| 121 | */
|
|---|
| [21025] | 122 | function AvoidTileClassConstraint(tileClass, distance)
|
|---|
| [9096] | 123 | {
|
|---|
| [21025] | 124 | this.tileClass = tileClass;
|
|---|
| [9096] | 125 | this.distance = distance;
|
|---|
| 126 | }
|
|---|
| 127 |
|
|---|
| [20978] | 128 | AvoidTileClassConstraint.prototype.allows = function(position)
|
|---|
| [9096] | 129 | {
|
|---|
| [21026] | 130 | return this.tileClass.countMembersInRadius(position, this.distance) == 0;
|
|---|
| [9096] | 131 | };
|
|---|
| 132 |
|
|---|
| [20336] | 133 | /**
|
|---|
| 134 | * The StayInTileClassConstraint is met if every tile within the given radius of the tile is marked with the given TileClass.
|
|---|
| 135 | */
|
|---|
| [21025] | 136 | function StayInTileClassConstraint(tileClass, distance)
|
|---|
| [9096] | 137 | {
|
|---|
| [21025] | 138 | this.tileClass = tileClass;
|
|---|
| [9096] | 139 | this.distance = distance;
|
|---|
| 140 | }
|
|---|
| 141 |
|
|---|
| [20978] | 142 | StayInTileClassConstraint.prototype.allows = function(position)
|
|---|
| [9096] | 143 | {
|
|---|
| [21026] | 144 | return this.tileClass.countNonMembersInRadius(position, this.distance) == 0;
|
|---|
| [9096] | 145 | };
|
|---|
| 146 |
|
|---|
| [20336] | 147 | /**
|
|---|
| [21085] | 148 | * The NearTileClassConstraint is met if at least one tile within the given radius of the tile is marked with the given TileClass.
|
|---|
| 149 | */
|
|---|
| 150 | function NearTileClassConstraint(tileClass, distance)
|
|---|
| 151 | {
|
|---|
| 152 | this.tileClass = tileClass;
|
|---|
| 153 | this.distance = distance;
|
|---|
| 154 | }
|
|---|
| 155 |
|
|---|
| 156 | NearTileClassConstraint.prototype.allows = function(position)
|
|---|
| 157 | {
|
|---|
| 158 | return this.tileClass.countMembersInRadius(position, this.distance) > 0;
|
|---|
| 159 | };
|
|---|
| 160 |
|
|---|
| 161 | /**
|
|---|
| [20336] | 162 | * The BorderTileClassConstraint is met if there are
|
|---|
| [20349] | 163 | * tiles not marked with the given TileClass within distanceInside of the tile and
|
|---|
| 164 | * tiles marked with the given TileClass within distanceOutside of the tile.
|
|---|
| [20336] | 165 | */
|
|---|
| [21025] | 166 | function BorderTileClassConstraint(tileClass, distanceInside, distanceOutside)
|
|---|
| [9096] | 167 | {
|
|---|
| [21025] | 168 | this.tileClass = tileClass;
|
|---|
| [9096] | 169 | this.distanceInside = distanceInside;
|
|---|
| 170 | this.distanceOutside = distanceOutside;
|
|---|
| 171 | }
|
|---|
| 172 |
|
|---|
| [20978] | 173 | BorderTileClassConstraint.prototype.allows = function(position)
|
|---|
| [9096] | 174 | {
|
|---|
| [21026] | 175 | return this.tileClass.countMembersInRadius(position, this.distanceOutside) > 0 &&
|
|---|
| 176 | this.tileClass.countNonMembersInRadius(position, this.distanceInside) > 0;
|
|---|
| [9096] | 177 | };
|
|---|
| [20862] | 178 |
|
|---|
| 179 | /**
|
|---|
| 180 | * The HeightConstraint is met if the elevation of the tile is within the given range.
|
|---|
| 181 | * One can pass Infinity to only test for one side.
|
|---|
| 182 | */
|
|---|
| 183 | function HeightConstraint(minHeight, maxHeight)
|
|---|
| 184 | {
|
|---|
| 185 | this.minHeight = minHeight;
|
|---|
| 186 | this.maxHeight = maxHeight;
|
|---|
| 187 | }
|
|---|
| 188 |
|
|---|
| [20978] | 189 | HeightConstraint.prototype.allows = function(position)
|
|---|
| [20862] | 190 | {
|
|---|
| [20994] | 191 | return this.minHeight <= g_Map.getHeight(position) && g_Map.getHeight(position) <= this.maxHeight;
|
|---|
| [20862] | 192 | };
|
|---|
| [21085] | 193 |
|
|---|
| 194 | /**
|
|---|
| 195 | * The SlopeConstraint is met if the steepness of the terrain is within the given range.
|
|---|
| 196 | */
|
|---|
| 197 | function SlopeConstraint(minSlope, maxSlope)
|
|---|
| 198 | {
|
|---|
| 199 | this.minSlope = minSlope;
|
|---|
| 200 | this.maxSlope = maxSlope;
|
|---|
| 201 | }
|
|---|
| 202 |
|
|---|
| 203 | SlopeConstraint.prototype.allows = function(position)
|
|---|
| 204 | {
|
|---|
| 205 | return this.minSlope <= g_Map.getSlope(position) && g_Map.getSlope(position) <= this.maxSlope;
|
|---|
| 206 | };
|
|---|
| [21401] | 207 |
|
|---|
| 208 | /**
|
|---|
| 209 | * The StaticConstraint is used for performance improvements of existing Constraints.
|
|---|
| 210 | * It is evaluated for the entire map when the Constraint is created.
|
|---|
| 211 | * So when a createAreas or createObjectGroups call uses this, it can rely on the cache,
|
|---|
| 212 | * rather than reevaluating it for every randomized coordinate.
|
|---|
| 213 | * Account for the fact that the cache is never updated!
|
|---|
| 214 | */
|
|---|
| 215 | function StaticConstraint(constraints)
|
|---|
| 216 | {
|
|---|
| [28036] | 217 | const mapSize = g_Map.getSize();
|
|---|
| [21401] | 218 |
|
|---|
| [21418] | 219 | this.constraint = new AndConstraint(constraints);
|
|---|
| 220 | this.cache = new Array(mapSize).fill(0).map(() => new Uint8Array(mapSize));
|
|---|
| [21401] | 221 | }
|
|---|
| 222 |
|
|---|
| 223 | StaticConstraint.prototype.allows = function(position)
|
|---|
| 224 | {
|
|---|
| [21418] | 225 | if (!this.cache[position.x][position.y])
|
|---|
| 226 | this.cache[position.x][position.y] = this.constraint.allows(position) ? 2 : 1;
|
|---|
| 227 |
|
|---|
| 228 | return this.cache[position.x][position.y] == 2;
|
|---|
| [21401] | 229 | };
|
|---|
| [21436] | 230 |
|
|---|
| 231 | /**
|
|---|
| 232 | * Constrains the area to any tile on the map that is passable.
|
|---|
| 233 | */
|
|---|
| 234 | function PassableMapAreaConstraint()
|
|---|
| 235 | {
|
|---|
| 236 | }
|
|---|
| 237 |
|
|---|
| 238 | PassableMapAreaConstraint.prototype.allows = function(position)
|
|---|
| 239 | {
|
|---|
| 240 | return g_Map.validTilePassable(position);
|
|---|
| 241 | };
|
|---|