Skip to content

New Contributors Guide C structure

Mark Langsdorf edited this page Aug 2, 2020 · 3 revisions

Warning: This is an introduction to Cataclysm: Dark Days Ahead's C++ code structure. If you're not comfortable reading C++ code, this is probably not a page you should read and you should go back to the Guide to contributing's front page.

The CDDA source code lives in the src/ directory.

I'm going to highlight some of the more important files and fundamental data structures, but again, there is a lot of CDDA code and I haven't ever touched large parts of it, so I might be missing things here.

First, some meta concepts:

  • Most of the game's data is loaded from JSON using a standardized set of functions. If you're referring to this guide, you probably shouldn't be touching the JSON manipulation functions themselves. You may need to use them to load or save a particular data structure, and those functions are usually in src/savegame_json.cpp and are pretty easy to figure out. CDDA uses a complicated deferred loading structure that reads the JSON in an arbitrary order while keeping track of data structures that have unresolved references to other pieces of JSON, and then keeps reloading the JSON until the references are resolved.
  • point and tripoint are the fundamental data structures to keep track of 2D and 3D co-ordinates on maps. Various levels of the game's maps have different co-ordinate schemes, see doc/POINTS_COORDINATES.md for a thorough, if confusing, explanation. The most important thing to remember is that local map coordinates are always relative to the current player position on the map and change as the player moves, while global coordinates are fixed and invariant, so if you need store map coordinates for use on a future turn of the game, you must always store the global coordinates.
    • Currently, all many instances of point and tripoint are the same, regardless of coordinate type, and many functions do not indicate which sets of coordinates they require or return. This is needlessly confusing and there is an ongoing project to replace point and tripoint with typed versions such as abs_omt_tripoint. Use the typed versions whenever possible.
  • cata::optional is a CDDA specific template for passing data that may be absent, such as a map co-ordinate to a building that may or may not exist. cata::optionals are not pointers, but can usually be treated that way: checking the variable is a true/false test as to whether it has valid data, and derefencing the variable gets the underlying value if it is valid.
  • CDDA has a bunch of standard units defined in src/units.h with standardized, templated classes. You can do things like units::mass weight = 3_kilograms; for assignment, and addition and division operators are usually defined for units. Using units provides type safety when dealing with quantities and is strongly encouraged.

Here are some of the major game files and data structures. Header files usually have a matching .cpp file, and may have more than 1 related .cpp file.

  • src/game.h contains the main game loop and various global data structures. The senior developers would like to deprecate game.cpp, and in the meantime, do not want people adding more code to game.cpp. Global data from the game:: class is accessible through the g-> global pointer. Global data access through g-> is deprecated to reducee overinclusion of the game.h header, which is slowing compile times.
  • The map local to the avatar is an instance of the map:: class in src/map.h and can be accessed from g->m getmap(). By convention, map &here = getmap() is the local reference the global map around the avatar. Distant maps can be loaded for brief editing via the tinymap:: child class of map::, also in src/map.h, and tinymap &there is a local reference to a selected portion of the global map (analogous to here). map:: also contains a huge amount of terrain and furniture editing functions and general utility.
    • The local map (aka here or getmap()) is sometimes called the "reality bubble", and consists of a 121x121 square grid of tiles roughly centered on the avatar.
    • Technically, maps consist of 24x24 map tiles, broken up into a 2x2 array of submaps containing 12x12 map tiles. Each 24x24 local map is a single tile in the overmap, and 180x180 overmap tiles form an overmap buffer, and all the overmap buffers are stored in the overmap. Each layer has its own set of source code and corresponding class.
  • src/creature.h implements the basic (and basically virtual) Creature:: class. Creature has two child classes: Character:: in src/character.h and monster:: in src/monster.h.
  • An individual monster is an instance of the monster:: class, and there are various monster related source files such as their AI, src/monmove.cpp and their JSON loader src/monstergenerator.cpp. All monsters of the same type share a monster type or mtype:: instance which contains the basic definition of the monster type and is coded in src/mtype.h.
  • Character:: was original supposed to be a virtual parent class for its child classes, but the terminology got confusing and there is an ongoing effort to refactor them and move more code into Character::. player:: in src/player.h was originally supposed to contain data relevant to the player of the game, but it is being deprecated in favor of the avatar:: class in src/avatar.h. g->u is the global variable for the current avatar. get_avatar() returns a reference to the current avatar.
    • When adding new code that applies to both the player's character and NPCs, put it in Character:: and pass variables as Character &. When adding new code that only applies to the player's character, such as UI code, put it in avatar::.
    • A lot of current code passes a player & or player * when it should pass a Character & or Character *. In general, that pattern should not be repeated.
    • melee combat and ranged combat are in src/melee.cpp and src/ranged.cpp but the functions mostly exist inside the Creature::, Character::, monster::, or player:: classes, and the player:: functions are being moved to Character:: or avatar:: as appropriate.
    • A lot of current code will do an is_player() or is_npc() check before executing some code, or recast a Character value into player, avatar, or npc. Gating some code on a check is sometimes a clean way to implement something, but recasting variables should be avoided in favor of virtual functions in Character:: that are overridden in avatar:: or npc:: and called directly and automatically.
    • avatar &you = get_avatar() is a preferred way to get a local reference to the current avatar, and npc &guy is a common way to refer to some NPC.
  • player:: has a child class npc:: in src/npc.h to support NPCs. Like monsters, npc:: have a lot of support code in related files such as the AI code in src/npcmove.cpp. npc:: should not be a child class of player:: but should be a child class of Character:: and there is a slow migration underway to correct this.
  • Items, like monsters, have an item type or itype:: in src/itype.h and an instance in item:: in src/item.h. Items can have more than one type, with each type containing a separate islot_ data structure in the itype::. The current implementation of islot_s is not ideal and will be restructured at some point in the near future. Item definitions are loaded from JSON via src/item_factory.cpp
  • src/calendar.h contains the classes used to track time in the game. time_point is a single point in time, and time_duration is the elapsed time between two time_points. Like other units, time_point and time_duration have addition, multiplication, and division operators defined, as well as textual assignment operators so you can do time_duration soon = 5_minutes; calendar.h also has definitions for longer time periods, including seasons.
  • The UI is split among a variety of classes, and a lot of basic functionality such as drawing a paned window still needs to be done by hand. Menus can easily be created using uillist:: from src/ui.h. Windows can be created and manipulated using the functions in src/cursesdef.h but a lot of window management still needs to be done by hand.

There are a lot of other classes and functions in the game: vehicle, artifacts, spells, missions, basecamps, and so on and so forth. This is only a high level introduction to get your feet wet; you'll have to read the code to understand it all. Again, git grep or equivalent is your friend.

Clone this wiki locally