In hindsight, there was a succinct description of these three NicCLIM alpha intro parts. (1) Making a map, (2) put host lisp lambdas in the map and finally (3) map edit macros. (This one).
I guess the map edit macros are the most important because they bridge the map and host lisp. So the map has secret alien technology, and the secret alien technology is given physical form to run rampant in.
If you will allow a diversion, I read the first five-ish books of Dungeon Crawler Carl recently. This genre of scifi has a confusing feature for me in contrast to Stephensonâs Snow Crash and Gibsonâs Neuromancer. In Snow Crashâs The Metaverse and Neuromancerâs The Matrix, you could reasonably construe either of those as a science fantasy realm the characters sometimes magically teleport to. However, they are both overtly useful- basically wedding physical intuition and computer usability.
In contrast, Dungeon Crawler Carlâs The Crawl is a sort of post-world-of-warcraft concept of virtual reality, where the player has magic and enhanced stats with all the literal meaning of Lorem Ipsum. Dungeon Crawler Carl does present this meaninglessness of The Crawlâs magic when the characterâs body is briefly outside The Crawl, and the character has to physically adjust to not experiencing the super-strength they have inside the game (The Crawl).
Dungeon Crawler Carl does make a move in the Matrix and Metaverse direction by introducing Enhancement Zones, real places where The Crawlâs game master AI is able to give players outside The Crawl limited access to their magic and enhanced stats from inside the game in the physical world.
This is different to The Metaverse and The Matrix, in that The Crawlâs magic is a game feature, whereas in the former two it is an abstraction over real computer programs being used.
In NicCLIM, my intent is that the magic as such of fantasy maps, here including Conwayâs game of life in my definition of fantasy, is host common lisp lambda forms literally in the map, and (lisp) wizardry is the NicCLIM map editorâs macro system for directly performing and scripting map actions involving those lambdas. Sufficiently advanced magic is secret alien technology, to invert a phrase.
After the NicCLIM alpha parts I and II, we have a game map (actually a normal lisp s-expression file), where symbols can be represented as layered graphics or text in a hextille grid. Structurally, it serendipitously made sense to consider the actual game map as being the second quadrant of the map and to store the lambdas in the fourth quadrant. Perhaps auxiliary data could be stored in the first and third quadrants, though this is future speculation.
I guess you saw parts I and II.
(enclose-map 'gol)
EDIT: I decided to just show picking up a lambda using eval
and apply
ing it (actually funcall
in this case) in the interest of concission. I will add a note about the player application database storage. Then the completed Conwayâs game of life game we are moving towards will be separate to this intro part 3, which is already pretty long.
My idea is to use the host lisp lambdas we made in part ii to run a hextille game of life in the left half of the 10x8 game map we originally made.
We will effect these by writing a sequence of NicCLIM actions in several stages
This will perform one game of life update. The hextille game of life rule we wrote was H:B2S34 which I got from Wikipedia.
I am writing this here, now, for the first time, as I think of it for the purpose of this documentation. If you construe more powerful useage idioms for NicCLIM as such, please announce them to me in the Mastodon thread (I will formally name them after you in NicCLIM).
Hmm, it looks like I was subconsciously making an emacs pun. Memacs.
I noticed that I wrote a lot of exposition in the next section, so let us just do the first bit first and talk about it after.
jump
eval
set cur1 eval
funcall
It puts the result in cursor 2.
jump
swap
funcall
Jump to the location, put the lambda in cursor 1, funcall
the lambda (it gets the current cell as an arguement).
If you do not like playing spot-the-difference, the lambda in cursor 1 replaced cursor 2, which had been the symbol EVAL
, with 1
, since this cell (with the @
in it) contained LIFE
per the lambda form we picked up.
eval
Since the lambdas exist as s-expressions, to pick up âour copyâ of one, we eval
the s-expression. This is not a discouraged useage of eval, since we really are saying âSet cursor 2 to be the evaluation of this data s-expressionâ, which is oddly reminiscent of the roguelike take action. We could alternately pick up the data as data. It is possible to be a bit tricky with what lisp thinks about unevaluated lambda forms, but in practice here I suggest just thinking of the unevaluated form as data and the eval
âed form as being the one suitable for apply
ing or funcall
ing. The material difference between apply
and funcall
is essentially that apply takes a list of arguements to the lambda, whereas funcall
takes the arguement as an arguement. Both are available because this difference turns out to be quite useful.
After evaluating it, the object we now have in our cursor is unreadable, and could be a closure (i.e. a lambda with enclosed state) as implied by some of the lambdas we wrote in part ii. Closures are very useful.
NB: If you are new to lisp, we can get a lambda expression and readable states out of an unreadable lambda or closure by using function-lambda-expression
when we want data again instead.
Since I already talked a lot, and this is meant to be an initial exploration, I am going to cease doing new stuff here except the following quick note on ephemeral application database storage.
I introduced the idea of an active player (the player is actually the mapâs⊠cartographer in this case). Remember that nothing but the map is stored in the map, so this storage is not persisted.
(enclose-map 'gol)
Basically
Change Player screwlisp
set cur1 foo
swap
set cur1 bar
setsgets
this saves FOO
âźBAR
for SCREWLISP
.
Gets
This replaced FOO in cursor 1 with screwlispâs saved value for FOO, which is BAR.
In part 3, we minimally saw picking up a lambda form, possibly a closure, for useage using eval
. (Actually, a map editor command named com-eval) in practice, where we jumped to a live cell in the nascent game-of-life, and funcall
ed the lambda to see that this live cell would count for 1
(in the neighbors count). Cursor 1 gets applied/funcalled to the current cell, denoted with an @. The result gets placed in cursor 2.
Then we saw that a âcurrent playerâ can ephemerally store values using setsgets, and retrieve stored values (per player) using gets. These values are not part of the map, so they are stored in the current lisp imageâs memory, similar to how the unreadable compiled lambda in the cursor will not be stored as part of the map.
Hence we can
The complete game of life example, which will basically be repeating and composing these activities I have separated out from this three part alpha announcement.
The only feature not pictured that is actually included and ~ finished in the alpha sense is the spacetime boxes, which are a way of syncronising distributed maps advancing through time loosely based on Ken Olumâs c. 2025 ANSI CL supercomputing at Tuft astrophysics. 4D spacetime volume propagation as multiplayer syncronisation is a slightly heavy topic that I am still exploring idioms for.