Suppose I have a (puzzle $) trait for things that are puzzles. I want all NPCs to be puzzles:
(puzzle *(animate $))
However, I need the player to be animate, but not a puzzle.
#player
(animate *)
~(puzzle *)
Except—this doesn’t work. Now if I make a multi-query to *(puzzle $) to iterate over all puzzles in the game, the multi-query terminates when it hits #player, because the negated rule head is equivalent to (just) (fail).
What’s the proper way to do this? Right now I’m adding the player as an exception to the “animate things are puzzles” rule, but this seems like the wrong solution.
I don’t have an answer for this (sorry!) but I did something similar in my own game and ended up making every item in my Dialog game alive. I felt like I was living in the castle in The Beauty and the Beast.
If I had to stab at a solution, I would make a new predicate/trait NPC that applies to animate things that aren’t the player, something like:
But it’s been a while since I tried Dialog, so this may not work at all. If it doesn’t work and wastes your time, I’ll boot up the compiler to make it up to you! (unless someone else figures it out first).
Edit: My impression of Dialog is that it works like magic and you can put if statements anywhere, which was my design idea in the above code.
I think the “standard dialog answer” is to reverse the line order… if you have the specific negation for the player above the general case it seems to work out as you’d hope?
For the negation to work it has to come before the general case. But the problem is (just) (fail) will discard the choice point, therefore it will cut short the backtracking and *(puzzle $P) won’t guarantee to iterate over all animate objects.