Final queue count now adjustable.
[jars.git] / mars.scm
index 23a0337..d2d73e3 100644 (file)
--- a/mars.scm
+++ b/mars.scm
@@ -6,13 +6,16 @@
     (make-instr
      make-prog
      prog-name
+     prog-author
      prog-instrs
      prog-offset
      prog->string
+     dump-prog
      install-progs
      make-queue
      queue-owner
      queue-ptrs
+     dump-queues
      make-core
      run-mars)
 
@@ -55,7 +58,7 @@
         (('->string)
          (conc opcode
                "." modifier
-               " " (mode->string A-mode) A-num
+               "\t" (mode->string A-mode) A-num
                ", " (mode->string B-mode) B-num))
         (else
          (error "Invalid instr arguments" args)))))
@@ -77,7 +80,9 @@
   ;;; Memory setup and addressing
   ;;
 
-  (define (make-core core-size initial-instr . set-functions)
+  (define INITIAL-INSTR (make-instr 'DAT 'F 'immediate 0 'immediate 0))
+
+  (define (make-core core-size . set-functions)
     (let ((core-vec (make-vector core-size '()))
           (names-vec (make-vector core-size '())))
       (define (norm-addr i)
         (let loop ((remaining-fns set-functions))
           (unless (null? remaining-fns)
             ((car remaining-fns) i n))))
+      (define (dump i)
+        (print* i ":\t" ((norm-ref core-vec i) '->string))
+        (let ((n (norm-ref names-vec i)))
+          (unless (null? n)
+            (print* "\t;" n)))
+        (print))
       (let loop ((i 0))
         (unless (>= i core-size)
-          (vector-set! core-vec i (initial-instr 'make-copy))
+          (vector-set! core-vec i (INITIAL-INSTR 'make-copy))
           (loop (+ i 1))))
       (lambda args
         (match args
            (norm-set! names-vec i n)
            (run-set-functions i n))
           ((i 'name) (norm-ref names-vec i))
+          ((i 'dump)
+           (let ((i1 (- i 4))
+                 (i2 (+ i 4)))
+             (let loop ((idx i1))
+               (unless (> idx i2)
+                 (if (= idx i)
+                     (print* "*"))
+                 (dump idx)
+                 (loop (+ idx 1))))))
+          (('size) core-size)
           (((? integer? i) v) ((norm-ref core-vec i) v))
-          (('->addr (? integer? i)) (norm-addr i))
-          (('dump)
-           (let loop ((i 0))
-             (unless (>= i core-size)
-               (print* i ":\t" ((vector-ref core-vec i) '->string))
-               (let ((n (vector-ref names-vec i)))
-                 (unless (null? n)
-                   (print* "\t;" n)))
-               (print)
-               (loop (+ i 1)))))
-          (('size) core-size)))))
+          (('->addr (? integer? i)) (norm-addr i))))))
+
 
 
   ;;; Programmes and task queues
   ;;
 
-  (define (make-prog name instrs offset)
-    (list name instrs offset))
+  (define (make-prog name author instrs offset)
+    (list name author instrs offset))
 
   (define (prog-name prog) (list-ref prog 0))
-  (define (prog-instrs prog) (list-ref prog 1))
-  (define (prog-offset prog) (list-ref prog 2))
+  (define (prog-author prog) (list-ref prog 1))
+  (define (prog-instrs prog) (list-ref prog 2))
+  (define (prog-offset prog) (list-ref prog 3))
 
   (define (install-prog core prog addr)
     (let loop ((ptr addr)
   (define (queue-set-ptrs! queue ptrs)
     (set-cdr! queue ptrs))
 
+  (define (dump-queues queues core)
+    (for-each (lambda (queue)
+                (print ";" (queue-owner queue))
+                (for-each (lambda (ptr)
+                            (core ptr 'dump)
+                            (print))
+                          (cdr queue))
+                (print))
+              queues))
+
   (define (prog->string prog)
     (conc ";redcode\n\n"
-          ";name " (prog-name prog) "\n\n"
+          ";name\t" (prog-name prog) "\n"
+          (if (not (null? (prog-author prog)))
+              (conc ";author\t" (prog-author prog) "\n\n")
+              "\n")
           "ORG\t" (prog-offset prog) "\t; Execution offset\n\n"
           (apply conc (map (lambda (instr) (conc (instr '->string) "\n")) (prog-instrs prog)))))
-    
+
+  (define (dump-prog prog)
+    (print (prog->string prog)))
+
+
   ;;; Executive function
   ;;
 
-  (define (run-mars core queues steps-left)
-    (cond
-     ((<= steps-left 0) queues)      ;Tie between remaining players
-     ;; ((<= (length queues) 1) queues) ;There's only one player left who thus wins
-     (else
-      (let* ((queue (car queues))
-             (remaining-queues (cdr queues))
-             (ptrs (queue-ptrs queue))
-             (new-ptrs (execute-instr core (car ptrs) (queue-owner queue))))
-        (if (null? new-ptrs)
-            (run-mars remaining-queues (- steps-left 1))
-            (begin
-              (queue-set-ptrs! queue (append (cdr ptrs) new-ptrs))
-              (run-mars core (append remaining-queues (list queue)) (- steps-left 1))))))))
+  (define (run-mars core queues steps-left min-queue-count)
+    (if (or (<= steps-left 0)
+            (< (length queues) min-queue-count))
+        queues
+        (let* ((queue (car queues))
+               (remaining-queues (cdr queues))
+               (ptrs (queue-ptrs queue))
+               (new-ptrs (execute-instr core (car ptrs) (queue-owner queue))))
+          (if (null? new-ptrs)
+              (run-mars core remaining-queues (- steps-left 1) min-queue-count)
+              (begin
+                (queue-set-ptrs! queue (append (cdr ptrs) new-ptrs))
+                (run-mars core (append remaining-queues (list queue))
+                          (- steps-left 1) min-queue-count))))))
 
   (define (execute-instr core ptr name)
+    ;; (print ptr "\t" (core ptr '->string) "\t(" name ")")
     (let* ((A-ptr (eval-operand core (core ptr 'A-mode) (core ptr 'A-num) ptr name))
            (B-ptr (eval-operand core (core ptr 'B-mode) (core ptr 'B-num) ptr name))
            (modifier (core ptr 'modifier)))
                (list (core '->addr (+ ptr 1))))
            ((exn arithmetic) '())))
         ((JMP)
-         (list (core '->addr (+ ptr (core A-ptr 'A-num)))))
+         (list (core '->addr A-ptr)))
         ((JMZ)
-         (list (core '->addr (+ ptr (if (instr-zero? B-ptr modifier #f name)
-                                        (core A-ptr 'A-num)
-                                        1)))))
+         (list (core '->addr (if (instr-zero? core B-ptr modifier #f name)
+                                 A-ptr
+                                 (+ ptr 1)))))
         ((JMN)
-         (list (core '->addr (+ ptr (if (not (instr-zero? B-ptr modifier #f name))
-                                        (core A-ptr 'A-num)
-                                        1)))))
+         (list (core '->addr (if (not (instr-zero? core B-ptr modifier #f name))
+                                 A-ptr
+                                 (+ ptr 1)))))
         ((DJN)
-         (list (core '->addr (+ ptr (if (not (instr-zero? B-ptr modifier #t name))
-                                        (core A-ptr 'A-num)
-                                        1)))))
+         (list (core '->addr (if (not (instr-zero? core B-ptr modifier #t name))
+                                 A-ptr
+                                 (+ ptr 1)))))
         ((SEQ CMP)
          (list (core '->addr (+ ptr (if (compare-instrs core A-ptr B-ptr modifier =) 2 1)))))
         ((SNE)
         ((SLT)
          (list (core '->addr (+ ptr (if (compare-instrs core A-ptr B-ptr modifier <) 2 1)))))
         ((SPL)
-         (list (core '->addr (+ ptr 1) (core '->addr (+ ptr (core A-ptr 'A-num))))))
+         (list (core '->addr (+ ptr 1)) (core '->addr A-ptr)))
         ((NOP)
          (list (core '->addr (+ ptr 1))))
         (else