Skip to content

Instantly share code, notes, and snippets.

@fogus
Created December 31, 2008 19:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fogus/42089 to your computer and use it in GitHub Desktop.
Save fogus/42089 to your computer and use it in GitHub Desktop.
zombies cl
(comment
Features:
- One monster type: Zombies!
- Teleporters
- Artificial Unintelligence technology for realistic zombie horde
behavior
- Full in-game documentation
- Trees
- Gold (because really, what's a roguelike without gold?)
- Each game is guaranteed to end in death by zombie
Release Notes:
- Designed for use with CLISP. Any other Lisp is likely not to work
without modification, due to implementation-specific single-character
input code. If you're trying to alter this program for your Lisp, the
function "get-input-char" is the only thing you need to touch.
- To run the program:
- install CLISP
- save the code as "zombies.lisp"
- type "clisp zombies.lisp" and start running for your life!
- The program is designed to run in an 80x24 terminal. Bigger will
work OK, smaller definitely won't.
License:
- This software is released under the Zombie Public License (ZPL).
This means you can use the code for anything you like, but if you
complain about any aspect of it, zombies will eat your BRRRAAAAINS!!!
Partial screenshot:
Level: 2 HP: 17 Gold: 10
.......#....#..$.......#..Z...
....................$.........
..............#Z....#.....#Z..
........#...>.Z.....ZZZ.......
...#......@Z...#Z.#..Z.ZZ.....
..........$...........#.......
..............................
)
(setf *random-state* (make-random-state t))
(defparameter *maxx* 79)
(defparameter *maxy* 22)
(defstruct player
x
y
(hp 20)
(gold 0))
(defstruct zombie
x
y)
(defvar *screen* (make-array (list *maxx* *maxy*)))
(defvar *messages* ())
(defvar *level* 0)
(defvar *player* (make-player))
(defvar *zombies* ())
(defun get-input-char ()
(system::input-character-char
(EXT:with-keyboard (read-char EXT:*keyboard-input*))))
(defun play-game()
(dotimes (i (1+ *maxy*))
(format t "~%"))
(new-level)
(setf *messages* (cons "Zombies! Press ? for help." nil))
(print-screen)
(loop
(setf *messages* nil)
(when (process-player)
(recover-hp)
(process-zombies)
(if (< (player-hp *player*) 1)
(die "You've been killed by zombies."))
(print-screen))))
(defun new-level ()
(dotimes (i (* 2 *maxy*))
(format t "~%"))
(incf *level*)
(dotimes (i *maxy*)
(dotimes (j *maxx*)
(setf (aref *screen* j i) (list #\.))))
(dotimes (i (random 100))
(push #\$ (aref *screen* (random *maxx*) (random *maxy*))))
(dotimes (i (random 10))
(push #\^ (aref *screen* (random *maxx*) (random *maxy*))))
(dotimes (i (random 80))
(push #\# (aref *screen* (random *maxx*) (random *maxy*))))
(setf *zombies* nil)
(dotimes (i (+ 8 (* 2 *level*)))
(let ((x (random *maxx*))
(y (random *maxy*)))
(push (make-zombie :x x :y y) *zombies*)
(push #\Z (aref *screen* x y))))
(push #\> (aref *screen* (random *maxx*) (random *maxy*)))
(let ((x (random *maxx*))
(y (random *maxy*)))
(setf (player-x *player*) x)
(setf (player-y *player*) y)
(push #\@ (aref *screen* x y)))
(push (format nil "Welcome to Level ~A." *level*) *messages*))
(defun print-screen ()
(format t "~A" #\Return)
(dotimes (i (1+ *maxx*))
(format t " "))
(format t "~A[23A" (code-char 27))
(format t "~A" #\Return)
(dotimes (i (1+ *maxx*))
(format t " "))
(format t "~A" #\Return)
(format t "Level: ~A HP: ~A Gold: ~A"
*level* (player-hp *player*) (player-gold *player*))
(dotimes (i *maxy*)
(format t "~%")
(dotimes (j *maxx*)
(format t "~A" (car (aref *screen* j i)))))
(format t "~%")
(dolist (i (reverse *messages*))
(format t "~A " i)))
(defun process-player ()
(let ((input (get-input-char))
(new-x nil)
(new-y nil))
(cond ((equal input #\q) (die "Goodbye."))
((equal input #\h)
(setf new-x (- (player-x *player*) 1))
(setf new-y (player-y *player*)))
((equal input #\j)
(setf new-y (+ (player-y *player*) 1))
(setf new-x (player-x *player*)))
((equal input #\k)
(setf new-y (- (player-y *player*) 1))
(setf new-x (player-x *player*)))
((equal input #\l)
(setf new-x (+ (player-x *player*) 1))
(setf new-y (player-y *player*)))
((equal input #\y)
(setf new-x (- (player-x *player*) 1))
(setf new-y (- (player-y *player*) 1)))
((equal input #\u)
(setf new-x (+ (player-x *player*) 1))
(setf new-y (- (player-y *player*) 1)))
((equal input #\b)
(setf new-x (- (player-x *player*) 1))
(setf new-y (+ (player-y *player*) 1)))
((equal input #\n)
(setf new-x (+ (player-x *player*) 1))
(setf new-y (+ (player-y *player*) 1)))
((equal input #\.)
(setf new-x (player-x *player*))
(setf new-y (player-y *player*)))
((equal input #\?) (print-help) (return-from process-player nil))
(t (return-from process-player nil)))
(when (or (< new-x 0) (>= new-x *maxx*) (< new-y 0) (>= new-y
*maxy*))
(return-from process-player nil))
(when (equal (car (aref *screen* new-x new-y)) #\>)
(new-level)
(return-from process-player t))
(let ((gold 0))
(loop
(if (not (equal (car (aref *screen* new-x new-y)) #\$))
(return))
(incf (player-gold *player*))
(pop (aref *screen* new-x new-y))
(incf gold))
(if (> gold 0)
(push (format nil "Found ~A gold." gold) *messages*)))
(when (equal (car (aref *screen* new-x new-y)) #\Z)
(return-from process-player nil))
(when (equal (car (aref *screen* new-x new-y)) #\#)
(return-from process-player nil))
(when (equal (car (aref *screen* new-x new-y)) #\^)
(pop (aref *screen* new-x new-y))
(loop
(setf new-x (random *maxx*))
(setf new-y (random *maxy*))
(if (equal (car (aref *screen* new-x new-y)) #\.)
(return))))
(move-player new-x new-y)))
(defun move-player (x y)
(pop (aref *screen* (player-x *player*) (player-y *player*)))
(setf (player-x *player*) x)
(setf (player-y *player*) y)
(push #\@ (aref *screen* x y)))
(defun recover-hp ()
(if (and (= 0 (random 10)) (< (player-hp *player*) 20))
(incf (player-hp *player*))))
(defun process-zombies ()
(dotimes (z (length *zombies*))
(if (or (= 0 (random 7)) (not (process-zombie-smart z)))
(process-zombie-random z))))
(defun process-zombie-smart (z)
(let* ((z-x (zombie-x (nth z *zombies*)))
(z-y (zombie-y (nth z *zombies*)))
(p-x (player-x *player*))
(p-y (player-y *player*))
(new-x z-x)
(new-y z-y))
(cond ((> z-x p-x) (decf new-x))
((< z-x p-x) (incf new-x)))
(cond ((> z-y p-y) (decf new-y))
((< z-y p-y) (incf new-y)))
(when (equal (car (aref *screen* new-x new-y)) #\@)
(decf (player-hp *player*))
(push "Ouch!" *messages*)
(return-from process-zombie-smart t))
(when (equal (car (aref *screen* new-x new-y)) #\Z)
(return-from process-zombie-smart nil))
(when (equal (car (aref *screen* new-x new-y)) #\#)
(return-from process-zombie-smart nil))
(when (equal (car (aref *screen* new-x new-y)) #\^)
(loop
(setf new-x (random *maxx*))
(setf new-y (random *maxy*))
(if (equal (car (aref *screen* new-x new-y)) #\.)
(return))))
(move-zombie z new-x new-y)
t))
(defun process-zombie-random (z)
(let* ((z-x (zombie-x (nth z *zombies*)))
(z-y (zombie-y (nth z *zombies*)))
(new-x z-x)
(new-y z-y)
(rand-x (random 3))
(rand-y (random 3)))
(if (= rand-x 0)
(incf new-x)
(if (= rand-x 1)
(decf new-x)))
(if (= rand-y 0)
(incf new-y)
(if (= rand-y 1)
(decf new-y)))
(when (or (< new-x 0) (>= new-x *maxx*) (< new-y 0) (>= new-y
*maxy*))
(return-from process-zombie-random nil))
(when (equal (car (aref *screen* new-x new-y)) #\Z)
(return-from process-zombie-random nil))
(when (equal (car (aref *screen* new-x new-y)) #\#)
(return-from process-zombie-random nil))
(when (equal (car (aref *screen* new-x new-y)) #\^)
(loop
(setf new-x (random *maxx*))
(setf new-y (random *maxy*))
(if (equal (car (aref *screen* new-x new-y)) #\.)
(return))))
(move-zombie z new-x new-y)))
(defun move-zombie (z x y)
(pop (aref *screen*
(zombie-x (nth z *zombies*))
(zombie-y (nth z *zombies*))))
(setf (zombie-x (nth z *zombies*)) x)
(setf (zombie-y (nth z *zombies*)) y)
(push #\Z (aref *screen* x y)))
(defun die (message)
(format t "~%~%~A Score: ~A~%~%" message
(+ (* (player-gold *player*) *level*) (* 10 (- *level* 1))))
(quit))
(defun print-help ()
(dotimes (i (+ 3 *maxx*))
(format t "~%"))
(format t "Welcome to Zombies!~%~%")
(format t "The world has been overrun by zombies. ")
(format t "You have no weapons or other means of~%")
(format t "self-defense. All you can do is run for ")
(format t "the exit! That, and collect gold.~%~%")
(format t "Objects:~%@ - You~%Z - Zombies!~%$ - Gold")
(format t "~%# - Trees~%^ - Teleporters~%")
(format t "> - Level Exit~%~%Controls:~%y k u~%h @ l")
(format t "~%b j n~%~%. - Wait~%q - Quit~%~%")
(format t "Press any key to continue.~%")
(get-input-char)
(print-screen))
(play-game)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment