/* rob.c */
#include "os.h"
#include "copyright.h"

/* rob and kill */

#include "config.h"
#include "db.h"
#include "interface.h"
#include "match.h"
#include "externs.h"

void do_rob (dbref player, const char *what)
{
  dbref thing;
  init_match (player, what, TYPE_PLAYER);
  match_neighbor ();
  match_me ();
  if (Wizard (player)) {
    match_absolute ();
    match_player ();
  }
  thing = match_result ();

  switch (thing) {
  case NOTHING:
    notify (player, "Rob whom?");
    break;
  case AMBIGUOUS:
    notify (player, "I don't know who you mean!");
    break;
  default:
    if (Typeof (thing) != TYPE_PLAYER) {
      notify (player, "Sorry, you can only rob other players.");
    } else if (Pennies (thing) < 1) {
      notify (player, tprintf ("%s has no %s.", db[thing].name, MONIES));
      notify (thing,
        tprintf ("%s tried to rob you, but you have no %s to take.",
          db[player].name, MONIES));
    } else if (could_doit (player, thing)) {
      /* steal a penny */
      giveto (player, 1);
      giveto (thing, -1);
      notify (player, tprintf ("You stole a %s.", MONEY));
      notify (thing, tprintf ("%s stole one of your %s!", db[player].name,
          MONIES));
      did_it (player, thing, "SUCCESS", NULL, "OSUCCESS", NULL, "ASUCCESS",
        NOTHING);
    } else
      did_it (player, thing, "FAILURE", "Your conscience tells you not to.",
        "OFAILURE", NULL, "AFAILURE", NOTHING);
    break;
  }
}

void do_kill (dbref player, const char *what, int cost, int slay)
{
  dbref victim;
  char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN];

  if (slay && !Wizard (player)) {
    notify (player, "You do not have such power.");
    return;
  }
  init_match (player, what, TYPE_PLAYER);
  match_neighbor ();
  match_possession ();
  match_me ();
  match_here ();
  if (Wizard (player)) {
    match_player ();
    match_absolute ();
  }
  victim = match_result ();

  if (slay) {
    static char pl[BUFFER_LEN], vic[BUFFER_LEN];
    strcpy (pl, unparse_object (player, player));
    strcpy (vic, unparse_object (player, victim));
    fprintf (stderr, "SLAY [%s] %s\n", pl, vic);
  }
  switch (victim) {
  case NOTHING:
    notify (player, "I don't see that here.");
    break;
  case AMBIGUOUS:
    notify (player, "I don't know what you mean!");
    break;
  default:
    if (db[player].flags & PLAYER_SUSPECT)
      raw_broadcast (WIZARD, "Broadcast: Suspect %s tried to kill %s(#%d).",
        db[player].name, db[victim].name, victim);
    if ((Typeof (victim) != TYPE_PLAYER) && (Typeof (victim) != TYPE_THING)) {
      notify (player, "Sorry, you can only kill players and objects.");
    } else if (((db[db[victim].location].flags & HAVEN) &&
        !Wizard (player)) ||
      (controls (victim, db[victim].location) &&
        !controls (player, db[victim].location))) {
      notify (player, "Sorry.");
    } else if ((db[victim].flags & THING_IMMORTAL) &&
      !Wizard (player) && (db[victim].owner != player)) {
      notify (player, "That object is immortal and cannot be killed.");
    } else {
      /* go for it */
      /* set cost */
      /* if this isn't called via slay */
      if (!slay) {
        if (cost < KILL_MIN_COST)
          cost = KILL_MIN_COST;

        /* see if it works */
        if (!payfor (player, cost)) {
          notify (player, tprintf ("You don't have enough %s.", MONIES));
          break;
        }
      }
      if ((((OS_RAND () % KILL_BASE_COST) < cost) || slay) && !Wizard (victim)) {
        /* you killed him */
        sprintf (tbuf1, "You killed %s!", db[victim].name);
        sprintf (tbuf2, "killed %s!", db[victim].name);
        do_halt (victim, "");
        did_it (player, victim, "DEATH", tbuf1, "ODEATH", tbuf2, "ADEATH",
          NOTHING);

        /* notify victim */
        notify (victim, tprintf ("%s killed you!", db[player].name));

        /* maybe pay off the bonus */
        /* if we were not called via slay */
        if (!slay) {
          if (Pennies (db[victim].owner) < MAX_PENNIES) {
            notify (victim, tprintf ("Your insurance policy pays %d %s.",
                KILL_BONUS, ((KILL_BONUS == 1) ? MONEY : MONIES)));
            giveto (db[victim].owner, KILL_BONUS);
          } else {
            notify (victim, "Your insurance policy has been revoked.");
          }
        }
        /* send him home */
        safe_tel (victim, HOME);
        /* if victim is object also dequeue all commands */
      } else {
        /* notify player and victim only */
        notify (player, "Your murder attempt failed.");
        notify (victim, tprintf ("%s tried to kill you!", db[player].name));
      }
      break;
    }
  }
}

void do_give (dbref player, char *recipient, char *amnt)
{
  dbref who;
  int amount;
  char *s;
  char tbuf1[BUFFER_LEN];

  /* check recipient */
  init_match (player, recipient, TYPE_PLAYER);
  match_neighbor ();
  match_me ();
  if (Wizard (player)) {
    match_player ();
    match_absolute ();
  }
  switch (who = match_result ()) {
  case NOTHING:
    notify (player, "Give to whom?");
    return;
  case AMBIGUOUS:
    notify (player, "I don't know who you mean!");
    return;
  }

  /* make sure amount is all digits */
  for (s = amnt; *s && ((isdigit ((int)*s)) || (*s == '-')); s++);
  /* must be giving object */
  if (*s) {
    dbref thing;
    init_match (player, amnt, TYPE_THING);
    match_possession ();
    match_me ();
    switch (thing = match_result ()) {
    case NOTHING:
      notify (player, "You don't have that!");
      return;
    case AMBIGUOUS:
      notify (player, "I don't know which you mean!");
      return;
    default:
      if (((Typeof (thing) == TYPE_THING) || (Typeof (thing) == TYPE_PLAYER))
        && ((db[who].flags & ENTER_OK) || controls (player, who))) {
        moveto (thing, who);
        notify (who,
          tprintf ("%s gave you %s.", db[player].name, db[thing].name));
        notify (player, "Given.");
        notify (thing, tprintf ("%s gave you to %s.", db[player].name,
            db[who].name));
        did_it (who, thing, "SUCCESS", NULL, "OSUCCES", NULL, "ASUCCSS",
          NOTHING);
      } else
        notify (player, "Permission denied.");
    }
    return;
  }
  amount = atoi (amnt);
  /* do amount consistency check */
  if (amount < 0 && !Wizard (player)) {
    notify (player, "Try using the \"rob\" command.");
    return;
  } else if (amount == 0) {
    notify (player, tprintf ("You must specify a positive number of %s.",
        MONIES));
    return;
  }
  if (!Wizard (player)) {
    if (Pennies (who) + amount > MAX_PENNIES) {
      notify (player, tprintf ("That player doesn't need that many %s!",
          MONIES));
      return;
    }
  }
  /* try to do the give */
  if (!payfor (player, amount)) {
    notify (player, tprintf ("You don't have that many %s to give!", MONIES));
  } else {
    /* objects work differently */
    if (Typeof (who) == TYPE_THING) {
      int cost = 0;
      ATTR *a;
      a = atr_get (who, "COST");
      if (a && (amount < (cost = atoi (uncompress (a->value))))) {
        notify (player, "Feeling poor today?");
        giveto (player, amount);
        return;
      }
      if (cost < 0)
        return;
      if ((amount - cost) > 0) {
        sprintf (tbuf1, "You get %d in change.", amount - cost);
      } else {
        sprintf (tbuf1, "You paid %d %s.", amount,
          ((amount == 1) ? MONEY : MONIES));
      }
      notify (player, tbuf1);
      giveto (player, amount - cost);
      giveto (who, cost);
      did_it (player, who, "PAYMENT", NULL, "OPAYMENT", NULL, "APAYMENT",
        NOTHING);
      return;
    } else {
      /* he can do it */
      if (amount > 0) {
        notify (player,
          tprintf ("You give %d %s to %s.", amount,
            ((amount == 1) ? MONEY : MONIES), db[who].name));
      } else {
        notify (player, tprintf ("You took %d %s from %s!", abs (amount),
            ((abs (amount) == 1) ? MONEY : MONIES), db[who].name));
      }
      if (Typeof (who) == TYPE_PLAYER) {
        if (amount > 0) {
          notify (who, tprintf ("%s gives you %d %s.", db[player].name,
              amount, ((amount == 1) ? MONEY : MONIES)));
        } else {
          notify (who, tprintf ("%s took %d %s from you!", db[player].name,
              abs (amount), ((abs (amount) == 1) ? MONEY : MONIES)));
        }
      }
      giveto (who, amount);
      did_it (player, who, "PAYMENT", NULL, "OPAYMENT", NULL, "APAYMENT",
        NOTHING);
    }
  }
}