diff --git a/changelog b/changelog index b105505..b1398c1 100644 --- a/changelog +++ b/changelog @@ -36,6 +36,16 @@ Xlist (mlist, olist, rlist, zlist, slist, tlist, qlist) (lots of major bugfixes too) @ tbaMUD 3.61 +[Oct 23 2009] - Rumble + Fixed bug in renumbering zone table after deleting mobiles. (thanks Drefs) + Fixed bug in renumbering zone table after deleting objects. (thanks Drefs) + Upgraded column_list to use player screenwidth to determine how many columns to create (use column arg of 0). (thanks Maclir) +[Oct 20 2009] - Rumble + Corrected several PRF_FLAGGED checks that mobs were using. + Removed l-desc from stat player and title from stat mob. (thanks Xiu) +[Oct 19 2009] - Rumble + Added a note to spec_assign.c assign_mobiles that guildguard, snake, thief, magic user, puff, fido, janitor, and cityguards are now implemented via triggers. + Fixed a bug where empty drink containers and fountains would show half empty. (thanks Parna) [Oct 17 2009] - Rumble Added Ultima Zone 555 and 556. Originally by Casret, rebuilt by Parna. Made MEDIT column menu's consistent with other OLC menu's. diff --git a/doc/syserr.txt b/doc/syserr.txt index 567276a..b4cc687 100644 --- a/doc/syserr.txt +++ b/doc/syserr.txt @@ -18,10 +18,11 @@ rumble@tbamud.com -- Rumble 8. Char is already equipped: (medit-s-desc), (oedit-s-desc) 9. SYSERR: Attempt to assign spec to non-existant mob # 10. No associated object exists when attempting to create a board [vnum #]. +11. 11: SYSERR: Mob using >'((ch)-)player_specials.... 1: Errant Rooms ------------- -12: (Nowhere) [ 8868] House of Elders Chamber in Silverwood City (south) + +(Nowhere) [ 8868] House of Elders Chamber in Silverwood City (south) The most common are exits to Nowhere. This happens when a builder modifies a room exit but does not include an exit room vnum. These errant @@ -87,4 +88,22 @@ that is not used. You need to delete this board from lib/etc/boards/ and modify boards.c and boards.h. Again "grep #" *.[ch] to search for this vnum in all of your .c and -.h files to remove the reference. +.h files to remove the reference. + +11: SYSERR: Mob using >'((ch)-)player_specials.... + +Players and mobs (NPC's) share many of the same data fields, but not all. +So when a mob tries to access player data it gives a SYSERR like this: +SYSERR: Mob using >'((ch)-)player_specials... + +The fix is actually a very easy one. All you have to do is make sure it only +checks player data if it is a player. The way this is done in the code is with +a non-player-character check. Now non-player-character (NPC) means it is a mob. +So you need a double negative to make sure it is not a non-player-character. I +know this is confusing, but just copy the example below. + +- if (PRF_FLAGGED(ch, PRF_NOREPEAT)) // This line should be removed, hence the "-" ++ if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT)) // This line should be added without the "+" + +The changed line now will not just check for a flag, instead it will check if +it is a player (not an NPC) and it is flagged then continue. diff --git a/lib/text/imotd b/lib/text/imotd index b158741..dd554f0 100644 --- a/lib/text/imotd +++ b/lib/text/imotd @@ -7,5 +7,5 @@ log in to the game. You should change it to something more interesting when you get a chance (as well as most of the other files in lib/text.) If you need help, find a bug, or wish to contribute please stop by -The Builder Academy at: builderacademy.net 9091 or @Chttp://tbamud.com@n. +The Builder Academy at: tbamud.com 9091 or @Chttp://tbamud.com@n. diff --git a/src/act.informative.c b/src/act.informative.c index 5babcd7..3e3d4c7 100644 --- a/src/act.informative.c +++ b/src/act.informative.c @@ -569,7 +569,7 @@ static void look_in_obj(struct char_data *ch, char *arg) list_obj_to_char(obj->contains, ch, SHOW_OBJ_SHORT, TRUE); } } else { /* item must be a fountain or drink container */ - if ((GET_OBJ_VAL(obj, 1) == 0) && (!GET_OBJ_VAL(obj, 0) == -1)) + if ((GET_OBJ_VAL(obj, 1) == 0) && (GET_OBJ_VAL(obj, 0) != -1)) send_to_char(ch, "It is empty.\r\n"); else { if (GET_OBJ_VAL(obj, 0) < 0) @@ -2237,7 +2237,7 @@ ACMD(do_commands) } /* display commands list in a nice columnized format */ - column_list(ch, 7, commands, no, FALSE); + column_list(ch, 0, commands, no, FALSE); } void free_history(struct char_data *ch, int type) diff --git a/src/act.movement.c b/src/act.movement.c index 72e1c32..9eeb144 100644 --- a/src/act.movement.c +++ b/src/act.movement.c @@ -351,7 +351,7 @@ int perform_move(struct char_data *ch, int dir, int need_specials_check) return (0); else if ((!EXIT(ch, dir) && !buildwalk(ch, dir)) || EXIT(ch, dir)->to_room == NOWHERE) send_to_char(ch, "Alas, you cannot go that way...\r\n"); - else if (EXIT_FLAGGED(EXIT(ch, dir), EX_CLOSED) && (GET_LEVEL(ch) < LVL_IMMORT || !PRF_FLAGGED(ch, PRF_NOHASSLE))) { + else if (EXIT_FLAGGED(EXIT(ch, dir), EX_CLOSED) && (GET_LEVEL(ch) < LVL_IMMORT || (!IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_NOHASSLE)))) { if (EXIT(ch, dir)->keyword) send_to_char(ch, "The %s seems to be closed.\r\n", fname(EXIT(ch, dir)->keyword)); else @@ -656,19 +656,19 @@ ACMD(do_gen_door) else if (!(DOOR_IS_LOCKED(ch, obj, door)) && IS_SET(flags_door[subcmd], NEED_LOCKED)) send_to_char(ch, "Oh.. it wasn't locked, after all..\r\n"); - else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) && IS_SET(flags_door[subcmd], NEED_UNLOCKED) && (PRF_FLAGGED(ch, PRF_AUTOKEY)) && (has_key(ch, keynum)) ) + else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) && IS_SET(flags_door[subcmd], NEED_UNLOCKED) && ((!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTOKEY))) && (has_key(ch, keynum)) ) { send_to_char(ch, "It is locked, but you have the key.\r\n"); send_to_char(ch, "*Click*\r\n"); do_doorcmd(ch, obj, door, subcmd); } - else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) && IS_SET(flags_door[subcmd], NEED_UNLOCKED) && (PRF_FLAGGED(ch, PRF_AUTOKEY)) && (!has_key(ch, keynum)) ) + else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) && IS_SET(flags_door[subcmd], NEED_UNLOCKED) && ((!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTOKEY))) && (!has_key(ch, keynum)) ) { send_to_char(ch, "It is locked, and you do not have the key!\r\n"); } else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) && IS_SET(flags_door[subcmd], NEED_UNLOCKED) && - (GET_LEVEL(ch) < LVL_IMMORT || !PRF_FLAGGED(ch, PRF_NOHASSLE))) + (GET_LEVEL(ch) < LVL_IMMORT || (!IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_NOHASSLE)))) send_to_char(ch, "It seems to be locked.\r\n"); else if (!has_key(ch, keynum) && (GET_LEVEL(ch) < LVL_GOD) && ((subcmd == SCMD_LOCK) || (subcmd == SCMD_UNLOCK))) diff --git a/src/act.wizard.c b/src/act.wizard.c index 25d3ad2..a7da7d9 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -739,12 +739,14 @@ static void do_stat_character(struct char_data *ch, struct char_data *k) buf, (!IS_NPC(k) ? "PC" : (!IS_MOB(k) ? "NPC" : "MOB")), GET_NAME(k), IS_NPC(k) ? GET_ID(k) : GET_IDNUM(k), GET_ROOM_VNUM(IN_ROOM(k)), IS_NPC(k) ? NOWHERE : GET_LOADROOM(k)); - if (IS_MOB(k)) + if (IS_MOB(k)) { send_to_char(ch, "Keyword: %s, VNum: [%5d], RNum: [%5d]\r\n", k->player.name, GET_MOB_VNUM(k), GET_MOB_RNUM(k)); + send_to_char(ch, "L-Des: %s", k->player.long_descr ? k->player.long_descr : "\r\n"); + } - send_to_char(ch, "Title: %s\r\n", k->player.title ? k->player.title : ""); + if (!IS_MOB(k)) + send_to_char(ch, "Title: %s\r\n", k->player.title ? k->player.title : ""); - send_to_char(ch, "L-Des: %s", k->player.long_descr ? k->player.long_descr : "\r\n"); send_to_char(ch, "D-Des: %s", k->player.description ? k->player.description : "\r\n"); sprinttype(k->player.chclass, pc_class_types, buf, sizeof(buf)); @@ -4441,7 +4443,7 @@ ACMD(do_plist) len = 0; len += snprintf(buf + len, sizeof(buf) - len, "@W[ Id] (Lv) Name Last@n\r\n" - "%s-----------------------------------------------%s\r\n", CCCYN(ch, C_NRM), + "%s-------------------------------------%s\r\n", CCCYN(ch, C_NRM), CCNRM(ch, C_NRM)); for (i = 0; i <= top_of_p_table; i++) { @@ -4466,7 +4468,7 @@ ACMD(do_plist) UPPER(*player_table[i].name), player_table[i].name + 1, time_str); count++; } - snprintf(buf + len, sizeof(buf) - len, "%s-----------------------------------------------%s\r\n" + snprintf(buf + len, sizeof(buf) - len, "%s-------------------------------------%s\r\n" "%d players listed.\r\n", CCCYN(ch, C_NRM), CCNRM(ch, C_NRM), count); page_string(ch->desc, buf, TRUE); } diff --git a/src/class.c b/src/class.c index 003a966..bcbfc1e 100644 --- a/src/class.c +++ b/src/class.c @@ -122,7 +122,8 @@ int prac_params[4][NUM_CLASSES] = { * to visit spec_assign.c if you create any new mobiles that should be a guild * master or guard so they can act appropriately. If you "recycle" the * existing mobs that are used in other guilds for your new guild, then you - * don't have to change that file, only here. */ + * don't have to change that file, only here. Guildguards are now implemented + * via triggers. This code remains as an example. */ struct guild_info_type guild_info[] = { /* Midgaard */ diff --git a/src/genmob.c b/src/genmob.c index e2e2eeb..84abad9 100644 --- a/src/genmob.c +++ b/src/genmob.c @@ -146,8 +146,12 @@ int delete_mobile(mob_rnum refpt) /* Update zone table. */ for (zone = 0; zone <= top_of_zone_table; zone++) for (cmd_no = 0; ZCMD(zone, cmd_no).command != 'S'; cmd_no++) - if (ZCMD(zone, cmd_no).command == 'M' && ZCMD(zone, cmd_no).arg1 == refpt) + if (ZCMD(zone, cmd_no).command == 'M'){ + if (ZCMD(zone, cmd_no).arg1 == refpt) { delete_zone_command(&zone_table[zone], cmd_no); + } else + ZCMD(zone, cmd_no).arg1 -= (ZCMD(zone, cmd_no).arg1 > refpt); + } /* Update shop keepers. */ if (shop_index) diff --git a/src/genobj.c b/src/genobj.c index c464626..1187e66 100644 --- a/src/genobj.c +++ b/src/genobj.c @@ -451,7 +451,7 @@ int delete_object(obj_rnum rnum) delete_zone_command(&zone_table[zone], cmd_no); } else ZCMD(zone, cmd_no).arg3 -= (ZCMD(zone, cmd_no).arg3 > rnum); - break; + /* No break here - drop into next case. */ case 'O': case 'G': case 'E': diff --git a/src/medit.c b/src/medit.c index 07a417f..d2e3f47 100644 --- a/src/medit.c +++ b/src/medit.c @@ -299,28 +299,18 @@ void medit_save_internally(struct descriptor_data *d) Display positions. (sitting, standing, etc) */ static void medit_disp_positions(struct descriptor_data *d) { - int i; - get_char_colors(d->character); clear_screen(d); - - for (i = 0; *position_types[i] != '\n'; i++) { - write_to_output(d, "%s%2d%s) %s\r\n", grn, i, nrm, position_types[i]); - } + column_list(d->character, 0, position_types, NUM_POSITIONS, TRUE); write_to_output(d, "Enter position number : "); } /* Display the gender of the mobile. */ static void medit_disp_sex(struct descriptor_data *d) { - int i; - get_char_colors(d->character); clear_screen(d); - - for (i = 0; i < NUM_GENDERS; i++) { - write_to_output(d, "%s%2d%s) %s\r\n", grn, i, nrm, genders[i]); - } + column_list(d->character, 0, genders, NUM_GENDERS, TRUE); write_to_output(d, "Enter gender number : "); } @@ -341,15 +331,11 @@ static void medit_disp_attack_types(struct descriptor_data *d) /* Display mob-flags menu. */ static void medit_disp_mob_flags(struct descriptor_data *d) { - int i, columns = 0; char flags[MAX_STRING_LENGTH]; get_char_colors(d->character); clear_screen(d); - for (i = 0; i < NUM_MOB_FLAGS; i++) { - write_to_output(d, "%s%2d%s) %-20.20s %s", grn, i + 1, nrm, action_bits[i], - !(++columns % 2) ? "\r\n" : ""); - } + column_list(d->character, 0, action_bits, NUM_MOB_FLAGS, TRUE); sprintbitarray(MOB_FLAGS(OLC_MOB(d)), action_bits, AF_ARRAY_MAX, flags); write_to_output(d, "\r\nCurrent flags : %s%s%s\r\nEnter mob flags (0 to quit) : ", cyn, flags, nrm); } @@ -357,15 +343,12 @@ static void medit_disp_mob_flags(struct descriptor_data *d) /* Display affection flags menu. */ static void medit_disp_aff_flags(struct descriptor_data *d) { - int i, columns = 0; char flags[MAX_STRING_LENGTH]; get_char_colors(d->character); clear_screen(d); - for (i = 0; i < NUM_AFF_FLAGS; i++) { - write_to_output(d, "%s%2d%s) %-20.20s %s", grn, i + 1, nrm, affected_bits[i+1], - !(++columns % 2) ? "\r\n" : ""); - } + /* +1 since AFF_FLAGS don't start at 0. */ + column_list(d->character, 0, affected_bits + 1, NUM_AFF_FLAGS, TRUE); sprintbitarray(AFF_FLAGS(OLC_MOB(d)), affected_bits, AF_ARRAY_MAX, flags); write_to_output(d, "\r\nCurrent flags : %s%s%s\r\nEnter aff flags (0 to quit) : ", cyn, flags, nrm); diff --git a/src/oedit.c b/src/oedit.c index c44d138..7838c5c 100644 --- a/src/oedit.c +++ b/src/oedit.c @@ -349,15 +349,9 @@ static void oedit_disp_prompt_apply_menu(struct descriptor_data *d) /* Ask for liquid type. */ static void oedit_liquid_type(struct descriptor_data *d) { - int counter, columns = 0; - get_char_colors(d->character); clear_screen(d); - - for (counter = 0; counter < NUM_LIQ_TYPES; counter++) { - write_to_output(d, " %s%2d%s) %s%-20.20s %s", grn, counter, nrm, yel, - drinks[counter], !(++columns % 2) ? "\r\n" : ""); - } + column_list(d->character, 0, drinks, NUM_LIQ_TYPES, TRUE); write_to_output(d, "\r\n%sEnter drink type : ", nrm); OLC_MODE(d) = OEDIT_VALUE_3; } @@ -365,15 +359,9 @@ static void oedit_liquid_type(struct descriptor_data *d) /* The actual apply to set. */ static void oedit_disp_apply_menu(struct descriptor_data *d) { - int counter, columns = 0; - get_char_colors(d->character); clear_screen(d); - - for (counter = 0; counter < NUM_APPLIES; counter++) { - write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter, nrm, - apply_types[counter], !(++columns % 2) ? "\r\n" : ""); - } + column_list(d->character, 0, apply_types, NUM_APPLIES, TRUE); write_to_output(d, "\r\nEnter apply type (0 is no apply) : "); OLC_MODE(d) = OEDIT_APPLY; } @@ -1036,6 +1024,7 @@ void oedit_parse(struct descriptor_data *d, char *arg) case ITEM_FOUNTAIN: min_val = 0; max_val = NUM_LIQ_TYPES - 1; + number--; break; case ITEM_KEY: min_val = 0; @@ -1096,7 +1085,7 @@ void oedit_parse(struct descriptor_data *d, char *arg) OLC_OBJ(d)->affected[OLC_VAL(d)].location = 0; OLC_OBJ(d)->affected[OLC_VAL(d)].modifier = 0; oedit_disp_prompt_apply_menu(d); - } else if (number < 0 || number >= NUM_APPLIES) + } else if (number < 0 || number > NUM_APPLIES) oedit_disp_apply_menu(d); else { int counter; @@ -1111,7 +1100,7 @@ void oedit_parse(struct descriptor_data *d, char *arg) } } - OLC_OBJ(d)->affected[OLC_VAL(d)].location = number; + OLC_OBJ(d)->affected[OLC_VAL(d)].location = number - 1; write_to_output(d, "Modifier : "); OLC_MODE(d) = OEDIT_APPLYMOD; } diff --git a/src/qedit.c b/src/qedit.c index 4b53626..8436488 100644 --- a/src/qedit.c +++ b/src/qedit.c @@ -347,16 +347,11 @@ static void qedit_disp_menu(struct descriptor_data *d) real_quest(quest->prev_quest) == NOTHING ? "" : QST_DESC(real_quest(quest->prev_quest))); OLC_MODE(d) = QEDIT_MAIN_MENU; } -/* For sector type. */ +/* For quest type. */ void qedit_disp_type_menu(struct descriptor_data *d) { - int counter, columns = 0; - clear_screen(d); - for (counter = 0; counter < NUM_AQ_TYPES; counter++) { - write_to_output(d, "@g%2d@n) %-20.20s %s", counter, - quest_types[counter], !(++columns % 2) ? "\r\n" : ""); - } + column_list(d->character, 0, quest_types, NUM_AQ_TYPES, TRUE); write_to_output(d, "\r\nEnter Quest type : "); OLC_MODE(d) = QEDIT_TYPES; } @@ -364,14 +359,10 @@ void qedit_disp_type_menu(struct descriptor_data *d) void qedit_disp_flag_menu(struct descriptor_data *d) { char bits[MAX_STRING_LENGTH]; - int counter, columns = 0; get_char_colors(d->character); clear_screen(d); - for (counter = 0; counter < NUM_AQ_FLAGS; counter++) { - write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter + 1, nrm, - aq_flags[counter], !(++columns % 2) ? "\r\n" : ""); - } + column_list(d->character, 0, aq_flags, NUM_AQ_FLAGS, TRUE); sprintbit(OLC_QUEST(d)->flags, aq_flags, bits, sizeof(bits)); write_to_output(d, "\r\nQuest flags: @c%s@n\r\n" "Enter quest flags, 0 to quit : ", bits); @@ -612,6 +603,7 @@ void qedit_parse(struct descriptor_data *d, char *arg) OLC_QUEST(d)->qm = number; break; case QEDIT_TYPES: + number--; if (number < 0 || number >= NUM_AQ_TYPES) { write_to_output(d, "Invalid choice!\r\n"); qedit_disp_type_menu(d); diff --git a/src/redit.c b/src/redit.c index a97ab11..e762307 100644 --- a/src/redit.c +++ b/src/redit.c @@ -371,14 +371,11 @@ static void redit_disp_exit_flag_menu(struct descriptor_data *d) static void redit_disp_flag_menu(struct descriptor_data *d) { char bits[MAX_STRING_LENGTH]; - int counter, columns = 0; get_char_colors(d->character); clear_screen(d); - for (counter = 0; counter < NUM_ROOM_FLAGS; counter++) { - write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter + 1, nrm, - room_bits[counter], !(++columns % 2) ? "\r\n" : ""); - } + column_list(d->character, 0, room_bits, NUM_ROOM_FLAGS, TRUE); + sprintbitarray(OLC_ROOM(d)->room_flags, room_bits, RF_ARRAY_MAX, bits); write_to_output(d, "\r\nRoom flags: %s%s%s\r\n" "Enter room flags, 0 to quit : ", cyn, bits, nrm); @@ -388,13 +385,8 @@ static void redit_disp_flag_menu(struct descriptor_data *d) /* For sector type. */ static void redit_disp_sector_menu(struct descriptor_data *d) { - int counter, columns = 0; - clear_screen(d); - for (counter = 0; counter < NUM_ROOM_SECTORS; counter++) { - write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter, nrm, - sector_types[counter], !(++columns % 2) ? "\r\n" : ""); - } + column_list(d->character, 0, sector_types, NUM_ROOM_SECTORS, TRUE); write_to_output(d, "\r\nEnter sector type : "); OLC_MODE(d) = REDIT_SECTOR; } @@ -625,7 +617,7 @@ void redit_parse(struct descriptor_data *d, char *arg) return; case REDIT_SECTOR: - number = atoi(arg); + number = atoi(arg) - 1; if (number < 0 || number >= NUM_ROOM_SECTORS) { write_to_output(d, "Invalid choice!"); redit_disp_sector_menu(d); diff --git a/src/spec_assign.c b/src/spec_assign.c index 8372e74..57dfd2a 100644 --- a/src/spec_assign.c +++ b/src/spec_assign.c @@ -59,7 +59,8 @@ static void ASSIGNROOM(room_vnum room, SPECIAL(fname)) } /* Assignments */ -/* assign special procedures to mobiles */ +/* assign special procedures to mobiles. Guildguards, snake, thief, magic user, + * puff, fido, janitor, and cityguards are now implemented via triggers. */ void assign_mobiles(void) { assign_kings_castle(); diff --git a/src/utils.c b/src/utils.c index 98118c9..5b138e4 100644 --- a/src/utils.c +++ b/src/utils.c @@ -954,6 +954,16 @@ void column_list(struct char_data *ch, int num_cols, const char **list, int list int num_per_col, col_width,r,c,i, offset=0, len=0, temp_len, max_len=0; char buf[MAX_STRING_LENGTH]; + /* Work out the longest list item */ + for (i=0; icharacter, 0, zone_bits, NUM_ZONE_FLAGS, TRUE); sprintbitarray(OLC_ZONE(d)->zone_flags, zone_bits, ZN_ARRAY_MAX, bits); write_to_output(d, "\r\nZone flags: @c%s@n\r\n" @@ -656,25 +652,12 @@ static void zedit_disp_arg2(struct descriptor_data *d) up the input catch clause. */ static void zedit_disp_arg3(struct descriptor_data *d) { - int i = 0; write_to_output(d, "\r\n"); switch (OLC_CMD(d).command) { case 'E': - while (*equipment_types[i] != '\n') { - write_to_output(d, "%2d) %26.26s", i, equipment_types[i]); - - if (*equipment_types[i + 1] != '\n') - write_to_output(d, " %2d) %26.26s", i + 1, - equipment_types[i + 1]); - - write_to_output(d, "\r\n"); - if (*equipment_types[i + 1] != '\n') - i += 2; - else - break; - } + column_list(d->character, 0, equipment_types, NUM_WEARS, TRUE); write_to_output(d, "Location to equip : "); break; case 'P': @@ -730,7 +713,7 @@ void zedit_disp_levels(struct descriptor_data *d) /* The event handler */ void zedit_parse(struct descriptor_data *d, char *arg) { - int pos, i = 0, number; + int pos, number; switch (OLC_MODE(d)) { case ZEDIT_CONFIRM_SAVESTRING: @@ -1104,12 +1087,9 @@ void zedit_parse(struct descriptor_data *d, char *arg) } switch (OLC_CMD(d).command) { case 'E': - pos = atoi(arg); - /* Count number of wear positions. We could use NUM_WEARS, this is - more reliable. */ - while (*equipment_types[i] != '\n') - i++; - if (pos < 0 || pos >= i) + pos = atoi(arg) - 1; + /* Count number of wear positions. */ + if (pos < 0 || pos >= NUM_WEARS) write_to_output(d, "Try again : "); else { OLC_CMD(d).arg3 = pos;