Risk Auto Roller — Source Code

Back to Auto Roller

<?php
	// the maximum number of dice that can be used by each side
	define("ATTACKER_MAX_DICE", 3);
	define("DEFENDER_MAX_DICE", 2);

 
	// number of troops allowed on each side in a battle. To protect server.
	define("TROOP_LIMIT", 200);
 
	// values of inputs to save for HTML page

	$attackerSave = "";
	$defenderSave = "";
	$attackerStopSave = "";

	$aboveCount = NULL;
	$belowCount = NULL;
 

	// set up attacker stop strategy
	$stopMethod = "none";
	$stopOptions = array("fixed" => false, "less" => false, "more" => false,

				 "equal" => false, "none" => false);
 

	// assume everything is OK
	$valid = true;
 
	// only show results if form has been submitted
	if ($_SERVER['REQUEST_METHOD'] == "POST")

	{
		// make sure our input is good
		if (isset($_POST['attackers'], $_POST['defenders']) && (int)$_POST['attackers'] > 1 && (int)$_POST['defenders'] > 0)

		{	
			$attackers = $attackerSave = (int)$_POST['attackers'];

			$defenders = $defenderSave = (int)$_POST['defenders'];

 
			// check our stopping strategy. If it's not set, default to
			// 'bitter end.'
			if (isset($_POST['stopMethod']) && array_key_exists($_POST['stopMethod'], $stopOptions))

			{
				$stopMethod = $_POST['stopMethod'];
 
				// get fixed number of troops for attacker to stop at. Make sure it's in legal range

				if ($stopMethod == "fixed" && isset($_POST['attackerStop']) && trim($_POST['attackerStop']) != "" && is_numeric($_POST['attackerStop']) && (int)$_POST['attackerStop'] < $attackers)

				{
					$attackerStop = (int)$_POST['attackerStop'];

					$attackerStopSave = $attackerStop;
				}
				// get variable number of troops above defender count
				else if ($stopMethod == "more" && isset($_POST['aboveCount']) && trim($_POST['aboveCount']) != "" && (int)$_POST['aboveCount'] >= 0 && $attackers - $defenders > (int)$_POST['aboveCount'])

				{
					$aboveCount = (int)$_POST['aboveCount'];

				}
				// get variable number of troops below defender count
				else if ($stopMethod == "less" && isset($_POST['belowCount']) && trim($_POST['belowCount']) != "" && (int)$_POST['belowCount'] >= 0 && $defenders - $attackers < (int)$_POST['belowCount'])

				{
					$belowCount = (int)$_POST['belowCount'];

				}
				// stop case for when the troop counts are equal. Sneakily, we
				// just pick the 'above' method, with an input of zero.
				else if ($stopMethod == "equal" && $attackers != $defenders)

				{
					$aboveCount = 0;
				}
				// now, if there was something wrong and all the conditions weren't right

				// for the given stop method, decide the correct error message
				else if ($stopMethod != "none")
				{

					$valid = false;
					switch ($stopMethod)
					{

						case "fixed":
							$error = "The number of troops the attacker stops at must be less than the number he attacks with.";
						break;

						case "more":
							$error = "Attacker already have fewer than " . $_POST['aboveCount'] . " troops more than the defender.";

						break;
						case "less":
							$error = "Attacker already have more than " . $_POST['belowCount'] . " troops less than the defender.";

						break;
						case "equal":
							$error = "The number of troops is already equal.";

						break;
					}
				} // end if input for stop strategy wasn't correct
 
				// if the stop strategy is none at all
				if ($valid && $stopMethod == "none")

				{
					$stopMethod = "none";
					$valid = true;

				}
 
			} // end if stop strategy is defined
 
			// set the attacker stopping value into a legal range
			$attackerStop = max(1, $attackerStop);

			$attackerStop = min($attackers - 1, $attackerStop);

 
			// set up array to track each roll and troop totals
			$rollTrack = array();			
 
			// set up total track array

			$totalTrack [] = array('attackers' => $attackers, 'defenders' => $defenders);

 
 
			// check for huge inputs
			if ($attackers > TROOP_LIMIT || $defenders > TROOP_LIMIT)

			{
				$error = "Sorry, I only allow up to " . TROOP_LIMIT . " troops on this page to reduce server load. Although a battle of 1,000,000 soldiers would be cool, it would hit the server pretty hard.";

				$valid = false;
			}
 
			$roll = 0;

 
			// now, loop until we hit a stop condition
			while ($valid && $attackers > $attackerStop && $defenders > 0)

			{
				$roll++;
 
				// dynamically update above or below defender counts, for the
				// attacker stop condition
				if (!is_null($aboveCount))

				{
					$attackerStop = $defenders + $aboveCount;
					if ($attackers < $attackerStop)

					{
						break;
					}
				}
				else if (!is_null($belowCount))

				{
					$attackerStop = $defenders - $belowCount;
					if ($attackers < $attackerStop)

					{
						break;
					}
				}
 
				// figure out how many dice each combatant gets this round		

				$dice['attackers'] = min(ATTACKER_MAX_DICE, $attackers - 1, $attackers - $attackerStop);

				$dice['defenders'] = min(DEFENDER_MAX_DICE, $defenders);

 
				// if attacker has zero dice, then the battle is over
				if ($dice['attackers'] < 1)

					break;
 
				// array for each combatant's rolls
				$rolls = array();

 
				// shake those dice
				for ($i = 0; $i < $dice['attackers']; $i++)

					$rolls['attackers'][] = rand(1, 6);

				for ($i = 0; $i < $dice['defenders']; $i++)

					$rolls['defenders'][] = rand(1, 6);

 
				// sort in reverse, for comparing
				rsort($rolls['attackers']);
				rsort($rolls['defenders']);

 
				// we only compare the same number of dice. Since the arrays of roll are
				// sorted, this is OK.
				for ($i = 0; $i < min($dice['attackers'], $dice['defenders']); $i++)

				{
					if ($rolls['attackers'][$i] <= $rolls['defenders'][$i])

						$attackers--;
					else
						$defenders--;
				}
 
				// save tracking data

				$totalTrack [] = array('attackers' => $attackers, 'defenders' => $defenders);

				$rollTrack [] = $rolls;
 
			} // end main battle loop

 
			// figure out WHY we stopped
			if (!isset($stopBecause))
			{

				if ($defenders <= 0)
					$stopBecause = "Defender was annihilated.";

				else if ($stopMethod == "more")
					$stopBecause = "Attacker troop count reached limit above defender count.";

				else if ($stopMethod == "less")
					$stopBecause = "Attacker troop count reached limit below defender count.";

				else if ($stopMethod == "equal" && $attackers == $defenders)

					$stopBecause = "Attacker count equals defender count.";
				else if ($stopMethod == "fixed" && $attackerStop != 1)

					$stopBecause = "Attacker count reached fixed limit.";
				else
					$stopBecause = "Attacker cannot continue battle because only one troop remains.";

			} // end block of code to figure out reason for stopping
 
		}
		else // Troop counts were bad or too low
		{

			$error = "Bad numbers assigned to attacking and defending troops. Attackers must have at least two troops, and defenders must have at least one.";
			$valid = false;
		}

 
	} // end if form was submitted
 
?>
 
<h2>Risk Auto Roller</h2>
<?php if ($valid && isset($totalTrack, $rollTrack)): ?>

 
	<h3>Results</h3>
	<p>
		<strong>Attackers: </strong><?php echo $attackers ?><br />

		<strong>Defenders: </strong><?php echo $defenders ?>
	</p>

 
	<h3>Rolls</h3>
	<table class="rolls">
		<tr>
			<th style="width: 8%;">Roll</th>

			<th style="width: 8%;">Attackers</th>
			<th style="width: 8%;">Defenders</th>
			<th style="width: 38%;">Attacker Rolls</th>

			<th style="width: 38%;">Defender Rolls</th>
		</tr>
		<?php for ($i = 0; $i < count($totalTrack); $i++): ?>

		<tr<?php if ($i >= count($rollTrack)): ?> style="height: 36px;"<?php endif; ?>>

			<td><?php echo ($i < count($rollTrack) ? $i + 1 : '-') ?></td>

			<td>
				<?php echo $totalTrack[$i]['attackers'] ?>

				<?php if ($i > 0 && $totalTrack[$i-1]['attackers'] > $totalTrack[$i]['attackers']): ?><span class="change">(-<?= $totalTrack[$i-1]['attackers'] - $totalTrack[$i]['attackers'] ?>)</span><?php endif; ?>

			</td>
			<td>
				<?php echo $totalTrack[$i]['defenders'] ?>

				<?php if ($i > 0 && $totalTrack[$i-1]['defenders'] > $totalTrack[$i]['defenders']): ?><span class="change">(-<?= $totalTrack[$i-1]['defenders'] - $totalTrack[$i]['defenders'] ?>)</span><?php endif; ?>

			</td>
			<?php if ($i < count($rollTrack)): ?>

			<td>
				<?php for ($j = 0; $i < count($rollTrack) && $j < count($rollTrack[$i]['attackers']); $j++): ?><img src="img/attacker-dice-<?php echo $rollTrack[$i]['attackers'][$j] ?>.png" alt="<?php echo $rollTrack[$i]['attackers'][$j] ?><?php echo ($j + 1 < count($rollTrack[$j]['attackers']) ? ', ' : '') ?>" />

				<?php endfor; ?>
			</td>
			<td>
				<?php for ($j = 0;  $i < count($rollTrack) && $j < count($rollTrack[$i]['defenders']); $j++): ?><img src="img/defender-dice-<?php echo $rollTrack[$i]['defenders'][$j] ?>.png" alt="<?php echo $rollTrack[$i]['defenders'][$j] ?><?php echo ($j + 1 < count($rollTrack[$j]['defenders']) ? ', ' : '') ?>" />

				<?php endfor; ?>
			</td>
			<?php else: ?>

			<td colspan="2" class="reason">
				<strong>Battle ended: </strong><?php echo $stopBecause ?>
			</td>

			<?php endif; ?>
		</tr>
		<?php endfor; ?>

	</table>
	<h3>Roll Again</h3>
<?php elseif (!$valid): ?>

	<h3>Invalid Input</h3>
	<?php if (isset($error)): ?>

		<p><?php echo $error ?></p>
	<?php endif; ?>

	<p>Please double-check your input.</p>
	<h3>Roll Again</h3>
<?php else: ?>

	<h3>Roll</h3>
<?php endif; ?>
 
<form action="riskRoller.php" method="post" class="roll">
	<fieldset>

		<legend>Troops</legend>
		<div class="item">
			<label for="attackers">Attackers:</label>
			<input name="attackers" id="attackers" value="<?php echo $attackerSave ?>" class="short" />

		</div>
		<div class="item">
			<label for="defenders">Defenders:</label>
			<input name="defenders" id="defenders" value="<?php echo $defenderSave ?>" class="short" />

		</div>
	</fieldset>
	<fieldset>
		<legend>Attacker Stops</legend>
		<div class="option">

			<input type="radio" class="radio" name="stopMethod" value="none" id="stopNone" <?php if ($stopMethod == "none"): ?>checked="checked"<?php endif; ?>/>

			<label for="stopNone"><strong>Bitter End: </strong>Stop when I cannot continue attacking</label>
		</div>
		<div class="option">
			<label for="attackerStop">

				<input type="radio" class="radio" name="stopMethod" value="fixed" id="stopFixed" <?php if ($stopMethod == "fixed"): ?>checked="checked"<?php endif; ?> />

			</label>
			<label for="stopFixed">
			<strong>Fixed Number: </strong>Stop when I have </label>
			<input name="attackerStop" id="attackerStop" value="<?php echo $attackerStopSave ?>" class="short" /> 
			<label for="stopFixed">units left</label>

		</div>
		<div class="option">
			<label for="aboveCount">
				<input type="radio" class="radio" name="stopMethod" value="more" id="stopMore" <?php if ($stopMethod == "more"): ?>checked="checked"<?php endif; ?> />

			</label>
			<label for="stopMore"><strong>More Than Defender: </strong>Stop if I have exactly </label>
			<input name="aboveCount" id="aboveCount" <?php if (!is_null($aboveCount)): ?>value="<?php echo $aboveCount ?>"<?php endif; ?> class="short" /> 
			<label for="stopMore">more units than the defender</label>

		</div>
		<div class="option">
			<input type="radio" class="radio" name="stopMethod" value="equal" id="stopEqual" <?php if ($stopMethod == "equal"): ?>checked="checked"<?php endif; ?> />

			<label for="stopEqual"><strong>Equal to Defender: </strong>
			Stop when I have the same number of units as the defender</label>
		</div>
		<div class="option">
			<label for="belowCount">

				<input type="radio" class="radio" name="stopMethod" value="less" id="stopLess" <?php if ($stopMethod == "less"): ?>checked="checked"<?php endif; ?> />

			</label>
			<label for="stopLess">
			<strong>Less Than Defender: </strong>Stop if I have exactly</label>
			<input name="belowCount" id="belowCount" <?php if (!is_null($belowCount)): ?>value="<?php echo $belowCount ?>"<?php endif; ?> class="short" />

			<label for="stopLess">fewer units than the defender</label>
		</div>
	</fieldset>
	<fieldset class="buttons">
		<button type="submit">Run Battle</button>

	</fieldset>
</form>