Skip to content

Commit b16c55f

Browse files
committed
feat: Expand PoBrawl roster with LBJ, JFK, Eisenhower, Truman, and FDR plus dev Key Vault fallback
- Add five new presidents with full personalities, caricatures, and per-fighter behaviors (LBJ Treatment, JFK Camelot Glint, Eisenhower Atoms for Peace, Truman Buck Stops Here, FDR Day of Infamy) - Scale AI ladder from 10 to 15 rungs to accommodate the expanded roster - Add chiptune intro themes (one per president) with independent introGain bus - Wire personality entrances and round-start intro music during countdown - Add RoomEnvironment IBL, KO limelight + victor halo, and godrays shader pass - Add soft contact shadow plus mass-tinted AO disc under each fighter - Make Key Vault auth use AzureCliCredential in Development and fall back to local config on failure so cold-start 403s don't block devs
1 parent d0148c3 commit b16c55f

25 files changed

Lines changed: 9016 additions & 117 deletions

game.js.out

Lines changed: 3408 additions & 0 deletions
Large diffs are not rendered by default.

scripts/_tmp2.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// game.js — PoBrawl match orchestrator.
2+
// Owns: scene, camera, fixed-timestep sim, per-fighter state machine, momentum +
3+
// per-region damage + hit-pause + screen shake + cinematic camera + replay buffer,
4+
// audio bus, and the Blazor interop callbacks.
5+
import * as THREE from 'three';
6+
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
7+
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';

scripts/check-game.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Parse-only diagnostic for the served pobrawl/game.js
2+
const fs = require('fs');
3+
const src = fs.readFileSync('C:/Users/punko/Downloads/PoMiniGames/served-game.js', 'utf8');
4+
// Strip ESM imports/exports for use as a function body
5+
const stripped = src
6+
.replace(/^export\s+\{[^}]*\}\s*;?/gm, '')
7+
.replace(/^export\s+default\s+/gm, '')
8+
.replace(/^export\s+class\s+/gm, 'class ')
9+
.replace(/^export\s+function\s+/gm, 'function ')
10+
.replace(/^export\s+const\s+/gm, 'const ');
11+
try {
12+
// Try to find a syntax problem before runtime.
13+
new Function(stripped);
14+
console.log('PARSE OK');
15+
} catch (e) {
16+
console.error('PARSE FAIL:', e.message);
17+
}

scripts/dump-intro-themes.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const src = fs.readFileSync(path.resolve('src/PoMiniGames.Client/wwwroot/js/pobrawl/audio.js'), 'utf8');
4+
const m = src.match(/const INTRO_THEMES = (\{[\s\S]*?\n\};)/);
5+
if (!m) { console.error('INTRO_THEMES not found'); process.exit(1); }
6+
const themes = eval('(' + m[1].slice(0, -2) + '\n)');
7+
const ids = Object.keys(themes);
8+
console.log('themes:', ids.length);
9+
for (const id of ids) {
10+
const t = themes[id];
11+
const mel = t.melody.reduce((s, [, d]) => s + d, 0);
12+
const bas = (t.bass || []).reduce((s, [, d]) => s + d, 0);
13+
const dur = Math.max(mel, bas) * 60 / t.bpm;
14+
console.log(id.padEnd(8), 'bpm=' + String(t.bpm).padStart(3), 'notes=' + String(t.melody.length).padStart(2), 'dur=' + dur.toFixed(2) + 's');
15+
}

scripts/find-bad-region.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Better parser: split every import (single + multi-line) by replacing the
2+
// import/export lines via multiline regex.
3+
const fs = require('fs');
4+
const src = fs.readFileSync('C:/Users/punko/Downloads/PoMiniGames/served-game.js', 'utf8');
5+
// Multi-line aware strippers
6+
const stripped = src
7+
.replace(/^\s*import\s+[\s\S]*?from\s+['"][^'"]+['"]\s*;?/gm, '/* i */')
8+
.replace(/^\s*import\s+['"][^'"]+['"]\s*;?/gm, '/* i */')
9+
.replace(/^\s*export\s+\{[\s\S]*?\}\s*;?/gm, '/* e */')
10+
.replace(/^\s*export\s+default\s+/gm, '')
11+
.replace(/^\s*export\s+(class|function|const|let|var|async)\s+/gm, '$1 ');
12+
try {
13+
new Function(stripped);
14+
console.log('PARSE OK');
15+
} catch (e) {
16+
console.error('FAIL:', e.message);
17+
// bisect
18+
const lines = stripped.split('\n');
19+
let lo = 0, hi = lines.length;
20+
while (hi - lo > 1) {
21+
const mid = (lo + hi) >> 1;
22+
try { new Function(lines.slice(0, mid).join('\n')); lo = mid; }
23+
catch { hi = mid; }
24+
}
25+
console.error('First bad line ≈', hi);
26+
for (let i = Math.max(0, hi - 4); i < Math.min(lines.length, hi + 3); i++) {
27+
console.error(`${i + 1}: ${lines[i]}`);
28+
}
29+
}

scripts/find-real-bad.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Bisect the served-game.js to find the exact bad line.
2+
const fs = require('fs');
3+
const src = fs.readFileSync('C:/Users/punko/Downloads/PoMiniGames/served-game.js', 'utf8');
4+
const lines = src.split('\n');
5+
6+
async function tryImport(prefix) {
7+
// Write the prefix to a temp .mjs file and try dynamic import.
8+
const tmp = 'C:/Users/punko/Downloads/PoMiniGames/scripts/_tmp_module.mjs';
9+
fs.writeFileSync(tmp, prefix);
10+
try {
11+
await import('file://' + tmp.replace(/\\/g, '/'));
12+
return true;
13+
} catch (e) {
14+
return e.message;
15+
}
16+
}
17+
18+
(async () => {
19+
let lo = 0, hi = lines.length;
20+
while (hi - lo > 1) {
21+
const mid = (lo + hi) >> 1;
22+
const res = await tryImport(lines.slice(0, mid).join('\n') + '\nexport default {};\n');
23+
if (res === true) lo = mid;
24+
else hi = mid;
25+
}
26+
console.log('First bad line ≈', hi);
27+
console.log('Error message at that prefix:', await tryImport(lines.slice(0, hi).join('\n') + '\nexport default {};\n'));
28+
for (let i = Math.max(0, hi - 4); i < Math.min(lines.length, hi + 3); i++) {
29+
console.log(`${i + 1}: ${lines[i]}`);
30+
}
31+
// cleanup
32+
try { fs.unlinkSync('C:/Users/punko/Downloads/PoMiniGames/scripts/_tmp_module.mjs'); } catch {}
33+
})();

scripts/find-real-bad2.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Find the *first* bad line in a module file.
2+
const fs = require('fs');
3+
4+
const prefix = (n) => `import { default as x } from 'data:text/javascript,';`; // not used; keep imports intact
5+
6+
const src = fs.readFileSync('C:/Users/punko/Downloads/PoMiniGames/served-game.js', 'utf8');
7+
const lines = src.split('\n');
8+
9+
async function tryImport(s) {
10+
const tmp = 'C:/Users/punko/Downloads/PoMiniGames/scripts/_tmp2.mjs';
11+
fs.writeFileSync(tmp, s);
12+
try {
13+
await import('file://' + tmp.replace(/\\/g, '/'));
14+
return 'OK';
15+
} catch (e) {
16+
return e.message;
17+
}
18+
}
19+
20+
(async () => {
21+
// Just binarily search the source — the parse fails at the IMPORT-prefix
22+
// boundary until we have a complete module.
23+
let lo = 1, hi = lines.length;
24+
while (hi - lo > 1) {
25+
const mid = (lo + hi) >> 1;
26+
// Slice to lines [0..mid] — enough to bisect.
27+
// We need a complete declaration by the end, but bisection needs only
28+
// parseable-at-all characters. So we close any open braces/brackets.
29+
const prefix = lines.slice(0, mid).join('\n');
30+
const res = await tryImport(prefix);
31+
if (res === 'OK') lo = mid;
32+
else hi = mid;
33+
}
34+
console.log('hi =', hi);
35+
console.log('error at hi lines =', await tryImport(lines.slice(0, hi).join('\n')));
36+
for (let i = Math.max(0, hi - 6); i < Math.min(lines.length, hi + 3); i++) {
37+
console.log(`${i + 1}: ${lines[i].slice(0, 200)}`);
38+
}
39+
})().catch(e => console.error(e));

scripts/find-real-bad3.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const fs = require('fs');
2+
const src = fs.readFileSync('C:/Users/punko/Downloads/PoMiniGames/served-game.js', 'utf8');
3+
const lines = src.split('\n');
4+
5+
async function tryImport(s) {
6+
const tmp = 'C:/Users/punko/Downloads/PoMiniGames/scripts/_t.mjs';
7+
fs.writeFileSync(tmp, s);
8+
try { await import('file://' + tmp.replace(/\\/g,'/')); return 'OK'; }
9+
catch (e) { return e.message; }
10+
}
11+
12+
(async () => {
13+
for (let i = 1; i < lines.length; i++) {
14+
const res = await tryImport(lines.slice(0, i).join('\n'));
15+
if (res !== 'OK') {
16+
console.log('First fail at', i, '-', res);
17+
for (let k = Math.max(0, i - 2); k < Math.min(lines.length, i + 3); k++) {
18+
console.log(k + 1, '::', lines[k].slice(0, 180));
19+
}
20+
break;
21+
}
22+
}
23+
try { fs.unlinkSync('C:/Users/punko/Downloads/PoMiniGames/scripts/_t.mjs'); } catch {}
24+
})();

scripts/find-shader-end.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const fs = require('fs');
2+
const src = fs.readFileSync('C:/Users/punko/Downloads/PoMiniGames/served-game.js', 'utf8');
3+
const start = src.indexOf('fragmentShader: /* glsl */');
4+
const after = start + 24;
5+
let positions = [];
6+
for (let i = after; i < src.length; i++) {
7+
if (src.charCodeAt(i) === 96) positions.push(i); // 96 == `
8+
}
9+
console.log('first 8 backticks after marker:', positions.slice(0, 8));
10+
console.log('chars around each:');
11+
for (const p of positions.slice(0, 6)) {
12+
console.log('---');
13+
console.log(src.slice(Math.max(0, p - 50), p + 50));
14+
}

scripts/parse-real.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Use Node's vm to parse ONLY (no eval) — this preserves module semantics.
2+
const fs = require('fs');
3+
const vm = require('vm');
4+
const src = fs.readFileSync('C:/Users/punko/Downloads/PoMiniGames/served-game.js', 'utf8');
5+
try {
6+
// Wrap in a script and try to compile (no execution)
7+
new vm.Script(src, { filename: 'served-game.js' });
8+
console.log('PARSE OK');
9+
} catch (e) {
10+
console.error('FAIL:', e.message);
11+
// vm.Script gives stack trace; extract line number
12+
const m = e.stack && e.stack.match(/served-game\.js:(\d+)/);
13+
if (m) {
14+
const ln = parseInt(m[1]);
15+
const lines = src.split('\n');
16+
console.error('Line', ln);
17+
for (let i = Math.max(0, ln - 4); i < Math.min(lines.length, ln + 3); i++) {
18+
console.error(`${i + 1}: ${lines[i]}`);
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)