| Line 3: |
Line 3: |
| | local sqrt = math.sqrt | | local sqrt = math.sqrt |
| | local floor = math.floor | | local floor = math.floor |
| | + | local ceil = math.ceil |
| | local min = math.min | | local min = math.min |
| | local max = math.max | | local max = math.max |
| | + | |
| | + | function initArgs(ship, target, context) |
| | + | return ship and ship.ship or ship or {}, target and target.ship or target or {}, context or {} |
| | + | end |
| | | | |
| | function target_morale_modifier(morale) | | function target_morale_modifier(morale) |
| | return not morale and 1 or morale <= 20 and 1.4 or morale <= 32 and 1.2 or morale <= 52 and 1 or 0.7 | | return not morale and 1 or morale <= 20 and 1.4 or morale <= 32 and 1.2 or morale <= 52 and 1 or 0.7 |
| | + | end |
| | + | |
| | + | function Combat2.evasion_value(target, context) |
| | + | _, target, context = initArgs(nil, target, context) |
| | + | local evasion = target._evasion or 0 |
| | + | local target_luck = target._luck or 0 |
| | + | local target_formation = context._target_formation or target._formation or 1 |
| | + | local base_evasion_value = floor((evasion + sqrt(2 * target_luck)) * target_formation) |
| | + | local capped_evasion_value |
| | + | = base_evasion_value < 40 |
| | + | and base_evasion_value |
| | + | or base_evasion_value < 65 |
| | + | and floor(40 + 3 * sqrt(base_evasion_value - 40)) |
| | + | or floor(55 + 2 * sqrt(base_evasion_value - 65)) |
| | + | local evasion_value = capped_evasion_value |
| | + | return evasion_value |
| | end | | end |
| | | | |
| Line 19: |
Line 40: |
| | | | |
| | function Combat2.accuracy_value(ship, target, context) | | function Combat2.accuracy_value(ship, target, context) |
| − | ship = ship and ship.ship or ship | + | ship, target, context = initArgs(ship, target, context) |
| − | target = target and target.ship or target
| |
| − | context = context or {}
| |
| − | if not ship or not target then
| |
| − | return
| |
| − | end
| |
| | local level = ship._level or 1 | | local level = ship._level or 1 |
| | local luck = ship._luck or 0 | | local luck = ship._luck or 0 |
| Line 43: |
Line 59: |
| | -- [[Category:Todo]]: detection based on _equipment, fuel modifier. | | -- [[Category:Todo]]: detection based on _equipment, fuel modifier. |
| | function Combat2.hit_rate(ship, target, context) | | function Combat2.hit_rate(ship, target, context) |
| − | | + | ship, target, context = initArgs(ship, target, context) |
| − | ship = ship and ship.ship or ship | |
| − | target = target and target.ship or target
| |
| − | context = context or {}
| |
| − | if not ship or not target then
| |
| − | return
| |
| − | end
| |
| − | | |
| | local _, _, accuracy_value = Combat2.accuracy_value(ship, target, context) | | local _, _, accuracy_value = Combat2.accuracy_value(ship, target, context) |
| − | accuracy_value = floor(accuracy_value)
| + | local evasion_value = Combat2.evasion_value(target, context) |
| − | | + | local base_hit_rate = floor(accuracy_value) - evasion_value |
| − | local evasion = target._evasion or 0 | |
| − | local target_luck = target._luck or 0
| |
| − | local target_formation = context._target_formation or target._formation or 1 | |
| | local target_morale = target_morale_modifier(target._morale) | | local target_morale = target_morale_modifier(target._morale) |
| − |
| |
| − | local base_evasion_value = floor((evasion + sqrt(2 * target_luck)) * target_formation)
| |
| − |
| |
| − | local capped_evasion_value
| |
| − | = base_evasion_value < 40
| |
| − | and base_evasion_value
| |
| − | or base_evasion_value < 65
| |
| − | and floor(40 + 3 * sqrt(base_evasion_value - 40))
| |
| − | or floor(55 + 2 * sqrt(base_evasion_value - 65))
| |
| − |
| |
| − | local evasion_value = capped_evasion_value
| |
| − |
| |
| − | local base_hit_rate = accuracy_value - evasion_value
| |
| − |
| |
| | local capped_hit_rate = min(96, max(10, base_hit_rate) * target_morale) | | local capped_hit_rate = min(96, max(10, base_hit_rate) * target_morale) |
| − |
| |
| | local proficiency = ship._proficiency or 0 | | local proficiency = ship._proficiency or 0 |
| − |
| |
| | return floor(capped_hit_rate) + proficiency + 1, capped_hit_rate | | return floor(capped_hit_rate) + proficiency + 1, capped_hit_rate |
| − |
| |
| | end | | end |
| | | | |
| Line 85: |
Line 74: |
| | local proficiency = ship._proficiency or 0 | | local proficiency = ship._proficiency or 0 |
| | return floor(1.3 * sqrt(capped_hit_rate)) + proficiency + 1 | | return floor(1.3 * sqrt(capped_hit_rate)) + proficiency + 1 |
| | + | end |
| | + | |
| | + | function Combat2.find_fit(ship, target, context) |
| | + | ship, target, context = initArgs(ship, target, context) |
| | + | local prev_fit = ship._fit |
| | + | local hit_rate = context._hit_rate |
| | + | local ci = context._ci |
| | + | if not hit_rate or not ci then |
| | + | return |
| | + | end |
| | + | local ng = context._ng or 1 |
| | + | local min_hit_rate = floor(hit_rate - ci) |
| | + | local max_hit_rate = ceil(hit_rate + ci) |
| | + | mw.log(min_hit_rate) |
| | + | mw.log(max_hit_rate) |
| | + | local fits = {} |
| | + | for fit = -10, 10 do |
| | + | ship._fit = fit * sqrt(ng) |
| | + | local hr = Combat2.hit_rate(ship, target, context) |
| | + | mw.log(fit, fit * sqrt(ng), hr, hr - hit_rate) |
| | + | if hr >= min_hit_rate and hr <= max_hit_rate then |
| | + | table.insert(fits, fit) |
| | + | end |
| | + | end |
| | + | local min_fit = math.min(unpack(fits)) |
| | + | local max_fit = math.max(unpack(fits)) |
| | + | local fit = (min_fit + max_fit) / 2 |
| | + | ship._fit = prev_fit |
| | + | return floor(fit + 0.5), min_fit, max_fit |
| | end | | end |
| | | | |
| Line 95: |
Line 113: |
| | _accuracy = 10, | | _accuracy = 10, |
| | _morale = 25, | | _morale = 25, |
| − | _fit = 5 * sqrt(2) | + | _fit = 5 * sqrt(2), |
| | } | | } |
| | local target = Ship("Destroyer Ro-Class") | | local target = Ship("Destroyer Ro-Class") |
| − | mw.log(Combat2.accuracy_value(ship, target)) | + | --mw.log(Combat2.accuracy_value(ship, target)) |
| − | mw.log(Combat2.hit_rate(ship, target), "") | + | --mw.log(Combat2.hit_rate(ship, target), "") |
| − | mw.log(Combat2.critical_hit_rate(ship, target)) | + | --mw.log(Combat2.critical_hit_rate(ship, target)) |
| | + | mw.log(Combat2.find_fit(ship, target, { _hit_rate = 94.4, _ci = 1.48, _ng = 2 } )) |
| | end | | end |
| | + | -- print(p.test()) |
| | | | |
| | return Combat2 | | return Combat2 |