Skip to content

Plugin Development

Open-Lotto Wiki edited this page Jun 5, 2026 · 1 revision

Plugin Development

Open-Lotto games are implemented as dynamically loaded shared libraries (.so). Adding a new game requires writing a single C file and one CMake block — no changes to the core engine.


Plugin ABI

Every plugin must export exactly three C symbols (defined in include/lottery_plugin.h):

/* Return static game configuration (number ranges and pick counts). */
const LotteryInfo *plugin_get_info(void);

/* Return a human-readable display name for the game. */
const char *plugin_get_name(void);

/* Perform one draw and write the result to *out.
 * cb is called at each DrawEvent milestone; may be NULL in non-GUI mode. */
void plugin_draw(LotteryResult *out, draw_event_callback cb);

LotteryInfo

typedef struct {
    int main_count;   /* how many main numbers to pick */
    int main_min;     /* lowest possible main number (inclusive) */
    int main_max;     /* highest possible main number (inclusive) */
    int extra_count;  /* how many extra numbers (0 = none) */
    int extra_min;    /* lowest extra number (inclusive) */
    int extra_max;    /* highest extra number (inclusive) */
} LotteryInfo;

LotteryResult

#define MAX_MAIN_NUMBERS  7
#define MAX_EXTRA_NUMBERS 3

typedef struct {
    int main_numbers[MAX_MAIN_NUMBERS];
    int main_count;
    int extra_numbers[MAX_EXTRA_NUMBERS];
    int extra_count;
} LotteryResult;

Step-by-Step: Adding a Game

1. Create the plugin source file

Create plugins/powerball.c:

/* SPDX-License-Identifier: MIT */
#include "combogen.h"
#include "lottery_plugin.h"

/* US Powerball: 5 main numbers from 1-69, 1 Powerball from 1-26 */
static const LotteryInfo INFO = {
    .main_count  = 5,
    .main_min    = 1,
    .main_max    = 69,
    .extra_count = 1,
    .extra_min   = 1,
    .extra_max   = 26,
};

const LotteryInfo *plugin_get_info(void) { return &INFO; }

const char *plugin_get_name(void) { return "PowerBall"; }

void plugin_draw(LotteryResult *out, draw_event_callback cb)
{
    generate_draw(INFO.main_count, INFO.main_min, INFO.main_max,
                  INFO.extra_count, INFO.extra_min, INFO.extra_max,
                  out, cb);
}

2. Register the plugin in CMakeLists.txt

Add the following block next to the existing plugin targets:

add_library(powerball SHARED plugins/powerball.c)
target_link_libraries(powerball PRIVATE m)
set_target_properties(powerball PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
)

3. Build and run

cmake --build build -j
./build/open-lotto --game powerball

Expected output:

PowerBall: 7 14 28 41 63 | PB: 18

Games Without Extra Numbers

Set extra_count = 0; the extra_min / extra_max values are ignored.

static const LotteryInfo INFO = {
    .main_count  = 6,
    .main_min    = 1,
    .main_max    = 42,
    .extra_count = 0,
    .extra_min   = 0,  /* ignored */
    .extra_max   = 0,  /* ignored */
};

Constraints

Constraint Limit
Maximum main numbers per draw 7 (MAX_MAIN_NUMBERS)
Maximum extra numbers per draw 3 (MAX_EXTRA_NUMBERS)
Extra range must be ≥ extra count validated at runtime
Main range must be ≥ main count validated at runtime

Common Lottery Configurations

Game main_count main_min main_max extra_count extra_min extra_max
Lotto 6aus49 6 1 49 1 0 9
Eurojackpot 5 1 50 2 1 12
EuroMillions 5 1 50 2 1 12
US Powerball 5 1 69 1 1 26
US Mega Millions 5 1 70 1 1 25
UK National Lottery 6 1 59 0 0 0

The draw_event_callback

The callback is invoked by generate_draw() at key moments in the draw so that GUI modes can animate each pick:

typedef enum {
    DRAW_EVENT_MAIN_NUMBER,   /* a main number was drawn */
    DRAW_EVENT_EXTRA_NUMBER,  /* an extra number was drawn */
    DRAW_EVENT_COMPLETE,      /* all numbers drawn */
} DrawEvent;

typedef void (*draw_event_callback)(DrawEvent event, const LotteryResult *result);

Pass NULL for cb when animation is not needed (e.g., batch/export mode).