1066 lines
36 KiB
JavaScript
Executable File
1066 lines
36 KiB
JavaScript
Executable File
#!/usr/bin/env nodejs
|
|
const fs = require("fs");
|
|
|
|
let CellType = {
|
|
EMPTY: 0,
|
|
WALL: 1,
|
|
FOOD: 2,
|
|
NEST: 3,
|
|
};
|
|
class C {
|
|
state;
|
|
constructor(e) {
|
|
((this.state = 0 | e), 0 === this.state && (this.state = 1));
|
|
}
|
|
next() {
|
|
let e = 0 | (this.state += 0x9e3779b9);
|
|
return (
|
|
(((e = Math.imul(
|
|
(e = Math.imul(e ^ (e >>> 16), 0x85ebca6b)) ^ (e >>> 13),
|
|
0xc2b2ae35,
|
|
)) ^
|
|
(e >>> 16)) >>>
|
|
0) /
|
|
0x100000000
|
|
);
|
|
}
|
|
nextInt(e) {
|
|
return (this.next() * e) | 0;
|
|
}
|
|
nextIntRange(e, t) {
|
|
return e + this.nextInt(t - e);
|
|
}
|
|
shuffle(e) {
|
|
for (let t = e.length - 1; t > 0; t--) {
|
|
let r = this.nextInt(t + 1);
|
|
[e[t], e[r]] = [e[r], e[t]];
|
|
}
|
|
return e;
|
|
}
|
|
}
|
|
|
|
function P(e, t, r, l) {
|
|
let a = e * t;
|
|
return {
|
|
width: e,
|
|
height: t,
|
|
cells: new Uint8Array(a),
|
|
food: new Uint16Array(a),
|
|
pheromones: new Uint16Array(a * 4),
|
|
visitCounts: new Uint32Array(a),
|
|
nestX: Math.floor(e / 2),
|
|
nestY: Math.floor(t / 2),
|
|
totalFood: 0,
|
|
seed: r,
|
|
name: l,
|
|
};
|
|
}
|
|
|
|
function H(e) {
|
|
for (let t = 0; t < e.width; t++)
|
|
(_(e, t, 0, CellType.WALL), _(e, t, e.height - 1, CellType.WALL));
|
|
for (let t = 0; t < e.height; t++)
|
|
(_(e, 0, t, CellType.WALL), _(e, e.width - 1, t, CellType.WALL));
|
|
}
|
|
|
|
let V = {
|
|
open: function (e, t, r) {
|
|
let n = P(e, t, r, `open-${r}`),
|
|
l = new C(r),
|
|
a = e / 128;
|
|
(H(n), J(n, l), $(n));
|
|
let s = 5 + l.nextInt(4);
|
|
for (let r = 0; r < s; r++) {
|
|
let r = 4 + l.nextInt(e - 8),
|
|
s = 4 + l.nextInt(t - 8);
|
|
if (W(r, s, n.nestX, n.nestY) < 15 * a) continue;
|
|
let o = 3 + l.nextInt(3),
|
|
i = 2 + l.nextInt(3);
|
|
for (let e = -o; e <= o; e++)
|
|
for (let t = -o; t <= o; t++) {
|
|
if (t * t + e * e > o * o) continue;
|
|
let l = r + t,
|
|
a = s + e;
|
|
G(n, l, a) && F(n, l, a, i);
|
|
}
|
|
}
|
|
return n;
|
|
},
|
|
maze: function (e, t, r) {
|
|
let l = P(e, t, r, `maze-${r}`),
|
|
a = new C(r),
|
|
s = e / 128;
|
|
H(l);
|
|
for (let r = 1; r < t - 1; r++)
|
|
for (let t = 1; t < e - 1; t++) _(l, t, r, CellType.WALL);
|
|
let o = Math.floor((e - 2) / 4),
|
|
i = Math.floor((t - 2) / 4),
|
|
c = new Uint8Array(o * i),
|
|
d = [];
|
|
function u(e, t) {
|
|
return [1 + 4 * e + 1, 1 + 4 * t + 1];
|
|
}
|
|
function h(r, a) {
|
|
let [s, i] = u(r, a);
|
|
for (let r = 0; r < 2; r++)
|
|
for (let a = 0; a < 2; a++)
|
|
s + a < e - 1 &&
|
|
i + r < t - 1 &&
|
|
_(l, s + a, i + r, CellType.EMPTY);
|
|
c[a * o + r] = 1;
|
|
}
|
|
function p(r, a, s, o) {
|
|
let [i, c] = u(r, a),
|
|
[d, h] = u(s, o),
|
|
p = Math.min(i, d),
|
|
f = Math.min(c, h),
|
|
m = Math.max(i, d) + 1,
|
|
x = Math.max(c, h) + 1;
|
|
for (let r = f; r <= x; r++)
|
|
for (let a = p; a <= m; a++)
|
|
a > 0 &&
|
|
a < e - 1 &&
|
|
r > 0 &&
|
|
r < t - 1 &&
|
|
_(l, a, r, CellType.EMPTY);
|
|
}
|
|
let f = Math.floor(o / 2),
|
|
m = Math.floor(i / 2);
|
|
(h(f, m), d.push(f, m));
|
|
let x = [
|
|
[0, -1],
|
|
[1, 0],
|
|
[0, 1],
|
|
[-1, 0],
|
|
];
|
|
for (; d.length > 0; ) {
|
|
let e = d[d.length - 1],
|
|
t = d[d.length - 2],
|
|
r = [];
|
|
for (let n = 0; n < 4; n++) {
|
|
let l = t + x[n][0],
|
|
a = e + x[n][1];
|
|
l >= 0 &&
|
|
l < o &&
|
|
a >= 0 &&
|
|
a < i &&
|
|
!c[a * o + l] &&
|
|
r.push(n);
|
|
}
|
|
if (0 === r.length) {
|
|
d.length -= 2;
|
|
continue;
|
|
}
|
|
let n = r[a.nextInt(r.length)],
|
|
l = t + x[n][0],
|
|
s = e + x[n][1];
|
|
(p(t, e, l, s), h(l, s), d.push(l, s));
|
|
}
|
|
for (let e = 0; e < i; e++)
|
|
for (let t = 0; t < o; t++)
|
|
if (c[e * o + t])
|
|
for (let [r, n] of [
|
|
[1, 0],
|
|
[0, 1],
|
|
]) {
|
|
let l = t + r,
|
|
s = e + n;
|
|
!(l >= o) &&
|
|
!(s >= i) &&
|
|
c[s * o + l] &&
|
|
0.25 > a.next() &&
|
|
p(t, e, l, s);
|
|
}
|
|
for (let r = 0; r < 100; r++) {
|
|
let r = 4 + a.nextInt(e - 8),
|
|
s = 4 + a.nextInt(t - 8);
|
|
if (l.cells[U(l, r, s)] === CellType.EMPTY) {
|
|
((l.nestX = r), (l.nestY = s));
|
|
break;
|
|
}
|
|
}
|
|
$(l);
|
|
let g = 16 + a.nextInt(7);
|
|
for (let r = 0; r < g; r++)
|
|
for (let r = 0; r < 50; r++) {
|
|
let r = 2 + a.nextInt(e - 4),
|
|
o = 2 + a.nextInt(t - 4);
|
|
if (
|
|
l.cells[U(l, r, o)] === CellType.EMPTY &&
|
|
W(r, o, l.nestX, l.nestY) > 12 * s
|
|
) {
|
|
let e = 1 + a.nextInt(3),
|
|
t = 3 + a.nextInt(6);
|
|
for (let a = -e; a <= e; a++)
|
|
for (let s = -e; s <= e; s++)
|
|
!(s * s + a * a > e * e) &&
|
|
G(l, r + s, o + a) &&
|
|
l.cells[U(l, r + s, o + a)] ===
|
|
CellType.EMPTY &&
|
|
F(l, r + s, o + a, t);
|
|
break;
|
|
}
|
|
}
|
|
return (Y(l), l);
|
|
},
|
|
spiral: function (e, t, r) {
|
|
let l = P(e, t, r, `spiral-${r}`),
|
|
a = new C(r);
|
|
(H(l), $(l));
|
|
let s = e / 2,
|
|
o = t / 2,
|
|
i = Math.min(e, t) / 2 - 2,
|
|
c = Math.max(5, Math.floor(0.06 * e));
|
|
for (let e = c + 2; e < i; e += c) {
|
|
let t = a.next() * Math.PI * 2,
|
|
r = 0.6 + 0.4 * a.next(),
|
|
i = 2 + a.nextInt(3),
|
|
c = 1 + 1.5 * a.next(),
|
|
d = a.next() * Math.PI * 2;
|
|
for (let a = 0; a < 2 * Math.PI; a += 0.02) {
|
|
let u = Math.abs(
|
|
((a - t + 3 * Math.PI) % (2 * Math.PI)) - Math.PI,
|
|
);
|
|
if (u < r) continue;
|
|
let h =
|
|
e +
|
|
c * Math.min(1, (u - r) / 0.5) * Math.sin(a * i + d),
|
|
p = Math.floor(s + Math.cos(a) * h),
|
|
f = Math.floor(o + Math.sin(a) * h);
|
|
G(l, p, f) && _(l, p, f, CellType.WALL);
|
|
}
|
|
}
|
|
for (let e = c; e < i; e += c) {
|
|
let t = e + c / 2,
|
|
r = 3 + a.nextInt(3);
|
|
for (let e = 0; e < r; e++) {
|
|
let e = a.next() * Math.PI * 2,
|
|
r = t + (a.next() - 0.5) * (0.3 * c),
|
|
n = Math.floor(s + Math.cos(e) * r),
|
|
i = Math.floor(o + Math.sin(e) * r),
|
|
d = 1 + a.nextInt(2),
|
|
u = 3 + a.nextInt(3);
|
|
for (let e = -d; e <= d; e++)
|
|
for (let t = -d; t <= d; t++) {
|
|
if (t * t + e * e > d * d) continue;
|
|
let r = n + t,
|
|
a = i + e;
|
|
G(l, r, a) && F(l, r, a, u);
|
|
}
|
|
}
|
|
}
|
|
return (Y(l), l);
|
|
},
|
|
field: function (e, t, r) {
|
|
let l = P(e, t, r, `field-${r}`),
|
|
a = new C(r),
|
|
s = e / 128;
|
|
(H(l),
|
|
J(l, a),
|
|
$(l),
|
|
(function (e, t, r, l) {
|
|
for (let a = 0; a < r; a++) {
|
|
let r = 4 + t.nextInt(e.width - 8),
|
|
a = 4 + t.nextInt(e.height - 8);
|
|
if (8 > W(r, a, e.nestX, e.nestY)) continue;
|
|
let s = l[0] + t.nextInt(l[1] - l[0]),
|
|
o = t.next() * Math.PI * 2,
|
|
i = 0,
|
|
c = !1;
|
|
for (
|
|
let l = 0;
|
|
l < s &&
|
|
((o += (t.next() - 0.5) * 1),
|
|
G(
|
|
e,
|
|
(r += Math.round(Math.cos(o))),
|
|
(a += Math.round(Math.sin(o))),
|
|
));
|
|
l++
|
|
)
|
|
!(5 > W(r, a, e.nestX, e.nestY)) &&
|
|
(i++,
|
|
!c && i > 8 + t.nextInt(12)
|
|
? ((c = !0), (i = 0))
|
|
: c &&
|
|
i > 2 + t.nextInt(3) &&
|
|
((c = !1), (i = 0)),
|
|
c || _(e, r, a, CellType.WALL));
|
|
}
|
|
})(l, a, 3 + a.nextInt(3), [70, 130]));
|
|
let o = 6 + a.nextInt(3);
|
|
for (let r = 0; r < o; r++) {
|
|
let r = 4 + a.nextInt(e - 8),
|
|
n = 4 + a.nextInt(t - 8);
|
|
if (W(r, n, l.nestX, l.nestY) < 12 * s) continue;
|
|
let o = 2 + a.nextInt(4),
|
|
i = 2 + a.nextInt(4);
|
|
for (let e = -o; e <= o; e++)
|
|
for (let t = -o; t <= o; t++) {
|
|
if (t * t + e * e > o * o) continue;
|
|
let a = r + t,
|
|
s = n + e;
|
|
G(l, a, s) && F(l, a, s, i);
|
|
}
|
|
}
|
|
return (Y(l), l);
|
|
},
|
|
bridge: function (e, t, r) {
|
|
let l = P(e, t, r, `bridge-${r}`),
|
|
a = new C(r);
|
|
H(l);
|
|
let s = Math.floor(e / 2),
|
|
o = Math.floor(0.1 * e),
|
|
i = new Int32Array(t),
|
|
c = s;
|
|
for (let r = 1; r < t - 1; r++) {
|
|
(0.3 > a.next() && (c += a.nextInt(3) - 1),
|
|
(c = Math.max(s - o, Math.min(s + o, c))),
|
|
(i[r] = c));
|
|
for (let t = -1; t <= 1; t++) {
|
|
let a = c + t;
|
|
a > 0 && a < e - 1 && _(l, a, r, CellType.WALL);
|
|
}
|
|
}
|
|
let d = 2 + a.nextInt(3),
|
|
u = Math.floor(t / (d + 1));
|
|
for (let r = 0; r < d; r++) {
|
|
let s = u * (r + 1),
|
|
o = 2 + a.nextInt(2);
|
|
for (let r = -o; r <= o; r++) {
|
|
let a = s + r;
|
|
if (a > 0 && a < t - 1)
|
|
for (let t = -1; t <= 1; t++) {
|
|
let r = i[a] + t;
|
|
r > 0 && r < e - 1 && _(l, r, a, CellType.EMPTY);
|
|
}
|
|
}
|
|
}
|
|
((l.nestX = Math.floor(e / 4)), (l.nestY = Math.floor(t / 2)), $(l));
|
|
let h = 6 + a.nextInt(4);
|
|
for (let r = 0; r < h; r++) {
|
|
let r = s + 4 + a.nextInt(Math.floor(e / 2) - 6),
|
|
o = 4 + a.nextInt(t - 8),
|
|
i = 2 + a.nextInt(3),
|
|
c = 3 + a.nextInt(4);
|
|
for (let e = -i; e <= i; e++)
|
|
for (let t = -i; t <= i; t++) {
|
|
if (t * t + e * e > i * i) continue;
|
|
let a = r + t,
|
|
s = o + e;
|
|
G(l, a, s) &&
|
|
l.cells[U(l, a, s)] !== CellType.WALL &&
|
|
F(l, a, s, c);
|
|
}
|
|
}
|
|
return (B(l, a), l);
|
|
},
|
|
gauntlet: function (e, t, r) {
|
|
let l = P(e, t, r, `gauntlet-${r}`),
|
|
a = new C(r);
|
|
(H(l), (l.nestX = 5), (l.nestY = Math.floor(t / 2)), $(l));
|
|
let s = 3 + a.nextInt(2),
|
|
o = Math.floor((e - 20) / (s + 1));
|
|
for (let r = 0; r < s; r++) {
|
|
let s = 12 + o * (r + 1),
|
|
i =
|
|
r % 2 == 0
|
|
? 4 + a.nextInt(Math.floor(t / 3))
|
|
: Math.floor((2 * t) / 3) +
|
|
a.nextInt(Math.floor(t / 3) - 4),
|
|
c = 4 + a.nextInt(4);
|
|
for (let r = 1; r < t - 1; r++)
|
|
!(Math.abs(r - i) < c) &&
|
|
s > 0 &&
|
|
s < e - 1 &&
|
|
_(l, s, r, CellType.WALL);
|
|
}
|
|
for (let r = 1; r <= s; r++) {
|
|
let n = 12 + r * o + 4,
|
|
i = r < s ? 12 + (r + 1) * o - 4 : e - 6;
|
|
if (i <= n) continue;
|
|
let c = (r - 1) / Math.max(1, s - 1),
|
|
d = 2 + a.nextInt(2) + Math.round(2 * c),
|
|
u = 1 + Math.round(2 * c),
|
|
h = 2 + a.nextInt(2) + Math.round(3 * c);
|
|
for (let e = 0; e < d; e++) {
|
|
let e = n + a.nextInt(Math.max(1, i - n)),
|
|
r = 4 + a.nextInt(t - 8);
|
|
for (let t = -u; t <= u; t++)
|
|
for (let n = -u; n <= u; n++) {
|
|
if (n * n + t * t > u * u) continue;
|
|
let a = e + n,
|
|
s = r + t;
|
|
G(l, a, s) && F(l, a, s, h);
|
|
}
|
|
}
|
|
}
|
|
return (B(l, a), l);
|
|
},
|
|
pockets: function (e, t, r) {
|
|
let l = P(e, t, r, `pockets-${r}`),
|
|
a = new C(r);
|
|
(H(l), J(l, a), $(l));
|
|
let s = [],
|
|
o = 7 + a.nextInt(4);
|
|
for (let r = 0; r < 300 && s.length < o; r++) {
|
|
let r = 7 + a.nextInt(6),
|
|
o = r + 4 + a.nextInt(e - 2 * r - 8),
|
|
i = r + 4 + a.nextInt(t - 2 * r - 8);
|
|
if (W(o, i, l.nestX, l.nestY) < r + 8) continue;
|
|
let c = !1;
|
|
for (let e of s)
|
|
if (W(o, i, e.cx, e.cy) < r + e.r + 5) {
|
|
c = !0;
|
|
break;
|
|
}
|
|
if (c) continue;
|
|
s.push({ cx: o, cy: i, r });
|
|
let d = a.next() * Math.PI * 2,
|
|
u = 0.2 + 0.1 * a.next();
|
|
for (let e = 0; e < 2 * Math.PI; e += 0.025) {
|
|
if (
|
|
Math.abs(
|
|
((e - d + 3 * Math.PI) % (2 * Math.PI)) - Math.PI,
|
|
) < u
|
|
)
|
|
continue;
|
|
let t = Math.round(o + Math.cos(e) * r),
|
|
a = Math.round(i + Math.sin(e) * r);
|
|
G(l, t, a) && _(l, t, a, CellType.WALL);
|
|
}
|
|
let h = 3 + a.nextInt(2),
|
|
p = 2 + a.nextInt(3);
|
|
for (let e = -h; e <= h; e++)
|
|
for (let t = -h; t <= h; t++) {
|
|
if (t * t + e * e > h * h) continue;
|
|
let r = o + t,
|
|
a = i + e;
|
|
G(l, r, a) &&
|
|
l.cells[U(l, r, a)] === CellType.EMPTY &&
|
|
F(l, r, a, p);
|
|
}
|
|
}
|
|
return (Y(l), l);
|
|
},
|
|
fortress: function (e, t, r) {
|
|
let l = P(e, t, r, `fortress-${r}`),
|
|
a = new C(r);
|
|
H(l);
|
|
let s = Math.floor(e / 2),
|
|
o = Math.floor(t / 2),
|
|
i = 3 + a.nextInt(2),
|
|
c = Math.max(4, Math.floor(Math.min(e, t) / (2 * i + 4)));
|
|
((l.nestX = 4), (l.nestY = 4), $(l));
|
|
for (let e = 1; e <= i; e++) {
|
|
let t = e * c,
|
|
r = a.next() * Math.PI * 2,
|
|
i = 0.35 + 0.2 * a.next(),
|
|
d = 3 + a.nextInt(3),
|
|
u = 1.5 + 2 * a.next(),
|
|
h = a.next() * Math.PI * 2;
|
|
for (let e = 0; e < 2 * Math.PI; e += 0.015) {
|
|
if (
|
|
Math.abs(
|
|
((e - r + 3 * Math.PI) % (2 * Math.PI)) - Math.PI,
|
|
) < i
|
|
)
|
|
continue;
|
|
let a = t + Math.sin(e * d + h) * u,
|
|
c = Math.floor(s + Math.cos(e) * a),
|
|
p = Math.floor(o + Math.sin(e) * a);
|
|
G(l, c, p) && _(l, c, p, CellType.WALL);
|
|
}
|
|
}
|
|
let d = c - 2;
|
|
for (let e = -d; e <= d; e++)
|
|
for (let t = -d; t <= d; t++) {
|
|
if (t * t + e * e > d * d) continue;
|
|
let r = s + t,
|
|
n = o + e;
|
|
G(l, r, n) && F(l, r, n, 3 + a.nextInt(3));
|
|
}
|
|
for (let r = 1; r < i; r++) {
|
|
let i = r * c + Math.floor(c / 2),
|
|
d = 4 + a.nextInt(4);
|
|
for (let r = 0; r < d; r++) {
|
|
let r = a.next() * Math.PI * 2,
|
|
c = Math.floor(s + Math.cos(r) * i),
|
|
d = Math.floor(o + Math.sin(r) * i);
|
|
c > 1 &&
|
|
c < e - 2 &&
|
|
d > 1 &&
|
|
d < t - 2 &&
|
|
l.cells[U(l, c, d)] === CellType.EMPTY &&
|
|
F(l, c, d, 2 + a.nextInt(4));
|
|
}
|
|
}
|
|
return (Y(l), l);
|
|
},
|
|
islands: function (e, t, r) {
|
|
let l = P(e, t, r, `islands-${r}`),
|
|
a = new C(r);
|
|
for (let r = 0; r < t; r++)
|
|
for (let t = 0; t < e; t++) _(l, t, r, CellType.WALL);
|
|
let s = Math.floor((e - 2) / 4),
|
|
o = Math.floor((t - 2) / 4),
|
|
i = [];
|
|
for (let e = 0; e < 4; e++)
|
|
for (let t = 0; t < 4; t++) {
|
|
let r = 1 + t * s + 2,
|
|
a = 1 + e * o + 2,
|
|
c = 1 + (t + 1) * s - 2,
|
|
d = 1 + (e + 1) * o - 2,
|
|
u = Math.floor((r + c) / 2),
|
|
h = Math.floor((a + d) / 2);
|
|
i.push({ cx: u, cy: h, ri: e, ci: t });
|
|
for (let e = a; e <= d; e++)
|
|
for (let t = r; t <= c; t++)
|
|
G(l, t, e) && _(l, t, e, CellType.EMPTY);
|
|
}
|
|
let c = i.map(() => []),
|
|
d = 2 + a.nextInt(2);
|
|
for (let e = 0; e < 4; e++)
|
|
for (let t = 0; t < 4; t++) {
|
|
let r = 4 * e + t;
|
|
if (t < 3) {
|
|
let i = 1 + (t + 1) * s,
|
|
u = 1 + e * o + 2 + a.nextInt(Math.max(1, o - 4 - d)),
|
|
h = u + Math.floor(d / 2);
|
|
(c[r].push({ x: i, y: h }), c[r + 1].push({ x: i, y: h }));
|
|
for (let e = 0; e < d; e++)
|
|
for (let t = -2; t <= 2; t++)
|
|
G(l, i + t, u + e) &&
|
|
_(l, i + t, u + e, CellType.EMPTY);
|
|
}
|
|
if (e < 3) {
|
|
let i = 1 + (e + 1) * o,
|
|
u = 1 + t * s + 2 + a.nextInt(Math.max(1, s - 4 - d)),
|
|
h = u + Math.floor(d / 2);
|
|
(c[r].push({ x: h, y: i }), c[r + 4].push({ x: h, y: i }));
|
|
for (let e = 0; e < d; e++)
|
|
for (let t = -2; t <= 2; t++)
|
|
G(l, u + e, i + t) &&
|
|
_(l, u + e, i + t, CellType.EMPTY);
|
|
}
|
|
}
|
|
let u = i[a.nextInt(i.length)];
|
|
((l.nestX = u.cx), (l.nestY = u.cy), $(l));
|
|
let h = s - 4,
|
|
p = o - 4,
|
|
f = ["empty", "blob", "walls", "diffuse", "corners"],
|
|
m = [],
|
|
x = d + 5;
|
|
for (let e = 0; e < i.length; e++) {
|
|
let t = i[e];
|
|
if (t === u) continue;
|
|
0 === m.length && (m.push(...f), a.shuffle(m));
|
|
let r = m.pop(),
|
|
n = t.cx - Math.floor(h / 2),
|
|
s = t.cy - Math.floor(p / 2),
|
|
o = c[e];
|
|
if ("empty" !== r) {
|
|
if ("blob" === r) {
|
|
let e = Math.max(1, Math.floor(Math.min(h, p) / 8)),
|
|
r = t.cx + a.nextInt(5) - 2,
|
|
n = t.cy + a.nextInt(5) - 2,
|
|
s = 1 + a.nextInt(2);
|
|
for (let t = -e; t <= e; t++)
|
|
for (let a = -e; a <= e; a++)
|
|
!(a * a + t * t > e * e) &&
|
|
G(l, r + a, n + t) &&
|
|
F(l, r + a, n + t, s);
|
|
} else if ("walls" === r) {
|
|
let e = n + h - 1,
|
|
t = s + p - 1,
|
|
r = (e, t) =>
|
|
o.some(
|
|
(r) =>
|
|
Math.abs(e - r.x) + Math.abs(t - r.y) < x,
|
|
);
|
|
for (let o = n; o <= e; o++)
|
|
(0.5 > a.next() &&
|
|
G(l, o, s) &&
|
|
!r(o, s) &&
|
|
F(l, o, s, 1),
|
|
0.5 > a.next() &&
|
|
G(l, o, t) &&
|
|
!r(o, t) &&
|
|
F(l, o, t, 1));
|
|
for (let o = s + 1; o < t; o++)
|
|
(0.5 > a.next() &&
|
|
G(l, n, o) &&
|
|
!r(n, o) &&
|
|
F(l, n, o, 1),
|
|
0.5 > a.next() &&
|
|
G(l, e, o) &&
|
|
!r(e, o) &&
|
|
F(l, e, o, 1));
|
|
} else if ("diffuse" === r)
|
|
for (let e = s; e < s + p; e++)
|
|
for (let t = n; t < n + h; t++)
|
|
0.12 > a.next() && G(l, t, e) && F(l, t, e, 1);
|
|
else if ("corners" === r) {
|
|
let e = Math.max(1, Math.floor(Math.min(h, p) / 7));
|
|
for (let [t, r] of [
|
|
[n + e + 1, s + e + 1],
|
|
[n + h - e - 2, s + e + 1],
|
|
[n + e + 1, s + p - e - 2],
|
|
[n + h - e - 2, s + p - e - 2],
|
|
]) {
|
|
if (0.3 > a.next()) continue;
|
|
let n = 1 + a.nextInt(3);
|
|
for (let a = -e; a <= e; a++)
|
|
for (let s = -e; s <= e; s++)
|
|
!(s * s + a * a > e * e) &&
|
|
G(l, t + s, r + a) &&
|
|
F(l, t + s, r + a, n);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return l;
|
|
},
|
|
chambers: function (e, t, r) {
|
|
let l = P(e, t, r, `chambers-${r}`),
|
|
a = new C(r);
|
|
for (let r = 0; r < t; r++)
|
|
for (let t = 0; t < e; t++) _(l, t, r, CellType.WALL);
|
|
let s = [],
|
|
o = 11 + a.nextInt(3);
|
|
for (let r = 0; r < o; r++) {
|
|
let r = 4 + a.nextInt(4),
|
|
o = 4 + a.nextInt(4),
|
|
i = r + 2 + a.nextInt(Math.max(1, e - 2 * r - 4)),
|
|
c = o + 2 + a.nextInt(Math.max(1, t - 2 * o - 4)),
|
|
d = !1;
|
|
for (let e of s)
|
|
if (
|
|
Math.abs(i - e.cx) < r + e.hw + 2 &&
|
|
Math.abs(c - e.cy) < o + e.hh + 2
|
|
) {
|
|
d = !0;
|
|
break;
|
|
}
|
|
if (!d) {
|
|
s.push({ cx: i, cy: c, hw: r, hh: o });
|
|
for (let e = c - o; e <= c + o; e++)
|
|
for (let t = i - r; t <= i + r; t++)
|
|
G(l, t, e) && _(l, t, e, CellType.EMPTY);
|
|
}
|
|
}
|
|
for (let e = 1; e < s.length; e++) {
|
|
let t = s[e - 1],
|
|
r = s[e],
|
|
a = t.cx,
|
|
o = t.cy;
|
|
for (; a !== r.cx; ) {
|
|
for (let e = -1; e <= 1; e++)
|
|
G(l, a, o + e) && _(l, a, o + e, CellType.EMPTY);
|
|
a += a < r.cx ? 1 : -1;
|
|
}
|
|
for (; o !== r.cy; ) {
|
|
for (let e = -1; e <= 1; e++)
|
|
G(l, a + e, o) && _(l, a + e, o, CellType.EMPTY);
|
|
o += o < r.cy ? 1 : -1;
|
|
}
|
|
}
|
|
{
|
|
let e = s[s.length - 1],
|
|
t = s[0],
|
|
r = e.cx,
|
|
a = e.cy;
|
|
for (; r !== t.cx; ) {
|
|
for (let e = -1; e <= 1; e++)
|
|
G(l, r, a + e) && _(l, r, a + e, CellType.EMPTY);
|
|
r += r < t.cx ? 1 : -1;
|
|
}
|
|
for (; a !== t.cy; ) {
|
|
for (let e = -1; e <= 1; e++)
|
|
G(l, r + e, a) && _(l, r + e, a, CellType.EMPTY);
|
|
a += a < t.cy ? 1 : -1;
|
|
}
|
|
}
|
|
let i = s.reduce(
|
|
(r, n) => {
|
|
let l = W(n.cx, n.cy, e / 2, t / 2);
|
|
return l < r.d ? { c: n, d: l } : r;
|
|
},
|
|
{ c: s[0], d: 1 / 0 },
|
|
);
|
|
for (let e of ((l.nestX = i.c.cx), (l.nestY = i.c.cy), $(l), s)) {
|
|
if (e === i.c) continue;
|
|
let t = Math.min(Math.min(e.hw, e.hh) - 1, 3);
|
|
if (t < 1) continue;
|
|
let r = 3 + a.nextInt(3);
|
|
for (let n = -t; n <= t; n++)
|
|
for (let a = -t; a <= t; a++) {
|
|
if (a * a + n * n > t * t) continue;
|
|
let s = e.cx + a,
|
|
o = e.cy + n;
|
|
G(l, s, o) && F(l, s, o, r);
|
|
}
|
|
}
|
|
return l;
|
|
},
|
|
prairie: function (e, t, r) {
|
|
let n = P(e, t, r, `prairie-${r}`),
|
|
l = new C(r);
|
|
(H(n), J(n, l), $(n));
|
|
let a = 6 + l.nextInt(4),
|
|
s = [];
|
|
for (let r = 0; r < a; r++)
|
|
s.push({
|
|
x: 4 + l.nextInt(e - 8),
|
|
y: 4 + l.nextInt(t - 8),
|
|
strength: 0.25 + 0.3 * l.next(),
|
|
radius: 6 + l.nextInt(10),
|
|
});
|
|
for (let r = 2; r < t - 2; r++)
|
|
for (let t = 2; t < e - 2; t++) {
|
|
if (5 > W(t, r, n.nestX, n.nestY)) continue;
|
|
let e = 0.016;
|
|
for (let n of s) {
|
|
let l = W(t, r, n.x, n.y);
|
|
l < n.radius && (e += n.strength * (1 - l / n.radius));
|
|
}
|
|
((e = Math.min(e, 0.25)),
|
|
l.next() < e &&
|
|
F(
|
|
n,
|
|
t,
|
|
r,
|
|
e > 0.12 ? 1 + l.nextInt(3) : 1 + l.nextInt(2),
|
|
));
|
|
}
|
|
return n;
|
|
},
|
|
brush: function (e, t, r) {
|
|
let l = P(e, t, r, `brush-${r}`),
|
|
a = new C(r),
|
|
s = e / 128;
|
|
(H(l), J(l, a), $(l));
|
|
for (let r = 2; r < t - 2; r++)
|
|
for (let t = 2; t < e - 2; t++)
|
|
!(5 > W(t, r, l.nestX, l.nestY)) &&
|
|
0.28 > a.next() &&
|
|
_(l, t, r, CellType.WALL);
|
|
for (let e = -3; e <= 3; e++)
|
|
for (let t = -3; t <= 3; t++) {
|
|
let r = l.nestX + t,
|
|
a = l.nestY + e;
|
|
G(l, r, a) &&
|
|
l.cells[U(l, r, a)] === CellType.WALL &&
|
|
_(l, r, a, CellType.EMPTY);
|
|
}
|
|
let o = 10 + a.nextInt(3);
|
|
for (let r = 0; r < o; r++)
|
|
for (let r = 0; r < 80; r++) {
|
|
let r = 4 + a.nextInt(e - 8),
|
|
o = 4 + a.nextInt(t - 8);
|
|
if (
|
|
W(r, o, l.nestX, l.nestY) < 10 * s ||
|
|
l.cells[U(l, r, o)] !== CellType.EMPTY
|
|
)
|
|
continue;
|
|
let i = 2 + a.nextInt(3),
|
|
c = 3 + a.nextInt(3);
|
|
for (let e = -i; e <= i; e++)
|
|
for (let t = -i; t <= i; t++) {
|
|
if (t * t + e * e > i * i) continue;
|
|
let n = r + t,
|
|
a = o + e;
|
|
G(l, n, a) && F(l, n, a, c);
|
|
}
|
|
break;
|
|
}
|
|
return (Y(l), l);
|
|
},
|
|
};
|
|
|
|
function Y(e) {
|
|
let t = new Uint8Array(e.width * e.height),
|
|
r = [e.nestX, e.nestY];
|
|
t[e.nestY * e.width + e.nestX] = 1;
|
|
let l = 0;
|
|
for (; l < r.length; ) {
|
|
let a = r[l++],
|
|
s = r[l++];
|
|
for (let [l, o] of [
|
|
[0, -1],
|
|
[1, 0],
|
|
[0, 1],
|
|
[-1, 0],
|
|
]) {
|
|
let i = a + l,
|
|
c = s + o;
|
|
if (i < 0 || i >= e.width || c < 0 || c >= e.height) continue;
|
|
let d = c * e.width + i;
|
|
t[d] || e.cells[d] === CellType.WALL || ((t[d] = 1), r.push(i, c));
|
|
}
|
|
}
|
|
for (let r = 0; r < e.width * e.height; r++)
|
|
if (e.cells[r] === CellType.FOOD && !t[r]) {
|
|
let l = Math.floor(r / e.width),
|
|
a = r % e.width,
|
|
s = new Uint8Array(e.width * e.height),
|
|
o = new Int32Array(e.width * e.height).fill(-1),
|
|
i = [a, l];
|
|
s[r] = 1;
|
|
let c = -1,
|
|
d = 0;
|
|
for (; d < i.length && c < 0; ) {
|
|
let r = i[d++],
|
|
n = i[d++];
|
|
for (let [l, a] of [
|
|
[0, -1],
|
|
[1, 0],
|
|
[0, 1],
|
|
[-1, 0],
|
|
]) {
|
|
let d = r + l,
|
|
u = n + a;
|
|
if (d < 1 || d >= e.width - 1 || u < 1 || u >= e.height - 1)
|
|
continue;
|
|
let h = u * e.width + d;
|
|
if (!s[h]) {
|
|
if (((s[h] = 1), (o[h] = n * e.width + r), t[h])) {
|
|
c = h;
|
|
break;
|
|
}
|
|
i.push(d, u);
|
|
}
|
|
}
|
|
}
|
|
if (c >= 0) {
|
|
let r = c;
|
|
for (; r >= 0; )
|
|
(e.cells[r] === CellType.WALL &&
|
|
(e.cells[r] = CellType.EMPTY),
|
|
(t[r] = 1),
|
|
(r = o[r]));
|
|
}
|
|
}
|
|
}
|
|
function W(e, t, r, n) {
|
|
return Math.sqrt((e - r) ** 2 + (t - n) ** 2);
|
|
}
|
|
function G(e, t, r) {
|
|
return t > 0 && t < e.width - 1 && r > 0 && r < e.height - 1;
|
|
}
|
|
function J(e, t, r) {
|
|
let n = r ?? Math.floor(0.15 * Math.min(e.width, e.height));
|
|
((e.nestX = n + t.nextInt(e.width - 2 * n)),
|
|
(e.nestY = n + t.nextInt(e.height - 2 * n)));
|
|
}
|
|
function $(e) {
|
|
let t = e.nestX,
|
|
r = e.nestY;
|
|
for (let l = -1; l <= 1; l++)
|
|
for (let a = -1; a <= 1; a++) {
|
|
let s = t + a,
|
|
o = r + l;
|
|
s >= 0 &&
|
|
s < e.width &&
|
|
o >= 0 &&
|
|
o < e.height &&
|
|
_(e, s, o, CellType.NEST);
|
|
}
|
|
}
|
|
|
|
function U(e, t, r) {
|
|
return r * e.width + t;
|
|
}
|
|
|
|
function _(e, t, r, n) {
|
|
e.cells[U(e, t, r)] = n;
|
|
}
|
|
|
|
function X(e, t, r) {
|
|
return e.cells[U(e, t, r)];
|
|
}
|
|
|
|
function G(e, t, r) {
|
|
return t > 0 && t < e.width - 1 && r > 0 && r < e.height - 1;
|
|
}
|
|
|
|
function F(e, t, r, l) {
|
|
let a = U(e, t, r);
|
|
e.cells[a] === CellType.EMPTY &&
|
|
((e.cells[a] = CellType.FOOD), (e.food[a] = l), (e.totalFood += l));
|
|
}
|
|
|
|
function B(e, t) {
|
|
if (e.width !== e.height) return;
|
|
let r = e.width,
|
|
n = 1 === t.nextInt(2),
|
|
l = 1 === t.nextInt(2),
|
|
a = 1 === t.nextInt(2);
|
|
if (!n && !l && !a) return;
|
|
let s = new Uint8Array(r * r),
|
|
o = new Uint16Array(r * r);
|
|
for (let t = 0; t < r; t++)
|
|
for (let i = 0; i < r; i++) {
|
|
let c = n ? r - 1 - i : i,
|
|
d = l ? r - 1 - t : t;
|
|
if (a) {
|
|
let e = c;
|
|
((c = d), (d = e));
|
|
}
|
|
((s[d * r + c] = e.cells[t * r + i]),
|
|
(o[d * r + c] = e.food[t * r + i]));
|
|
}
|
|
(e.cells.set(s), e.food.set(o));
|
|
let i = n ? r - 1 - e.nestX : e.nestX,
|
|
c = l ? r - 1 - e.nestY : e.nestY;
|
|
if (a) {
|
|
let e = i;
|
|
((i = c), (c = e));
|
|
}
|
|
((e.nestX = i), (e.nestY = c));
|
|
}
|
|
|
|
function renderMapASCII(map) {
|
|
const symbols = {
|
|
0: " ", // EMPTY
|
|
1: "#", // WALL
|
|
2: "o", // FOOD
|
|
3: "S", // NEST
|
|
};
|
|
|
|
let output = "";
|
|
|
|
for (let y = 0; y < map.height; y++) {
|
|
let row = "";
|
|
|
|
for (let x = 0; x < map.width; x++) {
|
|
const cell = X(map, x, y);
|
|
|
|
if (symbols[cell] !== undefined) {
|
|
row += symbols[cell];
|
|
}
|
|
}
|
|
|
|
output += row + "\n";
|
|
}
|
|
|
|
console.log(output);
|
|
}
|
|
|
|
function randomize_r(r, n) {
|
|
return (
|
|
0xfffffff &
|
|
Math.imul(
|
|
(l =
|
|
Math.imul(0x45d9f3b ^ r, 0x9e3779b9) ^
|
|
Math.imul(n + 1, 0x6c62272e)) ^
|
|
(l >>> 16),
|
|
0x85ebca6b,
|
|
) || 1
|
|
);
|
|
}
|
|
function generate_random_maps(e, t, r, n) {
|
|
let l = [];
|
|
for (let a = 0; a < n; a++)
|
|
l.push(
|
|
(function (e, t, r, n) {
|
|
let l,
|
|
a = new C(0x5a5a5a5a ^ r),
|
|
s = Object.entries(V);
|
|
a.shuffle(s);
|
|
let [o, i] = s[n % s.length],
|
|
c = randomize_r(r, n);
|
|
d = i(e, t, c);
|
|
return ((d.name = `${o}-${c.toString(36)}`), d);
|
|
})(e, t, r, a),
|
|
);
|
|
return l;
|
|
}
|
|
|
|
function generate_maps(e, t, r, n, typ) {
|
|
let l = [];
|
|
for (let a = 0; a < n; a++)
|
|
l.push(
|
|
(function (e, t, r, n) {
|
|
let a = new C(0x5a5a5a5a ^ r);
|
|
let i = V[typ];
|
|
let c = randomize_r(r, n);
|
|
d = i(e, t, c);
|
|
return ((d.name = `${typ}-${c.toString(36)}`), d);
|
|
})(e, t, r, a),
|
|
);
|
|
return l;
|
|
}
|
|
|
|
function map_from_name(name) {
|
|
let parts = name.split("-");
|
|
let generator = parts[0];
|
|
let code = parts[1];
|
|
let c = Number.parseInt(code, 36);
|
|
return V[generator](WIDTH, HEIGHT, c);
|
|
}
|
|
|
|
const WIDTH = 128;
|
|
const HEIGHT = 128;
|
|
r = 42;
|
|
n = 120;
|
|
|
|
const { program } = require("commander");
|
|
|
|
program.name("maps").description("Generate and view maps").version("1.0.0");
|
|
|
|
program.command("view <name>").action((name, options) => {
|
|
console.log(`Viewing ${name}`);
|
|
let map = map_from_name(name);
|
|
renderMapASCII(map);
|
|
});
|
|
|
|
program
|
|
.command("generate")
|
|
.option("-s, --seed <seed>", "Define seed", Number, 42)
|
|
.option("-n, --number <number>", "Amount of maps", Number, 120)
|
|
.option("-o, --output <output>", "Output file", "generated.maps")
|
|
.option("-t, --type <type>", "Map type", "random")
|
|
.action((options) => {
|
|
let maps = null;
|
|
if (options.type == "random") {
|
|
maps = generate_random_maps(
|
|
WIDTH,
|
|
HEIGHT,
|
|
options.seed,
|
|
options.number,
|
|
);
|
|
} else {
|
|
maps = generate_maps(
|
|
WIDTH,
|
|
HEIGHT,
|
|
options.seed,
|
|
options.number,
|
|
options.type,
|
|
);
|
|
}
|
|
const ws = fs.createWriteStream(options.output);
|
|
let header = Buffer.alloc(4);
|
|
header.writeInt32LE(maps.length);
|
|
ws.write(header);
|
|
const MAX_NAME_LENGTH = 31;
|
|
for (var i = 0; i < maps.length; i++) {
|
|
let header = Buffer.alloc(MAX_NAME_LENGTH + 3);
|
|
let name = maps[i].name;
|
|
let cells = Buffer.from(maps[i].cells);
|
|
let nest_cell = maps[i].nestY * WIDTH + maps[i].nestX;
|
|
|
|
header.fill(0);
|
|
header.write(name, 0, MAX_NAME_LENGTH);
|
|
header.writeInt16LE(nest_cell, MAX_NAME_LENGTH + 1);
|
|
ws.write(header);
|
|
ws.write(cells);
|
|
}
|
|
ws.end();
|
|
});
|
|
|
|
program.parse();
|
|
|
|
//let map = map_from_name("gauntlet-41jczs");
|
|
//renderMapASCII(map);
|