Section 2: Civilization 4 Multiplayer Concepts:
This section will go a bit more in depth with multiplayer concepts that are specific to Civ4. It will explain the differences between the various multiplayer types, and give an overview over what happens every game turn and in what order. Unforunately, I haven’t had much experience with Pitboss, so I won’t touch on that. If you’re just looking for OOS advice, you can probably skip over this chapter, but it might hold some good tidbits, especially those trying to figure out the simultaneous play. Mainly, I talk about how the turn-based system works in relation to simultaneous mode (onBeginPlayerTurn and onEndPlayerTurn both happen at the end of the turn in all game types but simultaneous, they happen at the beginning). I also show why testing a mod in the PBEM and Hosteat multiplayer game types does not test for OOS problems.
First off, in order to understand what happens in a multiplayer game, we’ll need a base to compare it against, so I’ll take a look at a typical singleplayer turn.
A turn begins with player 0 (or, if player 0 is not alive, the first alive player in the list of players). The first thing that is done on a player’s turn is setting them to “active” (see section four for more about what it means to be “active”

. Note that when this player’s turn becomes active (hence “starting” their turn), the onBeginPlayerTurn is NOT called. Actually, onBeginPlayerTurn is called at the end of a player’s turn. I’ll get back to this in a minute.
Rather, the first thing done is that the doTurn() for each of the player’s selection group is called. This will, in effect, call doTurn() on all units for that player, since every unit belongs to a selection group (even if that selection group contains only that one unit). A quick look through doTurn() shows us that it does basic things for each unit, such as resetting their movement points, doing any healing, and taking the unit out of automation if it’s in danger. This, however, does not do any automation (such as a worker doing it’s work, or a unit moving to the next plot in it’s queue). Any warnings (“An enemy spearman has been spotted outside your army of tanks!”

are then displayed to the screen and finally, the little bit that tells the computer to start cycling through your various selection groups is set to true, thus setting in motion the actual turn.
“So now it calls ‘onBeginPlayerTurn’, right?” Hold on, not yet.
Now the player’s turn actually has started, and all their construction popups and advisor ramblings and manual unit movements are done one at a time by the player. Finally, the player has no more moves left.
“So, ‘onBeginPlayerTurn should have been called by now, right?’ Nope.
Once the player has no more units to give orders to, any units that need to have automoves done will do so. These units may also perform their automoves directly after a player forces the turn to end, or when the player runs out of time on their turn.
The player, finished with their turn, hits enter or time runs out or whatever. In the SDK, the correct functions are called to make all of the automoves start. Sometime after this, the player’s CvPlayer::doTurn() function is called. This function starts with onBeginPlayerTurn being called (finally), and ends with onEndPlayerTurn being called. In between, it does things such as looping through all the player’s cities and calling the city’s doTurn function; updates gold, revolution and anarchy turns, etc.
So, it’s interesting to note that the onBeginPlayerTurn actually happens at the end of the entire turn. It’s called “begin” because it happens at the beginning of the CvPlayer::doTurn SDK function for the player.
When the player’s turn is finished, they tell the next player in line that it’s their turn to start. Then, when that player’s done, the next player starts. The entire time, there is always at least one player who’s currently the “active” player.
Throughout the entirety of the game, the CvGame::update function is repeatedly called. This happens multiple times per second. One thing it checks for is how many player’s have their turn considered “active”.
Code:
if (getNumGameTurnActive() == 0)
{
if (!isPbem() || !getPbemTurnSent())
{
doTurn();
}
}
The getNumGameTurnsActive() returns the number of players whose turn is “active”. In all game types (with the exception of Simultaneous, see “Simultaneous Games” below), this will always be zero or one, because as soon as one person no longer has their turn active (bringing the total to zero), they simply tell the next player that their turn is active (bringing the total back to one). The last player, the Barbarian, will simply make itself inactive. During the CvGame::update function, when the number hits zero, it’s assumed that the last player has finished their turn, and thus all player’s have done their turn for this game turn. Thus, the game’s doTurn SDK function. Like the player’s doTurn SDK, this starts with the onBeginGameTurn and ends with the onEndGameTurn. So, realize that the onBeginGameTurn python event doesn’t happen before player 0’s turn, but rather at the end, after the last player’s turn, as the first thing done in the CvGame::doTurn() SDK function.
Thus, the game does what it needs to do (spawn barbarians, update global warming, etc.), then increments to the next turn, and tells the first player to start their next turn.
Okay, so that was just Singleplayer. Now we get to see what makes the other game types different. First off, the most important thing about multiplayer games: the human player is not always player 0 anymore. So, if you have been getting used to using player 0 as the human player all the time, stop it. This works for singleplayer, but not for multiplayer.
Hotseat:
Hotseat is having one computer where player’s take turn behind the computer (during their turn, they’re in the “Hotseat”

. Due to the nature of the game being played on one computer throughout its entirety, it is the closest to Singleplayer that you’ll get out of all the different multiplayer modes.
The only real difference between Hotseat and a normal Singleplayer game is what happens at the start of a turn and how diplomacy works. At the start of a Hotseat turn, the screen is black and only a single popup to display the player’s entry box for their password is on the screen. Once that’s all done and the player enters their password, then their turn begins just like normal.
For diplomacy, unlike singleplayer where you’re diplomatic treaties are handled with the AI in a real-time way, any time you try to make a deal it will be put up for consideration. On the player’s turn that you’re dealing with, they can accept, reject, or make a counter-offer. Their response will not be known to you until your next turn (or, since this is a Hotseat game, until the player actually talks to you, since assumingly you guys can, you know, talk and communicate with each other. You do communicate in real life, correct?)
However, all these details are handled for you. Whenever you do anything, the only problem you need to worry about with making a Singleplayer mod compatible with Hotseat games is that you don’t assume that the human player is going to be player 0. Even if you do things that would cause OOS errors in a networked game, a hotseat game, due to how it’s naturally on one computer at one time, will not go OOS (more on this is in Section 3). However, that doesn’t mean that there isn’t room for screwing up. Using the wrong player ID, for example, will mean your event that gives a player a super-monkey unit for collecting 100 bananas will give the monkey unit to the wrong player. The game won’t go OOS, since the actual event of creating the unit will happen on the one computer, just for the wrong player.
PBEM:
Play By E-Mail (PBEM) games work like Hotseat games, with the main exception being that an e-mail is sent out with the saved game, so the game will typically be played on multiple computers. When a player finishes a turn, they go ahead and set into action the next player’s turn. This continues on until it hits the next human player. At that point, the game is saved just before that player’s turn starts, and the save is sent to the player.
Diplomacy works the same way. You don’t get your instant gratification of a Singleplayer game, but once again these issues are not things you need to worry about.
Finally, just like hotseat, the game cannot go OOS, but you can mess up how things work. A singleplayer game might have given you the correct message of “You have received a super-monkey”, because you were human player 0, and you never made the AI build super-monkeys. But when in PBEM, if human player 3 receives a super-monkey, and you told the message to show for player 0, then the message will be saved in the save game, and when player 0 opens it, they will be happy to know that they received a super-monkey without even trying.
Networked Multiplayer:
Here is where the fun begins. Networked Multiplayer games happen on multiple computers at the same time. Unlike the previous game types, anything that happens on one computer that changes the game-state needs to be sure to be replicated for other computers in the game. Thus, even if you’re player 0, and it is player 1’s turn, if player 1 moves a unit, that unit has to be moved on your computer as well. As described in Section One, Player 1’s computer will send out a message to all connected computers that it moved the unit. Both of your computers respond to the message and set into action what happens when a unit moves.
This is different than PBEM, where the action is done on only player 1’s computer, and then the results are stored in the save file, so that when your turn comes, you open it have all the completed results. Rather, in a networked game, all the changes to the game happen real-time.
Along with the problems you can have in the Hotseat and PBEM games where you are using the wrong player id, another problem creeps up. The dreaded OOS error. This happens due to one computer doing something to the game-state without telling another computer about it. In PBEM and Hotseat this is avoided because only one computer at a time has the up-to-date game-state. More on OOS errors in Section Three.
Simultaneous games:
You might be wondering why I went through the entire single-player example that I did, and just give a few paragraphs for the others. It seems as if I kinda went overboard on explaining Singleplayer, huh?
Well, fear not. Because Simultaneous games are a whole different breed to begin with, and you should probably understand what’s going on if you want to support it with your mod.
First off, unlike Singleplayer games, where the game tells the first person to make their turn active, and this continues down the line one at a time, at the beginning of a game turn ALL player’s are set active. You might recall that things such as unit movements are done at the beginning of the player’s turn, whereas things such as city turns and research updates and anarchy turns are done are done at the end. When two players finish a research or wonder at the same time, the tie will go to the player who is first in the order of player’s turn. In simultaneous games, everyone goes at the same time, so whose turn is run first?
A smart person would say that it’s the person who ends their turn first. After all, all the things such as city production and research updates are done during their doTurn called at the end of the turn, correct? Well, don’t worry if you didn’t think this, because it’s wrong anyway.
In order to keep things fair, you have to realize that the AI will probably finish their moves first, due to the fact that they can think many, many times faster than you (even if it’s not many, many times smarter than you). But, even in a game without AI, or if two players are racing for the wonder, wouldn’t one player just try to end their turn as quick as possible and be the first one done?
In order to stop things like this, Firaxis made this decision: In a simultaneous game, all players’ turns are done at the beginning of the game turn, just before the unit turns are done. So now, since all players have their turn start at the same time (as opposed to ending at different times), we can give each player and AI equal running for a tie in finishing a wonder or research first.
The key is that, unlike normal games where player 0 always gets to start their turn first, all the player ID’s are “shuffled”. Then, players “start” their turn in the shuffled order, so player 0 is not always first, and it’s a matter of luck as to who wins if two Civ’s finish at the same time. Of course, all of this happens so fast that player’s think it’s instantaneous, but as a modder you know better. The code is below.
Code:
void CvGame::doTurn()
...
...
[b]if (isMPOption(MPOPTION_SIMULTANEOUS_TURNS))[/b]
{
shuffleArray(aiShuffle, MAX_PLAYERS, GC.getGameINLINE().getSorenRand());
for (iI = 0; iI < MAX_PLAYERS; iI++)
{
iLoopPlayer = aiShuffle[iI];
if (GET_PLAYER((PlayerTypes)iLoopPlayer).isAlive())
{
GET_PLAYER((PlayerTypes)iLoopPlayer).setTurnActive(true);
}
}
}
...
As you can see, the emboldened code is the special case that the game being played is a simultaneous game. If so, it makes each player active. During that CvPlayer::setTurnActive SDK function, we have this code:
Code:
void CvPlayer::setTurnActive(bool bNewValue, bool bDoTurn)
...
...
if (bDoTurn)
{
if (GC.getGameINLINE().getElapsedGameTurns() > 0)
{
if (isAlive())
{
if (isHuman())
{
if (getTeam() == GC.getGameINLINE().getSecretaryGeneral())
{
if (GET_TEAM(getTeam()).getSecretaryID() == getID())
{
for (iI = 0; iI < GC.getNumVoteInfos(); iI++)
{
if (!(GC.getVoteInfo((VoteTypes)iI).isSecretaryGeneral()))
{
GC.getGameINLINE().setVoteTriggered(((VoteTypes)iI), false);
}
}
}
}
}
[b]if (GC.getGameINLINE().isMPOption(MPOPTION_SIMULTANEOUS_TURNS))
{
doTurn();
}[/b]
doTurnUnits();
}
}
if ((getID() == GC.getGameINLINE().getActivePlayer()) && (GC.getGameINLINE().getElapsedGameTurns() > 0))
{
if (GC.getGameINLINE().isNetworkMultiPlayer())
{
gDLL->getInterfaceIFace()->addMessage(getID(), true, GC.getDefineINT("EVENT_MESSAGE_TIME"), gDLL->getText("TXT_KEY_MISC_TURN_BEGINS").GetCString(), "AS2D_NEWTURN", MESSAGE_TYPE_DISPLAY_ONLY);
}
else
{
gDLL->getInterfaceIFace()->playGeneralSound("AS2D_NEWTURN");
}
}
doWarnings();
}
So, as you can see, when a player’s turn is set to “active”, their “doTurn” is called. This happens at the beginning of their turn, not at the end as is the case in other game types. Also interesting to note is that in the Singleplayer only one player has their turn active at a time. In Simultaneous, multiple players will be active. The same strategy of determining when all players finish their turn still holds. If at the start, 18 players have their turn active, one by one they will finish until there are no more players remaining with their turn active, and as a result the game goes through it’s CvGame::doTurn SDK function. Note that the CvGame::doTurn SDK function is always called at the end of a game turn, even in Simultaneous games.
One thing to learn from this is that if you are doing something in the onBeginPlayerTurn function that depends on the fact that the player’s orders are always 0 throught 18, you’re going to have some Simultaneous trouble.
One example I’ll give here dealing with the difference in Singleplayer to Multiplayer (specifically Simultaneous games) is with the Civcraft: SC mod (I promise I’ll try not to plug it too much in this tutorial, but this example was too good to pass up). For those not familiar with Starcraft, a Terran player can build a Nuclear silo, which, inside of that, can be built a Tactical Nuke. Unlike in Civ4, the nuke cannot be controlled to just be targeted anywhere within its range, but rather a covert ops “Ghost” unit must “mark” the nuke sight with a laser. Some small amount of time passes between when the ghost first marks the sight to when the nuke lands, given the enemy a chance to hear the siren (“Nuclear Launch Detected!”

and try to find the ghost (which is typically invisible without a unit around to detect it). If they kill the ghost or if the ghost cancels the nuke while the nuke is in mid-flight, then the nuke is lost in space and never lands on it’s target.
Translating this to a turn-based game, the idea is that a nuke should land one or more turns after the warning is first given. My original thought was that as soon as the nuke gets launched (that is, as soon as the ghost unit makes the mark to have it launched) to send up the warning. The nuke will land on the player’s next turn. Now, here’s the million dollar question: will this work in all multiplayer situations.
First, let’s see how it should work in singleplayer. Recall that in Singleplayer, a player’s doTurn is called at the end of their turn. So, if I were to in the onPlayerBeginTurn or onPlayerEndTurn place code that makes the nuke land for any ghost that is currently targeting a sight, then the nuke would land the very same turn. Also, in a simultaneous game, the player could just launch the nuke a second before the turn timer ends, and the nuke would land at the beginning of the next turn (remember, the doTurn of all players are done at the beginning of the turn in Simultaneous mode), giving nobody any chance of reacting.
So, instead, I would just make it wait a turn. The siren goes up, and a counter is created for the player of that nuke that starts at zero. At the end of the turn, the counter gets incremented (from zero to one). All players would have one turn to “find the ghost” or at least try to get their units out of the way of the blast. On the next players turn, the counter is incremented from one to two, and because two is the magical nuke number, the nuke lands. In multiplayer, the same concept applies. Now, will this work in simultaneous mode?
When the player launches the nuke, the siren goes up immediately. This means that if the player launches the nuke as the very first thing they do in the simultaneous turn, the other players will have the whole turn to be able to react. That turn ends, and the next begins. At the beginning of the next turn, the counter is incremented (from zero to one), and once again the players have a whole turn to react. That turn ends, the next turn begins, whereby the player’s nuke counter goes up to two, and the nuke lands. But, did you catch what happened?
If the player launches the nuke at the beginning of the simultaneous turn, there are essentially two turns for players to react, whereas if they launch it at the end, players will have essentially one turn to react. Some mod makers might be okay with this, and if so that’s great, but to me simultaneous mode isn’t there for you to have to time your movements in a real-time manner, rather it’s just supposed to make the turn-based game go faster. At it’s root, it’s still supposed to be turn based. As such, when a player who plays the game singleplayer or any non-simultaneous multiplayer sees that there is one turn to react to a nuke, I want them to believe that the same rule applies for simultaneous mode.
As a result, what I ended up doing is making the warning siren appear during the player’s doTurn. That way, no matter when during a player’s simultaneous turn they launch the nuke, the siren will go up exactly one full turn before the nuke hits. Of course, this may not be the best case for your mod, and you might have liked it better the other way, but I guess making mods is a lot like how Sid Meier’s views playing games: “A series of interesting choices.”
That concludes this section on the various multiplayer game types. Here are the things to remember:
- If a mod works in singleplayer, it doesn’t necessarily means that it will work in any multiplayer types.
- If a mod works in singleplayer, hotseat, and PBEM, it doesn’t necessarily mean it will work in the other multiplayer types.
- Simultaneous games should work mostly the same as other network-type games, so long as you don’t do anything tricky with the ordering of the doTurns.
- In all games, the unit’s CvUnit::doMove SDK function, which resets movement and other per-unit data, is called at the beginning of a player’s turn.
- In all but simultaneous games, the CvPlayer::doTurn SDK function for a player, which contains the python onBeginPlayerTurn and onEndPlayerTurn, happen at the END of the turn. The CvGame::doTurn SDK function, which includes the python onBeginGameTurn and onEndGameTurn, is called after all players have finished their turn
- In simultaneous games, the CvPlayer::doTurn SDK functions for all players are called at the very beginning of the game turn. All players are considered “active”, until they end their turn. The CvGame::doTurn is called, similar to other multiplayer games, after everyone is done.
- Knowing how the various Multiplayer systems work is not absolutely required for a modder, but can prove useful in realizing how gameplay might change in unexpected ways.