src/match.c

Go to the documentation of this file.
00001 /*
00002  * match.c -- Routines for parsing arguments 
00003  */
00004 
00005 #include "copyright.h"
00006 #include "config.h"
00007 
00008 #include "config.h"
00009 #include "db.h"
00010 #include "mudconf.h"
00011 #include "externs.h"
00012 #include "match.h"
00013 #include "attrs.h"
00014 #include "powers.h"
00015 
00016 #define CON_LOCAL               0x01    /*
00017                                                                  * Match is near me 
00018                                                                  */
00019 #define CON_TYPE                0x02    /*
00020                                                                  * Match is of requested type 
00021                                                                  */
00022 #define CON_LOCK                0x04    /*
00023                                                                  * I pass the lock on match 
00024                                                                  */
00025 #define CON_COMPLETE            0x08    /*
00026                                                                          * Name given is the full name 
00027                                                                          */
00028 #define CON_TOKEN               0x10    /*
00029                                                                  * Name is a special token 
00030                                                                  */
00031 #define CON_DBREF               0x20    /*
00032                                                                  * Name is a dbref 
00033                                                                  */
00034 
00035 static MSTATE md;
00036 
00037 static void promote_match(dbref what, int confidence)
00038 {
00039         /*
00040          * Check for type and locks, if requested 
00041          */
00042 
00043         if(md.pref_type != NOTYPE) {
00044                 if(Good_obj(what) && (Typeof(what) == md.pref_type))
00045                         confidence |= CON_TYPE;
00046         }
00047         if(md.check_keys) {
00048                 MSTATE save_md;
00049 
00050                 save_match_state(&save_md);
00051                 if(Good_obj(what) && could_doit(md.player, what, A_LOCK));
00052                 confidence |= CON_LOCK;
00053                 restore_match_state(&save_md);
00054         }
00055         /*
00056          * If nothing matched, take it 
00057          */
00058 
00059         if(md.count == 0) {
00060                 md.match = what;
00061                 md.confidence = confidence;
00062                 md.count = 1;
00063                 return;
00064         }
00065         /*
00066          * If confidence is lower, ignore 
00067          */
00068 
00069         if(confidence < md.confidence) {
00070                 return;
00071         }
00072         /*
00073          * If confidence is higher, replace 
00074          */
00075 
00076         if(confidence > md.confidence) {
00077                 md.match = what;
00078                 md.confidence = confidence;
00079                 md.count = 1;
00080                 return;
00081         }
00082         /*
00083          * Equal confidence, pick randomly 
00084          */
00085 
00086         if(random() % 2) {
00087                 md.match = what;
00088         }
00089         md.count++;
00090         return;
00091 }
00092 
00093 /*
00094  * ---------------------------------------------------------------------------
00095  * * This function removes repeated spaces from the template to which object
00096  * * names are being matched.  It also removes inital and terminal spaces.
00097  */
00098 
00099 static char *munge_space_for_match(char *name)
00100 {
00101         static char buffer[LBUF_SIZE];
00102         char *p, *q;
00103 
00104         p = name;
00105         q = buffer;
00106         while (isspace(*p))
00107                 p++;                                    /*
00108                                                                  * remove inital spaces 
00109                                                                  */
00110         while (*p) {
00111                 while (*p && !isspace(*p))
00112                         *q++ = *p++;
00113                 while (*p && isspace(*++p));
00114                 if(*p)
00115                         *q++ = ' ';
00116         }
00117         *q = '\0';                                      /*
00118                                                                  * remove terminal spaces and terminate * * * 
00119                                                                  * 
00120                                                                  * * string 
00121                                                                  */
00122         return (buffer);
00123 }
00124 
00125 void match_player(void)
00126 {
00127         dbref match;
00128         char *p;
00129 
00130         if(md.confidence >= CON_DBREF) {
00131                 return;
00132         }
00133         if(Good_obj(md.absolute_form) && isPlayer(md.absolute_form)) {
00134                 promote_match(md.absolute_form, CON_DBREF);
00135                 return;
00136         }
00137         if(*md.string == LOOKUP_TOKEN) {
00138                 for(p = md.string + 1; isspace(*p); p++);
00139                 match = lookup_player(NOTHING, p, 1);
00140                 if(Good_obj(match)) {
00141                         promote_match(match, CON_TOKEN);
00142                 }
00143         }
00144 }
00145 
00146 /*
00147  * returns nnn if name = #nnn, else NOTHING 
00148  */
00149 
00150 static dbref absolute_name(int need_pound)
00151 {
00152         dbref match;
00153         char *mname;
00154 
00155         mname = md.string;
00156         if(need_pound) {
00157                 if(*md.string != NUMBER_TOKEN) {
00158                         return NOTHING;
00159                 } else {
00160                         mname++;
00161                 }
00162         }
00163         match = parse_dbref(mname);
00164         if(Good_obj(match)) {
00165                 return match;
00166         }
00167         return NOTHING;
00168 }
00169 
00170 void match_absolute(void)
00171 {
00172         if(md.confidence >= CON_DBREF)
00173                 return;
00174         if(Good_obj(md.absolute_form))
00175                 promote_match(md.absolute_form, CON_DBREF);
00176 }
00177 
00178 void match_numeric(void)
00179 {
00180         dbref match;
00181 
00182         if(md.confidence >= CON_DBREF)
00183                 return;
00184         match = absolute_name(0);
00185         if(Good_obj(match))
00186                 promote_match(match, CON_DBREF);
00187 }
00188 
00189 void match_me(void)
00190 {
00191         if(md.confidence >= CON_DBREF)
00192                 return;
00193         if(Good_obj(md.absolute_form) && (md.absolute_form == md.player)) {
00194                 promote_match(md.player, CON_DBREF | CON_LOCAL);
00195                 return;
00196         }
00197         if(!string_compare(md.string, "me"))
00198                 promote_match(md.player, CON_TOKEN | CON_LOCAL);
00199         return;
00200 }
00201 
00202 void match_home(void)
00203 {
00204         if(md.confidence >= CON_DBREF)
00205                 return;
00206         if(!string_compare(md.string, "home"))
00207                 promote_match(HOME, CON_TOKEN);
00208         return;
00209 }
00210 
00211 void match_here(void)
00212 {
00213         dbref loc;
00214 
00215         if(md.confidence >= CON_DBREF)
00216                 return;
00217         if(Good_obj(md.player) && Has_location(md.player)) {
00218                 loc = Location(md.player);
00219                 if(Good_obj(loc)) {
00220                         if(loc == md.absolute_form) {
00221                                 promote_match(loc, CON_DBREF | CON_LOCAL);
00222                         } else if(!string_compare(md.string, "here")) {
00223                                 promote_match(loc, CON_TOKEN | CON_LOCAL);
00224                         } else if(!string_compare(md.string, (char *) PureName(loc))) {
00225                                 promote_match(loc, CON_COMPLETE | CON_LOCAL);
00226                         }
00227                 }
00228         }
00229 }
00230 
00231 static void match_list(dbref first, int local)
00232 {
00233         char *namebuf;
00234 
00235         if(md.confidence >= CON_DBREF)
00236                 return;
00237         DOLIST(first, first) {
00238                 if(first == md.absolute_form) {
00239                         promote_match(first, CON_DBREF | local);
00240                         return;
00241                 }
00242                 /*
00243                  * Warning: make sure there are no other calls to Name() in 
00244                  * promote_match or its called subroutines; they
00245                  * would overwrite Name()'s static buffer which is
00246                  * needed by string_match(). 
00247                  */
00248                 namebuf = (char *) PureName(first);
00249 
00250                 if(!string_compare(namebuf, md.string)) {
00251                         promote_match(first, CON_COMPLETE | local);
00252                 } else if(string_match(namebuf, md.string)) {
00253                         promote_match(first, local);
00254                 }
00255         }
00256 }
00257 
00258 void match_possession(void)
00259 {
00260         if(md.confidence >= CON_DBREF)
00261                 return;
00262         if(Good_obj(md.player) && Has_contents(md.player))
00263                 match_list(Contents(md.player), CON_LOCAL);
00264 }
00265 
00266 void match_neighbor(void)
00267 {
00268         dbref loc;
00269 
00270         if(md.confidence >= CON_DBREF)
00271                 return;
00272         if(Good_obj(md.player) && Has_location(md.player)) {
00273                 loc = Location(md.player);
00274                 if(Good_obj(loc)) {
00275                         match_list(Contents(loc), CON_LOCAL);
00276                 }
00277         }
00278 }
00279 
00280 static int match_exit_internal(dbref loc, dbref baseloc, int local)
00281 {
00282         dbref exit;
00283         int result, key;
00284 
00285         if(!Good_obj(loc) || !Has_exits(loc))
00286                 return 1;
00287 
00288         result = 0;
00289         DOLIST(exit, Exits(loc)) {
00290                 if(exit == md.absolute_form) {
00291                         key = 0;
00292                         if(Examinable(md.player, loc))
00293                                 key |= VE_LOC_XAM;
00294                         if(Dark(loc))
00295                                 key |= VE_LOC_DARK;
00296                         if(Dark(baseloc))
00297                                 key |= VE_BASE_DARK;
00298                         if(exit_visible(exit, md.player, key)) {
00299                                 promote_match(exit, CON_DBREF | local);
00300                                 return 1;
00301                         }
00302                 }
00303                 if(matches_exit_from_list(md.string, (char *) PureName(exit))) {
00304                         promote_match(exit, CON_COMPLETE | local);
00305                         result = 1;
00306                 }
00307         }
00308         return result;
00309 }
00310 
00311 void match_exit(void)
00312 {
00313         dbref loc;
00314 
00315         if(md.confidence >= CON_DBREF)
00316                 return;
00317         loc = Location(md.player);
00318         if(Good_obj(md.player) && Has_location(md.player))
00319                 (void) match_exit_internal(loc, loc, CON_LOCAL);
00320 }
00321 
00322 void match_exit_with_parents(void)
00323 {
00324         dbref loc, parent;
00325         int lev;
00326 
00327         if(md.confidence >= CON_DBREF)
00328                 return;
00329         if(Good_obj(md.player) && Has_location(md.player)) {
00330                 loc = Location(md.player);
00331                 ITER_PARENTS(loc, parent, lev) {
00332                         if(match_exit_internal(parent, loc, CON_LOCAL))
00333                                 break;
00334                 }
00335         }
00336 }
00337 
00338 void match_carried_exit(void)
00339 {
00340         if(md.confidence >= CON_DBREF)
00341                 return;
00342         if(Good_obj(md.player) && Has_exits(md.player))
00343                 (void) match_exit_internal(md.player, md.player, CON_LOCAL);
00344 }
00345 
00346 void match_carried_exit_with_parents(void)
00347 {
00348         dbref parent;
00349         int lev;
00350 
00351         if(md.confidence >= CON_DBREF)
00352                 return;
00353         if(Good_obj(md.player) && (Has_exits(md.player) || isRoom(md.player))) {
00354                 ITER_PARENTS(md.player, parent, lev) {
00355                         if(match_exit_internal(parent, md.player, CON_LOCAL))
00356                                 break;
00357                 }
00358         }
00359 }
00360 
00361 void match_master_exit(void)
00362 {
00363         if(md.confidence >= CON_DBREF)
00364                 return;
00365         if(Good_obj(md.player) && Has_exits(md.player))
00366                 (void) match_exit_internal(mudconf.master_room,
00367                                                                    mudconf.master_room, 0);
00368 }
00369 
00370 void match_zone_exit(void)
00371 {
00372         if(md.confidence >= CON_DBREF)
00373                 return;
00374         if(Good_obj(md.player) && Has_exits(md.player))
00375                 (void) match_exit_internal(Zone(md.player), Zone(md.player), 0);
00376 }
00377 
00378 void match_everything(int key)
00379 {
00380         /*
00381          * Try matching me, then here, then absolute, then player FIRST, since
00382          * this will hit most cases. STOP if we get something, since those are
00383          * exact matches.
00384          */
00385 
00386         match_me();
00387         match_here();
00388         match_absolute();
00389         if(key & MAT_NUMERIC)
00390                 match_numeric();
00391         if(key & MAT_HOME)
00392                 match_home();
00393         match_player();
00394         if(md.confidence >= CON_TOKEN)
00395                 return;
00396 
00397         if(!(key & MAT_NO_EXITS)) {
00398                 if(key & MAT_EXIT_PARENTS) {
00399                         match_carried_exit_with_parents();
00400                         match_exit_with_parents();
00401                 } else {
00402                         match_carried_exit();
00403                         match_exit();
00404                 }
00405         }
00406         match_neighbor();
00407         match_possession();
00408 }
00409 
00410 dbref match_result(void)
00411 {
00412         switch (md.count) {
00413         case 0:
00414                 return NOTHING;
00415         case 1:
00416                 return md.match;
00417         default:
00418                 return AMBIGUOUS;
00419         }
00420 }
00421 
00422 /*
00423  * use this if you don't care about ambiguity 
00424  */
00425 
00426 dbref last_match_result(void)
00427 {
00428         return md.match;
00429 }
00430 
00431 dbref match_status(player, match)
00432          dbref player, match;
00433 {
00434         switch (match) {
00435         case NOTHING:
00436                 notify(player, NOMATCH_MESSAGE);
00437                 return NOTHING;
00438         case AMBIGUOUS:
00439                 notify(player, AMBIGUOUS_MESSAGE);
00440                 return NOTHING;
00441         case NOPERM:
00442                 notify(player, NOPERM_MESSAGE);
00443                 return NOTHING;
00444         }
00445         if(Good_obj(match) && Dark(match) && Good_obj(player) &&
00446            !WizRoy(Owner(player)) && !Builder(Owner(player)))
00447                 return match_status(player, NOTHING);
00448         return match;
00449 }
00450 
00451 dbref noisy_match_result(void)
00452 {
00453         return match_status(md.player, match_result());
00454 }
00455 
00456 dbref dispatched_match_result(player)
00457          dbref player;
00458 {
00459         return match_status(player, match_result());
00460 }
00461 
00462 int matched_locally(void)
00463 {
00464         return (md.confidence & CON_LOCAL);
00465 }
00466 
00467 void save_match_state(mstate)
00468          MSTATE *mstate;
00469 {
00470         mstate->confidence = md.confidence;
00471         mstate->count = md.count;
00472         mstate->pref_type = md.pref_type;
00473         mstate->check_keys = md.check_keys;
00474         mstate->absolute_form = md.absolute_form;
00475         mstate->match = md.match;
00476         mstate->player = md.player;
00477         mstate->string = alloc_lbuf("save_match_state");
00478         StringCopy(mstate->string, md.string);
00479 }
00480 
00481 void restore_match_state(mstate)
00482          MSTATE *mstate;
00483 {
00484         md.confidence = mstate->confidence;
00485         md.count = mstate->count;
00486         md.pref_type = mstate->pref_type;
00487         md.check_keys = mstate->check_keys;
00488         md.absolute_form = mstate->absolute_form;
00489         md.match = mstate->match;
00490         md.player = mstate->player;
00491         StringCopy(md.string, mstate->string);
00492         free_lbuf(mstate->string);
00493 }
00494 
00495 void init_match(dbref player, char *name, int type)
00496 {
00497         md.confidence = -1;
00498         md.count = md.check_keys = 0;
00499         md.pref_type = type;
00500         md.match = NOTHING;
00501         md.player = player;
00502         md.string = munge_space_for_match((char *) name);
00503         md.absolute_form = absolute_name(1);
00504 }
00505 
00506 void init_match_check_keys(dbref player, char *name, int type)
00507 {
00508         init_match(player, name, type);
00509         md.check_keys = 1;
00510 }

Generated on Mon May 28 04:25:25 2007 for BattletechMUX by  doxygen 1.4.7