我正在爲編碼挑戰編寫常見的lisp代碼,這是一個RPG式的難題,您需要計算戰士處理的總體過度殺傷傷害。因爲我對通用的lisp很陌生,所以我的代碼可能很糟糕。請不要發佈一般的通用lisp編碼技巧,除非它們與錯誤有關。我計劃在發佈此代碼後,在錯誤得到修復後,我們將codereviewT是一個常量,不能用作變量
代碼運行良好,直到tick
(底部)條件when (> overkill-damage 0)
爲真。我使用GNU Clisp 2.49來運行此代碼。
(defun timer (initialization-time interval)
(list :init initialization-time :interval interval :ready nil :time-passed 0))
(defun tick-timer (timer)
(let ((newtime (1+ (getf timer :time-passed))))
(when (and (not (getf timer :ready)) (>= newtime (getf timer :init)))
(setf (getf timer :ready) t))
(setf (getf timer :time-passed) newtime)))
(defun timer-ready? (timer)
(and
(getf timer :ready)
(= 0 (mod (getf timer :time-passed) (getf timer :interval)))))
(defun weapon (damage timer)
(list :damage damage :timer timer))
(defun weapon-attack (weapon)
(tick-timer (getf weapon :timer))
(if (timer-ready? (getf weapon :timer))
(getf weapon :damage)
0))
(defun attack (character)
(reduce #'(lambda (total weapon) (+ (weapon-attack weapon) total)) (getf character :weapons) :initial-value 0))
(defun attack-monster (monster damage)
(- monster damage))
(defun calculate-overkill-damage (health)
(if (> health 0)
0
(abs health)))
(defparameter *warrior* `(:weapons ,(list (weapon 35 (timer 0 4)))))
(defparameter *mage* `(:weapons ,(list (weapon 80 (timer 2 8)))))
(defparameter *rogue* `(:weapons ,(list (weapon 20 (timer 0 3))
(weapon 30 (timer 0 4)))))
(defparameter *monsters* '(300 600 850 900 1100 3500))
(defparameter *current-monster* 0)
(defparameter *overkill* 0)
(defparameter *game-over* nil)
; I assume, for now, that when a monster dies, they will miss the rest of their attacks
(defun tick()
(sleep .1)
(let* ((monster (nth *current-monster* *monsters*))
(new-health (attack-monster monster (attack *warrior*)))
(overkill-damage (calculate-overkill-damage new-health)))
(format t "Attacking~%-------~%Attacking monster ~a, which has ~a health." *current-monster* monster)
(format t "~%Dealt ~a overkill damage!" overkill-damage)
(when (> overkill-damage 0)
(do (format t "Dealt ~a overkill damage!" overkill-damage)
(setf *overkill* (+ *overkill* overkill-damage))
(format t "Total overkill damage is now ~a" *overkill*)
(setf *current-monster* (1+ *current-monster*))
(format t "Moving to next monster, ~a" *current-monster*)
(when (= *current-monster* (1- (length *monsters*)))
(setf *game-over* t))))
(let* ((new-health (attack-monster monster (attack *mage*)))
(new-health (attack-monster monster (attack *rogue*))))
(setf (nth *current-monster* *monsters*) new-health)
(format t "~%Monster is now at ~a health~%" (nth *current-monster* *monsters*)))))
(loop for x from 1 until (equal *game-over* t)
do (tick))
最重要的部分是代碼底部的tick
函數。當此代碼運行時,出現錯誤*** - LET: T is a constant, may not be used as a variable
。
這是什麼獲取在執行打印:
TRUNCATED LOTS OF POINTLESS MESSAGES...
-------
Attacking monster 0, which has 10 health.
Dealt 0 overkill damage!
Monster is now at 10 health
Attacking
-------
Attacking monster 0, which has 10 health.
Dealt 25 overkill damage!
*** - LET: T is a constant, may not be used as a variable
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead.
ABORT :R2 Abort main loop
Break 1 [18]> :w
<1/172> #<SPECIAL-OPERATOR LET>
[170] EVAL frame for form
(LET (FORMAT T "Dealt ~a overkill damage!" OVERKILL-DAMAGE)
(TAGBODY #:LOOP-5923 (IF SETF (GO #:END-5924))
(FORMAT T "Total overkill damage is now ~a" *OVERKILL*)
(SETQ *CURRENT-MONSTER* (1+ *CURRENT-MONSTER*))
(FORMAT T "Moving to next monster, ~a" *CURRENT-MONSTER*)
(WHEN (= *CURRENT-MONSTER* (1- (LENGTH *MONSTERS*))) (SETQ *GAME-OVER* T))
(PSETQ) (GO #:LOOP-5923) #:END-5924
(RETURN-FROM NIL (PROGN *OVERKILL* (+ *OVERKILL* OVERKILL-DAMAGE)))))
Break 1 [18]>
這:w
命令顯示的代碼,是不是即使在那裏,我真不明白這是怎麼回事那裏。 即使我在tick
上調用宏展開,代碼(LET (FORMAT T "Dealt ~a overkill damage!" OVERKILL-DAMAGE)......
也不會出現在任何地方。
有誰知道發生了什麼事?或者,如果您有任何CLISP調試提示可幫助我找出錯誤,請告訴我!
噢好吧,我似乎錯了。我認爲只要順序地執行它的正文中的每個陳述。什麼功能*做*然後呢? – Azeirah
@Azeirah ['progn'](http://www.lispworks.com/documentation/HyperSpec/Body/s_progn.htm#progn),但在這種情況下你甚至不需要這樣做。看到我的答案。 – melpomene