Adding identify to tbaMUD

As discussed on the forums here is how to add identify:

Index: interpreter.c
===================================================================
--- interpreter.c       (revision 197)
+++ interpreter.c       (working copy)
@@ -171,6 +171,7 @@
   { "holylight", "holy"    , POS_DEAD    , do_gen_tog  , LVL_IMMORT, SCMD_HOLYLIGHT },
   { "house"    , "house"   , POS_RESTING , do_house    , 0, 0 },

+  { "identify" , "id"      , POS_STANDING, do_not_here , 1, 0 },
   { "inventory", "i"       , POS_DEAD    , do_inventory, 0, 0 },
   { "idea"     , "id"      , POS_DEAD    , do_ibt      , 0, SCMD_IDEA },
   { "imotd"    , "imo"     , POS_DEAD    , do_gen_ps   , LVL_IMMORT, SCMD_IMOTD },
Index: spell_parser.c
===================================================================
--- spell_parser.c      (revision 197)
+++ spell_parser.c      (working copy)
@@ -916,7 +916,11 @@
        TAR_CHAR_ROOM, FALSE, MAG_MANUAL,
        NULL);

+  spello(SPELL_IDENTIFY, "identify", 50, 25, 5, POS_STANDING,
+        TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL,
+        NULL);

+
   /* NON-castable spells should appear below here. */
   spello(SPELL_IDENTIFY, "identify", 0, 0, 0, 0,
        TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL,
Index: class.c
===================================================================
--- class.c     (revision 197)
+++ class.c     (working copy)
@@ -1586,6 +1586,7 @@
   spell_level(SPELL_POISON, CLASS_MAGIC_USER, 14);
   spell_level(SPELL_FIREBALL, CLASS_MAGIC_USER, 15);
   spell_level(SPELL_CHARM, CLASS_MAGIC_USER, 16);
+  spell_level(SPELL_IDENTIFY, CLASS_MAGIC_USER, 20);
   spell_level(SPELL_ENCHANT_WEAPON, CLASS_MAGIC_USER, 26);
   spell_level(SPELL_CLONE, CLASS_MAGIC_USER, 30);

@@ -1607,6 +1608,7 @@
   spell_level(SPELL_CURE_CRITIC, CLASS_CLERIC, 9);
   spell_level(SPELL_SUMMON, CLASS_CLERIC, 10);
   spell_level(SPELL_REMOVE_POISON, CLASS_CLERIC, 10);
+  spell_level(SPELL_IDENTIFY, CLASS_CLERIC, 11);
   spell_level(SPELL_WORD_OF_RECALL, CLASS_CLERIC, 12);
   spell_level(SPELL_EARTHQUAKE, CLASS_CLERIC, 12);
   spell_level(SPELL_DISPEL_EVIL, CLASS_CLERIC, 14);
Index: shop.c
===================================================================
--- shop.c      (revision 197)
+++ shop.c      (working copy)
@@ -25,6 +25,7 @@
 #include "constants.h"
 #include "act.h"
 #include "modify.h"
+#include "spells.h"  /* for skill_name() */

 /* Global variables definitions used externally */
 /* Constant list for printing out who we sell to */
@@ -57,6 +58,7 @@
 static int read_type_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max);
 static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max, int type);
 static void shopping_list(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
+static bool shopping_identify(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
 static void shopping_value(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
 static void shopping_sell(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
 static struct obj_data *get_selling_obj(struct char_data *ch, char *name, struct char_data *keeper, int shop_nr, int msg);
@@ -984,6 +986,8 @@
   } else if (CMD_IS("list")) {
     shopping_list(argument, ch, keeper, shop_nr);
     return (TRUE);
+  } else if (CMD_IS("identify")) {
+    return (shopping_identify(argument, ch, keeper, shop_nr));
   }
   return (FALSE);
 }
@@ -1543,3 +1547,114 @@
   shop_index = NULL;
   top_shop = -1;
 }
+
+bool shopping_identify(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr)
+{
+  char buf[MAX_STRING_LENGTH];
+  struct obj_data *obj;
+  int i, found;
+
+  if (!is_ok(keeper, ch, shop_nr))
+    return FALSE;
+
+  if (SHOP_SORT(shop_nr) < IS_CARRYING_N(keeper))
+    sort_keeper_objs(keeper, shop_nr);
+
+  if (!*arg) {
+    snprintf(buf, sizeof(buf), "%s What do you want to identify??", GET_NAME(ch));
+    do_tell(keeper, buf, cmd_tell, 0);
+    return TRUE;
+  }
+  if (!(obj = get_purchase_obj(ch, arg, keeper, shop_nr, TRUE)))
+    return FALSE;
+
+  send_to_char(ch, "Name: %s\r\n", (obj->short_description) ? obj->short_description : "");
+  sprinttype(GET_OBJ_TYPE(obj), item_types, buf, sizeof(buf));
+  send_to_char(ch, "Type: %s\r\n", buf);
+  send_to_char(ch, "Weight: %d, Cost to Buy: @Y%d@n\r\n", GET_OBJ_WEIGHT(obj), sell_price(obj, shop_nr, keeper, ch));
+
+      sprintbitarray(GET_OBJ_WEAR(obj), wear_bits, TW_ARRAY_MAX, buf);
+      send_to_char(ch, "Can be worn on: %s\r\n", buf);
+
+      switch (GET_OBJ_TYPE(obj)) {
+        case ITEM_LIGHT:
+          if (GET_OBJ_VAL(obj, 2) == -1)
+            send_to_char(ch, "Hours Remaining: (Infinite)\r\n");
+          else if (GET_OBJ_VAL(obj, 2) == 0)
+            send_to_char(ch, "Hours Remaining: None!\r\n");
+          else
+            send_to_char(ch, "Hours Remaining: %d\r\n", GET_OBJ_VAL(obj, 2));
+          break;
+        case ITEM_SCROLL:
+        case ITEM_POTION:
+          send_to_char(ch, "Spells: %s, %s, %s\r\n",
+                  skill_name(GET_OBJ_VAL(obj, 1)),
+                  skill_name(GET_OBJ_VAL(obj, 2)),
+                  skill_name(GET_OBJ_VAL(obj, 3)));
+          break;
+        case ITEM_WAND:
+        case ITEM_STAFF:
+          send_to_char(ch, "Spell: %s\r\n", skill_name(GET_OBJ_VAL(obj, 3)));
+          send_to_char(ch, "Charges: %d/%d\r\n", GET_OBJ_VAL(obj, 2), GET_OBJ_VAL(obj, 1));
+          break;
+        case ITEM_WEAPON:
+            send_to_char(ch, "Damage Dice is '%dD%d' for an average per-round damage of %.1f.\r\n",
+                        GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 2),
+                        ((GET_OBJ_VAL(obj, 2) + 1) / 2.0) * GET_OBJ_VAL(obj, 1));
+            break;
+        case ITEM_ARMOR:
+          if(GET_OBJ_VAL(obj,1) == 0)
+          {
+            send_to_char(ch, "AC-apply: [%d]\r\n", GET_OBJ_VAL(obj, 0));
+          }
+          else
+          {
+            send_to_char(ch, "AC-apply: [%d] - This item has magical affects.\r\n", GET_OBJ_VAL(obj, 0));
+          }
+          break;
+        case ITEM_CONTAINER:
+          send_to_char(ch, "Capacity: %d/%d\r\n", GET_OBJ_WEIGHT(obj), GET_OBJ_VAL(obj, 0));
+          break;
+        case ITEM_DRINKCON:
+        case ITEM_FOUNTAIN:
+          send_to_char(ch, "Drinks: %d/%d\r\n", GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 0));
+          break;
+        case ITEM_NOTE:
+          send_to_char(ch, "\r\n");
+          break;
+        case ITEM_KEY:
+          send_to_char(ch, "\r\n");
+          break;
+        case ITEM_FOOD:
+          send_to_char(ch, "\r\n");
+          break;
+        case ITEM_MONEY:
+          send_to_char(ch, "\r\n");
+          break;
+        case ITEM_WORN:
+          if(GET_OBJ_VAL(obj,1) > 0)
+            send_to_char(ch, "This item has magical affects.\r\n");
+          else
+            send_to_char(ch, "\r\n");
+          break;
+        default:
+          send_to_char(ch, "\r\n");
+          break;
+      }
+
+      found = 0;
+      send_to_char(ch, "Affections:");
+      for (i = 0; i < MAX_OBJ_AFFECT; i++)
+        if (obj->affected[i].modifier) {
+          sprinttype(obj->affected[i].location, apply_types, buf, sizeof(buf));
+          send_to_char(ch, "%s %+d to %s", found++ ? "," : "", obj->affected[i].modifier, buf);
+        }
+      if (!found)
+        send_to_char(ch, " None");
+
+      send_to_char(ch, "\r\nExtra Flags: ");
+      sprintbitarray(GET_OBJ_EXTRA(obj), extra_bits, EF_ARRAY_MAX, buf);
+      send_to_char(ch, "%s\r\n", buf);
+
+  return TRUE;
+}
Index: spells.h
===================================================================
--- spells.h    (revision 197)
+++ spells.h    (working copy)
@@ -89,6 +89,7 @@
 #define SPELL_GROUP_RECALL          49 /* Reserved Skill[] DO NOT CHANGE */
 #define SPELL_INFRAVISION           50 /* Reserved Skill[] DO NOT CHANGE */
 #define SPELL_WATERWALK                     51 /* Reserved Skill[] DO NOT CHANGE */
+#define SPELL_IDENTIFY               52 /* Reserved Skill[] DO NOT CHANGE */
 /** Total Number of defined spells */
-#define NUM_SPELLS    51
+ #define NUM_SPELLS    52

@@ -113,7 +114,6 @@
  * intended use is for spells and skills associated with objects (such as
  * SPELL_IDENTIFY used with scrolls of identify) or non-players (such as NPC
  * only spells). */
-#define SPELL_IDENTIFY               201

 /* To make an affect induced by dg_affect look correct on 'stat' we need to
  * define it with a 'spellname'. */