Dear List, There was some discussion on the forums about some odd behavior of some of the new filter features in 1.11.x series. Specifically, the filters [allied_with] and [enemy_of] in a standard side filter, and also [filter_vision] in a unit filter or terrain filter.
This was discussed at length on the forums, but in brief there are three issues, in order of increasing significance: 1.) All WML filters in the game (afaik) besides these are designed so that they result in a match whenever *any* object matches the condition. These filters are instead implemented so that *all* objects matching the filter must match the condition, e.g., every side that matches [allied_with] condition, must be allied with the side at hand, in order to match the larger filter. This seems not to have been intended, but it is not necessarily a bug, rather merely an inconsistency with the rest of WML. 2.) Realizing the quirk, but perhaps not realizing the any vs all distinction, it seems that we decided to define exceptional behavior for [allied_with] and [enemy_of] in the case that they do not match any objects -- in this case the subfilter is defined to fail to match, rather than to be vacuously true. So if there are no matches, it behaves like *any*, but if there are multiple matches, it behaves like *all*. I find this fairly confusing / complicated, but again it's debatable whether it is actually a bug. 3.) Finally, [filter_vision] tags are similar in that they require all matching objects to satisfy the condition if there are multiple tags, but very unfortunately, in the case that there are no matches, they do *different* things depending on whether the tag appears in a unit filter or a location filter. For a unit filter, the "tweak" mentioned above is applied, so that the overall filter fails to match if there are no matches to the inner filter, but for a location filter, the tweak is not applied, and the overall filter may succeed when the inner filter has no matches. This I feel is unambiguously a bug and will likely cause great frustration -- it is *not* good for tags with the same name to mean different things. The question now is, what if anything do we want to do in 1.12 branch regarding any of this? (Of course we also should fix in master but how we fix there depends on what we do in 1.12.) We have many options: Regarding [filter_vision] first: - We could do nothing. But, I think (3) is a big enough problem that we should address it somehow. - We could bring the unit_filter version into alignment with the terrain_filter version, by removing the "tweak". - We could change both, so that they match when any side matching the filter has the indicated visibility status. This is my favored option, the reason being, it is the simplest, and I don't think it is actually much more disruptive than the previous option. These filters were introduced in the 1.11.x series, it seems possible that not many people have used them extensively in scenarios yet. My feeling is, if we have to make some kind of change, we might as well just get it like we want it and bury the issue. - We could add a new tag / mode. More on this later. I have made a pull request implementing my favored option here. (However, before it would be merged hypothetically, I would prefer to make a similar change on master and write some unit tests.) https://github.com/wesnoth/wesnoth/pull/237 Regarding [allied_with] / [enemy_of]: - We could do nothing. However, if we are going to make changes to [filter_vision] though, then it is an opportune moment to fix the same problem here also. - We could add a new tag, which implements the *any* functionality which we originally desired. This is my favored option, see the forum discussion for why. I have made a pull request which adds [has_ally] and [has_enemy] which does this. Should we do this, we might also want to add warnings to [allied_with] / [enemy_of] saying "this tag is deprecated...", or we could just leave them, I don't have an opinion about that. https://github.com/wesnoth/wesnoth/pull/238 - We could change the behavior of [allied_with] / [enemy_of]. But since these are actually consistent with eachother, I'm not sure a compatibility breaking change is justified. - Another option was also suggested, that instead of new tags, we could add attributes which modify the behavior, e.g. [allied_with] could have an attribute "require_all" which defaults to yes, but if no is given, then it follows the expected 'any match' behavior. This is not my solution of choice, I think it becomes harder to read. Compare: [has_ally] [has_unit] type=Orcish Grunt [/has_unit] [/has_ally] versus [allied_with] require_all=no [has_unit] type=Orcish Grunt [/has_unit] [/allied_with] IMO it's just much better to have crisp tags that mean what we want, rather than something like [foo] disable_bugs=yes [bar] ... [/bar] [/foo] With that syntax it goes without saying that we won't deprecate later. In summary, my view is that: - For any misbehaving tag, we should provide an alternative without breaking compatibility. - For any truly broken tag (inconsistent behavior), we should just fix it the way it's supposed to be without preserving compatibility with the bug, esp. if the tag is new to 1.11.x series. I find it regrettable to lobby for changes like this to the WML API this close to release, but it seems we don't have great options. Next time we will have some unit tests to catch these problems, and the changes I propose would be accompanied with tests in this cycle. Anyways please write with your views. Best Regards, Chris Beck
_______________________________________________ Wesnoth-dev mailing list Wesnoth-dev@gna.org https://mail.gna.org/listinfo/wesnoth-dev