summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorsanine-a <sanine.not@pm.me>2023-05-23 14:15:18 -0500
committersanine-a <sanine.not@pm.me>2023-05-23 14:15:18 -0500
commit29ed5eacb80cdfe49bff0d9335241dc3e2188981 (patch)
tree5414dcc72c76a879966b9f283b47d9dbc1432ee6 /src/vm
parent6826d32ca70ec6b6e751813bb595b6ade288cb69 (diff)
add step()
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/core.js21
-rw-r--r--src/vm/vm.js75
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;