Multiplayer implementation of the classic Catan board game built in C++ and Qt, featuring a client-server architecture, real‑time gameplay synchronization, customizable game sessions, in‑game chat, and match statistics.
Tech focus:
C++17 • Qt6 • Client–Server Architecture • Network Programming • Protobuf • CMake • State Machine Architecture • Design Patterns
The game includes the full core Catan gameplay, along with several additional features:
- Parallel Game Sessions: the server supports multiple game rooms simultaneously, allowing different groups to play separate matches.
- Customizable Game Rooms: the host can configure game parameters such as number of players, victory point threshold, and map options.
- In‑Game Chat: players can communicate and negotiate during gameplay.
- Game History and Statistics: match statistics and history are recorded and available for review after each game.
- Custom and Random Maps: supports both randomized standard/extended maps and fully custom board configurations.
- ASCII Map Prototype: used during early development phases for testing core game mechanics.
GameSession, GameController, Move system, Render state system and Rules engine were my area: the layer for rules, state, and everything that happens on a player's turn.
- GameSession and GameController: full match lifecycle. Turn order, phase transitions, which actions are valid when. The GUI doesn't decide any of this, it just reflects what the engine says.
- The move system: every player action is a move with
isValid()andapply(). The sameisValid()that enforces rules also drives GUI highlighting and board shake on placement. - Server-authoritative design: all moves are validated on the server before taking effect. Every client sees the same game state.
- Dual-mode phase state machine: tracks both game phase and current move sequence, with input-blocking guards. Invalid actions aren't filtered in the UI, they're not offered in the first place.
- Render state system: BoardRenderState, ToolbarRenderState, and PopupRenderState turn the engine's valid move list and current phase into what's highlighted and enabled. No rules live here, it's a state derived from the phase the game is currently in.
- Rules engine: win conditions, longest road, and largest army each live in their own Rule subclass. After every move, a single
evaluate()call checks whether any rule's condition is now satisfied.
- Command:
isValid()/apply()on every move type - State Machine: dual-mode TurnPhase transitions with input-blocking guards
- Observer (Qt signals/slots): GUI reacts to engine state changes
- Fake test double:
makeTestBoard()for isolated unit testing - Singleton:
AudioManageris one shared instance that handles sound effects across the whole app
- Built
TestHelper.h, the shared Catch2 infrastructure used across the team. Fake board withforcePhase()/forceCurrent()helpers, covering move validation and phase transitions. Found several real move-validation and phase-transition bugs before integration. - Board elements: houses, cities, roads, robber (Qt)
- AudioManager for app sound effects
- GUI refactoring and styling improvements across the application.
- Maintained and populated GameHistory.
- Type aliases and cost tables: NodeId, EdgeId, TileId are int aliases for readability. Build costs live in one place as C++17 inline const ResourcePacks, so changing costs is easy and there is no code duplication or inconsistency across classes.
- Set up Git hooks and kept the development workflow smooth. Coordinated refactoring and helped the team figure out where things fit.
- Designed architecture and GUI sketches along with the initial UML class diagram.
@MatijaRadulovic built the networking layer, we worked out how moves and game events get passed between the engine and the network.
The following is required to build and run the project:
- C++ compiler with C++17 support
- Qt 6 SDK, recommended version 6.2 or newer
- CMake 3.16 or newer
- Conan 2, if building with Conan
- Protobuf, if building with plain CMake
- Catch2, if building tests with plain CMake
Protobuf and Catch2 can be installed using:
vcpkg install protobuf catch2Before running the application, configure the client to connect to the server:
- File path: local app storage location
resources/config.ini - Setting to update:
server_ip - Set it to the address of the machine running the server
Clone the repository:
git clone https://github.com/andja45/catan-frontier-settlements
cd catan-frontier-settlements/CatanIf you build without Conan, make sure Qt and Protobuf are installed locally and available to CMake.
You may need to point CMake to your Qt installation:
cmake -B build -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x/gcc_64
cmake --build buildIf you build with Conan, make sure Conan is installed and provide your local Qt path.
Option 1: environment variable
export QT_DIR=/path/to/Qt/6.x/gcc_64Option 2: Conan profile/config
Add this to your local Conan profile:
[conf]
user.qt:path=/path/to/Qt/6.x/gcc_64Then run:
conan install . --build=missing
conan build .If you want to package the project into your local Conan cache:
export QT_DIR=/path/to/Qt/6.x/gcc_64
conan create . --build=missing