function downsizegame($downsizetype) { global $GAME; $GAME['MoveMade'] = 1; $GAME['KickVote'] = '00000'; $GAME['SecondRailMode'] = 0; $GAME['SecondDevelopMode'] = 0; $GAME['ContinueSellingMode'] = 0; if ($GAME['GameStatus'] == 'In Progress') { if (KickPlayer($GAME['PlayerToMove'], 3)) { return; } // If KickPlayer aborts the game then it will return true. // We don't want any shenanigans going on after a game is aborted. } $GAME['PlayersMissing']--; $GAME['PlayerMissing'][$GAME['PlayerToMove']] = 0; $GAME['PlayersMissingThatMatter']--; $GAME['PlayerMissingAndMatters'][$GAME['PlayerToMove']] = 0; dbquery(DBQUERY_WRITE, 'DELETE FROM "ReplacementOffer" WHERE "Game" = :game: AND "Colour" = :colour:', 'game', $GAME['GameID'], 'colour', $GAME['PlayerToMove']); $GAME['GameStatus'] = 'In Progress'; if ($downsizetype) { $GAME['AltGameTicker'] .= '7A' . callmovetimediff(); } else { $GAME['AltGameTicker'] .= '7B' . callmovetimediff(); } $GAME['PlayerExists'][$GAME['PlayerToMove']] = 0; for ($i = 0; $i < $GAME['NumIndustrySpaces']; $i++) { if ($GAME['SpaceStatus'][$i] == $GAME['PlayerToMove']) { $GAME['SpaceStatus'][$i] = 8; } } for ($i = 0; $i < $GAME['RailPhase'] * $GAME['NumRailLinks'] + (1 - $GAME['RailPhase']) * $GAME['NumCanalLinks']; $i++) { if ($GAME['LinkStatus'][$i] == $GAME['PlayerToMove']) { $GAME['LinkStatus'][$i] = 8; } } switch ($GAME['CurrentPlayers']) { case 4: if ($GAME['Round'] < 3) { $GAME['NumRounds'] = 10; } else { if ($GAME['Round'] == 3) { $GAME['NumRounds'] = 9; } } if (!$GAME['RailPhase'] or $GAME['Round'] < 4) { $GAME['EffectiveNumPlayers'] = 3; } $GAME['ShuffledDeck'] = array_reverse($GAME['ShuffledDeck']); if (count($GAME['ShuffledDeck']) == 1 and $GAME['ShuffledDeck'][0] === '') { $GAME['ShuffledDeck'] = array(); } shuffle($GAME['Cards'][$GAME['PlayerToMove']]); for ($i = 0; $i < $GAME['HandSize'][$GAME['PlayerToMove']]; $i++) { $GAME['ShuffledDeck'][] = array_pop($GAME['Cards'][$GAME['PlayerToMove']]); } $GAME['ShuffledDeck'] = array_reverse($GAME['ShuffledDeck']); $GAME['AltGameTicker'] .= 'AAA9J'; break; case 3: // At present, it is not permitted for games to be downsized from 3 players to 2 players. // This function should not be called when CurrentPlayers is equal to 3; it will stop script execution with an error message. die('Programming error: Downsize function called when number of players is 3. Please contact Administrator and give details of how you obtained this error message.'); break; case 2: for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$i]) { $TheLastPlayer = $i; } } if ($GAME['RailPhase'] and $GAME['NumRounds'] - $GAME['Round'] < 2) { require_once HIDDEN_FILES_PATH . 'scoringresource.php'; endgamescoring(); } else { $GAME['GameStatus'] = 'Finished'; require_once HIDDEN_FILES_PATH . 'createpgr.php'; CreatePGR(0, 0, -1, 0, $TheLastPlayer); } $GAME['AltGameTicker'] .= 'AAA9J'; break; } $GAME['CurrentPlayers']--; if ($GAME['CurrentPlayers'] > 1) { for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['TurnOrder'][$i] == $GAME['PlayerToMove']) { $WhereInTurnOrder = $i; } } for ($i = $WhereInTurnOrder; $i < MAX_PLAYERS - 1; $i++) { $GAME['TurnOrder'][$i] = $GAME['TurnOrder'][$i + 1]; } $GAME['TurnOrder'][MAX_PLAYERS - 1] = $GAME['PlayerToMove']; if ($GAME['DebtMode']) { $SomeoneInDebt = 9; for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$GAME['TurnOrder'][$i]] and $GAME['Money'][$GAME['TurnOrder'][$i]] < 0) { for ($j = 0; $j < $GAME['NumIndustrySpaces']; $j++) { if ($GAME['SpaceStatus'][$j] == $GAME['TurnOrder'][$i]) { $SomeoneInDebt = $GAME['TurnOrder'][$i]; break 2; } } } } if ($SomeoneInDebt == 9) { $GAME['DebtMode'] = 0; $GAME['PlayerToMove'] = $GAME['TurnOrder'][0]; } else { $GAME['PlayerToMove'] = $SomeoneInDebt; } } else { $EndRound = true; for ($i = MAX_PLAYERS - 2; $i >= $WhereInTurnOrder; $i--) { if ($GAME['PlayerExists'][$GAME['TurnOrder'][$i]]) { $GAME['PlayerToMove'] = $GAME['TurnOrder'][$i]; $EndRound = false; } } if ($EndRound) { if ($GAME['Round'] == $GAME['NumRounds']) { if ($GAME['RailPhase']) { require_once HIDDEN_FILES_PATH . 'scoringresource.php'; endgamescoring(); } else { require_once HIDDEN_FILES_PATH . 'scoringresource.php'; require_once HIDDEN_FILES_PATH . 'turnorderresource.php'; canalphasescoring(); DoTurnOrder(1); } } else { require_once HIDDEN_FILES_PATH . 'turnorderresource.php'; DoTurnOrder(1); } } } if ($GAME['RailPhase'] and $GAME['Round'] == $GAME['NumRounds'] and $GAME['GameStatus'] != 'Finished') { require_once HIDDEN_FILES_PATH . 'nomovesresource.php'; CheckNoMovesShell(); } } }
function endgamescoring() { global $GAME; if (isset($GAME['EndScoringDone'])) { return; } $GAME['EndScoringDone'] = true; // This is a precaution - I aim to avoid calling this function // more than once, but if I slip up I want to cover myself. if ($GAME['CurrentPlayers'] < $GAME['OriginalPlayers']) { flip_UOCMs(); } // flip_UOCMs: see above $TheOutput = '<p>Rail Phase scoring occurred at ' . date('Y-m-d H:i:s') . '. The players\' scores beforehand are as follows:</p><ul>'; for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$i]) { $TheOutput .= '<li>' . $GAME['PlayerFullName_Eng'][$i] . ': ' . $GAME['VictoryPoints'][$i] . '</li>'; } } $TheOutput .= '</ul><p>First of all, rail links are scored.</p><ul>'; $RailPoints = array(0, 0, 0, 0, 0); $TilePoints = array(0, 0, 0, 0, 0); // Initialise the number of points to be given at 0. $NumFlippedTiles = $GAME['LocationAutoValue']; // Blackpool, Scotland, Yorkshire et al. all have automatic value 2. for ($i = 0; $i < $GAME['NumIndustrySpaces']; $i++) { if ($GAME['SpaceStatus'][$i] != 9 and !$GAME['SpaceCubes'][$i]) { $NumFlippedTiles[$GAME['spacetowns'][$i]]++; // For each flipped industry tile, increment the value of the location of the tile. } } for ($i = 0; $i < $GAME['NumRailLinks']; $i++) { if ($GAME['LinkStatus'][$i] < 8 and $GAME['PlayerExists'][$GAME['LinkStatus'][$i]]) { // I'm not sure why the PlayerExists condition is here. I think it might be a // hangover from earlier bad design decisions, and no longer necessary. $pointstoadd = $NumFlippedTiles[$GAME['RailStarts'][$i]] + $NumFlippedTiles[$GAME['RailEnds'][$i]]; if ($pointstoadd == 1) { $pluraltext = ''; } else { $pluraltext = 's'; } $RailPoints[$GAME['LinkStatus'][$i]] += $pointstoadd; // For each owned rail link, award points equal to the sum // of the values of the start and end locations. $TheOutput .= '<li>' . $GAME['PlayerFullName_Eng'][$GAME['LinkStatus'][$i]] . ' receives ' . $pointstoadd . ' point' . $pluraltext . ' for ' . $GAME['PossessivePronounLC_Eng'][$GAME['LinkStatus'][$i]] . ' rail link between ' . $GAME['locationnames'][$GAME['RailStarts'][$i]] . ' and ' . $GAME['locationnames'][$GAME['RailEnds'][$i]] . '.</li>'; } } $TheOutput .= '</ul><p>The number of points scored from rail links is as follows:</p><ul>'; for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$i]) { $TheOutput .= '<li>' . $GAME['PlayerFullName_Eng'][$i] . ': ' . $RailPoints[$i] . '</li>'; } } $TheOutput .= '</ul><p>Secondly, industry tiles are scored.</p><ul>'; for ($i = 0; $i < $GAME['NumIndustrySpaces']; $i++) { if ($GAME['SpaceStatus'][$i] < 8 and !$GAME['SpaceCubes'][$i] and $GAME['PlayerExists'][$GAME['SpaceStatus'][$i]]) { // I'm not sure why the PlayerExists condition is here. I think it might be a // hangover from earlier bad design decisions, and no longer necessary. $pointstoadd = $GAME['TileVPValue'][$GAME['SpaceTile'][$i]][$GAME['TechLevels'][$i] - 1]; if ($pointstoadd == 1) { $pluraltext = ''; } else { $pluraltext = 's'; } $TilePoints[$GAME['SpaceStatus'][$i]] += $pointstoadd; // For each flipped non-orphan industry tile, award points to the owner. $TheOutput .= '<li>' . $GAME['PlayerFullName_Eng'][$GAME['SpaceStatus'][$i]] . ' receives ' . $pointstoadd . ' point' . $pluraltext . ' for ' . TileDescription($i, $GAME['SpaceStatus'][$i], 0, 1, 0, 1) . '.</li>'; } } $TheOutput .= '</ul><p>The number of points scored from industry tiles is as follows:</p><ul>'; for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$i]) { $TheOutput .= '<li>' . $GAME['PlayerFullName_Eng'][$i] . ': ' . $TilePoints[$i] . '</li>'; } } $TheOutput .= '</ul><p>Finally, the players receive the following numbers of points for their remaining funds:</p><ul>'; for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$i]) { if ($GAME['Money'][$i] >= 0) { $MoneyRemainder = $GAME['Money'][$i] % 10; $MoneyPoints[$i] = ($GAME['Money'][$i] - $MoneyRemainder) / 10; $MoneyString[$i] = '£' . $GAME['Money'][$i]; } else { $MoneyPoints[$i] = 0; $NegMoney = -$GAME['Money'][$i]; $MoneyString[$i] = '-£' . $NegMoney; } if ($MoneyPoints[$i] == 1) { $pluraltext = ''; } else { $pluraltext = 's'; } $TheOutput .= '<li>' . $GAME['PlayerFullName_Eng'][$i] . ': ' . $MoneyPoints[$i] . ' point' . $pluraltext . ', for having ' . $MoneyString[$i] . ' remaining</li>'; } } $TheOutput .= '</ul>'; for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$i]) { $GAME['VictoryPoints'][$i] += $RailPoints[$i] + $TilePoints[$i] + $MoneyPoints[$i]; // Give the players their points now that we have tallied them up. } } $MustKnowMoney = false; $MustDoTurnOrder = false; // If the second and third tie breakers aren't necessary, // we don't bother mentioning them. for ($i = 0; $i < MAX_PLAYERS - 1; $i++) { for ($j = $i + 1; $j < MAX_PLAYERS; $j++) { if ($GAME['PlayerExists'][$i] and $GAME['PlayerExists'][$j] and $GAME['VictoryPoints'][$i] == $GAME['VictoryPoints'][$j] and $GAME['IncomeSpace'][$i] == $GAME['IncomeSpace'][$j]) { $MustKnowMoney = true; if ($GAME['Money'][$i] == $GAME['Money'][$j]) { $MustDoTurnOrder = true; } } } } if ($MustDoTurnOrder) { require_once HIDDEN_FILES_PATH . 'turnorderresource.php'; DoTurnOrder(0); // Recalculate the turn order, but don't give out income or collect interest $TO_NameArray = array(); for ($i = 0; $i < $GAME['CurrentPlayers']; $i++) { if ($GAME['PlayerExists'][$GAME['TurnOrder'][$i]]) { $TO_NameArray[] = $GAME['PlayerFullName_Eng'][$GAME['TurnOrder'][$i]]; } } $TheOutput .= '<p>In order to determine player positions, it is necessary to calculate the turn order for the theoretical next turn. This turn order is: ' . implode(', ', $TO_NameArray) . '.</p>'; } $points = $GAME['VictoryPoints']; $space = $GAME['IncomeSpace']; $cash = $GAME['Money']; // Copies of the variables that affect positioning, for sorting purposes. $FlippedTurnOrder = array_flip(str_split($GAME['TurnOrder'], 1)); // Get an array telling us where each player is in the turn order. for ($i = 0; $i < MAX_PLAYERS; $i++) { $ReindexedFlippedTurnOrder[$i] = $FlippedTurnOrder[$i]; // Without this step, $FlippedTurnOrder has the correct key-value pairs, but they may // appear in the wrong order. This results in the call to array_multisort going wrong. } $whoarray = array(0, 1, 2, 3, 4); // This array will tell us which player is which after sorting. $CopyPlayerExists = str_split($GAME['PlayerExists'], 1); for ($i = 0; $i < MAX_PLAYERS; $i++) { $CopyPlayerExists[$i] = (int) $CopyPlayerExists[$i]; // Necessary? Might be able to get rid of this without changing behaviour. } array_multisort($CopyPlayerExists, SORT_DESC, $points, SORT_DESC, $space, SORT_DESC, $cash, SORT_DESC, $ReindexedFlippedTurnOrder, SORT_ASC, $whoarray); $positionlabels = array('1st', '2nd', '3rd', '4th', '5th'); $TheOutput .= '<p>Here are the results of the game:</p><ul>'; for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$whoarray[$i]]) { if ($points[$i] == 1) { $pluraltext = ''; } else { $pluraltext = 's'; } $TheOutput .= '<li>' . $positionlabels[$i] . ': ' . $GAME['PlayerFullName_Eng'][$whoarray[$i]] . ': ' . $points[$i] . ' VP' . $pluraltext . '; Income Space ' . $space[$i]; if ($MustKnowMoney) { $TheOutput .= '; ' . $MoneyString[$whoarray[$i]] . ' remaining'; } if ($MustDoTurnOrder) { $TheOutput .= '; ' . $positionlabels[$ReferenceTurnOrder[$i]] . ' for turn order'; } $TheOutput .= '</li>'; $Score = 100 * $points[$i] + $space[$i]; if (!$GAME['PlayerMissing'][$whoarray[$i]]) { require_once HIDDEN_FILES_PATH . 'createpgr.php'; CreatePGR(0, 0, $Score, $i, $whoarray[$i]); // Change this player's record for this game in the database // to include the result and score } } } dbquery(DBQUERY_WRITE, 'CALL "CalculateRanks_Rating"()'); dbquery(DBQUERY_WRITE, 'CALL "CalculateRanks_GamesCompleted"()'); // Get the database to recalculate rankings. if ($GAME['CurrentPlayers'] != 1) { // Congratulating the only player left in the game would look kind of silly. $TheOutput .= '</ul><p>Congratulations to ' . $GAME['PlayerName_Eng'][$whoarray[0]] . '!</p>'; } $GAME['GameStatus'] = 'Finished'; for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$i] and !$GAME['PlayerMissing'][$i] and $GAME['EmailAtEnd'][$i] and $GAME['Email'][$i] != '') { // Email all the game's players with a summary of scoring. $subject = 'Game number ' . $GAME['GameID'] . ' has finished'; $body = '<p>This is an automated message. Game number ' . $GAME['GameID'] . ' has finished. Here is the URL of the game page:</p><p><a href="' . SITE_ADDRESS . 'board.php?GameID=' . $GAME['GameID'] . '">' . SITE_ADDRESS . 'board.php?GameID=' . $GAME['GameID'] . '</a></p><p>Here is a summary of the end-game scoring:</p>' . $TheOutput . EMAIL_FOOTER; send_email($subject, $body, $GAME['Email'][$i], null); } } $WatchersQuery = 'SELECT "User"."Email", "User"."EmailAtEnd" FROM "WatchedGame" LEFT JOIN "User" ON "WatchedGame"."User" = "User"."UserID" WHERE "WatchedGame"."Game" = ' . $GAME['GameID']; // Find out who is watching the game, so that they can be sent emails as well. for ($i = 0; $i < MAX_PLAYERS; $i++) { if ($GAME['PlayerExists'][$i] and !$GAME['PlayerMissing'][$i]) { $WatchersQuery .= ' AND "WatchedGame"."User" <> ' . $GAME['PlayerUserID'][$i]; // If any of the game's players are watching the game, // there's no point in sending them two emails. } } $QueryResult = dbquery(DBQUERY_READ_RESULTSET, $WatchersQuery); while ($row = db_fetch_assoc($QueryResult)) { if ($row['EmailAtEnd'] and $row['Email'] != '') { $subject = 'Game number ' . $GAME['GameID'] . ' has finished'; $body = '<p>This is an automated message. Game number ' . $GAME['GameID'] . ' has finished. You are receiving this message because you are watching that game. Here is the URL of the game page:</p><p><a href="' . SITE_ADDRESS . 'board.php?GameID=' . $GAME['GameID'] . '">' . SITE_ADDRESS . 'board.php?GameID=' . $GAME['GameID'] . '</a></p><p>Here is a summary of the end-game scoring:</p>' . $TheOutput . EMAIL_FOOTER; send_email($subject, $body, $row['Email'], null); } } }
function abortgame($byAdmin) { global $GAME; if ($GAME['GameStatus'] != 'Aborted') { // I don't think there is currently any code that will call this // function if the game is already aborted, but may as well be safe $GAME['GameStatus'] = 'Aborted'; if ($byAdmin == 2) { // by the system $GAME['AltGameTicker'] .= '6A' . callmovetimediff(); } else { if ($byAdmin) { // by an admin $GAME['AltGameTicker'] .= '6B' . callmovetimediff() . letter_end_number($_SESSION['MyUserID']) . letter_end_number($_SESSION['MyGenderCode']); $GAME['GameTickerNames'] .= '|' . $_SESSION['MyUserName']; } else { // by vote $GAME['AltGameTicker'] .= '6C' . callmovetimediff(); } } require_once HIDDEN_FILES_PATH . 'createpgr.php'; for ($i = 0; $i < 5; $i++) { if ($GAME['PlayerExists'][$i] and !$GAME['PlayerMissing'][$i]) { CreatePGR(1, 0, 0, 0, $i); } } } }