Заказать Сервер Заказать Плагин Контакты Поиск

[ вход ]
[ последние сообщения ]

Страница 1 из 11
Форум » SourceMod - Counter Strike Source && CS GO » Обсуждение » Сложный(наверное) алгоритм рандомизации
Сложный(наверное) алгоритм рандомизации
Black_Hawk1451 Дата: Воскресенье, 13.03.2016, 23:26:34 | Сообщение # 1
Сообщений: 11
Репутация: 0 [ +/- ]
Итак, представим что у меня есть 48 различных картинок.
Среди этих 48 картинок существует 14 картинок в единичном экземпляре а остальные 17 повторяются только 1 раз(т.е. двойной экземпляр). Итого 14 + 17*2 = 48. При этом среди 14 картинок в единичном экземпляре существует еще 10 единичных VIP-картинок.

Далее, представим что у меня есть 10 телевизоров, среди которых есть один VIP-телевизор. И я хочу чтобы при старте карты происходил такой алгоритм:
- в первом телевизоре отображается рандомная картинка из 48 оставшихся
- во втором телевизоре отображается рандомная картинка из 47 оставшихся, при этом, она не должна повторяться с первой!
- в третьем телевизоре отображается рандомная картинка из 46 оставшихся, при этом, она не должна повторяться с первой и второй!
...и так далее до десятого телевизора.
- в десятом, VIP-телевизоре, может отобразиться только одна из 10 VIP-картинок, при этом она, конечно же, не должна повторяться с теми, которые уже могли появиться на предыдущих 9 телевизорах. То есть, должна быть реальна ситуация, когда на всех 9 обычных телевизорах появились VIP-картинки.
Однако, повторяться не должен только порядковый номер каждой картинки. Те картинки, которые в двойном экземпляре, имеют бОльший шанс на появление на телевизоре и должны иметь возможность при проходе этого алгоритма появиться, например, на двух разных телевизорах.

Затем, у меня должна быть возможность один раз активировать второй триггер для каждого телевизора.
Его алгоритм должен быть следующим(тут у меня 2 варианта):

I вариант:
- На каждом телевизоре, кроме VIP, я могу нажать, например, на красную кнопку, и после нажатия картинка на этом телевизоре должна смениться на любую из оставшихся 28-38 картинок, так как 10 картинок уже были использованы в первом триггере и еще максимум 10 могут быть использованы. На VIP-телевизоре же кнопка должна выполнять ту же функцию, но выбирать только из оставшихся VIP-картинок(мог ошибиться в подсчетах на единичку, хочется спать, извиняйте )

II вариант:
- На каждом телевизоре я могу нажать, например, на красную кнопку, и таким образом отметить все телевизоры,
картинки на которых я хочу поменять. Затем нажать, например, на оранжевую кнопку(она одна) и после этого все картинки на отмеченных телевизорах сменятся на те, которые еще не были использованы.

Второй вариант мне кажется более геморным, поэтому я его не особо рассматриваю. Но, возможно, я ошибаюсь.

В общем, на форуме мапперов мне сказали, что сурс движок не очень хорошо ладит с использованием большого количества энтитей(а там по-другому никак :c) и посоветовали написать отдельный плагин под все это дело.
Я подумал над этим и примерно набросал как это должно выглядеть:

1. Первым делом нужно объявить переменные из карты в самом плагине, а также привязать нажатия кнопок и мб что-то еще.
2. Затем, мне нужна такая функция, которая из 48 чисел(от 1 до 48 включительно) выберет 9 штук без повторений. Не знаю, реально ли такое в языке SourcePawn, но раз в редакторе карт такая возможность есть, то скорее всего и в языке должна быть.
3. Когда выбралось какое-то число, то передавать на карту в нужные энтити(через targetname) 2 значения:
- номер попытки(от 1 до 9)
- число, которое выбралось рандомно и без повторений(от 1 до 48, ноль учитывать не нужно)
4. Еще должен быть случайный выбор из 10 VIP-картинок, без повторений. Кстати, скорее всего именно его нужно провести первым и затем как-то передать полученное число в функцию из пункта 2, чтобы это же число не могло быть выбрано, т.е VIP-картинка никак не повторится. Опять же не знаю, возможно ли это или нет.
5. Теперь к функции перевыбора. Она должна быть привязана к 10 кнопкам.
6. При нажатии на любую не VIP-кнопку, она должна передавать на карту в нужную энтити:
- новое рандомное число(все также без повторений)
Передавать номер попытки уже не стоит, так как это будет делать своя собственная кнопка на каждом телевизоре.
7. При нажатии на VIP-кнопку происходить должно все то же самое, только новое рандомное число выбирается уже как минимум из 9 вариантов и, конечно же, не должно быть повторений.

Заранее выложу список энтитей, используемых в этом плагине:
10 штук func_wall - телевизоры, каждый со своим именем, начиная с televisor[1,2,3...10].
10 штук func_button - кнопки на телевизорах, каждая со своим именем, but[1,2,3...10]
10 штук env_texturetoggle - энтити, отвечающие за смену текстуры на другую. Каждая со своим именем, texture[1,2,3...10]
9 штук math_counter - энтити, отвечающие за выбор правильного телевизора при первом проходе алгоритма рандома. В них передаются попытки. Для VIP-телевизора такая не нужна, потому что он всего лишь один, и работает, по сути, по другому алгоритму рандома. counter[1,2,3...9].
Последние, теоретически, можно убрать если в самый первый проход рандома добавить такую вещь, что выбранное число будет по очереди для каждой texture[1,2,3...10] именно в самом плагине активировать команду SetTextureIndex [число]. Опять же не знаю насколько реально через плагины активировать команды из редактора карт.

Я честно не знаю насколько муторный должен получиться плагин, мб кто-то тут подобные за пять минут пишет. Тем не менее, я не прошу Вас написать его за меня, мне просто нужны подсказки, мб примеры плагинов с исходниками, где подобный алгоритм уже был реализован и т.д.
Если нужен будет исходник карты, то могу кинуть чуть позже. В данный момент он немного не соответствует тому, о чем я написал выше.
Заранее очень благодарен за любую помощь!


Сообщение отредактировал Black_Hawk1451 - Понедельник, 14.03.2016, 00:37:37
 
barcelona58341 Дата: Понедельник, 14.03.2016, 10:23:00 | Сообщение # 2
Сообщений: 18
Репутация: 0 [ +/- ]
Цитата
Заранее выложу список энтитей, используемых в этом плагине:

Реализация, можно сделать но по другими функциями без некоторых энтитей, а подобный плагин наверно нету
 
BarD Дата: Понедельник, 14.03.2016, 12:51:57 | Сообщение # 3
Сообщений: 944
Репутация: 132 [ +/- ]
Не очень понял, что тебе нужно. Попробуй затолкать в массив все картинки и отсортируй через
Код
SortIntegers(array[], array_size, Sort_Random);

Затем выцепляй по одной. Гарантированно будет без повторений.


Сообщение отредактировал BarD - Понедельник, 14.03.2016, 12:52:17
 
_wS_ Дата: Понедельник, 14.03.2016, 13:40:09 | Сообщение # 4
Цитата BarD ()
Не очень понял, что тебе нужно

+1, как-то запутан(н?)о. Говоришь что одни картинки повторяются, другие нет, но на каждом телевизоре должна быть уникальная картинка без повторений, зачем тогда инфа о том что какие-то повторяются, а какие-то нет? Исходя из того что я понял, вот пару строк кода:

Код
// Текущая картинка на телевизоре
new Handle:g_hCurrentTvImageAr;

// Номера картинок
new Handle:g_hImageAr;

public OnPlubinStart()
{
    decl i;

    // по умолчанию у каждого телевизора (от 1 до 10) картинка отключена (0)
    g_hCurrentTvImageAr = CreateArray(1);
    for (i = 1; i < 11; i++) PushArrayCell(g_hCurrentTvImageAr, 0);

    // номера картинок от 1 до 48 (вип картинки от 1 до 10)
    g_hImageAr = CreateArray(1);
    for (i = 1; i < 49; i++) PushArrayCell(g_hImageAr, i);
}

// Меняем картинку (на телевизорах всегда разные картинки)
// Tv - номер телевизора от 1 до 10
stock wS_SetRandomTvImage(Tv)
{
    decl image;
    new max = Tv == 10 ? 10 : 48;

    new Handle:hAr = CreateArray(1);
    for (new i = 0; i < max; i++)
    {
        image = GetArrayCell(g_hImageAr, i);
        if (FindValueInArray(g_hCurrentTvImageAr, image) < 0)
        {
            PushArrayCell(hAr, image);
        }
    }
    image = GetArrayCell(hAr, GetRandomInt(0, GetArraySize(hAr) - 1));
    CloseHandle(hAr);

    SetArrayCell(g_hCurrentTvImageAr, --Tv, image);

    SetVariantInt(image);
    AcceptEntityInput(env_texturetoggle_ENTITY_INDEX, "SetTextureIndex");

    --
    вместо AcceptEntityInput(env_texturetoggle_ENTITY_INDEX, "SetTextureIndex");
    можно попробовать так:

    decl String:info[65];
    new entity = CreateEntityByName("info_target");
    FormatEx(info, 65, "env_texturetoggle_%d,SetTextureIndex,%d,0,1", Tv, image);
    DispatchKeyValue(entity,  "OnUser1", info);
    AcceptEntityInput(entity, "FireUser1");
    AcceptEntityInput(entity, "Kill");
    --
}
 
Black_Hawk1451 Дата: Понедельник, 14.03.2016, 15:28:24 | Сообщение # 5
Сообщений: 11
Репутация: 0 [ +/- ]
Цитата _wS_ ()
+1, как-то запутан(н?)о. Говоришь что одни картинки повторяются, другие нет, но на каждом телевизоре должна быть уникальная картинка без повторений, зачем тогда инфа о том что какие-то повторяются, а какие-то нет? Исходя из того что я понял, вот пару строк кода:


Сорри если запутал, просто считал должным донести эту информацию. Еще раз более подробно объясню:
Всего 31 картинка, из них:
14 - в единичном экземпляре, среди которых 10 являются VIP-картинками
17 - в двойном экземпляре.
Каждой картинке присвоен свой порядковый номер, в том числе и двойным, именно из-за этого условия общее количество возможных картинок вырастает до 48. Надеюсь, сейчас стало более понятно.

_wS_, по коду есть несколько вопросов:
1. Я не много не понял в каком месте я должен подставить имена своих энтитей в код, чтобы плагин работал корректно.

2. Не понял вот эту строку:
Код
// номера картинок от 1 до 48 (вип картинки от 1 до 10)
    g_hImageAr = CreateArray(1);
    for (i = 1; i < 49; i++) PushArrayCell(g_hImageAr, i);

То есть для этого кода я должен буду заранее обозначить все вип картинки под порядковыми номерами от 1 до 10?

3. По поводу этой строки:
Код
    // по умолчанию у каждого телевизора (от 1 до 10) картинка отключена (0)
    g_hCurrentTvImageAr = CreateArray(1);
    for (i = 1; i < 11; i++) PushArrayCell(g_hCurrentTvImageAr, 0);

А есть ли в ней смысл? Если я заранее на карте могу сделать так, что картинки будут отключены.

4. Вот в этой функции очень много непонятных для меня вещей, был бы признателен если бы Вы смогли оставить хотя бы комментарий рядом с каждой строчкой:
Код
stock wS_SetRandomTvImage(Tv)
{
    decl image;
    new max = Tv == 10 ? 10 : 48;

    new Handle:hAr = CreateArray(1);
    for (new i = 0; i < max; i++)
    {
        image = GetArrayCell(g_hImageAr, i);
        if (FindValueInArray(g_hCurrentTvImageAr, image) < 0)
        {
            PushArrayCell(hAr, image);
        }
    }
    image = GetRandomInt(0, GetArraySize(hAr) - 1);
    CloseHandle(hAr);

    SetArrayCell(g_hCurrentTvImageAr, --Tv, image);

    SetVariantInt(image);
    AcceptEntityInput(env_texturetoggle_ENTITY_INDEX, "SetTextureIndex");


Пока попробую сам разобраться в Вашем коде, но, чувствую, это будет ооочень долго :<
 
Форум » SourceMod - Counter Strike Source && CS GO » Обсуждение » Сложный(наверное) алгоритм рандомизации
Страница 1 из 11
Поиск: