diff options
-rw-r--r-- | src/vm/core.js | 21 | ||||
-rw-r--r-- | src/vm/vm.js | 75 |
2 files changed, 96 insertions, 0 deletions
diff --git a/src/vm/core.js b/src/vm/core.js index 184be00..a8fbce7 100644 --- a/src/vm/core.js +++ b/src/vm/core.js @@ -81,6 +81,27 @@ class Core { } + initialize(programs) { + const ranges = this.getRanges( + programs.map(p => p.program.length) + ) + + const pc = []; + for (let i=0; i<programs.length; i++) { + const range = ranges[i]; + const program = programs[i].program; + pc.push(programs[i].start + range.start); + + for (let j=0; j<program.length; j++) { + const index = this.normalize(range.start, j); + this.data[index] = JSON.parse(JSON.stringify(program[j])); + } + } + + return pc; + } + + normalize(pc, value) { return mod((pc + value), this.data.length); } diff --git a/src/vm/vm.js b/src/vm/vm.js index 1ec890b..6add546 100644 --- a/src/vm/vm.js +++ b/src/vm/vm.js @@ -31,6 +31,81 @@ class Warrior { 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<this.warriors.length; i++) { + console.log(`${i} running: ${!this.warriors[i].isDead()}`); + } } }; + + +exports.RedcodeVm = RedcodeVm; |