Generics Registry FO (#777)(an instance of Generic Feature Object made by Dred)     This is the Generic Feature Object. It is not meant to be used as a feature object itself, but is handy for making new feature objects. Go to location of this object, Dredful. VERB SOURCE CODE: @add-gen*eric: "Usage: @add-generic @generic-cat*egories @cat*egories:
"Usage: @generic-categories [category]";
" @categories [category]";
"";
"Lists all categories, and sub categories if they exist, that are present in the
Registry. Use these names for the other generic search, add, and remove verbs present
on this feature. If the optional [category] is supplied, only that category and subcategories
of it will be displayed.";
if (!argstr)
player:tell("Categories present in the ", this.name, ":");
for cats in (this.categories)
topcat = (clist = this:sort_cat(cats))[1];
for cat in (clist)
data = this:match_cat(cat, 1);
info = this.db:find(data[1]);
name = info[1];
indent = 2 * (data[2] - 1);
prefix = data[3] ? "\\ " | "| ";
prefix = (cat == topcat) ? "+ " | prefix;
player:tell($string_utils:left(tostr($string_utils:space(indent), prefix,
name), 25), " => ", info[2] ? info[2] | "No description.");
endfor
endfor
elseif (result = this:match_cat(argstr))
if (result[3])
topcat = result[1];
cats = this.categories;
for ind in (result[4][1..length(result[4]) - 1])
cats = cats[ind];
endfor
player:tell("Subcategory listing for \"", topcat, "\":");
for cat in (this:sort_cat(cats))
data = this:match_cat(cat, 1);
info = this.db:find(data[1]);
name = info[1];
indent = 2 * (data[2] - result[2]);
prefix = data[3] ? "\\ " | "| ";
prefix = (cat == topcat) ? "+ " | prefix;
player:tell($string_utils:left(tostr($string_utils:space(indent), prefix,
name), 25), " => ", info[2] ? info[2] | "No description.");
endfor
else
info = this.db:find(result[1]);
player:tell($string_utils:left(tostr("+ ", info[1]), 25), " => ", info[2]
? info[2] | "No description.");
endif
else
player:tell("No such category exists.");
endif
player:tell("--------------------");
.
@rm-gen*eric: "Usage: @rm-generic @gen*erics: "Usage: @generics @add-cat*egory: "Usage: @add-category @rm-cat*egory: "Usage: @rm-category @add-sub*category: "Usage: @add-subcategory match_cat:
"tries to find the given category. Returns:";
"if args[2] exists and is true, then assume args[1] was taken from .categories and
does exist.";
"{full category name, depth level (1 is top), FLAG, does it have sub-cats, LIST of
indexes of the category itself}";
if (!(cat = ((length(args) > 1) && args[2]) ? args[1] | this:get_cat(args[1], 1)))
return 0;
endif
curcats = this.categories;
for d in [1..length(curcats)]
maincat = curcats[d];
if (typeof(maincat) == STR)
if (cat == maincat)
return {maincat, 1, 0, {d}};
endif
else
sub = maincat;
level = 1;
"level will be length(indices), but -1 if the last element of indices is
a 1";
temp = {};
atend = 1;
indices = {d};
while (atend)
result = this:is_end_branch(sub);
parent = result[2];
if (cat == parent)
indices = this:find_ind(parent);
if (indices[length(indices)] == 1)
level = length(indices) - 1;
else
level = length(indices);
endif
return {parent, level, !result[1], indices};
elseif (result[1])
if (temp)
sub = temp[length(temp)];
temp = listdelete(temp, length(temp));
else
atend = 0;
endif
else
kids = result[3];
if (length(kids) > 1)
temp = {@temp, @kids[2..length(kids)]};
sub = kids[1];
else
sub = kids[1];
endif
endif
endwhile
endif
endfor
.
find_ind:
find = args[1];
cats = this.categories;
for d in [1..length(cats)]
maincat = cats[d];
if (typeof(maincat) == STR)
if (find == maincat)
return {d};
endif
else
result = this:in_this_branch(find, maincat);
if (result[1])
indices = {d, @result[2]};
return indices;
endif
endif
endfor
.
is_end_branch:
"Determines if the input is the end of a branch. Is a string if it is, is a LIST
if not.";
test = args[1];
if (typeof(test) == STR)
return {1, test};
else
return {0, test[1], test[2..length(test)]};
endif
.
in_this_branch:
"Given a string, and a branch, goes through that whole branch and searches for the
string, returning indexes if we're lucky.";
find = args[1];
branch = args[2];
result = this:is_end_branch(branch);
parent = result[2];
if (find == parent)
return {1, result[1] ? {} | {1}};
endif
if (result[1])
"it's an end branch, so nothing found.";
return {0};
else
kids = result[3];
for nbran in [1..length(kids)]
nres = this:in_this_branch(find, kids[nbran]);
if (nres[1])
return {1, {nbran + 1, @nres[2]}};
endif
endfor
return {0};
endif
.
@add-cat-desc: "Usage: @add-cat-desc sort_cat:
"sort_cat(LIST|STR branch) => given a list of categories, returns a list of names
sorted all nice";
cats = args[1];
if (typeof(cats) == STR)
return {cats};
endif
subs = {};
for cat in (cats)
subs = {@subs, @this:sort_cat(cat)};
endfor
return subs;
.
add_gen:
":add_gen(STR key, OBJ new object) => adds the new object to the category stored
at the key. Returns 1 if object was really added, 0 if already there.";
if (caller != this)
return E_PERM;
endif
catkey = args[1];
target = args[2];
data = this.db:find(catkey);
if (target in data[3])
return 0;
else
data[3] = setadd(data[3], target);
this.db:insert(catkey, data);
return 1;
endif
.
rem_gen:
":rem_gen(STR catkey, OBJ old object) => removes the object from the category at
the catkey. Returns 1 if object removed, returns 0 if object wasn't in there to begin
with.";
if (caller != this)
return E_PERM;
endif
catkey = args[1];
target = args[2];
data = this.db:find(catkey);
if (target in data[3])
data[3] = setremove(data[3], target);
this.db:insert(catkey, data);
return 1;
else
return 0;
endif
.
add_cat:
if (caller != this)
return E_PERM;
endif
name = args[1];
desc = args[2];
next = tostr(this.last = this.last + 1);
this.db:insert(next, {name, desc, {}});
return next;
.
rem_cat:
if (caller != this)
return E_PERM;
endif
cat = args[1];
if (tonum(cat) == this.last)
this.last = this.last - 1;
endif
return this.db:delete(cat);
.
get_cat:
"Given a full name, return either the data (args[2] false) or the keyname (args[2]
true). Args[2] is optional, will be false if not included.";
if (caller != this)
return E_PERM;
endif
catname = args[1];
for d in ($list_utils:flatten(this.categories))
if (match((data = this.db:find(d))[1], catname))
return ((length(args) > 1) && args[2]) ? d | data;
endif
endfor
return 0;
.
PROPERTY DATA:       categories       db       last |