# How to make walls opaque in PuzzleScript

On the PuzzleScript home page, there is an example of an enemy (Eyeball) which, when you (Player) are directly in its line of sight, will move one square closer to you, using the rule

[ Eyeball | ... | Player ] -> [ > Eyeball | ... | Player ]


However, the Eyeball will walk towards Player even if it shouldn't be able to see you, for instance if there is a wall in the way. This is apparent in a level like

#########
#....O..#
#.......#
#########
#.......#
#..P....#
#########


where, if Player passes below Eyeball, Eyeball will move one square down.

How do I make it so that the enemy can't see me through walls?

Inserting no Wall into the rule above doesn't work, as that doesn't tell ... to only match wall-free tiles, but rather checks whether there is at least one non-wall tile between Eyeball and Player. And adding the rule

[ > Eyeball | ... | Wall | ... | Player ] -> [ Eyeball | ... | Wall | ... | Player ]


in an attempt to correct the movement doesn't work as two ellipses in a single match pattern isn't allowed.

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 Eyeballs, apart form some slight hiccups when Eyeballs compete for a square. That is to say, if you have two Eyeballs 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.