Oh, and it does require the bitmask C version be installed.


Here's an example of how it was used inside of do_get

    if ( arg2[0] == '\0' ) {
        // olist is an OBJ_DATA**, or an array. It must be freed and it's NULL terminated.
        olist = nget_obj_list(ch, arg1, type ? ch->in_room->contents);

        if ( olist[0] == NULL ) {
            act( "I see no $T here.", ch, NULL, arg1, TO_CHAR );
            free(olist);
            return;
        }
       
        // For each item in olist, grab it. it means it met our search critera from nget_obj_list().
        for(i = 0;olist[i];++i) {
            if (olist[i]->item_type == ITEM_CONTAINER || olist[i]->item_type == ITEM_CORPSE_NPC)
                continue;
            get_obj( ch, olist[i], NULL );
        }
        free(olist);
    }

// below this point all goes into act_obj.c or similar

typedef struct obj_find {
    int number; // number in the list to act on.
    int multiple; // How many times? Negative 1 is all.
    BITMASK flags; // Flags to look for.
    char *arg; // string to parse!
    int valid; // Is it valid?
} OBJ_FIND_DATA;

OBJ_FIND_DATA *recursive_obj_flag_search(OBJ_FIND_DATA *ofd) {
    char buf[MSL];
    char *arg, *ptr= buf;

    for(arg = ofd->arg;;++arg) {
        if (!arg || *arg == 0 || *arg == ' ') {
            *ptr = 0;
            return ofd;
        }
        if (*arg == '.') {
            *ptr = 0;
            break;
        }
        *ptr = *arg;
        ++ptr;
    }
    if (is_number(buf)) {
        ofd->number = atoi(buf);
        if (ofd->number < 1 || ofd->number > 100)
            ofd->valid = FALSE;
    }
    else if (!strcmp(buf, "hum"))
        set_bit(&ofd->flags, ITEM_HUM);
    else if (!strcmp(buf, "all"))
        ofd->multiple = 100;
    else if (!strcmp(buf, "empty"))
        set_bit(&ofd->flags, 1000); // Looking for empty object
    else if (buf[0] == 'X' || buf[0] == 'x' || buf[0] == '*') {
        if (!is_number(buf+1))
            ofd->valid = FALSE;
        ofd->multiple = atoi(buf+1);
        if (ofd->multiple < 1 || ofd->multiple > 100)
            ofd->valid = FALSE;
    }

    ofd->arg = arg+1;
    return recursive_obj_flag_search(ofd);
}

OBJ_DATA **nget_obj_list(CHAR_DATA *ch, char *arg, OBJ_DATA *from_list) {
    OBJ_FIND_DATA ofd;
    static BITMASK bmclear;
    OBJ_DATA **oarray;
    int which = 0;
    int num_pass;
    int count = 0;

    oarray = (OBJ_DATA **) malloc(sizeof(OBJ_DATA *) * 101);

    BITMASK found = bmclear;

    OBJ_DATA *pObj;

    ofd.valid = TRUE;
    ofd.number = 1;
    ofd.multiple = 1;
    ofd.flags = bmclear;
    ofd.arg = arg;

    if (!recursive_obj_flag_search(&ofd)->valid) {
        free_bitmask(&ofd.flags);
        oarray[0] = 0;
        return oarray;
    }
    while(which < ofd.multiple || (!strcmp(ofd.arg, "all") && which < 100)) {
        num_pass = 0;
        for(pObj = from_list;pObj;pObj = pObj->next_content) {
            if (pObj->wear_loc != WEAR_NONE)
                continue;
            if (strcmp(ofd.arg, "all") && !is_name (ofd.arg, pObj->name))
                continue;
            if (!can_see_obj(ch, pObj))
                continue;
            if (is_set(&ofd.flags, ITEM_HUM))
                if (!IS_SET(pObj->extra_flags, ITEM_HUM))
                    continue;
            if (is_set(&ofd.flags, 1000)) // For empty things only
                if (pObj->item_type != ITEM_ARROW || pObj->value[3] != 0)
                    continue;


            if (is_set(&found, (int)pObj))
                continue;

            ++num_pass;

            if (num_pass == ofd.number)
                break;
        }
        oarray[which] = pObj;
        if (pObj == NULL)
            break;
        set_bit(&found, (int)pObj);
        ++which;
    }
    oarray[which] = NULL;
    free_bitmask(&found);
    free_bitmask(&ofd.flags);
    return oarray;
}