Contributing Code (UFO2000)

From UFOpaedia
Jump to navigation Jump to search

This file is a guide for new UFO2000 developers

Note: This page is still not complete and some things still can be changed in the future. You can ask questions and discuss it in ufo2000 forum and also suggest what you would like to see changed or updated here.

Getting started

First you need to get the latest sources of the game. We are using Subversion as a version control system. It is very similar to CVS, so if you are familiar with CVS, you will have no problems using it.

Checking out your working copy of ufo2000 sources:

svn co ufo2000

Other people may commit their changes to the repository while you are working with your copy of sources, so you need to update your working copy from time to time to keep it up to date:

svn up

There is quite a comprehensive and well written book about Subversion and version control systems in general.

Compilation instruction can be found here or in the wiki for MacOS and Linux.

Once you got familiar with compiling the game and have added some useful feature or fixed a bug, you may want to share your changes with the other people and get them in the next version of the game. Please review everything you have changed in order to avoid adding bugs or breaking existing code. Check that your code conforms to our sources formatting style described in the next chapter. Also any patch should be reasonably small, readable and address a single problem. Patches can be created with subversion using:

svn diff > somefile.diff

You can submit the patch to our bugtracker and one of the developers with full access to the repository can review it and commit. Also if anyone finds any problems with the patch, we can discuss it there before it gets committed.

If you don't know where to start and what to do, you can visit our bugtracker and be sure to see a big list of currently open and unassigned bugs and feature requests: (Doesn't exist any more.)

Sources formatting style

Most important rules:

The other issue that always comes up in C styling is the placement of braces. Unlike the indent size, there are few technical reasons to choose one placement strategy over the other, but the preferred way, as shown to us by the prophets Kernighan and Ritchie, is to put the opening brace last on the line, and put the closing brace first, thusly:

if (x is true) {
    we do y

However, there is one special case, namely functions: they have the opening brace at the beginning of the next line, thus:

int function(int x)
    body of function

Heretic people all over the world have claimed that this inconsistency is ... well ... inconsistent, but all right-thinking people know that (a) K&R are right and (b) K&R are right. Besides, functions are special anyway (you can't nest them in C).

Note that the closing brace is empty on a line of its own, except in the cases where it is followed by a continuation of the same statement, i. e. a while in a do-statement or an else in an if-statement, like this:

do {
    body of do-loop
} while (condition);


if (x == y) {
} else if (x > y) {
} else {

switch statement example:

switch (x) {
    case 1:
    case 2:

It is also currently recommended to add g_ prefix to global variables and m_ to class member fields. Class names should have first uppercase letter, function and variable names should begin with a lowercase letter. Constants should be all uppercase. The use of #ifdef's should be avoided if possible.

The sources should have doxygen style comments describing arguments and return values for different functions (doxygen home page is here).

Note: not all the UFO2000 sources are formatted as described here. This is a guide for writing new code and fixing old code when refactoring.

Any proposals for changing sources formatting style will be ignored as it is the easiest way to start another flame war. The only persons who can initiate sources formatting style change are the developers who had already submitted a lot of useful patches :-)

Sources documentation

Sources documentation can can be generated by doxygen tool (doxygen home page is here). Documenatation is very helpful when trying to understand internal structure of the project.

Building html documentation from ufo2000 sources can be performed by running:

make source-docs

In general, all the sources can be found within src subdirectory. It contains a number of subdirectories with third-party code and libraries which are included into ufo2000 source tree.

Building and testing experimental versions of the game

Some patches or other changes might be not stable enough for committing to SVN and need more real-world testing. Just compiling experimental build of the game and connecting to the main server can cause problems because starting the game against normal build user might cause all sorts of compatibility problems.

In this case it is recommended to edit src/version.h file in the sources directory and change UFO_VERSION_TAG define to something else, for example to something like experimental-mindcontrol. After that you can safely distribute this experimental binary, connect to the primary server, play games and do some testing without interfering other users playing ordinary "release" or "beta" builds.

The server allows different versions to play on the same server without interfering each other. In version.h now we have VERSION_TAG constant, only clients which have the same tag see each other on the server, so changing it to something like experimental any other tag and building the game will ensure that »normal« players will be able to continue playing »beta« versions, but the courageous and curious ones will be able to play »experimental« versions. Server status page now also shows some information about the versions and tags of the players currently logged on to the server.

It should be easy to provide separate stability statistics for each tag on page. So now anyone can checkout the latest sources of the game from the repository, apply some patch, set some special tag in version.h and put this build for download. People can download this build and play it, if we see that stability of this build is acceptable after a reasonable number of games, the patch can be safely committed to the repository.

Some issues that should be taken into account when coding for UFO2000

Don't use floating point calculations for anything that should be identically processed on both local and remote computer. Currently the game sends a command to the remote host and simultaneously executes it on both computers when making any action. If the results of command execution differ, the game state gets out of sync. Floating point is bad as different hardware implementations can have different precision and rounding mechanics, also different compilers can reorder some instructions or change them to equivalents but with slightly different precision (see '-ffast-math' option for gcc for example)

Also see this article for more explanations.

Some correction: now we use fdlibm (src/fdlibm) math library which is used in java to ensure the same results for floating point calculations, so this problem it not so critical now. Anyway, it seems to be a bit fragile and requires special care, in addition floating point math must be IEEE-754 compatible on target platform anyway (which is not true for some platforms).

Good rules of programming

  1. Copy/paste is a bad habbit, better create a function containing reusable code
  2. Hide implementation details for classes (use private members when possible) and modules (use static functions and variables). It makes the interaction between different parts of code more obvious and easier to understand.
  3. Avoid the use of global variables, as they are visible from just anywhere, you never know for sure when they can be unexpectedly modified.
  4. Don't add anything that "can be useful in the future". The code that is not really used tends to contain bugs and makes the sources harder to maintain. In addition, when the future really comes, there is a good chance that this code will need to be rewritten anyway :)
  5. If you have to add some dirty hack to make a quick fix or workaround some weird problem, always add a comment explaining why you did this. Otherwise other people (or even you after some time) will have problems understanding this code in the future increasing a chance of breaking it.
  6. Comment every none trivial function, input arguments and return value, interaction with the rest of code if there are some issues. If you find that something is hard to comment, that's an indication that this code is probably written wrong :)
  7. More to add....

Commit access

How commit access is granted:

After someone has successfully contributed a few non-trivial patches, some full committer, usually whoever has reviewed and applied the most patches from that contributor, proposes them for commit access. This proposal is sent only to the other full committers -- the ensuing discussion is private, so that everyone can feel comfortable speaking their minds. Assuming there are no objections, the contributor is granted commit access. The decision is made by consensus; there are no formal rules governing the procedure, though generally if someone strongly objects the access is not offered, or is offered on a provisional basis.

The criteria for commit access are that the person's patches adhere to the guidelines in this file, adhere to all the usual unquantifiable rules of coding (code should be readable, robust, maintainable, etc.), and that the person respects the "Hippocratic Principle": first, do no harm. In other words, what is significant is not the size or quantity of patches submitted, but the degree of care shown in avoiding bugs and minimizing unnecessary impact on the rest of the code. Many full committers are people who have not made major code contributions, but rather lots of small, clean fixes, each of which was an unambiguous improvement to the code.

Version numbers and release management

Every ufo2000 release uses three part version number convention: major.minor.svnrev

major: is the major version number (is currently set to 0), it is currently reserved for future use, it will change to '1' some day minor: that's the primary version number which can identify big releases even minor version numbers are used for stable releases and odd minor version numbers are used for beta releases svnrev: that's just SVN revision number which can be used to easily find the sources for any UFO2000 build in SVN repository

As mentioned above, there are generally two types of releases: beta and stable.

Beta versions are released quite frequently as soon as some new features get implemented (new beta releases may become available weekly or even daily), they are compiled directly from SVN trunk. When you see an odd minor version number, you can clearly know that the sources of this build can be obtained from SVN repository by performing checkout of svnrev revision from SVN trunk. In other words, we make use of subversion ability to identify the whole source three by a single revision number and use it as an automatically generated version number. Makefile automatically takes case of assigning version numbers and can build full ufo2000 installers with running only a single command. This eliminates human factor and guarantees consistent releases with proper version. If some ufo2000 build has 'M' suffix in the end of the version string, it means that this release was built from not a pure SVN revision but from modified sources. Beta versions should be always built from some pure SVN revision so that we clearly know what sources were used for it (knowing what sources exactly were used for any version is vital when analyzing bugreports and debugging).

Stable versions are released less frequently (interval between stable releases is usually measured in months) after some extensive testing to ensure that they don't have any major problems. Stable versions are intended for general use by the players who don't like to upgrade too often and want more stability.

The list of planned features and bugfixes for each stable release can be found in the bugtracker pinned at top (the bugtracker doesn't exist any more!). Once SVN trunk is in the more or less consistent form and all the needed features already got implemented, release branch gets created. Stable branches have a name matching planned version number in the form of 'major.minor' without revision number (exact revision number is not known at that time). Branches can be seen here.

After a stable branch got created, development may continue in trunk and new beta versions may get released from it as usual. On the other hand, only bugfixes and other changes which are blocking release are allowed in the stable branch. In some exceptional cases it is allowed to backport some changes to a stable branch from trunk, but these changes must be solid and well tested. A few release candidate builds can precede the final release. Getting the sources for any release candidate is also quite simple: if the minor version number is even, we need to checkout the appropriate revision from the branch named after 'major.minor' pair. Once the quality of sources in the stable branch is considered good enough, a release is built from them and tagged:

Some fixes may get released for stable versions later, but it is important not to break game compatibility. If compatibility breakage is unavoidable for the required fixes, minor number should be also changed effectively resulting in a new 'big' stable version release. Minor bugfixes for stable releases can result in only svnrev part of the version number changing.

This document »borrows« a lot of text from: