Common Lisp is a multi-paradigm programming language, which was used for programming roguelikes several times.
The ANSI standard of Common Lisp was written about 20 years ago. Let’s look at the advantages that Common Lisp had and still has over most other programming languages.
As you can see, Common Lisp was way ahead of it’s time in 80s, and it’s still ahead now. Maybe you could use this alien technology to get ahead of other roguelike developers?
There are a lot of Common Lisp implementations, and they are mostly quite good. SBCL is an industrial-strength free implementation, and generally considered the best free Lisp for stuff like web-applications or where speed does matter. However, as a roguelike developer you’ll want to choose CLISP. It is somewhat slower than SBCL, but two things set it apart: it runs quite well on Windows, and the executables it produces are not very big (<10 mb, compressed to ~3mb), unlike mammoth-sized SBCL images. Anyway, if you’ll stick to ANSI standard and portable libraries, there’s little difference between various Lisps.
Practical Common Lisp is usually considered the best introductory book about CL. What’s good about this book is how it really opens up the whole lot of possibilities, without the fawning advocacy that you’ll find in some books on Ruby and similar trendy languages. Get a copy of SLIME (Superior Lisp Interaction Mode for Emacs), its a lisp-mode for the Emacs text-editor which’ll make things easier. It may take some time to get comfortable to Emacs but it is surely a powerful tool for Common-Lisp developers.
Also check comp.lang.lisp Usenet newsgroup, which is frequented by the most skilled users of the language.
Yes, and you can use other C libraries (such as SDL and OpenGL) too. You can even use them more effectively, since you’ll still have the advantages of interactive development (as with any Lisp program). This is done using Foreign Function Interface, such as CFFI.
You’ll have to write a library wrapper that maps the functions of C library to Lisp functions, or use someone else’s work. The wrappers for SDL and OpenGL are easily found through Google. The wrapper for PDCurses (and other curses variations) was written by Timofei Shatrov (get curses.lisp from the sources of his latest game). However it takes some work to set it up.
By now, I’ll assume you’re using SLIME with CLISP. The basic setup won’t work here, because curses and Emacs don’t play well together. Here’s a workaround: start CLISP separately and type:
(load "/path/to/asdf.lisp")
(load "/path/to/slime/swank.asd")
(asdf:oos 'asdf:load-op :swank)
(ext:saveinitmem "clispswank" :quiet t :norc t :executable t
- - - - :init-function #'swank:create-server)
Now, you’ll have executable file called clispswank somewhere. Run it, and in Emacs type M-x slime-connect and press Enter until it connects. Now, you’re in a good shape to start using curses. Load/compile CFFI, trivial-gray-streams and curses.lisp (you can automate this process by writing an appropriate asd file). Then you can start playing with it:
(in-package :curses)
(connect-console)
(erase)
(attrset :cpurple)
(mvaddstr 2 2 "Hello World!")
(refresh)
Look how the text appears in the other window. You can start from here and incrementally develop the entire roguelike!
As of April 2020, known Lisp bindings for ncurses are croatoan, cl-charms and cl-ncurses. croatoan and cl-charms are based on CFFI and actively developed, cl-ncurses was based on the less portable UFFI and has not been touched for some ten years now.
All three of them are available in the popular Common Lisp library manager Quicklisp.
By using Quicklisp, the libraries can be installed as easily as calling
(ql:quickload "croatoan")
Then, provided that ncurses is installed, the library can be used as easily as:
(in-package :croatoan)
(defun test1 ()
(with-screen (scr :input-echoing nil :input-blocking t :enable-colors t)
- (clear scr)
- (move scr 2 0)
- (format scr "Type chars. Type q to quit.~%~%")
- (refresh scr)
- (setf (color-pair scr) '(:yellow :red)
- - (attributes scr) '(:bold))
- (event-case (scr event)
- (#\q (return-from event-case))
- (otherwise (princ event scr)
- - - - (refresh scr)))))
Some examples can be seen here:
McParen (talk) 13:15, 23 June 2018 (CEST)