AwakeMUD-0.51Beta/area/
AwakeMUD-0.51Beta/doc/
AwakeMUD-0.51Beta/lib/
AwakeMUD-0.51Beta/lib/etc/
AwakeMUD-0.51Beta/lib/fixer_data/
AwakeMUD-0.51Beta/lib/misc/
AwakeMUD-0.51Beta/lib/plrobjs/
AwakeMUD-0.51Beta/lib/plrobjs/A-E/
AwakeMUD-0.51Beta/lib/plrobjs/K-O/
AwakeMUD-0.51Beta/lib/plrobjs/U-Z/
AwakeMUD-0.51Beta/lib/plrspells/A-E/
AwakeMUD-0.51Beta/lib/plrtext/A-E/
AwakeMUD-0.51Beta/lib/world/
AwakeMUD-0.51Beta/lib/world/mob/
AwakeMUD-0.51Beta/lib/world/obj/
AwakeMUD-0.51Beta/lib/world/qst/
AwakeMUD-0.51Beta/lib/world/shp/
AwakeMUD-0.51Beta/lib/world/wld/
AwakeMUD-0.51Beta/lib/world/zon/
/* ***********************************************************************
*             Those wonderful cyberspace routines go here.               *
*            written by Christopher J. Dickey, Rift, et al.              *
*    matrix.cc   (c) 1995 Christopher J. Dickey, (c)1997-1999 Andrew     *
*               Hynek, (c)2001 The AwakeMUD Consortium                   *
*********************************************************************** */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "structs.h"
#include "awake.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "screen.h"
#include "boards.h"

int matrix_combat_util(struct char_data * ch, struct char_data * vict,
                       struct obj_data *program);
int execution_test(struct char_data *persona, struct obj_data *program,
                   struct char_data *vict);
int find_node_required(struct char_data *persona);
void matrix_fight(struct char_data *ch, struct char_data *victim);
void sleaze_ic(struct char_data *persona, struct obj_data *program);
void do_ic_response(struct char_data *ic, struct char_data *persona);
void deceive_ic(struct char_data *persona, struct obj_data *program, struct char_data *ic);
void check_trace(struct char_data *ic);
int check_shield(struct char_data *persona, int dam);
int find_smoke(struct char_data *persona);

/* extern vars */
extern int dice(int number, int size);
extern int is_blocker(struct char_data *ic);
extern int reverse_web(struct char_data *ch, int &skill, int &target);
extern struct room_data *world;
extern struct index_data *obj_index;
extern struct index_data *mob_index;
extern struct descriptor_data *descriptor_list;
extern struct zone_data *zone_table;
extern struct char_data *character_list;

extern void obj_to_cyberware(struct obj_data * object, struct char_data * ch);
extern void obj_from_cyberware(struct obj_data * cyber);
extern void look_at_room(struct char_data * ch, int ignore_brief);
extern void update_pos(struct char_data * victim);
extern void dam_message(int dam, struct char_data * ch, struct char_data *victim, int w_type);
extern int calc_karma(struct char_data *ch, struct char_data *vict);
extern void appear(struct char_data * ch);
extern void die(struct char_data * ch);
extern void set_attacking(struct char_data *ch, struct char_data *vict,
                          const char *file, int line);
extern void hunt_victim(struct char_data * ch);
extern void docwagon(struct char_data *ch);
extern void remember(struct char_data * ch, struct char_data * victim);

/*  Well, here it goes, the way to get into the matrix     --cjd    */

#define PERSONA         20

struct obj_data *get_program(struct obj_data *cyberdeck, int type)
{
  struct obj_data *prog;

  for (prog = cyberdeck->contains; prog; prog = prog->next_content)
    if (GET_OBJ_TYPE(prog) == ITEM_PROGRAM && GET_OBJ_VAL(prog, 0) == type)
      return prog;

  return NULL;
}

struct obj_data *create_matrix_item(struct obj_data * prog)
{
  struct obj_data *obj;

  if (GET_OBJ_TYPE(prog) == ITEM_DECK_ACCESSORY && GET_OBJ_VAL(prog, 0) == TYPE_FILE) {
    obj = read_object(prog->item_number, REAL);
    GET_OBJ_WEAR(obj) = ITEM_WEAR_TAKE;
    return obj;
  }

   if ((GET_PROG_TYPE(prog) == PROG_BOD) || (GET_PROG_TYPE(prog) == PROG_EVASION) ||
      (GET_PROG_TYPE(prog) == PROG_MASKING) || (GET_PROG_TYPE(prog) == PROG_SENSOR))
     return NULL;

   obj = read_object(prog->item_number, REAL);
   return obj;
}


void create_persona(struct char_data * ch, struct char_data * persona,
                    struct obj_data *cyberdeck)
{
  struct obj_data *program, *obj;
  bool have_deck = TRUE;

  if (cyberdeck == NULL) {
     send_to_char("You must either be a great hacker or insane to jack into the net without\r\na cyberdeck!\r\n", ch);
     have_deck = FALSE;
  }

  /* the basic modifications for the persona go below */
  if (have_deck) {
    persona->real_abils.wil = GET_OBJ_VAL(cyberdeck, 0);
    GET_WIL(persona) = GET_OBJ_VAL(cyberdeck, 0);
    GET_BALLISTIC(persona) = GET_OBJ_VAL(cyberdeck, 1);
    GET_ACTIVE(persona) = MIN(30000, GET_OBJ_VAL(cyberdeck, 2));
    GET_STORAGE(persona) = MIN(30000, GET_OBJ_VAL(cyberdeck, 3));
    GET_LOAD_SPEED(persona) = MIN(30000, GET_OBJ_VAL(cyberdeck, 4));
    GET_IO_SPEED(persona) = MIN(30000, GET_OBJ_RENT(cyberdeck));

    /* next the persona programs are loaded and the persona is modified */
    program = get_program(cyberdeck, PROG_BOD);
    if (program) {
      persona->real_abils.bod = GET_PROG_RATING(program);
      GET_BOD(persona) = GET_PROG_RATING(program);
    } else {
      persona->real_abils.bod = 1;
      GET_BOD(persona) = 1;
    }
    program = get_program(cyberdeck, PROG_EVASION);
    if (program) {
      persona->real_abils.qui = GET_PROG_RATING(program);
      GET_QUI(persona) = GET_PROG_RATING(program);
    } else {
      persona->real_abils.qui = 1;
      GET_QUI(persona) = 1;
    }
    program = get_program(cyberdeck, PROG_MASKING);
    if (program) {
      persona->real_abils.cha = GET_PROG_RATING(program);
      GET_CHA(persona) = GET_PROG_RATING(program);
    } else {
      persona->real_abils.cha = 1;
      GET_CHA(persona) = 1;
    }
    program = get_program(cyberdeck, PROG_SENSOR);
    if (program) {
      persona->real_abils.intel = GET_PROG_RATING(program);
      GET_INT(persona) = GET_PROG_RATING(program);
    } else {
      persona->real_abils.intel = 1;
      GET_INT(persona) = 1;
    }

   /* here's the fun part, programs are loaded as useable items in the matrix */
    for (program = cyberdeck->contains; program; program = program->next_content) {
      if (GET_OBJ_TYPE(program) == ITEM_DECK_ACCESSORY &&
          GET_OBJ_VAL(program, 0) == TYPE_UPGRADE &&
          GET_OBJ_VAL(program, 1) == 5) {
        switch(GET_OBJ_VAL(program, 2)) {
          case 1:
            persona->real_abils.rea = 2;
            GET_REA(persona) = persona->real_abils.rea;
            GET_INIT_DICE(persona) = 1;
            break;
          case 2:
            persona->real_abils.rea = 4;
            GET_REA(persona) = persona->real_abils.rea;
            GET_INIT_DICE(persona) = 2;
            break;
          case 3:
            persona->real_abils.rea = 6;
            GET_REA(persona) = persona->real_abils.rea;
            GET_INIT_DICE(persona) = 3;
            break;
         }
       } else {
         obj = create_matrix_item(program);
         if (obj) {
            obj_to_char(obj, persona);
            if (GET_OBJ_TYPE(obj) == ITEM_PROGRAM)
              GET_STORAGE(persona) -= GET_OBJ_VAL(obj, 2);
            if (GET_OBJ_TYPE(obj) == ITEM_DECK_ACCESSORY && GET_OBJ_VAL(obj, 0) == TYPE_FILE)
              GET_STORAGE(persona) -= GET_OBJ_VAL(obj, 1);
         }
       }
    }
  } else {
    GET_WIL(persona) = GET_WIL(ch);
    GET_BALLISTIC(persona) = 0;
    GET_IO_SPEED(persona) = GET_INT(ch);
  }
  GET_HACKING(persona) = GET_HACKING(ch);
  GET_SKILL(persona,SKILL_COMPUTER) = GET_SKILL(ch,SKILL_COMPUTER);
}

ACMD(do_connect)
{
  struct char_data *persona, *temp;
  struct obj_data *cyber, *obj, *cyberdeck = NULL;
  int r_num, i;
  bool has_datajack = FALSE;

  one_argument(argument, arg);

  if (IS_PERSONA(ch)) {
    send_to_char("You're already connected.\r\n", ch);
    return;
  } else if (ch->desc->original) {
    send_to_char("You can't connect now.\r\n", ch);
    return;
  } else if (IS_NPC(ch)) {
    send_to_char("That won't work, for some reason.\r\n", ch);
    return;
  }

  if (!EXIT(ch, MATRIX) || EXIT(ch, MATRIX)->to_room < 1) {
    send_to_char("You cannot connect to the matrix from here.\r\n", ch);
    return;
  }

 for (temp = world[ch->in_room].people; temp; temp = temp->next_in_room)
   if (temp != ch && PLR_FLAGGED(temp, PLR_MATRIX)) {
     send_to_char("The terminal is already in use.\r\n", ch);
     return;
   }

  for (cyber = ch->cyberware; cyber; cyber = cyber->next_content)
    if (GET_OBJ_VAL(cyber, 2) == CYB_DATAJACK)
      has_datajack = TRUE;

  if (!has_datajack && !access_level(ch, LVL_PRESIDENT)) {
    send_to_char("You need at least a datajack to connect to the matrix.\r\n", ch);
    return;
  }

  for (obj = ch->carrying; obj; obj = obj->next_content)
    if (GET_OBJ_TYPE(obj) == ITEM_CYBERDECK)
      cyberdeck = obj;

  for (i = WEAR_LIGHT; !cyberdeck && i < NUM_WEARS; i++)
    if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_CYBERDECK)
      cyberdeck = GET_EQ(ch, i);

  if (cyberdeck && GET_OBJ_VAL(cyberdeck, 0) == 0) {
    send_to_char("You cannot connect to the Matrix with fried MPCP chips!\r\n", ch);
    return;
  }

  if (cyberdeck && IS_OBJ_STAT(cyberdeck, ITEM_GODONLY) && GET_LEVEL(ch) < LVL_LEGEND) {
    act("You do not understand how to operate $p.", FALSE, ch, cyberdeck, 0, TO_CHAR);
    return;
  }

  if ((r_num = real_mobile(PERSONA)) < 0) {
    log("No persona mob for matrix");
    send_to_char("The matrix seems to be out of order right now.\r\n", ch);
    return;
  }

  if (zone_table[world[EXIT(ch, MATRIX)->to_room].zone].alert > 2) {
    send_to_char("It seems like that system has been shut down...\r\n", ch);
    return;
  } else if (zone_table[world[EXIT(ch, MATRIX)->to_room].zone].number == 31) {
    sprintf(buf, "%s connected to MCN (#%d) from #%d", GET_NAME(ch),
            EXIT(ch, MATRIX)->to_room_vnum, world[ch->in_room].number);
    mudlog(buf, ch, LOG_MISCLOG, TRUE);
  }

  GET_POS(ch) = POS_SITTING;

  if (!ch->player.mname)
    ch->player.mname = str_dup("persona");
  if (!ch->player.msdesc)
    ch->player.msdesc = str_dup("a persona");
  if (!ch->player.mdesc)
    ch->player.mdesc = str_dup("A nondescript persona stands idly here.\r\n");

  persona = read_mobile(r_num, REAL);
  char_to_room(persona, EXIT(ch, MATRIX)->to_room);
  create_persona(ch, persona, cyberdeck);

  persona->player.name = ch->player.mname;
  persona->player.short_descr = ch->player.msdesc;
  persona->player.long_descr = ch->player.mdesc;
  persona->player.description = ch->player.mldesc;

  ch->desc->character = persona;
  ch->desc->original = ch;

  persona->desc = ch->desc;
  ch->desc = NULL;

  act("$n jacks into the Net.", TRUE, ch, 0, 0, TO_ROOM);
  act("You jack into the Net.", FALSE, persona, 0, 0, TO_CHAR);
  act("$n slowly pixellizes into view.", TRUE, persona, 0, 0, TO_ROOM);

  SET_BIT(PLR_FLAGS(ch), PLR_MATRIX);
  look_at_room(persona, 1);
}

ACMD(do_disconnect)
{
  int i, success, stun;
  struct obj_data *obj, *deck = NULL, *o;
  struct char_data *temp;

  if (IS_PERSONA(ch)) {
    if (FIGHTING(ch) && GET_RACE(FIGHTING(ch)) == CLASS_BLACK && subcmd != SCMD_MORTED) {
      success = success_test(GET_WIL(ch->desc->original), GET_LEVEL(FIGHTING(ch)) +
        (zone_table[world[ch->in_room].zone].alert > 0 ? (GET_LEVEL(FIGHTING(ch)) / 2) : 0));
      if (success < 1) {
        send_to_char("You fail to escape!\r\n", ch);
        return;
      }
      stun = convert_damage(stage(4 - success_test(GET_BOD(ch->desc->original), 4), MODERATE));
      GET_MENTAL(ch->desc->original) -= stun * 100;
      update_pos(ch->desc->original);
    }

    act("$n depixellizes.", FALSE, ch, 0, 0, TO_ROOM);

    /* extract objects, if any */
    while (ch->carrying) {
      obj = ch->carrying;
      obj_from_char(obj);
      if (GET_OBJ_TYPE(obj) == ITEM_DECK_ACCESSORY && GET_OBJ_VAL(obj, 0) == TYPE_FILE) {
        for (o = ch->desc->original->carrying; o; o = o->next_content)
          if (GET_OBJ_TYPE(o) == ITEM_CYBERDECK)
            deck = o;
        for (i = WEAR_LIGHT; !deck && i < NUM_WEARS; i++)
          if (GET_EQ(ch->desc->original, i) && GET_OBJ_TYPE(GET_EQ(ch->desc->original, i)) == ITEM_CYBERDECK)
            deck = GET_EQ(ch->desc->original, i);
        obj_to_obj(obj, deck);
        GET_OBJ_VAL(deck, 5) += GET_OBJ_VAL(obj, 1);
      } else extract_obj(obj);
    }

    /* extract all cyberware */
    while (ch->cyberware) {
      obj = ch->cyberware;
      obj_from_cyberware(obj);
      extract_obj(obj);
    }

    /* extract equipment, if any */
    for (i = 0; i < NUM_WEARS; i++)
      if (ch->equipment[i])
        extract_obj(unequip_char(ch, i));

    REMOVE_BIT(PLR_FLAGS(ch->desc->original), PLR_MATRIX);
    send_to_char("You feel disoriented as you jack out of the Net.\r\n", ch);
    WAIT_STATE(ch, PULSE_VIOLENCE);

    if (ch->desc->original->desc)
      close_socket(ch->desc->original->desc);

    temp = ch;
    ch->desc->character = ch->desc->original;
    ch->desc->original = NULL;

    ch->desc->character->desc = ch->desc;
    ch->desc = NULL;

    extract_char(temp);
  }
}

ACMD(do_software)
{
  int i = 0, found = 0, mode;
  struct obj_data *obj, *temp;

  skip_spaces(&argument);
  if (!IS_PERSONA(ch)) {
    any_one_arg(argument, arg);
    if (!*arg) {
      send_to_char("List what's software?\r\n", ch);
      return;
    }
    if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying)))
      if (!(obj = get_object_in_equip_vis(ch, arg, ch->equipment, &i))) {
        send_to_char(ch, "You don't seem to have a '%s'.\r\n", arg);
        return;
      }
    act("$p contains:", FALSE, ch, obj, 0, TO_CHAR);
    for (temp = obj->contains; temp; temp = temp->next_content) {
      act("  $p", FALSE, ch, temp, 0, TO_CHAR);
      found = 1;
    }
    if (!found)
      send_to_char("  Nothing.\r\n", ch);
    return;
  }

  if (!*argument || is_abbrev(argument, "all"))
    mode = 1;
  else if (is_abbrev(argument, "programs"))
    mode = 2;
  else if (is_abbrev(argument, "loaded"))
    mode = 3;
  else if (is_abbrev(argument, "files"))
    mode = 4;
  else if (is_abbrev(argument, "idle"))
    mode = 5;
  else {
    send_to_char("Usage: software <all/programs/loaded/files/idle>\r\n", ch);
    return;
  }

  if (mode == 4 || mode == 1) {
    found = 0;
    send_to_char("Data files:\r\n", ch);
    for (obj = ch->carrying; obj; obj = obj->next_content)
      if (GET_OBJ_TYPE(obj) == ITEM_DECK_ACCESSORY && GET_OBJ_VAL(obj, 0) == TYPE_FILE) {
        found = 1;
        sprintf(buf, "  %-25s\r\n", obj->short_description);
        send_to_char(buf, ch);
      }
    if (!found)
      send_to_char("  None.\r\n", ch);
    if (is_abbrev(argument, "all"))
      send_to_char("\r\n", ch);
  }

  if (mode == 2 || mode == 5 || mode == 1) {
    found = 0;
    send_to_char("Idle programs:\r\n", ch);
    for (obj = ch->carrying; obj; obj = obj->next_content)
      if (GET_OBJ_TYPE(obj) == ITEM_PROGRAM) {
        found = 1;
        sprintf(buf, "  %-25s\r\n", obj->short_description);
        send_to_char(buf, ch);
      }
    if (!found)
      send_to_char("  None.\r\n", ch);
    if (is_abbrev(argument, "programs") || is_abbrev(argument, "all"))
      send_to_char("\r\n", ch);
  }

  if (mode == 2 || mode == 3 || mode == 1) {
    found = 0;
    send_to_char("Loaded programs:\r\n", ch);
    for (i = 0; i < NUM_WEARS; i++) {
      if (GET_EQ(ch, i)) {
        sprintf(buf, "  %-25s  %s\r\n", GET_EQ(ch, i)->short_description,
          (GET_OBJ_VAL(GET_EQ(ch, i), 9) ? "(running)" : ""));
        found = 1;
        send_to_char(buf, ch);
      }
    }
    if (!found)
      sprintf(buf, "  None.\r\n");
  }
}

struct obj_data *loaded_programs(struct char_data *ch, char *arg,
                                 struct obj_data *equipment[])
{
  int i;

  for (i = 0; i < NUM_WEARS; i++)
    if (equipment[i])
      if (CAN_SEE_OBJ(ch, equipment[i]))
        if (isname(arg, equipment[i]->name))
          return (equipment[i]);

  return NULL;
}

ACMD(do_run)
{
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  extern struct index_data *mob_index;
  struct char_data *vict = NULL;
  struct obj_data *prog, *obj, *o = NULL;
  int resist, success, i, pool;

  if (!IS_PERSONA(ch)) {
    send_to_char("But you aren't connected to the Matrix?!\r\n", ch);
    return;
  }

  two_arguments(argument, arg1, arg2);

  if (!*arg1) {
    send_to_char("Run what?\r\n", ch);
    return;
  }

  prog = loaded_programs(ch, arg1, ch->equipment);

  if (!prog) {
    send_to_char("You don't seem to have anything like that loaded.\r\n", ch);
    return;
  }

  switch (GET_PROG_TYPE(prog)) {
    case PROG_ATTACK:
      if (!*arg2) {
        send_to_char("Destroy what?\r\n", ch);
        return;
      }
      if (!(vict = get_char_room_vis(ch, arg2)) ||
          ((vict = get_char_room_vis(ch, arg2)) && IS_NPC(vict) &&
          (GET_RACE(vict) > CLASS_SCRAMBLE && !is_blocker(vict) &&
          zone_table[world[ch->in_room].zone].alert < 2)))
        send_to_char("They don't seem to be here.\r\n", ch);
      else if (vict == ch) {
        send_to_char("You hit yourself...OUCH!.\r\n", ch);
        act("$n hits $mself, and says OUCH!", FALSE, ch, 0, vict, TO_ROOM);
      } else if ((GET_POS(ch) == POS_STANDING) && (vict != FIGHTING(ch))) {
        set_fighting(ch, vict);
        GET_INIT_ROLL(ch) = MIN(28, (dice(1 + GET_INIT_DICE(ch), 6) + GET_REA(ch)));
        if (!FIGHTING(vict)) {
          if (IS_IC(vict))
            GET_INIT_ROLL(vict) = GET_LEVEL(ch) + (zone_table[world[vict->in_room].zone].alert > 0 ? (GET_LEVEL(vict) / 2) : 0);
          else GET_INIT_ROLL(vict) = MIN(28, (dice(1 + GET_INIT_DICE(vict), 6) + GET_REA(vict)));
        }
        matrix_fight(ch, vict);
        GET_OBJ_VAL(prog, 9) = 1;
        GET_INIT_ROLL(ch) -= 10;
        WAIT_STATE(ch, PULSE_VIOLENCE + 2);
      } else send_to_char("You do the best you can!\r\n", ch);
      break;
    case PROG_SLOW:
      if (!*arg2) {
        if (!FIGHTING(ch)) {
          send_to_char("What do you want to slow?\r\n", ch);
          return;
        } else vict = FIGHTING(ch);
      } else if (!FIGHTING(ch)) {
        vict = get_char_room_vis(ch, arg2);
        if (!vict || (vict && IS_NPC(vict) && !is_blocker(vict) &&
            GET_RACE(vict) > CLASS_SCRAMBLE &&
            zone_table[world[ch->in_room].zone].alert < 2)) {
          send_to_char("They don't seem to be here.\r\n", ch);
          return;
        }
      } else {
        send_to_char("You can't focus on that right now.\r\n", ch);
        return;
      }
      if (!IS_IC(vict)) {
        send_to_char("You can only slow ICs.\r\n", ch);
        return;
      }
      if (!execution_test(ch, GET_EQ(ch, WEAR_FEET), vict)) {
        act("$p fails to execute!", FALSE, ch, GET_EQ(ch, WEAR_FEET), 0, TO_CHAR);
        return;
      }
      if ((success = matrix_combat_util(ch, vict, GET_EQ(ch, WEAR_FEET))) < 1) {
        send_to_char(ch, "%s seems to have no effect.\r\n",
                     CAP(GET_EQ(ch, WEAR_FEET)->short_description));
        return;
      }
      if (!FIGHTING(vict)) {
        switch(world[vict->in_room].sector_type) {
          case SECT_GREEN:
            GET_INIT_ROLL(vict) = 5 + GET_LEVEL(vict) +
              (zone_table[world[vict->in_room].zone].alert > 0 ? (GET_LEVEL(vict) / 2) : 0);
            break;
          case SECT_ORANGE:
            GET_INIT_ROLL(vict) = 7 + GET_LEVEL(vict) +
              (zone_table[world[vict->in_room].zone].alert > 0 ? (GET_LEVEL(vict) / 2) : 0);
            break;
          case SECT_RED:
            GET_INIT_ROLL(vict) = 9 + GET_LEVEL(vict) +
              (zone_table[world[vict->in_room].zone].alert > 0 ? (GET_LEVEL(vict) / 2) : 0);
            break;
          case SECT_BLACK:
            GET_INIT_ROLL(vict) = 10 + GET_LEVEL(vict) +
              (zone_table[world[vict->in_room].zone].alert > 0 ? (GET_LEVEL(vict) / 2) : 0);
            break;
          default:
            GET_INIT_ROLL(vict) = 0;
            break;
        }
        set_fighting(vict, ch);
      }
      GET_INIT_ROLL(vict) -= GET_OBJ_VAL(prog, 1);
      if (!AFF_FLAGGED(vict, AFF_COUNTER_ATT))
        SET_BIT(AFF_FLAGS(vict), AFF_COUNTER_ATT);
      if (GET_INIT_ROLL(vict) < 1) {
        act("$n freezes and shatters into minute slivers.", FALSE, vict, 0, 0, TO_ROOM);
        for (i = 0; i < NUM_WEARS; i++)
          if (vict->equipment[i])
            extract_obj(vict->equipment[i]);
        for (obj = vict->carrying; obj; obj = obj->next_content) {
          o = obj->next_content;
          extract_obj(obj);
        }
        extract_char(vict);
      }
      break;
    case PROG_DECRYPT:
      if (FIGHTING(ch)) {
        send_to_char("You can't use that program while fighting.\r\n", ch);
        return;
      }
      if (!*arg2) {
        send_to_char("Who do you want to decrypt?\r\n", ch);
        return;
      }
      vict = get_char_room_vis(ch, arg2);
      if (!vict || (vict && IS_NPC(vict) && GET_RACE(vict) > CLASS_SCRAMBLE &&
          !is_blocker(vict) && zone_table[world[ch->in_room].zone].alert < 2)) {
        send_to_char("They don't seem to be here.\r\n", ch);
        return;
      }
      if (!IS_IC(vict) || (IS_IC(vict) && GET_RACE(vict) != CLASS_SCRAMBLE)) {
        send_to_char("You can only decrypt scramble ICs.\r\n", ch);
        return;
      }
      if (!execution_test(ch, prog, vict)) {
        act("You fail to execute $p!", FALSE, ch, prog, 0, TO_CHAR);
        do_ic_response(vict, ch);
      } else {
        pool = MIN((GET_HACKING(ch)), GET_PROG_RATING(prog));
        success = success_test(GET_PROG_RATING(prog) + pool, GET_SECURITY(ch));
        if (success < find_node_required(ch)) {
          act("You feel the node absorb $p's effects!", FALSE, ch, prog, 0, TO_CHAR);
          do_ic_response(vict, ch);
        } else {
          success -= success_test(GET_LEVEL(vict) + (zone_table[world[vict->in_room].zone].alert > 0 ?
                                 (GET_LEVEL(vict) / 2) : 0), GET_QUI(ch));
          if (success <= 0) {
            act("$N resists the effects of $p!", FALSE, ch, prog, vict, TO_CHAR);
            act("You resist $n's feeble attempt to decrypt you!", FALSE, ch, 0, vict, TO_VICT);
            do_ic_response(vict, ch);
            return;
          }
          act("$n dissolves into nothing.", FALSE, vict, 0, 0, TO_ROOM);
          act("You feel yourself eaten away bit by bit.", FALSE, ch, 0, vict, TO_VICT);
          for (i = 0; i < NUM_WEARS; i++)
            if (vict->equipment[i])
              extract_obj(vict->equipment[i]);
          for (obj = vict->carrying; o; obj = o) {
            o = obj->next_content;
            extract_obj(obj);
          }
          extract_char(vict);
        }
      }
      break;
    case PROG_MIRRORS:
    case PROG_SHIELD:
      if (GET_OBJ_VAL(prog, 9)) {
        act("$p is already running, it seems.", FALSE, ch, prog, 0, TO_CHAR);
        return;
      }
      act("$n activates $p.", TRUE, ch, prog, 0, TO_ROOM);
      act("You activate $p.", FALSE, ch, prog, 0, TO_CHAR);
      GET_OBJ_VAL(prog, 9) = GET_OBJ_VAL(prog, 1);
      if (GET_PROG_TYPE(prog) == PROG_MIRRORS)
        GET_QUI(ch) += GET_OBJ_VAL(prog, 1);
      if (FIGHTING(ch))
        stop_fighting(ch);
      break;
    case PROG_MEDIC:
      if (!GET_OBJ_VAL(prog, 1)) {
        sprintf(buf, "%s has degraded beyond use.\r\n", CAP(prog->short_description));
        send_to_char(buf, ch);
        return;
      }
      if (GET_PHYSICAL(ch) < 500)
        resist = 6;
      else if (GET_PHYSICAL(ch) < 800)
        resist = 5;
      else resist = 4;
      success = success_test(GET_OBJ_VAL(prog, 1), resist);
      GET_OBJ_VAL(prog, 1)--;
      if (success > 0) {
        GET_PHYSICAL(ch) += success * 100;
        if (GET_PHYSICAL(ch) > GET_MAX_PHYSICAL(ch))
          GET_PHYSICAL(ch) = GET_MAX_PHYSICAL(ch);
        act("You feel repaired!", FALSE, ch, 0, 0, TO_CHAR);
        act("$n runs $p and appears better.", TRUE, ch, prog, 0, TO_ROOM);
      } else act("$p can't seem to repair any damage.", FALSE, ch, prog, 0, TO_CHAR);
      break;
    case PROG_DECEPTION:
      if (FIGHTING(ch)) {
        send_to_char("You can't run that program while fighting.\r\n", ch);
        return;
      }
      if (zone_table[world[ch->in_room].zone].alert == 2) {
        send_to_char("You cannot deceive any ICs during an active alert.\r\n", ch);
        return;
      }
      if (!*arg2) {
        send_to_char("Deceive what?\r\n", ch);
        return;
      }
      if (!(vict = get_char_room_vis(ch, arg2)) ||
          ((vict = get_char_room_vis(ch, arg2)) && IS_NPC(vict) &&
          GET_RACE(vict) > CLASS_SCRAMBLE && !is_blocker(vict) &&
          zone_table[world[ch->in_room].zone].alert < 2))
        send_to_char("They don't seem to be here.\r\n", ch);
      else if (vict == ch)
        send_to_char("Try as hard as you might, you can't deceive yourself.\r\n", ch);
      else if (!IS_IC(vict))
        send_to_char("You can only deceive ICs.\r\n", ch);
      else deceive_ic(ch, prog, vict);
      break;
    case PROG_SLEAZE:
      if (GET_OBJ_VAL(prog, 9))
        act("$p is already running, it seems.", FALSE, ch, prog, 0, TO_CHAR);
      else if (FIGHTING(ch))
        act("You can't run $p while fighting.", FALSE, ch, prog, 0, TO_CHAR);
      else sleaze_ic(ch, prog);
      break;
    case PROG_SMOKE:
      if (find_smoke(ch))
        act("Smoke a smoked room?", FALSE, ch, 0, 0, TO_CHAR);
      else {
        GET_OBJ_VAL(prog, 9) = GET_OBJ_VAL(prog, 1);
        send_to_room("Smoke suddenly rises in the node!\r\n", ch->in_room);
        if (FIGHTING(ch)) {
          stop_fighting(FIGHTING(ch));
          stop_fighting(ch);
        }
      }
      break;
    default:
      send_to_char("That program type has yet to be implemented.\r\n", ch);
      break;
  }
  return;
}

void do_ic_response(struct char_data *ic, struct char_data *persona)
{
  struct obj_data *obj, *next_obj = NULL;

  switch(GET_RACE(ic)) {
    case CLASS_ACCESS:
    case CLASS_BARRIER:
      if (!number(0, 2))
        return;
      if (!zone_table[world[ic->in_room].zone].alert) {
        act("Yellow lights begin to flash throughout the system!", FALSE, ic, 0, 0, TO_ROOM);
        act("You succeed in declaring a passive alert.", FALSE, ic, 0, 0, TO_CHAR);
        zone_table[world[ic->in_room].zone].alert = 1;
      } else if (zone_table[world[ic->in_room].zone].alert == 1 && !AFF_FLAGGED(ic, AFF_COUNTER_ATT) && !number(0,1)) {
        act("The yellow lights become red, and sirens join in the cacophony!", FALSE, ic, 0, 0, TO_ROOM);
        act("You succeed in changing the passive alert to active.", FALSE, ic, 0, 0, TO_CHAR);
        zone_table[world[ic->in_room].zone].alert = 2;
      }
      break;
    case CLASS_SCRAMBLE:
      if (AFF_FLAGGED(ic, AFF_COUNTER_ATT) || (GET_EQ(persona, WEAR_WAIST) &&
          GET_OBJ_VAL(GET_EQ(persona, WEAR_WAIST), 9)))
        return;
      act("$n glows brighter and emits a high-pitched sound!", FALSE, ic, 0, 0, TO_ROOM);
      act("You glow brighter and emit a high-pitched sound!", FALSE, ic, 0, 0, TO_CHAR);
      for (obj = world[ic->in_room].contents; obj; obj = next_obj) {
        next_obj = obj->next_content;
        if (GET_OBJ_TYPE(obj) == ITEM_DECK_ACCESSORY && GET_OBJ_VAL(obj, 0) == TYPE_FILE) {
          act("$p has been deleted!", FALSE, ic, obj, 0, TO_ROOM);
          act("$p has been deleted!", FALSE, ic, obj, 0, TO_CHAR);
          extract_obj(obj);
        }
      }
      break;
    case CLASS_KILLER:
    case CLASS_BLASTER:
    case CLASS_BLACK:
      matrix_fight(ic, persona);
      break;
    case CLASS_TAR_BABY:
    case CLASS_TAR_PIT:
      if (!FIGHTING(ic))
        set_fighting(ic, persona);
      if (!FIGHTING(persona))
        set_fighting(persona, ic);
      if (zone_table[world[ic->in_room].zone].alert != 2) {
        zone_table[world[ic->in_room].zone].alert = 2;
        act("Flashing red lights scan the node as sirens blare!", FALSE, ic, 0, 0, TO_ROOM);
        act("You set the system alert to active.", FALSE, ic, 0, 0, TO_CHAR);
      }
      break;
    case CLASS_TRACE_BURN:
    case CLASS_TRACE_REPORT:
    case CLASS_TRACE_DUMP:
      if (!FIGHTING(ic))
        set_fighting(ic, persona);
      if (!FIGHTING(persona))
        set_fighting(persona, ic);
      GET_MENTAL(ic) = 1000 - 100 * success_test((GET_LEVEL(ic) +
        (zone_table[world[ic->in_room].zone].alert > 0 ? (GET_LEVEL(ic) / 2) : 0)), GET_CHA(persona));
      if (GET_MENTAL(ic) < 0)
        GET_MENTAL(ic) = 0;
      break;
    default:
      break;
  }
  return;
}

int find_node_required(struct char_data *persona)
{
  if (world[persona->in_room].sector_type == SECT_BLUE)
    return 1;
  else if (world[persona->in_room].sector_type == SECT_GREEN)
    return 2;
  else if (world[persona->in_room].sector_type == SECT_ORANGE)
    return 3;
  else if (world[persona->in_room].sector_type == SECT_RED)
    return 4;
  else if (world[persona->in_room].sector_type == SECT_BLACK)
    return 4;

  return 0;
}

int find_smoke(struct char_data *persona)
{
  struct char_data *temp;

  for (temp = world[persona->in_room].people; temp; temp = temp->next_in_room)
    if (IS_PERSONA(temp) && GET_EQ(temp, WEAR_ARMS) &&
        GET_OBJ_VAL(GET_EQ(temp, WEAR_ARMS), 9))
      return(GET_OBJ_VAL(GET_EQ(temp, WEAR_ARMS), 9));

  return 0;
}

int execution_test(struct char_data *persona, struct obj_data *program,
                   struct char_data *vict)
{
  int rating, hacking_pool, targnum, char_success, vict_success, masking = 0;
  int victrating, victtarg;
  
  if (!IS_PERSONA(persona))
    return 1;
  else if (!program)
    {
      act( "Exec: No program.  Failed.", 1, persona, NULL, NULL, TO_ROLLS );
      return 0;
    }

  hacking_pool = MIN(GET_PROG_RATING(program), GET_HACKING(persona));

  if (GET_PROG_TYPE(program) == PROG_DECEPTION ||
      GET_PROG_TYPE(program) == PROG_SLEAZE)
    masking = 1;

  rating = GET_PROG_RATING(program) + hacking_pool;
  targnum = (vict ? GET_QUI(vict) : GET_SECURITY(persona))
           + find_smoke(persona);

  victrating = (vict ? GET_WIL(vict) : GET_SECURITY(persona));
  victtarg = (masking ? GET_CHA(persona) : GET_QUI(persona))
            + find_smoke(persona);

  char_success = success_test(rating, targnum);
  vict_success = success_test(victrating, victtarg);

  if(1)
    {
      char rbuf[MAX_STRING_LENGTH];
      sprintf(rbuf,"Exec: Rating %d+%d=%d, Targ %d%c+%d=%d.  VR %d%c, VT %d%c+%d=%d. %d-%d %d/%d",
	      GET_PROG_RATING(program), hacking_pool, rating,
	      (vict ? GET_QUI(vict) : GET_SECURITY(persona)),
	      (vict ? 'Q' : 'S'), find_smoke(persona), targnum,
	      victrating, (vict ? 'W' : 'S'),
	      masking ? GET_CHA(persona) : GET_QUI(persona),
	      masking ? 'C' : 'Q', find_smoke(persona), victtarg,
	      char_success, vict_success,
	      char_success,
	      masking ? 0 : find_node_required(persona));
      act( rbuf, 1, persona, NULL, NULL, TO_ROLLS );      
    }

  if (masking)
    return (char_success - vict_success);

  if (access_level(persona, LVL_OWNER))
    return 1;

  if (char_success < vict_success)
    return 0;

  if (char_success < find_node_required(persona))
    return 0;

  return 1;
}

void deceive_ic(struct char_data *persona, struct obj_data *program, struct char_data *ic)
{
  int success, i;
  struct obj_data *obj, *o = NULL;

  success = execution_test(persona, program, ic);
  if (success > 0) {
    if (success > find_node_required(persona) && (GET_RACE(ic) != CLASS_BARRIER && GET_RACE(ic) != CLASS_BLACK)) {
      act("You succeed in fooling $N.", FALSE, persona, 0, ic, TO_CHAR);
      return;
    } else act("Your attempt to fool $N fails.", FALSE, persona, 0, ic, TO_CHAR);
  }
  do_ic_response(ic, persona);
  if (!number(0, 2) && GET_EQ(persona, WEAR_WAIST) && (GET_RACE(ic) == CLASS_TAR_BABY ||
       GET_RACE(ic) == CLASS_TAR_PIT)) {
    switch(GET_RACE(ic)) {
      case CLASS_TAR_BABY:
        act("As you fail to deceive $N, $E knocks $p out of active memory!", FALSE, persona, GET_EQ(persona, WEAR_WIELD), ic, TO_CHAR);
        act("As $n fails to deceive you, you knock $p out of $s active memory!", FALSE, persona, GET_EQ(persona, WEAR_WIELD), ic, TO_VICT);
        GET_ACTIVE(persona) += GET_OBJ_VAL(GET_EQ(persona, WEAR_WAIST), 2);
        obj_to_char(unequip_char(persona, WEAR_WAIST), persona);
        break;
      case CLASS_TAR_PIT:
        act("As you fail to deceive $N, $E knocks $p out of online memory!", FALSE, persona, GET_EQ(persona, WEAR_WIELD), ic, TO_CHAR);
        act("As $n fails to deceive you, you knock $p out of $s online memory!", FALSE, persona, GET_EQ(persona, WEAR_WIELD), ic, TO_VICT);
        GET_ACTIVE(persona) += GET_OBJ_VAL(GET_EQ(persona, WEAR_WAIST), 2);
        extract_obj(unequip_char(persona, WEAR_WAIST));
        break;
    }
  }
}

void sleaze_ic(struct char_data *persona, struct obj_data *program)
{
  int success = 0, i;
  struct char_data *ic;
  struct obj_data *o, *obj;

  for (ic = world[persona->in_room].people; ic; ic = ic->next_in_room)
    if (IS_IC(ic)) {
      success = execution_test(persona, program, ic);
      if (success > 0) {
        if (success > find_node_required(persona)) {
          act("You feel your persona waver.", FALSE, persona, 0, ic, TO_CHAR);
          act("$n wavers slightly.", TRUE, persona, 0, ic, TO_NOTVICT);
          GET_OBJ_VAL(program, 9) = GET_OBJ_VAL(program, 1);
          return;
        } else {
          act("Nothing seems to happen.", FALSE, persona, 0, 0, TO_CHAR);
          return;
        }
      } else {
        switch(GET_RACE(ic)) {
          case CLASS_TAR_BABY:
          case CLASS_TAR_PIT:
            do_ic_response(ic, persona);
            if (!number(0, 2) && GET_EQ(persona, WEAR_HEAD))
              switch (GET_RACE(ic)) {
                case CLASS_TAR_BABY:
                  act("As you fail to fool $N, $E knocks $p out of active memory!", FALSE, persona, GET_EQ(persona, WEAR_WIELD), ic, TO_CHAR);
                  act("As $n fails to fool you, you knock $p out of $s active memory!", FALSE, persona, GET_EQ(persona, WEAR_WIELD), ic, TO_VICT);
                  GET_ACTIVE(persona) += GET_OBJ_VAL(GET_EQ(persona, WEAR_HEAD), 2);
                  obj_to_char(unequip_char(persona, WEAR_HEAD), persona);
                  break;
                case CLASS_TAR_PIT:
                  act("As you fail to damage $N, $E knocks $p out of online memory!", FALSE, persona, GET_EQ(persona, WEAR_WIELD), ic, TO_CHAR);
                  act("As $n fails to damage you, you knock $p out of $s online memory!", FALSE, persona, GET_EQ(persona, WEAR_WIELD), ic, TO_VICT);
                  GET_ACTIVE(persona) += GET_OBJ_VAL(GET_EQ(persona, WEAR_HEAD), 2);
                  extract_obj(unequip_char(persona, WEAR_HEAD));
                  break;
              }
            break;
          default:
            do_ic_response(ic, persona);
            break;
        }
      }
    }
  return;
}

int matrix_combat_util(struct char_data * ch, struct char_data * vict,
                       struct obj_data *program)
{
  int successes, skill = SKILL_COMPUTER, i = 0;
  int ch_dice = 0, res_dice = 0, ch_tar = 0, res_tar = 0;

  if (IS_IC(ch) && GET_RACE(ch) == CLASS_BLACK && IS_PERSONA(vict)) {
    ch_dice = GET_LEVEL(ch) + zone_table[world[ch->in_room].zone].alert > 0 ?
              (int)(GET_LEVEL(ch) / 2) : 0;
    res_dice = GET_BOD(vict->desc->original);
    res_tar = GET_LEVEL(ch) + zone_table[world[ch->in_room].zone].alert > 0 ?
              (int)(GET_LEVEL(ch) / 2) : 0;
    ch_tar = GET_BOD(vict->desc->original);
    ch_tar += find_smoke(ch);
    res_tar += find_smoke(vict);

    successes = resisted_test(ch_dice, ch_tar, res_dice, res_tar);
    successes -= GET_BALLISTIC(vict);

    for (; successes >= 0; successes -= 2)
      i++;
    return i;
  }

  if (IS_PERSONA(ch)) {
    if (!GET_SKILL(ch->desc->original, skill))
      reverse_web(ch->desc->original, skill, ch_tar);
    else ch_dice = GET_SKILL(ch->desc->original, skill);
    res_tar = ch_dice;
    if (program)
      ch_dice += MIN(GET_PROG_RATING(program), (int)(GET_HACKING(ch)));
  } else {
    ch_dice = GET_LEVEL(ch) + zone_table[world[ch->in_room].zone].alert > 0 ?
              (int)(GET_LEVEL(ch) / 2) : 0;
    res_tar = GET_SECURITY(ch);
  }

  if (IS_PERSONA(vict)) {
    res_dice = GET_WIL(vict) + MIN(GET_WIL(vict), (int)(GET_HACKING(vict)));
    ch_tar += GET_BOD(vict);
  } else {
    res_dice = GET_LEVEL(vict) + zone_table[world[vict->in_room].zone].alert > 0 ?
               (int)(GET_LEVEL(vict) / 2) : 0;
    ch_tar += GET_SECURITY(vict);
  }

  ch_tar += find_smoke(ch);
  res_tar += find_smoke(vict);

  successes = resisted_test(ch_dice, ch_tar, res_dice, res_tar);

  if (IS_PERSONA(ch) && IS_IC(vict))
    successes -= find_node_required(ch);
  else if (IS_PERSONA(vict))
    successes -= GET_BALLISTIC(vict);

  return successes;
}

void check_trace(struct char_data *ic)
{
  int mpcp, dir, room, distance, i, nextroom;
  struct char_data *vict, *guard, *temp;
  struct obj_data *obj, *o, *cyberdeck = NULL;

  if (!FIGHTING(ic) && GET_MENTAL(ic) < GET_MAX_MENTAL(ic))
    GET_MENTAL(ic) = GET_MAX_MENTAL(ic);

  if (!FIGHTING(ic) || (FIGHTING(ic) && !IS_PERSONA(FIGHTING(ic))) ||
      (GET_RACE(ic) != CLASS_TRACE_REPORT &&
      GET_RACE(ic) != CLASS_TRACE_DUMP) || number(0, 2))
    return;
  vict = FIGHTING(ic);

  if (GET_MENTAL(ic) > 0)
    GET_MENTAL(ic) -= 100;

  switch (GET_RACE(ic)) {
    case CLASS_TRACE_REPORT:
    case CLASS_TRACE_DUMP:
    case CLASS_TRACE_BURN:
      if (GET_MENTAL(ic) < 1) {
        temp = vict->desc->original;
        if (GET_RACE(ic) == CLASS_TRACE_DUMP)
          do_disconnect(vict, "", 0, SCMD_MORTED);
        else if (GET_RACE(ic) == CLASS_TRACE_BURN) {
          mpcp = success_test(GET_LEVEL(ic), GET_WIL(vict)) - GET_BALLISTIC(vict);
          if (mpcp > 0) {
            act("You succeed in frying some of $N's MPCP chips.", FALSE, ic, 0, vict, TO_CHAR);
            do_disconnect(vict, "", 0, SCMD_MORTED);
            send_to_char("A faint stream of smoke rises from your cyberdeck.\r\n", temp);
            for (obj = temp->carrying; obj; obj = obj->next_content)
              if (GET_OBJ_TYPE(obj) == ITEM_CYBERDECK)
                cyberdeck = obj;
            for (i = WEAR_LIGHT; !cyberdeck && i < NUM_WEARS; i++)
              if (GET_EQ(temp, i) && GET_OBJ_TYPE(GET_EQ(temp, i)) == ITEM_CYBERDECK)
                cyberdeck = GET_EQ(temp, i);
            if (cyberdeck) {
              GET_OBJ_VAL(cyberdeck, 0) -= mpcp;
              if (GET_OBJ_VAL(cyberdeck, 0) < 0)
                GET_OBJ_VAL(cyberdeck, 0) = 0;
            }
            return;
          }
        }
        room = temp->in_room;
        for (guard = world[room].people; guard; guard = guard->next_in_room)
          if (IS_NPC(guard) && MOB_FLAGGED(guard, MOB_GUARD)) {
            SET_BIT(MOB_FLAGS(guard), MOB_TRACK);
            HUNTING(guard) = temp;
            set_fighting(guard, temp);
          }
        for (dir = 0; dir < (NUM_OF_DIRS - 1); dir++) {
          room = temp->in_room;
          if (CAN_GO2(room, dir))
            nextroom = EXIT2(room, dir)->to_room;
          else nextroom = NOWHERE;
          for (distance = 1; ((nextroom != NOWHERE) && (distance <= 4)); distance++) {
            for (guard = world[nextroom].people; guard; guard = guard->next_in_room)
              if (IS_NPC(guard) && MOB_FLAGGED(guard, MOB_GUARD)) {
                SET_BIT(MOB_FLAGS(guard), MOB_TRACK);
                HUNTING(guard) = temp;
                hunt_victim(guard);
              }
            room = nextroom;
            if (CAN_GO2(room, dir))
              nextroom = EXIT2(room, dir)->to_room;
            else nextroom = NOWHERE;
          }
        }
        GET_MENTAL(ic) = GET_MAX_MENTAL(ic);
      }
      break;
  }

  return;
}

void check_smoke(struct char_data *persona)
{
  struct char_data *temp;
  int i = 0;

  for (temp = world[persona->in_room].people; temp; temp = temp->next_in_room)
    if (IS_PERSONA(temp) && GET_EQ(temp, WEAR_ARMS) && GET_OBJ_VAL(GET_EQ(temp, WEAR_ARMS), 9)) {
      GET_OBJ_VAL(GET_EQ(temp, WEAR_ARMS), 9)--;
      if (!GET_OBJ_VAL(GET_EQ(temp, WEAR_ARMS), 9) && i == 0) {
        send_to_room("The smoke clears.\r\n", persona->in_room);
        i = 1;
      }
    }

  return;
}

int check_shield(struct char_data *persona, int dam)
{
  int damage;
  bool found = FALSE;

  if (!IS_PERSONA(persona))
    return (dam);

  if (GET_EQ(persona, WEAR_SHIELD) &&
      GET_PROG_TYPE(GET_EQ(persona, WEAR_SHIELD)) == PROG_SHIELD &&
      GET_OBJ_VAL(GET_EQ(persona, WEAR_SHIELD), 9)) {
    GET_OBJ_VAL(GET_EQ(persona, WEAR_SHIELD), 9) -= dam;
    found = TRUE;
    if (GET_OBJ_VAL(GET_EQ(persona, WEAR_SHIELD), 9) <= 0) {
      damage = -(GET_OBJ_VAL(GET_EQ(persona, WEAR_SHIELD), 9));
      GET_OBJ_VAL(GET_EQ(persona, WEAR_SHIELD), 9) = 0;
      act("Your shield program collapses from active use.", FALSE, persona, 0, 0, TO_CHAR);
      act("$n's shield program collapses.", TRUE, persona, 0, 0, TO_ROOM);
      GET_ACTIVE(persona) += GET_OBJ_VAL(GET_EQ(persona, WEAR_SHIELD), 2);
      obj_to_char(unequip_char(persona, WEAR_SHIELD), persona);
      return (damage);
    }
  }

  if (!found)
    return (dam);

  return 0;
}

void check_mirrors(struct char_data *persona)
{
  if (GET_EQ(persona, WEAR_HANDS) &&
      GET_PROG_TYPE(GET_EQ(persona, WEAR_HANDS)) == PROG_MIRRORS &&
      GET_OBJ_VAL(GET_EQ(persona, WEAR_HANDS), 9)) {
    GET_OBJ_VAL(GET_EQ(persona, WEAR_HANDS), 9)--;
    GET_QUI(persona)--;
    if (GET_OBJ_VAL(GET_EQ(persona, WEAR_HANDS), 9) == 0) {
      GET_QUI(persona) = persona->real_abils.qui;
      act("Your $p stops running.",
          FALSE, persona, GET_EQ(persona, WEAR_HANDS), 0, TO_CHAR);
    }
    return;
  }
}

void check_sleaze(struct char_data *persona)
{
  if (GET_EQ(persona, WEAR_HEAD) &&
      GET_PROG_TYPE(GET_EQ(persona, WEAR_HEAD)) == PROG_MIRRORS &&
      GET_OBJ_VAL(GET_EQ(persona, WEAR_HEAD), 9)) {
    GET_OBJ_VAL(GET_EQ(persona, WEAR_HEAD), 9)--;
    if (GET_OBJ_VAL(GET_EQ(persona, WEAR_HEAD), 9) == 0)
      act("Your $p stops running.",
          FALSE, persona, GET_EQ(persona, WEAR_HEAD), 0, TO_CHAR);
  }
}

void matrix_fight(struct char_data *ch, struct char_data *victim)
{
  int attacktype, dam, i, mpcp, exp;
  struct obj_data *wielded, *obj, *o = NULL, *cyberdeck = NULL;
  struct char_data *temp = NULL;

  wielded = ch->equipment[WEAR_WIELD];

  if (!IS_PERSONA(ch) && !IS_IC(ch))
    return;

  if (IS_IC(ch) & (GET_RACE(ch) != CLASS_KILLER && GET_RACE(ch) != CLASS_BLASTER &&
      GET_RACE(ch) != CLASS_BLACK))
    return;

  if (IS_PERSONA(ch) && (!wielded || GET_OBJ_TYPE(wielded) != ITEM_PROGRAM ||
      GET_PROG_TYPE(wielded) != PROG_ATTACK)) {
    stop_fighting(ch);
    return;
  } else if (IS_IC(ch) && wielded)
    wielded = NULL;

  if (wielded) {
    if (!execution_test(ch, wielded,
        IS_PERSONA(victim) ? victim : (struct char_data *) NULL)) {
      act("$p fails to execute!", FALSE, ch, wielded, 0, TO_CHAR);
      return;
    }
    dam = matrix_combat_util(ch, victim, wielded);
  } else dam = matrix_combat_util(ch, victim, NULL);

  dam = MAX(0, dam);

  if (victim != ch) {
    if (!FIGHTING(ch))
      set_fighting(ch, victim);
    if (!FIGHTING(victim))
      set_fighting(victim, ch);
  }

  if (IS_AFFECTED(ch, AFF_HIDE))
    appear(ch);

  if (IS_PERSONA(victim))
    temp = victim->desc->original;

  if (wielded)
    attacktype = GET_OBJ_VAL(wielded, 3);
  else {
    if (IS_NPC(ch) && (ch->mob_specials.attack_type != 0))
      attacktype = ch->mob_specials.attack_type;
    else attacktype = TYPE_HIT;
  }

  if (IS_IC(ch) && GET_RACE(ch) == CLASS_BLACK && IS_PERSONA(victim)) {
    if (!IS_WEAPON(attacktype))
      skill_message(dam, ch, victim, attacktype);
    else dam_message(dam, ch, victim, attacktype);

    damage(ch, ch, dam, 0, TRUE);
    return;
  }

  GET_PHYSICAL(victim) -= MAX(0, check_shield(victim, dam) * 100);

  if (GET_PHYSICAL(victim) < 100)
    GET_POS(victim) = POS_DEAD;

  if (!IS_WEAPON(attacktype))
    skill_message(dam, ch, victim, attacktype);
  else {
    if (GET_POS(victim) == POS_DEAD) {
      if (!skill_message(dam, ch, victim, attacktype))
         dam_message(dam, ch, victim, attacktype);
    } else dam_message(dam, ch, victim, attacktype);
  }

  if (dam < 1 && IS_IC(victim) && GET_POS(victim) != POS_DEAD) {
    if (GET_RACE(victim) != CLASS_BLASTER && GET_RACE(victim) != CLASS_KILLER &&
        GET_RACE(victim) != CLASS_BLACK && GET_RACE(victim) != CLASS_TRACE_BURN &&
        GET_RACE(victim) != CLASS_TRACE_REPORT && GET_RACE(victim) != CLASS_TRACE_DUMP)
      do_ic_response(victim, ch);
    if (!number(0, 2)) {
      switch (GET_RACE(victim)) {
        case CLASS_TAR_BABY:
          act("As you fail to damage $N, $E knocks $p out of active memory!",
              FALSE, ch, GET_EQ(ch, WEAR_WIELD), victim, TO_CHAR);
          act("As $n fails to damage you, you knock $p out of $s active memory!",
              FALSE, ch, GET_EQ(ch, WEAR_WIELD), victim, TO_VICT);
          GET_ACTIVE(ch) += GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2);
          obj_to_char(unequip_char(ch, WEAR_WIELD), ch);
          break;
        case CLASS_TAR_PIT:
          act("As you fail to damage $N, $E knocks $p out of online memory!",
              FALSE, ch, GET_EQ(ch, WEAR_WIELD), victim, TO_CHAR);
          act("As $n fails to damage you, you knock $p out of $s online memory!",
              FALSE, ch, GET_EQ(ch, WEAR_WIELD), victim, TO_VICT);
          GET_ACTIVE(ch) += GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2);
          extract_obj(GET_EQ(ch, WEAR_WIELD));
          break;
      }
    }
  }

  if (GET_POS(victim) == POS_DEAD) {
    /** CODE HERE TO CALCULATE KARMA **/
    exp = calc_karma(ch, victim);
    exp = exp + 300;
    if ( ch && ch->desc && ch->desc->original )
      exp = gain_exp(ch->desc->original, exp);
    else
      exp = gain_exp(ch, exp);

    if (wielded)
      GET_OBJ_VAL(wielded, 9) = 0;
    act("$n shatters into a million pixels.", FALSE, victim, 0, 0, TO_ROOM);
    send_to_char(ch, "You receive %0.2f karma.\r\n", ((float)exp / 100));

    if (IS_PERSONA(victim) && IS_IC(ch) && GET_RACE(ch) == CLASS_BLASTER) {
      mpcp = success_test(GET_LEVEL(ch), GET_WIL(victim)) - GET_BALLISTIC(victim);
      if (mpcp > 0) {
        act("You succeed in frying some of $N's MPCP chips.",
            FALSE, ch, 0, victim, TO_CHAR);
        do_disconnect(victim, "", 0, SCMD_MORTED);
        send_to_char("A faint stream of smoke rises from your cyberdeck.\r\n", temp);
        for (obj = temp->carrying; obj; obj = obj->next_content)
          if (GET_OBJ_TYPE(obj) == ITEM_CYBERDECK)
            cyberdeck = obj;
        for (i = WEAR_LIGHT; !cyberdeck && i < NUM_WEARS; i++)
          if (GET_EQ(temp, i) && GET_OBJ_TYPE(GET_EQ(temp, i)) == ITEM_CYBERDECK)
            cyberdeck = GET_EQ(temp, i);
        if (cyberdeck) {
          GET_OBJ_VAL(cyberdeck, 0) -= mpcp;
          if (GET_OBJ_VAL(cyberdeck, 0) < 0)
            GET_OBJ_VAL(cyberdeck, 0) = 0;
        }
        return;
      }
      do_disconnect(victim, "", 0, SCMD_MORTED);
      return;
    }
    for (i = 0; i < NUM_WEARS; i++)
      if (victim->equipment[i])
        extract_obj(victim->equipment[i]);
    for (obj = victim->carrying; o; obj = o) {
      o = obj->next_content;
      extract_obj(obj);
    }
    extract_char(victim);
  }
}

void matrix_update(void)
{
  struct descriptor_data *d;

  for (d = descriptor_list; d; d = d->next)
    if (d->character && IS_PERSONA(d->character)) {
      check_mirrors(d->character);
      check_sleaze(d->character);
      check_smoke(d->character);
      if (!FIGHTING(d->character) && GET_EQ(d->character, WEAR_WIELD) &&
          GET_OBJ_VAL(GET_EQ(d->character, WEAR_WIELD), 9))
        GET_OBJ_VAL(GET_EQ(d->character, WEAR_WIELD), 9) = 0;
    }
}