~octaspire/crates2

90662a000cf64099caf0beaeacd2fed962f68b2e — octaspire 10 months ago 6153ab7
Fix Makefile, implement initial movement

 * Fix the sources wildcard in Makefile;
   it was not updated when the source files
   were moved into a subdirectory.

 * Implement initial movement into east,
   west, north and south directions.
5 files changed, 99 insertions(+), 9 deletions(-)

M Makefile
M src/crates.lisp
M src/level.lisp
M src/main.lisp
M src/textual.lisp
M Makefile => Makefile +1 -1
@@ 15,7 15,7 @@
LISP  ?= sbcl
EVAL  ?= "--eval"
LOAD  ?= "--load
SOURCES = $(wildcard *.lisp)
SOURCES = $(wildcard src/*.lisp)

.PHONY: slime clean help


M src/crates.lisp => src/crates.lisp +87 -2
@@ 14,6 14,20 @@
;; limitations under the License.
(in-package :crates2)

;; Functions

(defun find-at (x y z)
  "Get crate at (X,Y,Z) or NIL if location is empty."
  (find-if #'(lambda (crate)
               (if (and (= (x crate) x)
                        (= (y crate) y)
                        (= (z crate) z))
                   crate
                   nil))
           *level*))

;; Classes

(defclass crate ()
  ((x :initarg :x
      :accessor x)


@@ 37,16 51,48 @@
(defgeneric update (obj)
  (:documentation "Update a crate"))

(defgeneric east (obj)
  (:documentation "Move crate east"))

(defgeneric west (obj)
  (:documentation "Move crate west"))

(defgeneric north (obj)
  (:documentation "Move crate north"))

(defgeneric south (obj)
  (:documentation "Move crate south"))

(defgeneric visual (obj)
  (:documentation "Get visual representation for a crate"))

(defgeneric escape (crate)
  (:documentation "Handle CRATE flying out of the level"))

(defgeneric collide (target crate)
  (:documentation "Handle CRATE colliding into TARGET"))

;; Methods

(defmethod update ((obj crate))
  (format t "update crate "))

(defmethod update ((obj wall))
  (format t "update wall"))
  (format t "update wall ")
  (call-next-method))

(defmethod update ((obj moving))
  (format t "update moving ")
  (let ((v (v obj)))
    (ecase v (:east  (east obj))
             (:west  (west obj))
             (:north (north obj))
             (:south (south obj))))
  (call-next-method))

(defmethod update ((obj player))
  (format t "update player"))
  (format t "update player ")
  (call-next-method))

(defmethod visual ((obj wall))
  #\x)


@@ 54,3 100,42 @@
(defmethod visual ((obj player))
  #\o)

(defmethod west ((obj moving))
  (format t "west~%")
  (let* ((x (- (x obj) 1))
         (crate (find-at x (y obj) (z obj))))
    (if (< x 0)
        (escape obj)
        (if crate
            (collide obj crate)
            (setf (x obj) x)))))

(defmethod east ((obj moving))
  (let* ((x (+ (x obj) 1))
         (crate (find-at x (y obj) (z obj))))
    (if (>= x *level-width*)
        (escape obj)
        (if crate
            (collide obj crate)
            (setf (x obj) x)))))

(defmethod north ((obj moving))
  (let* ((y (+ (y obj) 1))
         (crate (find-at (x obj) y (z obj))))
    (if (>= y *level-height*)
        (escape obj)
        (if crate
            (collide obj crate)
            (setf (y obj) y)))))

(defmethod south ((obj moving))
  (let* ((y (- (y obj) 1))
         (crate (find-at (x obj) y (z obj))))
    (if (< y 0)
        (escape obj)
        (if crate
            (collide obj crate)
            (setf (y obj) y)))))

(defmethod escape ((crate player))
  (setf *running* nil))

M src/level.lisp => src/level.lisp +4 -1
@@ 14,6 14,7 @@
;; limitations under the License.
(in-package :crates2)

(defparameter *running* t)
(defparameter *level* (list))
(defparameter *level-width* 32)
(defparameter *level-height* 24)


@@ 21,7 22,9 @@
;; Methods

(defmethod update ((obj list))
  (format t "update level"))
  (when *running* (loop for crate in *level*
                        do (update crate)))
  *running*)

(defmethod render ((obj list))
  (loop for crate in *level*

M src/main.lisp => src/main.lisp +5 -3
@@ 44,9 44,10 @@
  (when (> *verbose* 0)
    (format t fmt args)))

(defun run ()
(defun run (level)
  (unless *errors*
    (ui-render)))
    (loop while (update level)
          do (ui-render level))))

(defun usage ()
  (opts:describe


@@ 75,6 76,7 @@

(setf *level* (cons (make-instance 'wall   :x 2 :y 2 :z 0) *level*))
(setf *level* (cons (make-instance 'player :x 5 :y 4 :z 0) *level*))
(setf (v (car *level*)) :west)

(defun main ()
  (let ((options (handler-case


@@ 84,4 86,4 @@
    (cond-option options
                 (:help (usage))
                 (:version (version))
                 (otherwise (run)))))
                 (otherwise (run *level*)))))

M src/textual.lisp => src/textual.lisp +2 -2
@@ 29,10 29,10 @@
          do (setf (aref a i) (empty-line)))
    a))

(defun ui-render ()
(defun ui-render (level)
  (let ((lines (empty-level))
        (bar (format nil "~v@{~A~:*~}" *level-width* #\-)))
    (loop for crate in *level*
    (loop for crate in level
          do (progn
               (let* ((x (x crate))
                      (y (y crate))