Add arches, which demand to be collapsed
This commit is contained in:
parent
9ad13f7a5a
commit
01e316d979
Binary file not shown.
Before Width: | Height: | Size: 737 B After Width: | Height: | Size: 867 B |
BIN
assets/images/vaults/warehouse_1x1.png
Normal file
BIN
assets/images/vaults/warehouse_1x1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 820 B |
BIN
assets/images/vaults/warehouse_2x2.png
Normal file
BIN
assets/images/vaults/warehouse_2x2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 792 B |
@ -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;
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user