/* Hamlet, November 1995 -- Things that respond to gives. */
#define MONEY_HAND "/obj/handlers/money_handler"
int likesgive = 0;
string *givefunc = ({ });
mixed *givecond = ({ });
object *oldinv;
int value = 0;
int RECALC_VALUE = 1;
void give_init() {
  if(likesgive) {
    add_action("give_trigger","give");
    add_action("give_trigger","put");
    add_action("give_trigger","slip");
  }
}
/* This function just does validity checking and then stores values */
varargs void respond_give(string func, mixed *to_match) {
  int VALID = 0;
  
  if(!func)  return;
  
  if(to_match && !sizeof(to_match))
    to_match = 0;
      
  if(!to_match)  VALID = 1;  /* if no to_match, we unconditionally call */
    
  if(!VALID && stringp(to_match))  VALID = 1;  /* Match by name */
      
  if(!VALID && to_match[0] == "unconditional")  VALID = 1; /* see !to_match */
      
  if(!VALID && (to_match[0] == "name") && (sizeof(to_match) == 2) )
    VALID = 1;  /* same as the stringp case */
      
  if(!VALID && (to_match[0] == "property") && (sizeof(to_match) > 1) )
    VALID = 1;  /* match by property */
  if(!VALID && (to_match[0] == "money") && (sizeof(to_match) > 1) ) {
    if(sizeof(to_match) > 2)
      to_match = ({ to_match[0] , MONEY_HAND->
                   query_total_value(to_match[1..sizeof(to_match)-1]) });
    VALID = 1;  /* match by augmented money */
  }
          
  if(VALID) { /* Turn stuff on */
    likesgive = 1;
    givefunc += ({ func });
    if(to_match)  givecond += ({ to_match });
    else givecond += ({ 0 });
  }
}
void give_trigger(string str) {
  int i;
  
  oldinv = all_inventory(this_object());
  value = 0;
  
  if(RECALC_VALUE && sizeof(oldinv))
    for(i=0;i<sizeof(oldinv);i++)
      if(oldinv[i]->query_name() == "coin") {
        value = oldinv[i]->query_value();
        break;
      }
      
  call_out("give_response",2,this_player());
  return 0;
}
void give_response(object player) {
  int i,j;
  object *inv;
  object *inv2 = ({ });
  string namematch;
  int MATCHBYNAME = 0;
  /* These next two shouldn't be possible, but let's be paranoid */  
  if(!sizeof(givefunc))  return;
  if(!player)  return;
  for(j=0;j<sizeof(givecond);j++) {
    /* unconditional */  
    if(!givecond[j]) {
      if(sizeof(all_inventory(this_object())) - sizeof(oldinv))
        call_other(this_object(),givefunc[j],player);
      continue;
    }
  
    /* Match by name */  
    MATCHBYNAME = 0;
    if(stringp(givecond[j])) {
      namematch = givecond[j];
      MATCHBYNAME = 1;
    }
    else if(givecond[j][0] == "name") {
      namematch = givecond[j][1];
      MATCHBYNAME = 1;
    }
    
    if(MATCHBYNAME) {
      inv = find_match(namematch, this_object());
      for(i=0;i<sizeof(oldinv);i++) /* looks stupid, but it's the best way */
        inv -= ({ oldinv[i] });
      if(sizeof(inv))
        call_other(this_object(),givefunc[j],player,inv);
      continue;
    }
    /* This is truly unconditional */  
    if(givecond[j][0] == "unconditional") {
      if(sizeof(all_inventory(this_object())))
        call_other(this_object(),givefunc[j],player);
      continue;
    }
  
    /* Match by property? */  
    if(givecond[j][0] == "property") {
      inv = all_inventory(this_object());
      for(i=0;i<sizeof(oldinv);i++) /* looks stupid, but it's the best way */
        inv -= ({ oldinv[i] });
      
      inv2 = ({ });
      if(sizeof(inv)) 
        for(i=0;i<sizeof(inv);i++) 
          if(sizeof(givecond[j]) == 2) {
            if(inv[i]->query_property(givecond[j][1]))
              inv2 += ({ inv[i] });
          }
          else {
            if(inv[i]->query_property(givecond[j][1]) == givecond[j][2])
              inv2 += ({ inv[i] });
          }
        
      if(sizeof(inv2))
        call_other(this_object(),givefunc[j],player,inv2);
      continue;
    }
    
    /* Match on money */
    if(givecond[j][0] == "money") {
      inv = all_inventory(this_object());
      for(i=0;i<sizeof(inv);i++)
        if(inv[i]->query_name() == "coin")
          break;
      
      if(i<sizeof(inv)) {
        if( (inv[i]->query_value() - value) >= givecond[j][1] ) {
          RECALC_VALUE = 1;
          call_other(this_object(),givefunc[j],player,({ inv[i] }));
        }
        else 
          RECALC_VALUE = 0;
      }
    }
  }
  
  return;    
}
mixed tell_me_gives() {
  return ({ givefunc, givecond });
}