char* selectionList; //list of items to be used by loop to be put in pc_data or in the character somewhere if you want mob to ba able to use it, your call

void free_string( char **pstr) {
    if ( !*pstr || (*pstr == &str_empty[0]))
        return;
    free(*pstr);
    *pstr = NULL;
}

/**
 * Caller is responsible for freeing pstr
 * warning if pstr is set to empty string
 * to malloc is done, string is assigned &str_empyt[0]
 */
void replace_string(char **pstr, char *nstr) {
    if (*pstr && *pstr != &str_empty[0])
        free_string( &*pstr);
    if ( !nstr || nstr == &str_empty[0])
        *pstr = &str_empty[0];
    else {
        *pstr = (char *)malloc((strlen(nstr) + 1) * sizeof(char));
        strcpy( *pstr, nstr);
    }
}

bool_t do_loop(CHAR_DATA *ch, char *argument) {
    if ( !ch || !ch->valid || !argument)
        return FALSE;
    char helpmsg[MAX_STRING_LENGTH];
    sprintf(helpmsg, "loop <number of times/selection> <looping command>\n\r");
    char arg1[MAX_INPUT_LENGTH];
    argument = one_argument(argument, arg1);

    if (arg1[0] == '\0' || argument[0] == '\0') {
        send_to_char(helpmsg, ch);
        return FALSE;
    }
    if (is_number(arg1)) {
        int value = is_number(arg1) ? atoi(arg1) : -1;
        if (value < 0) {
            send_to_char("How many times ?\n\r", ch);
            return FALSE;
        }
        int i;
        if (IS_IMMORTAL(ch)) {
            for (i = 0;i < value;i ++)
                if ( !interpret(ch, argument, FALSE))
                    break;
        }
        else {
            for (i = 0;i < value;i ++) {
                if (strlen(ch->desc->inbuf) +strlen(argument) < 128 * MAX_INPUT_LENGTH - 6) {//char inbuf[128 * MAX_INPUT_LENGTH]
                    strcat(ch->desc->inbuf, argument);
                    strcat(ch->desc->inbuf, "\n\r");
                }
            }
        }
        return TRUE;
    }
    if ( !str_cmp(arg1, "selection")) {
        if (ch->pcdata->selectionList == &str_empty[0]) {
            send_to_char("Your selection list is empty\n\r", ch);
            return FALSE;
        }
        char *command = &str_empty[0];
        replace_string( &command, argument);
        char *numberList = ch->pcdata->selectionList;
        char arg[MAX_INPUT_LENGTH];
        for (numberList = one_argument(numberList, arg); arg[0] != '\0';) {
            command = string_replace(command, "<xxx>", arg);
            if (IS_IMMORTAL(ch)) {
                if ( !interpret(ch, command, FALSE))
                    break;
            }
            else {
                if (strlen(ch->desc->inbuf) + strlen(command) < 128 * MAX_INPUT_LENGTH - 6) { //char inbuf[128 * MAX_INPUT_LENGTH]
                    strcat(ch->desc->inbuf, command);
                    strcat(ch->desc->inbuf, "\n\r");
                }
            }
            replace_string( &command, argument);
            arg[0] = '\0';
            numberList = one_argument(numberList, arg);
        }
        free_string(&command);
        return TRUE;
    }
    send_to_char(helpmsg, ch);
    return FALSE;
}

bool_t do_selection(CHAR_DATA *ch, char *argument) {
    if ( !ch || !ch->valid || !argument || IS_NPC(ch))
        return FALSE;
    char helpmsg[MAX_STRING_LENGTH];
    sprintf(helpmsg, "Usage: selection <start> <end> or <clear> or <show> or <number/string>\n\r");
    char arg[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
    argument = one_argument(argument, arg);
    argument = one_argument(argument, arg2);

    if (arg[0] == '\0') {
        send_to_char(helpmsg, ch);
        return FALSE;
    }

    if ( !str_cmp(arg, "clear")) {
        free_string( &ch->pcdata->selectionList);
        ch->pcdata->selectionList = &str_empty[0];
        return TRUE;
    }
    char buf[MAX_STRING_LENGTH];
    buf[0] = '\0';
    char *argLeft = ch->pcdata->selectionList;
    if ( !str_cmp(arg, "show")) {
        if (ch->pcdata->selectionList == &str_empty[0]) {
            send_to_char("Your selection list is empty\n\r", ch);
            return FALSE;
        }
        short int count = 1;

        for (argLeft = one_argument(argLeft, arg); arg[0] != '\0';) {
            sprintf(buf, "%s %6s", buf, arg);
            if (count ++ % 13 == 0) {
                chprintf(ch, "%s\n\r", buf);
                buf[0] = '\0';
                count = 1;
            }
            arg[0] = '\0';
            argLeft = one_argument(argLeft, arg);
        }
        if (buf[0] != '\0')
            chprintf(ch, "%6s\n\r", buf);
        return TRUE;
    }

    if (is_number(arg) && arg2[0] != '\0' && is_number(arg2)) {
        char buf[(strlen(arg2) + 1) * (atoi(arg2) - atoi(arg) + 1)];
        buf[0] = '\0';
        short int i;
        for (i = atoi(arg);i <= atoi(arg2);i ++)
            sprintf(buf, "%s%6d ", buf, i);
        replace_string( &ch->pcdata->selectionList, buf);
        send_to_char("Selection filled\n\r", ch);
        return TRUE;
    }

    if (ch->pcdata->selectionList == &str_empty[0]) {
        replace_string( &ch->pcdata->selectionList, arg);
        chprintf(ch, "%s inserted.\n\r", arg);
        return TRUE;
    }
    char value[MAX_INPUT_LENGTH];
    sprintf(value, "%s", arg);
    bool_t isRemoved = FALSE, isInserted = FALSE;
    for (argLeft = one_argument(argLeft, arg);arg[0] != '\0';) {
        if (str_cmp(arg, value)) {
            if ( !isInserted && !isRemoved) {
                if ((is_number(value) && is_number(arg) && atoi(value) < atoi(arg))
                                || ( !is_number(value) && strcmp(value, arg) < 0)) {
                    sprintf(buf, "%s %s", buf, value);
                    isInserted = TRUE;
                }
            }
            sprintf(buf, "%s %s", buf, arg);
        }
        else
            isRemoved = TRUE;
        arg[0] = '\0';
        argLeft = one_argument(argLeft, arg);
    }
    if ( !isRemoved && !isInserted)
        sprintf(buf, "%s %s", buf, value);
    trim(buf);
    if (buf[0] == '\0') {
        free_string( &ch->pcdata->selectionList);
        ch->pcdata->selectionList = &str_empty[0];
    }
    else
        replace_string( &ch->pcdata->selectionList, buf);
    chprintf(ch, "%s %s.\n\r", value, isRemoved ? "removed" : "inserted");
    return TRUE;
}