Completed
Push — trunk ( ad61f6...5a98ee )
by SuperNova.WS
04:15
created

Ube4_1Calc::sn_ube_combat_analyze()   F

Complexity

Conditions 29
Paths 16576

Size

Total Lines 141
Code Lines 74

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 870

Importance

Changes 0
Metric Value
cc 29
eloc 74
nc 16576
nop 1
dl 0
loc 141
rs 2
c 0
b 0
f 0
ccs 0
cts 93
cp 0
crap 870

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Created by Gorlum 13.02.2018 7:53
4
 */
5
6
namespace Ube\Ube4_1;
7
8
9
class Ube4_1Calc {
10
  const CONVERT_UNIT_PARAMS = [
11
    UBE_ATTACK => 'attack',
12
    UBE_ARMOR  => 'armor',
13
    UBE_SHIELD => 'shield',
14
  ];
15
16
  public $ube_combat_bonus_list;
17
  public $ube_convert_techs;
18
19
  public function __construct() {
20
    global $ube_combat_bonus_list, $ube_convert_techs;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
21
22
    $this->ube_combat_bonus_list = $ube_combat_bonus_list;
23
    $this->ube_convert_techs = $ube_convert_techs;
24
  }
25
26
  public function sn_ube_combat(&$combat_data) {
27
    // TODO: Сделать атаку по типам,  когда они будут
28
29
    $start = microtime(true);
30
    $this->sn_ube_combat_prepare_first_round($combat_data);
31
32
    for ($round = 1; $round <= 10; $round++) {
33
      // Готовим данные для раунда
34
      $this->sn_ube_combat_round_prepare($combat_data, $round);
35
36
      // Проводим раунд
37
      $this->sn_ube_combat_round_crossfire_fleet($combat_data, $round);
38
39
      // Анализируем итоги текущего раунда и готовим данные для следующего
40
      if ($this->sn_ube_combat_round_analyze($combat_data, $round) != UBE_COMBAT_RESULT_DRAW) {
41
        break;
42
      }
43
    }
44
    $combat_data[UBE_TIME_SPENT] = microtime(true) - $start;
45
46
    // Делать это всегда - нам нужны результаты боя: луна->обломки->количество осташихся юнитов
47
    $this->sn_ube_combat_analyze($combat_data);
48
  }
49
50
  // ------------------------------------------------------------------------------------------------
51
  protected function sn_ube_combat_prepare_first_round(&$combat_data) {
52
    // Готовим информацию для первого раунда - проводим все нужные вычисления из исходных данных
53
    $first_round_data = array();
54
    foreach ($combat_data[UBE_FLEETS] as $fleet_id => &$fleet_info) {
55
      $fleet_info[UBE_COUNT] = is_array($fleet_info[UBE_COUNT]) ? $fleet_info[UBE_COUNT] : array();
56
      $player_data = &$combat_data[UBE_PLAYERS][$fleet_info[UBE_OWNER]];
57
      $fleet_info[UBE_FLEET_TYPE] = $player_data[UBE_ATTACKER] ? UBE_ATTACKERS : UBE_DEFENDERS;
58
59
      foreach ($this->ube_combat_bonus_list as $bonus_id => $bonus_value) {
60
        // Вычисляем бонус игрока
61
        $bonus_value = isset($player_data[UBE_BONUSES][$bonus_id]) ? $player_data[UBE_BONUSES][$bonus_id] : 0;
62
        // Добавляем к бонусам флота бонусы игрока
63
        $fleet_info[UBE_BONUSES][$bonus_id] += $bonus_value;
64
      }
65
66
      $first_round_data[$fleet_id][UBE_COUNT] = $fleet_info[UBE_PRICE] = array();
67
      foreach ($fleet_info[UBE_COUNT] as $unit_id => $unit_count) {
68
        if ($unit_count <= 0) {
69
          continue;
70
        }
71
72
        $unit_info = get_unit_param($unit_id);
73
        // Заполняем информацию о кораблях в информации флота
74
        foreach ($this->ube_combat_bonus_list as $bonus_id => $bonus_value) {
75
          $fleet_info[$bonus_id][$unit_id] = floor($unit_info[static::CONVERT_UNIT_PARAMS[$bonus_id]] * (1 + $fleet_info[UBE_BONUSES][$bonus_id]));
76
        }
77
        $fleet_info[UBE_AMPLIFY][$unit_id] = $unit_info[P_AMPLIFY];
78
        // TODO: Переделать через get_ship_data()
79
        $fleet_info[UBE_CAPACITY][$unit_id] = $unit_info[P_CAPACITY];
80
        $fleet_info[UBE_TYPE][$unit_id] = $unit_info[P_UNIT_TYPE];
81
        // TODO: Переделать через список ресурсов
82
        $fleet_info[UBE_PRICE][RES_METAL]    [$unit_id] = $unit_info[P_COST][RES_METAL];
83
        $fleet_info[UBE_PRICE][RES_CRYSTAL]  [$unit_id] = $unit_info[P_COST][RES_CRYSTAL];
84
        $fleet_info[UBE_PRICE][RES_DEUTERIUM][$unit_id] = $unit_info[P_COST][RES_DEUTERIUM];
85
        $fleet_info[UBE_PRICE][RES_DARK_MATTER][$unit_id] = $unit_info[P_COST][RES_DARK_MATTER];
86
87
        // Копируем её в информацию о первом раунде
88
        $first_round_data[$fleet_id][UBE_ARMOR][$unit_id] = $fleet_info[UBE_ARMOR][$unit_id] * $unit_count;
89
        $first_round_data[$fleet_id][UBE_COUNT][$unit_id] = $unit_count;
90
        $first_round_data[$fleet_id][UBE_ARMOR_REST][$unit_id] = $fleet_info[UBE_ARMOR][$unit_id];
91
        $first_round_data[$fleet_id][UBE_SHIELD_REST][$unit_id] = $fleet_info[UBE_SHIELD][$unit_id];
92
      }
93
    }
94
    $combat_data[UBE_ROUNDS][0][UBE_FLEETS] = $first_round_data;
95
    $combat_data[UBE_ROUNDS][1][UBE_FLEETS] = $first_round_data;
96
    $this->sn_ube_combat_round_prepare($combat_data, 0);
97
  }
98
99
// ------------------------------------------------------------------------------------------------
100
// Вычисление дополнительной информации для расчета раунда
101
  protected function sn_ube_combat_round_prepare(&$combat_data, $round) {
102
    $is_simulator = $combat_data[UBE_OPTIONS][UBE_SIMULATOR];
103
104
    $round_data = &$combat_data[UBE_ROUNDS][$round];
105
    foreach ($round_data[UBE_FLEETS] as $fleet_id => &$fleet_data) {
106
      // Кэшируем переменные для легкого доступа к подмассивам
107
      $fleet_info = &$combat_data[UBE_FLEETS][$fleet_id];
108
      $fleet_data[UBE_FLEET_INFO] = &$fleet_info;
109
      $fleet_type = $fleet_info[UBE_FLEET_TYPE];
110
111
      foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) {
112
        if ($unit_count <= 0) {
113
          continue;
114
        }
115
116
// TODO:  Добавить процент регенерации щитов
117
118
        // Для не-симулятора - рандомизируем каждый раунд значения атаки и щитов
119
        $fleet_data[UBE_ATTACK_BASE][$unit_id] = floor($fleet_info[UBE_ATTACK][$unit_id] * ($is_simulator ? 1 : mt_rand(80, 120) / 100));
120
        $fleet_data[UBE_SHIELD_BASE][$unit_id] = floor($fleet_info[UBE_SHIELD][$unit_id] * ($is_simulator ? 1 : mt_rand(80, 120) / 100));
121
        $fleet_data[UBE_ARMOR_BASE][$unit_id] = floor($fleet_info[UBE_ARMOR][$unit_id]);// * ($is_simulator ? 1 : mt_rand(80, 120) / 100));
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
122
123
        $fleet_data[UBE_ATTACK][$unit_id] = $fleet_data[UBE_ATTACK_BASE][$unit_id] * $unit_count;
124
        $fleet_data[UBE_SHIELD][$unit_id] = $fleet_data[UBE_SHIELD_BASE][$unit_id] * $unit_count;
125
        $fleet_data[UBE_SHIELD_REST][$unit_id] = $fleet_data[UBE_SHIELD_BASE][$unit_id];
126
        // $fleet_data[UBE_SHIELD][$unit_id] = $fleet_data[UBE_SHIELD_BASE][$unit_id] * ($combat_data[UBE_OPTIONS][UBE_METHOD] ? $unit_count : 1);
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
127
        // $fleet_data[UBE_ARMOR][$unit_id] = $fleet_info[UBE_ARMOR_BASE][$unit_id] * $unit_count;
0 ignored issues
show
Unused Code Comprehensibility introduced by
61% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
128
      }
129
130
      // Суммируем данные по флоту
131
      foreach ($this->ube_combat_bonus_list as $bonus_id) {
132
        $round_data[$fleet_type][$bonus_id][$fleet_id] += is_array($fleet_data[$bonus_id]) ? array_sum($fleet_data[$bonus_id]) : 0;
133
      }
134
    }
135
136
    // Суммируем данные по атакующим и защитникам
137
    foreach ($this->ube_combat_bonus_list as $bonus_id) {
138
      $round_data[UBE_TOTAL][UBE_DEFENDERS][$bonus_id] = array_sum($round_data[UBE_DEFENDERS][$bonus_id]);
139
      $round_data[UBE_TOTAL][UBE_ATTACKERS][$bonus_id] = array_sum($round_data[UBE_ATTACKERS][$bonus_id]);
140
    }
141
142
    // Высчитываем долю атаки, приходящейся на юнит равную отношению брони юнита к общей броне - крупные цели атакуют чаще
143
    foreach ($round_data[UBE_FLEETS] as &$fleet_data) {
144
      $fleet_type = $fleet_data[UBE_FLEET_INFO][UBE_FLEET_TYPE];
145
      foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) {
146
        $fleet_data[UBE_DAMAGE_PERCENT][$unit_id] = $fleet_data[UBE_ARMOR][$unit_id] / $round_data[UBE_TOTAL][$fleet_type][UBE_ARMOR];
147
      }
148
    }
149
  }
150
151
// ------------------------------------------------------------------------------------------------
152
// Разбирает данные боя для генерации отчета
153
  protected function sn_ube_combat_analyze(&$combat_data) {
154
    global $config;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
155
156
//  $combat_data[UBE_OUTCOME] = array();
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
157
    $combat_data[UBE_OPTIONS][UBE_EXCHANGE] = array(RES_METAL => $config->rpg_exchange_metal);
158
159
    $exchange = &$combat_data[UBE_OPTIONS][UBE_EXCHANGE];
160
    foreach (array(RES_CRYSTAL => 'rpg_exchange_crystal', RES_DEUTERIUM => 'rpg_exchange_deuterium', RES_DARK_MATTER => 'rpg_exchange_darkMatter') as $resource_id => $resource_name) {
161
      $exchange[$resource_id] = $config->$resource_name * $exchange[RES_METAL];
162
    }
163
//  $total_resources_value = array_sum($exchange);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
164
165
    // Переменные для быстрого доступа к подмассивам
166
    $outcome = &$combat_data[UBE_OUTCOME];
167
    $fleets_info = &$combat_data[UBE_FLEETS];
168
    $last_round_data = &$combat_data[UBE_ROUNDS][count($combat_data[UBE_ROUNDS]) - 1];
169
170
    $outcome[UBE_DEBRIS] = array();
171
172
    // Генерируем результат боя
173
    foreach ($fleets_info as $fleet_id => &$fleet_info) {
174
      $fleet_type = $fleet_info[UBE_FLEET_TYPE];
175
      // Инициализируем массив результатов для флота
176
      $outcome[UBE_FLEETS][$fleet_id] = array(UBE_UNITS_LOST => array());
177
      $outcome[$fleet_type][UBE_FLEETS][$fleet_id] = &$outcome[UBE_FLEETS][$fleet_id];
178
179
      // Переменные для быстрого доступа к подмассивам
180
      $fleet_outcome = &$outcome[UBE_FLEETS][$fleet_id];
181
      $fleet_data = &$last_round_data[UBE_FLEETS][$fleet_id];
182
183
      foreach ($fleet_info[UBE_COUNT] as $unit_id => $unit_count) {
184
        // Вычисляем сколько юнитов осталось и сколько потеряно
185
        $units_left = $fleet_data[UBE_COUNT][$unit_id];
186
187
        // Восстановление обороны - 75% от уничтоженной
188
        if ($fleet_info[UBE_TYPE][$unit_id] == UNIT_DEFENCE) {
189
          $giveback_chance = 75; // TODO Configure
190
          $units_lost = $unit_count - $units_left;
191
          if ($combat_data[UBE_OPTIONS][UBE_SIMULATOR]) { // for simulation just return 75% of loss
192
            $units_giveback = round($units_lost * $giveback_chance / 100);
193
          } else {
194
            if ($unit_count > 10) { // if there were more then 10 defense elements - mass-calculating giveback
195
              $units_giveback = round($units_lost * mt_rand($giveback_chance * 0.8, $giveback_chance * 1.2) / 100);
196
            } else { //if there were less then 10 defense elements - calculating giveback per element
197
              $units_giveback = 0;
198
              for ($i = 1; $i <= $units_lost; $i++) {
199
                if (mt_rand(1, 100) <= $giveback_chance) {
200
                  $units_giveback++;
201
                }
202
              }
203
            }
204
          }
205
          $units_left += $units_giveback;
206
          $fleet_outcome[UBE_DEFENCE_RESTORE][$unit_id] = $units_giveback;
207
        }
208
209
        // TODO: Сбор металла/кристалла от обороны
210
211
        $units_lost = $unit_count - $units_left;
212
213
        // Вычисляем емкость трюмов оставшихся кораблей
214
        $outcome[$fleet_type][UBE_CAPACITY][$fleet_id] += $fleet_info[UBE_CAPACITY][$unit_id] * $units_left;
215
216
        // Вычисляем потери в ресурсах
217
        if ($units_lost) {
218
          $fleet_outcome[UBE_UNITS_LOST][$unit_id] = $units_lost;
219
220
          foreach ($fleet_info[UBE_PRICE] as $resource_id => $unit_prices) {
221
            if (!$unit_prices[$unit_id]) {
222
              continue;
223
            }
224
225
            // ...чистыми
226
            $resources_lost = $units_lost * $unit_prices[$unit_id];
227
            $fleet_outcome[UBE_RESOURCES_LOST][$resource_id] += $resources_lost;
228
229
            // Если это корабль - прибавляем потери к обломкам на орбите
230
            if ($fleet_info[UBE_TYPE][$unit_id] == UNIT_SHIPS) {
231
              $outcome[UBE_DEBRIS][$resource_id] += floor($resources_lost * ($combat_data[UBE_OPTIONS][UBE_SIMULATOR] ? 30 : mt_rand(20, 40)) / 100); // TODO: Configurize
232
            }
233
234
            // ...в металле
235
            $resources_lost_in_metal = $resources_lost * $exchange[$resource_id];
236
            $fleet_outcome[UBE_RESOURCES_LOST_IN_METAL][RES_METAL] += $resources_lost_in_metal;
237
          }
238
        }
239
      }
240
241
      // На планете ($fleet_id = 0) ресурсы в космос не выбрасываются
242
      if ($fleet_id == 0) {
243
        continue;
244
      }
245
246
      // Количество ресурсов флота
247
      $fleet_total_resources = empty($fleet_info[UBE_RESOURCES]) ? 0 : array_sum($fleet_info[UBE_RESOURCES]);
248
      // Если на борту нет ресурсов - зачем нам все это?
249
      if ($fleet_total_resources == 0) {
250
        continue;
251
      }
252
253
      // Емкость трюмов флота
254
      $fleet_capacity = $outcome[$fleet_type][UBE_CAPACITY][$fleet_id];
255
      // Если емкость трюмов меньше количество ресурсов - часть ресов выбрасываем нахуй
256
      if ($fleet_capacity < $fleet_total_resources) {
257
        $left_percent = $fleet_capacity / $fleet_total_resources; // Сколько ресурсов будет оставлено
258
        foreach ($fleet_info[UBE_RESOURCES] as $resource_id => $resource_amount) {
259
          // Не просчитываем ресурсы, которых нет на борту кораблей флота
260
          if (!$resource_amount) {
261
            continue;
262
          }
263
264
          // TODO Восстанавливаем ошибку округления - придумать нормальный алгоритм - вроде round() должно быть достаточно. Проверить
265
          $fleet_outcome[UBE_RESOURCES][$resource_id] = round($left_percent * $resource_amount);
266
          $resource_dropped = $resource_amount - $fleet_outcome[UBE_RESOURCES][$resource_id];
267
          $fleet_outcome[UBE_CARGO_DROPPED][$resource_id] = $resource_dropped;
268
269
          $outcome[UBE_DEBRIS][$resource_id] += round($resource_dropped * ($combat_data[UBE_OPTIONS][UBE_SIMULATOR] ? 50 : mt_rand(30, 70)) / 100); // TODO: Configurize
270
          $fleet_outcome[UBE_RESOURCES_LOST_IN_METAL][RES_METAL] += $resource_dropped * $exchange[$resource_id];
271
        }
272
        $fleet_total_resources = array_sum($fleet_outcome[UBE_RESOURCES]);
273
      }
274
275
      $outcome[$fleet_type][UBE_CAPACITY][$fleet_id] = $fleet_capacity - $fleet_total_resources;
276
    }
277
278
    $outcome[UBE_COMBAT_RESULT] = !isset($last_round_data[UBE_OUTCOME]) || $last_round_data[UBE_OUTCOME] == UBE_COMBAT_RESULT_DRAW_END ? UBE_COMBAT_RESULT_DRAW : $last_round_data[UBE_OUTCOME];
279
    // SFR - Small Fleet Reconnaissance ака РМФ
280
    $outcome[UBE_SFR] = count($combat_data[UBE_ROUNDS]) == 2 && $outcome[UBE_COMBAT_RESULT] == UBE_COMBAT_RESULT_LOSS;
281
282
    if (!$combat_data[UBE_OPTIONS][UBE_LOADED]) {
283
      if ($combat_data[UBE_OPTIONS][UBE_MOON_WAS]) {
284
        $outcome[UBE_MOON] = UBE_MOON_WAS;
285
      } else {
286
        $this->sn_ube_combat_analyze_moon($outcome, $combat_data[UBE_OPTIONS][UBE_SIMULATOR]);
287
      }
288
289
      // Лутаем ресурсы - если аттакер выиграл
290
      if ($outcome[UBE_COMBAT_RESULT] == UBE_COMBAT_RESULT_WIN) {
291
        $this->sn_ube_combat_analyze_loot($combat_data);
292
        if ($combat_data[UBE_OPTIONS][UBE_MOON_WAS] && $combat_data[UBE_OPTIONS][UBE_MISSION_TYPE] == MT_DESTROY) {
293
          $this->sn_ube_combat_analyze_moon_destroy($combat_data);
294
        }
295
      }
296
    }
297
298
  }
299
300
// ------------------------------------------------------------------------------------------------
301
  protected function sn_ube_combat_analyze_moon(&$outcome, $is_simulator) {
302
    $outcome[UBE_DEBRIS_TOTAL] = 0;
303
    foreach (array(RES_METAL, RES_CRYSTAL) as $resource_id) // TODO via array
304
    {
305
      $outcome[UBE_DEBRIS_TOTAL] += $outcome[UBE_DEBRIS][$resource_id];
306
    }
307
308
    if ($outcome[UBE_DEBRIS_TOTAL]) {
309
      // TODO uni_calculate_moon_chance
310
      $moon_chance = min($outcome[UBE_DEBRIS_TOTAL] / 1000000, 30); // TODO Configure
311
      $moon_chance = $moon_chance >= 1 ? $moon_chance : 0;
312
      $outcome[UBE_MOON_CHANCE] = $moon_chance;
313
      if ($moon_chance) {
314
        if ($is_simulator || mt_rand(1, 100) <= $moon_chance) {
315
          $outcome[UBE_MOON_SIZE] = round($is_simulator ? $moon_chance * 150 + 1999 : mt_rand($moon_chance * 100 + 1000, $moon_chance * 200 + 2999));
316
          $outcome[UBE_MOON] = UBE_MOON_CREATE_SUCCESS;
317
318
          if ($outcome[UBE_DEBRIS_TOTAL] <= 30000000) {
319
            $outcome[UBE_DEBRIS_TOTAL] = 0;
320
            $outcome[UBE_DEBRIS] = array();
321
          } else {
322
            $moon_debris_spent = 30000000;
323
            $moon_debris_left_percent = ($outcome[UBE_DEBRIS_TOTAL] - $moon_debris_spent) / $outcome[UBE_DEBRIS_TOTAL];
324
325
            $outcome[UBE_DEBRIS_TOTAL] = 0;
326
            foreach (array(RES_METAL, RES_CRYSTAL) as $resource_id) // TODO via array
327
            {
328
              $outcome[UBE_DEBRIS][$resource_id] = floor($outcome[UBE_DEBRIS][$resource_id] * $moon_debris_left_percent);
329
              $outcome[UBE_DEBRIS_TOTAL] += $outcome[UBE_DEBRIS][$resource_id];
330
            }
331
          }
332
        } else {
333
          $outcome[UBE_MOON] = UBE_MOON_CREATE_FAILED;
334
        }
335
      }
336
    } else {
337
      $outcome[UBE_MOON] = UBE_MOON_NONE;
338
    }
339
  }
340
341
// ------------------------------------------------------------------------------------------------
342
  protected function sn_ube_combat_analyze_moon_destroy(&$combat_data) {
343
    // TODO: $is_simulator
344
    $reapers = 0;
345
    foreach ($combat_data[UBE_ROUNDS][count($combat_data[UBE_ROUNDS]) - 1][UBE_FLEETS] as $fleet_data) {
346
      if ($fleet_data[UBE_FLEET_INFO][UBE_FLEET_TYPE] == UBE_ATTACKERS) {
347
        foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) {
348
          // TODO: Работа по группам - группа "Уничтожители лун"
349
          $reapers += ($unit_id == SHIP_HUGE_DEATH_STAR) ? $unit_count : 0;
350
        }
351
      }
352
    }
353
354
    $moon_size = $combat_data[UBE_OUTCOME][UBE_PLANET][PLANET_SIZE];
355
    if ($reapers) {
356
      $random = mt_rand(1, 100);
357
      $combat_data[UBE_OUTCOME][UBE_MOON_DESTROY_CHANCE] = max(1, min(99, round((100 - sqrt($moon_size)) * sqrt($reapers))));
358
      $combat_data[UBE_OUTCOME][UBE_MOON_REAPERS_DIE_CHANCE] = round(sqrt($moon_size) / 2 + sqrt($reapers));
359
      $combat_data[UBE_OUTCOME][UBE_MOON] = $random <= $combat_data[UBE_OUTCOME][UBE_MOON_DESTROY_CHANCE] ? UBE_MOON_DESTROY_SUCCESS : UBE_MOON_DESTROY_FAILED;
360
      $random = mt_rand(1, 100);
361
      $combat_data[UBE_OUTCOME][UBE_MOON_REAPERS] = $random <= $combat_data[UBE_OUTCOME][UBE_MOON_REAPERS_DIE_CHANCE] ? UBE_MOON_REAPERS_DIED : UBE_MOON_REAPERS_RETURNED;
362
    } else {
363
      $combat_data[UBE_OUTCOME][UBE_MOON_REAPERS] = UBE_MOON_REAPERS_NONE;
364
    }
365
  }
366
367
// ------------------------------------------------------------------------------------------------
368
  protected function sn_ube_combat_analyze_loot(&$combat_data) {
369
    $exchange = &$combat_data[UBE_OPTIONS][UBE_EXCHANGE];
370
    $planet_resource_list = &$combat_data[UBE_FLEETS][0][UBE_RESOURCES];
371
    $outcome = &$combat_data[UBE_OUTCOME];
372
373
    $planet_looted_in_metal = 0;
374
    $planet_resource_looted = array();
375
    $planet_resource_total = is_array($planet_resource_list) ? array_sum($planet_resource_list) : 0;
376
    if ($planet_resource_total && ($total_capacity = array_sum($outcome[UBE_ATTACKERS][UBE_CAPACITY]))) {
377
      // Можно вывести только половину ресурсов, но не больше, чем общая вместимость флотов атакующих
378
      $planet_lootable = min($planet_resource_total / 2, $total_capacity);
379
      // Вычисляем процент вывоза. Каждого ресурса будет вывезено в одинаковых пропорциях
380
      $planet_lootable_percent = $planet_lootable / $planet_resource_total;
381
382
      // Вычисляем какой процент общей емкости трюмов атакующих будет задействован
383
      $total_lootable = min($planet_lootable, $total_capacity);
0 ignored issues
show
Unused Code introduced by
The assignment to $total_lootable is dead and can be removed.
Loading history...
384
385
      // Вычисляем сколько ресурсов вывезено
386
      foreach ($outcome[UBE_ATTACKERS][UBE_CAPACITY] as $fleet_id => $fleet_capacity) {
387
        $looted_in_metal = 0;
388
        $fleet_loot_data = array();
389
        foreach ($planet_resource_list as $resource_id => $resource_amount) {
390
          // TODO Восстанавливаем ошибку округления - придумать нормальный алгоритм - вроде round() должно быть достаточно. Проверить
391
          $fleet_lootable_percent = $fleet_capacity / $total_capacity;
392
          $looted = round($resource_amount * $planet_lootable_percent * $fleet_lootable_percent);
393
          $fleet_loot_data[$resource_id] = -$looted;
394
          $planet_resource_looted[$resource_id] += $looted;
395
          $looted_in_metal -= $looted * $exchange[$resource_id];
396
        }
397
        $outcome[UBE_FLEETS][$fleet_id][UBE_RESOURCES_LOOTED] = $fleet_loot_data;
398
        $outcome[UBE_FLEETS][$fleet_id][UBE_RESOURCES_LOST_IN_METAL][RES_METAL] += $looted_in_metal;
399
        $planet_looted_in_metal += $looted_in_metal;
400
      }
401
    }
402
403
    $outcome[UBE_FLEETS][0][UBE_RESOURCES_LOST_IN_METAL][RES_METAL] -= $planet_looted_in_metal;
404
    $outcome[UBE_FLEETS][0][UBE_RESOURCES_LOOTED] = $planet_resource_looted;
405
  }
406
407
408
// ------------------------------------------------------------------------------------------------
409
// Анализирует результаты раунда и генерирует данные для следующего раунда
410
  protected function sn_ube_combat_round_analyze(&$combat_data, $round) {
411
    $round_data = &$combat_data[UBE_ROUNDS][$round];
412
    $round_data[UBE_OUTCOME] = UBE_COMBAT_RESULT_DRAW;
413
414
    $outcome = array();
415
    $next_round_fleet = array();
416
    foreach ($round_data[UBE_FLEETS] as $fleet_id => &$fleet_data) {
417
      if (array_sum($fleet_data[UBE_COUNT]) <= 0) {
418
        continue;
419
      }
420
421
      foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) {
422
        if ($unit_count <= 0) {
423
          continue;
424
        }
425
        $next_round_fleet[$fleet_id][UBE_COUNT][$unit_id] = $unit_count;
426
        $next_round_fleet[$fleet_id][UBE_ARMOR][$unit_id] = $fleet_data[UBE_ARMOR][$unit_id];
427
        $next_round_fleet[$fleet_id][UBE_ARMOR_REST][$unit_id] = $fleet_data[UBE_ARMOR_REST][$unit_id];
428
        $outcome[$fleet_data[UBE_FLEET_INFO][UBE_FLEET_TYPE]] = 1;
429
      }
430
    }
431
432
    // Проверяем - если кого-то не осталось или не осталось обоих - заканчиваем цикл
433
    if (count($outcome) == 0 || $round == 10) {
434
      $round_data[UBE_OUTCOME] = UBE_COMBAT_RESULT_DRAW_END;
435
    } elseif (count($outcome) == 1) {
436
      $round_data[UBE_OUTCOME] = isset($outcome[UBE_ATTACKERS]) ? UBE_COMBAT_RESULT_WIN : UBE_COMBAT_RESULT_LOSS;
437
    } elseif (count($outcome) == 2) {
438
      if ($round < 10) {
439
        $combat_data[UBE_ROUNDS][$round + 1][UBE_FLEETS] = $next_round_fleet;
440
      }
441
    }
442
443
    return ($round_data[UBE_OUTCOME]);
444
  }
445
446
447
// ------------------------------------------------------------------------------------------------
448
// Рассчитывает результат столкновения флотов ака раунд
449
  protected function sn_ube_combat_round_crossfire_fleet(&$combat_data, $round) {
450
    if (BE_DEBUG === true) {
0 ignored issues
show
introduced by
The condition Ube\Ube4_1\BE_DEBUG === true can never be false.
Loading history...
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
451
      // sn_ube_combat_helper_round_header($round);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
452
    }
453
454
    $round_data = &$combat_data[UBE_ROUNDS][$round];
455
    // Проводим бой. Сталкиваем каждый корабль атакующего с каждым кораблем атакуемого
456
    foreach ($round_data[UBE_ATTACKERS][UBE_ATTACK] as $attack_fleet_id => $temp) {
457
      $attack_fleet_data = &$round_data[UBE_FLEETS][$attack_fleet_id];
458
      foreach ($round_data[UBE_DEFENDERS][UBE_ATTACK] as $defend_fleet_id => $temp2) {
459
        $defend_fleet_data = &$round_data[UBE_FLEETS][$defend_fleet_id];
460
461
        foreach ($attack_fleet_data[UBE_COUNT] as $attack_unit_id => $attack_unit_count) {
462
          // if($attack_unit_count <= 0) continue; // TODO: Это пока нельзя включать - вот если будут "боевые порядки юнитов..."
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
463
          foreach ($defend_fleet_data[UBE_COUNT] as $defend_unit_id => $defend_unit_count) {
464
            $this->sn_ube_combat_round_crossfire_unit2($attack_fleet_data, $defend_fleet_data, $attack_unit_id, $defend_unit_id, $combat_data[UBE_OPTIONS]);
465
            $this->sn_ube_combat_round_crossfire_unit2($defend_fleet_data, $attack_fleet_data, $defend_unit_id, $attack_unit_id, $combat_data[UBE_OPTIONS]);
466
          }
467
        }
468
      }
469
    }
470
471
    if (BE_DEBUG === true) {
0 ignored issues
show
introduced by
The condition Ube\Ube4_1\BE_DEBUG === true can never be false.
Loading history...
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
472
      // sn_ube_combat_helper_round_footer();
473
    }
474
  }
475
476
477
  // ------------------------------------------------------------------------------------------------
478
// Рассчитывает результат столкновения двух юнитов ака ход
479
  protected function sn_ube_combat_round_crossfire_unit2(&$attack_fleet_data, &$defend_fleet_data, $attack_unit_id, $defend_unit_id, &$combat_options) {
480
    if ($defend_fleet_data[UBE_COUNT][$defend_unit_id] <= 0) {
481
      return;
482
    }
483
484
    // Вычисляем прямой дамадж от атакующего юнита с учетом размера атакуемого
485
    $direct_damage = floor($attack_fleet_data[UBE_ATTACK][$attack_unit_id] * $defend_fleet_data[UBE_DAMAGE_PERCENT][$defend_unit_id]);
486
487
    // Применяем амплифай, если есть
488
    $amplify = $attack_fleet_data[UBE_FLEET_INFO][UBE_AMPLIFY][$attack_unit_id][$defend_unit_id];
489
    $amplify = $amplify ? $amplify : 1;
490
    $amplified_damage = floor($direct_damage * $amplify);
491
492
    // Проверяем - не взорвался ли текущий юнит
493
    $this->sn_ube_combat_round_crossfire_unit_damage_current($defend_fleet_data, $defend_unit_id, $amplified_damage, $units_lost, $units_boomed, $combat_options);
494
495
    $defend_unit_base_defence = $defend_fleet_data[UBE_SHIELD_BASE][$defend_unit_id] + $defend_fleet_data[UBE_ARMOR_BASE][$defend_unit_id];
496
497
    // todo Добавить взрывы от полуповрежденных юнитов - т.е. заранее вычислить из убитых юнитов еще количество убитых умножить на вероятность от структуры
498
499
    // Вычисляем, сколько юнитов взорвалось полностью
500
    $units_lost_full = floor($amplified_damage / $defend_unit_base_defence);
501
    // Уменьшаем дамадж на ту же сумму
502
    $amplified_damage -= $units_lost_full * $defend_unit_base_defence;
503
    // Вычисляем, сколько юнитов осталось
504
    $defend_fleet_data[UBE_COUNT][$defend_unit_id] = max(0, $defend_fleet_data[UBE_COUNT][$defend_unit_id] - $units_lost_full);
505
    // Уменьшаем броню подразделения на броню потерянных юнитов
506
    $defend_fleet_data[UBE_ARMOR][$defend_unit_id] -= $units_lost_full * $defend_fleet_data[UBE_ARMOR_BASE][$defend_unit_id];
507
    $defend_fleet_data[UBE_SHIELD][$defend_unit_id] -= $units_lost_full * $defend_fleet_data[UBE_SHIELD_BASE][$defend_unit_id];
508
509
    // Проверяем - не взорвался ли текущий юнит
510
    $this->sn_ube_combat_round_crossfire_unit_damage_current($defend_fleet_data, $defend_unit_id, $amplified_damage, $units_lost, $units_boomed, $combat_options);
511
  }
512
513
  protected function sn_ube_combat_round_crossfire_unit_damage_current(&$defend_fleet_data, $defend_unit_id, &$amplified_damage, &$units_lost, &$units_boomed, &$combat_options) {
514
    $unit_is_lost = false;
515
516
    $units_boomed = $units_boomed ? $units_boomed : 0;
517
    $units_lost = $units_lost ? $units_lost : 0;
518
519
    $boom_limit = 75; // Взрываемся на 75% прочности
520
    if ($defend_fleet_data[UBE_COUNT][$defend_unit_id] > 0 && $amplified_damage) {
521
      // $defend_fleet_info = &$defend_fleet_data[UBE_FLEET_INFO];
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
522
523
      $damage_to_shield = min($amplified_damage, $defend_fleet_data[UBE_SHIELD_REST][$defend_unit_id]);
524
      $amplified_damage -= $damage_to_shield;
525
      $defend_fleet_data[UBE_SHIELD_REST][$defend_unit_id] -= $damage_to_shield;
526
527
      $damage_to_armor = min($amplified_damage, $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id]);
528
      $amplified_damage -= $damage_to_armor;
529
      $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id] -= $damage_to_armor;
530
531
      // Если брони не осталось - юнит потерян
532
      if ($defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id] <= 0) {
533
        $unit_is_lost = true;
534
      } // Если броня осталось, но не осталось щитов - прошел дамадж по броне и надо проверить - не взорвался ли корабль
535
      elseif ($defend_fleet_data[UBE_SHIELD_REST][$defend_unit_id] <= 0) {
536
        $last_unit_hp = $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id];
537
        $last_unit_percent = $last_unit_hp / $defend_fleet_data[UBE_ARMOR_BASE][$defend_unit_id] * 100;
538
539
        $random = $combat_options[UBE_SIMULATOR] ? $boom_limit / 2 : mt_rand(0, 100);
540
        if ($last_unit_percent <= $boom_limit && $last_unit_percent <= $random) {
541
          $unit_is_lost = true;
542
          $units_boomed++;
543
          $damage_to_armor += $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id];
544
          $defend_fleet_data[UBE_UNITS_BOOM][$defend_unit_id]++;
545
          $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id] = 0;
546
        }
547
      }
548
549
      $defend_fleet_data[UBE_ARMOR][$defend_unit_id] -= $damage_to_armor;
550
      $defend_fleet_data[UBE_SHIELD][$defend_unit_id] -= $damage_to_shield;
551
552
      if ($unit_is_lost) {
553
        $units_lost++;
554
        $defend_fleet_data[UBE_COUNT][$defend_unit_id]--;
555
        if ($defend_fleet_data[UBE_COUNT][$defend_unit_id]) {
556
          $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id] = $defend_fleet_data[UBE_ARMOR_BASE][$defend_unit_id];
557
          $defend_fleet_data[UBE_SHIELD_REST][$defend_unit_id] = $defend_fleet_data[UBE_SHIELD_BASE][$defend_unit_id];
558
        }
559
      }
560
    }
561
562
    return $unit_is_lost;
563
  }
564
565
}
566