Fixed up address arithmetic.
[jars.git] / mars.scm
index c77e2d3..f2e3d99 100644 (file)
--- a/mars.scm
+++ b/mars.scm
 ;;
 
 (define core (make-vector core-size '()))
-
+(define (addr+ . args)
+  (foldl (lambda (a b)
+           (modulo (+ a b core-size) core-size))
+         0 args))
 
 ;;; 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
 
 (define (run players step)
   (cond
-   ((> step max-steps) players) ;Tie between remaining players
-   ((null? players) '())        ;Somehow we have no players remaining
+   ((> step max-steps) players)      ;Tie between remaining players
+   ((<= (length players) 1) players) ;There's only one player left who thus wins
    (else
     (let ((player (car players))
-          (other-players (cdr players)))
-      (if (null? ptrs)
-          (run other-players (+ step 1))  ;Player is out
-          (let* ((ptrs (player-ptrs player))
-                 (new-ptrs (execute-instr (car ptrs))))
-            (player-set-ptrs! (append (cdr ptrs) new-ptrs))
-            (run (append other-players (list player)) (+ step 1))))))))
+          (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)))
+  (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))
+         (modifier (instr-modifier instr)))
     (case (instr-opcode instr)
-      ((DAT))
+      ((DAT) '()) ;Game over, man, game over!
       ((MOV))
       ((ADD))
       ((SUB))
       (else
        (error "Unrecognised opcode" (instr-opcode instr))))))
                
+(define (eval-operand mode num ptr)
+  (case mode
+    ((immediate) 0)
+    ((direct) num)
+    ((indirect-A) (addr+ num (instr-A-num (vector-ref core (addr+ ptr num)))))
+    ((indirect-B) (addr+ num (instr-B-num (vector-ref core (addr+ ptr num)))))
+    ((pre-indirect-A)
+     (let ((aux-instr (vector-ref core (addr+ ptr num))))
+       (instr-set-A-num! aux-instr (addr+ -1 (instr-A-num aux-instr)))
+       (addr+ num (instr-A-num aux-instr))))
+    ((pre-indirect-B)
+     (let ((aux-instr (vector-ref core (addr+ ptr num))))
+       (instr-set-B-num! aux-instr (addr+ -1 (instr-B-num aux-instr)))
+       (addr+ num (instr-B-num aux-instr))))
+    ((post-indirect-A)
+     (let* ((aux-instr (vector-ref core (addr+ ptr num)))
+            (old-A-num (instr-A-num aux-instr)))
+       (instr-set-A-num! aux-instr (addr+ 1 (instr-A-num aux-instr)))
+       (addr+ num old-A-num)))
+    ((post-indirect-B)
+     (let* ((aux-instr (vector-ref core (addr+ ptr num)))
+            (old-B-num (instr-B-num aux-instr)))
+       (instr-set-B-num! aux-instr (addr+ 1 (instr-B-num aux-instr)))
+       (addr+ num old-B-num)))
+    (else
+     (error "Unrecognized mode" mode))))