Example #1
0
function whatdied($remain, $start)
{
    $lost = array();
    foreach ($start as $type => $count) {
        if (isset($remain[$type]) && $remain[$type] > 0) {
            if ($count > $remain[$type]) {
                $lost[$type] = $count - $remain[$type];
            }
        } else {
            $lost[$type] = $count;
        }
    }
    if (can_bombard($start) && has_land($start)) {
        if (isset($lost['Bat'])) {
            unset($lost['Bat']);
        }
        if (isset($lost['Cru'])) {
            unset($lost['Cru']);
        }
        if (isset($lost['Des'])) {
            unset($lost['Des']);
        }
    }
    return $lost;
}
Example #2
0
function skirmish($aforce, $dforce)
{
    global $t, $options, $submerged;
    //conduct opening fire step
    $ofsaresolved = false;
    $ofsdresolved = false;
    $killsfireback = false;
    $air_a = false;
    $air_d = false;
    $avals = array('totalhits' => 0);
    $dvals = array('totalhits' => 0);
    $alost = array();
    $dlost = array();
    if ($options['seabattle']) {
        //if sea battle:
        if (has_sub($aforce)) {
            $avals['ofs'] = subattack($aforce, 'attack');
        }
        //handle attack subs
        if (has_sub($dforce)) {
            $dvals['ofs'] = subattack($dforce, 'defend');
        }
    } else {
        if ($t == 1 && ($_REQUEST['ruleset'] == 'Classic' || $_REQUEST['ruleset'] == 'Revised')) {
            //check for other opening fire
            //the amphibious assault casualties for AA50 and AA1942 are moved into the regular take casualities section
            if (has_land($aforce) && can_bombard($aforce)) {
                //Amphibious assault
                #debug ('Bombarding');
                $avals['ofs'] = bombard($aforce);
                if (isset($aforce['Bat'])) {
                    $submerged['att']['Bat'] = $aforce['Bat'];
                    unset($aforce['Bat']);
                }
                if (isset($aforce['Des'])) {
                    $submerged['att']['Des'] = $aforce['Des'];
                    unset($aforce['Des']);
                }
            }
        }
    }
    if ($t == 1) {
        if (aa_present() && has_air($aforce)) {
            $dvals['ofs'] = aa_fire($aforce);
        }
    }
    if (isset($avals['ofs'])) {
        $ofsd_triaged = triage($dforce, $avals['ofs'], $dlost, 'def');
        //determine what the casualties will be from OFS for each side:
        $dlost = $ofsd_triaged['lost'];
        $avals['totalhits'] += $avals['ofs']['hits'];
        if (!$options['seabattle'] or $options['seabattle'] && !isset($dforce['Des'])) {
            //resolve casualties if OFS victims are not saved by destroyers
            $dforce = $ofsd_triaged['force'];
            $ofsdresolved = true;
        }
    }
    //lather, rinse, repeat for defender.
    if (isset($dvals['ofs'])) {
        //triage attacking casualties from OFS
        $ofsa_triaged = triage($aforce, $dvals['ofs'], $alost, 'att');
        $alost = $ofsa_triaged['lost'];
        $dvals['totalhits'] += $dvals['ofs']['hits'];
        if (!$options['seabattle'] or $options['seabattle'] && (!isset($aforce['Des']) && $_REQUEST['ruleset'] !== 'Europe')) {
            #take hits right away
            $aforce = $ofsa_triaged['force'];
            $ofsaresolved = true;
        }
    }
    // for all but sub sneak attacks vs a force with DDs and AA50/AA1942 bombardment, OFS casualties already taken.
    //for AA50 and AA1942, taking casualties from bombardment - if it is round 1
    if ($t == 1 && ($_REQUEST['ruleset'] == 'AA50' || $_REQUEST['ruleset'] == 'AA1942')) {
        if (has_land($aforce) && can_bombard($aforce)) {
            //Amphibious assault attacker has to have land units
            //bombards can hit air units now in the AA50 and AA1942 editions.
            #debug ('Bombarding');
            $killsfireback = true;
            $avals['ofs'] = bombard($aforce);
            #print_r ($avals['ofs']);
            $avals['totalhits'] += $avals['ofs']['hits'];
            if (isset($aforce['Bat'])) {
                $submerged['att']['Bat'] = $aforce['Bat'];
                unset($aforce['Bat']);
            }
            if (isset($aforce['Cru'])) {
                $submerged['att']['Cru'] = $aforce['Cru'];
                unset($aforce['Cru']);
            }
        }
    }
    //if AA50/AA1942 AND attacker has air, but no destroyer, and defender has subs, then
    //find hits scored by air (so their hits can be applied to subs or not with DD interaction)
    $air_a = false;
    //reset boolean flags that keep track if air have already fired in this round of combat
    $air_d = false;
    if ($_REQUEST['ruleset'] == 'AA50' or $_REQUEST['ruleset'] == 'AA1942') {
        if (has_air($aforce) && !isset($aforce['Des']) && has_sub($dforce)) {
            //if there are nonsubs in the defenders, then roll for attacking air units
            if (nonsubs($dforce)) {
                $avals['norm'] = airattack($aforce, 'attack');
                $avals['totalhits'] += $avals['norm']['hits'];
                //store result from airattack function in a temp array to be merged with the takeshots results later
                $airavals = $avals;
            }
            //set boolean flag to indicate air have fired in this round already
            $air_a = true;
        }
        if (has_air($dforce) && !isset($dforce['Des']) && has_sub($aforce)) {
            //if there are nonsubs in the attackers, then roll for defending air units
            if (nonsubs($aforce)) {
                $dvals['norm'] = airattack($dforce, 'defend');
                $dvals['totalhits'] += $dvals['norm']['hits'];
                //store result from airattack function in a temp array to be merged with the takeshots results later
                $airdvals = $dvals;
            }
            //set boolean flag to indicate air have fired in this round already
            $air_d = true;
        }
    }
    //find number of hits scored by all regular remaining units
    if (nonsubs($aforce)) {
        $avals['norm'] = takeshots($aforce, 'attack', $air_a);
        //pass tracking flag if air has already fired
        $avals['totalhits'] += $avals['norm']['hits'];
    }
    if (nonsubs($dforce) or $options['AA']) {
        $dvals['norm'] = takeshots($dforce, 'defend', $air_d);
        //pass tracking flag if air has already fired
        $dvals['totalhits'] += $dvals['norm']['hits'];
    }
    //Having allowed the counterattack for sub victims saved by destroyers, now take them off before other casualties are taken
    if (isset($ofsa_triaged) && !$ofsaresolved) {
        $aforce = $ofsa_triaged['force'];
    }
    if (isset($ofsd_triaged) && !$ofsdresolved) {
        $dforce = $ofsd_triaged['force'];
    }
    //triage casualties from bombardment for AA50 and AA1942, so use all other OFS hits besides subs
    if ($_REQUEST['ruleset'] == 'AA50' || $_REQUEST['ruleset'] == 'AA1942') {
        if (nonsubs($aforce) && nonsubs($dforce) && $killsfireback) {
            if (isset($avals['ofs'])) {
                $d_triaged = triage($dforce, $avals['ofs'], $dlost, 'def');
                $dforce = $d_triaged['force'];
                $dlost = $d_triaged['lost'];
            }
        }
    }
    //Now triagecasualties from air attack
    //determine air casualties for defender
    if ($air_a && isset($airavals['norm'])) {
        $aird_triaged = triage($dforce, $airavals['norm'], $dlost, 'def');
        //determine defender's casualties from air attack
        $dforce = $aird_triaged['force'];
        $dlost = $aird_triaged['lost'];
    }
    //determine air casualties for attacker
    if ($air_d && isset($airdvals['norm'])) {
        $aira_triaged = triage($aforce, $airdvals['norm'], $alost, 'att');
        //determine attacker's casualties from air attack
        $aforce = $aira_triaged['force'];
        $alost = $aira_triaged['lost'];
    }
    //Now, triage all other casualties
    if (isset($avals['norm'])) {
        $d_triaged = triage($dforce, $avals['norm'], $dlost, 'def');
        $dforce = $d_triaged['force'];
        $dlost = $d_triaged['lost'];
    }
    if (isset($dvals['norm'])) {
        $a_triaged = triage($aforce, $dvals['norm'], $alost, 'att');
        $aforce = $a_triaged['force'];
        $alost = $a_triaged['lost'];
    }
    //merge the attacker airvals and vals arrays into one so dice get displayed correctly.
    if ($air_a && isset($airavals['norm'])) {
        $avals["totalhits"] += $airavals["totalhits"];
        $avals["norm"]["hits"] += $airavals["norm"]["hits"];
        $avals["norm"]["punch"] += $airavals["norm"]["punch"];
        $avals["norm"]["dice"]["rolled"] += $airavals["norm"]["dice"]["rolled"];
        //ADD dice rolls at 1 3 4 5 (possible dice rolls for air units)
        //may not need dice rolls at 2 or 6 until air is listed to hit at 2 or 6.
        $index = array(1, 3, 4, 5);
        foreach ($index as $v) {
            if (array_key_exists($v, $airavals["norm"]["dice"]) && array_key_exists($v, $avals["norm"]["dice"])) {
                $avals["norm"]["dice"][$v] = array_merge($airavals["norm"]["dice"][$v], $avals["norm"]["dice"][$v]);
            } elseif (array_key_exists($v, $airavals["norm"]["dice"])) {
                $avals["norm"]["dice"][$v] = $airavals["norm"]["dice"][$v];
            }
        }
        ksort($avals["norm"]["dice"]);
    }
    //merge the defender airvals and vals arrays into one so dice get displayed correctly.
    if ($air_d && isset($airdvals['norm'])) {
        $dvals["totalhits"] += $airdvals["totalhits"];
        $dvals["norm"]["hits"] += $airdvals["norm"]["hits"];
        $dvals["norm"]["punch"] += $airdvals["norm"]["punch"];
        $dvals["norm"]["dice"]["rolled"] += $airdvals["norm"]["dice"]["rolled"];
        //ADD dice rolls at 1 3 4 5 (possible dice rolls for air units)
        //may not need dice rolls at 2 or 6 until air is listed to hit at 2 or 6.
        $index = array(1, 3, 4, 5);
        foreach ($index as $v) {
            if (array_key_exists($v, $airdvals["norm"]["dice"]) && array_key_exists($v, $dvals["norm"]["dice"])) {
                $dvals["norm"]["dice"][$v] = array_merge($airdvals["norm"]["dice"][$v], $dvals["norm"]["dice"][$v]);
            } elseif (array_key_exists($v, $airdvals["norm"]["dice"])) {
                $dvals["norm"]["dice"][$v] = $airdvals["norm"]["dice"][$v];
            }
        }
        ksort($dvals["norm"]["dice"]);
    }
    return array('att' => array('force' => $aforce, 'lost' => $alost, 'vals' => $avals), 'def' => array('force' => $dforce, 'lost' => $dlost, 'vals' => $dvals));
}
Example #3
0
function showaverages($results)
{
    global $forces, $options;
    //set colors and units in the next if-then for rulesets on PHP side...uses the CSS
    $className = '';
    if (isset($_REQUEST['ruleset'])) {
        if ($_REQUEST['ruleset'] == 'Classic') {
            $className = 'cla';
        }
        if ($_REQUEST['ruleset'] == 'Revised') {
            $className = 'rev';
        }
        if ($_REQUEST['ruleset'] == 'AA50') {
            $className = 'aa50';
        }
    }
    $output = '';
    $sides = array('att' => 'Attacker', 'def' => 'Defender');
    $statkeys = array('count', 'cost', 'punch');
    $output .= '<h2>Average outcome of ' . number_format($_REQUEST['reps']) . ' battles</h2><b>Attacker: </b>' . showforce($forces['att']) . '<b> v. Defender: </b>' . showforce($forces['def']) . ' ' . scenariolink('web');
    $output .= '<p>Average battle duration: <b>' . $results['duration'] . '</b> rounds of combat</p>';
    $breaks = array('att' => array(), 'def' => array());
    if (!has_sea($forces['def']) && can_bombard($forces['att'])) {
        //Amphibious assault
        unset($forces['att']['Des']);
        unset($forces['att']['Cru']);
        unset($forces['att']['Bat']);
        $output .= "<b>Note:</b> Bombarding units are included in the statistics, although not reported in count/cost/punch/units.<br />";
    }
    $benchmarks = calibrate($forces);
    $graphstyles = ' display: block; float: left; font-size: 60%; text-align: center; padding: 0; margin: 0; height:15px; border: 1px solid grey; ';
    $output .= '<table border=0><tr><th>&nbsp;</th>
	<th>avg. # units left<!--<div style="font-size: 60%">scale: ' . $benchmarks['count'] . '</div>--></th>
	<th>IPC value <!--<div style="font-size: 60%">scale: ' . $benchmarks['cost'] . '</div>--></th>
	<th>Punch <!--<div style="font-size: 60%">scale: ' . $benchmarks['punch'] . '</div>--></th>
	</tr>';
    $gross = array();
    #debugarray($results);
    $stats = array();
    foreach ($sides as $side => $name) {
        // show both sides
        arsort($results[$side]);
        $totals = array('count' => 0, 'cost' => 0, 'punch' => 0, 'wins' => 0);
        #debugarray ($results[$side]);
        $percentpoint = 0;
        foreach ($results[$side] as $index => $data) {
            $wins = round($data['total'] / $_REQUEST['reps'] * 100, 2);
            $lastpercent = $percentpoint;
            $percentpoint += $wins;
            $units = $data['stats']['count'];
            $lossdata = assess($data['lost'], substr(strtolower($name), 0, -2));
            #debug ("$wins, total $percentpoint, $index");
            #debug($percentpoint);
            //the 1st SD includes 68% of the results centered about the mean or median
            $stdev1 = $percentpoint >= 84 && $lastpercent < 84 || $percentpoint >= 16 && $lastpercent < 16;
            //the 2nd SD includes 94% of the results centered about the mean or median
            $stdev2 = $percentpoint >= 97 && $lastpercent < 97 || $percentpoint >= 3 && $lastpercent < 3;
            $median = $percentpoint >= 50 && $lastpercent < 50;
            if ($wins > 0) {
                $breaks[$side][$index] = probgraph($wins, showforce($data['force']), $units, showforce($data['lost']), $lossdata['cost'], $median, $stdev1, $stdev2);
            }
            foreach ($statkeys as $key) {
                $totals[$key] += $data['stats'][$key] * $wins;
            }
            $totals['wins'] += $wins;
        }
        #debugarray ($breaks[$side]);
        $astats = array();
        foreach ($statkeys as $key) {
            if ($totals['wins'] !== 0) {
                $astats[$key] = round($totals[$key] / 100, 1);
                #			if ($side=='att'){$astats['punch']=$astats['opunch'];}else{$astats['punch']=$astats['dpunch'];}
            } else {
                $astats[$key] = 0;
            }
        }
        $stats[$side] = $astats;
        //save for later
        $mode = strtolower(substr($sides[$side], 0, -2));
        //gets 'attack' or 'defend' from "Attacker" or "Defender"
        $astartstats = assess($forces[$side], $mode);
        #if ($side=='att'){$astartstats['punch']=$astartstats['opunch'];}else{$astartstats['punch']=$astartstats['dpunch'];}
        $aloststats = array();
        foreach ($statkeys as $key) {
            $aloststats[$key] = $astartstats[$key] - $astats[$key];
        }
        if ($totals['wins'] > 100) {
            $totals['wins'] = 100;
        }
        $gross[$side] = round($totals['wins'], 1);
        $survive = '<th class="' . $side . $className . '">' . $name . ':</th>';
        if ($totals['wins'] < 99) {
            $losses = 100 - $totals['wins'];
            $stdev2 = $losses >= 3;
            //2nd standard deviation contains about 95% of the results. thus, 50-(95/2) = 3% when rounded up
            $stdev1 = $losses >= 16;
            //1st standard deviation contains about 68% of the results. thus, 50-(68/2) = 16%
            $median = $losses >= 50;
            $width = width($losses, 50);
            $lossdata = assess($forces[$side], substr(strtolower($name), 0, -2));
            $breaks[$side][0] = probgraph($losses, 'no units.', 0, showforce($forces[$side]), $lossdata['cost'], $median, $stdev1, $stdev2);
            #'<!--0-->
            #<span style="background: grey; width: '.$width.'px; display: block; float: left; border: 1px solid black; margin: 3px 3px 0 0; font-size: 60%;">&nbsp;</span>
            #0 units: '.$losses.'%: left with <b>nothing</b>.';
        }
        foreach ($benchmarks as $stat => $bmark) {
            $afw = width($astats[$stat], $bmark);
            $alw = width($aloststats[$stat], $bmark);
            $alossw = width($astartstats[$stat], $bmark);
            $survive .= '<td class="graph">';
            if ($astats[$stat] > 0) {
                $survive .= '<span class="' . $side . $className . '"style="width:' . $afw . 'px; ' . $graphstyles . '">' . $astats[$stat] . '</span>';
            }
            #<span class="noshow">Left:</span> ';
            if ($aloststats[$stat] > 0) {
                $survive .= '<span class="lost" style="' . $graphstyles . ' border: none !important; padding: 1px 0px !important; width:' . ($alw - 1) . 'px;">' . $aloststats[$stat] . '</span>';
            }
            $survive .= '</td>';
        }
        #if ($totals['wins'] > 0)
        #		$ics=$astartstats['count']*$astartstats['punch'];
        #		$survive.= "<td>count: ".$astartstats['count']." punch: ".$astartstats['punch']. "ICS: $ics</td>";
        $output .= '<tr>' . $survive . '</tr>';
    }
    $output .= '
	<tr><td>&nbsp;</td><td><span class="att' . $className . '" style="display: block; float: left; border: 1px solid black; padding: 0 3px; margin: 3px 3px 0 0; font-size: 60%;">#</span> Surviving Attackers <br />
	 </td>
	<td valign="top"><span class="def' . $className . '" style="display: block; float: left; border: 1px solid black; padding: 0 3px; margin: 3px 3px 0 0; font-size: 60%;">#</span> Surviving Defenders</td><td><span class="lost" style="display: block; float: left; border: 1px solid  grey; padding: 0 3px; margin: 3px 3px 0 0; font-size: 60%; ">#</span>Casualties</td></tr>
	<tr><td colspan="4"><hr /></td></tr>
	<tr style="font-weight: bold;">
	<th>Overall %*:</th><td class="att' . $className . '" style="font-weight: bold; padding: 0px 4px;">A. survives: ' . $gross['att'] . '%</td>
	<td class="def' . $className . '" style="font-weight: bold; padding: 0px 4px;">D. survives: ' . $gross['def'] . '%</td>
	<td class="lost" style="font-weight: bold; padding: 0px 4px;">No one survives: ' . round($results['draw'] / $_REQUEST['reps'] * 100, 1) . '%</td></tr>
	</table>
	<em>* percentages may not total 100 due to rounding. The average results from above are<span style="background: yellow;"> highlighted </span>in charts below, while the median result (equal odds of getting a worse or better result) is written in <span style="color: red">red</span>. If shown, the 1st and 2nd standard deviations about the mean are represented in <span style="color: blue">blue</span> and <span style="color: dodgerblue">light blue</span>.</em>
	<table>';
    #debugarray ($results);
    foreach ($sides as $side => $name) {
        $output .= '<tr><th colspan="4">' . $name . ' results:<hr /></td></tr>
		<tr><th style="text-align: right;">Probability</th><th style="text-align: left;">%</th><th style="text-align: right;">#</th><th style="text-align: left">units</th><th>/ losses</th></tr>
		';
        #		<tr><td>';
        #		foreach ($breaks[$side] as $line) $output .= "<tr>$line</tr>";
        #$output .= '</ul></td><td><h3>By remaining count</h3><ul>';
        natcasesort($breaks[$side]);
        #debug ('Stats:');
        #debugarray ($stats[$side]);
        #debug ('Avg. Count for '.$side.': '.$stats[$side]['count']);
        $breaks[$side] = array_reverse($breaks[$side]);
        #debugarray ($r);
        #debug (count($breaks[$side]));
        foreach ($breaks[$side] as $index => $line) {
            $color = 'background: #eef;';
            $avgcount = round($stats[$side]['count']);
            $count = 0;
            if ($index !== 0) {
                $count = $results[$side][$index]['stats']['count'];
            }
            if ($count > $avgcount - 1.0 and $count < $avgcount + 1.0) {
                $color = 'background: yellow;';
            }
            if ($count !== 0 && $color == '') {
                $countratio = $avgcount / $count;
                if ($countratio >= 0.9 and $countratio <= 1.1) {
                    $color = 'background: yellow;';
                }
            }
            $output .= "<tr style=\"font-size: 60%; {$color}\">{$line}</tr>\n\t\t\t";
        }
        $output .= '<tr><td colspan=4><hr /></td></tr>';
    }
    $output .= '</table>';
    global $rounds;
    #if ($rounds == '')
    $output .= showipcdiffs($results['ipcdiff']);
    #debug ($rounds);
    $output .= scenariolink('mail');
    return $output;
}
Example #4
0
     $forces['def'] = $swap;
 }
 $savedool = $ool;
 $goahead = true;
 if (isset($options['gameidok'])) {
     $goahead = $options['gameidok'];
 }
 $results = array('att' => array(), 'def' => array(), 'draw' => 0);
 $saveunits = intval($_REQUEST['saveunits']);
 $strafeunits = intval($_REQUEST['strafeunits']);
 if (!$options['nounits'] && $options['legal'] or $_REQUEST['battle'] !== 'Run') {
     $history[0] = array('att' => array('force' => $forces['att'], 'lost' => array(), 'hits' => array(), 'dice' => array()), 'def' => array('force' => $forces['def'], 'lost' => array(), 'hits' => array(), 'dice' => array()));
     $duration = 0;
     $ipcdiff = array();
     $startforces = $forces;
     if (can_bombard($startforces['att']) && has_land($startforces['def'])) {
         if (isset($startforces['att']['Bat'])) {
             unset($startforces['att']['Bat']);
         }
         if (isset($startforces['att']['Cru'])) {
             unset($startforces['att']['Cru']);
         }
         if (isset($startforces['att']['Des'])) {
             unset($startforces['att']['Des']);
         }
     }
     $astartstats = assess($startforces['att'], 'attack');
     //call function to assess attacker stats
     $dstartstats = assess($startforces['def'], 'defend');
     //call function to assess defender stats
     while ($goahead) {