So at the z-machine level, an attribute is a bit associated with an object, and a property is a 1-64 byte quantity associated with an object. Both are referred to by an index.
But there are a lot of things that only make sense applied to rooms, and only make sense applied to (world) objects.
Since the total number of attributes and properties is limited, does it make sense to partition them?
Offhand:
Both objects and rooms can reasonably have a description property
Both objects and rooms can reasonably have a lit attribute
Only a room would reasonably have a property like n_to or an attribute like above_ground.
Only an object would reasonably have a property like weight or an attribute like wearable.
So for example weight and n_to could share the same property index since they’d never exist at the same time on the same object.
Now I could see this being error-prone if you accidentally pass the wrong “kind” of property or attribute to a generic routine.
We could burn an attribute to specify whether something is a room or an object, and then generate debug code to assert that it’s the right kind or not. Or simply have functions like get_room_attr and get_object_attr that will only return true if the attribute is set and it’s a room or an object. (Likewise for properties)
This seems like a pretty effective way to significantly expand the total number of attributes and properties available?
Am I missing something obvious?
(The fact that I haven’t mentioned either Inform 6 or ZIL is intentional)
I do wonder if vehicles are a potential pain point. What if you’re making a Star Wars game and you’ve implemented a sand crawler vehicle with multiple locations.
i don’t know about the z-machine specifically but probably, yes? there was just a discussion of something like this on the punyinform discord server and about how you can pretty much repurpose any attribute not normally used by a room for rooms (like enterable, supporter, animate, etc.). this is more economical than defining a new attribute and the compiler doesn’t care.
Absolutely possible. The Inform 6 library does this extensively, and Puny does it even more. I’ll dig up some examples when I’m back at my laptop if someone else doesn’t get to them first.
In Inform, this is what the “alias” directive on attributes and properties is for. In Dialog, it’s handled with access predicates: the standard library only defines a single property, which is “relation to parent” on things and “route finder scratch space” on rooms.
Nope, I was wrong about that, as far as the Inform 6 library is concerned—it only defines one alias, which is for compatibility rather than efficiency. PunyInform, though, uses this as much as possible:
Property door_to alias n_to; ! For economy: these properties
Property when_closed alias s_to; ! are used only by objects which
Property when_off alias s_to; ! aren't rooms
Property with_key alias e_to;
Property door_dir alias w_to;
Property orders alias ne_to;
Property capacity alias nw_to;
Property invent alias se_to;
Property inside_description alias sw_to;
Property react_before alias u_to;
Property react_after alias d_to;
Property add_to_scope alias in_to;
Property parse_name alias out_to;
Property when_open alias initial;
Property when_on alias initial;
Property daemon alias time_out;
Property article alias cant_go;
Similarly it aliases “visited” (for rooms) and “moved” (for objects), which Dialog doesn’t do.
Inform library 6/1 relied heavily on property aliasing, but this was dropped in a later version, since (A) it doesn’t matter much for z5+, and z3 support had largely been phased out, and (B) the library could be (slightly) more convenient to use without aliasing, e.g. an item can have either when_on and when_open and the library can check which one it is and act accordingly.