Paul Sexton avatar Paul Sexton committed 92719c2

console-init-root: Made title, fullscreen and renderer arguments optional.
The renderer defaults to GLSL (the fastest).

Added a README in Markdown format.

Comments (0)

Files changed (3)

+# 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
+    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.
+## License
+The `cl-tcod` package is placed in the Public Domain by its author.
+## Dependencies
+`cl-tcod` depends on the following libraries:
+* `ASDF`:
+* `defstar`:
+* `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
+    :::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
+### 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
+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 [[][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);
+    :::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.
 (in-package #:tcod-system)
 (defsystem tcod
-    :description "CFFI for libtcod, a truecolour console library."
-    :author ""
+    :description "Common Lisp bindings for libtcod, a truecolour
+terminal-emulation library written in C."
+    :author "Paul Sexton <>"
     ((:file "tcod") (:file "tcod-colours"))
     :depends-on ("cffi" "defstar"))
    is a function containing the code below.
 ;;;   (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-init-root 80 25 :title \"Test\")
 ;;;   (tcod:console-clear tcod:*root*)
 ;;;   (tcod:console-print tcod:*root* 1 1 \"Hello, world!~%\")
 ;;;   (tcod:console-wait-for-keypress t)
 ;;TCODLIB_API void TCOD_console_init_root(int w, int h, const char * title,
 ;;                                        bool fullscreen);
-(define-c-function ("TCOD_console_init_root" console-init-root) :void
-    ((width :int) (height :int) (title :string) (fullscreen? :boolean)
-     (renderer renderer))
+(defcfun ("TCOD_console_init_root" %console-init-root) :void
+  (width :int) (height :int) (title :string) (fullscreen? :boolean)
+  (renderer renderer))
+(defun* console-init-root ((width uint) (height uint)
+                           &key (title "libtcod")
+                                 (fullscreen? nil)
+                                 (renderer :RENDERER-GLSL))
   (check-type width ucoord)
   (check-type height ucoord)
   (setf (gethash *root* *console-width-table*) width)
   (setf (gethash *root* *console-height-table*) height)
-  (call-it))
-;;TCODLIB_API void TCOD_console_set_custom_font(const char *fontFile,
-;;                        int char_width, int char_height, int nb_char_horiz,
-;;                        int nb_char_vertic, bool chars_by_row,
-;;                        TCOD_color_t key_color);
+  (%console-init-root width height title fullscreen? renderer))
+;;TCODLIB_API void TCOD_console_set_custom_font(const char *fontFile, int
+;;                        char_width, int char_height, int nb_char_horiz, int
+;;                        nb_char_vertic, bool chars_by_row, TCOD_color_t
+;;                        key_color);
 (define-c-function ("TCOD_console_set_custom_font" console-set-custom-font)
     ((fontfile :string) (flags custom-font-flags)
 (defun hello-world ()
-  (tcod:console-init-root 80 50 "Libtcod Hello World" nil :renderer-sdl)
+  (tcod:console-init-root 80 50 :title "Libtcod Hello World")
   (tcod:console-set-alignment *root* :center)
   (tcod:console-print tcod:*root* 40 25 "Hello World!")
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.