A little thing like an 'edit' button introduces cascading issues:
In this way I find myself playing meta-Sokoban.. ๐
Tl;dr - the 'edit' button isn't really usable yet.
I really don't want to go down the road of building a compare and merge flow ๐
More devlog stuff.
I switched the next/previous level buttons to say just >>
and <<
. This kills two birds with one stone:
(With my app user's hat on, I know in this case my changes are minor in a way that I don't with my app developer's hat on.)
Not having distinct hats sounds a lot like convivial technology.
Oh you and your idealism ๐
You can also think of it as compile time vs run-time. Convivial technology means I can go do unsafe things when I know what I'm doing, things I never want the computer to blindly do to me.
I think convivial technology implies that you are yourself responsible for judging the safety of whatever you do. Though that's not an aspect I remember Ivan Illich talk about.
Simple shortest-path routing to reduce some of the drudgery in Sokoban. Integrated with undo.
Next up: routing while pushing a single crate without moving any other crates. That feels more complicated than this glorified breadth-first search. In particular, I'm not yet sure how to detect cycles. Moving a crate can involve being in the same place over and over again. I think I need to hash the player's location in combination with the crate's location ๐ค
My solver can now push a single crate to a destination without moving any other crates. But I feel ambivalent about this. Devlog in ๐งต
๐ฅ sokoban-solver.webm
12th: I first play level 64 (pictured above), which is a really great puzzle -- but also the steps are killing on my fingers on a touchscreen without any tactile feedback.
Tapping an empty square to get the player to go there (pictured in previous thread) is just 20 lines of code! All I need is a breadth-first search (BFS). I am encouraged. However, it only gets me one way across those steps. On the way down I'm carrying a crate. Next step: move a single crate from a starting point to an ending point without disturbing any other crates.
a hazy idea starts to form:
assign each crate a unique id
add ability to select a crate and show some visual feedback when you do
do another BFS. Where the first time generates moves out of empty cells, here I want to generate moves out of either empty cells or the crate with the unique id I originally selected.
I do the first two steps, but the third is still unclear. Will I need to make a copy of the board on each iteration of the BFS? I didn't for the first BFS.
13th: I wake up and open up the program again, and immediately have a flash of insight: BFS #2 needs to use BFS #1 as a primitive operation. For each candidate move, for each direction, use BFS #1 to move the player to the opposite side of the target crate. If that succeeds, add the direction to the BFS.
I'm operating in "plan space". The move to the opposite direction is just a plan, it doesn't mutate the board. Since a single crate moves throughout the BFS, I figure I don't need to copy the entire board each iteration. I can just track the position of that crate as a delta on the original position.
This plan doesn't need the unique crate ids anymore, but I haven't noticed that yet. They'll still come in handy in debugging, but I think the ensuing tale might have gone easier if I'd never added them.
Bugs as I encountered them:
and
s and or
s into a helper function with early returns, and the sun shines again.By the end this is nowhere near as elegant as my original insight. BFS #2 isn't quite a BFS because the queue is a priority queue, and it's not using BFS #1 unmodified. All in all, the solver for moving a crate takes 200+ lines of code. Might not actually be a worthwhile trade-off. Might make the puzzles too easy. Also, I notice now that level 64 requires moving multiple crates on the way down, so this isn't really improving my life very much at least in this level. We'll see..
"Might make the puzzles too easy" โ that's something you can lean into. Zach Gage is a fantastic game designer. One way he works is by taking a classic game (like, say, Sudoku) and building a new interface for the game that makes people "better" at it by reducing inessential complexity. In his game Good Sudoku, the interface helps you avoid making mistakes and quickly test out theories and skip over tedious bits, but it doesn't do anything to ~solve~ the puzzle for you. This improved interface means that you can then play more challenging puzzles, which are more satisfying.