TinyMAZE/
TinyMAZE/config/
TinyMAZE/doc/
TinyMAZE/run/msgs/
TinyMAZE/src/
TinyMAZE/src/db/
TinyMAZE/src/ident/
TinyMAZE/src/io/
TinyMAZE/src/prog/
TinyMAZE/src/softcode/
TinyMAZE/src/util/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "db.h"
#include "externs.h"

static void add_match(OBJ *obj, OBJ ***match_list)
{
  int i;

  if(!*match_list)
    *match_list = (OBJ **)stack_alloc(sizeof(OBJ *), 0, 1);

  for(i = 0;(*match_list)[i];++i)
    if((*match_list)[i] == obj)
      return;

  *match_list = (OBJ **)stack_realloc_tmp(*match_list, sizeof(OBJ *)*(i+1));
  (*match_list)[i] = obj;
  (*match_list)[i+1] = NULL;
}

OBJ *match_dbref(char *str, int type)
{
  OBJ *o;

  if(*str != '#' || !*(str+1))
    return(NULL);

  if((o = find_object(atoi(str+1))))
    if(type & Typeof(o))
      return(o);

  return(NULL);
}

OBJ *match_player(OBJ *player, char *str)
{
  OBJ *o, *loc;
  char *p = str;

  if(player)
  {
    if(!string_compare(str, "me"))
      return(player);
    loc = player->location;
  }
  else
    loc = NULL;

  if(*str == '*')
  {
    loc = NULL;
    p++;
  }

  if(!*p)
    return(NULL);

  for(o = player_list;o;o = o->next)
    if(!loc || o->location == loc)
      if(!string_compare(p, o->name) ||
        !string_compare(p, atr_get(o, "ALIAS")))
      {
        return(o);
      }

  o = match_dbref(p, TYPE_PLAYER);

  return(o);
}

OBJ *match_contents(OBJ *thing, char *str, int type)
{
  OBJ *o, **matches = NULL;

  if(!thing || !*str)
    return(NULL);

  for(o = thing->contents;o;o = o->next_con)
    if(Typeof(o) & type)
    {
      if(string_match(o->name, str))
        add_match(o, &matches);
      if(type & TYPE_PLAYER)
        if(!string_compare(atr_get(o, "ALIAS"), str))
          add_match(o, &matches);
    }

  if(!matches || !matches[0] || matches[1])
    return(NULL);
  return(matches[0]);
}

static OBJ *match_exits(OBJ *room, char *str)
{
  OBJ *o;
  char buf[1024];
  char *p, *q, *r;

  if(!room || !*str)
    return(NULL);

  for(o = room->exits;o;o = o->next_exit)
  {
    if((p = strchr(o->name, '<')))
    {
      if((r = strchr(p+1, '>')))
      {
        q = p;
        while(isspace(q > o->name && *(--q)));  /* Whole loop */
        if(q > o->name)
        {
          strncpy(buf, o->name, q-o->name);
          *(buf+(q-o->name)) = '\0';
          if(!string_compare(buf, str))
            return(o);
        }

        p++;
        if(p-r)
        {
          strncpy(buf, p, r-p);
          *(buf+(r-p)) = '\0';
          if(!string_compare(buf, str))
            return(o);
        }
      }
    }

    if((p = strchr(o->name, EXIT_DELIMITER)))
    {
      if(!string_compare(p+1, str))
        return(o);

      strncpy(buf, o->name, p-o->name);
      *(buf+(p-o->name)) = '\0';
    }
    else
      strcpy(buf, o->name);

    if(!string_compare(buf, str))
      return(o);
  }

  return(NULL);
}

OBJ *match_object(OBJ *player, char *str, int type)
{
  OBJ *o;
  OBJ **matches = NULL;

/* If it starts with a '#', they MUST be specifying a dbref number */
  if(*str == '#')
    return(match_dbref(str, type));

  if(player)
  {
    if(!string_compare(str, "me") && (Typeof(player) & type))
      return(player);
    if(!string_compare(str, "here") && (Typeof(player->location) & type))
      return(player->location);
    if((Typeof(player->location) & type) &&
     string_prefix(str, player->location->name))
    {
      add_match(player->location, &matches);
    }
    if((o = match_contents(player->location, str, type)))
      add_match(o, &matches);
    if(type & TYPE_EXIT)
      if((o = match_exits(player->location, str)))
        add_match(o, &matches);
  }

  if(type & TYPE_PLAYER)
    if((o = match_player(player, str)))
      add_match(o, &matches);

  if((o = match_contents(player, str, type)))
    add_match(o, &matches);

/* Ambiguity check */
/* If there's more than one match, don't match anything */
  if(!matches || !matches[0] || matches[1])
    return(NULL);
  return(matches[0]);
}

char *no_match(char *str)
{
  char buf[4096];

  if(!*str)
    strcpy(buf, "You must specify a target!");
  else
    sprintf(buf, "I don't see %s here!", str);

  return(stack_string_alloc(buf, 0));
}

char *name(OBJ *thing)
{
  char buf[1024];
  char *p;
  OBJ *lnk = thing;
  ATTR *coloratr = find_attr("COLOR"), *rainbowatr = find_attr("RAINBOW");

  if(!thing)
    return("");

/* Exits might use their link's color */
  if(Typeof(thing) == TYPE_EXIT)
  {
    if(thing->link && my_is_color(atr_get_a(thing->link, coloratr)))
      lnk = thing->link;
    if(my_is_color(atr_get_a(thing, coloratr)))
      lnk = thing;
  }

  if(my_is_color(atr_get_a(lnk, coloratr)))
  {
    if(!*atr_get_a(thing, rainbowatr))
      sprintf(buf, "|%s|%s|n|",
        atr_get_a(lnk, coloratr), thing->name);
    else
      sprintf(buf, "|%s|%s|n|",
        atr_get_a(lnk, coloratr), atr_get_a(thing, rainbowatr));
  }
  else
  {
    if(!*atr_get_a(thing, rainbowatr))
      sprintf(buf, "|n|%s|n|", thing->name);
    else
      sprintf(buf, "|n|%s|n|", atr_get_a(thing, rainbowatr));
  }

  if(Typeof(thing) == TYPE_EXIT && (p = strchr(buf, EXIT_DELIMITER)))
    *p = '\0';

  return(stack_string_alloc(buf, 0));
}

char *poss(OBJ *thing)
{
  char format[1024];
  char buf[1024];
  char *p = thing->name;

  if(!thing)
    return("");

  if(tolower(*(p+strlen(p)-1) == 's'))
    sprintf(format, "%s'", atr_get(thing, "RAINBOW"));
  else
    sprintf(format, "%s's", atr_get(thing, "RAINBOW"));

  if(my_is_color(atr_get(thing, "COLOR")))
    sprintf(buf, "|%s|%s|n|", atr_get(thing, "COLOR"), format);
  else
    sprintf(buf, "|n|%s|n|", format);

  return(stack_string_alloc(buf, 0));
}