RR_PERMISSIONS corruption when relation permission change disallowed?

In Relations.i6t, the first six routines are used to test/set various parameters that define the relation’s type. Using the first one as an example:

[ RELATION_TY_EquivalenceAdjective rel set  perms state handler;
	    perms = RlnGetF(rel, RR_PERMISSIONS);		! <--- retrieves current permissions
	    if (perms & RELS_EQUIVALENCE) state = true;
	    if (set < 0) return state;
	    if ((set) && (state == false)) {
	            perms = perms + RELS_EQUIVALENCE;
	            if (perms & RELS_SYMMETRIC == 0) perms = perms + RELS_SYMMETRIC;
	    }
	    if ((set == false) && (state)) {
	            perms = perms - RELS_EQUIVALENCE;
	            if (perms & RELS_SYMMETRIC) perms = perms - RELS_SYMMETRIC;
	    }
	    RlnSetF(rel, RR_PERMISSIONS, perms);		! <--- modifies current permissions
	    handler = RlnGetF(rel, RR_HANDLER);
	    if (handler(rel, RELS_SET_VALENCY, perms & VALENCY_MASK) == 0) ! <--- tests for success of change
	            "*** Can't change this to an equivalence relation ***";         
];

Note that the current permissions are changed whether or not the handler reports a success for the RELS_SET_VALENCY task. Future tests of permissions will report state as though the change had been successful.

To demonstrate the effect:

"False Positive"

Place is a room.

Alice is a woman in Place.

Bob is a man in Place.

When play begins:
	let R be a relation of things; [defaults to non-equivalence]
	now R relates Alice to Bob; [assertion prevents change of relation type]
	if R is equivalence, say "Test 1: equiv."; [correctly fails]
	now R is equivalence; [conversion fails]
	if R is equivalence, say "Test 2: equiv."; [false positive]

Although the demonstration uses a temporary relation, the same occurs for normal relations.

Is this intended behavior? If so, can someone explain why?

2 Likes

The fix for the apparent issue is straightforward enough:

[ RELATION_TY_EquivalenceAdjective rel set  perms state handler;
	    perms = RlnGetF(rel, RR_PERMISSIONS);		! <--- retrieves current permissions
	    if (perms & RELS_EQUIVALENCE) state = true;
	    if (set < 0) return state;
	    if ((set) && (state == false)) {
	            perms = perms + RELS_EQUIVALENCE;
	            if (perms & RELS_SYMMETRIC == 0) perms = perms + RELS_SYMMETRIC;
	    }
	    if ((set == false) && (state)) {
	            perms = perms - RELS_EQUIVALENCE;
	            if (perms & RELS_SYMMETRIC) perms = perms - RELS_SYMMETRIC;
	    }
	    handler = RlnGetF(rel, RR_HANDLER);
	    if (handler(rel, RELS_SET_VALENCY, perms & VALENCY_MASK) == 0) ! <--- tests for success of change
	            "*** Can't change this to an equivalence relation ***";
		else
	    		RlnSetF(rel, RR_PERMISSIONS, perms);	! <--- modifies permissions only on success

];

The same pattern applies to all of the other routines in the same group.

This resolves the issue of false positives, and seems like it’s functioning as might be expected given the design, but I’m still not sure whether the original code has a non-obvious functional reason for operating the way that it does.

I’ll mark this as solved since it addresses my problem, but if anyone has some idea of the “why” of the original code, please chime in.

1 Like