I’m looking for the best way to un-attract objects from a room, that is if I have an object attracted to multiple rooms how do I remove the attraction to one or more or all attracted rooms?
If I want to remove the object from all of the attracted rooms I can define the object as being in multiple rooms using (* is #in#room1)(* is #in#room2) and then now the object to nowhere. This seems to work, and does make it easy to move the object back into multiple rooms, but is there something I’m missing, does this break something else?
So you want it to only be attracted to a certain room under certain conditions?
((room $) attracts #moon) ~(eclipse is happening)
This means that the moon is attracted to every room, as long as the eclipse is not happening. Replace (room $) (“anything that is a room”) with the name of a specific room, or a region, etc, if you like.
You can also make a new per-object flag that removes a floating object from all rooms, if you want:
($ attracts $Obj)
($Obj is absent)
(just) (fail)
This will need to be listed before all other attraction rules, in order to override them. But it allows (now) (#moon is absent) and (now) ~(#moon is absent) to remove and un-remove the moon, or any other object, from the world.
Waiting moves the moon into the three locations but waiting again only removes the moon from two locations. The room where the wait command was issued still has the moon. If I move to another room, wait twice, the moon is now in the new room and not the other two. What am I missing? Thanks in advance,
Ah, that comes down to how floating objects work. When the player enters a room $Room, the library runs a multi-query for ($Room attracts $Obj), and moves all those $Objs to be #in $Room.
But it never explicitly moves them away again. So changing the attraction will prevent it from being summoned into new rooms, but won’t stop it from lingering in the room where it already was.
The easiest way to fix this is just to add (now) (#moon is nowhere) after (now) (full moon).
I believe it does work; it just doesn’t automatically move things away again (because attraction only moves things into the location, it never gets rid of them again except by moving them somewhere else).
“Per-object variables” in Dialog are effectively many-to-one relations, not many-to-many (I think the standard implementation is literally a property on the object, using the Z-machine property table). As soon as you use (now) with the predicate ($ attracts $), it becomes a per-object variable: each room can attract at most one object. Think of it as room.attracts = obj in C/Python/I6/etc terms.
And because of this, the compiler gets confused about (now) ~(#field attracts #moon): you’re saying that field.attracts should not be set to moon, but you haven’t said what it should be set to. As a special case, though, (now) ~(#field attracts $) is allowed: that’s equivalent to field.attracts = NULL (“now the field doesn’t attract anything at all”).
Currently, as far as I know, Dialog doesn’t support dynamic many-to-many relations. You could implement them with a list of pairs, but that would be messy and probably not very efficient.
(prevent [eat #wallpaper])
(current room $Loc)
($Loc has been depapered)
There's no paper left to eat!
(perform [eat #wallpaper])
(current room $Loc)
(now) ($Loc has been depapered)
(now) (#wallpaper is nowhere)
Mm, tasty wallpaper.
((room $Room) attracts #wallpaper) ~($Room has been depapered)