fr.quatrevieux.araknemu.game.fight.ai.simulation.Simulator   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 79
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 34
c 1
b 0
f 0
dl 0
loc 79
ccs 33
cts 33
cp 1
rs 10
wmc 9

4 Methods

Rating   Name   Duplication   Size   Complexity  
A simulate(Spell,CastScope) 0 28 5
A Simulator(CriticalityStrategy) 0 2 1
A register(int,EffectSimulator) 0 2 1
A simulate(Spell,ActiveFighter,BattlefieldCell) 0 17 2
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2019 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.game.fight.ai.simulation;
21
22
import fr.quatrevieux.araknemu.game.fight.ai.simulation.effect.EffectSimulator;
23
import fr.quatrevieux.araknemu.game.fight.castable.CastScope;
24
import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter;
25
import fr.quatrevieux.araknemu.game.fight.fighter.FighterData;
26
import fr.quatrevieux.araknemu.game.fight.map.BattlefieldCell;
27
import fr.quatrevieux.araknemu.game.fight.turn.action.util.CriticalityStrategy;
28
import fr.quatrevieux.araknemu.game.spell.Spell;
29
30
import java.util.HashMap;
31
import java.util.Map;
32
33
/**
34
 * Perform simulation on fight
35
 */
36
public final class Simulator {
37 1
    private final Map<Integer, EffectSimulator> simulators = new HashMap<>();
38
    private final CriticalityStrategy criticalityStrategy;
39
40 1
    public Simulator(CriticalityStrategy criticalityStrategy) {
41 1
        this.criticalityStrategy = criticalityStrategy;
42 1
    }
43
44
    /**
45
     * Register an effect simulator
46
     *
47
     * @param effectId The effect to simulate
48
     * @param simulator The simulator
49
     */
50
    public void register(int effectId, EffectSimulator simulator) {
51 1
        simulators.put(effectId, simulator);
52 1
    }
53
54
    /**
55
     * Simulate the spell cast
56
     *
57
     * @param spell Spell to cast
58
     * @param caster The caster (current fighter)
59
     * @param target The cell target
60
     *
61
     * @return The simulation result
62
     */
63
    public CastSimulation simulate(Spell spell, ActiveFighter caster, BattlefieldCell target) {
64 1
        final CastSimulation normalSimulation = simulate(spell, new SimulationCastScope(spell, caster, target, spell.effects()));
65 1
        final int hitRate = spell.criticalHit();
66
67 1
        if (hitRate < 2) {
68 1
            return normalSimulation;
69
        }
70
71 1
        final CastSimulation criticalSimulation = simulate(spell, new SimulationCastScope(spell, caster, target, spell.criticalEffects()));
72 1
        final CastSimulation simulation = new CastSimulation(spell, caster, target);
73
74 1
        final int criticalRate = 100 / criticalityStrategy.hitRate(caster, hitRate);
75
76 1
        simulation.merge(normalSimulation, 100 - criticalRate);
0 ignored issues
show
Bug introduced by
Math operands should be cast to prevent unwanted loss of precision when mixing types. Consider casting one of the operands of this subtraction to double.
Loading history...
77 1
        simulation.merge(criticalSimulation, criticalRate);
78
79 1
        return simulation;
80
    }
81
82
    /**
83
     * Simulate a cast result
84
     *
85
     * @param scope The cast scope
86
     */
87
    private CastSimulation simulate(Spell spell, CastScope<FighterData, BattlefieldCell> scope) {
88
        // Remove invisible fighters from simulation
89 1
        scope.targets().forEach(target -> {
90 1
            if (target.hidden()) {
91 1
                scope.removeTarget(target);
92
            }
93 1
        });
94
95 1
        final CastSimulation simulation = new CastSimulation(spell, scope.caster(), scope.target());
96
97 1
        for (CastScope.EffectScope<FighterData> effect : scope.effects()) {
98 1
            final EffectSimulator simulator = simulators.get(effect.effect().effect());
99
100 1
            if (simulator == null) {
101 1
                continue;
102
            }
103
104 1
            if (effect.effect().probability() > 0) {
105 1
                final CastSimulation probableSimulation = new CastSimulation(spell, scope.caster(), scope.target());
106
107 1
                simulator.simulate(probableSimulation, effect);
108 1
                simulation.merge(probableSimulation, effect.effect().probability());
109 1
            } else {
110 1
                simulator.simulate(simulation, effect);
111
            }
112 1
        }
113
114 1
        return simulation;
115
    }
116
}
117