В другом вопросе вы помогли мне создать алгоритм моделирования для футбола. У меня есть очень хорошие ответы. Еще раз спасибо!
Теперь я закодировал этот алгоритм. Я хотел бы улучшить его и найти небольшие ошибки, которые могут быть в нем. Я не хочу обсуждать, как его решить, как мы это делали в последнем вопросе. Теперь я только хочу его улучшить. Можете ли вы снова помочь мне?
Тактические настройки, которые должны влиять на случайность:
Примечание: Тактика 0 и тактика 4 частично интегрированы в остальную часть двигателя, не требуются в этой функции.
Текущий алгоритм:
<?php function tactics_weight($wert) { $neuerWert = $wert*0.1+0.8; return $neuerWert; } function strengths_weight($wert) { $neuerWert = log10($wert+1)+0.35; return $neuerWert; } function Chance_Percent($chance, $universe = 100) { $chance = abs(intval($chance)); $universe = abs(intval($universe)); if (mt_rand(1, $universe) <= $chance) { return true; } return false; } function simulate_attack($teamname_att, $teamname_def, $strength_att, $strength_def) { global $minute, $goals, $_POST, $matchReport, $fouls, $yellowCards, $redCards, $offsides, $shots, $tactics; // input values: attacker's name, defender's name, attacker's strength array, defender's strength array // players' strength values vary from 0.1 to 9.9 $matchReport .= '<p>'.$minute.'\': '.comment_action($teamname_att, 'attack'); $offense_strength = $strength_att['forwards']/$strength_def['defenders']; $defense_strength = $strength_def['defenders']/$strength_att['forwards']; if (Chance_Percent(50*$offense_strength*tactics_weight($tactics[$teamname_att][1])/tactics_weight($tactics[$teamname_att][2]))) { // attacking team passes 1st third of opponent's field side $matchReport .= ' '.comment_action($teamname_def, 'advance'); if (Chance_Percent(25*tactics_weight($tactics[$teamname_def][5]))) { // the defending team fouls the attacking team $fouls[$teamname_def]++; $matchReport .= ' '.comment_action($teamname_def, 'foul'); if (Chance_Percent(43)) { // yellow card for the defending team $yellowCards[$teamname_def]++; $matchReport .= ' '.comment_action($teamname_def, 'yellow'); } elseif (Chance_Percent(3)) { // red card for the defending team $redCards[$teamname_def]++; $matchReport .= ' '.comment_action($teamname_def, 'red'); } // indirect free kick $matchReport .= ' '.comment_action($teamname_att, 'iFreeKick'); if (Chance_Percent(25*strengths_weight($strength_att['forwards']))) { // shot at the goal $shots[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_att, 'iFreeKick_shot'); if (Chance_Percent(25/strengths_weight($strength_def['goalkeeper']))) { // attacking team scores $goals[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_att, 'shot_score'); } else { // defending goalkeeper saves $matchReport .= ' '.comment_action($teamname_def, 'iFreeKick_shot_save'); } } else { // defending team cleares the ball $matchReport .= ' '.comment_action($teamname_def, 'iFreeKick_clear'); } } elseif (Chance_Percent(17)*tactics_weight($tactics[$teamname_att][2])) { // attacking team is caught offside $offsides[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_def, 'offside'); } else { // attack isn't interrupted // attack passes the 2nd third of the opponent's field side - good chance $matchReport .= ' '.comment_action($teamname_def, 'advance_further'); if (Chance_Percent(25*tactics_weight($tactics[$teamname_def][5]))) { // the defending team fouls the attacking team $fouls[$teamname_def]++; $matchReport .= ' '.comment_action($teamname_def, 'foul'); if (Chance_Percent(43)) { // yellow card for the defending team $yellowCards[$teamname_def]++; $matchReport .= ' '.comment_action($teamname_def, 'yellow'); } elseif (Chance_Percent(3)) { // red card for the defending team $redCards[$teamname_def]++; $matchReport .= ' '.comment_action($teamname_def, 'red'); } if (Chance_Percent(19)) { // penalty for the attacking team $shots[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_att, 'penalty'); if (Chance_Percent(77)) { // attacking team scores $goals[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_att, 'shot_score'); } elseif (Chance_Percent(50)) { // shot misses the goal $matchReport .= ' '.comment_action($teamname_att, 'penalty_miss'); } else { // defending goalkeeper saves $matchReport .= ' '.comment_action($teamname_def, 'penalty_save'); } } else { // direct free kick $matchReport .= ' '.comment_action($teamname_att, 'dFreeKick'); if (Chance_Percent(33*strengths_weight($strength_att['forwards']))) { // shot at the goal $shots[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_att, 'dFreeKick_shot'); if (Chance_Percent(33/strengths_weight($strength_def['goalkeeper']))) { // attacking team scores $goals[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_att, 'shot_score'); } else { // defending goalkeeper saves $matchReport .= ' '.comment_action($teamname_def, 'dFreeKick_shot_save'); } } else { // defending team cleares the ball $matchReport .= ' '.comment_action($teamname_def, 'dFreeKick_clear'); } } } elseif (Chance_Percent(62*strengths_weight($strength_att['forwards'])*tactics_weight($tactics[$teamname_att][2])*tactics_weight($tactics[$teamname_att][3]))) { // shot at the goal $shots[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_att, 'shot'); if (Chance_Percent(30/strengths_weight($strength_def['goalkeeper']))) { // the attacking team scores $goals[$teamname_att]++; $matchReport .= ' '.comment_action($teamname_att, 'shot_score'); } else { if (Chance_Percent(50)) { // the defending defenders block the shot $matchReport .= ' '.comment_action($teamname_def, 'shot_block'); } else { // the defending goalkeeper saves $matchReport .= ' '.comment_action($teamname_def, 'shot_save'); } } } else { // attack is stopped $matchReport .= ' '.comment_action($teamname_def, 'stopped'); if (Chance_Percent(15*$defense_strength*tactics_weight($tactics[$teamname_att][1])*tactics_weight($tactics[$teamname_att][3])*tactics_weight($tactics[$teamname_def][4]))) { // quick counter attack - playing on the break $strength_att['defenders'] = $strength_att['defenders']*0.8; // weaken the current attacking team's defense $matchReport .= ' '.comment_action($teamname_def, 'quickCounterAttack'); $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line return simulate_attack($teamname_def, $teamname_att, $strength_def, $strength_att); // new attack - this one is finished } } } } // attacking team doesn't pass 1st third of opponent's field side elseif (Chance_Percent(15*$defense_strength*tactics_weight($tactics[$teamname_att][1])*tactics_weight($tactics[$teamname_att][3])*tactics_weight($tactics[$teamname_def][4]))) { // attack is stopped // quick counter attack - playing on the break $matchReport .= ' '.comment_action($teamname_def, 'stopped'); $strength_att['defenders'] = $strength_att['defenders']*0.8; // weaken the current attacking team's defense $matchReport .= ' '.comment_action($teamname_def, 'quickCounterAttack'); $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line return simulate_attack($teamname_def, $teamname_att, $strength_def, $strength_att); // new attack - this one is finished } else { // ball goes into touch - out of the field $matchReport .= ' '.comment_action($teamname_def, 'throwIn'); if (Chance_Percent(33)) { // if a new chance is created if (Chance_Percent(50)) { // throw-in for the attacking team $matchReport .= ' '.comment_action($teamname_def, 'throwIn_att'); $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line return simulate_attack($teamname_att, $teamname_def, $strength_att, $strength_def); // new attack - this one is finished } else { // throw-in for the defending team $matchReport .= ' '.comment_action($teamname_def, 'throwIn_def'); $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line return simulate_attack($teamname_def, $teamname_att, $strength_def, $strength_att); // new attack - this one is finished } } } $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line return TRUE; // finish the attack }
Обновление (2014 год): Несколько лет спустя я выпустил полную базу кода игры в качестве открытого источника на GitHub . Вы найдете конкретную реализацию этого моделирования в этом файле , если кому-то это интересно.
В общем, похоже, что это довольно сложная проблема, и я не уверен, насколько эффективно вы ее получите.
Тем не менее, я видел кое-что, что решительно помогло бы вам.
Сначала я бы напечатал переменные в параметрах. Возможно, это не обязательно сделает ваш код быстрее, но это упростит чтение и отладку. Затем я удаляю параметры $ teamname_att, $ teamname_def и просто получаю их как значения в ассоциативных массивах $ strength_att, $ strong_def. Так как эти данные всегда в паре все равно, это уменьшит риск случайного использования имени одной команды в качестве ссылки на другую команду.
Это сделает так, что вам не придется постоянно искать значения в массивах:
// replace all $tactics[$teamname_att] with $attackers $attackers = $tactics[$teamname_att]; $defenders = $tactics[$teamname_def]; // Now do the same with arrays like $_POST[ "team1" ];
У вас есть три вспомогательные функции, которые имеют шаблон:
function foo( $arg ){ $bar = $arg * $value; return $bar; }
Поскольку это означает, что при каждом запуске функции вам нужно создать дополнительную переменную (что может быть дорогостоящим), используйте вместо этого:
function tactics_weight($wert) { return $wert*0.1+0.8; } function strengths_weight($wert) { return log10($wert+1)+0.35; } /* Perhaps I missed it, but I never saw Chance_Percent( $num1, $num2 ) consider using this function instead: (one line instead of four, it also functions more intuitively, Chance_Percent is your chance out of 100 (or per cent) function Chance_Percent( $chance ) { return (mt_rand(1, 100) <= $chance); } */ function Chance_Percent($chance, $universe = 100) { $chance = abs(intval($chance)); // Will you always have a number as $chance? // consider using only abs( $chance ) here. $universe = abs(intval($universe)); return (mt_rand(1, $universe) <= $chance); }
Я не мог не заметить, что эта закономерность складывается последовательно:
$matchReport .= ' ' . comment_action($teamname_att, 'attack');
Мой общий опыт заключается в том, что если вы переместите конкатенацию $ matchReport в comment_action, то она будет немного быстрее (обычно менее десятка миллисекунд, но поскольку вы вызываете эту функцию в полдюжины раз внутри рекурсивной функции, это может сбрить пару десятых доли секунды за ход).
Я думаю, что это будет намного лучше (как с точки зрения читателя, так и с
Наконец, есть несколько раз, когда вы будете использовать один и тот же вызов с той же функцией с тем же параметром. Сделайте этот вызов вперед:
$goalieStrength = strengths_weight($strength_def['goalkeeper']);
Надеюсь это поможет.
Я (быстро) прочитал это, и я заметил пару вещей:
Процент, который красная / желтая карточка передается, одинакова во всех трети поля, является ли это преднамеренным? Я не футбольный парень, но я бы сказал, что правонарушения чаще всего происходят на последней трети поля, чем на первом. (Потому что, если вы на первом, вы, вероятно, защищаетесь)
Процент для определения того, что штраф забит, одинаковый для каждой команды, однако некоторые команды, или, скорее, игроки, с большей вероятностью наберут штраф, чем другие.
Вы не принимаете во внимание угловые удары, возможные травмы после фола или забитые голы головой (что можно было бы упомянуть в отчете).
Кроме того, вам просто нужно много раз запускать эту симуляцию и посмотреть, правильно ли вы выбрали значения; настроить алгоритм. Лучше всего это вручную настроить его (например, прочитать все константы из файла и запустить несколько сотен симуляций с разными значениями и разными командами), проще всего сделать это, чтобы реализовать генетический алгоритм, чтобы попытаться найти лучшие значения.
В основном то, что у вас здесь, – это подлинный код геймплея / ai, поэтому вы можете ознакомиться с техникой, используемой игровыми студиями для управления этим типом кода. (Одна вещь заключается в том, чтобы поместить переменные в электронную таблицу google, которую вы можете затем добавить / настроить более легко, например).
Кроме того, несмотря на то, что вам не хватает некоторых вещей, которые есть в реальном матче с футболом, нет смысла пытаться быть настолько реалистичным, насколько это возможно, потому что, как правило, в этих случаях важно обеспечить хороший игровой процесс, чем обеспечить точное моделирование.
Yous, кажется, отсутствует: –
#include oscar.h; void function dive (int ball_location, int[] opposition, int[] opposition_loc) { if (this.location != PenaltyBox || ball_location != PenatlyBox) return; } else { for (x = 0; x < 11; x++) { if ( opposition_loc[x] = PenaltyBox ) { scream(loudly); falldown(); roll_around(); cry(); roll_around(); scream(patheticaly); plead_with_ref(); return; } } return; }
Как часто эти значения будут проверяться? Если он будет использоваться многими людьми и постоянно рекурсивно проверяет эти утверждения if / else, я вижу, что вы много едите и работаете довольно медленно.
Возможно, вы могли бы, кроме нескольких переключателей, заменить некоторые из них?
Это все, что я могу видеть для улучшения скорости. Что касается самого алгоритма, мне придется немного подумать об этом чуть позже, если никто не сделает этого.