Phase Runner
chunks.js3.3 KB
1// Phase Runner - hand designed chunks + fairness solver.2// Cell legend (one char per lane, rows listed nearest first):3// . empty c coin4// a day block b night block (solid only in that world)5// g day gap h night gap6// e day drone f night drone7(function (root) {8 "use strict";9 var CH = [10 // tier 0 : learn the two worlds11 { t: 0, r: ["a..", "...", "..a", "...", ".a."] },12 { t: 0, r: ["aaa", "...", "...", "bbb"] },13 { t: 0, r: [".b.", "...", "b.b", "...", "..b"] },14 { t: 0, r: ["g..", "...", ".g.", "...", "..g"] },15 { t: 0, r: ["e..", "...", ".e.", "...", "..e"] },16 { t: 0, r: ["hhh", "...", "...", "aaa"] },17 { t: 0, r: ["cc.", ".cc", "c.c", ".cc", "cc."] },18 // tier 1 : mixed worlds19 { t: 1, r: ["aab", "...", "baa", "...", "aba"] },20 { t: 1, r: ["a.b", "...", "b.a", "...", "a.b"] },21 { t: 1, r: ["ggg", "...", "...", "bbb", "...", "hh."] },22 { t: 1, r: ["e.f", "...", "f.e", "...", ".ef"] },23 { t: 1, r: ["abb", "...", ".ab", "...", "ba."] },24 { t: 1, r: ["aaa", "...", "bbb", "...", "aaa"] },25 { t: 1, r: ["..a", "..b", ".a.", ".b.", "a..", "b.."] },26 { t: 1, r: ["g.h", "...", "h.g", "...", "g.h"] },27 // tier 2 : dense28 { t: 2, r: ["aab", "baa", "aab", "baa"] },29 { t: 2, r: ["abb", "bab", "bba", "abb"] },30 { t: 2, r: ["g.h", ".e.", "h.g", "...", "f.e"] },31 { t: 2, r: ["aab", "hgg", "bba", "ggh"] },32 { t: 2, r: ["aaa", "...", "bbb", "aaa"] },33 { t: 2, r: ["e.f", "f.e", "e.f", "...", "hhh", "...", "ggg"] },34 // tier 3 : rapid phase work35 { t: 3, r: ["aaa", ".c.", "bbb", ".c.", "aaa", ".c.", "bbb"] },36 { t: 3, r: ["abb", "aba", "bba", "baa", "aab", "abb"] },37 { t: 3, r: ["aab", "...", "bab", "...", "bba", "...", "aab"] },38 { t: 3, r: ["ggg", "bbb", "hhh", "aaa"] },39 { t: 3, r: ["abf", "bag", "hab", "abe", "fba"] }40 ];41 function safe(row, l, w) {42 var ch = row.charAt(l);43 if (w === 0) return ch !== "a" && ch !== "g" && ch !== "e";44 return ch !== "b" && ch !== "h" && ch !== "f";45 }46 // Returns array of [lane, world] (one per row) or null when unsolvable.47 // Player may change at most one lane and toggle world between consecutive rows.48 function solve(rows, rnd) {49 var layers = [], prev = [1, 1, 1, 1, 1, 1], i, l, w, pl, pw, cur, any;50 for (i = 0; i < rows.length; i++) {51 cur = [0, 0, 0, 0, 0, 0]; any = false;52 for (l = 0; l < 3; l++) for (w = 0; w < 2; w++) {53 if (!safe(rows[i], l, w)) continue;54 for (pl = Math.max(0, l - 1); pl <= Math.min(2, l + 1) && !cur[l * 2 + w]; pl++)55 for (pw = 0; pw < 2; pw++) if (prev[pl * 2 + pw]) { cur[l * 2 + w] = pl * 2 + pw + 1; any = true; break; }56 }57 if (!any) return null;58 layers.push(cur);59 prev = cur.map(function (x) { return x ? 1 : 0; });60 }61 var opts = [];62 layers[layers.length - 1].forEach(function (x, k) { if (x) opts.push(k); });63 var idx = opts[Math.floor((rnd ? rnd() : 0) * opts.length)];64 var path = new Array(rows.length);65 for (i = rows.length - 1; i >= 0; i--) { path[i] = [idx >> 1, idx & 1]; idx = layers[i][idx] - 1; }66 return path;67 }68 root.PR_CHUNKS = CH; root.PR_solve = solve; root.PR_safe = safe;69 if (typeof module !== "undefined") module.exports = { CH: CH, solve: solve, safe: safe };70})(typeof window !== "undefined" ? window : globalThis);71