X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?p=jars.git;a=blobdiff_plain;f=mars.scm;h=b1aa9db8f03f1bd52c38fbce981ca6423de07d0a;hp=57e3e13e3f77809ca51d491c4682e1b5afcc0282;hb=707bcb205c185815e2b94ab3fca5f769afb58264;hpb=c30656b58f082be264e382d0da5866c4c04a10f7 diff --git a/mars.scm b/mars.scm index 57e3e13..b1aa9db 100644 --- a/mars.scm +++ b/mars.scm @@ -2,6 +2,10 @@ ;;; An implementation of the Memory Array Redcode Simulator (MARS) ;;; +(import (chicken io) + (chicken string) + matchable) + ;;; Constants ;; @@ -18,7 +22,13 @@ ;;; Instructions ;; -(define (make-instr opcode modifier addrA modeA addrB modeB)) +(define (make-instr opcode modifier A-mode A-num B-mode B-num)) +(define (instr-opcode instr) (list-ref instr 0)) +(define (instr-modifier instr) (list-ref instr 1)) +(define (instr-A-mode instr) (list-ref instr 2)) +(define (instr-A-num instr) (list-ref instr 3)) +(define (instr-B-mode instr) (list-ref instr 4)) +(define (instr-B-num instr) (list-ref instr 5)) ;;; Players @@ -40,24 +50,67 @@ ;;; Main loop ;; -(define (list-rot l) - (if (> (length l) 1) - (append (cdr l) (list (car l))) - l)) - -(define (run playerA playerB step) +(define (run players step) (cond - ((> step max-steps) 'tie) - ((null? (player-ptrs playerA) playerB)) - ((null? (player-ptrs playerB) playerA)) + ((> step max-steps) players) ;Tie between remaining players + ((<= (length players) 1) players) ;There's only one player left who thus wins (else - (let ((ptrs (player-ptrs playerA))) - (player-set-ptrs! (append (cdr ptrs) - (execute-instr (car ptrs))))) - (run playerB player A (+ step 1))))) + (let ((player (car players)) + (other-players (cdr players)) + (ptrs (player-ptrs player))) + (let ((new-ptrs (execute-instr (car ptrs)))) + (if (null? new-ptrs) + (run other-players (+ step 1)) + (begin + (player-set-ptrs! (append (cdr ptrs) new-ptrs)) + (run (append other-players (list player)) (+ step 1))))))))) (define (execute-instr ptr) - (let ((instr (vector-ref core ptr))) - (match instr - ()))) + (let* ((instr (vector-ref core ptr)) + (A-pointer (eval-operand (instr-A-mode instr) (instr-A-num) ptr)) + (B-pointer (eval-operand (instr-B-mode instr) (instr-B-num) ptr))) + (case (instr-opcode instr) + ((DAT)) + ((MOV)) + ((ADD)) + ((SUB)) + ((MUL)) + ((DIV)) + ((MOD)) + ((JMP)) + ((JMN)) + ((DJN)) + ((SEQ CMP)) + ((SNE)) + ((SLT)) + ((SPL)) + ((NOP)) + (else + (error "Unrecognised opcode" (instr-opcode instr)))))) +(define (eval-operand mode num ptr) + (case mode + ((immediate) 0) + ((direct) num) + ((indirect-A) (+ num (instr-A-num (vector-ref core (+ ptr num))))) + ((indirect-B) (+ num (instr-B-num (vector-ref core (+ ptr num))))) + ((pre-indirect-A) + (let ((aux-instr (vector-ref core (+ ptr num)))) + (instr-set-A-num! aux-instr (- 1 (instr-A-num aux-instr))) + (+ num (instr-A-num aux-instr)))) + ((pre-indirect-B) + (let ((aux-instr (vector-ref core (+ ptr num)))) + (instr-set-B-num! aux-instr (- 1 (instr-B-num aux-instr))) + (+ num (instr-B-num aux-instr)))) + ((post-indirect-A) + (let* ((aux-instr (vector-ref core (+ ptr num))) + (old-A-num (instr-A-num aux-instr))) + (instr-set-A-num! aux-instr (+ 1 (instr-A-num aux-instr))) + (+ num old-A-num))) + ((post-indirect-B) + (let* ((aux-instr (vector-ref core (+ ptr num))) + (old-B-num (instr-B-num aux-instr))) + (instr-set-B-num! aux-instr (+ 1 (instr-B-num aux-instr))) + (+ num old-B-num))) + (else + (error "Unrecognized mode" mode))))