Lock (frob class) This is a frob class for locks. Constructor methods: true_lock() A lock which always succeeds false_lock() A lock which always fails object_lock(obj) A lock which matches against obj and_lock(left, right) Boolean and of two locks or_lock(left, right) Boolean or of two locks not_lock(lock) Boolean not of a lock parse(s, env) Parse a lock from a string s Frob methods: try(obj) Check lock against obj parent frob_class object true_lock_class .eval .initialize(); .set_name("True lock class"); . method new return <this(), []>; . method try arg lock, obj; return 1; . parent frob_class object false_lock_class .eval .initialize(); .set_name("False lock class"); . method new return <this(), []>; . method try arg lock, obj; return 0; . parent frob_class object object_lock_class .eval .initialize(); .set_name("Object lock class"); . method new arg obj; if (type(obj) != 'dbref) throw(~perm, "Argument is not a dbref."); return <this(), [obj]>; . method try arg lock, obj; return lock[1] == obj; . parent frob_class object and_lock_class .eval .initialize(); .set_name("And lock class"); . method new arg lhs, rhs; if (type(lhs) != 'frob || type(rhs) != 'frob) throw(~perm, "Arguments are not both frobs."); return <this(), [lhs, rhs]>; . method try arg lock, obj; return lock[1].try(obj) && lock[2].try(obj); . parent frob_class object or_lock_class .eval .initialize(); .set_name("Or lock class"); . method new arg lhs, rhs; if (type(lhs) != 'frob || type(rhs) != 'frob) throw(~perm, "Arguments are not both frobs."); return <this(), [lhs, rhs]>; . method try arg lock, obj; return lock[1].try(obj) || lock[2].try(obj); . parent frob_class object not_lock_class .eval .initialize(); .set_name("Not lock class"); . method new arg lock; if (type(lock) != 'frob) throw(~perm, "Argument is not a lock."); return <this(), [lock]>; . method try arg lock; return !lock[1].try(obj); . parent root object lock_parser eval .initialize(); .set_name("Lock parser"); . method parse arg s, env; var stack, lock, n, m, obj, len; stack = []; while (1) { // Look for valid prefixes. while (1) { while (s && s[1] == " ") s = substr(s, 2); if (!s) throw(~parse, "String ends unexpectedly."); if (s[1] == "(") { stack = stack + ['open]; s = substr(s, 2); } else if (s[1] == "!") { stack = stack + ['not]; s = substr(s, 2); } else { break; } } // Look for an object name. for n in [1..strlen(s)] { if (s[n] in ")&|") { n = n - 1; break; } } m = n; while (m && s[m] == " ") m = m - 1; if (!m) throw(~parse, "Null object name."); obj = (> env.match_environment(substr(s, 1, m)) <); lock = $object_lock_class.new(obj); stack = stack + [lock]; s = substr(s, n + 1); // Loop until no more reduction to be done. while (1) { // Process negations, ands, ors. while (1) { len = listlen(stack); if (len < 2) break; if (stack[len - 1] == 'not) { lock = $not_lock_class.new(stack[len]); stack = sublist(stack, 1, len - 2) + [lock]; } else if (stack[len - 1] == 'and) { lock = $and_lock_class.new(stack[len - 2], stack[len]); stack = sublist(stack, 1, len - 3) + [lock]; } else if (stack[len - 1] == 'or) { lock = $or_lock_class.new(stack[len - 2], stack[len]); stack = sublist(stack, 1, len - 3) + [lock]; } else { break; } } // Close parens, if necessary; otherwise stop. if (!s || s[1] != ")") break; while (s && s[1] == ")") { len = listlen(stack); if (len < 2 || stack[len - 1] != 'open) throw(~parse, "Misplaced right parenthesis."); stack = sublist(stack, 1, len - 2) + [stack[len]]; s = substr(s, 2); while (s && s[1] == " ") s = substr(s, 2); } } // Are we done? if (!s) { if (listlen(stack) > 1) throw(~parse, "Unmatched left parentheses."); return stack[1]; } // No, we're at a conjunction. if (s[1] == "&") { stack = stack + ['and]; s = substr(s, 2); } else if (s[1] == "|") { stack = stack + ['or]; s = substr(s, 2); } else { throw(~parse, "Illegal character following right parenthesis."); } } .