/* match.c */ #include "copyright.h" /* Routines for parsing arguments */ #include <ctype.h> #ifdef WANT_ANSI #ifdef __STDC__ #include <stddef.h> #endif /* __STDC__ */ #endif /* WANT_ANSI */ #include "config.h" #include "db.h" #include "mudconf.h" #include "externs.h" #include "match.h" extern long random(); 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 */ /* * This function removes repeated spaces from the template to which object * names are being matched. It also removes inital and terminal spaces. */ static char *munge_space_for_match(char *name) { static char buffer[LBUF_SIZE]; char *p, *q; p = name; q = buffer; while (isspace(*p)) p++; /* remove inital spaces */ while (*p) { while (*p && !isspace(*p)) *q++ = *p++; while (*p && isspace(*++p)) ; if (*p) *q++ = ' '; } *q = '\0'; /* remove terminal spaces and terminate * string */ return (buffer); } /* * check a list for objects that are prefix's for string, && are controlled * || link_ok */ dbref pref_match(dbref player, dbref list, const char *string) { dbref lmatch = NOTHING; int mlen = 0; while (list != NOTHING) { if (string_prefix(string, Name(list)) && (Flags(list) & PUPPET) && controls(player, list)) { if (strlen(Name(list)) > mlen) { lmatch = list; mlen = strlen(Name(list)); } } list = Next(list); } return (lmatch); } void init_match(dbref player, const char *name, int type) { exact_match = last_match = NOTHING; match_count = 0; match_who = player; match_name = munge_space_for_match((char *)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, A_LOCK); has2 = could_doit(match_who, thing2, A_LOCK); if (has1 && !has2) { return thing1; } else if (has2 && !has1) { return thing2; } /* else fall through */ } return (random() % 2 ? thing1 : thing2); } void match_player() { dbref match; char *p; if (*match_name == LOOKUP_TOKEN) { for (p = (char *)match_name + 1; isspace(*p); p++) ; if ((match = lookup_player(NOTHING, p, 1)) != NOTHING) { exact_match = match; } } } /* returns nnn if name = #nnn, else NOTHING */ static dbref absolute_name() { dbref match; if (*match_name == NUMBER_TOKEN) { match = parse_dbref(match_name + 1); if (!Good_obj(match)) { return NOTHING; } else { return match; } } else { return NOTHING; } } void match_absolute() { dbref match; match = absolute_name(); if (Good_obj(match)) { exact_match = match; } } void match_me() { if (!string_compare(match_name, "me")) { exact_match = match_who; } } void match_here() { if (Good_obj(match_who) && Has_location(match_who)) { if (!string_compare(match_name, "here") && Good_obj(Location(match_who))) { exact_match = Location(match_who); } } } static void match_list(dbref first) { dbref absolute; absolute = absolute_name(); if (!Good_obj(absolute) || !controls(match_who, absolute)) absolute = NOTHING; DOLIST(first, first) { if (first == absolute) { exact_match = first; return; } else if (!string_compare(Name(first), match_name)) { /* if multiple exact matches, randomly choose one */ exact_match = choose_thing(exact_match, first); } else if (string_match(Name(first), match_name)) { last_match = first; match_count++; } } } void match_possession() { if (Good_obj(match_who) && Has_contents(match_who)) match_list(Contents(match_who)); } void match_neighbor() { dbref loc; if (Good_obj(match_who) && Has_location(match_who)) { loc = Location(match_who); if (Good_obj(loc)) { match_list(Contents(loc)); } } } static void match_exit_internal (dbref loc) { dbref exit, absolute; if (!Good_obj(loc) || !Has_exits(loc)) return; absolute = absolute_name(); if (!Good_obj(absolute) || !controls(match_who, absolute)) absolute = NOTHING; DOLIST(exit, Exits(loc)) { if (exit == absolute) { exact_match = exit; return; } if (matches_exit_from_list((char *)match_name, Name(exit))) exact_match = choose_thing(exact_match, exit); } } void match_exit() { if (Good_obj(match_who) && Has_location(match_who)) match_exit_internal(Location(match_who)); } void match_exit_with_parents() { dbref loc, parent; int lev; if (Good_obj(match_who) && Has_location(match_who)) { loc = Location(match_who); match_exit_internal(loc); if (exact_match == NOTHING) { for (lev=0, parent=Parent(loc); (Good_obj(parent) && (lev < mudconf.parent_nest_lim) && (exact_match == NOTHING)); parent=Parent(parent), lev++) { match_exit_internal(parent); } } } } void match_carried_exit() { if (Good_obj(match_who) && Has_exits(match_who)) match_exit_internal(match_who); } void match_carried_exit_with_parents() { dbref parent; int lev; if (Good_obj(match_who) && Has_exits(match_who)) { match_exit_internal(match_who); if (exact_match == NOTHING) { for (lev=0, parent=Parent(match_who); (Good_obj(parent) && (lev < mudconf.parent_nest_lim) && (exact_match == NOTHING)); parent=Parent(parent), lev++) { match_exit_internal(parent); } } } } void match_master_exit() { if (Good_obj(mudconf.master_room)) match_exit_internal(mudconf.master_room); } void match_everything() { match_carried_exit(); match_exit(); match_neighbor(); match_possession(); match_me(); match_here(); match_absolute(); match_player(); } dbref match_result() { 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() { if (exact_match != NOTHING) { return exact_match; } else { return last_match; } } dbref noisy_match_result() { 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; } }