diff --git a/assets/images/vaults/house1.png b/assets/images/vaults/house1.png index f16ab36..c7b4c07 100644 Binary files a/assets/images/vaults/house1.png and b/assets/images/vaults/house1.png differ diff --git a/assets/images/vaults/warehouse_1x1.png b/assets/images/vaults/warehouse_1x1.png new file mode 100644 index 0000000..8c10f1a Binary files /dev/null and b/assets/images/vaults/warehouse_1x1.png differ diff --git a/assets/images/vaults/warehouse_2x2.png b/assets/images/vaults/warehouse_2x2.png new file mode 100644 index 0000000..c45793a Binary files /dev/null and b/assets/images/vaults/warehouse_2x2.png differ diff --git a/lib/bitmap.dart b/lib/bitmap.dart index 9ee22ad..b13799a 100644 --- a/lib/bitmap.dart +++ b/lib/bitmap.dart @@ -82,7 +82,7 @@ class Bitmap { } void set(int x, int y, T value) { - assert(x < 0 || y < 0 || x >= size.dx || y >= size.dy); + assert(!(x < 0 || y < 0 || x >= size.dx || y >= size.dy)); data[y * size.dx + x] = value; } @@ -101,6 +101,22 @@ class Bitmap { } } + void blitFromWith(Bitmap other, int dx, int dy, T Function(T, T) merge) { + assert(rect.containsRect(geo.Rect(dx, dy, other.size.dx, other.size.dy))); + var x0 = other.rect.x0; + var y0 = other.rect.x0; + var x1 = other.rect.x1; + var y1 = other.rect.y1; + var myW = size.dx; + var otW = other.size.dx; + for (var x = x0; x < x1; x++) { + for (var y = y0; y < y1; y++) { + data[(y + dy) * myW + (x + dx)] = + merge(data[(y + dy) * myW + (x + dx)], other.data[y * otW + x]); + } + } + } + Bitmap flip() { var geo.Size(:dx, :dy) = size; diff --git a/lib/game.dart b/lib/game.dart index 4fd7d7f..6a396ae 100644 --- a/lib/game.dart +++ b/lib/game.dart @@ -31,7 +31,7 @@ void main() async { while (true) { clear(); Vault output = Generator(math.Random(seed), vaults) - .generate(Requirement(16, 32, 16, 24, DirectionSet({})), false); + .generate(Requirement(16, 32, 16, 24, DirectionSet({}))); var geo.Size(dx: w, dy: h) = output.size; for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { @@ -44,7 +44,12 @@ void main() async { case VaultTile.door: cursor.puts("d"); case VaultTile.wall: + case VaultTile.defaultwall: cursor.puts("#"); + case VaultTile.archpronewall: + cursor.puts("%"); + case VaultTile.archwall: + cursor.puts("\$"); case VaultTile.exit: cursor.puts("X"); case VaultTile.meta0: diff --git a/lib/gen/generator.dart b/lib/gen/generator.dart index e331c54..1a886c8 100644 --- a/lib/gen/generator.dart +++ b/lib/gen/generator.dart @@ -12,7 +12,7 @@ part 'requirement.dart'; part 'vault.dart'; part 'vaults.dart'; -const vaultTries = 10; +const vaultTries = 30; class Generator { final math.Random _random; @@ -21,7 +21,12 @@ class Generator { Generator(this._random, this._vaults); - Vault generate(Requirement requirement, bool canBeVault) { + Vault generate(Requirement requirement) { + var out = _generateOriented(requirement, false); + return _finalize(out); + } + + Vault _generateOriented(Requirement requirement, bool canBeVault) { if (canBeVault) { Vault? suggested = _suggest(vaultTries, requirement); if (suggested != null) { @@ -47,7 +52,7 @@ class Generator { } req2 = unReorientRequirement(requirement, orientation); - var out2 = _generate(req2); + var out2 = _generateBsp(req2); var out1 = reorientVault(out2, orientation); // log("$orientation ${requirement.vx} ${requirement.vy} ${req2.vx} ${req2.vy} ${out2.vx} ${out2.vy} ${out1.vx} ${out1.vy}"); @@ -58,7 +63,7 @@ class Generator { return out1; } - Vault _generate(Requirement req) { + Vault _generateBsp(Requirement req) { var vxMin = req.vxMin; var vyMin = req.vyMin; var vxMax = req.vxMax; @@ -72,7 +77,7 @@ class Generator { var vyRand = _random.nextInt(vyMax + 1 - vyMin) + vyMin; if (vxMax < 2 || vyMax < 2) { - return Vault.blank(vxMax, vyRand, VaultTile.wall, req.smooth); + return Vault.blank(vxMax, vyRand, VaultTile.defaultwall, req.smooth); } else if (vxMax < 9 || (vxMax - 2) * (vyMax - 2) < 12) { var v2 = Vault.blank( vxMax - 2, vyMax - 2, VaultTile.bspfloor, req.smooth.clone()); @@ -83,7 +88,7 @@ class Generator { var leftReq = Requirement( math.max(vxMin - 4, 2), vxMax - 4, vyMin, vyMax, req.smooth.clone()); leftReq.smooth.directions.add(Direction.right); - var leftChild = generate(leftReq, true); + var leftChild = _generateOriented(leftReq, true); var vyMinRight = vyMin; var vyMaxRight = vyMax; @@ -100,21 +105,21 @@ class Generator { req.smooth.clone(), ); rightReq.smooth.directions.add(Direction.left); - var rightChild = generate(rightReq, true); + var rightChild = _generateOriented(rightReq, true); var vxTotal = leftChild.vx + rightChild.vx - 1; var vyTotal = math.max(leftChild.vy, rightChild.vy); if (smoothUp) { - var v = - Vault.blank(vxTotal, vyTotal, VaultTile.wall, req.smooth.clone()); + var v = Vault.blank( + vxTotal, vyTotal, VaultTile.defaultwall, req.smooth.clone()); v.blitFrom(leftChild, 0, 0); v.blitFrom(rightChild, leftChild.vx - 1, 0); return v; } if (smoothDown) { - var v = - Vault.blank(vxTotal, vyTotal, VaultTile.wall, req.smooth.clone()); + var v = Vault.blank( + vxTotal, vyTotal, VaultTile.defaultwall, req.smooth.clone()); v.blitFrom(leftChild, 0, vyTotal - leftChild.vy); v.blitFrom(rightChild, leftChild.vx - 1, vyTotal - rightChild.vy); return v; @@ -126,7 +131,8 @@ class Generator { if (vyTMax > vyTotal) { vyTotal += _random.nextInt(vyTMax - vyTotal); } - var v = Vault.blank(vxTotal, vyTotal, VaultTile.wall, req.smooth.clone()); + var v = Vault.blank( + vxTotal, vyTotal, VaultTile.defaultwall, req.smooth.clone()); if (_random.nextBool()) { v.blitFrom(leftChild, 0, 0); v.blitFrom(rightChild, leftChild.vx - 1, vyTotal - rightChild.vy); @@ -230,8 +236,8 @@ class Generator { sz.dy, DirectionSet( {Direction.up, Direction.left, Direction.down, Direction.right})); - var inner = generate(metaRequirement, true); - var dest = Vault(Bitmap.blank(vault.vx, vault.vy, VaultTile.wall), + var inner = _generateOriented(metaRequirement, true); + var dest = Vault(Bitmap.blank(vault.vx, vault.vy, VaultTile.defaultwall), vault.smooth.clone()); dest.blitFrom(vault, 0, 0); dest.blitFrom(inner, i.rect.x0, i.rect.y0); @@ -240,4 +246,52 @@ class Generator { return vault; } + + Vault _finalize(Vault subj) { + var vx = subj.vx, vy = subj.vy; + subj = Vault.blankWith(vx, vy, (x, y) { + var bed = VaultTile.defaultwall; + if (x == 0 || x == vx - 1 || y == 0 || y == vy - 1) { + bed = VaultTile.wall; + } + var tile = mergeVaultTile(bed, subj.tiles.get(x, y)!); + return tile; + }, subj.smooth.clone()); + + bool canSupportArch(VaultTile? tile) { + return tile == VaultTile.bspfloor || + tile == VaultTile.floor || + tile == VaultTile.exit; + } + + var orthoOffsets = [(0, -1), (0, 1), (-1, 0), (1, 0)]; + List<(int, int)> newArches = []; + for (int x = 0; x < vx; x++) { + for (int y = 0; y < vy; y++) { + var t = subj.tiles.get(x, y); + if (t == VaultTile.archwall) { + var supporters = 0; + for (var (dx, dy) in orthoOffsets) { + VaultTile? neighbor = subj.tiles.get(x + dx, y + dy); + if (canSupportArch(neighbor)) { + supporters++; + } + } + + if (supporters == 2) { + newArches.add((x, y)); + } + subj.tiles.set(x, y, VaultTile.wall); + } + if (t == VaultTile.archpronewall || t == VaultTile.defaultwall) { + subj.tiles.set(x, y, VaultTile.wall); + } + } + } + + for (var (ax, ay) in newArches) { + subj.tiles.set(ax, ay, VaultTile.floor); + } + return subj; + } } diff --git a/lib/gen/vault.dart b/lib/gen/vault.dart index ed21ec8..215d472 100644 --- a/lib/gen/vault.dart +++ b/lib/gen/vault.dart @@ -14,12 +14,17 @@ class Vault { return Vault(Bitmap.blank(vx, vy, lt), smooth); } + static Vault blankWith( + int vx, int vy, VaultTile Function(int, int) lt, DirectionSet smooth) { + return Vault(Bitmap.blankWith(vx, vy, lt), smooth); + } + void clear(VaultTile lt) { tiles.clear(lt); } void blitFrom(Vault other, int dx, int dy) { - tiles.blitFrom(other.tiles, dx, dy); + tiles.blitFromWith(other.tiles, dx, dy, mergeVaultTile); } Vault flip() { @@ -34,3 +39,16 @@ class Vault { return Vault(tiles.rotateLeft(), smooth.rotateLeft()); } } + +VaultTile mergeVaultTile(VaultTile bottom, VaultTile top) { + if (bottom == VaultTile.wall && top == VaultTile.archpronewall) { + return VaultTile.wall; + } + if (bottom == VaultTile.wall && top == VaultTile.archwall) { + return VaultTile.wall; + } + if (bottom == VaultTile.archwall && top == VaultTile.archpronewall) { + return VaultTile.archwall; + } + return top; +} diff --git a/lib/gen/vaults.dart b/lib/gen/vaults.dart index 620aa6c..f7b9bc5 100644 --- a/lib/gen/vaults.dart +++ b/lib/gen/vaults.dart @@ -73,6 +73,9 @@ enum VaultTile { door, bspfloor, floor, + defaultwall, // defaultwall is in generated rooms and is overwritten by anything + archpronewall, // archpronewall cannot overwrite wall or archwall + archwall, // archwall cannot overwrite wall. wall, } @@ -91,6 +94,10 @@ VaultTile? colorToVaultTile(int c) { case 0x000000: case 0x707070: return VaultTile.wall; + case 0xFF8000: + return VaultTile.archwall; + case 0x7F4000: + return VaultTile.archpronewall; case 0xFFFFFF: case 0xFFFF00: case 0xFF00FF: