00001
00002
00003
00004
00005
00006 #include "copyright.h"
00007 #include "autoconf.h"
00008 #include "config.h"
00009 #include "externs.h"
00010
00011 #include "attrs.h"
00012 #include "powers.h"
00013 #ifdef REALITY_LVLS
00014 #include "levels.h"
00015 #endif
00016
00017 const char *NOMATCH_MESSAGE = "I don't see that here.";
00018 const char *AMBIGUOUS_MESSAGE = "I don't know which one you mean!";
00019 const char *NOPERM_MESSAGE = "Permission denied.";
00020 const char *FUNC_FAIL_MESSAGE = "#-1";
00021 const char *FUNC_NOMATCH_MESSAGE = "#-1 NO MATCH";
00022 const char *OUT_OF_RANGE = "#-1 OUT OF RANGE";
00023 const char *FUNC_NOT_FOUND = "#-1 NOT FOUND";
00024 const char *FUNC_AMBIGUOUS = "#-2 AMBIGUOUS";
00025 const char *FUNC_NOPERM_MESSAGE = "#-1 PERMISSION DENIED";
00026
00027 #define CON_LOCAL 0x01 // Match is near me.
00028 #define CON_TYPE 0x02 // Match is of requested type.
00029 #define CON_LOCK 0x04 // I pass the lock on match.
00030 #define CON_COMPLETE 0x08 // Name given is the full name.
00031 #define CON_TOKEN 0x10 // Name is a special token.
00032 #define CON_DBREF 0x20 // Name is a dbref.
00033
00034 static MSTATE md;
00035
00036 static void promote_match(dbref what, int confidence)
00037 {
00038 #ifdef REALITY_LVLS
00039
00040 if(Good_obj(what) && (confidence & CON_LOCAL) &&
00041 !IsReal(md.player, what) && what != Location(md.player))
00042 return;
00043 #endif
00044
00045
00046 if (md.pref_type != NOTYPE)
00047 {
00048 if ( Good_obj(what)
00049 && Typeof(what) == md.pref_type)
00050 {
00051 confidence |= CON_TYPE;
00052 }
00053 }
00054 if (md.check_keys)
00055 {
00056 MSTATE save_md;
00057
00058 save_match_state(&save_md);
00059 if ( Good_obj(what)
00060 && could_doit(md.player, what, A_LOCK))
00061 {
00062 confidence |= CON_LOCK;
00063 }
00064 restore_match_state(&save_md);
00065 }
00066
00067
00068
00069 if (md.count == 0)
00070 {
00071 md.match = what;
00072 md.confidence = confidence;
00073 md.count = 1;
00074 return;
00075 }
00076
00077
00078
00079 if (confidence < md.confidence)
00080 {
00081 return;
00082 }
00083
00084
00085
00086 if (confidence > md.confidence)
00087 {
00088 md.match = what;
00089 md.confidence = confidence;
00090 md.count = 1;
00091 return;
00092 }
00093
00094
00095
00096 md.count++;
00097 if (RandomINT32(1,md.count) == 1)
00098 {
00099 md.match = what;
00100 }
00101 return;
00102 }
00103
00104
00105
00106
00107
00108
00109 static char *munge_space_for_match(char *name)
00110 {
00111 static char buffer[LBUF_SIZE];
00112
00113 char *p = name;
00114 char *q = buffer;
00115
00116 if (p)
00117 {
00118
00119
00120 while (mux_isspace(*p))
00121 {
00122 p++;
00123 }
00124
00125 while (*p)
00126 {
00127 while ( *p
00128 && !mux_isspace(*p))
00129 {
00130 *q++ = *p++;
00131 }
00132
00133 while (mux_isspace(*p))
00134 {
00135 p++;
00136 }
00137
00138 if (*p)
00139 {
00140 *q++ = ' ';
00141 }
00142 }
00143 }
00144
00145
00146
00147 *q = '\0';
00148 return buffer;
00149 }
00150
00151 void match_player(void)
00152 {
00153 if (md.confidence >= CON_DBREF)
00154 {
00155 return;
00156 }
00157 if (Good_obj(md.absolute_form) && isPlayer(md.absolute_form))
00158 {
00159 promote_match(md.absolute_form, CON_DBREF);
00160 return;
00161 }
00162 if (*md.string == LOOKUP_TOKEN)
00163 {
00164 char *p;
00165 for (p = md.string + 1; mux_isspace(*p); p++)
00166 {
00167 ;
00168 }
00169 dbref match = lookup_player(NOTHING, p, true);
00170 if (Good_obj(match))
00171 {
00172 promote_match(match, CON_TOKEN);
00173 }
00174 }
00175 }
00176
00177
00178
00179
00180 static dbref absolute_name(bool bNeedPound)
00181 {
00182 char *mname = md.string;
00183 if (bNeedPound)
00184 {
00185 if (*mname != NUMBER_TOKEN)
00186 {
00187 return NOTHING;
00188 }
00189 mname++;
00190 }
00191 if (*mname)
00192 {
00193 dbref match = parse_dbref(mname);
00194 if (Good_obj(match))
00195 {
00196 return match;
00197 }
00198 }
00199 return NOTHING;
00200 }
00201
00202 void match_absolute(void)
00203 {
00204 if (md.confidence >= CON_DBREF)
00205 {
00206 return;
00207 }
00208 if (Good_obj(md.absolute_form))
00209 {
00210 promote_match(md.absolute_form, CON_DBREF);
00211 }
00212 }
00213
00214 static void match_numeric(void)
00215 {
00216 if (md.confidence >= CON_DBREF)
00217 {
00218 return;
00219 }
00220 dbref match = absolute_name(false);
00221 if (Good_obj(match))
00222 {
00223 promote_match(match, CON_DBREF);
00224 }
00225 }
00226
00227 void match_me(void)
00228 {
00229 if (md.confidence >= CON_DBREF)
00230 {
00231 return;
00232 }
00233 if ( Good_obj(md.absolute_form)
00234 && md.absolute_form == md.player)
00235 {
00236 promote_match(md.player, CON_DBREF | CON_LOCAL);
00237 return;
00238 }
00239 if (!string_compare(md.string, "me"))
00240 {
00241 promote_match(md.player, CON_TOKEN | CON_LOCAL);
00242 }
00243 return;
00244 }
00245
00246 static void match_home(void)
00247 {
00248 if (md.confidence >= CON_DBREF)
00249 {
00250 return;
00251 }
00252 if (!string_compare(md.string, "home"))
00253 {
00254 promote_match(HOME, CON_TOKEN);
00255 }
00256 return;
00257 }
00258
00259 void match_here(void)
00260 {
00261 if (md.confidence >= CON_DBREF)
00262 {
00263 return;
00264 }
00265 if ( Good_obj(md.player)
00266 && Has_location(md.player))
00267 {
00268 dbref loc = Location(md.player);
00269 if (Good_obj(loc))
00270 {
00271 if (loc == md.absolute_form)
00272 {
00273 promote_match(loc, CON_DBREF | CON_LOCAL);
00274 }
00275 else if (!string_compare(md.string, "here"))
00276 {
00277 promote_match(loc, CON_TOKEN | CON_LOCAL);
00278 }
00279 else if (!string_compare(md.string, PureName(loc)))
00280 {
00281 promote_match(loc, CON_COMPLETE | CON_LOCAL);
00282 }
00283 }
00284 }
00285 }
00286
00287 static void match_list(dbref first, int local)
00288 {
00289 if (md.confidence >= CON_DBREF)
00290 {
00291 return;
00292 }
00293 DOLIST(first, first)
00294 {
00295 if (first == md.absolute_form)
00296 {
00297 promote_match(first, CON_DBREF | local);
00298 return;
00299 }
00300
00301
00302
00303
00304
00305
00306 const char *namebuf = PureName(first);
00307
00308 if (!string_compare(namebuf, md.string))
00309 {
00310 promote_match(first, CON_COMPLETE | local);
00311 }
00312 else if (string_match(namebuf, md.string))
00313 {
00314 promote_match(first, local);
00315 }
00316 }
00317 }
00318
00319 void match_possession(void)
00320 {
00321 if (md.confidence >= CON_DBREF)
00322 {
00323 return;
00324 }
00325 if (Good_obj(md.player) && Has_contents(md.player))
00326 {
00327 match_list(Contents(md.player), CON_LOCAL);
00328 }
00329 }
00330
00331 void match_neighbor(void)
00332 {
00333 if (md.confidence >= CON_DBREF)
00334 {
00335 return;
00336 }
00337 if ( Good_obj(md.player)
00338 && Has_location(md.player))
00339 {
00340 dbref loc = Location(md.player);
00341 if (Good_obj(loc))
00342 {
00343 match_list(Contents(loc), CON_LOCAL);
00344 }
00345 }
00346 }
00347
00348 static bool match_exit_internal(dbref loc, dbref baseloc, int local)
00349 {
00350 if ( !Good_obj(loc)
00351 || !Has_exits(loc))
00352 {
00353 return true;
00354 }
00355
00356 dbref exit;
00357 bool result = false;
00358 int key;
00359
00360 DOLIST(exit, Exits(loc))
00361 {
00362 if (exit == md.absolute_form)
00363 {
00364 key = 0;
00365 if (Examinable(md.player, loc))
00366 {
00367 key |= VE_LOC_XAM;
00368 }
00369 if (Dark(loc))
00370 {
00371 key |= VE_LOC_DARK;
00372 }
00373 if (Dark(baseloc))
00374 {
00375 key |= VE_BASE_DARK;
00376 }
00377 if (exit_visible(exit, md.player, key))
00378 {
00379 promote_match(exit, CON_DBREF | local);
00380 return true;
00381 }
00382 }
00383 if (matches_exit_from_list(md.string, PureName(exit)))
00384 {
00385 promote_match(exit, CON_COMPLETE | local);
00386 result = true;
00387 }
00388 }
00389 return result;
00390 }
00391
00392 void match_exit(void)
00393 {
00394 if (md.confidence >= CON_DBREF)
00395 {
00396 return;
00397 }
00398
00399 dbref loc = Location(md.player);
00400 if ( Good_obj(md.player)
00401 && Has_location(md.player))
00402 {
00403 (void)match_exit_internal(loc, loc, CON_LOCAL);
00404 }
00405 }
00406
00407 void match_exit_with_parents(void)
00408 {
00409 if (md.confidence >= CON_DBREF)
00410 {
00411 return;
00412 }
00413 if ( Good_obj(md.player)
00414 && Has_location(md.player))
00415 {
00416 dbref parent;
00417 int lev;
00418 dbref loc = Location(md.player);
00419 ITER_PARENTS(loc, parent, lev)
00420 {
00421 if (match_exit_internal(parent, loc, CON_LOCAL))
00422 {
00423 break;
00424 }
00425 }
00426 }
00427 }
00428
00429 void match_carried_exit(void)
00430 {
00431 if (md.confidence >= CON_DBREF)
00432 {
00433 return;
00434 }
00435 if ( Good_obj(md.player)
00436 && Has_exits(md.player))
00437 {
00438 (void)match_exit_internal(md.player, md.player, CON_LOCAL);
00439 }
00440 }
00441
00442 void match_carried_exit_with_parents(void)
00443 {
00444 if (md.confidence >= CON_DBREF)
00445 {
00446 return;
00447 }
00448 if ( Good_obj(md.player)
00449 && Has_exits(md.player))
00450 {
00451 dbref parent;
00452 int lev;
00453 ITER_PARENTS(md.player, parent, lev)
00454 {
00455 if (match_exit_internal(parent, md.player, CON_LOCAL))
00456 {
00457 break;
00458 }
00459 }
00460 }
00461 }
00462
00463 void match_master_exit(void)
00464 {
00465 if (md.confidence >= CON_DBREF)
00466 {
00467 return;
00468 }
00469 if ( Good_obj(md.player)
00470 && Has_exits(md.player))
00471 {
00472 (void)match_exit_internal(mudconf.master_room, mudconf.master_room, 0);
00473 }
00474 }
00475
00476 void match_zone_exit(void)
00477 {
00478 if (md.confidence >= CON_DBREF)
00479 {
00480 return;
00481 }
00482 if ( Good_obj(md.player)
00483 && Has_exits(md.player))
00484 {
00485 (void)match_exit_internal(Zone(md.player), Zone(md.player), 0);
00486 }
00487 }
00488
00489 void match_everything(int key)
00490 {
00491
00492
00493
00494
00495
00496
00497 match_me();
00498 match_here();
00499 match_absolute();
00500 if (key & MAT_NUMERIC)
00501 {
00502 match_numeric();
00503 }
00504 if (key & MAT_HOME)
00505 {
00506 match_home();
00507 }
00508 match_player();
00509 if (md.confidence >= CON_TOKEN)
00510 {
00511 return;
00512 }
00513
00514 if (!(key & MAT_NO_EXITS))
00515 {
00516 if (key & MAT_EXIT_PARENTS)
00517 {
00518 match_carried_exit_with_parents();
00519 match_exit_with_parents();
00520 }
00521 else
00522 {
00523 match_carried_exit();
00524 match_exit();
00525 }
00526 }
00527 match_neighbor();
00528 match_possession();
00529 }
00530
00531 dbref match_result(void)
00532 {
00533 switch (md.count)
00534 {
00535 case 0:
00536 return NOTHING;
00537
00538 case 1:
00539 return md.match;
00540
00541 default:
00542 return AMBIGUOUS;
00543 }
00544 }
00545
00546
00547
00548 dbref last_match_result(void)
00549 {
00550 return md.match;
00551 }
00552
00553 dbref match_status(dbref player, dbref match)
00554 {
00555 switch (match)
00556 {
00557 case NOTHING:
00558 notify(player, NOMATCH_MESSAGE);
00559 return NOTHING;
00560
00561 case AMBIGUOUS:
00562 notify(player, AMBIGUOUS_MESSAGE);
00563 return NOTHING;
00564
00565 case NOPERM:
00566 notify(player, NOPERM_MESSAGE);
00567 return NOTHING;
00568 }
00569 return match;
00570 }
00571
00572 dbref noisy_match_result(void)
00573 {
00574 return match_status(md.player, match_result());
00575 }
00576
00577 void save_match_state(MSTATE *mstate)
00578 {
00579 mstate->confidence = md.confidence;
00580 mstate->count = md.count;
00581 mstate->pref_type = md.pref_type;
00582 mstate->check_keys = md.check_keys;
00583 mstate->absolute_form = md.absolute_form;
00584 mstate->match = md.match;
00585 mstate->player = md.player;
00586 mstate->string = alloc_lbuf("save_match_state");
00587 strcpy(mstate->string, md.string);
00588 }
00589
00590 void restore_match_state(MSTATE *mstate)
00591 {
00592 md.confidence = mstate->confidence;
00593 md.count = mstate->count;
00594 md.pref_type = mstate->pref_type;
00595 md.check_keys = mstate->check_keys;
00596 md.absolute_form = mstate->absolute_form;
00597 md.match = mstate->match;
00598 md.player = mstate->player;
00599 strcpy(md.string, mstate->string);
00600 free_lbuf(mstate->string);
00601 }
00602
00603 void init_match(dbref player, const char *name, int type)
00604 {
00605 md.confidence = -1;
00606 md.count = 0;
00607 md.check_keys = false;
00608 md.pref_type = type;
00609 md.match = NOTHING;
00610 md.player = player;
00611 md.string = munge_space_for_match((char *)name);
00612 md.absolute_form = absolute_name(true);
00613 }
00614
00615 void init_match_check_keys(dbref player, const char *name, int type)
00616 {
00617 init_match(player, name, type);
00618 md.check_keys = true;
00619 }
00620
00621 dbref match_thing(dbref player, char *name)
00622 {
00623 init_match(player, name, NOTYPE);
00624 match_everything(MAT_EXIT_PARENTS);
00625 return noisy_match_result();
00626 }
00627
00628 dbref match_thing_quiet(dbref player, char *name)
00629 {
00630 init_match(player, name, NOTYPE);
00631 match_everything(MAT_EXIT_PARENTS);
00632 return match_result();
00633 }
00634
00635 void safe_match_result(dbref it, char *buff, char **bufc)
00636 {
00637 if (it == AMBIGUOUS)
00638 {
00639 safe_ambiguous(buff, bufc);
00640 }
00641 else
00642 {
00643 safe_notfound(buff, bufc);
00644 }
00645 }