ClementSparrow / Pattern-Script

Open Source HTML5 Game Engine based on PuzzleScript
19 stars 2 forks source link

Mappings from tag classes that include `directions` always map from the rule's direction #52

Open ClementSparrow opened 2 years ago

ClementSparrow commented 2 years ago

In the following code, Pos is a tag class adding top and bottom to directions and there is a mapping RotUp from Pos to Pos. However, in the first rule, even if Pos is a tag class rule parameter and the rule is non-directional, the mapping RotUp is applied on the rule direction rather than on the value of the parameter Pos as it should.

Pos = top bottom left right up down

MAPPINGS
Pos => RotUp
top bottom left right up down -> up down left right bottom top

OBJECTS
Face:Pos
white

Background
lightgreen

Wall
brown

Player
blue

COLLISIONLAYERS

Background
Face:Pos

RULES

(This rule:)
up Pos [Face:Pos] -> [Face:RotUp]

(Should be equivalent to this block, but isn't:)
  up [Face:top] -> [Face:up]
+ up [Face:bottom] -> [Face:down]
+ up [Face:left] -> [Face:left]
+ up [Face:right] -> [Face:right]
+ up [Face:up] -> [Face:bottom]
+ up [Face:down] -> [Face:top]

The expansion of the first rule is:

+ (30) UP POS=bottom [ face:bottom ] -> [ face:bottom ]
+ (30) UP POS=left [ face:left ] -> [ face:bottom ]
+ (30) UP POS=right [ face:right ] -> [ face:bottom ]
+ (30) UP POS=up [ face:up ] -> [ face:bottom ]
+ (30) UP POS=down [ face:down ] -> [ face:bottom ]

Workaround: It's possible to avoid the issue by renaming the tags in Pos so that they have different names than those in directions. It would work fine in that example, but of course it would not work in the case where some rules would need to map on the rule's direction.

See also #43, possibly related.

Thanks to knexator for reporting the bug.

ClementSparrow commented 2 years ago

Complement of information: this behavior seems to be caused by the function replace_directional_tag_mappings in identifiers.js.

Unless I was confused at the time I wrote this function, it seems there was a good reason to have this behavior, as there is this comment in the code: // Replace direction parameters only when the tag uses a directional mapping (not when the tag is 'directions' or a subset or superset of it)

What it does however is not exactly what is stated in this comment. Instead, it applies the tag mapping when the direction parameter of the function (set to the rule's direction) is an element of the start set of the mapping.

I guess the reason why it was done like that is that rule directions can be given by listing all the directions (like right left), not only by giving the name of a single "direction set" (like horizontal), so we cannot use the name of the start set to select the tag mappings to apply in the case of rule directions.

Maybe a fix would be to give the priority to the rule parameters over the rule's direction? I'm afraid it might break some existing games.