/* match.c */
/* $Id: match.c,v 1.5 1993/05/12 17:17:03 nils Exp $ */
#include "copyright.h"
/* Routines for parsing arguments */
#include <ctype.h>
#include "db.h"
#include "config.h"
#include "match.h"
#include "externs.h"
#ifdef __STDC__
#include <stdlib.h>
#endif
#define DOWNCASE(x) to_lower(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 char *match_name; /* name to match */
static int preferred_type = NOTYPE; /* preferred type */
static dbref it; /* the *IT*! */
/* this probably doesn't belong here but I didn't want to make another file */
/* check case insensitively if p is prefix for s */
int is_prefix(p,s)
char *p;
char *s;
{
if (!*s)
return(0);
while(*p)
if (!*s || (to_upper(*p++)!=to_upper(*s++)))
return(0);
return(1);
}
/* check a list for objects that are prefix's for string, && are controlled
|| link_ok */
dbref pref_match(player,list,string)
dbref player;
dbref list;
char *string;
{
dbref lmatch=NOTHING;
int mlen=0;
while(list!=NOTHING)
{
if (is_prefix(db[list].name,string) && (db[list].flags & PUPPET) &&
(controls(player,list,POW_MODIFY) || (db[list].flags & LINK_OK)))
{
if (strlen(db[list].name)>mlen)
{
lmatch=list;
mlen=strlen(db[list].name);
}
}
list=db[list].next;
}
return(lmatch);
}
void init_match(player,name,type)
dbref player;
char *name;
int type;
{
exact_match = last_match = NOTHING;
match_count = 0;
match_who = player;
match_name = name;
check_keys = 0;
preferred_type = type;
if((!string_compare(name,"it")) && *atr_get(player,A_IT))
it=atoi(1+atr_get(player,A_IT));
else
it=NOTHING;
}
void init_match_check_keys(player,name,type)
dbref player;
char *name;
int type;
{
init_match(player, name, type);
check_keys = 1;
}
static dbref choose_thing(thing1,thing2)
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(it != NOTHING && Typeof(it)==TYPE_PLAYER) {
exact_match=it;
return;
}
if(*match_name == LOOKUP_TOKEN) {
for(p = match_name + 1; isspace(*p); p++);
if((match = lookup_player(p)) != 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(match < 0 || match >= db_top) {
return NOTHING;
} else {
return match;
}
} else {
return NOTHING;
}
}
void match_absolute()
{
dbref match;
if(it != NOTHING) {
exact_match=it;
return;
}
if((match = absolute_name()) != NOTHING) {
exact_match = match;
}
}
void match_me()
{
if((it != NOTHING) && (it == match_who)) {
exact_match=it;
return;
}
if(!string_compare(match_name, "me")) {
exact_match = match_who;
}
}
void match_here()
{
if(it != NOTHING && it == db[match_who].location) {
exact_match = it;
return;
}
if(db[match_who].location != NOTHING)
if(!string_compare(match_name, "here"))
exact_match = db[match_who].location;
}
static void match_list(first)
dbref first;
{
dbref absolute;
absolute = absolute_name();
DOLIST(first, first) {
Access(first);
if(first == absolute || first == it) {
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)) {
if (match_count>0 && !string_compare(db[last_match].name,db[first].name))
match_count = 0;
last_match = first;
match_count++;
}
}
}
void match_possession()
{
match_list(db[match_who].contents);
}
void match_neighbor()
{
dbref loc;
if((loc = db[match_who].location) != NOTHING) {
match_list(db[loc].contents);
}
}
void match_perfect()
{
dbref loc;
dbref first;
if ((loc = db[match_who].location) != NOTHING)
first = db[loc].contents;
else return;
DOLIST(first, first) {
Access(first);
if (!strcmp(db[first].name, match_name) &&
((Typeof(first) == preferred_type) || (preferred_type == NOTYPE)))
exact_match = first;
}
}
void match_exit()
{
dbref loc;
dbref exit;
dbref absolute;
char *match;
char *p;
if (Typeof(db[match_who].location)!=TYPE_ROOM &&
Typeof(db[match_who].location) !=TYPE_THING)
return;
if((loc = db[match_who].location) != NOTHING) {
absolute = absolute_name();
DOLIST(exit, Exits(loc)) {
Access(exit);
if(exit == absolute || exit == it) {
exact_match = exit;
} else {
match = db[exit].name;
while(*match) {
/* check out this one */
for(p = match_name;
(*p
&& DOWNCASE(*p) == DOWNCASE(*match)
&& *match != EXIT_DELIMITER);
p++, match++);
/* did we get it? */
if(*p == '\0') {
/* make sure there's nothing afterwards */
while(isspace(*match)) match++;
if(*match == '\0' || *match == EXIT_DELIMITER) {
/* we got it */
exact_match = choose_thing(exact_match, exit);
goto next_exit; /* got this match */
}
}
/* we didn't get it, find next match */
while(*match && *match++ != EXIT_DELIMITER);
while(isspace(*match)) match++;
}
}
next_exit:
;
}
}
}
void match_everything()
{
match_exit();
match_neighbor();
match_possession();
match_me();
match_here();
/* if(power(player, TYPE_HONWIZ)) {*/
match_absolute();
match_player();
/* }*/
}
dbref match_result()
{
if(exact_match != NOTHING) {
store_it(exact_match);
return exact_match;
} else {
switch(match_count) {
case 0:
return NOTHING;
case 1:
store_it(last_match);
return last_match;
default:
return AMBIGUOUS;
}
}
}
/* use this if you don't care about ambiguity */
dbref last_match_result()
{
if(exact_match != NOTHING) {
store_it(exact_match);
return exact_match;
} else {
store_it(last_match);
return last_match;
}
}
dbref noisy_match_result()
{
dbref match;
switch(match = match_result()) {
case NOTHING:
notify(match_who, tprintf(NOMATCH_PATT,match_name));
return NOTHING;
case AMBIGUOUS:
notify(match_who, tprintf("I don't know which %s you mean.",match_name));
return NOTHING;
default:
return match;
}
}
void store_it(what)
dbref what;
{
char buf[50];
if(what==NOTHING) return;
sprintf(buf,"#%d",what);
atr_add(match_who,A_IT,buf);
}