Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add {flag?} MPI function #718

Merged
merged 3 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions include/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -2194,6 +2194,18 @@ int member(dbref thing, dbref list);
*/
dbref new_object(bool isplayer);

/**
* Returns true if the object has the given flag set (or reset).
*
* Understands flag alias and multiple not conditions (!!x = x, !!!x = !x).
*
* Checking "truewizard" is the same as checking "wizard" and "!quell".
*
* @param ref the object to check
* @param flag the flag (or alias) to check
*/
bool has_flag(dbref ref, const char *flag);

/**
* Find a dbref in an objnode list
*
Expand Down
19 changes: 19 additions & 0 deletions include/mfun.h
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,24 @@ const char *mfn_exits(MFUNARGS);
*/
const char *mfn_filter(MFUNARGS);

/**
* MPI function that returns if an object if it has the given flag (re)set.
*
* @see has_flag
*
* @param descr the descriptor of the caller
* @param player the ref of the calling player
* @param what the dbref of the trigger
* @param perms the dbref for permission consideration
* @param argc the number of arguments
* @param argv the array of strings for arguments
* @param buf the working buffer
* @param buflen the size of the buffer
* @param mesgtyp the type of the message
* @return string parsed results
*/
const char *mfn_flagp(MFUNARGS);

/**
* MPI function that returns the object flags for provided object as a string.
*
Expand Down Expand Up @@ -2985,6 +3003,7 @@ static struct mfun_dat mfun_list[] = {
{"EXEC!", mfn_execbang, 1, 0, 1, 1, 2},
{"EXITS", mfn_exits, 1, 0, 1, 1, 1},
{"FILTER", mfn_filter, 0, 0, 0, 3, 5},
{"FLAG?", mfn_flagp, 1, 0, 1, 2, 2},
{"FLAGS", mfn_flags, 1, 0, 1, 1, 1},
{"FOLD", mfn_fold, 0, 0, 0, 4, 5},
{"FOR", mfn_for, 0, 0, 0, 5, 5},
Expand Down
99 changes: 99 additions & 0 deletions src/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -2339,3 +2339,102 @@ env_distance(dbref from, dbref to)

return distance;
}

/**
* Returns true if the object has the given flag set (or reset).
*
* Understands flag alias and multiple not conditions (!!x = x, !!!x = !x).
*
* Checking "truewizard" is the same as checking "wizard" and "!quell".
*
* @param ref the object to check
* @param flag the flag (or alias) to check
*/
bool
has_flag(dbref ref, const char *flag)
{
object_flag_type tmp = 0;
int truwiz = 0;
bool result, negated = false;

while (*flag == '!') {
flag++;
negated = (!negated);
}

if (!*flag) {
return false;
}

if (string_prefix("abode", flag)
|| string_prefix("autostart", flag)
|| string_prefix("abate", flag)) {
tmp = ABODE;
} else if (string_prefix("builder", flag)
|| string_prefix("bound", flag)) {
tmp = BUILDER;
} else if (string_prefix("chown_ok", flag)
|| string_prefix("color", flag)) {
tmp = CHOWN_OK;
} else if (string_prefix("dark", flag)
|| string_prefix("debug", flag)) {
tmp = DARK;
} else if (string_prefix("guest", flag)) {
tmp = GUEST;
} else if (string_prefix("haven", flag)
|| string_prefix("hide", flag)
|| string_prefix("harduid", flag)) {
tmp = HAVEN;
} else if (string_prefix("interactive", flag)) {
tmp = INTERACTIVE;
} else if (string_prefix("jump_ok", flag)) {
tmp = JUMP_OK;
} else if (string_prefix("kill_ok", flag)) {
tmp = KILL_OK;
} else if (string_prefix("link_ok", flag)) {
tmp = LINK_OK;
} else if (string_prefix("mucker", flag)) {
tmp = MUCKER;
} else if (string_prefix("nucker", flag)) {
tmp = SMUCKER;
} else if (string_prefix("overt", flag)) {
tmp = (int)OVERT;
} else if (string_prefix("quell", flag)) {
tmp = QUELL;
} else if (string_prefix("sticky", flag)
|| string_prefix("silent", flag)
|| string_prefix("setuid", flag)) {
tmp = STICKY;
} else if (string_prefix("vehicle", flag)
|| string_prefix("viewable", flag)) {
tmp = VEHICLE;
} else if (string_prefix("wizard", flag)) {
tmp = WIZARD;
} else if (string_prefix("truewizard", flag)) {
tmp = WIZARD;
truwiz = 1;
} else if (string_prefix("xforcible", flag)
|| string_prefix("xpress", flag)) {
tmp = XFORCIBLE;
} else if (string_prefix("yield", flag)) {
tmp = YIELD;
} else if (string_prefix("zombie", flag)) {
tmp = ZOMBIE;
}

if (negated) {
if ((!truwiz) && (tmp == WIZARD)) {
result = (!Wizard(ref));
} else {
result = (tmp && ((FLAGS(ref) & tmp) == 0));
}
} else {
if ((!truwiz) && (tmp == WIZARD)) {
result = Wizard(ref);
} else {
result = (tmp && ((FLAGS(ref) & tmp) != 0));
}
}

return result;
}
34 changes: 34 additions & 0 deletions src/mfuns2.c
Original file line number Diff line number Diff line change
Expand Up @@ -3460,3 +3460,37 @@ mfn_width(MFUNARGS)

return buf;
}

/**
* MPI function that returns if an object if it has the given flag (re)set.
*
* @see has_flag
*
* @param descr the descriptor of the caller
* @param player the ref of the calling player
* @param what the dbref of the trigger
* @param perms the dbref for permission consideration
* @param argc the number of arguments
* @param argv the array of strings for arguments
* @param buf the working buffer
* @param buflen the size of the buffer
* @param mesgtyp the type of the message
* @return string parsed results
*/

const char *
mfn_flagp(MFUNARGS)
{
dbref obj = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp);

if (obj == PERMDENIED || obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING ||
obj == HOME) {
return "0";
}

if (has_flag(obj, argv[1])) {
return "1";
} else {
return "0";
}
}
97 changes: 12 additions & 85 deletions src/p_db.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,8 @@ prim_set(PRIM_PROTOTYPE)
|| string_prefix("autostart", flag)
|| string_prefix("abate", flag))
tmp = ABODE;
else if (string_prefix("builder", flag))
else if (string_prefix("builder", flag)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should note in both this code and in has_flag that any change needs to be made in both places?

Ideally, we'd unify these 2 case statements in some way since it looks like this has a lot of overlap with has_flag's code. However, there's also such a thing as optimizing yourself until you're weary, so if you rather put a TODO and a note that both places need to be changed, I wouldn't judge you :)

If you wanted to go the extra mile, though, I'd say make a str_to_flag call that has this case statement, then both has_flag and prim_set can use it (along with anywhere else this mess lives).

Copy link
Member Author

@wyld-sw wyld-sw Jan 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

str_to_flag is definitely coming - just wanted to see if I could be clever with ALL the flag checking. I can certainly add str_to_flag to this PR in the meantime so it definitely doesn't wait for a unified process.

It may have been added when I got to fully reviewing p_db.c :)

Copy link
Member Author

@wyld-sw wyld-sw Jan 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both changes are made. Please review; I think everything's in order...

I'm not too thrilled about the duplicate "truewizard" check, but it seemed like the best way (right now?) to preserve the different meanings for SET and FLAG?.

do_set is on notice as needing a change, too, but it uses both the str_to_flag logic and the restricted function (while introducing its own restrictions) and will take more thought.

|| string_prefix("bound", flag))
tmp = BUILDER;
else if (string_prefix("chown_ok", flag)
|| string_prefix("color", flag))
Expand All @@ -1082,6 +1083,7 @@ prim_set(PRIM_PROTOTYPE)
else if (string_prefix("guest", flag))
tmp = GUEST;
else if (string_prefix("haven", flag)
|| string_prefix("hide", flag)
|| string_prefix("harduid", flag))
tmp = HAVEN;
else if (string_prefix("interactive", flag))
Expand All @@ -1101,7 +1103,8 @@ prim_set(PRIM_PROTOTYPE)
else if (string_prefix("quell", flag))
tmp = QUELL;
else if (string_prefix("sticky", flag)
|| string_prefix("silent", flag))
|| string_prefix("silent", flag)
|| string_prefix("setuid", flag))
tmp = STICKY;
else if (string_prefix("vehicle", flag)
|| string_prefix("viewable", flag))
Expand All @@ -1110,7 +1113,8 @@ prim_set(PRIM_PROTOTYPE)
tmp = WIZARD;
else if (string_prefix("truewizard", flag))
tmp = WIZARD;
else if (string_prefix("xforcible", flag))
else if (string_prefix("xforcible", flag)
|| string_prefix("xpress", flag))
tmp = XFORCIBLE;
else if (string_prefix("yield", flag))
tmp = YIELD;
Expand Down Expand Up @@ -1234,99 +1238,22 @@ prim_mlevel(PRIM_PROTOTYPE)
void
prim_flagp(PRIM_PROTOTYPE)
{
int truwiz = 0;

CHECKOP(2);
oper1 = POP();
oper2 = POP();

if (oper1->type != PROG_STRING)
if (oper1->type != PROG_STRING) {
abort_interp("Invalid argument type (2)");
}

if (!valid_object(oper2))
if (!valid_object(oper2)) {
abort_interp("Invalid object.");
}

ref = oper2->data.objref;
CHECKREMOTE(ref);

tmp = 0;
result = 0;
{
char *flag = DoNullInd(oper1->data.string);

while (*flag == '!') {
flag++;
result = (!result);
}

if (!*flag)
abort_interp("Unknown flag.");

if (string_prefix("abode", flag)
|| string_prefix("autostart", flag)
|| string_prefix("abate", flag))
tmp = ABODE;
else if (string_prefix("builder", flag))
tmp = BUILDER;
else if (string_prefix("chown_ok", flag)
|| string_prefix("color", flag))
tmp = CHOWN_OK;
else if (string_prefix("dark", flag)
|| string_prefix("debug", flag))
tmp = DARK;
else if (string_prefix("guest", flag))
tmp = GUEST;
else if (string_prefix("haven", flag)
|| string_prefix("harduid", flag))
tmp = HAVEN;
else if (string_prefix("interactive", flag))
tmp = INTERACTIVE;
else if (string_prefix("jump_ok", flag))
tmp = JUMP_OK;
else if (string_prefix("kill_ok", flag))
tmp = KILL_OK;
else if (string_prefix("link_ok", flag))
tmp = LINK_OK;
else if (string_prefix("mucker", flag))
tmp = MUCKER;
else if (string_prefix("nucker", flag))
tmp = SMUCKER;
else if (string_prefix("overt", flag))
tmp = (int)OVERT;
else if (string_prefix("quell", flag))
tmp = QUELL;
else if (string_prefix("sticky", flag)
|| string_prefix("silent", flag))
tmp = STICKY;
else if (string_prefix("vehicle", flag)
|| string_prefix("viewable", flag))
tmp = VEHICLE;
else if (string_prefix("wizard", flag))
tmp = WIZARD;
else if (string_prefix("truewizard", flag)) {
tmp = WIZARD;
truwiz = 1;
} else if (string_prefix("xforcible", flag))
tmp = XFORCIBLE;
else if (string_prefix("yield", flag))
tmp = YIELD;
else if (string_prefix("zombie", flag))
tmp = ZOMBIE;
}

if (result) {
if ((!truwiz) && (tmp == WIZARD)) {
result = (!Wizard(ref));
} else {
result = (tmp && ((FLAGS(ref) & tmp) == 0));
}
} else {
if ((!truwiz) && (tmp == WIZARD)) {
result = Wizard(ref);
} else {
result = (tmp && ((FLAGS(ref) & tmp) != 0));
}
}
result = has_flag(ref, DoNullInd(oper1->data.string));

CLEAR(oper1);
CLEAR(oper2);
Expand Down
Loading