CONTRIBUTING.md 7.7 KB

Reporting an Issue

  • Report all issues
  • Trivial documentation issues welcome (example)
  • Non-trivial feature requests welcome (example)

Creating a Pull Request

  • Do development on the develop branch.

Versioning

BWAPI versioning is categorized as follows: major.minor.patch [Beta]

Version Component Description
major Increased when massive structural changes are made.
minor Increased when breaking changes are made. Modules will need to be recompiled.
patch Increased when non-breaking changes are made.
Beta Appended to a major version increase until stability has been verified.

Coding Standards

Spacing

  • Use double-spaces instead of tabs. You should be able to convert tabs to spaces automatically in your editor's settings.
  • Always indent for each scope level.
  • Always put a space between all arithmetic, binary, and conditional operators.
  • Don't put a space between function names and the open parenthesis.
  • Put a space after a comma.

Examples of spacing

// bad, can't tell if assignment is a typo, and
// there is a space between the member function and its parameters
if(Broodwar->canMake (UnitTypes::Terran_Marine, builder))
  reservedMinerals=-UnitTypes::Terran_Marine.mineralPrice();

// good, the arithmetic is clear
if(Broodwar->canMake(UnitTypes::Terran_Marine, builder))
  reservedMinerals = -UnitTypes::Terran_Marine.mineralPrice();

// bad, the scope is not indented, no space following the comma
if ( Broodwar->canMake(UnitTypes::Terran_Marine,builder) )
reservedMinerals = -UnitTypes::Terran_Marine.mineralPrice();

// good, alternative spacing style for if statements
if ( Broodwar->canMake(UnitTypes::Terran_Marine, builder) )
  reservedMinerals = -UnitTypes::Terran_Marine.mineralPrice();

Formatting

  • Use ANSI style braces.
  • Break up large single-line if statements to be multi-line if statements.
  • Format constructor initializer lists as follows (so that the colon is in the same column as the commas):
  BulletImpl::BulletImpl(BW::CBullet* originalBullet, u16 _index)
      : bwOriginalBullet(originalBullet)
      , index(_index)
  {
  }

Naming

  • Use meaningful names. If a variable's purpose cannot be identified by another project member without analysing the code, then the variable needs to be renamed.
  • In local looping scopes, single-letter variable names are generally used as follows:
    • b for Bullet
    • f for Force
    • p for Player
    • r for Region
    • u for Unit
    • i for iterator/index
  • Member variables and member function names should be in lower camel case. Examples: getUnitsInRectangle, wasSeenByBWAPIPlayer.
  • Constants and macros should be in ALL CAPS and words separated by underscores. Example: PLAYER_COUNT
  • Use upper Camel Case for classes, structures, enums, and namespaces.

Hacking

  • Offsets must be in hexadecimal. Example: 0x00408CF0.
  • Offsets must be placed in BW/offsets.h.
  • Avoid using inline assembly unless it is impossible to do so.
  • Always perform version checking before making code patches, to maintain partial cross-version compatibility.

Documentation

  • Use the triple slash (///) format.
  • Try to include as much details on the function as possible. Redundancy can express clarity.
  • Include example code if possible.
  • Wrap lines before the 100th column.

Doxygen Generation

  • Use @ for doxygen commands.
  • Use @see to refer to other functions/classes.
  • When introducing a new function, include a @since tag with the version number.
  • Include @returns, and @retval where necessary.
  • When specifying @param, also specify if the argument is optional. Present an indented description on the next line, and also specify its default value if applicable.

Intellisense Compatibility

  • Use the summary tag to wrap the function/class/enum description.
  • Use the param tag to identify all of the parameters.
  • Identify if an argument is optional with (optional) on the same line as the tag.
  • Put parameter descriptions indented on the next line, between the tags.

Examples of documentation:

    /// <summary>Sets the size of the text for all calls to drawText following this one.</summary>
    ///
    /// <param name="size"> (optional)
    ///   The size of the text. This value is one of Text::Size::Enum. If this value is omitted,
    ///   then a default value of Text::Size::Default is used.
    /// </param>
    ///
    /// Example usage
    /// @code
    ///   void ExampleAIModule::onFrame()
    ///   {
    ///     // Centers the name of the player in the upper middle of the screen
    ///     BWAPI::Broodwar->setTextSize(BWAPI::Text::Size::Large);
    ///     BWAPI::Broodwar->drawTextScreen(BWAPI::Positions::Origin, "%c%c%s",
    ///                                     BWAPI::Text::Align_Center,
    ///                                     BWAPI::Text::Green,
    ///                                     BWAPI::Broodwar->self()->getName().c_str() );
    ///     BWAPI::Broodwar->setTextSize();   // Set text size back to default
    ///   }
    /// @endcode
    /// @see Text::Size::Enum
    virtual void setTextSize(Text::Size::Enum size = Text::Size::Default) = 0;
    /// <summary>Retrieves the region at a given position.</summary>
    ///
    /// <param name="x">
    ///   The x coordinate, in pixels.
    /// </param>
    /// <param name="y">
    ///   The y coordinate, in pixels.
    /// </param>
    ///
    /// @returns Pointer to the Region interface at the given position.
    /// @retval nullptr if the provided position is not valid (i.e. not within the map bounds).
    ///
    /// @note If the provided position is invalid, the error Errors::Invalid_Parameter is set.
    /// @see getAllRegions, getRegion
    virtual BWAPI::Region getRegionAt(int x, int y) const = 0;
    /// @overload
    BWAPI::Region getRegionAt(BWAPI::Position position) const;

Language Features

  • Use the nullptr keyword instead of NULL.
  • Create move constructors if appropriate.
  • Use the const keyword where appropriate.
  • Use std::array instead of C-style arrays.
  • Use explicit enum types (preferably enum class) instead of ints.
  • Use in-class member initialization.
  • Use the keywords default, delete, override, final, etc.

Changing the API

Adding a Virtual Function

  1. Add it after all other virtual functions.
  2. Label it with Doxygen @since tag, indicating the version it was introduced.

Note: Virtual functions are implementation defined, but Visual Studio appears to maintain some consistency regarding the use of virtual functions. Adding a new function to the end will maintain some backwards compatibility.

Renaming a Function

  1. Rename the function.
  2. Create a non-virtual function with the old name that calls the new function.
  3. Label it with Doxygen @deprecated tag and refer to the new function.
  4. Optionally add a compiler deprecation warning (until we move to VS 2015).
  5. Remove it after the next 2 minor versions or next major version, whichever comes first.

Deprecating a Function

  1. Label it with Doxygen @deprecated tag.
  2. Provide reason for the deprecation and alternatives if applicable.
  3. Optionally add a compiler deprecation warning (until we move to VS 2015).
  4. Remove it after the next 2 minor versions or next major version, whichever comes first.