戦闘モジュール2
(let ((tb (make-hash-table :size 7)) (t-t (list '(0 0) '(0 1) '(0 2))) (lim 100) (cur 0) (pl (list 0 1 2)) ms act (name 0)(tgh 1)(n 2)(x 3)(dur 4)(spd 5)(win 6)(lose 7)) (make-random-state) (setf (gethash 0 tb) (list "John" 20 1 18 1 3 "I'm No.1!!" "Oops!!")) (setf (gethash 1 tb) (list "Tosh" 30 2 8 2 6 "I win!!" "Ouch!!")) (setf (gethash 2 tb) (list "Keel" 40 5 2 3 11 "I've done!!" "Oh,my...")) (while (and (setq act (pop t-t)) (< cur lim)) (setq cur (car act)) (let ((acter (gethash (cadr act) tb)) (tgl (remove-if (lambda (x) (>= 0 (elt (gethash x tb) tgh))) (remove (cadr act) pl)))) (if (>= 0 (cadr acter)) (progn (setq pl (delete (cadr act) pl)) (push (format nil "~A \"~A\"" (elt acter name) (elt acter lose)) ms)) (if (>= 0 (length tgl)) (push (format nil "~A \"~A\"" (elt acter name) (elt acter win)) ms) (let ((target (gethash (elt tgl (random (length tgl))) tb)) (dmg (apply '+ (map 'list #'(lambda (x) (1+ (random x))) (make-sequence 'list (elt acter n) :initial-element (elt acter x)))))) (push (format nil "~A's attack!! ~A " (car acter) (car target)) ms) (if (>= 0 (decf dmg (elt target dur))) (push (format nil "deffenced!!") ms) (progn (setf (elt target 1) (- (elt target tgh) dmg)) (push (format nil "got ~A damage!!" dmg) ms))) (setq t-t (merge 'list `((,(+ cur (elt acter spd) (random 6)) ,(cadr act))) t-t '< :key 'car)) (push (format nil " (~A ~A / ~A ~A)" (elt acter name) (elt acter tgh) (elt target name) (elt target tgh)) ms))))) (push (format nil "~%") ms)) (push (format nil (if (= 1 (length pl)) "~%~A won." "~%time over. drawn game.~*") (car (gethash (car pl) tb))) ms) (with-output-to-temp-buffer ("*hoge*" nil) (dolist (m (reverse ms)) (format t "~A" m))))
改良版。パラメータを付けてみた。なかなからしくなってきた。アンテナ対策に書いておくけど、xyzzyで動くLispだよ。
追記
defunして繰り返し動かしたら挙動がおかしかったので修正した。データをquoteで与えていたのが問題。