| 91 | } |
| 92 | |
| 93 | AIDecision AIBlockUnit::think(GameState &state, BattleUnit &u, bool forceInterrupt) |
| 94 | { |
| 95 | auto curTicks = state.gameTime.getTicks(); |
| 96 | if (ticksLastThink + ticksUntilReThink > curTicks) |
| 97 | { |
| 98 | if (u.visibleUnits.empty() || u.isMoving() || u.isAttacking() || |
| 99 | u.psiStatus != PsiStatus::NotEngaged || |
| 100 | ticksLastOutOfOrderThink + ticksUntilReThink > curTicks) |
| 101 | { |
| 102 | return {}; |
| 103 | } |
| 104 | ticksLastOutOfOrderThink = curTicks; |
| 105 | } |
| 106 | |
| 107 | bool interrupt = forceInterrupt; |
| 108 | if (!interrupt && state.current_battle->mode == Battle::Mode::TurnBased) |
| 109 | { |
| 110 | if (!state.current_battle->interruptQueue.empty()) |
| 111 | { |
| 112 | return {}; |
| 113 | } |
| 114 | if (u.owner != state.current_battle->currentActiveOrganisation || |
| 115 | !state.current_battle->interruptUnits.empty()) |
| 116 | { |
| 117 | auto it = state.current_battle->interruptUnits.find({&state, u.id}); |
| 118 | interrupt = it != state.current_battle->interruptUnits.end() && |
| 119 | u.agent->modified_stats.time_units > it->second; |
| 120 | if (!interrupt) |
| 121 | { |
| 122 | return {}; |
| 123 | } |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | ticksLastThink = curTicks; |
| 128 | ticksUntilReThink = UNIT_AI_THINK_INTERVAL; |
| 129 | |
| 130 | AIDecision decision = {}; |
| 131 | for (auto &ai : aiList) |
| 132 | { |
| 133 | if (forceInterrupt) |
| 134 | { |
| 135 | ai->reset(state, u); |
| 136 | } |
| 137 | auto result = ai->think(state, u, interrupt); |
| 138 | auto newDecision = std::get<0>(result); |
| 139 | auto halt = std::get<1>(result); |
| 140 | if (!newDecision.isEmpty()) |
| 141 | { |
| 142 | // We can keep last decision's movement if this one is action only, |
| 143 | // because that would mean this decision may be possible to be done on the move |
| 144 | // We cannot take last decision's action because it might override |
| 145 | // our move or malfunction otherwise |
| 146 | if (!newDecision.movement && decision.movement) |
| 147 | { |
| 148 | newDecision.movement = decision.movement; |
| 149 | } |
| 150 | decision = newDecision; |
no test coverage detected