about summary refs log tree commit diff stats
path: root/crpg.lisp
diff options
context:
space:
mode:
authorDarren Bane <dbane@tilde.institute>2020-05-02 13:27:08 -0400
committerDarren Bane <dbane@tilde.institute>2020-05-02 13:27:08 -0400
commit1e64fdf07c45e0380f759589b7669bb9bf88fea0 (patch)
tree6e1c1837a8fa7a9ae0d5ec8a1fc087ca24567426 /crpg.lisp
downloadlsp-1e64fdf07c45e0380f759589b7669bb9bf88fea0.tar.gz
Switched to using git, even though its only hobby programming
Diffstat (limited to 'crpg.lisp')
-rwxr-xr-xcrpg.lisp197
1 files changed, 197 insertions, 0 deletions
diff --git a/crpg.lisp b/crpg.lisp
new file mode 100755
index 0000000..10f40d3
--- /dev/null
+++ b/crpg.lisp
@@ -0,0 +1,197 @@
+#!/usr/local/bin/clisp
+(load "cscreen")
+(require "cscreen")
+(defpackage #:crpg
+  (:use #:common-lisp #:cscreen)
+  (:export
+   #:main))
+(in-package #:crpg)
+(defclass <location> () ((row :initarg r :accessor row)
+			 (col :initarg c :accessor col)))
+(defmethod print-object ((obj <location>) stream)
+  (format stream "~A ~A" (row obj) (col obj)))
+
+;; TODO: <location-contents> class, or maybe rename the other one to <coord>
+(defvar *monster* (make-array '(10 10)))
+(defvar *item* (make-array '(10 10)))
+
+(defvar *curr-loc* (make-instance (find-class '<location>) 'r 5 'c 5))
+(defconstant +move-err+ "You cannot move in that direction!")
+(defconstant +press-key+ "Press Enter to continue.")
+(defconstant +exit+ (make-instance (find-class '<location>)
+				   'r (+ (random 10) 1)
+				   'c (+ (random 10) 1)))
+;; (format *standard-output* "~A~%" +exit+)
+;; (sleep 3)
+
+;; TODO: <player> class?
+(defvar *gold* 0)
+(defvar *health* 20)
+(defvar *weapon* 1)
+
+(defclass <monster> () ((name :initarg n :reader name)
+			(attack :initarg a :reader attack)
+			(health :initarg h :accessor health)))
+(defmethod print-object ((obj <monster>) stream)
+  (format stream "~A" (name obj)))
+(defun create-monster (n a h)
+  (make-instance (find-class '<monster>) 'n n 'a a 'h h))
+(defconstant +monsters+
+  (vector
+   (create-monster "blind bat" 2 1)
+   (create-monster "rat" 1 1)
+   (create-monster "snake" 3 1)
+   (create-monster "goblin" 2 3)
+   (create-monster "troll" 4 4)
+   (create-monster "bear" 5 5)
+   (create-monster "lion" 5 4)
+   (create-monster "sabretooth" 6 5)
+   (create-monster "elephant" 7 8)
+   (create-monster "dragon" 9 8)))
+(defclass <item> () ((name :initarg n :reader name)
+		     (class :initarg c :reader class)
+		     (val :initarg v :reader val)))
+(defun create-item (n c v)
+  (make-instance (find-class '<item>) 'n n 'c c 'v v))
+(defconstant +items+
+  (vector
+   (create-item "apple" 'food 1)
+   (create-item "bread" 'food 2)
+   (create-item "chicken" 'food 3)))
+(defgeneric copy (obj))
+(defmethod copy ((obj <monster>))
+  (create-monster (name obj) (attack obj) (health obj)))
+(defvar *curr-monster*)
+(defvar *monster-gold*)
+(defun my-print (x)
+  (format *standard-output* "~A~%" x))
+(defun print-help ()
+  (cursor 14 1)
+  (my-print "Commands:   n - north")
+  (my-print "            s - south")
+  (my-print "            e - east")
+  (my-print "            w - west")
+  (my-print "            a - attack")
+  (my-print "            x - use exit")
+  (write-char #\newline)
+  (my-print "            q - quit"))
+(defgeneric move (loc dir))
+(defmethod move ((loc <location>) dir)
+  (case dir
+	((n) (if (= (row loc) 1)
+		 (my-print +move-err+)
+	       (progn (setf (row loc) (- (row loc) 1))
+		      (my-print "You go north."))))
+	((s) (if (= (row loc) 10)
+		 (my-print +move-err+)
+	       (progn (setf (row loc) (+ (row loc) 1))
+		      (my-print "You go south."))))
+	((w) (if (= (col loc) 1)
+		 (my-print +move-err+)
+	       (progn (setf (col loc) (- (col loc) 1))
+		      (my-print "You go west."))))
+	((e) (if (= (col loc) 10)
+		 (my-print +move-err+)
+	       (progn (setf (col loc) (+ (col loc) 1))
+		      (my-print "You go east."))))
+	(t (error "bad dir"))))
+(defgeneric loc= (l r))
+(defmethod loc= ((l <location>) (r <location>))
+  (and (= (row l) (row r)) (= (col l) (col r))))
+(defun handle-cmd (cmd)
+  (cond
+   ((string= cmd "n")
+    (move *curr-loc* 'n))
+   ((string= cmd "s")
+    (move *curr-loc* 's))
+   ((string= cmd "w")
+    (move *curr-loc* 'w))
+   ((string= cmd "e")
+    (move *curr-loc* 'e))
+   ((string= cmd "x")
+    (if (loc= *curr-loc* +exit+)
+	(if (< *gold* 100)
+	    (my-print "You dont have enough gold!")
+	  (my-print "You have escaped! Well done!"))))
+   ((string= cmd "a")
+    (if (null *curr-monster*)
+	(my-print "There's nothing to attack!")
+      (progn (loop while (and (> (health *curr-monster*) 0) (> *health* 0))
+		   do (cursor 10 1) (clrtoeol)
+		   (cursor 11 1) (clrtoeol)
+		   (cursor 12 1) (clrtoeol)
+		   (cursor 10 1)
+		   (let ((attack (+ *weapon* (random 9)))
+			 (monster-attack (attack *curr-monster*)))
+		     (cond
+		      ((= attack monster-attack)
+		       (my-print "No one wins this round."))
+		      ((> attack monster-attack)
+		       (format *standard-output* "You deal the ~A a blow!~%" (name *curr-monster*))
+		       (setf (health *curr-monster*) (- (health *curr-monster*) 1)))
+		      ((< attack monster-attack)
+		       (my-print "You have been wounded!")
+		       (setq *health* (- *health* 1))))
+		     (my-print +press-key+)
+		     (read-line)))
+	     (cursor 10 1)
+	     (if (> *health* 0)
+		 (progn (my-print "You won the fight!")
+			(format *standard-output* "You found ~A pieces of gold!~%" *monster-gold*)
+			(setq *gold* (+ *gold* *monster-gold*))
+			(setq *curr-monster* nil)
+			(setf (aref *monster* (row *curr-loc*) (col *curr-loc*)) nil)
+			(my-print +press-key+)
+			(read-line))
+	       (progn (format *standard-output* "The ~A killed you!~%" (name *curr-monster*))
+		      (my-print "Game over!")
+		      (throw 'quit nil))))))
+   ((string= cmd "q")
+    (my-print "Bye!")
+    (throw 'quit nil))))
+(defun get-next-cmd ()
+  (cursor 8 1)
+  (my-print "What now")
+  (let ((reply (read-line)))
+    (cursor 10 1)
+    (clrtoeol)
+    reply))
+(defun main-loop ()
+  (loop
+   (cursor 1 1)
+   (format *standard-output* "Your position: ~A~%" *curr-loc*)
+   (cursor 1 25)
+   (format *standard-output* "Gold: ~A   Health: ~A~%" *gold* *health*)
+   (cursor 2 1)
+   (if (loc= *curr-loc* +exit+)
+       (my-print "You are at the exit!")
+     (clrtoeol))
+   (cursor 3 1)
+   (clrtoeol)
+   (let ((monster-type (aref *monster* (row *curr-loc*) (col *curr-loc*))))
+     (if (null monster-type)
+	 (progn (setq *curr-monster* nil)
+		(setq *monster-gold* 0))
+       (progn (setq *curr-monster* (copy (elt +monsters+ monster-type)))
+	      (format *standard-output* "Monster: ~A~%" *curr-monster*)
+	      (setq *monster-gold* (* monster-type (random 6))))))
+   (handle-cmd (get-next-cmd))))
+(defun init ()
+  (page)
+  (setq *random-state* (make-random-state t))
+  (do ((row 1 (+ row 1)))
+      ((>= row 10))
+      (do ((col 1 (+ col 1)))
+	  ((>= col 10))
+	  (let ((rnd (random 11)))
+	    (if (/= rnd 0)
+		(setf (aref *monster* row col) (- rnd 1))))))
+  
+  (do ((row 1 (+ row 1)))
+      ))
+(defun main ()
+  (init)
+  (print-help)
+  (catch 'quit (main-loop)))
+(provide "crpg")
+(crpg:main)