# cl-tcod The `cl-tcod` library provides an interface (wrapper) between Common Lisp and the Doryen Library (libtcod). Libtcod is described on its [website][libtcod] as follows: libtcod, a.k.a. "The Doryen Library", is a free, fast, portable and uncomplicated API for roguelike developpers providing an advanced true color console, input, and lots of other utilities frequently used in roguelikes. ## Files `cl-tcod` consists of the following files: * `tcod.lisp`, a lisp file which creates lisp bindings for C functions in the compiled libtcod library, using the CFFI lisp foreign function interface. * `tcod.asd`, which allows TCOD to be easily loaded and used as a library by other common lisp programs, via the ASDF library-loading facility. * `tcod-colours.lisp`, a lisp file containing definitions for all the colours named in /etc/X11/rgb.txt; autogenerated using 'parse-rgb' (see below) * `parse-rgb.lisp`, a lisp file containing code for parsing `/etc/X11/rgb.txt` and generating `tcod-colours.lisp` * `parse-rgb.asd`, ASDF system definition file for `parse-rgb.lisp` `cl-tcod` has been tested with [SBCL][] 1.1.0 on Linux, Mac OSX Mountain Lion and Windows, [Clozure Common Lisp][Clozure] 1.5 on Linux and Windows, and [Clisp][] on Windows. [libtcod]: http://doryen.eptalys.net/libtcod/ [SBCL]: http://www.sbcl.org [Clozure]: http://ccl.clozure.com [Clisp]: http://clisp.cons.org [Quicklisp]: http://www.quicklisp.org/ [ASDF]: http://common-lisp.net/project/asdf/ [defstar]: http://bitbucket.org/eeeickythump/defstar/ [CFFI]: http://common-lisp.net/project/cffi/ ## License The `cl-tcod` package is placed in the Public Domain by its author. ## Dependencies `cl-tcod` depends on the following libraries: * `ASDF`: http://common-lisp.net/project/asdf/ * `defstar`: http://bitbucket.org/eeeickythump/defstar/ * `CFFI`: http://common-lisp.net/project/cffi/ ## Installation You need to know your way around your chosen common lisp and how to install and load lisp libraries before proceeding. You also need to have a version of libtcod newer than 1.4.1rc2, which is the first version that includes the `wrappers.c` and `wrappers.h` source files that allow `cl-tcod` to interface with libtcod. 1. Ensure you have a working common lisp installation. 2. Ensure either [Quicklisp][] or the [ASDF][] lisp library is installed. 3. If [CFFI][] or [defstar][] are not installed, download and install them somewhere ASDF can find them. CFFI requires several third-party lisp libraries -- see the CFFI documentation for more details. Note that if you have Quicklisp installed, you can install CFFI and its dependencies easily using the command `(ql:quickload "cffi")` at the Lisp prompt. 4. Put the `cl-tcod` files in a directory where ASDF can find them. 5. Make sure libtcod is installed and compiled. Make sure the libtcod dynamically linked library (.dll, .so or .dylib file) is somewhere your lisp system can find it. It probably is, but if `CFFI` complains about being unable to find the library, you can either copy it to an appropriate directory or add its directory to the list variable `cffi:*foreign-library-directories*` e.g. by typing the following in the lisp interpreter: :::cl (push #P"/my/libtcod/directory/" cffi:*foreign-library-directories*) On windows, .dll files should be put in one of the directories listed in the `PATH` environment variable. You will need to put `SDL.dll` in the same place if you don't already have SDL installed. On Linux, you can usually put .so files in `/usr/local/lib/`. Use your package installer to install `libSDL`. Try running the libtcod demo programs to check everything works. 6. Start lisp, then load `cl-tcod`. Using Quicklisp: :::cl (ql:quickload :tcod) Using ASDF: :::cl (load "/path/to/asdf/asdf.lisp") (asdf:oos 'asdf:load-op :tcod) 7. Type something like the following commands at the lisp prompt to start using libtcod from within Lisp. Alternatively you can type `(tcod:hello-world)`, which is a function containing the code below. :::cl (tcod:console-set-custom-font "terminal.png" '(:font-layout-ascii-in-row) 16 16) (tcod:console-init-root 80 25 "Test" nil :renderer-sdl) (tcod:console-clear tcod:*root*) (tcod:console-print tcod:*root* 1 1 "Hello, world!~%") (tcod:console-wait-for-keypress t) ## Differences between CL-TCOD and libtcod ### Naming conventions The C function `TCOD_foo_bar` corresponds to the lisp function `foo-bar`, which is in the `tcod` package (and so requires a prefix of `tcod:` to access in most situations). Underscores become hyphens. So: :::cl (tcod:foobar-function a b) ; = TCOD_foobar_function(a, b) `Predicate functions' are functions whose main job is to return a boolean value, true (non `nil`) or false (`nil`), that answers a question. These have a terminal '?' added to their name: :::cl (tcod:console-is-fullscreen?) ; TCOD_console_is_fullscreen() C enums have generally more succinct names. As they are lisp keywords, their names all begin with a colon `:`. THey are named according to the following pattern: :::cl :backspace ; TCODK_BACKSPACE (etc) :char-hline ; TCOD_CHAR_HLINE (etc) :colctrl-1 ; TCOD_COLCTRL_1 (etc) :set ; TCOD_BKGND_SET (etc) :font-layout-ascii-in-col ; TCOD_FONT_LAYOUT_ASCII_INCOL :fov-shadow ; FOV_SHADOW :key-pressed ; TCOD_KEY_PRESSED :center, :centre ; CENTER In general, most functions exist in both U.S. and non-U.S. spellings, This is mainly relevant to those functions with colour/color or centre/center in their names. ### Colournums In libtcod, colours are represented as structures containing three integer values: *red*, *green* and *blue* (each 0-255). The name of the structure type is `TCOD_color_t`. In `cl-tcod`, these colour structs are converted into 3-byte integers using the C functions `int_to_color(int)` and `color_to_int(TCOD_color_t)`, both defined in `wrappers.c`. The 3 bytes are red, green and blue in order (blue is 1's). ie: :::C struct TCOD_color_t {r, g, b} /* becomes #x00RRGGBB */ So, for example, one way to use the function `TCOD_color_multiply_scalar()` from lisp is: :::cl (tcod:color-multiply-scalar (tcod:compose-colour 218 165 32) 0.5) All C functions that take or return `TCOD_color_t` structs, are wrapped by lisp functions that take or return integers as described above. ### Colours by keyword A lisp keyword is any symbol beginning with a colon `:`. In lisp, keywords (like all symbols) are first-class values and can be passed around just like any other value. `cl-tcod` uses keywords to refer to particular colours, for example the keyword `:cyan` refers to the colour #x0056A3CD (or 5678029 in decimal notation). You can use keywords instead of colournums as arguments to lisp functions, by using the function `colour` to return the colournum associated with a keyword: :::cl (tcod:colour :cyan) ; returns 5678029 You can also define your own colour names, like so: :::cl (tcod:make-colour :my-goldenrod 218 165 32) (tcod:color-multiply-scalar (tcod:colour :my-goldenrod) 0.5) `cl-tcod` knows all the colour names defined in the "rgb.txt" file under Xwindows -- `:navajo-white`, `:honeydew`, `:mint-cream`, and so on. There is nothing special about the fact that rgb.txt comes from Xwindows -- the colours are just named R,G,B values and can be used anywhere that `cl-tcod` can be used. Look in the source file `tcod-colours.lisp` to see the available colour names. If you are using [[http://www.gnu.org/software/emacs/][GNU Emacs]], do `M-x list-colors-display` to see a list of all colours. ### Lisp `format` versus C `printf` The TCOD functions that accept `printf`-like string-formatting arguments, have been modified to instead accept arguments to Common Lisp's much more capable `format` function. For example: :::C TCOD_console_print (con, x, y, "Printing at %d, %dn", x, y); becomes: :::cl (tcod:console-print con x y "Printing at ~D, ~D~%" x y) ### Miscellaneous extra functions `console-print-double-frame` is like `console-print-frame`, but draws using `double-line' characters: :::cl (tcod:console-print-double-frame CONSOLE X Y W H EMPTY? STRING...) ### Coverage Does not provide wrappers for: * File parser. Using this from lisp would be a very cumbersome way to read values from a file, as the resulting values are not lisp objects. You would be better to either consider using the lisp `read` function, or looking into lisp libraries for parser generation. * `namegen-get-sets` -- I haven't yet implemented this as it will have to involve converting from libtcod's bespoke 'linked list' to a lisp list. You may be better to write your random name generator in lisp (fairly trivial). * `sys-get-directory-content`, `sys-file-exists`, `sys-is-directory`, `sys-delete-file`: Common Lisp already has functions that do the same thing.