If on the other hand SBCL had a more powerful type system or extension points for a pluggable type system...
You should be using the pairs when using make-hash, for example.
Cons also doesn't always return a pair. Its main purpose is for prepending to a list. Only when "the second argument is not empty and not itself produced by cons" does it produce a pair.
Which means '(a . b) is clearer code in intent, than (cons a b).
Deeply nested pair & list constructs that need to be unpacked with complex car/cdr combinations is what IMHO gets messy and I take the appearance of cddar & co in code as a sign that I should start thinking about using proper data structures.
That is a... Choice.
Breaking the pair operator in favour of something new.
Personally I have mostly sometimes used it with Emacs Lisp, but in general relying too much on plain cons cells and cadring down the cars of their cddars feels like a code smell to me and if I need a pair I can always just use cons? As the (only, I think?) infix operator in traditional lisps it has always felt extra-ordinarily useless to me (outside of Schemes use of it lambda lists), but maybe I'm just missing something.
((. sum numbers) (1 2 3))
But all that gives me a nagging feeling that maybe traditional Lisp macros don't really compose that well? So as a band-aid I had the idea to introduce special infix macros so one could for example do "(if (expr as: var) (something-something var))", or maybe "(something-something var where: var expr)" and so on. I'm not sure what the exact semantics should be though, especially with the as: form. It's probably just a result of doing too much Smalltalk lately, but out of all the "let's fix lisp's syntax" ideas I don't think I have seen exactly this one before, so that's something I guess. (As an alternative we could also of course just replace the lambda form with something less verbose so one could "(if expr [var | something-something var])" and then make the conditionals regular functions, or even generic ones specialized on booleans. Or maybe I'll just get back to hacking my init.el for now and try to cleanse my mind of these impure thoughts.)
The spaghetti code was astounding, and I remember squeezing line numbers between existing code-- adding a "31 GOTO 40" so I could squeeze a "room" into lines 32-39.
I never did grok the idea of building an "engine". Mostly I had PRINTs, INPUTs, and IF/GOTOs.
I spent too many nights trying to implement complex text adventures in Commodore 64 Basic and I'm sure that instead of permanently damaging me (at least in the sense that Dijkstra meant) it just made me appreciate more all the abstractions later languages introduced to me.
Taken further the assistant's role could be expanded with greater autonomy. Games could include metadata and authors hints & directives for the narrator. Or a limited interface for manipulating the game state and shifting the traditional IF model closer to a two player collaborative game. Using the LLM to transform and extend pre-authored text might actually offer new narrative possibilities, assuming the model could do it subtly and well enough, the style, POV, mood an so on of prewritten content could be freely modified in some interesting ways. E.g introduce unreliable narrators, describe the player's actions from a point of a security camera or their dog, rewind and replay events from some other characters POV. Simulate psychological issues by subtly rewriting the player's (or the narrator's or NPCs) perception of the world and have them navigate a little twisty maze of emotional states, all different.
Restricting the model into operating strictly within the limits of human authored content could bypass some of the usual problems associated with purely AI generated games and the approach seems fitting for the genre and it's pre-existing rich tooling and talent.
To me the homoiconity of Lisp is mainly about code-as-data, the exact nature of the data doesn't matter to me that much as long as it's a first class citizen and enclosed in nicely balanced parenthesis (though sadly here Janet seems to have fallen to the temptations of the curly braces, and thus, is indeed heresy).
[1] https://coalton-lang.github.io/
I just found it funny how Clojure's lack of cons pairs is enough to cause religious debates about its Lisp nature while (ISTR) adding symbols to Coalton basically requires foreign calls to the host system, but it still counts as a CL-with-types.