I made a few alterations...
1) Added
get_random_eq and
get_random_inventory functions. This means that if the player has ANY eq (or inventory), it will return one random item. If the player has no worn eq/inventory, it returns NULL. This is less hit-and-miss than just randomly choosing an eq slot or cycling through a player's inventory with a 1-in-4 chance of picking each item.
2) Removed the msg boolean variable. Can just send NULL for the text, or an empty string, if you don't want to show a message.
3) Changed the while loop to a for loop. This is really personal preference - I just prefer for loops, which seem to get 'stuck' in an infinite loop less often. I know it's a cosmetic change.
4) Changed
rand_number(1,20) < 5 to
!rand_number(0,3) - still a 1-in-4 chance, just tidier.
5) Removed the for loop for the inventory, and removed the
break; that was in there. I don't use break in a loop, simply because I was taught it was wrong (like using a goto, because the program can jump about unexpectedly). Not all coders agree that it's wrong, and I now believe that using break in a loop isn't 'wrong' if it's clear why it's used (usually with a comment).
6) Removed 'tries' because now, each time through the main loop, it
WILL find an eq or inventory item, there are no 'misses'. The 1-in-4 chance of removing an inventory item remains, but if that misses, it still counts (tries wasn't updated here before anyway). Instead, loop ends if found == FALSE
Other considerations:
I did think about converting the send_to_char's to acts. This would involve changing this:
send_to_char(ch, "%s's %s %s\r\n", GET_NAME(vict), GET_OBJ_NAME(obj), text);
to this
char buf[MAX_STRING_LENGTH];
sprintf(buf, "$n's $o %s\r\n", text);
act (buf, TRUE, ch, obj, vict, TO_NOTVICT);
which may seem like a lot more work, but it allows everyone in the room to see the destruction, not just the destroyer.
Anyways, here's all the changed code, note that all of this code below is untested:
struct obj_data *get_random_eq(struct char_data *ch)
{
struct obj_data *eq_list[NUM_WEARS], *obj;
int num_found=0, i;
if (!ch) return NULL;
/* Cycle through slots */
for (i=0; i<NUM_WEARS; i++) {
if (GET_EQ(ch, i)) {
/* Found one, add it to the list */
eq_list[num_found] = GET_EQ(ch, i);
num_found++;
}
}
if (num_found == 0)
return NULL;
/* Pick one of the eq items at random */
obj = eq_list[(rand_number(0, num_found))];
return obj;
}
struct obj_data *get_random_inventory(struct char_data *ch)
{
struct obj_data *eq_list[NUM_WEARS], *obj;
int num_found=0, o_num, i;
if (if !ch || ch->carrying == NULL)
return NULL;
/* Count inventory items */
for (obj = ch->carrying; obj; obj = obj->next_content)
num_found++;
/* Pick one at random */
o_num = rand_number(0, num_found);
/* Jump to the correct item in the inventory */
for (obj = ch->carrying, i=0; obj && i<o_num; obj = obj->next_content) i++;
return obj;
}
/*
* This function destroys equipment worn by the character, or possibly in the character's equipment.
* @params: character, victim, how many pieces to destroy, destroy inventory pieces?, send victim a message?,
* message text (which will be appended after the object's name)
* Ulath
*/
void destroy_equip(struct char_data *ch, struct char_data *vict, ush_int pieces, bool inv, char *text)
{
ush_int num = 0, tries = 0;
bool found;
struct obj_data *obj = NULL;
for (num=0; num < pieces && found; num++) {
found = FALSE;
obj = get_random_eq(vict);
if (obj && OBJ_FLAGGED(obj, ITEM_RELIC | ITEM_QUEST | ITEM_RARE | ITEM_NODISIN) && text && *text) {
send_to_char(vict, "Your %s protects itself from destruction!\r\n", GET_OBJ_NAME(obj));
send_to_char(ch, "%s's %s protects itself from destruction!\r\n", GET_NAME(vict), GET_OBJ_NAME(obj));
} else if (obj) {
if (text && *text) {
send_to_char(vict, "Your %s %s\r\n", GET_OBJ_NAME(obj), text);
send_to_char(ch, "%s's %s %s\r\n", GET_NAME(vict), GET_OBJ_NAME(obj), text);
}
found = TRUE;
extract_obj(obj);
}
else if (!found && inv) {
obj = get_random_inventory(vict);
if (obj && !rand_number(0, 3) && !OBJ_FLAGGED(obj, ITEM_RELIC | ITEM_QUEST | ITEM_RARE | ITEM_NODISIN)) {
if (msg) {
send_to_char(vict, "Your %s %s\r\n", GET_OBJ_NAME(obj), text);
send_to_char(ch, "%s's %s %s\r\n", GET_NAME(vict), GET_OBJ_NAME(obj), text);
}
extract_obj(obj);
found = TRUE;
}
}
}
}