diff --git a/terranostra.lisp b/terranostra.lisp index 0e647bb..cba9b40 100644 --- a/terranostra.lisp +++ b/terranostra.lisp @@ -9,13 +9,13 @@ (defvar *world* NIL) (defconstant *directions* '(N NE E SE S SW W NW)) - +(defconstant *base-height* 50) (defstruct patch (pos '(0 0)) ;position - (alt 50) ;altitude - (streams-in NIL) - (streams-out NIL)) + (alt *base-height*) ;altitude + (stream-in NIL) + (stream-out NIL)) (defun init-matrix (size) @@ -95,9 +95,8 @@ (defun create-peak (x y height world) "Create a mountain peak at the specified location" - (let ((base-height (patch-alt (make-patch)))) - ;;TODO - )) + ;;TODO + ) (defun create-valleys (world &optional (aqueousness 5)) "Create valleys through streams. Aqueousness determines their number." @@ -105,32 +104,38 @@ (* (length world) (length (first world))))))) ((= n nstreams) world) - (setf world (create-stream (random (first world)) - (random (length world)) world)))) + (create-stream (random (first world)) + (random (length world)) world))) (defun create-stream (x y world) "Create a stream, starting at x/y" - (let ((dir NIL) (min 10000) (nextpatch NIL)) - ;;XXX min=1000 is is a hack to get a hypothetical maximum altitude + (let* ((minheight (* *base-height* 1000)) (here (coord x y world)) + ;;XXX hack: minheight must initially be higher than any patch + (nextpatch NIL) (dir NIL)) ;;Figure out the lowest neighbouring patch (dolist (d *directions*) - (let ((np (patchindir x y d))) - (when (and np (< (patch-alt np) min)) - (setf min (patch-alt np)) + (let* ((np (patchindir x y d)) (alt (when np (patch-alt np)))) + (when (and np (not (eq d (patch-stream-in here))) + (or (< alt minheight) + (and (= alt minheight) (zerop (random 2))))) + (setf minheight alt) (setf dir d nextpatch np)))) - (unless (and dir nextpatch) (return-from create-stream world)) - ;;Set streams-in and streams-out - (setf (patch-streams-out (coord x y)) - (append (patch-streams-out (coord x y)) (list dir))) - (setf (patch-streams-in nextpatch) - (append (patch-streams-out nextpatch) - (list (opposite-dir dir)))) ;;Erode this patch - (setf (patch-alt (coord x y)) - (- (patch-alt (coord x y)) - (random (round (/ (patch-alt (coord x y)) 10))))) + (let* ((instream (patch-stream-in here)) + (maxheight (if instream + (patch-alt (neighbour here instream)) + (patch-alt here)))) + (setf (patch-alt here) + (- maxheight (random (round (/ maxheight 10)))))) + (format t "~&Creating a stream at ~S/~S, flowing ~S." x y dir) + ;; Test for break conditions (hitting another stream or the edge + ;; of the world) + (unless (and dir nextpatch (null (patch-stream-out nextpatch))) + (return-from create-stream)) + ;;Set streams-in and streams-out + (setf (patch-stream-out (coord x y)) dir) + (setf (patch-stream-in nextpatch) (opposite-dir dir)) ;;Continue forming the stream - ;;FIXME causes an endless loop -> lowest neighbour becomes this patch (create-stream (first (patch-pos nextpatch)) (second (patch-pos nextpatch)) world)))