Eugene Wee is the author of this PHP round robin algorithm to create schedules for tournaments for almost everything.
I have slightly changed it to associate every player with a “tag” (parameters : first_team, second_team).
These tags could be, for example, the color of chess pieces (white / black) or the place where every team plays (home / away).
If the number of teams is odd, a fictional team is added (the last) to assure that every player plays the same amount of games.
/****************************************************************************** * Round Robin Pairing Generator * Author: Eugene Wee * Date: 23 May 2005 * Last updated: 13 May 2007 * Based on an algorithm by Tibor Simko. * * Copyright (c) 2005, 2007 Eugene Wee * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. ******************************************************************************/ function generateRoundRobinPairings($num_teams, $first_team='first', $second_team='second') { // Do we have a positive number of players? If not, default to 4. $num_teams = ($num_teams > 0) ? (int)$num_teams : 4; // If necessary, round up number of players to nearest even number. $num_teams += $num_teams % 2; // Format for pretty alignment of pairings across rounds. $format = "%0" . ceil(log10($num_teams)) . "d"; $pairing = "$format-$format "; $games = array(); // Generate the pairings for each round. for ($round = 1; $round < $num_teams; $round++) { $players_done = array(); // Pair each player except the last. for ($player = 1; $player < $num_teams; $player++) { if (!in_array($player, $players_done)) { // Select opponent. $opponent = $round - $player; $opponent += ($opponent < 0) ? $num_teams : 1; // Ensure opponent is not the current player. if ($opponent != $player) { // Choose colours. if (($player + $opponent) % 2 == 0 xor $player < $opponent) { // Player plays white. $games[$round][$player][$first_team] = $player; $games[$round][$player][$second_team] = $opponent; } else { // Player plays black. $games[$round][$player][$first_team] = $opponent; $games[$round][$player][$second_team] = $player; } // This pair of players are done for this round. $players_done[] = $player; $players_done[] = $opponent; } } } // Pair the last player. if ($round % 2 == 0) { $opponent = ($round + $num_teams) / 2; // Last player plays white. $games[$round][$player][$first_team] = $num_teams; $games[$round][$player][$second_team] = $opponent; } else { $opponent = ($round + 1) / 2; // Last player plays black. $games[$round][$player][$first_team] = $opponent; $games[$round][$player][$second_team] = $num_teams; } } return $games; }

