Алгоритмы, Наработки и Способности
Способ реализации:
cJass
Тип:
Наработка
Искал-искал когда-то, не нашёл, может тоже кто-то будет искать, пусть найдёт
Функция сложения или вычитания шансов по Формуле убывающей полезности из Dota 2
phantom_miss_chance - текущий шанс уклонения
Чтобы "Добавить Фантомке Бабочку" нужно ввести RecalculateChance(phantom_miss_chance, 35)
Чтобы "Забрать у Фантомки Бабочку" нужно ввести RecalculateChance(phantom_miss_chance, -35)
//changing_chance - Шанс который будем менять
//change - На сколько изменить
//Возвращает полученный шанс

function RecalculateChance takes real changing_chance, real change returns real
	local real new_changing_chance = 0
	if change >= 0 then 
		if changing_chance >= 0 and changing_chance >= change
			new_changing_chance = changing_chance+((100 - changing_chance)/100*change)
		elseif changing_chance >= 0 and changing_chance < change
			new_changing_chance = changing_chance+((100 - changing_chance)/100*change)
		elseif changing_chance < 0 and -changing_chance >= change
			changing_chance = -changing_chance
			new_changing_chance = -(100 - ((100 - changing_chance) / (1-(change/100))))
		elseif changing_chance < 0 and -changing_chance < change
			changing_chance = -changing_chance
			new_changing_chance = 100 - (100 - change) / (1 - changing_chance/100)                
		endif
	else 
		change = -change
		if changing_chance >= 0 and changing_chance >= change
			new_changing_chance = 100 - ((100 - changing_chance) / (1-(change/100)))
		elseif changing_chance >= 0 and changing_chance < change
			new_changing_chance = -(100 - (100 - change) / (1 - changing_chance/100)) 
		elseif changing_chance < 0 and -changing_chance >= change
			changing_chance = -changing_chance
			new_changing_chance = -(changing_chance -((100-changing_chance) * (1/(1-(change/100))) - (100-changing_chance)))
		elseif changing_chance < 0 and -changing_chance < change
			changing_chance = -changing_chance
			new_changing_chance = 100 - (100 - change) / (1 - changing_chance/100)
		endif
	endif
	return new_changing_chance
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...
16
Без set, значит это vJass?
Ответы (21)
8
Ydav, Наверное, могу расставить все call, set, then если нужно
16
KaneThaumaturge, да, меня сбило, что тут он нетипичный
16
Tredor46, код на cJASS не очень стабильный с другим кодом, как я понимаю. Сам на нем писал когда-то, но сейчас от него отказываются, чтобы ничего не ломать. А сбило меня конкретно то, что в cJASS обычно пишут не function и т.д., а в сишном стиле:
тип ИмяФункции(аргументы) {
...
}
15
Ydav, а если он просто юзает какой нибудь JNGP 2013 года где это не обязательно писать ?!
16
LastUchiha, не понял вопроса, не обязательно писать set\call? Тогда это и есть cJASS, а значит все описанные выше проблемы могут быть
9
Tredor46, код на cJASS не очень стабильный с другим кодом, как я понимаю. Сам на нем писал когда-то, но сейчас от него отказываются, чтобы ничего не ломать. А сбило меня конкретно то, что в cJASS обычно пишут не function и т.д., а в сишном стиле:
тип ИмяФункции(аргументы) {
...
}
Ну вообще от него никто не отказывается по причинам описанным выше.
Просто в UJAPI и REFORGED нет поддержки cjass.
Если бы она была там, то все бы и дальше юзали, потому-что это правда очень удобно.
Скорп давал наводку, я пытался разобраться, но пока мозгов недостаточно осилить HEX редактор.
30
Smeto, в ужопе есть AngelScript, который заруливает ваши сижасы с луа на пару. Так что не нужно заливать. Да и писать на сижасе под ужопу ничего не мешает кроме конечно отсутствия мыслительных процессов.
25
Smeto,
Просто в UJAPI и REFORGED нет поддержки cjass.
А с каких пор ужопа и рефа стали мерилами хоть чего-то в ру коммьюнити? Посоны тут кулаком в грудь бьют, кричат, что лучше ванильного 1.26a ещё ничего в этом мире не придумано (утрирую конечно, но тем не менее).
9
Makeba,
Так это вы тут топите за 1.26 и ужопу, позабыв мнение людей которые за Рефу. А так это всегда актуально, если абстрагироваться от говно выбросов
>Если внимательно посмотреть вопросы или посты где есть рефа, там обязательно, например, Назар напишет, что РЕФ ГОВНО, а УЖОПА БОЖЕСТВО.
Я за рефу, там все прелести ванильки и даже больше.
9
nazarpunk, чудо кстати какое-то, за последние время, не слышно про то какой реф говно.
Какой же реф плохой да? А что если сказать ужопа плохая, сразу 100500 пруфов вылетит
"ты не поверишь, но прямо сейчас, на ваших глазах творится история пишутся тулзы для оптимизации всего этого дела. Да и почему ты решил, что на рефе будет грамотней, раз кардинально там ничего не завезли и так же ничего не мешает насовать неиспользуемого импорта?"
"ИМХО он прекрасен именно в ванилле. Переход на реф такое. А фреймами можно обмазаться и на UjAPI. Правда придётся кастомный сейвлоад писать."
"Ещёб тоже самое под реф.графику))
В приличном обществе упоминать это поделие не принято."
30
Smeto, ну и в какой из приведённых и вырванных из контекста цитат ты увидел "что РЕФ ГОВНО, а УЖОПА БОЖЕСТВО"?
8
Makeba, а в UjAPI правда нет поддержки cJass? Я уже тут запустался
30
Tredor46, какое отношение сижас имеет к ужопе? Сижасс компилит скрипт, а ужопа уже запускает то что накомпилилось.
8
nazarpunk, Я вот и думаю что не так, у меня же всё работает
25
Я не совсем понимаю, что конкретно мы тут считаем, и (не)читабельность простыни ифов не способствует этому пониманию. И похоже, что автор сам в ней запутался. Типа здесь при разных условиях выполняется одна операция
		if changing_chance >= 0 and changing_chance >= change
			new_changing_chance = changing_chance+((100 - changing_chance)/100*change)
		elseif changing_chance >= 0 and changing_chance < change
			new_changing_chance = changing_chance+((100 - changing_chance)/100*change)
Это просто то, что бросилось в глаза, уверен, что тут добрую половину кода можно сократить, и ничего не изменится.

		elseif changing_chance >= 0 and changing_chance < change
			new_changing_chance = -(100 - (100 - change) / (1 - changing_chance/100)) 
Тут деления на ноль случайно выскочить не может?
Ответы (24)
38
Makeba, видишь NaN? А он есть!)
Ставишь changing_chance = 100.0 и ловишь NaN
25
ScorpioT1000, не, ну тут ещё при условии, что change будет больше 100.0. Если пользователь кода считает вероятности в пределах 100, то может таких ситуаций и не предвидится. Правда я всё равно до конца не понимаю, что по факту должно быть на входе, и что на выходе. Типа задача ясна: если есть два предмета на миссы, то их общая вероятность мисса должна считаться не простым сложением, но понять чё тут по факту происходит я не в состоянии, а с этим сижассом ещё и фиг проверишь
8
ScorpioT1000, Ну блин, ставить значения >= 100 Бессмысленно, нужна ли тут проверка или дописать комментай типа не ставите значния >= 100?
8
Makeba, changing_chance это текущий шанс (например у нас сейчас шанс уклонения 50%)
change это насколько изменить шанс (например если у нас сейчас шанс уклонения 50% и change = 50%, то 50% + 50% = 75%)
Эти 75% и вернуться
function RecalculateChance takes real changing_chance, real change returns real
        local real new_changing_chance = 0
        if change >= 0 then //+ Шансы
            if changing_chance >= 0 and changing_chance >= change
                new_changing_chance = changing_chance+((100 - changing_chance)/100*change)
                //60+((100 - 60)/100*50 = 80
                //80+((100 - 80)/100*80 = 96
            elseif changing_chance >= 0 and changing_chance < change
                new_changing_chance = changing_chance+((100 - changing_chance)/100*change)
                //50+((100 - 50)/100*60 = 80
                
            elseif changing_chance < 0 and -changing_chance >= change
                changing_chance = -changing_chance
                new_changing_chance = -(100 - ((100 - changing_chance) / (1-(change/100))))
                //100 - (100 - 80) / (1 - 50/100) = 60
            elseif changing_chance < 0 and -changing_chance < change
                changing_chance = -changing_chance
                new_changing_chance = 100 - (100 - change) / (1 - changing_chance/100)                
                //-(100 - ((100 - 80) / (1-(50/100)))) = -60
            endif
        else //Минус шансы
            change = -change
            if changing_chance >= 0 and changing_chance >= change
                new_changing_chance = 100 - ((100 - changing_chance) / (1-(change/100)))
                //100 - ((100 - 80) / (1-(50/100))) = 60
            elseif changing_chance >= 0 and changing_chance < change
                new_changing_chance = -(100 - (100 - change) / (1 - changing_chance/100)) 
                //-(100 - (100 - 80) / (1 - 50/100)) = -60
                
            elseif changing_chance < 0 and -changing_chance >= change
                changing_chance = -changing_chance
                new_changing_chance = -(changing_chance -((100-changing_chance) * (1/(1-(change/100))) - (100-changing_chance)))
                //80-((100 - 80)/100*60 = 50
                
                //1-(60/100) = 0.4 = 80 -((100-80) * (1/0.4) - (100-80))
                //(1-(60/100)) = 0.4 = 80 -((100-80) * (1/(1-(60/100))) - (100-80))
                //-(90 -((100-90) * (1/(1-(50/100))) - (100-90))) = -80
            elseif changing_chance < 0 and -changing_chance < change
                changing_chance = -changing_chance
                new_changing_chance = 100 - (100 - change) / (1 - changing_chance/100)
                //100 - (100 - 80) / (1 - 50/100) = 60
            endif
        endif
        
        return new_changing_chance
    endfunction
38
Tredor46, надо оперировать абсолютными величинами, а не процентами. Но если все-таки хочется процентами по какой-то космической причине, умножай на 0.01, а не дели на 100. Деление - долгая операция.
25
Tredor46, слушай, а где ты вообще этот алгоритм нашёл? Я загуглил убывающую полезность в доте 2, нашёл обсуждение на д2ру
Это оно? То есть вся формула это P = 1 - (1 - p1) * (1 - p2) * ... * (1 - pn)? А что ты тогда проверяешь ифами?
Ну типа блин
function sumProbabilities(...)
    local p = 100
    for _, v in ipairs {...} do
        p = p * (100 - v) / 100
    end
    return 100 - p
end

print(sumProbabilities(50, 50)) -- 75.0
print(sumProbabilities(35, 35)) -- 57.75
print(sumProbabilities(10, 20, 30)) -- 49.6
print(sumProbabilities(35, 35, 35, 35, 35, 35)) -- 92.458
print(sumProbabilities()) -- 0
Ну ладно, если нужно ещё отнимать отрицательные, то придётся чутка усложнить, и взять модуль числа, но серьёзно, в чём соль?
Загруженные файлы
8
Makeba, Так одна формула это если их просто складывать, а если нужно вычитать или тем более чтобы оно в минус нормально уходило, нужно несколько формул (по крайней мере я не знаю как это сделать одной)
Вот там это всё и проверяется
25
Tredor46,
или тем более чтобы оно в минус нормально уходило
Чтобы оно в минус нормально уходило придётся ввести понятие отрицательной вероятности, и придумать как его использовать в контексте проверки на шанс промаха по юниту
30
Чтобы оно в минус нормально уходило придётся ввести понятие отрицательной вероятности
Вероятность это количество удачных исходов делённые на количество всех исходов. Чтоб при делении двух чисел получилось отрицательное число необходимо чтоб одно из чисел было отрицательным. Удачи это натянуть на сову исходов.
С другой стороны можно вообще переопределить отрицательую ось, но разумно ли этим заниматься в рамках варкрафта?
8
Makeba, Да всё просто, типо...
Есть герой со способностью "Снижает шанс уклонения врага на 75% на 20 секунд", допустим он применил её на врага
У врага станет -75% Уклонения, если враг в течении этих 20 секунд решит, например закупить предмет, дающий ему 75% уклонения, то уклонение врага станет равно = 0 и враг всё ещё не сможет уклоняться
30
Я ничего найти не смог, сам написал, что смог
А что ты вообще писал то? Можешь математическую базу сего действа привести?
8
nazarpunk, Какая математическая база? (Скорее всего её нет)
Я не понял о чём ты
30
Да всё просто, типо...
А где здесь убывающая полезность и зачем городить такой костыль что б по сути решить неравенство 75 + (-75) = 0?
30
Какая математическая база?
У тебя в заголовке красуется слово "Формула", да ещё и с заглавной буквы. Что как-бы подразумевает что ты взял какой-то алгоритм и воплотил его в коде. Так вот, можно глянуть на сам алгоритм в голом виде?
8
nazarpunk, не, это просто пример с неудачными числами...
Есть герой со способностью "Снижает шанс уклонения врага на 75% на 20 секунд", допустим он применил её на врага
У врага станет -75% Уклонения, если враг в течении этих 20 секунд решит, например закупить предмет, дающий ему 50% уклонения, то уклонение врага станет равно = -50% и враг всё ещё не сможет уклоняться
Есть герой со способностью "Снижает шанс уклонения врага на 75% на 20 секунд", допустим он применил её на врага
У врага станет -75% Уклонения, если враг в течении этих 20 секунд решит, например закупить предмет, дающий ему 90% уклонения, то уклонение врага станет равно = 60% и враг будет уклоняться гораздо меньше, чем должен
Вот такое у меня тут
8
nazarpunk, Нету такого в интернете (скорее всего есть, но я незнаю где), я сам вывел эти формулы и написал по ним код
25
nazarpunk, ну я на то и намекал, что вероятность должна остаться в пределах [0, 1].
Tredor46, так это всё ты можешь складывать в этой функции, но вернуть в итоге нужно валидное значение, ибо куда ты приткнёшь потом свои отрицательные вероятности миссов? Но это точно можно сложить проще, а не так
8
Makeba, Отрицательные вероятности нужны, чтобы юнит с вероятностями ничего не получил, при получении предмета/баффа/способности, добавляющие ему вероятности
30
если враг в течении этих 20 секунд решит, например закупить предмет, дающий ему 90% уклонения
А если враг закупит три таких предмета, то он станет Борисом?
8
nazarpunk, Котом Борисом? Нет, для этого он ещё должен закупить Китикет
30
Котом Борисом?
Вот и выросло поколение, которое не знает Бориса Бритву...
8
nazarpunk, Вырастет и поколение, которое не будет знать Кота Бориса
Этот комментарий удален
32
// Evasion
// Blur
// Drunken Brawler
// Butterfly
// Halberd
// Talisman
// Smoke screen -
// Whirling Axes - 60%
// Crippling Fear - 50%
// Drunken Haze - 45, 55, 65, 75

function GT1 takes unit SFI returns nothing // evasion up
    local real GR1 = 1
    local integer GP1 = UnitInventorySize( SFI )
    local integer x = 0
    local item i
    local integer SUI = GetUnitAbilityLevel( SFI, 'A03P' ) // blur
    
    if SUI > 0 then
        if SUI == 1 then
            set GR1 = GR1 * 0.8
        elseif SUI == 2 then
            set GR1 = GR1 * 0.7
        elseif SUI == 3 then
            set GR1 = GR1 * 0.6
        elseif SUI == 4 then
            set GR1 = GR1 * 0.5
        endif
    endif
    
    set SUI = GetUnitAbilityLevel( SFI, 'A0MX' )
    if SUI > 0 then
        set GR1 = GR1 * ( 1 - ( 0.05 + 0.05 * SUI ) )
    endif
    
    loop
        exitwhen x > GP1
        set i = UnitItemInSlot( SFI, x )
        if F01( i ) == ButterflyActiveId then
            set GR1 = GR1 * 0.65
        elseif F01( i ) == HN0 or F01( i ) == HeavensHalbertId then
            set GR1 = GR1 * 0.75
        endif
        set x = x + 1
    endloop
    set SUI = R2I( ( 1 - GR1 ) / 0.05 )* 1
    if SUI > 0 then
        call AddPermanentAbility( SFI, 'A2V3' )
        call SetUnitAbilityLevel( SFI, 'A2V3', SUI )
        set x = GetUnitAbility( SFI, 'A2V3' )
        if x < 1 then
            call BJDebugMsg("ability not added!")
        else
            call SaveInteger( HashData, ExEvasionData, GetHandleId( SFI ), x )
            if IsUnitIllusion( SFI ) then
                if RMem( x + 0x3C ) > 0 then
                    call WMem( x + 0x3C, 0 )
                endif
            endif
        endif
    else
        call UnitRemoveAbility( SFI, 'A2V3' )
        call RemoveSavedInteger( HashData, ExEvasionData, GetHandleId( SFI ))
    endif
    set i = null
endfunction
Вот функция сложения шансов промахов из доты, автор IceFrog.

GR -это вероятность попасть по юниту, перечисляются всё источники, после идёт округление до 5, т.у у пассивки шаг промахов 5%, добивать до 1% смысла нет.
Ответы (10)
8
quq_CCCP, Помоему это что-то не то, я не найду где тут шансы складываются
32
Tredor46, как нето перечислены источники уклонения и ведется сложение, после 1 абилке 20 лвл выдается уровень, таким образом в доте 6.83 фрога слкадываются пассивные уклонения,
8
quq_CCCP, Тут я так понял шансы считаются,
set GR1 = GR1 * ( 1 - ( 0.05 + 0.05 * SUI ) ) 
но это какая-то узконаправленная функция, чё с ней делать то
8
quq_CCCP, точнее во всех этих
GR1 = 
шансы считаются
16
OVOgenez, наверное, это дота лича на мемхаке
32
OVOgenez, а не это я уже фиксы делал, для кастомного мкб, на это внимание можно не обращать.
12
quq_CCCP, От кода который скинул только больше вопросов. Судя по всему добавляются уклонения с иконкой, у которой координаты сломаны, чтобы не была видна. Так понимаю, эта функция function GT1 - evasion up должна вызваться каждый раз, при получении предметов с уклонением или она пересчитывается постоянно?
call RemoveSavedInteger( HashData, ExEvasionData, GetHandleId( SFI )) не хватает контекста, что это
что за функция F01( i ) == HeavensHalbertId может быть проверка инвентаря героя или чисто айдиник предмета GetItemTypeId(i) ?
32
Daro, если интересно - в лс напиши, расскажу как этот код работает в доте.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.