maker-rus, А вот оно что, это пример отличный от моего, окей. Что я не могу сейчас понять: По моим условиям до реализации цикла ( два удара лучника, удар воина, повторить до тех пор пока кто-то не помрет) должны быть несколько атак лучника. Как мне записать эти атаки чтобы они выполнялись в начале схватки каждый из n количества боев, но при этом не повторялись каждый шаг боя.
maker-rus, спасибо, конечно. но я вот читаю ваш код, и насколько я могу понять он вообще не соответствует условию задачи. почему-то когда бьет лучник, воин всегда снижает урон на 7, а не в 50% случаев. когда бьет воин лучник почему-то использует 50% процентный шанс воина на снижение урона, хотя он в 40% случаев полностью игнорирует урон. Еще я не совсем понял как у вас реализована двойная скорость атаки лучника. А еще вы не реализовали то, что лучник атакует дополнительное количество раз когда они сближаются ( но я тоже не придумал как это сделать, я совсем не программист, скорее начинающий гейм дизайнер) не удивительно что при таком раскладе у вас воин вышел победителем в большинстве случаев. у меня почему-то лучник почти всегда выигрывает, что тоже не совсем похоже на правду ( а я даже не учитывал доп атаки на сближении!!) На бумаге, при расчете этой задачи в средних значениях выигрывет лучник с разрывом в одну атаку буквально. немного переделал ваш код ( не знаю как реализовать двойную скорость атаки лучника, потому написал блок с атакой лучника дважды :))
--параметры испытаний iterations = 200000; -- итерации limit_step_count = 1000; -- число попыток, если не убили за него, то ничья distance = 60; --расстояние между противниками
-- структура у всех объектов ОБЯЗАНА быть одинаковой -- объекты персонажей
-- победа воина if (archer.health <= 0) then win.warrior = true; return win; end
-- победа лучника if (warrior.health <= 0) then win.archer = true; return win; end
if (limit_step == count_step) then win.nobody = true return win; end
return win; end
local count_step = 0;
for count_iterations = 0, iterations do
count_step = count_step + 1;
-- (попытка) бьет лучник (первая атака) if (is_attack(archer.chance_to_hit)) then -- (попытка) критует лучник if (math.random() < archer.chance_to_crit) then -- (попытка) снижение урона воином if (math.random() < warrior.chance_to_reduce) then warrior.health = warrior.health - (2 * archer.damage - 7); else warrior.health = warrior.health - 2 * archer.damage; end else if (math.random() < warrior.chance_to_reduce) then warrior.health = warrior.health - (archer.damage - 7); else warrior.health = warrior.health - archer.damage; end end end -- (попытка) бьет лучник (вторая атака) if (is_attack(archer.chance_to_hit)) then if (math.random() < archer.chance_to_crit) then if (math.random() < warrior.chance_to_reduce) then warrior.health = warrior.health - (2 * archer.damage - 7); else warrior.health = warrior.health - 2 * archer.damage; end else if (math.random() < warrior.chance_to_reduce) then warrior.health = warrior.health - (archer.damage - 7); else warrior.health = warrior.health - archer.damage; end end end
-- (попытка) бьет воин if (is_attack(warrior.chance_to_hit)) then -- (попытка) спас-бросок if (math.random() < archer.chance_to_save) then archer.health = archer.health; else archer.health = archer.health - warrior.damage; end end
-- проверяем, кто победил local win = get_win(archer, warrior, count_step, limit_step_count);
-- записываем результат if (win.archer) then archer.win = archer.win + 1; warrior.lose = warrior.lose + 1;
archer, warrior = reset_player(archer, warrior); end
if (win.warrior) then warrior.win = warrior.win + 1; archer.lose = archer.lose + 1;
archer, warrior = reset_player(archer, warrior); end
if (win.nobody) then archer.nobody = archer.nobody + 1; warrior.nobody = warrior.nobody + 1;
count_step = 0; archer, warrior = reset_player(archer, warrior); end end
local function calc_win_rate(win, lose, nobody) if (win > 0) then local all_battle = win + lose + nobody; local k = win / all_battle; return math.floor(k * 100); else return 0; end end
по результатам испытаний воин выигрывает в большем числе столкновений. это потому, что лучник каждый раз не делает дополнительные 12 (2*60/10) атак, моих знаний в этом языке недостаточно чтобы это реализовать, ХЕЛП
Сообщение отредактировал EvgenShet - Вторник, 04 Мая 2021, 13:42
Добавлено (29 Апреля 2021, 15:56) --------------------------------------------- maker-rus, не помогло, выдает ошибку, решил избавится от функций archerAttack(), WarriorAttack() прописал их в основном цикле. Теперь считает, но по моему мнению не верно. если посчитать эту задачу руками, лучник выигрывает прям совсем на тоненького. Один лишний несейв лучником или сейв воином меняет ситуацию на противоположную, а моя прога выдает 99.9 случаев победы лучника, что-то я сделал не так
Сообщение отредактировал EvgenShet - Четверг, 29 Апреля 2021, 15:57
первый день изучаю Lua хотел решить такую задачку: Лучник атакует Воина дальней атакой, находясь в неподвижной точке. Воин приближается к лучнику с фиксированной скоростью. Параметры лучника: ● Здоровье 600 ● Атака 10 за выстрел ● 25% вероятность x2 урона ● 40% вероятность увернуться от атаки (полностью избежав урон) Параметры воина: ● Здоровье 800 ● Атака 25 за удар ● 50% вероятность заблокировать 7 единиц получаемого урона В момент начала боя воин находится на расстоянии 60 метров от лучника. Пока воин успевает сократить дистанцию на 10 метров, лучник делает 2 попадания по воину. Скорость атаки воина в 2 раза ниже, чем у лучника.
Написал такой вот код ( делал по одному образцу, но там задача была в разы проще) :
Код
--параметры испытаний iterations = 1500000; -- итерации timeout_limit = 1000; -- число попыток, если не убили за него, то ничья distance=60; --расстояние между противниками
-- попал юнит или нет IsDamage = function(chance) local isdamage1 = false; local r = math.random(); if (r<chance) then isdamage1 = true; end return isdamage1; end -- спас бросок IsSave = function(chance1) local issave1 = false; local z = math.random(); if (z>chance1) then issave1 = true; end return issave1; end --крит IsCrit = function(chance2) local iscrit1 = false; local y = math.random(); if (y<chance2) then iscrit1 = true; end return iscrit1; end --уменьшение урона IsReduce = function(chance3) local isreduce1 = false; local f = math.random(); if (f<chance3) then iscrit1 = true; end return isreduce1; end -- [[лучник атакует
archerAttack=function() if(IsCrit(char[1].chancetocrit)) then if (IsReduce(char[2].chancetoreduceto7)) then char_B_health = char_B_health - (2 * char[1].damage - 7); else char_B_health = char_B_health - 2 * char[1].damage; end else if (IsReduce (char[2].chancetoreduceto7)) then char_B_health = char_B_health - (char[1].damage - 7); else char_B_health = char_B_health - char[1].damage; end end return archerAttack; end -- воин атакует WarriorAttack=function() if (not(IsSave(char[1].chancetosave))) then char_A_health = char_A_health - char[2].damage; end return WarriorAttack; end
-- генератор случайных чисел math.randomseed(os.time()); -- d = расстояние между противниками for d=1, distance/6 do local char_A_health = char[1].health; local char_B_health = char[2].health; local char_A_dead = false; local char_B_dead = false; archerAttack();
end
-- основной цикл for i = 1, iterations do local char_A_health = char[1].health; local char_B_health =char_B_health; local char_A_dead = false; local char_B_dead = false;
-- i2 = число попыток, если не убили за негото ничья for i2 = 1, timeout_limit do archerAttack(); archerAttack(); WarriorAttack(); if (char_A_health<=0) then char_A_dead = true; end if (char_B_health<=0) then char_B_dead = true; end if (char_A_dead or char_B_dead) then break; end end if (not(char_A_dead)) and( not(char_B_dead)) then -- считаем ничьи по таймауту отдельно timeout_count = timeout_count +1; else if (char_A_dead and char_B_dead) then -- ничьи без таймаута char_AB_wins = char_AB_wins + 1; else if (char_A_dead) then -- победил B char_B_wins = char_B_wins + 1; end if (char_B_dead) then -- победил A char_A_wins = char_A_wins + 1; end end end end print ("A wins =" .. char_A_wins .. " (" .. (100*char_A_wins/(char_A_wins+char_B_wins+char_AB_wins+timeout_count)) .. "%)"); print ("B wins =" .. char_B_wins .. " (" .. (100*char_B_wins/(char_A_wins+char_B_wins+char_AB_wins+timeout_count)) .. "%)"); print ("AB wins =" .. char_AB_wins .. " (" .. (100*char_AB_wins/(char_A_wins+char_B_wins+char_AB_wins+timeout_count)) .. "%)"); print ("timeout =" .. timeout_count .. " (" .. (100*timeout_count/(char_A_wins+char_B_wins+char_AB_wins+timeout_count)) .. "%)");
выдает ошибку lua: fight.lua:76: attempt to perform arithmetic on global 'char_B_health' (a nil value) stack traceback: fight.lua:76: in function 'archerAttack' fight.lua:96: in main chunk [C]: ?
Сообщение отредактировал EvgenShet - Среда, 14 Апреля 2021, 20:21