While my next steps with NicCLIM common lisp interface manager map editor are very exciting, I donāt want this-first-release to be vacant. Or, I would like to know if it is. So Iām committed to giving it the old college try here and now, while I should be preparing more for my interview of https://as.tufts.edu/physics/people/faculty/ken-olum tomorrow (0UTC Wednesday / 8pm Tuesday Boston time on https://anonradio.net/ live/ https://communitymedia.video/c/screwtape_channel/videos archive) instead.
Edit: (Worth listening to the archive about modern sbcl getting 60+ hours on the Tufts supercomputer https://communitymedia.video/w/9kysH4ZwVuP4J4erZozqFT .)
Iām going to start NicCLIM in a background thread (remember, McCLIM application-frame
commands are threadsafe), and drive it using eepitch
from this markdown file.
If something doesnāt work for you in this example, please howl at me on the mastodon or on https://lispy-gopher-show.itch.io/ .
EDIT: Note, on a sufficiently slow computer, sometimes McCLIM signals that it waited-too-long for a response. Just choose 0 (do nothing) and it will continue normally.
EDIT2: Since this demo includes setup, scroll halfway down to get to screenshots/pictures/commands of the action.
First, download nicclim.lisp
from https://lispy-gopher-show.itch.io/nicclim (Name your price ⨠ājust take me to the fileā) to ~/Downloads/nicclim.lisp
.
I wrote a broad spectrum minimal common lisp / emacs / eev guide here.
⢠(setq inferior-lisp-program "ecl")
⢠(slime)
⢠(setq eepitch-buffer-name "*slime-repl ECL*")
(for me, at least). Remember that with eev
we press F8
to send a line to eepitch-buffer-name
in emacs. If you arenāt in emacs+eev you would come up with something different.
Incidentally, it is called inferior-lisp-program
because the common lisp image is being controlled by (is inferior to) the emacs lisp major mode. Hence the joke-y names.
If you used https://www.quicklisp.org/beta/ to install McCLIM implementation of the Common Lisp Interface Manager spec,
(ql:quickload :mcclim)
or otherwise (asdf:load-system :mcclim)
.
We use it from inside of CLIM-USER
. -USER
packages are designed to absorb user code. We are users of CLIM
in this case: We are developers of our game maps. I am confident Jack Daniel would appreciate your contributions to developing McCLIM as well.
EDIT: Note that we end up using it (in-package :nicclim)
in a moment instead to avoid some namespace stuff.
(in-package :clim-user)
(make-pathname :directory '(:relative "~/Downloads"))
(make-pathname :name "nicclim" :type "lisp")
(merge-pathnames ** *)
Phew! I love and prefer lispās portably abstracted classic pathname stuff, but itās hard to remember! I checked the end of my article over here as an example. Back to it.
(compile-file * :load t)
(I use * ** *** to refer to recent results).
I use embeddable common lispās compile-file
-and-then-load extension. Conceivably,
(unless t
(compile-file *)
(load *)
) ; instead.
Well, finally we got setup.
Iāve been putting maps in ~/GAME/
.
(ensure-directories-exist #p"~/GAME/")
(uiop:chdir #p"~/GAME/")
(uiop:chdir #p"~/GAME/")
(with-open-file ; don't replace an existing file (error).
(*standard-output* "CURRENT"
:direction :output
:if-does-not-exist :create
:if-exists :error))
(ensure-directories-exist #p"MAP/")
(ensure-directories-exist #p"PIC/")
Iām going to be honest, I donāt know why I have to issue that posix uiop:chdir
twice.
The idea is maps would go in #p"~/GAME/MAP/"
and later pictures would go in #p"~/GAME/PIC/"
with the idea that we can just use the symbol map/room
for a room map and so forth.
mcclim
has already dragged in in bordeaux-threads.
(asdf:load-system :bordeaux-threads)
(in-package :nicclim)
(bt:make-thread
(lambda ()
(enclose-map "CURRENT")))
Iām not alleging that I should win an award for layout design, but I squeezed a bunch of useful shortcuts into this layout (see the layouts menu).
create rect
some kind of starting mapWhile we would use a mixture of hotkeys and clim completions in practice, since Iām writing this markdown document, Iām going to adopt the approach of explicitly typing (well, autocompleting) full clim command forms by hand, then running execute-frame-command
execute-frame-command) (which is the low level interaction).
'(com-create-rect map/grass-5x5 5 5 (GRASS))
(execute-frame-command *nic* *)
EDIT: Earlier, we went (in-package :nicclim)
to wholly circumscribe needing to type these so the below is deprecated.
well, thatās kind of annoying. Because I donāt export the command names since theyāre always used internally to the map editor, I have to pass them as internal symbols of the package, i.e. nic::com-create-rect
for com-create-rect
(and nic:com-create-rect
would be an exported symbol). I guess Nicholas Martyanoff prefers people namespace like this in general.
'(com-change-map map/grass-5x5)
(execute-frame-command *nic* *)
I added the special variable *nic*
to nicclim
expose the-current enclose-map
application-frame
.
'(com-create-rect map/desert-5x5 5 5 (sand))
(execute-frame-command *nic* *)
'(com-change-map map/desert-5x5)
(execute-frame-command *nic* *)
horizontal-cat
grass and desert'(com-horizontal-cat map/grass-5x5 map/desert-5x5 map/gd-5x5 0 nil)
(execute-frame-command *nic* *)
'(com-change-map map/gd-5x5)
(execute-frame-command *nic* *)
Note this would be done with keyboard accelerators (hotkeys).
'(jump 4 2)
(execute-frame-command *nic* *)
'(set-cur1 tree)
(execute-frame-command *nic* *)
'(push-cur1)
(execute-frame-command *nic* *)
'(com-j)
(execute-frame-command *nic* *)
'(push-cur1)
(execute-frame-command *nic* *)
'(vec-mov 2 1)
(execute-frame-command *nic* *)
'(push-cur1)
(execute-frame-command *nic* *)
Out of interest, the hotkey version of this was
C-M-i 4 2
C-M-u tree
C-M-o
M-S-j
C-M-o
C-S-i 2 1
C-M-o
Some apologies for my unmnemonic choices! If you have the hotkey screenshot in clear view somewhere, it is possible to operate very fast using these keyboard accelerators.
Save cool bits of larger tiles.
'(com-writef map/dg)
(execute-frame-command *nic* *)
'(com-extract-rect map/dg map/treesand 4 7 2 4)
(execute-frame-command *nic* *)
'(com-cat map/treesand)
(execute-frame-command *nic* *)
On the right side of the screen:
*NIC*> '(com-cat map/treesand)
(COM-CAT MAP/TREESAND)
*NIC*> (execute-frame-command *nic* *)
T
(GRASS NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND)
(GRASS NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND)
'(com-clobber-rect map/dg map/treesand map/dg2 3 0 2 2)
(execute-frame-command *nic* *)
'(com-change-map map/dg2)
(execute-frame-command *nic* *)
Whoops, it turns out x, y, width, height in com-clobber-rect
is right-exclusive whereas com-extract-rect
x, xlim, y, ylim is right-inclusive (I think?). However, we accidentally showed that the maps can be right-jagged, and critically that the slightly peculiar com-clobber-rect
can be used to delete and insert rectangles from and into a larger map, potentially resizing it. So I am leaving this slightly odd outcome in.
Firstly, there were lots of great insights ranging into small essays to my Mastodon toot asking about gamedevsā map-editor experiences which you should review at your leisure.
Viz this article, I think we saw NicCLIM can quickly perform large, medium, and VI-cursor scope changes while flicking between many āmapā ascii files. Oh, for reference, MAP/TREESAND
looks like this internally:
(GRASS NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND)
(GRASS NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND)
which is just normal lisp symbols/lists, annoying explicit namespace aside. The idea is that transparency-using pictures will optionally on top of each other stacked from left-to-right in a future version.
The fact that this markdown document is executable source code reinforces the macro programming addition planned in the next major version.
I would really like it if you managed to give it a try, as Larian is for his https://www.chroniclesofember.com/ (Larianās interview).
Talk on the Mastodon toot as always please.
(GRASS) (GRASS) (GRASS) (GRASS NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND)
(GRASS) (GRASS) (GRASS) (GRASS NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND)
(GRASS) (GRASS) (GRASS) (GRASS) (GRASS NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND)
(GRASS) (GRASS) (GRASS) (GRASS) (GRASS NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND)
(GRASS) (GRASS) (GRASS) (GRASS) (GRASS) (NICCLIM::SAND) (NICCLIM::SAND NICCLIM::TREE) (NICCLIM::SAND) (NICCLIM::SAND) (NICCLIM::SAND)
screwlisp proposes kittens