If you haven't played the game Baba is You, I think you really should. Whether you’ve played it or not, have a go at implementing it as a code golf.
The idea behind this challenge is to have a bit more complicated, non-standard task with a bit longer answers.
Game rules
Alas, the challenge is not to implement the entire game, impressive though that may be (I'm sure there is a single 05ab1e instruction for it. If not, someone should submit an issue. It's a gross omission from the language 😉). This will be a simplified version of the game:
- There are only 3 entities:
Baba
,Rock
andFlag
and the corresponding nouns (lowercasebaba
,rock
andflag
) - There is only one operator -
is
- There are only 3 properties:
you
,win
andpush
- Everything is always
stop
(N.b.stop
is not a property which exists on the board) This prevents anything from overlapping and makes the management of the game grid simpler. - Because everything is always
stop
, there is an alternate win condition. You can win if:noun is you
andnoun is win
-- just like in the originalnoun
which isyou
attempts to push something which iswin
, but that something cannot move (whether because it's notpush
, or it ispush
and is somehow blocked form moving). See examples for more details.
- Just like in the main game text (nouns
you
,win
andpush
and the operatoris
) are alwayspush
- There is only one level. This one:
. . . . . . . . . . . . .
. r i p . . . . R R R . .
. . . . . . . R . . . R .
. b i y . B . R . F . R .
. . . . . . . R . . . R .
. f i n . . . . R R R . .
. . . . . . . . . . . . .
where uppercase letter correspond to entities and lowercase to their respective nouns. .
is empty, p
is push
, y
is you
and n
is win
(originally I've implemented walls, and there was a namesake crash so I've made win n
instead).
- The grid is parsed for rules just like in the original game. There are two types of rules:
noun is property
, for examplebaba is you
orflag is push
. These type of rules are referred to as behaviours.noun is noun
, for examplebaba is rock
. These type of rules are referred to as swaps. Since this grid does not have two of any of the nouns, one does not have to worry about the case likerock is rock
(which would, otherwise, affect the execution of other rules)
- The rules work only from left to right, and from top to bottom.
- The only allowed moves are up, down, left and right. No idle, no undo.
- When a move is made, every entity which is
you
attempts to move in the direction specified. - The order of actions in a single step is as follows:
- Search the grid for all the current rules
- Parse the rules into behaviours and swaps
- Apply all the swaps to the grid in an alphabetical order (Only one swap per cell)
- Perform an action for the turn according to the behaviours
Here is an example game where the rule rock is push
has been changed into rock is win
.
Golfing challenge rules
Your task is to implement the above game of Baba is You, using the smallest number of source code bytes (the usual). Your program will take a sequence of moves as an input, and output 1
, or True
, or otherwise something meaningful if this sequence of moves leads to a victory on the above grid (and only on this grid. Just hardcode it in). Otherwise, the program will output 0
, or False
or nothing.
You can assume that every sequence of moves is a valid sequence in any format. I've used symbols ^V<>^
for example, but you're most welcome to assume it's udlr
instead.
You can assume any input sequence either ends on a win, or does not lead to one. This means you do not have to worry about there being any more moves past the winning one. If such sequence is passed to your program, it's an undefined behaviour and your program can do anything.
I've implemented this version of the game in python. You can find it here. Some of the more tricky behaviour is specified in the readme (If you find any weird edge cases I haven't thought of let me know or send me a PR). There is a minimal self-contained version of the code in /golf/golfing_full.py
and the abbreviated version in /golf/golfing_short.py
. The sum total comes to 1930 bytes (sans the test at the end).
Test cases
- Fastest win
1: >>^>>V
- Fastest loss (you don't actually have to check for loss explicitly)
0: <^<V
- Baba is win
1: <VV<V<<^V>>^<
- Rock is baba
1: <^^^<<V>V<>>
- Rock is you
1: <^^^<<V^<<VV>><<^>><<
- Rock is win
1: <VVV<^<^>V>^^V<<<<^^^>^>>>>VVV<^>>>
- Rock is win but also push
1: <^<<<<V>>>V>VV<<^^^>^<VV>>V<V<^^>^<V>>>>>>>V<^^^^>^<<<<<<<<<
- Baba is flag
0: <V<<<<V>>V>^^>>^^>>^>>V
- Baba is you is win
0: <V<<<<V>>V>>^^VV>^^
- Flag is rock is win
1: <V<<V^<V>>>^^<^>^^<<V^<<VV>>>^>VVVV^^^<<<<^>>^>VVVV>>V^<<V>>^^>>
- Flag is rock is win, but win on what used to be the flag
1: >VV>^^<^>V>^VV<<<<<<<V^>V>>^>V^^<<^>^^<<V^<<VV>>>^>VVVV^^^<<<<^>>^>VVVVV^^>>>>>>
- Rules don't work upside down
0: <V<<<<V>>V>>>^V<<<^>V>>^V<<^>V>>^^^>>^>>V
- Rules don't work backwards
0: <V<<<<V>>V>>>^V<<<^>V>>^V<<^>><^^^>V>V<^<V<VV>>>>^<<<>^^>>^>>V
- Rules (swaps) are applied alphabetically
1: <^<<<<V>>^<<^^>>V^<<VV>>^><V><V><<<VVV>^^<^>>V>^^<^>VVV>VV<<^^^<^>V>^<^>><<V<<^>>>>>V<^<VV<<
- Rules (swaps) are applied alphabetically, case 2
1: <^<<<<V>>^<<^^>>VV<V>V>>VV<<^V<<^>^^^<^>^>VV>V<V<V>^^>V>V>>>^^<<
- Rock is baba is flag
0: <^^^<<V^<<V><VVVVV>>^V<<^>^<^><
- Rock is baba is flag, case 2
0: <^^^<<V^<<V>>>><<<V>>><<<<VVVV>>^V<<<^^>>>><<<<V>>>><<<<^^>>>><
- Walk into the corner for a while and make a circle around the board
1: VVVV>>>>>>>>^^^^^^^>^^>^>^<<<<<<<<<<<<<VVVVVVV^^>>>>>>>>^>
- Win at the last moment
1: >>V>V<<<V<<<^V<<^><^^^^^>>V^<<V><VV><
you
under current rules". But then, ifRock is you
- do all the rocks move? What if some of them are blocked? What constitutes a block? It's very much preferable to walk through several such cases in the task rather than just point to examples. \$\endgroup\$stop
, and is it really relevant in your version of the game? For me, the winning conditions - (1) an entity isyou
andwin
simultaneously, and (2) ayou
entity bumps into a non-pushablewin
entity - look fully self-contained without the need to introducestop
, or maybe am I missing something? \$\endgroup\$>>V>V<<<V<<<^V<<^><^^^^^>>V^<<V><VV><
(assuming I didn't make a mistake) \$\endgroup\$