bbpPairings: the open-source Swiss pairing engine

bbpPairings (BBP Pairings) is an open-source pairing engine for Swiss chess tournaments. It is not a tournament manager and not arbiter software: it has one job - take a file containing the history of an event and return the pairings for the next round under the FIDE rules. Written in C++, developed since 2016, distributed freely with source. It is the engine that computes pairings in the Vibe Chess app.

What it is, in plain terms

The Swiss system is built so that pairing a field by hand honestly becomes nearly impossible past twenty players. Dozens of requirements have to hold simultaneously: never pair the same two people twice, keep the colours balanced, pair players on equal scores, and where that is impossible, choose the least bad option from a strictly ordered list of priorities. A pairing engine takes that work on.

bbpPairings is such an engine. It reads a file with the full history of the event, computes the pairings for the next round and writes them to a file. No interface, no database, no network: the program reads one text file and writes another. Everything else - registration, entering results, the standings, the display - belongs to whichever program calls it.

That separation is the industry norm: there is a reference engine, and there are tournament managers that use one. The best-known counterpart is JaVaFoby Roberto Ricca, the reference implementation of the Dutch system in Java. The bbpPairings interface was deliberately made similar to JaVaFo 1.4, with the permission of JaVaFo's author - about JaVaFo.

Who wrote it and on what terms

  • Developer: Bierema Boyz Programming. Repository - github.com/BieremaBoyzProgramming/bbpPairings.
  • Language: C++. Built with an ordinary Makefile on Unix; the repository includes a MinGW-w64 build for Windows.
  • Licence: Apache 2.0 - free to use including commercially, and free to study and modify.
  • History: the project started in August 2016. Versions 2.x and 3.x came in 2017, 4.1.0 in July 2017, 5.0.0 in January 2022, 5.0.1 in February 2023, and the current 6.0.0 on 1 February 2026 - the day the new edition of the Dutch rules took effect.

A property that matters to an organizer: the engine sends nothing anywhere. It is a local executable working with files on disk. Participants' personal data does not leave the machine the engine runs on.

Which systems it supports

The Dutch system is the main one. This is the Swiss that FIDE describes in section C.04.3 of its handbook and that is used at the overwhelming majority of open tournaments worldwide. Version 6.0.0 implements the 2025 edition of the rules, in force from 1 February 2026.

The Burstein system is the secondary one. Here the author is candid: the README states it implements the previous version of the system and contains shortcomings. It has no FIDE endorsement. In practice the engine is used for Dutch.

Round robins need no engine at all: there the schedule is computed arithmetically from the Berger tables, with nothing to search - the Berger tables.

Inside the Dutch system: score groups, brackets and floaters

To follow what the engine does, it helps to know the vocabulary of the FIDE rules - the same terms appear in its source and in its error messages.

  • Pairing number- the player's number setting the initial order, normally handed out by rating before round one.
  • Score group - everybody on the same number of points. The idea of the Swiss is to pair players within such a group.
  • Bracket - the group currently being paired: the score group itself plus whoever was left unpaired in the previous, higher group.
  • Homogeneous and heterogeneous brackets - in the first everybody has the same score, in the second some arrived from above.
  • Downfloater - a player with no partner in their own group who drops into the next one. In the new group they are a moved-down player (MDP), and the opponent from below receives an upfloat - a game against a higher-scoring side.
  • PAB (pairing-allocated bye) - the bye given when the field is odd: no opponent, no colour, and points awarded as for a win.
  • Transposition and exchange - the two ways of searching: reorder the players inside one half of the bracket, or swap equally sized groups of players between the halves. Searching through transpositions and exchanges is how the engine finds an admissible pairing.

Colours: absolute, strong and mild preference

Half the difficulty of a Swiss is colours. The rules divide a player's preference into three degrees:

  • Absolute - the difference between games as White and as Black has gone outside ±1, or the player has had the same colour twice running. This preference cannot be violated: the engine will not pair two players with the same absolute preference (outside special cases involving the tournament leaders).
  • Strong - the colour difference is exactly ±1. The player should get the equalizing colour, but where necessary this yields to more important criteria.
  • Mild - colours are level. Then the player should get the colour opposite to their last game.

Which is where the familiar picture comes from: colours alternate, long runs of one colour do not happen, and with an odd field somebody gets a bye - but not twice - about byes.

The pairing criteria and their priority

The FIDE rules state pairing as a strictly ordered list of requirements. The absolute ones come first and may never be broken:

  • two players do not meet each other twice;
  • a player who has already had a full-point bye does not get another;
  • two players with the same absolute colour preference are not paired together.

Then come the quality criteria, also ordered: maximize the pairs in the bracket, minimize the players floating down, keep the next bracket pairable, then honour the colour preferences - first any of them, then the strong ones, and only at the end the cosmetic concerns, such as not floating the same player down or up several rounds in a row.

The practical meaning is simple: the engine is not looking for a «nice» pairing, it is looking for one admissible under the highest-priority rule, and it concedes only where a round is mathematically impossible otherwise. Which is why arguing with its answer is usually pointless - if a pair looks odd, every alternative broke a higher-ranked rule.

TRF: how a tournament reaches the engine

Communication with the engine goes through TRF - the FIDE tournament data exchange format, also called the Krause format. It is a plain text file with a strictly positional layout: the meaning of a value is given by its column number, not by a delimiter.

The key line is 001, one per player: the player number, title, name, rating, federation, FIDE ID, date of birth, score, and then the round history in blocks of ten characters. Each block holds the opponent's number, the colour (w or b) and the result: 1 win, 0 loss, = draw, U a full-point bye, and + and - for wins and losses by forfeit.

Version 6.0.0 works with TRF-2026 and keeps backward compatibility with the older TRF(bx). It also has its own extensions for non-standard scoring - codes such as BBW, BBD and BBL, which set your own values for a win, a draw and a loss.

The same TRF is needed after the event: arbiter software and federations accept the file with the results, which is why «export the TRF» and «submit the tournament for rating» are close to synonyms in practice - the TRF format in detail.

Run modes and exit codes

The engine has three modes.

  • Pair a round: bbpPairings --dutch tournament.trf -p pairings.txt - the main mode. The output file has the number of pairs on the first line and then the pairs by player number.
  • Check a tournament: bbpPairings --dutch tournament.trf -c - the engine checks whether an existing pairing complies with the rules. Useful when the pairing came from another program or from a human.
  • Generate a random tournament: bbpPairings --dutch -g -o trf_file - creates a random event for testing. This is how the authors verify the engine across thousands of generated scenarios.

The outcome comes back as an exit code: 0 success, 1 no valid pairing exists, 2 internal error, 3 invalid request or data, 4 the tournament exceeds the size limits, 5 the file could not be read.

Code 1 is worth distinguishing from a real error. It is not a failure but arithmetic: a Swiss cannot pair the same two players twice, so with N players there are no opponents left after N-1 rounds. The correct response from the calling program is not to retry but to say the tournament has run its course.

Performance and limits

The README gives the theoretical complexity: roughly O(n³) for Burstein and O(n³ × s² × log n) for Dutch, where n is the number of players and s the number of occupied score groups. In practice an amateur event of a few dozen players is paired instantly, and the computation takes noticeable time only at very large opens.

Size limits are fixed at build time; exceed them and the engine returns code 4. Separately, remember that the engine knows only what the file told it - not the rating on a federation website, and not that somebody arrived late. All of that is the calling program's responsibility.

Its status with FIDE

This is easy to get wrong, so point by point. FIDE maintains a list of endorsed programs - a certification granted by the SPP commission after testing. That list holds tournament managers such as Swiss-Manager and Vega, and JaVaFo is treated as the reference implementation of the Dutch algorithm.

bbpPairings is not on that list. Its README is careful about the claim: the program aims to implement the rules described in the FIDE handbook. The Burstein implementation is explicitly marked as incomplete and unendorsed.

What that means in practice. For a club, school, company or amateur tournament bbpPairings is entirely suitable: it computes pairings by the same Dutch rules as the certified programs. If your event is going for FIDE rating, check the requirements on software with your federation and chief arbiter in advance - because of the absent certificate, not because of the algorithm - Swiss-Manager, Vega.

Who uses it

  • Lichess - its Swiss tournaments run a fork of bbpPairings with an added Fast Swiss system, pairing linearly from the top for speed on very large fields - Swiss on Lichess.
  • SwissSys - the well-known American tournament manager, where bbpPairings is available as a pairing option.
  • Vibe Chess - our app for over-the-board events, described below.
  • A great many home-built bots and services: the open licence and the plain «file in, file out» interface make it easy to embed.

How bbpPairings works inside the Vibe Chess app

In Vibe Chess the Swiss pairings are computed by bbpPairings - version 6.0.0, built from source and run with the --dutchflag. The scheme is exactly the one described above: the app assembles a TRF from the tournament history, hands it to the engine, receives the round's pairs and lays them out across the tables.

Several consequences an organizer notices:

  • pairings follow the Dutch rules rather than a home-made scheme: score groups, alternating colours, no repeat meetings and no two byes in a row;
  • the bye on an odd field is issued as a PAB - a point and no opponent, as the rules require;
  • when the engine answers that no valid pairing exists, the app does not invent pairs; it says plainly that the field is exhausted and the tournament should be closed;
  • a finished tournament exports as the same TRF file, which arbiter software and federations accept.

The same caveat as above: following the Dutch rules is not a FIDE certificate. Vibe Chess has not gone through SPP endorsement, and for rated events that has to be taken into account. For club, school, bar and company tournaments there is no restriction - and all of it is free - how to run an event in it.

Building it yourself

Prebuilt binaries live in the repository's releases section, but building from source is straightforward. You need a C++ compiler and make:

  • clone the repository: git clone https://github.com/BieremaBoyzProgramming/bbpPairings.git
  • build it: make - producing an executable called bbpPairings.exe (that name on Linux too);
  • generate a test tournament: ./bbpPairings.exe --dutch -g -o test.trf
  • get a pairing: ./bbpPairings.exe --dutch test.trf -p out.txt

If you simply want to run a tournament rather than work through a build, that path has been walked for you: the engine is already embedded in the app, and the organizer only creates the event and presses buttons.

FIDE-rules pairings with nothing to install

bbpPairings is already embedded in the Vibe Chess app: create the event, open registration, press start, and the same engine pairs every round. Free, with no limit on tournaments or players.

Frequently asked questions about bbpPairings

What is bbpPairings?

An open-source Swiss pairing engine written in C++ by Bierema Boyz Programming. It takes a file with the tournament history in TRF format and returns the next round's pairings under the FIDE Dutch rules. It is not a tournament manager: it has no interface, no player database and no standings.

Is bbpPairings free?

Yes. The source is open under the Apache 2.0 licence: the engine may be used, studied and embedded freely, including in commercial software.

Is bbpPairings endorsed by FIDE?

It is not on the official list of FIDE-endorsed programs: certification is granted to tournament managers, and JaVaFo is treated as the reference implementation of Dutch. bbpPairings implements the same FIDE rules, and its author states that the Burstein implementation is incomplete and unendorsed. For club and amateur events that is no obstacle; for FIDE-rated events check the requirements with your federation.

Which pairing systems does it support?

Two Swiss systems: Dutch (the main one, following FIDE handbook section C.04.3) and Burstein (secondary, implementing the previous edition with known shortcomings). Round robins need no engine - their schedule comes from the Berger tables.

What is the TRF format?

The FIDE tournament data exchange format, also called the Krause format. A text file with a strictly positional layout: line 001 holds a player's details, score and round history - opponent, colour and result for each game. The same file is accepted by arbiter software and federations when submitting an event.

Why did the engine refuse to pair a round?

Most likely it returned code 1 - no valid pairing exists. A Swiss cannot pair the same two players twice, so with N players there are no opponents left after N-1 rounds. That is not a program failure but a signal that the rounds have run out.

Where is bbpPairings used?

In Lichess Swiss tournaments (a fork with the Fast Swiss system), in the SwissSys tournament manager, in the Vibe Chess app and in a great many home-built services - the open licence and simple file interface make it easy to embed.

Which version is current?

6.0.0, released on 1 February 2026, the day the new edition of the Dutch rules took effect. Earlier versions: 5.0.1 (2023), 5.0.0 (2022), 4.1.0 (2017).

Which engine does Vibe Chess use?

bbpPairings 6.0.0 with the --dutch flag. The app assembles a TRF from the tournament history and the engine returns the round's pairs. The service has no FIDE SPP endorsement, while the Dutch rules themselves are followed.

The tournament app

Create your own tournament for free

The Vibe Chess app opens from a link and needs no installation. Setting up a tournament takes a minute: pick the system, set the date, the venue and the time control - the app handles the rest.

Swiss system

for a large field: opponents are matched by score, you choose the number of rounds

Round robin

for a small circle: everyone plays everyone, the round count follows from the field

Free meetup

no rounds, no pairings: players sign up and pick opponents at the table

How the tournament runs
  1. 1Create the event and share the link - sign-up opens right away
  2. 2Press start and the app announces the first pairing
  3. 3Enter results, the table with points and Buchholz updates itself
  4. 4At the end - final standings and a TRF report in the FIDE data exchange format

More than a bot: the app, FIDE rules and a TRF report

  • The app. Besides the bot there is an app - inside Telegram and simply at vibechess.ru/app: what is on in your city, the player list, a live table, the current round, your profile and game history - everything that is awkward to read as chat messages.
  • Pairings by FIDE rules. Pairings are computed by bbpPairings, an open-source engine implementing the Dutch system: score groups, floats on an odd field, colour alternation, no rematches and no two byes in a row.
  • A TRF report. A finished tournament exports as a single file in the FIDE data exchange format - the one arbiter software and federations accept. Your profile stores the FIDE ID, national federation code, title, sex and date of birth for it.
  • Free. All of the above, with no subscriptions, paid plans or limits on the number of tournaments and players.

Full overview

Missing a feature? Message the developers

The bot is constantly improved based on real tournaments. If you need a feature that isn't there yet, message the developers right inside the bot with the /support command. Many features appeared exactly because organizers asked for them, and useful ideas get added quickly.

What to read next

The reference implementation - JaVaFo. The file it reads - the TRF format. The system itself - Swiss or round robin. Standings - the Buchholz score.