/* $Header: match.c,v 1.1 90/04/14 14:56:46 lachesis Exp $ * $Log: match.c,v $ * Revision 1.1 90/04/14 14:56:46 lachesis * Initial revision * */ #include "copyright.h" /* Routines for parsing arguments */ #include <ctype.h> #include "db.h" #include "config.h" #include "match.h" #define DOWNCASE(x) (isupper(x) ? tolower(x) : (x)) static dbref exact_match = NOTHING; /* holds result of exact match */ static int check_keys = 0; /* if non-zero, check for keys */ static dbref last_match = NOTHING; /* holds result of last match */ static int match_count; /* holds total number of inexact matches */ static dbref match_who; /* player who is being matched around */ static const char *match_name; /* name to match */ static int preferred_type = NOTYPE; /* preferred type */ void init_match(dbref player, const char *name, int type) { exact_match = last_match = NOTHING; match_count = 0; match_who = player; match_name = name; check_keys = 0; preferred_type = type; } void init_match_check_keys(dbref player, const char *name, int type) { init_match(player, name, type); check_keys = 1; } static dbref choose_thing(dbref thing1, dbref thing2) { int has1; int has2; if(thing1 == NOTHING) { return thing2; } else if(thing2 == NOTHING) { return thing1; } if(preferred_type != NOTYPE) { if(Typeof(thing1) == preferred_type) { if(Typeof(thing2) != preferred_type) { return thing1; } } else if(Typeof(thing2) == preferred_type) { return thing2; } } if(check_keys) { has1 = could_doit(match_who, thing1); has2 = could_doit(match_who, thing2); if(has1 && !has2) { return thing1; } else if (has2 && !has1) { return thing2; } /* else fall through */ } return (random() % 2 ? thing1 : thing2); } void match_player(void) { dbref match; const char *p; if(*match_name == LOOKUP_TOKEN && payfor(match_who, LOOKUP_COST)) { for(p = match_name + 1; isspace(*p); p++) /*EMPTY*/ ; if((match = lookup_player(p)) != NOTHING) { exact_match = match; } } } /* returns nnn if name = #nnn, else NOTHING */ static dbref absolute_name(void) { dbref match; if(*match_name == NUMBER_TOKEN) { match = parse_dbref(match_name+1); if(match < 0 || match >= db_top) { return NOTHING; } else { return match; } } else { return NOTHING; } } void match_absolute(void) { dbref match; if((match = absolute_name()) != NOTHING) { exact_match = match; } } void match_me(void) { if(!string_compare(match_name, "me")) { exact_match = match_who; } } void match_home(void) { if (!string_compare(match_name, "home")) { exact_match = HOME; } } void match_here(void) { if(!string_compare(match_name, "here") && db[match_who].location != NOTHING) { exact_match = db[match_who].location; } } static void match_list(dbref first) { dbref absolute; absolute = absolute_name(); if(!controls(match_who, absolute)) absolute = NOTHING; DOLIST(first, first) { if(first == absolute) { exact_match = first; return; } else if(!string_compare(db[first].name, match_name)) { /* if there are multiple exact matches, randomly choose one */ exact_match = choose_thing(exact_match, first); } else if (string_match(db[first].name, match_name) != NULL) { last_match = first; match_count++; } } } void match_possession(void) { match_list(db[match_who].contents); } void match_neighbor(void) { dbref loc; if((loc = db[match_who].location) != NOTHING) { match_list(db[loc].contents); } } /* * match_exits matches a list of exits, starting with 'first'. * It is will match exits of players, rooms, or things. */ void match_exits(dbref first) { dbref exit, absolute; const char *exitname, *p; if (first == NOTHING) return; /* Easy fail match */ if ((db[match_who].location) == NOTHING) return; absolute = absolute_name(); /* parse #nnn entries */ if (!controls(match_who, absolute)) absolute = NOTHING; DOLIST(exit, first) { if (exit == absolute) { exact_match = exit; continue; } exitname = db[exit].name; while (*exitname) { /* for all exit aliases */ for (p = match_name; /* check out 1 alias */ *p && DOWNCASE(*p) == DOWNCASE(*exitname) && *exitname != EXIT_DELIMITER; p++, exitname++) /*EMPTY*/ ; /* did we get a match on this alias? */ if (*p == '\0') { /* make sure there's nothing afterwards */ while (isspace(*exitname)) exitname++; if(*exitname == '\0' || *exitname == EXIT_DELIMITER) { /* we got a match on this alias */ exact_match = choose_thing(exact_match, exit); goto next_exit; } } /* we didn't get it, go on to next alias */ while (*exitname && *exitname++ != EXIT_DELIMITER) /*EMPTY*/ ; while (isspace(*exitname)) exitname++; } /* end of while alias string matches */ next_exit: ; } } /* * match_room_exits * Matches exits and actions attached to player's current room. * Formerly 'match_exit'. */ void match_room_exits(void) { dbref loc; if((loc = db[match_who].location) == NOTHING) return; if(Typeof(loc) != TYPE_ROOM) return; if(db[loc].sp.room.exits != NOTHING) { match_exits(db[loc].sp.room.exits); } } /* * match_invobj_actions * matches actions attached to objects in inventory */ void match_invobj_actions(void) { dbref thing; if (db[match_who].contents == NOTHING) return; DOLIST(thing, db[match_who].contents) { if (Typeof(thing) == TYPE_THING && db[thing].sp.thing.actions != NOTHING) { match_exits(db[thing].sp.thing.actions); } } } /* * match_roomobj_actions * matches actions attached to objects in the room */ void match_roomobj_actions(void) { dbref thing, loc; if ((loc = db[match_who].location) == NOTHING) return; if (db[loc].contents == NOTHING) return; DOLIST(thing, db[loc].contents) { if (Typeof(thing) == TYPE_THING && db[thing].sp.thing.actions != NOTHING) { match_exits(db[thing].sp.thing.actions); } } } /* * match_player_actions * matches actions attached to player */ void match_player_actions(void) { if (db[match_who].sp.player.actions == NOTHING) return; match_exits(db[match_who].sp.player.actions); } /* * match_all_exits * Matches actions on player, objects in room, objects in inventory, * and room actions/exits (in reverse order of priority order). */ void match_all_exits(void) { match_roomobj_actions(); match_invobj_actions(); match_player_actions(); match_room_exits(); } void match_everything(void) { match_all_exits(); match_neighbor(); match_possession(); match_me(); match_here(); if(Wizard(match_who)) { match_absolute(); match_player(); } } dbref match_result(void) { if(exact_match != NOTHING) { return exact_match; } else { switch(match_count) { case 0: return NOTHING; case 1: return last_match; default: return AMBIGUOUS; } } } /* use this if you don't care about ambiguity */ dbref last_match_result(void) { if(exact_match != NOTHING) { return exact_match; } else { return last_match; } } dbref noisy_match_result(void) { dbref match; switch(match = match_result()) { case NOTHING: notify(match_who, NOMATCH_MESSAGE); return NOTHING; case AMBIGUOUS: notify(match_who, AMBIGUOUS_MESSAGE); return NOTHING; default: return match; } }