- Rename app/binary/app-id to nomines (io.github.bemagri.nomines), config dir moves to ~/.config/nomines with legacy path fallback - Add persistent best-time leaderboard (Glib::KeyFile) - Theme-aware board following system light/dark preference - Beveled 3D cells, confetti win animation, keyboard shortcuts, right-click chording, per-difficulty window sizing - Add AppStream metainfo, validate desktop file and metainfo via meson tests - Fix license metadata to GPL-3.0-or-later and real homepage
3.9 KiB
3.9 KiB
AGENTS.md
GTK4/gtkmm4 Minesweeper clone ("NoMines") in C++20, built with Meson. ~800 lines total.
Build & run
meson setup build # or reuse existing build/
meson compile -C build
./build/nomines
- Dev deps come from the Nix flake via direnv (
.envrcusesuse flake);nix developworks standalone. - Alternative:
nix build/nix run. - No unit tests; two optional release-validation tests (desktop file + AppStream metainfo via
desktop-file-validate/appstreamcli) are auto-added when those tools exist. build/compile_commands.jsonexists for clangd (it's gitignored, regenerate withmeson setup --wipe buildif stale).- WARNING: flake builds only see git-tracked files. New source files must be
git added beforenix buildworks.
Architecture
src/minefield.*— pure game logic, no GTK:Minefield(board state, flag counting, chording),Cellbitfield,GameDifficultypresets,GameStateenum.src/board_widget.*—Gtk::DrawingArea; all rendering is hand-drawn Cairo primitives (draw_cell/draw_digit/draw_flag/draw_bomb), input viaGtk::GestureClick+EventControllerMotion, confetti particle animation on win (frame-rate independent viaGdk::FrameClock).src/window.*—Gtk::ApplicationWindowwith HeaderBar, difficulty popover (radio-styleCheckButtons), leaderboard popover, timer; owns theshared_ptr<Minefield>and swaps it on new game. Keyboard shortcuts viaGtk::EventControllerKey(R/Ctrl+N new game, 1-4 difficulties, L leaderboard).src/leaderboard.*— persistent best times per difficulty viaGlib::KeyFileat~/.config/nomines/leaderboard.ini(recorded on win, shown in a header-bar popover; falls back to the pre-1.0~/.config/minesweeper/path for migration). NOTE: uses the glibmm 2.80 refcountedKeyFile::create()API and gtkmm 4.14CheckButton(aWidget+Actionable, not aButton— usesignal_toggled()+get_active(), andset_group(CheckButton&)).- glibmm 2.80 quirk:
SignalProxy<R(T...)>::connect()(non-void return signals likesignal_key_pressed) requires theafterbool explicitly —connect(slot, false). Void signals default it to true. src/main.cpp— singleGtk::Application(io.github.bemagri.nomines);make_window_and_run<MainWindow>.
Release
- Version
1.0.0is stamped in FOUR places:meson.build,flake.nix,default.nix, and the<releases>entry inresources/io.github.bemagri.nomines.metainfo.xml. Bump all four together. - Release sanity:
nix build .(validates the flake),desktop-file-validate+appstreamcli validate --no-neton the resources (wired up as meson tests). - The metainfo screenshot URL points at
raw.githubusercontent.com/bemagri/nomines/main/...— it 404s until the repo is published; replace if the repo moves.
Gotchas
resources/gresource.xml+ thegnome.compile_resourcesstep inmeson.buildcompile unused code: the app never loads these SVGs/textures (theconfetti.pngis also unused). All art is Cairo-drawn. Don't extend the GResource to implement visual features; draw with Cairo instead.- README's feature list is mostly accurate but not trustworthy in detail; verify against code. (An older
leaderboard.txtCSV may linger in~/.config/minesweeper/from a previous experiment — the app now uses~/.config/nomines/leaderboard.ini.) - Code style: snake_case methods/fields, trailing
_on private members,#pragma once, nested-struct headers. C++20 stdlib only, no third-party libs beyond gtkmm/sigc++. - Board colors are theme-aware:
BoardWidget::resolve_palette()maps GTK CSS named colors (theme_bg_color,theme_base_color, ...) to a light/dark palette each draw. Don't hardcode light grays indraw_*helpers; thread thePalettethrough instead. - Meson source list is explicit in
meson.build— new source files must be added there. .direnv/andbuild*/are gitignored; flake builds require files to be committed/tracked.