Add arches, which demand to be collapsed

This commit is contained in:
Pyrex 2023-09-21 17:33:48 -07:00
parent 9ad13f7a5a
commit 01e316d979
8 changed files with 117 additions and 17 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

After

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 B

View File

@ -82,7 +82,7 @@ class Bitmap<T> {
} }
void set(int x, int y, T value) { 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; data[y * size.dx + x] = value;
} }
@ -101,6 +101,22 @@ class Bitmap<T> {
} }
} }
void blitFromWith(Bitmap<T> 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<T> flip() { Bitmap<T> flip() {
var geo.Size(:dx, :dy) = size; var geo.Size(:dx, :dy) = size;

View File

@ -31,7 +31,7 @@ void main() async {
while (true) { while (true) {
clear(); clear();
Vault output = Generator(math.Random(seed), vaults) 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; var geo.Size(dx: w, dy: h) = output.size;
for (var y = 0; y < h; y++) { for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) { for (var x = 0; x < w; x++) {
@ -44,7 +44,12 @@ void main() async {
case VaultTile.door: case VaultTile.door:
cursor.puts("d"); cursor.puts("d");
case VaultTile.wall: case VaultTile.wall:
case VaultTile.defaultwall:
cursor.puts("#"); cursor.puts("#");
case VaultTile.archpronewall:
cursor.puts("%");
case VaultTile.archwall:
cursor.puts("\$");
case VaultTile.exit: case VaultTile.exit:
cursor.puts("X"); cursor.puts("X");
case VaultTile.meta0: case VaultTile.meta0:

View File

@ -12,7 +12,7 @@ part 'requirement.dart';
part 'vault.dart'; part 'vault.dart';
part 'vaults.dart'; part 'vaults.dart';
const vaultTries = 10; const vaultTries = 30;
class Generator { class Generator {
final math.Random _random; final math.Random _random;
@ -21,7 +21,12 @@ class Generator {
Generator(this._random, this._vaults); 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) { if (canBeVault) {
Vault? suggested = _suggest(vaultTries, requirement); Vault? suggested = _suggest(vaultTries, requirement);
if (suggested != null) { if (suggested != null) {
@ -47,7 +52,7 @@ class Generator {
} }
req2 = unReorientRequirement(requirement, orientation); req2 = unReorientRequirement(requirement, orientation);
var out2 = _generate(req2); var out2 = _generateBsp(req2);
var out1 = reorientVault(out2, orientation); var out1 = reorientVault(out2, orientation);
// log("$orientation ${requirement.vx} ${requirement.vy} ${req2.vx} ${req2.vy} ${out2.vx} ${out2.vy} ${out1.vx} ${out1.vy}"); // 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; return out1;
} }
Vault _generate(Requirement req) { Vault _generateBsp(Requirement req) {
var vxMin = req.vxMin; var vxMin = req.vxMin;
var vyMin = req.vyMin; var vyMin = req.vyMin;
var vxMax = req.vxMax; var vxMax = req.vxMax;
@ -72,7 +77,7 @@ class Generator {
var vyRand = _random.nextInt(vyMax + 1 - vyMin) + vyMin; var vyRand = _random.nextInt(vyMax + 1 - vyMin) + vyMin;
if (vxMax < 2 || vyMax < 2) { 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) { } else if (vxMax < 9 || (vxMax - 2) * (vyMax - 2) < 12) {
var v2 = Vault.blank( var v2 = Vault.blank(
vxMax - 2, vyMax - 2, VaultTile.bspfloor, req.smooth.clone()); vxMax - 2, vyMax - 2, VaultTile.bspfloor, req.smooth.clone());
@ -83,7 +88,7 @@ class Generator {
var leftReq = Requirement( var leftReq = Requirement(
math.max(vxMin - 4, 2), vxMax - 4, vyMin, vyMax, req.smooth.clone()); math.max(vxMin - 4, 2), vxMax - 4, vyMin, vyMax, req.smooth.clone());
leftReq.smooth.directions.add(Direction.right); leftReq.smooth.directions.add(Direction.right);
var leftChild = generate(leftReq, true); var leftChild = _generateOriented(leftReq, true);
var vyMinRight = vyMin; var vyMinRight = vyMin;
var vyMaxRight = vyMax; var vyMaxRight = vyMax;
@ -100,21 +105,21 @@ class Generator {
req.smooth.clone(), req.smooth.clone(),
); );
rightReq.smooth.directions.add(Direction.left); rightReq.smooth.directions.add(Direction.left);
var rightChild = generate(rightReq, true); var rightChild = _generateOriented(rightReq, true);
var vxTotal = leftChild.vx + rightChild.vx - 1; var vxTotal = leftChild.vx + rightChild.vx - 1;
var vyTotal = math.max(leftChild.vy, rightChild.vy); var vyTotal = math.max(leftChild.vy, rightChild.vy);
if (smoothUp) { if (smoothUp) {
var v = var v = Vault.blank(
Vault.blank(vxTotal, vyTotal, VaultTile.wall, req.smooth.clone()); vxTotal, vyTotal, VaultTile.defaultwall, req.smooth.clone());
v.blitFrom(leftChild, 0, 0); v.blitFrom(leftChild, 0, 0);
v.blitFrom(rightChild, leftChild.vx - 1, 0); v.blitFrom(rightChild, leftChild.vx - 1, 0);
return v; return v;
} }
if (smoothDown) { if (smoothDown) {
var v = var v = Vault.blank(
Vault.blank(vxTotal, vyTotal, VaultTile.wall, req.smooth.clone()); vxTotal, vyTotal, VaultTile.defaultwall, req.smooth.clone());
v.blitFrom(leftChild, 0, vyTotal - leftChild.vy); v.blitFrom(leftChild, 0, vyTotal - leftChild.vy);
v.blitFrom(rightChild, leftChild.vx - 1, vyTotal - rightChild.vy); v.blitFrom(rightChild, leftChild.vx - 1, vyTotal - rightChild.vy);
return v; return v;
@ -126,7 +131,8 @@ class Generator {
if (vyTMax > vyTotal) { if (vyTMax > vyTotal) {
vyTotal += _random.nextInt(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()) { if (_random.nextBool()) {
v.blitFrom(leftChild, 0, 0); v.blitFrom(leftChild, 0, 0);
v.blitFrom(rightChild, leftChild.vx - 1, vyTotal - rightChild.vy); v.blitFrom(rightChild, leftChild.vx - 1, vyTotal - rightChild.vy);
@ -230,8 +236,8 @@ class Generator {
sz.dy, sz.dy,
DirectionSet( DirectionSet(
{Direction.up, Direction.left, Direction.down, Direction.right})); {Direction.up, Direction.left, Direction.down, Direction.right}));
var inner = generate(metaRequirement, true); var inner = _generateOriented(metaRequirement, true);
var dest = Vault(Bitmap.blank(vault.vx, vault.vy, VaultTile.wall), var dest = Vault(Bitmap.blank(vault.vx, vault.vy, VaultTile.defaultwall),
vault.smooth.clone()); vault.smooth.clone());
dest.blitFrom(vault, 0, 0); dest.blitFrom(vault, 0, 0);
dest.blitFrom(inner, i.rect.x0, i.rect.y0); dest.blitFrom(inner, i.rect.x0, i.rect.y0);
@ -240,4 +246,52 @@ class Generator {
return vault; 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;
}
} }

View File

@ -14,12 +14,17 @@ class Vault {
return Vault(Bitmap.blank(vx, vy, lt), smooth); 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) { void clear(VaultTile lt) {
tiles.clear(lt); tiles.clear(lt);
} }
void blitFrom(Vault other, int dx, int dy) { void blitFrom(Vault other, int dx, int dy) {
tiles.blitFrom(other.tiles, dx, dy); tiles.blitFromWith(other.tiles, dx, dy, mergeVaultTile);
} }
Vault flip() { Vault flip() {
@ -34,3 +39,16 @@ class Vault {
return Vault(tiles.rotateLeft(), smooth.rotateLeft()); 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;
}

View File

@ -73,6 +73,9 @@ enum VaultTile {
door, door,
bspfloor, bspfloor,
floor, 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, wall,
} }
@ -91,6 +94,10 @@ VaultTile? colorToVaultTile(int c) {
case 0x000000: case 0x000000:
case 0x707070: case 0x707070:
return VaultTile.wall; return VaultTile.wall;
case 0xFF8000:
return VaultTile.archwall;
case 0x7F4000:
return VaultTile.archpronewall;
case 0xFFFFFF: case 0xFFFFFF:
case 0xFFFF00: case 0xFFFF00:
case 0xFF00FF: case 0xFF00FF: