array(), 'Great Dragon' => array( '4' => array('melee' => 459, 'ranged' => 459, 'def' => 459, 'hp' => 45947, 'speed' => 750, 'range' => 1500), '5' => array('melee' => 747, 'ranged' => 747, 'def' => 747, 'hp' => 74743, 'speed' => 750, 'range' => 1500), '6' => array('melee' => 1055, 'ranged' => 1055, 'def' => 1055, 'hp' => 105560, 'speed' => 750, 'range' => 1500), '7' => array('melee' => 1379, 'ranged' => 1379, 'def' => 1379, 'hp' => 137972, 'speed' => 750, 'range' => 1500), '8' => array('melee' => 1717, 'ranged' => 1717, 'def' => 1717, 'hp' => 171716, 'speed' => 750, 'range' => 1500), '9' => array('melee' => 2066, 'ranged' => 2066, 'def' => 2066, 'hp' => 206608, 'speed' => 750, 'range' => 1500), '10' => array('melee' => 2425, 'ranged' => 2425, 'def' => 2425, 'hp' => 242514, 'speed' => 750, 'range' => 1500)), 'Stone Dragon' => array( '4' => array('melee' => 1836, 'ranged' => 1378, 'def' => 2754, 'hp' => 183788, 'speed' => 650, 'range' => 1700), '5' => array('melee' => 2988, 'ranged' => 2242, 'def' => 4482, 'hp' => 298972, 'speed' => 650, 'range' => 1700), '6' => array('melee' => 4220, 'ranged' => 3164, 'def' => 6330, 'hp' => 422240, 'speed' => 650, 'range' => 1700), '7' => array('melee' => 5516, 'ranged' => 4138, 'def' => 8274, 'hp' => 551888, 'speed' => 650, 'range' => 1700), '8' => array('melee' => 6868, 'ranged' => 5152, 'def' => 10302, 'hp' => 686864, 'speed' => 650, 'range' => 1700), '9' => array('melee' => 8264, 'ranged' => 6198, 'def' => 12396, 'hp' => 826432, 'speed' => 650, 'range' => 1700), '10' => array('melee' => 9700, 'ranged' => 7276, 'def' => 14550, 'hp' => 970056, 'speed' => 650, 'range' => 1700)), ); $bs = array( 1 => array('melee' => 1, 'ranged' => 0, 'def' => 10, 'hp' => 45, 'speed' => 100, 'range' => 0, 'name' => 'Porter'), 2 => array('melee' => 10, 'ranged' => 0, 'def' => 10, 'hp' => 75, 'speed' => 200, 'range' => 0, 'name' => 'Conscript'), 3 => array('melee' => 5, 'ranged' => 0, 'def' => 5, 'hp' => 10, 'speed' => 3000, 'range' => 0, 'name' => 'Spy'), 4 => array('melee' => 40, 'ranged' => 0, 'def' => 40, 'hp' => 150, 'speed' => 300, 'range' => 0, 'name' => 'Halberdsmen'), 5 => array('melee' => 70, 'ranged' => 0, 'def' => 45, 'hp' => 225, 'speed' => 275, 'range' => 0, 'name' => 'Minotaur'), 6 => array('melee' => 5, 'ranged' => 80, 'def' => 30, 'hp' => 75, 'speed' => 250, 'range' => 1200, 'name' => 'Longbowmen'), 7 => array('melee' => 150, 'ranged' => 0, 'def' => 60, 'hp' => 300, 'speed' => 1000, 'range' => 0, 'name' => 'Swift strike dragon'), 8 => array('melee' => 300, 'ranged' => 0, 'def' => 300, 'hp' => 1500, 'speed' => 750, 'range' => 0, 'name' => 'Battle dragon'), 9 => array('melee' => 5, 'ranged' => 0, 'def' => 200, 'hp' => 750, 'speed' => 150, 'range' => 0, 'name' => 'Armored transport'), 10 => array('melee' => 1000, 'ranged' => 0, 'def' => 400, 'hp' => 4000, 'speed' => 120, 'range' => 0, 'name' => 'Giant'), 11 => array('melee' => 20, 'ranged' => 1200, 'def' => 30, 'hp' => 1500, 'speed' => 50, 'range' => 1500, 'name' => 'Fire Mirror'), 12 => array('melee' => 150, 'ranged' => 0, 'def' => 400, 'hp' => 850, 'speed' => 1000, 'range' => 0, 'name' => 'Pack Dragon'), 13 => array('melee' => 1600, 'ranged' => 800, 'def' => 300, 'hp' => 3000, 'speed' => 500, 'range' => 600, 'name' => 'Fangtooth'), 14 => array('melee' => 650, 'ranged' => 0, 'def' => 900, 'hp' => 15000, 'speed' => 350, 'range' => 0, 'name' => 'Granite Ogre'), 15 => array('melee' => 500, 'ranged' => 2000, 'def' => 150, 'hp' => 1000, 'speed' => 400, 'range' => 1600, 'name' => 'Lava Jaw'), 16 => array('melee' => 700, 'ranged' => 0, 'def' => 200, 'hp' => 2850, 'speed' => 1350, 'range' => 0, 'name' => 'Banshee'), 17 => array('melee' => 1000, 'ranged' => 0, 'def' => 500, 'hp' => 3000, 'speed' => 450, 'range' => 0, 'name' => 'Soul Reaper'), 18 => array('melee' => 900, 'ranged' => 800, 'def' => 225, 'hp' => 3500, 'speed' => 300, 'range' => 700, 'name' => 'Venom Dweller'), 19 => array('melee' => 1500, 'ranged' => 0, 'def' => 200, 'hp' => 5500, 'speed' => 200, 'range' => 0, 'name' => 'Frost Giant'), 20 => array('melee' => 5000, 'ranged' => 0, 'def' => 1500, 'hp' => 7500, 'speed' => 50, 'range' => 0, 'name' => 'Petrified Titan'), 21 => array('melee' => 600, 'ranged' => 400, 'def' => 600, 'hp' => 2000, 'speed' => 1000, 'range' => 1200, 'name' => 'Sand Strider'), ); $wall_koef = 1.05; ?>

Нападающая сторона (attacker)

Сторона обороны (defender)

Дракон (Dragon)

Уровень: Уровень:

Войска (Battle units)

Porter
Conscript
Spy
Halbersman
Minotaur
Longbowman
Swift Dragon
Battle Dragon
Armored Tr.
Giant
Fire Mirror
Pack Dragon
FangTooth
Granite Ogre
Lava Jaw
Banshee
Soul Reaper
Venom Dweller
Frost Giant
Petrified Titan
Sand Strider
Porter
Conscript
Spy
Halbersman
Minotaur
Longbowman
Swift Dragon
Battle Dragon
Armored Tr.
Giant
Fire Mirror
Pack Dragon
FangTooth
Granite Ogre
Lava Jaw
Banshee
Soul Reaper
Venom Dweller
Frost Giant
Petrified Titan
Sand Strider

Технологии (Technologies)

WC
MET
MED
DRG
RD
WR
GR
WC
MET
MED
DRG
RD
WR
GR
Уровень стены (city wall level)
array(), 's' => array(), ); $def = array( 'f' => array(), 's' => array(), 'w' => 0 ); //научка for($k = 1; $k < 7; $k ++) { if (!empty($_POST['s' . $k])) { $value = _num_read('s' . $k); $att['s'][$k] = $value; } if (!empty($_POST['sc' . $k])) { $value = _num_read('sc' . $k); $def['s'][$k] = $value; } } //стена $def['w'] = _num_read('wall') * $wall_koef; //модификатор защиты стенки $maxRange = 0; //драконы if ($_POST['da'] != '-- Нет --' && isset($dragons[$_POST['da']]) && $_POST['da_lev'] + 0 >= 8 && $_POST['da_lev'] + 0 <= 10) { $att['f'][0] = $dragons[$_POST['da']][$_POST['da_lev'] + 0]; $att['f'][0]['amount'] = 1; $att['f'][0]['name'] = $_POST['da']; $maxRange = $att['f'][0]['range']; } if ($_POST['dd'] != '-- Нет --' && isset($dragons[$_POST['dd']]) && $_POST['dd_lev'] + 0 >= 8 && $_POST['dd_lev'] + 0 <= 10) { $def['f'][0] = $dragons[$_POST['dd']][$_POST['dd_lev'] + 0]; $def['f'][0]['amount'] = 1; $def['f'][0]['name'] = $_POST['dd']; // $maxRange = max($def['f'][0]['range'], $maxRange); } //отряды for($k = 1; $k < 22; $k ++) { if (!empty($_POST['p' . $k])) { $value = _num_read('p' . $k); if ($value > 0) { $att['f'][$k] = $bs[$k]; $att['f'][$k]['amount'] = $value; $att['f'][$k]['range'] *= 1 + $att['s'][1] * 0.05; //WC $att['f'][$k]['ranged'] *= 1 + $att['s'][2] * 0.05; //MET $att['f'][$k]['melee'] *= 1 + $att['s'][2] * 0.05; //MET $att['f'][$k]['def'] *= 1 + $att['s'][2] * 0.05; //MET $att['f'][$k]['hp'] *= 1 + $att['s'][3] * 0.05; //MED $att['f'][$k]['speed'] *= 1 + $att['s'][5] * 0.05 //RD + ($k == 7 || $k == 8 ? $att['s'][4] * 0.05 : 0); //DRAG if ($maxRange < $att['f'][$k]['range']) $maxRange = $att['f'][$k]['range']; } } if (!empty($_POST['r' . $k])) { $value = _num_read('r' . $k); if ($value > 0) { $def['f'][$k] = $bs[$k]; $def['f'][$k]['amount'] = $value; $def['f'][$k]['range'] *= 1 + $def['s'][1] * 0.05; //WC $def['f'][$k]['ranged'] *= 1 + $def['s'][2] * 0.05; //MET $def['f'][$k]['melee'] *= 1 + $def['s'][2] * 0.05; //MET $def['f'][$k]['def'] *= 1 + $def['s'][2] * 0.05; //MET $def['f'][$k]['hp'] *= 1 + $def['s'][3] * 0.05; //MED $def['f'][$k]['speed'] *= 1 + $def['s'][5] * 0.05 //RD + ($k == 7 || $k == 8 ? $def['s'][4] * 0.05 : 0); //DRAG // if ($maxRange < $def['f'][$k]['range']) $maxRange = $def['f'][$k]['range']; } } } $len = rand(350, 500) + $maxRange; //вообще то от 325 до 550 //расчет раундов и вывод информации по итерациям $DOA = new DAO_calc($att, $def, $len); echo "

Обратите внимание, что некоторые детали боя зависят от случайных факторов (от генератора случаных чисел - RNG). Потому стоит несколько раз прогонять одни и те же данные через расчет, чтобы поглядеть возможные варианты исхода боя.

Перед боем (Before fight)

"; echo $DOA->show(); while ($DOA -> iteration()) { echo "

Раунд (Round) № " . $DOA->n_inter . '

'; echo $DOA->show(); } } function _num_read($name) { if (!empty($_POST[$name])) { return floor(abs($_POST[$name] + 0)); } return 0; } /* класс для расчета раундов боя */ class DAO_calc { var $att, $def; var $n_inter = 0; function DAO_calc($att, $def, $range) { uasort($att['f'], 'DAO_calc::speed_buble'); $this->att = $att; uasort($def['f'], 'DAO_calc::speed_buble'); $this->def = $def; foreach($this->att['f'] as $k => $v) { $this->att['f'][$k]['pos'] = 0; //общее число хитов и брони $this->att['f'][$k]['hp-amount'] = $v['amount'] * $v['hp']; $this->att['f'][$k]['arm-amount'] = $v['amount'] * $v['def']; } foreach($this->def['f'] as $k => $v) { $this->def['f'][$k]['pos'] = $range; //общее число хитов и брони $this->def['f'][$k]['hp-amount'] = $v['amount'] * $v['hp']; $this->def['f'][$k]['arm-amount'] = $v['amount'] * $v['def']; } } //расстояние и описание группы войск - рассчитаем потенц. опасность function danger_rating($distance, $bg) { if ($distance > 0 && $bg['ranged'] > 0) { return $bg['ranged'] * $bg['amount']; } else { return $bg['melee'] * $bg['amount']; } } /* выбрать ближайшего врага со строны защиты */ function select_def($att_ind) { $z = &$this->att[$att_ind]; $pos = 1000000; $danger = 0; $t = -1; foreach($this->def['f'] as $ek => $ev) { $new_danger = $this->danger_rating($ev['pos'] - $z['pos'], $ev); if ($pos > $ev['pos'] || ($pos == $ev['pos'] && $new_danger > $danger) ) { $pos = $ev['pos']; $danger = $new_danger; $t = $ek; } } return $t; } /* выбрать ближайшего врага со строны атаккера */ function select_att($def_ind) { $z = &$this->def[$def_ind]; $pos = -100; $danger = 0; $t = -1; foreach($this->att['f'] as $ek => $ev) { $new_danger = $this->danger_rating($z['pos'] - $ev['pos'], $ev); if ($pos < $ev['pos'] || ($pos == $ev['pos'] && $new_danger > $danger) ) { $pos = $ev['pos']; $danger = $new_danger; $t = $ek; } } return $t; } /* вывод таблицы раунда */ function show() { $as = ''; foreach ($this->att['f'] as $k => $v) { if (!$v['amount']) { $as .= ""; unset($this->att['f'][$k]); } else { if ($v['f']) { $class = 'wounded'; $this->att['f'][$k]['f'] = 0; } else $class = ''; $as .= ""; } } $as .= '
ATTeffHPDEFAmountPos
{$v['name']}" . floor($v['pos']) . "
{$v['name']}" . round($v['attack'], 2) . "" . floor($v['hp-amount'] / $v['amount']) . "" . floor($v['arm-amount'] / $v['amount']). "" . floor($v['amount']) . "" . floor($v['pos']) . "
'; $ds = ''; foreach ($this->def['f'] as $k => $v) { if (!$v['amount']) { $ds .= ""; unset($this->def['f'][$k]); } else { if ($v['f']) { $class = 'wounded'; $this->def['f'][$k]['f'] = 0; } else $class = ''; $ds .= ""; } } $ds .= '
ATTeffHPDEFAmountPos
{$v['name']}" . floor($v['pos']) . "
{$v['name']}" . round($v['attack'] ,2) . "" . floor($v['hp-amount'] / $v['amount']) . "" . floor($v['arm-amount'] / $v['amount']). "" . floor($v['amount']) . "" . floor($v['pos']) . "
'; return "
$as $ds
"; } function iteration() { //остались ли ещё воины $n = 0; foreach($this->att['f'] as $k => $v) { $n += $this->att['f'][$k]['amount']; } if (!$n) return false; $n = 0; foreach($this->def['f'] as $k => $v) { $n += $this->def['f'][$k]['amount']; } if (!$n) return false; $this->n_inter ++; if ($this->n_inter > 50) return false; //ограничение по числу расчетных раундов //ход атакующего foreach($this->att['f'] as $k => $v) { //ближайший враг $t = $this->select_def($k); $defer = &$this->def['f'][$t]; if ($t == -1) return true; //враг не обнаружен - но итерация полноценная, поэтому вернем true $pos = $defer['pos']; //движение if ($pos > $v['pos'] + $v['range']) { $new_pos = min($v['pos'] + $v['speed'], $pos - $v['range']); if ($new_pos > $v['pos']) { $this->att['f'][$k]['pos'] = $new_pos; $v['pos'] = $new_pos; } } if ($v['pos'] < $pos && $v['pos'] + $v['range'] >= $pos) { //атака ranged $attack = $v['ranged']; } else if ($v['pos'] == $pos) { //атака melee $attack = $v['melee']; } else continue; $attack -= $this->def['w']; $this->att['f'][$k]['attack'] = $attack; if ($attack <= 0) continue; $dem = $attack * $v['amount']; $defer['f'] = 1; $amount = $defer['amount']; $arm = $defer['arm-amount']; $hp = $defer['hp-amount']; //коэф неопред $min = 0.5; $max = $attack / ($attack + $defer['def']); $dem = $dem * 0.5 + $dem * $max * mt_rand() / mt_getrandmax(); //особенности if ($k == 18 && $t == 14) $dem *= 2; //venom dveller атакует granite ogre с удвоенным уроном if ($k == 19 && $t == 15) $dem /= 2; //lava jaw получает в два раза меньший урон от frost giant //варианты стычки if ($dem >= $arm + $hp) { $defer['amount'] = 0; //сдохли } else if ($dem <= $arm) { // $this->def['f'][$t]['def'] = ($arm - $dem) / $amount; //ослабление брони (чисто для индикации) $defer['arm-amount'] -= $dem; } else { // $this->def['f'][$t]['def'] = 0 $dem -= $defer['arm-amount']; $defer['arm-amount'] = 0; //броня выбита $defer['hp-amount'] -= $dem; $defer['amount'] = ceil($defer['hp-amount'] / $defer['hp']); } } //ход обороняющегося foreach($this->def['f'] as $k => $v) { if (!$v['amount']) continue; //ближайший враг $t = $this->select_att($k); $ataker = &$this->att['f'][$t]; if ($t == -1) return true; //враг не обнаружен - но итерация полноценная, поэтому вернем true $pos = $ataker['pos']; //движение if ($pos < $v['pos'] - $v['range']) { $new_pos = max($v['pos'] - $v['speed'], $pos + $v['range']); if ($new_pos < $v['pos']) { $this->def['f'][$k]['pos'] = $new_pos; $v['pos'] = $new_pos; } } if ($v['pos'] > $pos && $v['pos'] - $v['range'] <= $pos) { //атака ranged $attack = $v['ranged']; } else if ($v['pos'] == $pos) { //атака melee $attack = $v['melee']; } else continue; $this->def['f'][$k]['attack'] = $attack; $dem = $attack * $v['amount']; $ataker['f'] = 1; $amount = $ataker['amount']; $arm = $ataker['arm-amount']; $hp = $ataker['hp-amount']; //коэф неопред $min = 0.5; $max = $attack / ($attack + $ataker['def']); $dem = $dem * 0.5 + $dem * $max * mt_rand() / mt_getrandmax(); //особенности if ($k == 18 && $t == 14) $dem *= 2; //venom dveller атакует granite ogre с удвоенным уроном if ($k == 19 && $t == 15) $dem /= 2; //lava jaw получает в два раза меньший урон от frost giant //варианты стычки if ($dem >= $arm + $hp) { $ataker['amount'] = 0; //сдохли } else if ($dem <= $arm) { // $this->att['f'][$t]['def'] = ($arm - $dem) / $amount; //ослабление брони $ataker['arm-amount'] -= $dem; } else { // $this->att['f'][$t]['def'] = 0 $dem -= $ataker['arm-amount']; $ataker['arm-amount'] = 0; //броня выбита $ataker['hp-amount'] -= $dem; $ataker['amount'] = ceil($ataker['hp-amount'] / $ataker['hp']); } } return true; } static function speed_buble($a, $b) { if ($a['speed'] == $b['speed']) { return 0; } return ($a['speed'] > $b['speed']) ? -1 : 1; //с большей скоротью объекты всплвывают вверх } }