2 ;;; An implementation of the Memory Array Redcode Simulator (MARS)
14 (define max-steps 10000)
20 (define ((make-instr opcode modifier A-mode A-num B-mode B-num name) . args)
22 (('copy n) (make-instr opcode modifier A-mode A-num B-mode B-num n))
24 (('modifier) modifier)
30 (('print) (print opcode
32 " " (mode-string A-mode) A-num
33 ", " (mode-string B-mode) B-num
34 (if (null? name) "" (conc " ; " name))))
35 (('set-opcode! x n) (set! opcode x) (set! name n))
36 (('set-modifier! x n) (set! modifier x) (set! name n))
37 (('set-A-mode! x n) (set! A-mode x) (set! name n))
38 (('set-A-num! x n) (set! A-num x) (set! name n))
39 (('set-B-mode! x n) (set! B-mode x) (set! name n))
40 (('set-B-num! x n) (set! B-num x) (set! name n))))
42 (define (mode-string mode)
48 ((pre-indirect-A "{"))
49 ((pre-indirect-B "<"))
50 ((post-indirect-A "}"))
51 ((post-indirect-B ">"))))
53 (define initial-instruction
54 (make-instr 'DAT 'F 'immediate 0 'immediate 0 '()))
57 ;;; Memory setup and addressing
60 (define core (make-vector core-size '()))
65 (define (core-set! i x)
66 (vector-set! core i x))
68 (define (initialize-core)
70 (unless (>= i core-size)
71 (core-set! i (initial-instruction 'copy '()))
76 (unless (>= i core-size)
80 (define (addr+ . args)
82 (modulo (+ a b core-size) core-size))
88 (define (make-prog name instrs offset)
89 (list name instrs offset))
91 (define (prog-name prog) (list-ref prog 0))
92 (define (prog-instrs prog) (list-ref prog 1))
93 (define (prog-offset prog) (list-ref prog 2))
95 (define (install-prog prog addr)
97 (instrs (prog-instrs prog)))
98 (unless (null? instrs)
99 (core-set! ptr ((car instrs) 'copy (prog-name prog)))
100 (loop (addr+ ptr 1) (cdr instrs))))
101 (make-player (prog-name prog)
102 (addr+ addr (prog-offset prog))))
104 (define (can-install-prog? prog-len addr)
105 (let loop ((ptr addr)
106 (remaining prog-len))
109 (if (null? ((core-get ptr) 'name))
114 (define (install-progs progs)
115 (let loop ((players '())
117 (if (null? progs-left)
119 (let ((addr (pseudo-random-integer core-size))
120 (prog (car progs-left)))
121 (if (can-install-prog? (length (prog-instrs prog)) addr)
122 (loop (cons (install-prog prog addr) players)
124 (loop players progs-left))))))
126 (define (make-player name ptr)
129 (define (player-set-ptrs! player ptrs)
130 (set-cdr! prog-queue ptrs))
133 ;;; Executive function
136 (define (run players step)
138 ((> step max-steps) players) ;Tie between remaining players
139 ((<= (length players) 1) players) ;There's only one player left who thus wins
141 (let ((player (car players))
142 (other-players (cdr players))
143 (ptrs (player-ptrs player)))
144 (let ((new-ptrs (execute-instr (car ptrs))))
146 (run other-players (+ step 1))
148 (player-set-ptrs! (append (cdr ptrs) new-ptrs))
149 (run (append other-players (list player)) (+ step 1)))))))))
151 (define (execute-instr ptr)
152 (let* ((instr (core-get ptr))
153 (A-pointer (eval-operand (instr 'A-mode) (instr 'A-num) ptr))
154 (B-pointer (eval-operand (instr 'B-mode) (instr 'B-num) ptr))
155 (modifier (instr-modifier instr)))
156 (case (instr-opcode instr)
157 ((DAT) '()) ;Game over, man, game over!
193 ((NOP) (list (addr+ ptr 1)))
195 (error "Unrecognised opcode" (instr-opcode instr))))))
197 (define (eval-operand mode num ptr)
202 ((indirect-A) (addr+ num ((core-get (addr+ ptr num)) 'A-num)))
203 ((indirect-B) (addr+ num ((core-get (addr+ ptr num)) 'B-num)))
205 (let ((aux-instr (core-get (addr+ ptr num))))
206 (instr-set-A-num! aux-instr (addr+ -1 (aux-instr 'A-num)))
207 (addr+ num (aux-instr 'A-num))))
209 (let ((aux-instr (core-get (addr+ ptr num))))
210 (instr-set-B-num! aux-instr (addr+ -1 (aux-instr 'B-num)))
211 (addr+ num (aux-instr 'B-num))))
213 (let* ((aux-instr (core-get (addr+ ptr num)))
214 (old-A-num (aux-instr 'A-num)))
215 (instr-set-A-num! aux-instr (addr+ 1 (aux-instr 'A-num)))
216 (addr+ num old-A-num)))
218 (let* ((aux-instr (core-get (addr+ ptr num)))
219 (old-B-num (aux-instr 'B-num)))
220 (instr-set-B-num! aux-instr (addr+ 1 (aux-instr 'B-num)))
221 (addr+ num old-B-num)))
223 (error "Unrecognized mode" mode)))))