Holy shit! It works

This commit is contained in:
Pyrex 2023-09-20 22:00:45 -07:00
parent 757cca1392
commit 5de409515e
5 changed files with 114 additions and 51 deletions

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'dart:math' as math;
import 'package:dartterm/assets.dart';
import 'package:dartterm/gen/generator.dart';
@ -29,11 +28,9 @@ void main() async {
int seed = 0;
while (true) {
Vault output = Generator(math.Random(seed), vaults).generate(Requirement(
32,
24,
DirectionSet(
{Direction.up, Direction.left, Direction.right, Direction.down})));
clear();
Vault output = Generator(math.Random(seed), vaults)
.generate(Requirement(16, 32, 16, 24, DirectionSet({})), false);
var w = output.vx;
var h = output.vy;
for (var y = 0; y < h; y++) {
@ -55,7 +52,7 @@ void main() async {
}
inpLoop:
await for (var inp in rawInput()) {
print(inp);
skreek("$inp");
switch (inp) {
case Keystroke(text: "a"):
seed -= 1;

View File

@ -20,11 +20,13 @@ class Generator {
Generator(this._random, this._vaults);
Vault generate(Requirement requirement) {
Vault generate(Requirement requirement, bool canBeVault) {
if (canBeVault) {
Vault? suggested = _suggest(vaultTries, requirement);
if (suggested != null) {
return suggested;
}
}
// First of all: randomize orientation
// This way we only have to consider one kind of spilt
@ -32,46 +34,108 @@ class Generator {
// Try to make vx the long axis if possible
var req2 = unReorientRequirement(requirement, orientation);
if (req2.vy > (req2.vx - 2) * 3 / 2) {
if (req2.vyMax > (req2.vxMax - 2) * 3 / 2) {
orientation = (orientation + 2) % 8; // rotate once more
}
// if only one of "left" and "right" needs to be smooth, prioritize right
// as left is generated first
req2 = unReorientRequirement(requirement, orientation);
if (req2.smooth.directions.contains(Direction.left) &&
req2.smooth.directions.contains(Direction.right)) {
orientation = (orientation + 4) % 8;
}
req2 = unReorientRequirement(requirement, orientation);
var out2 = _generate(req2);
var out1 = reorientVault(out2, orientation);
// log("$orientation ${requirement.vx} ${requirement.vy} ${req2.vx} ${req2.vy} ${out2.vx} ${out2.vy} ${out1.vx} ${out1.vy}");
assert(out1.vx == requirement.vx);
assert(out1.vy == requirement.vy);
assert(out1.vx >= requirement.vxMin && out1.vx <= requirement.vxMax);
assert(out1.vy >= requirement.vyMin && out1.vy <= requirement.vyMax);
assert(out1.smooth.directions.containsAll(requirement.smooth.directions));
return out1;
}
Vault _generate(Requirement req) {
var vx = req.vx;
var vy = req.vy;
var v = Vault.blank(vx, vy, req.smooth, VaultTile.wall);
var vxMin = req.vxMin;
var vyMin = req.vyMin;
var vxMax = req.vxMax;
var vyMax = req.vyMax;
if (vx < 2 || vy < 2) {
} else if (vx < 9 || (vx - 2) * (vy - 2) < 12) {
var v2 = Vault.blank(vx - 2, vy - 2, req.smooth, VaultTile.bspfloor);
var smoothUp = req.smooth.directions.contains(Direction.up);
var smoothDown = req.smooth.directions.contains(Direction.down);
var smoothUpDown = smoothUp && smoothDown;
// var vxRand = _random.nextInt(vxMax - vxMin) + vxMin;
var vyRand = _random.nextInt(vyMax + 1 - vyMin) + vyMin;
if (vxMax < 2 || vyMax < 2) {
return Vault.blank(vxMax, vyRand, req.smooth, VaultTile.wall);
} else if (vxMax < 9 || (vxMax - 2) * (vyMax - 2) < 12) {
var v2 =
Vault.blank(vxMax - 2, vyMax - 2, req.smooth, VaultTile.bspfloor);
var v = Vault.blank(vxMax, vyMax, req.smooth, VaultTile.wall);
v.blitFrom(v2, 1, 1);
return v;
} else {
// pick a split point
var splitVx = _random.nextInt(vx - 8) + 4;
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 reqLeft = Requirement(splitVx, vy, req.smooth.clone());
reqLeft.smooth.directions.add(Direction.right);
var reqRight = Requirement((vx - splitVx + 1), vy, req.smooth.clone());
reqRight.smooth.directions.add(Direction.left);
var vyMinRight = vyMin;
var vyMaxRight = vyMax;
var vaultLeft = generate(reqLeft);
var vaultRight = generate(reqRight);
v.blitFrom(vaultLeft, 0, 0);
v.blitFrom(vaultRight, splitVx - 1, 0);
if (smoothUpDown) {
vyMinRight = leftChild.vy;
vyMaxRight = leftChild.vy;
}
var rightReq = Requirement(
vxMin - (leftChild.vx - 1),
vxMax - (leftChild.vx - 1),
vyMinRight,
vyMaxRight,
req.smooth.clone(),
);
rightReq.smooth.directions.add(Direction.left);
var rightChild = generate(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, req.smooth.clone(), VaultTile.wall);
v.blitFrom(leftChild, 0, 0);
v.blitFrom(rightChild, leftChild.vx - 1, 0);
return v;
}
if (smoothDown) {
var v =
Vault.blank(vxTotal, vyTotal, req.smooth.clone(), VaultTile.wall);
v.blitFrom(leftChild, 0, vyTotal - leftChild.vy);
v.blitFrom(rightChild, leftChild.vx - 1, vyTotal - rightChild.vy);
return v;
}
// no smoothing reqs
// min: ensure some overlap
var vyTMax = math.min(vyMax, leftChild.vy + rightChild.vy - 3);
if (vyTMax > vyTotal) {
vyTotal += _random.nextInt(vyTMax - vyTotal);
}
var v = Vault.blank(vxTotal, vyTotal, req.smooth.clone(), VaultTile.wall);
if (_random.nextBool()) {
v.blitFrom(leftChild, 0, 0);
v.blitFrom(rightChild, leftChild.vx - 1, vyTotal - rightChild.vy);
} else {
v.blitFrom(leftChild, 0, vyTotal - leftChild.vy);
v.blitFrom(rightChild, leftChild.vx - 1, 0);
}
return v;
}
}
Vault? _suggest(int tries, Requirement req) {
for (var i = 0; i < tries; i++) {
@ -100,27 +164,19 @@ class Generator {
}
Vault? _tidy(Vault vault, Requirement req) {
if (vault.vx > req.vx || vault.vy > req.vy) {
if (vault.vx > req.vxMax || vault.vy > req.vyMax) {
return null;
}
if (vault.vx < req.vx / 2 || vault.vy < req.vy / 2) {
if (vault.vx < req.vxMin || vault.vy < req.vyMin) {
return null;
}
if (!vault.smooth.directions.containsAll(req.smooth.directions)) {
return null;
}
return vault;
/*
var rsd = req.smooth.directions;
bool mustFillX =
rsd.contains(Direction.left) && rsd.contains(Direction.right);
if (vault.vx != req.vx && mustFillX) {
return null;
}
bool mustFillY = rsd.contains(Direction.up) && rsd.contains(Direction.down);
if (vault.vy != req.vy && mustFillY) {
return null;
}
Vault full = Vault.blank(req.vx, req.vy, req.smooth, VaultTile.wall);
int vx = vault.vx;
int dx;
@ -143,5 +199,6 @@ class Generator {
}
full.blitFrom(vault, dx, dy);
return full;
*/
}
}

View File

@ -1,20 +1,25 @@
part of 'generator.dart';
class Requirement {
final int vx, vy;
final int vxMin, vxMax, vyMin, vyMax;
final DirectionSet smooth;
Requirement(this.vx, this.vy, this.smooth);
Requirement(this.vxMin, this.vxMax, this.vyMin, this.vyMax, this.smooth) {
assert(vxMin <= vxMax);
assert(vyMin <= vyMax);
assert(vxMax > 2);
assert(vyMax > 2);
}
Requirement flip() {
return Requirement(vx, vy, smooth.flip());
return Requirement(vxMin, vxMax, vyMin, vyMax, smooth.flip());
}
Requirement rotateLeft() {
return Requirement(vy, vx, smooth.rotateLeft());
return Requirement(vyMin, vyMax, vxMin, vxMax, smooth.rotateLeft());
}
Requirement rotateRight() {
return Requirement(vy, vx, smooth.rotateRight());
return Requirement(vyMin, vyMax, vxMin, vxMax, smooth.rotateRight());
}
}

View File

@ -31,7 +31,9 @@ class Vaults {
var tiles = [
for (var y = r.rect.top; y < r.rect.bottom; y++)
for (var x = r.rect.left; x < r.rect.right; x++)
b.get(x, y) ?? VaultTile.wall
r.points.contains((x, y))
? (b.get(x, y) ?? VaultTile.wall)
: VaultTile.wall
];
DirectionSet smooth = DirectionSet(
{Direction.up, Direction.left, Direction.right, Direction.down});

View File

@ -1,4 +1,6 @@
import 'package:flutter/foundation.dart';
void skreek(String msg) {
// ignore: avoid_print
print("[skreek] $msg");
debugPrint("[skreek] $msg");
}