'use strict'; const { Core } = require('./core.js'); const { DAT, MOV, ADD, SUB, CMP, SLT, JMP, JMZ, JMN, DJN, SPL, } = require('./instruction.js'); class Warrior { constructor(start) { this.queue = [start]; } isDead() { return (this.queue.length === 0); } append(heads) { this.queue.push(...heads); } next() { const pc = this.queue[0]; this.queue = this.queue.slice(1); return next; } }; class RedcodeVm { constructor(coresize, warriors) { this.core = new Core(coresize); this.warriors = this.core.initialize(warriors) .map(start => new Warrior(start)); } step() { let running = 0; for (let warrior of this.warriors) { if (warrior.isDead()) { continue; } else { running += 1; } const pc = warrior.next(); const ins = this.core.data[pc]; let next; switch(ins.opcode) { case 'DAT': next = DAT(this.core, pc, ins); break; case 'MOV': next = MOV(this.core, pc, ins); break; case 'ADD': next = ADD(this.core, pc, ins); break; case 'SUB': next = SUB(this.core, pc, ins); break; case 'CMP': next = CMP(this.core, pc, ins); break; case 'SLT': next = SLT(this.core, pc, ins); break; case 'JMP': next = JMP(this.core, pc, ins); break; case 'JMZ': next = JMZ(this.core, pc, ins); break; case 'JMN': next = JMN(this.core, pc, ins); break; case 'DJN': next = DJN(this.core, pc, ins); break; case 'SPL': next = SPL(this.core, pc, ins); break; default: throw `core corruption: bad instruction ${ins}` } } return running; } run(maxSteps) { let steps = 0; let running = this.warriors.length; while(running > 0 && steps < maxSteps) { running = this.step(); steps += 1; } if (running !== 0) { console.log("draw, maximum steps exceeded"); } for (let i=0; i