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

View File

@ -20,11 +20,13 @@ class Generator {
Generator(this._random, this._vaults); Generator(this._random, this._vaults);
Vault generate(Requirement requirement) { Vault generate(Requirement requirement, bool canBeVault) {
if (canBeVault) {
Vault? suggested = _suggest(vaultTries, requirement); Vault? suggested = _suggest(vaultTries, requirement);
if (suggested != null) { if (suggested != null) {
return suggested; return suggested;
} }
}
// First of all: randomize orientation // First of all: randomize orientation
// This way we only have to consider one kind of spilt // 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 // Try to make vx the long axis if possible
var req2 = unReorientRequirement(requirement, orientation); 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 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); 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 out2 = _generate(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}");
assert(out1.vx == requirement.vx); assert(out1.vx >= requirement.vxMin && out1.vx <= requirement.vxMax);
assert(out1.vy == requirement.vy); assert(out1.vy >= requirement.vyMin && out1.vy <= requirement.vyMax);
assert(out1.smooth.directions.containsAll(requirement.smooth.directions));
return out1; return out1;
} }
Vault _generate(Requirement req) { Vault _generate(Requirement req) {
var vx = req.vx; var vxMin = req.vxMin;
var vy = req.vy; var vyMin = req.vyMin;
var v = Vault.blank(vx, vy, req.smooth, VaultTile.wall); var vxMax = req.vxMax;
var vyMax = req.vyMax;
if (vx < 2 || vy < 2) { var smoothUp = req.smooth.directions.contains(Direction.up);
} else if (vx < 9 || (vx - 2) * (vy - 2) < 12) { var smoothDown = req.smooth.directions.contains(Direction.down);
var v2 = Vault.blank(vx - 2, vy - 2, req.smooth, VaultTile.bspfloor); 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); v.blitFrom(v2, 1, 1);
return v;
} else { } else {
// pick a split point var leftReq = Requirement(
var splitVx = _random.nextInt(vx - 8) + 4; 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()); var vyMinRight = vyMin;
reqLeft.smooth.directions.add(Direction.right); var vyMaxRight = vyMax;
var reqRight = Requirement((vx - splitVx + 1), vy, req.smooth.clone());
reqRight.smooth.directions.add(Direction.left);
var vaultLeft = generate(reqLeft); if (smoothUpDown) {
var vaultRight = generate(reqRight); vyMinRight = leftChild.vy;
v.blitFrom(vaultLeft, 0, 0); vyMaxRight = leftChild.vy;
v.blitFrom(vaultRight, splitVx - 1, 0);
} }
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; 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) { Vault? _suggest(int tries, Requirement req) {
for (var i = 0; i < tries; i++) { for (var i = 0; i < tries; i++) {
@ -100,27 +164,19 @@ class Generator {
} }
Vault? _tidy(Vault vault, Requirement req) { 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; return null;
} }
if (vault.vx < req.vx / 2 || vault.vy < req.vy / 2) { if (vault.vx < req.vxMin || vault.vy < req.vyMin) {
return null; return null;
} }
if (!vault.smooth.directions.containsAll(req.smooth.directions)) { if (!vault.smooth.directions.containsAll(req.smooth.directions)) {
return null; return null;
} }
return vault;
/*
var rsd = req.smooth.directions; 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); Vault full = Vault.blank(req.vx, req.vy, req.smooth, VaultTile.wall);
int vx = vault.vx; int vx = vault.vx;
int dx; int dx;
@ -143,5 +199,6 @@ class Generator {
} }
full.blitFrom(vault, dx, dy); full.blitFrom(vault, dx, dy);
return full; return full;
*/
} }
} }

View File

@ -1,20 +1,25 @@
part of 'generator.dart'; part of 'generator.dart';
class Requirement { class Requirement {
final int vx, vy; final int vxMin, vxMax, vyMin, vyMax;
final DirectionSet smooth; 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() { Requirement flip() {
return Requirement(vx, vy, smooth.flip()); return Requirement(vxMin, vxMax, vyMin, vyMax, smooth.flip());
} }
Requirement rotateLeft() { Requirement rotateLeft() {
return Requirement(vy, vx, smooth.rotateLeft()); return Requirement(vyMin, vyMax, vxMin, vxMax, smooth.rotateLeft());
} }
Requirement rotateRight() { 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 = [ var tiles = [
for (var y = r.rect.top; y < r.rect.bottom; y++) for (var y = r.rect.top; y < r.rect.bottom; y++)
for (var x = r.rect.left; x < r.rect.right; x++) 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( DirectionSet smooth = DirectionSet(
{Direction.up, Direction.left, Direction.right, Direction.down}); {Direction.up, Direction.left, Direction.right, Direction.down});

View File

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