Line data Source code
1 : /** 2 : * @file A Constraint decides if a tile satisfies a condition defined by the class. 3 : */ 4 : 5 : /** 6 : * The NullConstraint is always satisfied. 7 : */ 8 : function NullConstraint() {} 9 : 10 6 : NullConstraint.prototype.allows = function(position) 11 : { 12 0 : return true; 13 : }; 14 : 15 : /** 16 : * The AndConstraint is met if every given Constraint is satisfied by the tile. 17 : */ 18 : function AndConstraint(constraints) 19 : { 20 10 : if (constraints instanceof Array) 21 0 : this.constraints = constraints; 22 10 : else if (!constraints) 23 10 : this.constraints = []; 24 : else 25 0 : this.constraints = [constraints]; 26 : } 27 : 28 6 : AndConstraint.prototype.allows = function(position) 29 : { 30 23956 : return this.constraints.every(constraint => constraint.allows(position)); 31 : }; 32 : 33 : /** 34 : * The OrConstraint is met if any given Constraint is satisfied by the tile. 35 : */ 36 : function OrConstraint(constraints) 37 : { 38 0 : if (constraints instanceof Array) 39 0 : this.constraints = constraints; 40 0 : else if (!constraints) 41 0 : this.constraints = []; 42 : else 43 0 : this.constraints = [constraints]; 44 : } 45 : 46 6 : OrConstraint.prototype.allows = function(position) 47 : { 48 0 : return this.constraints.some(constraint => constraint.allows(position)); 49 : }; 50 : 51 : 52 : /** 53 : * The StayAreasConstraint is met if some of the given Areas contains the point. 54 : */ 55 : function StayAreasConstraint(areas) 56 : { 57 0 : this.areas = areas; 58 : } 59 : 60 6 : StayAreasConstraint.prototype.allows = function(position) 61 : { 62 0 : return this.areas.some(area => area.contains(position)); 63 : }; 64 : 65 : /** 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 0 : this.areas = areas; 71 : } 72 : 73 6 : AdjacentToAreaConstraint.prototype.allows = function(position) 74 : { 75 0 : return this.areas.some(area => 76 0 : !area.contains(position) && 77 0 : g_Map.getAdjacentPoints(position).some(adjacentPosition => area.contains(adjacentPosition))); 78 : }; 79 : 80 : /** 81 : * The AvoidAreasConstraint is met if none of the given Areas contain the point. 82 : */ 83 : function AvoidAreasConstraint(areas) 84 : { 85 0 : this.areas = areas; 86 : } 87 : 88 6 : AvoidAreasConstraint.prototype.allows = function(position) 89 : { 90 0 : return this.areas.every(area => !area.contains(position)); 91 : }; 92 : 93 : /** 94 : * The StayTextureConstraint is met if the tile has the given texture. 95 : */ 96 : function StayTextureConstraint(texture) 97 : { 98 0 : this.texture = texture; 99 : } 100 : 101 6 : StayTextureConstraint.prototype.allows = function(position) 102 : { 103 0 : return g_Map.getTexture(position) == this.texture; 104 : }; 105 : 106 : /** 107 : * The AvoidTextureConstraint is met if the terrain texture of the tile is different from the given texture. 108 : */ 109 : function AvoidTextureConstraint(texture) 110 : { 111 0 : this.texture = texture; 112 : } 113 : 114 6 : AvoidTextureConstraint.prototype.allows = function(position) 115 : { 116 0 : return g_Map.getTexture(position) != this.texture; 117 : }; 118 : 119 : /** 120 : * The AvoidTileClassConstraint is met if there are no tiles marked with the given TileClass within the given radius of the tile. 121 : */ 122 : function AvoidTileClassConstraint(tileClass, distance) 123 : { 124 3 : this.tileClass = tileClass; 125 3 : this.distance = distance; 126 : } 127 : 128 6 : AvoidTileClassConstraint.prototype.allows = function(position) 129 : { 130 3 : return this.tileClass.countMembersInRadius(position, this.distance) == 0; 131 : }; 132 : 133 : /** 134 : * The StayInTileClassConstraint is met if every tile within the given radius of the tile is marked with the given TileClass. 135 : */ 136 : function StayInTileClassConstraint(tileClass, distance) 137 : { 138 0 : this.tileClass = tileClass; 139 0 : this.distance = distance; 140 : } 141 : 142 6 : StayInTileClassConstraint.prototype.allows = function(position) 143 : { 144 0 : return this.tileClass.countNonMembersInRadius(position, this.distance) == 0; 145 : }; 146 : 147 : /** 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 3 : this.tileClass = tileClass; 153 3 : this.distance = distance; 154 : } 155 : 156 6 : NearTileClassConstraint.prototype.allows = function(position) 157 : { 158 3 : return this.tileClass.countMembersInRadius(position, this.distance) > 0; 159 : }; 160 : 161 : /** 162 : * The BorderTileClassConstraint is met if there are 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. 165 : */ 166 : function BorderTileClassConstraint(tileClass, distanceInside, distanceOutside) 167 : { 168 0 : this.tileClass = tileClass; 169 0 : this.distanceInside = distanceInside; 170 0 : this.distanceOutside = distanceOutside; 171 : } 172 : 173 6 : BorderTileClassConstraint.prototype.allows = function(position) 174 : { 175 0 : return this.tileClass.countMembersInRadius(position, this.distanceOutside) > 0 && 176 : this.tileClass.countNonMembersInRadius(position, this.distanceInside) > 0; 177 : }; 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 0 : this.minHeight = minHeight; 186 0 : this.maxHeight = maxHeight; 187 : } 188 : 189 6 : HeightConstraint.prototype.allows = function(position) 190 : { 191 0 : return this.minHeight <= g_Map.getHeight(position) && g_Map.getHeight(position) <= this.maxHeight; 192 : }; 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 0 : this.minSlope = minSlope; 200 0 : this.maxSlope = maxSlope; 201 : } 202 : 203 6 : SlopeConstraint.prototype.allows = function(position) 204 : { 205 0 : return this.minSlope <= g_Map.getSlope(position) && g_Map.getSlope(position) <= this.maxSlope; 206 : }; 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 : { 217 0 : let mapSize = g_Map.getSize(); 218 : 219 0 : this.constraint = new AndConstraint(constraints); 220 0 : this.cache = new Array(mapSize).fill(0).map(() => new Uint8Array(mapSize)); 221 : } 222 : 223 6 : StaticConstraint.prototype.allows = function(position) 224 : { 225 0 : if (!this.cache[position.x][position.y]) 226 0 : this.cache[position.x][position.y] = this.constraint.allows(position) ? 2 : 1; 227 : 228 0 : return this.cache[position.x][position.y] == 2; 229 : }; 230 : 231 : /** 232 : * Constrains the area to any tile on the map that is passable. 233 : */ 234 : function PassableMapAreaConstraint() 235 : { 236 : } 237 : 238 6 : PassableMapAreaConstraint.prototype.allows = function(position) 239 : { 240 0 : return g_Map.validTilePassable(position); 241 : };