aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/live-rules/cli.mjs
blob: 2c8a564b6cb63976ed5a50b97565932a6a025cfd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env node
import { createInterface } from 'node:readline';
import { loadCore, storage, parseCommand, execute } from './runtime.mjs';

const help = `Pure · 규칙 실험실 (브라우저와 같은 Zig 코어)
  jump                       점프 입력
  step [1..600]              지정한 프레임만 진행 (기본 1)
  rules ground|double 6..16 on|off
                             점프 조건·힘·활성화를 함께 적용
  status / inspect / memory  현재 상태 / 마지막 판정·기록 / 공간
  reset                      규칙과 상태 모두 처음으로
  help / quit
예: jump → step 8 → jump → rules double 10 on → jump
시간은 step으로만 진행합니다. 실행 규칙 변경은 진행 상태를 보존합니다.`;

const reason = ['아직 입력 없음', '점프 허용', '점프 비활성', '공중: 땅에서만 가능', '두 번 모두 사용', '지원하지 않는 입력'];

async function main() {
  const args = process.argv.slice(2);
  if (args.includes('--help')) { console.log(help); return; }
  if (args.some((x) => !['--demo', '--json'].includes(x))) throw new Error('사용법: node cli.mjs [--demo] [--json]');
  const json = args.includes('--json');
  const core = await loadCore();
  function show(line) {
    const command = parseCommand(line);
    if (command.op === 'help') { console.log(help); return true; }
    if (command.op === 'quit') return false;
    const result = execute(core, command);
    if (json) {
      console.log(JSON.stringify({ command: line, ...result, ...(command.op === 'memory' ? { storage: storage(core) } : {}) }));
    } else if (command.op === 'memory') {
      console.log(JSON.stringify(storage(core), null, 2));
    } else if (command.op === 'inspect') {
      console.log(JSON.stringify(result, null, 2));
    } else {
      const s = result.state;
      console.log(`t=${s.tick} · 높이 ${(s.y / 100).toFixed(2)} · 속도 ${(s.vy / 100).toFixed(2)} · 점프 ${s.jumpsUsed}/2 · 규칙 r${s.revision} (${s.mode ? 'double' : 'ground'}, ${s.impulse}, ${s.enabled ? 'on' : 'off'}) · ${reason[s.lastReason]}`);
    }
    return true;
  }
  if (args.includes('--demo')) {
    for (const line of ['status', 'jump', 'step 8', 'jump', 'rules double 10 on', 'jump', 'step 60', 'memory']) show(line);
    return;
  }
  if (!json && process.stdin.isTTY) console.log(help);
  const terminal = createInterface({ input: process.stdin, output: process.stdout,
    terminal: Boolean(process.stdin.isTTY) });
  terminal.setPrompt('pure> ');
  if (process.stdin.isTTY) terminal.prompt();
  for await (const line of terminal) {
    try {
      if (!show(line)) { terminal.close(); break; }
    } catch (error) {
      console.error(error.message);
      if (!process.stdin.isTTY) process.exitCode = 1;
    }
    if (process.stdin.isTTY) terminal.prompt();
  }
}

main().catch((error) => {
  console.error(`${error.message}\n빌드: python3 prototypes/live-rules/manage.py build`);
  process.exitCode = 1;
});