Cirkoban: Sokoban meets cellular automata written in Scheme
spritely.institute
spritely.institute
I ran into the System Crafter's Spring Lisp Game Jam livestream (https://www.youtube.com/live/n-4kZhvkK4M?si=YPCSElylTLeSDcCN) and I'm rather impressed with Hoot, the Scheme -> WASM compiler. Still an early release, but it seemed stable and reasonably featuriferous.
On a different note, I also ran across WASM compiles of z3 and minizinc recently. (File under "It's Not How Well The Elephant Dances, But That It Dances At All," I guess.)
I assume it would be horrible, though. :-)
- The game crashed during load on Chrome on Android.
- The undo feels really slow. Is is intentional for some kind for artistic effect, or is it related to the tech stack? It feels like a full second, with a really distracting screen fade effect. From the article it seems that the rollback support is one of your core features, but an instant undo is table stakes for this kind of puzzle game. It's not something you should be showcasing by making it slow and have graphical effects.
- Games like this should have a restart level button, not just undo. That'd be the case even if the undo was faster.
- I think the genre convention is that invalid moves don't advance time, but there's a "wait" input. Having to run at walls to get the timing parity right feels just wrong.
- Curious, this sounds like local machine slowness. Undo is basically instantaneous under the hood, and there's a quarter-second screen wipe effect for fun, but you can mash "undo" as much as you want and it interrupts the animation so you don't have to wait. On my laptop and Android phone I feel no slow down nor have I heard of this from anyone else who played the game.
- Fair point. On a keyboard you can just hold the Z key and it zips back pretty quick. Less fun on mobile since I didn't implement repeat on the touch controls.
- That may be a convention but it was a deliberate choice not to implement it. I was inspired by Void Stranger which does not have an idle. At least in the levels I designed, I tuned the timing so if you do the optimal solution there's no time spent walking into walls.
Thanks for the feedback!
Holding Z down to roll back everything is near instant, so I think it's purely a presentation thing then. Both the screen wipe and the sound effect are very obtrusive. I spot-checked a random puzzle game (Monster's Expedition) with higher than average production values for the genre, and the undo is instant with no transitions or animations, and a sound effect so subtle it took me a while to realize it was even there.
In our case the choice to have undo be very visible, well it may be a bit overdone, but I think it's partly because in some ways this is a showcase of Goblins' time travel feature, and so we wanted to add some juice to the effect to highlight it. It would definitely be better if we had a "level reset" feature, which would make us comparable to Baba is You: holding undo takes a bit if you did a lot of things, but you can also just start over.
The other thing I really wished we had added was a level select menu but... all this stuff was accomplished in a week and two days; game jams are intense, there's always things you wish you had gotten done. Now that the jam is over, it might be worth adding some quality of life improvements, but of course now that the jam is over we are back to working on the core tech again instead of the demo. :)
But also, hi jsnell, nice to see you again! Glad you got to play the game, and hope you had fun. :)
Source is `e.querySelectorAll("\\\f"),` in function of file `lib.min.js`:
(d.qsa = K.test(C.querySelectorAll)) && (ce(function(e) {
var t;
a.appendChild(e).innerHTML = "<a id='" + S + "'></a><select id='" + S + "-\r\\' msallowcapture=''><option selected=''></option></select>",
e.querySelectorAll("[msallowcapture^='']").length && v.push("[*^$]=" + M + "*(?:''|\"\")"),
e.querySelectorAll("[selected]").length || v.push("\\[" + M + "*(?:value|" + R + ")"),
e.querySelectorAll("[id~=" + S + "-]").length || v.push("~="),
(t = C.createElement("input")).setAttribute("name", ""),
e.appendChild(t),
e.querySelectorAll("[name='']").length || v.push("\\[" + M + "*name" + M + "*=" + M + "*(?:''|\"\")"),
e.querySelectorAll(":checked").length || v.push(":checked"),
e.querySelectorAll("a#" + S + "+*").length || v.push(".#.+[+~]"),
e.querySelectorAll("\\\f"),
v.push("[\\r\\n\\f]")
}),
where `e` is the following: <fieldset><a id="sizzle1717482165204"></a><select id="sizzle1717482165204-
\" msallowcapture=""><option selected=""></option></select><input name=""></fieldset>
Yes, there is a newline (actually a CR) after `id="sizzle1717482165204-`Chrome Version 125.0.6422.141 (arm64)
I love it.