I've come across a solution which works. It basically uses a phantom block to raycast from Player
to any Eyeball
in line with the Player
, and if that block hits an Eyeball
before it hits a Wall
, it will make the Eyeball
move toward the Player
:
[Player | Eyeball] -> [Player | < Eyeball]
[Player | no Wall |... | EyeBall] -> [ Player | > Gaze | ... | Eyeball]
[> Gaze | no Wall | ... | Eyeball ] -> [ | > Gaze | ... | Eyeball ]
+ [> Gaze | Eyeball ] -> [ | < Eyeball > Gaze]
[ Gaze ] -> []
This works fine even for multiple Eyeball
s, apart form some slight hiccups when Eyeballs compete for a square (which Eyeball
wins is probably decided by the internals of the engine at resolution of movement, and would be tricky to solve using rules because doing so would either require to match patterns that are not along a single line, or to move the Eyeball
s manually using absolute directions).
That is to say, if you have two Eyeball
s both touching the Player
, and the Player
moves out of the way, only one Eyeball
will move to fill in the spot left by the Player
, and which one that turns out to be is decided by the engine when the movement occurs.
(This competition would probably be tricky to solve using rules because doing so would require to match patterns that are not along a single line.)
If there is only one Eyeball
, then the first two rules may be put together and simplified to
[Player | ... | EyeBall] -> [ Player > Gaze | ... | Eyeball]
This runs into issues with more than one Eyeball
because several Gaze
blocks cannot coexist in the same cell, meaning only one Gaze
block ever gets made. One could also mend this by putting again
after each rule, but that would make moves not happen instantaneously so it's not optimal.