---
layout: ../Site.layout.js
---
# INSTRUCTIONS FOR LISP GAME JAM SUBMISSION `unix-surrealism-jam.lisp`
Instructions for playing my two example levels I made after making `unix-surrealism-jam.lisp` for this jam on top of my existing `nicclim.lisp`, and then instructions for making your own new levels for `unix-surrealism-jam.lisp`, which is also an intended player activity. I am happy to help with anything and debug anything.
- [nicclim.lisp](../nicclim.lisp)
- [unix-surrealism-jam.lisp](../unix-surrealism-jam.lisp)
- [GAME.TAR](../GAME.TAR)
Video of me copying and pasting code from this article into lisp:
<img src="../game-working.gif">
> ASIDE: Tiny note about debugging. "Return to command loop" has never not been the right thing for me to do. On old hardware McCLIM occasionally gets confused about an event not resolving super promptly, but it is not a big deal. Further note, Changing to the map-view layout is a better map experience. Last piece of debugging advice: `jump 2 3` in the interactor unconditionally teleports you to x=2 y=3.
## Download
## untar `GAME.TAR` in `~/`
```
cd ~/
tar xvfk ~/Downloads/GAME.TAR
```
## Start lisp and [`quickload`](https://beta.quicklisp.org/) [McCLIM](https://codeberg.org/McCLIM/McCLIM)
### shell (alternative 1)
```
ecl
```
#### Now in lisp:
```
(ql:quickload :McCLIM)
```
### Emacs (lisp) / [slime](https://slime.common-lisp.dev/doc/html/) (alternative 2)
#### Emacs lisp:
```
(setq inferior-lisp-program "ecl")
(slime)
```
#### In `*slime-repl ECL*`:
```
(ql:quickload :McCLIM)
```
## Compile and load `~/Downloads/nicclim.lisp` and `~/Downloads/unix-surrealism-jam.lisp`
```
(compile-file "~/Downloads/nicclim.lisp")
(load "~/Downloads/nicclim.fas")
(in-package :nic)
(compile-file "~/Downloads/unix-surrealism-jam.lisp")
(load "~/Downloads/unix-surrealism-jam.fas")
(uiop:chdir "~/GAME")
(uiop:chdir "~/GAME") ; not a typo
```
# Load all your levels, in order
(This way, you can freeform extend the game and swap new levels without my intercession, though I am very happy to include your levels- but I will not be able to during voting week).
```
(load "LEVELS/LEVEL-1-STRANDED.LISP")
(load "LEVELS/LEVEL-2-WALL-RADIO.LISP")
```
# Start the game
```
(enclose-map 'TECHNO-MAGE/STRANDED.MAP)
```
# THE CONTROLS ARE
- up = ↑ -key
- the-other-up = control-↑ -key
- down = ↓ -key
- the-other-down = control-↓ -key
- left = ← -key
- right = → -key
- button-1 "do cursor cur1" = M-- = (#\- :meta) = alt-dash
- button-2 "swap cur1 cur2" = C-- = (#\- :control) = control-dash
- button-3 "type in cur1" = C-M-- = (#\- :control :meta) = alt-control-dash
The radio selection events set your `cur2` alternate cursor to your choice's association. So to then *action* your radio event choice you must press *button-2* (control-dash) which moves the radio choice to the main cursor, `cur1`, then press *button-1* as above to *do-*`cur1`.
# ADDING A LEVEL
A level consists of a file with a bunch of s-expressions in it like
- `~/GAME/TECHNO-MAGE/STRANDED.MAP` or
- `~/GAME/WALL-RADIO.MAP`
along with a settings-setting lisp file like
- `~/GAME/LEVELS/LEVEL-1-STRANDED.LISP` and
- `~/GAME/LEVELS/LEVEL-2-WALL-RADIO.LISP`
respectively.
These files should all `(in-package :nic)` indicating NicCLIM is being used, then
1. Overwrite a `:radio-choices` property from a previous level to be outcome `((com-change-map my/own.map))` (for `~/GAME/MY/OWN.MAP` sexp file).
1. `push` any impassable symbols to `*impassable*` (or conceivably `delete` some from `*impassable*`
1. Set new `:bitmap`s used in your `MY/OWN.MAP`, otherwise they will appear as previous levels or text. `(setf (get 'wall :bitmap) 'techno-mage/tree-2.png)` will make `WALL` symbols in `~/GAME/MY/OWN.MAP` render as `~/GAME/TECHNO-MAGE/TREE-2.PNG`
1. Set up radio choice symbols used in your map. A radio choice is a symbol that has a `:radio-choices` property, which is triggered when a game movement command walks onto it. It also has a `:radio-descriptions` list of texts, newlines etc or `:bitmap`ped symbols which will inline images. E.g.
```
(setf (get 'ruins :radio-choices)
'(member
("Enter the ruins"
((com-change-map REPLACE-WITH-YOUR-LEVEL))))
(get 'ruins :radio-description)
'("The loop terminates as the troupe come across some ruins. " NIL)
(get 'ruins :radio-lisp-hook)
())
```
# Two full examples
Creating and linking together to your own new maps and freely changing others' maps is a key `unix-surrealism-jam.lisp` activity created in and for this jam.
## STRANDED
### `~/GAME/TECHNO-MAGE/STRANDED.MAP`
```
(SKY) (SKY) (SKY SUN) (SKY) (SKY)
(HORIZON SCRUB) (HORIZON TREE) (HORIZON PUFFY) (HORIZON RUINS) (HORIZON SCRUB)
(GROUND SCRUB) (GROUND OPENBLADE) (GROUND MAGE) (GROUND PENGUIN) (GROUND
SCRUB)
(GROUND SCRUB) (GROUND SODA) (GROUND BAG) (GROUND OLD-MONITOR) (GROUND
SCRUB)
(GROUND SCRUB) (GROUND SCRUB) (GROUND SCRUB) (GROUND SCRUB) (GROUND SCRUB)
```
### `~/GAME/LEVELS/LEVEL-1-STRANDED.LISP`
```
;;;; ~/GAME/LEVELS/LEVEL-1-STRANDED.LISP goes with ~/GAME/TECHNO-MAGE/STRANDED.MAP
(in-package :nic)
;; Impassable:
(push 'sky *impassable*)
(push 'scrub *impassable*)
;; images used here:
;;; backgrounds
(setf (get 'ground :bitmap) 'techno-mage/imgs/dune.png)
(setf (get 'sky :bitmap) 'techno-mage/imgs/desert-sky.png)
(setf (get 'horizon :bitmap) 'techno-mage/imgs/desert-horizon.png)
;;; foregrounds
(setf (get 'sun :bitmap) 'techno-mage/imgs/sun.png)
(setf (get 'mage :bitmap) 'techno-mage/imgs/techno-mage-sit.png)
(setf (get 'tree :bitmap) 'techno-mage/imgs/tree.png)
(setf (get 'scrub :bitmap) 'techno-mage/imgs/desert-scrub.png)
(setf
(get 'bag :bitmap) 'techno-mage/imgs/bag.png
(get 'puffy :bitmap) 'techno-mage/imgs/puffy.png
(get 'soda :bitmap) 'techno-mage/imgs/soda-can.png
(get 'ruins :bitmap) 'techno-mage/imgs/desert-ruins.png
(get 'penguin :bitmap) 'techno-mage/imgs/penguin.png
(get 'openblade :bitmap) 'techno-mage/imgs/openblade.png
(get 'old-monitor :bitmap) 'techno-mage/imgs/pentium-head.png
)
;;; radio
(setf (get 'str2 :bitmap) 'techno-mage/imgs/str2.png)
;;; events
(setf (get 'PUFFY :radio-choices)
'(member ("Heed the fish" ((com-game-l))))
(get 'puffy :radio-description)
'("mage: I feel like we've been going in circles"
#\newline
str2
"puffy: It's called a LOOP"
#\newline)
(get 'puffy :radio-lisp-hook)
())
(setf (get 'ruins :radio-choices)
'(member
("Enter the ruins"
((com-change-map REPLACE-WITH-YOUR-LEVEL))))
(get 'ruins :radio-description)
'("The loop terminates as the troupe come across some ruins. " NIL)
(get 'ruins :radio-lisp-hook)
())
```
## `WALL-RADIO`
### `~/GAME/WALL-RADIO.MAP`
```
(WALL) (WALL) (WALL) (WALL) (WALL) (WALL) (WALL)
(WALL) NIL NIL NIL NIL NIL (WALL)
(WALL) NIL NIL NIL NIL NIL (WALL)
(WALL) NIL NIL (EXAMPLE) NIL NIL (WALL)
(WALL) NIL NIL NIL NIL NIL (WALL)
(WALL) (ROCKRADIO) (ROCK) NIL NIL NIL (WALL)
(WALL) (WALL) (WALL) (WALL) (WALL) (WALL) (WALL)
```
### `~/GAME/LEVELS/LEVEL-2-WALL-RADIO.LISP`
```
;;;; ~/GAME/LEVELS/LEVEL-2-WALL-RADIO.LISP goes with ~/GAME/WALL-RADIO.MAP
(in-package :nic)
;;; Redirect some previous level radio choice towards this map
#|last form in LEVEL-1-STRANDED.LISP:
(setf (get 'ruins :radio-choices)
'(member
("Enter the ruins"
((com-change-map REPLACE-WITH-YOUR-LEVEL))))
(get 'ruins :radio-description)
'("The loop terminates as the troupe come across some ruins. " NIL)
(get 'ruins :radio-lisp-hook)
())
|#
(setf (get 'ruins :radio-choices)
'(member
("Enter the ruins"
((com-change-map wall-radio.map))))
(get 'ruins :radio-description)
'("The loop terminates as the troupe come across some ruins. " NIL)
(get 'ruins :radio-lisp-hook)
())
;;; Impassable:
(push 'wall *impassable*)
;;; Images used here:
(setf (get 'grass :bitmap)
'techno-mage/imgs/grass.png
(get 'solid :bitmap)
'techno-mage/imgs/solid.png
(get 'example :bitmap)
'techno-mage/imgs/lambda.png
(get 'rock :bitmap) 'techno-mage/imgs/rock.png
(get 'wall :bitmap) 'techno-mage/imgs/tree-2.png
)
;; radio events:
(setf (get 'example :radio-description)
'("Lots of
text!"
asdf grass solid
(1 2 (3 4) 5))
(get 'example :radio-lisp-hook)
(list (lambda () 'nothing)
(lambda () 'nothing-else))
(get 'example :radio-choices)
'(member
("choice the first" ((com-set-cur1 rock)))
("choice the second" ((com-jump 1 1))
("choice the third" (COM-CHANGE-MAP REPLACE-WITH-YOUR-NEXT-MAP)))))
;; another radio event
(setf (get 'rockradio :radio-description)
'("Some rocks:"
rock rock
#\newline rock "rocks." grass)
(get 'rockradio :radio-choices)
'(member
("good old rock" ((com-game-k)))
("nothing beats rock" ((COM-CHANGE-MAP your-other-map)))))
```
# Conclusions
I am going to leave the conclusions for my post-submission post-mortem. The goal of my NicCLIM was to recapture something like the Warcraft 3 map editor, but in lisp; the goal of my `unix-surrealism-jam.lisp` is to have one player-extensible "custom map".
# Fin.
See you on [the Mastodon thread](https:/gamerplus.org/@screwlisp) stroke [the jam submission page](https://itch.io/jam/autumn-lisp-game-jam-2025/rate/3822491).