diff --git a/Makefile b/Makefile index 0a290d1..792afc7 100644 --- a/Makefile +++ b/Makefile @@ -12,13 +12,16 @@ SRCTAR = $(PKG)-$(VERSION)-src.tar.gz DIST = dist BATCH = $(EMACS) -Q --batch -L . MANUAL = doc/card-games.texi +VERTEXI = doc/version.texi INFO = doc/card-games.info +IMAGES = doc/images/klondike.png doc/images/hearts.png MAKEINFO ?= makeinfo TEXI2PDF ?= texi2pdf -EXTRA = README.org $(PKGDESC) $(MANUAL) +README = README.md +EXTRA = README.org $(README) $(PKGDESC) $(MANUAL) $(VERTEXI) $(IMAGES) .PHONY: all compile test clean distclean checkdoc lint package tarball elpa release help \ - info html pdf docclean + info info-emacs html pdf docclean version readme hooks help: @echo "card-games $(VERSION) -- make targets:" @@ -26,7 +29,11 @@ help: @echo " test run the ERT test suite" @echo " checkdoc run checkdoc on all sources" @echo " lint run package-lint (if installed)" - @echo " info build the Info manual ($(INFO))" + @echo " version regenerate $(VERTEXI) from VERSION" + @echo " readme export README.org -> README.md (Emacs batch)" + @echo " hooks install the git pre-commit hook" + @echo " info build the Info manual ($(INFO)) with makeinfo" + @echo " info-emacs build the Info manual with Emacs alone (fallback)" @echo " html build the one-file HTML manual" @echo " pdf build the PDF manual (needs a TeX installation)" @echo " package build the installable package tarball ($(TAR))" @@ -74,8 +81,8 @@ elpa: tarball # Source snapshot for a GitHub release. Archive an explicit file list # (not ".") so the growing output tarball and editor lock files are never # read mid-write -- which is what caused "tar: .: file changed as we read it". -SRCFILES = $(EL) $(EXTRA) Makefile .gitignore test -release: distclean test tarball +SRCFILES = $(EL) $(EXTRA) build.el hooks Makefile .gitignore test +release: distclean version readme test tarball rm -f $(SRCTAR) tar --transform 's,^,$(TARDIR)/,' \ --exclude='*.elc' --exclude='*.tar' --exclude='*.tar.gz' \ @@ -84,15 +91,46 @@ release: distclean test tarball @echo "Built $(SRCTAR) and $(TAR) for release $(VERSION)" # Documentation. The Texinfo source lives in doc/; the Info manual is -# built from it with makeinfo. +# built from it with makeinfo. doc/version.texi carries the version and +# is committed; `make version' regenerates it from VERSION (run at release). +version: + @printf '@set VERSION %s\n@set UPDATED %s\n@set YEAR %s\n' \ + "$(VERSION)" "$$(date '+%-d %B %Y')" "$$(date +%Y)" > $(VERTEXI) + @echo "Wrote $(VERTEXI) (VERSION $(VERSION))" + +# README: Org is the source; GitHub and MELPA render Markdown better than +# Org, so we export README.org -> README.md with Emacs batch (ox-md). The +# git pre-commit hook (make hooks) keeps README.md in step automatically. +readme: $(README) +$(README): README.org build.el + $(BATCH) -l build.el + +# Install the pre-commit hook into this checkout's .git/hooks. +hooks: + @if [ -d .git ]; then \ + cp hooks/pre-commit .git/hooks/pre-commit && \ + chmod +x .git/hooks/pre-commit && \ + echo "Installed .git/hooks/pre-commit"; \ + else \ + echo "No .git directory here; skipping hook install."; \ + fi + info: $(INFO) -$(INFO): $(MANUAL) +$(INFO): $(MANUAL) $(VERTEXI) $(MAKEINFO) -o $@ $(MANUAL) -html: $(MANUAL) +# Fallback: build the Info manual with Emacs alone (no makeinfo needed). +# Handy on Windows/MSYS2 where Emacs is present but texinfo may not be. +# The native formatter is lower fidelity than makeinfo, so `make info' +# stays the default; this is only for a makeinfo-less environment. +info-emacs: $(MANUAL) $(VERTEXI) + cd doc && $(EMACS) -Q --batch --eval "(require 'texinfmt)" \ + -f batch-texinfo-format card-games.texi + +html: $(MANUAL) $(VERTEXI) $(MAKEINFO) --html --no-split -o doc/card-games.html $(MANUAL) -pdf: $(MANUAL) +pdf: $(MANUAL) $(VERTEXI) cd doc && $(TEXI2PDF) -q card-games.texi docclean: diff --git a/README.md b/README.md new file mode 100644 index 0000000..35ef522 --- /dev/null +++ b/README.md @@ -0,0 +1,306 @@ +Card games for Emacs: about thirty of them, from Klondike and FreeCell +to Hearts, 500, Gin, Cribbage, and two-player Russian Bank against the +computer. Every game plays with the keyboard everywhere and with the +mouse on a graphical display. + +![img](doc/images/klondike.png) + +On a graphical display the cards are drawn as SVG; in a terminal they +fall back to UNICODE glyphs (customize `card-game-symbols`). You can +switch how every game is drawn from the menu – `text` (UNICODE), +`svg` (drawn cards), or `full` (a full-window SVG table) – and dial the +computer opponents between `easy`, `normal`, and `hard`. + +A full Info manual ships with the package: after installing, `C-h i` and +choose **Card Games**, or `M-x info RET (card-games) RET`. + + +# Games + +To open the game menu type `M-x card-game`, or start a game directly +with its command. From the menu you can also switch the card treatment +(text / SVG / full-window) and the AI difficulty. + + +## Trick-taking + +- `cg-bid` – 500 (Bid). Win the auction, name the trump suit, then take + tricks with your partner to reach 500 points before the opposing pair. + Also playable live over the network (`M-x cg-bid-host` / `cg-bid-join`). +- `cg-hearts` – Hearts. Avoid taking hearts and the Queen of Spades, or + take them all to "shoot the moon"; lowest score loses. +- `cg-spades` – Spades. Partnership bidding to 500; spades are always + trump. Make your side's combined bid, mind the bags, dare a nil. +- `cg-whist` – Whist. Trump is the turned card, there is no bidding; + score one point for each trick past the book of six. +- `cg-ohhell` – Oh Hell. The hand shrinks each round; bid the exact + number of tricks you will take, no more and no fewer. + + +## Solitaire + +- `cg-montana` – Montana (also called Gaps). Each row is anchored by a + Two and built upward in one suit, 2 through King; slide cards into the + gaps until all four rows are sorted. +- `cg-gaps` – an alias for `cg-montana`. +- `cg-hells-half-acre` – the build-down variant: each row is anchored by + a King and built downward, King through 2. +- `cg-klondike` – Klondike, the classic "Solitaire": build the four + foundations up by suit from the Ace. +- `cg-freecell` – FreeCell: every card in view, four free cells, a game + of nearly pure skill. +- `cg-spider` – Spider (two decks): build down regardless of suit, but + only same-suit runs move; clear eight King-to-Ace runs. +- `cg-yukon` – Yukon: Klondike's layout dealt mostly face up, with any + buried group movable and no stock. +- `cg-canfield` – Canfield: a 13-card reserve and a foundation base rank + set by the deal; foundations wrap King to Ace. +- `cg-forty-thieves` – Forty Thieves: two decks, ten columns, eight + foundations, build down by suit, and no second pass through the stock. +- `cg-scorpion` – Scorpion: build down by suit and free any buried group + to assemble four King-to-Ace runs. +- `cg-golf` – Golf: clear the layout by playing exposed cards one rank + above or below the waste top. +- `cg-tripeaks` – TriPeaks: the same, on three overlapping peaks, with + Ace-King wrapping for long chains. +- `cg-pyramid` – Pyramid: remove pairs of exposed cards whose ranks sum + to thirteen; Kings go alone. + + +## Shedding and climbing + +- `cg-eights` – Crazy Eights. Match the suit or rank of the discard; + eights are wild and let you name the next suit. +- `cg-president` – President (Scum). Climb: play one to four of a rank, + beat it or pass; first out rules, last out scrubs, and the roles trade + cards on the next deal. + + +## Rummy + +- `cg-gin` – Gin Rummy. A two-handed duel: draw or take the discard, + build sets and runs, and knock once your deadwood is ten or less, or go + gin with none; your opponent then lays off and may undercut you. First + to 100 wins. +- `cg-rummy-basic` – Rummy. Meld sets and runs onto the table and lay + cards off onto them; empty your hand to go out and score the cards left + in the other hands. +- `cg-rum500` – Rummy 500. As above, but you score the cards you lay + down and lose the cards left in your hand; first past 500 wins. Take a + buried discard card with `T`: you take it and every card above it, and + meld the chosen card at once. +- `cg-handfoot` – Hand & Foot. A partnership Canasta cousin: play a hand + and then a foot, build books of a rank with Twos and Jokers wild, and go + out once your side has completed two of them. Each round opens with a + rising go-down minimum (50, 90, 120, 150); red threes are bonus cards; + and you can pick up the discard pile (`p`) by melding its top card with + two matching naturals. + + +## Matching + +- `cg-go-fish` – Go Fish. Ask another player for a rank you hold; + collect all four to lay down a book, and make the most books. +- `cg-old-maid` – Old Maid. One Queen is set aside; discard pairs and + draw blind from your neighbour, and do not be left with the odd Queen. + + +## Pegging + +- `cg-cribbage` – Cribbage. Lay two cards to the crib, cut a starter, + peg toward 31, then count fifteens, pairs, runs, flushes, and his nobs. + Two-handed to 121. + + +## Capturing + +- `cg-scopa` – Scopa. A 40-card deck; capture table cards by value and + sweep the board for a scopa. Score cards, coins, the sette bello, and + primiera to 11. +- `cg-casino` – Casino. The full deck; capture by pairs and sums and + score cards, spades, the casinos, and aces to 21. + + +## More trick-taking + +- `cg-euchre` – Euchre. A 24-card deck with the two bowers; order up or + call trump and take three of five tricks. Partnership to 10. +- `cg-pitch` – Auction Pitch. Bid for the pitch; your first lead sets + trump. Score High, Low, Jack, and Game; first to 7. +- `cg-briscola` – Briscola. A fixed trump turned from the deal and no + obligation to follow suit; capture the Aces and Threes. Partnership to + 61 of the 120 points. + + +## Climbing patience + +- `cg-spite` – Spite & Malice. Race the computer to empty your goal + pile onto shared centre piles that build Ace to Queen; Kings are wild. + + +## Bridge + +- `cg-bridge` – Contract Bridge. A full auction (bids, pass, double, + redouble), play with the dummy exposed, and classic rubber scoring with + vulnerability. You are South; when you declare you play the dummy too. + The bidding AI is a small natural system, sensible but no expert. + + +## Two-player patience + +- `cg-russian-bank` / `cg-crapette` – Russian Bank (Crapette). A race + against the computer: build the eight shared foundations up by suit, + build the shared houses down in alternating colour, and empty your + reserve to win. Load your cards onto your opponent's piles when the + rank and suit line up, mind the "stop" rule that ends your turn if you + skip a foundation play, and sequence house-to-house moves within the + free houses (`[` / `]` choose how many cards of a run to drop on an + empty house). The opponent plays all three difficulty levels. + + +# TODO + +- [X] make the suit symbols customizable (`cg-symbols`) and obey them +- [X] a Texinfo manual +- [ ] finish `checkdoc` docstrings across the per-game files + (the shared engine files are clean; `make compile` is warning-free) +- [ ] renderer "skins": let games subclass the display components (text, + SVG, full-window SVG) +- [X] a manual card-size control for the full-window SVG UI +- [ ] more games + + +# Install + + +## From the package tarball + + make package # builds card-games-1.0.90.tar + +Then in Emacs: `M-x package-install-file RET card-games-1.0.90.tar`. + + +## With `use-package` + +Once the package is on your `load-path` (installed from the tarball or an +ELPA archive), the whole collection loads from the single `card-games` +feature: + + (use-package card-games + :commands (card-game cg-klondike cg-bid cg-hearts cg-gin cg-crapette)) + +Then `M-x card-game` for the menu. + + +## From a local ELPA archive + + make elpa # builds dist/ (archive-contents + tar) + + (add-to-list 'package-archives '("cg" . "/path/to/dist/")) + (package-refresh-contents) + (package-install 'card-games) + + +## Manually + +Put the `cg-*.el` and `card-games.el` files on your `load-path` and +`(require 'card-games)`. + + +# Manual + +A complete Info manual is included. After installing, `C-h i` and pick +**Card Games**, or `M-x info RET (card-games) RET`. To build it from a +source checkout: + + make info # builds doc/card-games.info with makeinfo + +The manual text is licensed CC-BY-4.0; the code is GPL-3.0-or-later. + + +# Playing + +Every game works with the keyboard everywhere and with the mouse on a +graphical display. + +- 500: `b` bid, `p` pass, arrows + `RET` to play (or click a card), + `n` next hand / new game, `?` help. +- Gaps: arrows to move (or `hjkl` when `cg-keys` is `classic`), `RET` to + fill a gap (or click it), `r` redeal, `u` undo, `n` new, `?` help. +- Klondike / FreeCell / Spider / Yukon: arrows move between piles, `RET` + picks up a movable run and drops it, `f` sends a card to a foundation, + `a` auto-plays everything it can, `u` undo, `n` new, `?` help. On the + stock pile, `RET` deals or recycles. +- Hearts / Spades: arrows choose a card, `RET` plays it (in Hearts, `RET` + marks a card to pass and `p` sends the three), `n` new match, `?` help. +- Crazy Eights: arrows choose, `RET` plays, `d` draws, `x` passes, `n` + new deal, `?` help. + +On a graphical display, `v` toggles the full-window SVG table. A +**Card size** slider (and the `+` / `-` / `0` keys) resizes the cards, and +in 500 the `? Help / Rules` button explains play. Every game accepts the +mouse: click cards, board slots, buttons, and the slider. + +![img](doc/images/hearts.png) + + +# Testing + +This is a 1.0.90 pre-test snapshot. To try it: + +1. `make compile && make test` – should be warning-free and all green. +2. `M-x card-game` opens the menu, or jump straight in, e.g. + `M-x cg-klondike`, `M-x cg-bid` (500), `M-x cg-gin`, `M-x cg-handfoot`. +3. On a graphical display, press `v` in 500 for the full-window SVG + table and play entirely with the mouse: click a bid, click five kitty + cards and the **Discard** button, click cards to play, move the **Card + size** slider, and open `? Help / Rules`. + +Feedback most wanted: anything a mouse-only player who is new to Emacs +finds confusing or unreachable, rules bugs, and rendering glitches. + + +# Customization + +`M-x customize-group RET cg-svg` and `RET card-games`: + +- `cg-ai-level` – how hard the computer plays: `easy`, `normal`, or + `hard` (also on the `M-x card-game` menu, or `M-x + card-games-set-ai-level`). +- `card-games-treatment` – how the games are drawn: `text`, `svg`, or + `full` (also on the menu, or `M-x card-games-set-treatment`). +- `cg-svg-theme-colors` – derive the highlight ring and card backs + from your theme (on by default). +- `cg-svg-highlight-color` – the cursor/selection ring (gold by default). +- `cg-bid-felt-color` – the 500 table felt. +- `cg-svg-card-width`, `cg-svg-card-height`, `cg-svg-card-shadow`, + `cg-svg-font-family` – card appearance. +- `cg-svg-card-back` – the card-back design: `dots`, `rings`, `solid`, + `lattice`, `waves`, `diamond`, an Emacs-logo back (`emacs`, + `emacs-classic`, `gnu`, `splash`), or `random` (the default – picks + one for the session; `M-x cg-svg-shuffle-card-back` rolls a new one). +- `cg-svg-emacs-logo` – the emblem on the full-window table: + `modern` (default), `classic`, `gnu`, `splash`, `drawn`, or `none`. +- `cg-symbols` – the Unicode suit glyphs (and the joker) drawn on cards. +- `cg-svg-four-color` – draw a four-colour deck (clubs green, diamonds + blue-purple). +- `cg-keys` – `emacs` (default) or `classic` (adds vi-style `hjkl` and + `SPC`). +- `cg-bid-animate`, `cg-bid-ai-delay`, `cg-bid-trick-pause` – pace the + 500 AI so play is watchable and completed tricks linger. +- `M-x card-games-set-theme` – apply a preset (classic, dark, contrast). + + +# Development + + make compile # byte-compile (should be warning-free) + make test # run the ERT suite + make checkdoc # documentation lint + make release # clean + test + package + source tarball + + +# License + +GPL-3.0-or-later. See the file headers; add a COPYING file with the +full GPLv3 text for distribution. + diff --git a/README.org b/README.org index 9a939c7..6a18be2 100644 --- a/README.org +++ b/README.org @@ -1,16 +1,28 @@ #+TITLE: card-games -- Play card games in Emacs #+AUTHOR: Corwin Brust +#+OPTIONS: toc:nil -Card games for Emacs. +Card games for Emacs: about thirty of them, from Klondike and FreeCell +to Hearts, 500, Gin, Cribbage, and two-player Russian Bank against the +computer. Every game plays with the keyboard everywhere and with the +mouse on a graphical display. -Renders SVG by default when ~display-graphic-p~ is t and rsvg is -available. The default (UNICODE) symbols maybe customized by -configuring ~card-game-symbols~. +[[file:doc/images/klondike.png]] + +On a graphical display the cards are drawn as SVG; in a terminal they +fall back to UNICODE glyphs (customize ~card-game-symbols~). You can +switch how every game is drawn from the menu -- ~text~ (UNICODE), +~svg~ (drawn cards), or ~full~ (a full-window SVG table) -- and dial the +computer opponents between ~easy~, ~normal~, and ~hard~. + +A full Info manual ships with the package: after installing, ~C-h i~ and +choose *Card Games*, or ~M-x info RET (card-games) RET~. * Games To open the game menu type ~M-x card-game~, or start a game directly -with its command. +with its command. From the menu you can also switch the card treatment +(text / SVG / full-window) and the AI difficulty. ** Trick-taking - ~cg-bid~ -- 500 (Bid). Win the auction, name the trump suit, then take @@ -116,9 +128,19 @@ with its command. vulnerability. You are South; when you declare you play the dummy too. The bidding AI is a small natural system, sensible but no expert. +** Two-player patience +- ~cg-russian-bank~ / ~cg-crapette~ -- Russian Bank (Crapette). A race + against the computer: build the eight shared foundations up by suit, + build the shared houses down in alternating colour, and empty your + reserve to win. Load your cards onto your opponent's piles when the + rank and suit line up, mind the "stop" rule that ends your turn if you + skip a foundation play, and sequence house-to-house moves within the + free houses (~[~ / ~]~ choose how many cards of a run to drop on an + empty house). The opponent plays all three difficulty levels. + * TODO - [X] make the suit symbols customizable (~cg-symbols~) and obey them -- [ ] a Texinfo manual +- [X] a Texinfo manual - [ ] finish ~checkdoc~ docstrings across the per-game files (the shared engine files are clean; ~make compile~ is warning-free) - [ ] renderer "skins": let games subclass the display components (text, @@ -133,6 +155,16 @@ make package # builds card-games-1.0.90.tar #+end_src Then in Emacs: ~M-x package-install-file RET card-games-1.0.90.tar~. +** With ~use-package~ +Once the package is on your ~load-path~ (installed from the tarball or an +ELPA archive), the whole collection loads from the single ~card-games~ +feature: +#+begin_src emacs-lisp +(use-package card-games + :commands (card-game cg-klondike cg-bid cg-hearts cg-gin cg-crapette)) +#+end_src +Then ~M-x card-game~ for the menu. + ** From a local ELPA archive #+begin_src make elpa # builds dist/ (archive-contents + tar) @@ -147,8 +179,17 @@ make elpa # builds dist/ (archive-contents + tar) Put the ~cg-*.el~ and ~card-games.el~ files on your ~load-path~ and ~(require 'card-games)~. +* Manual +A complete Info manual is included. After installing, ~C-h i~ and pick +*Card Games*, or ~M-x info RET (card-games) RET~. To build it from a +source checkout: +#+begin_src +make info # builds doc/card-games.info with makeinfo +#+end_src +The manual text is licensed CC-BY-4.0; the code is GPL-3.0-or-later. + * Playing -Both games work with the keyboard everywhere and with the mouse on a +Every game works with the keyboard everywhere and with the mouse on a graphical display. - 500: ~b~ bid, ~p~ pass, arrows + ~RET~ to play (or click a card), @@ -169,6 +210,8 @@ On a graphical display, ~v~ toggles the full-window SVG table. A in 500 the ~? Help / Rules~ button explains play. Every game accepts the mouse: click cards, board slots, buttons, and the slider. +[[file:doc/images/hearts.png]] + * Testing This is a 1.0.90 pre-test snapshot. To try it: 1. ~make compile && make test~ -- should be warning-free and all green. @@ -184,12 +227,23 @@ finds confusing or unreachable, rules bugs, and rendering glitches. * Customization ~M-x customize-group RET cg-svg~ and ~RET card-games~: +- ~cg-ai-level~ -- how hard the computer plays: ~easy~, ~normal~, or + ~hard~ (also on the ~M-x card-game~ menu, or ~M-x + card-games-set-ai-level~). +- ~card-games-treatment~ -- how the games are drawn: ~text~, ~svg~, or + ~full~ (also on the menu, or ~M-x card-games-set-treatment~). - ~cg-svg-theme-colors~ -- derive the highlight ring and card backs from your theme (on by default). +- ~cg-svg-highlight-color~ -- the cursor/selection ring (gold by default). - ~cg-bid-felt-color~ -- the 500 table felt. - ~cg-svg-card-width~, ~cg-svg-card-height~, ~cg-svg-card-shadow~, ~cg-svg-font-family~ -- card appearance. -- ~cg-svg-card-back~ -- card-back pattern: dots, rings, or solid. +- ~cg-svg-card-back~ -- the card-back design: ~dots~, ~rings~, ~solid~, + ~lattice~, ~waves~, ~diamond~, an Emacs-logo back (~emacs~, + ~emacs-classic~, ~gnu~, ~splash~), or ~random~ (the default -- picks + one for the session; ~M-x cg-svg-shuffle-card-back~ rolls a new one). +- ~cg-svg-emacs-logo~ -- the emblem on the full-window table: + ~modern~ (default), ~classic~, ~gnu~, ~splash~, ~drawn~, or ~none~. - ~cg-symbols~ -- the Unicode suit glyphs (and the joker) drawn on cards. - ~cg-svg-four-color~ -- draw a four-colour deck (clubs green, diamonds blue-purple). diff --git a/build.el b/build.el new file mode 100644 index 0000000..3e90ead --- /dev/null +++ b/build.el @@ -0,0 +1,77 @@ +;;; build.el --- Batch Org -> Markdown export for card-games -*- lexical-binding: t; -*- + +;; Copyright (C) 2026 Corwin Brust +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: + +;; A very small Emacs-batch exporter. It renders the project's Org +;; sources to Markdown siblings (foo.org -> foo.md) using the built-in +;; `ox-md' backend, so GitHub and MELPA -- which render Markdown more +;; faithfully than Org -- can display them. +;; +;; Run it by hand, from the Makefile, or from the git pre-commit hook: +;; +;; emacs -Q --batch -l build.el +;; +;; By default it exports the files named in `build-org-files' (README.org). +;; Set the CARD_GAMES_ORG environment variable to a space-separated list +;; to override that, e.g. to export more documents. It never touches +;; known-games.org (an internal research list) unless you ask for it. + +;;; Code: + +(require 'org) +(require 'ox-md) + +;; Keep batch mode from blocking on prompts. +(setq org-confirm-babel-evaluate nil + org-export-show-temporary-export-buffer nil + ;; A stray or not-yet-committed image link must never abort the run. + org-export-with-broken-links 'mark + make-backup-files nil) + +(defvar build-org-files '("README.org") + "Default list of Org files to export to Markdown. +Overridden by the CARD_GAMES_ORG environment variable when set.") + +(defvar build-inhibit-run nil + "When non-nil, loading build.el defines helpers but does not export. +ERT or an interactive session can bind this to exercise the helpers.") + +(defun build--targets () + "Return the list of Org files to export. +Honours the CARD_GAMES_ORG environment variable; falls back to +`build-org-files'." + (let ((env (getenv "CARD_GAMES_ORG"))) + (if (and env (not (string-empty-p (string-trim env)))) + (split-string (string-trim env) "[ \t\n]+" t) + build-org-files))) + +(defun build--export-one (orgfile) + "Export ORGFILE to a Markdown sibling. +Log the outcome; never signal, so one bad file cannot abort the run." + (cond + ((not (file-readable-p orgfile)) + (message "build: SKIP %s (not readable)" orgfile)) + (t + (message "build: exporting %s -> markdown" orgfile) + (with-current-buffer (find-file-noselect orgfile) + (condition-case err + (let ((out (org-md-export-to-markdown))) + (message "build: wrote %s" out)) + (error + (message "build: ERROR exporting %s: %s" + orgfile (error-message-string err)))))))) + +(defun build--run () + "Export every file in `build--targets' to Markdown." + (dolist (orgfile (build--targets)) + (build--export-one orgfile)) + (message "build: done")) + +(unless (bound-and-true-p build-inhibit-run) + (build--run)) + +(provide 'build) +;;; build.el ends here diff --git a/doc/card-games.texi b/doc/card-games.texi index af282cb..17af0ed 100644 --- a/doc/card-games.texi +++ b/doc/card-games.texi @@ -8,8 +8,7 @@ @syncodeindex fn cp @c %**end of header -@set VERSION 1.0.90 -@set YEAR 2026 +@include version.texi @copying This manual is for Card Games for Emacs (version @value{VERSION}), an @@ -81,6 +80,10 @@ Card Games for Emacs is a collection of more than thirty card games --- solitaires, two-player games, and four-handed partnership games --- played entirely inside GNU Emacs. +@ifnotinfo +@center @image{images/klondike, , , Klondike solitaire in Emacs, png} +@end ifnotinfo + Every game draws itself two ways. In a terminal it uses plain UNICODE text, so it works anywhere Emacs runs, including over @command{ssh} and on a phone. On a graphical display it draws proper SVG cards, with a @@ -599,6 +602,10 @@ the highest card (or the highest trump) wins it. You sit South; the other three seats are computer players, and for the partnership games North is your partner. +@ifnotinfo +@center @image{images/hearts, , , A hand of Hearts, png} +@end ifnotinfo + @cindex trick games, controls Most of them share these controls: diff --git a/doc/images/hearts.png b/doc/images/hearts.png new file mode 100644 index 0000000..e9f7c18 Binary files /dev/null and b/doc/images/hearts.png differ diff --git a/doc/images/klondike.png b/doc/images/klondike.png new file mode 100644 index 0000000..fdfb195 Binary files /dev/null and b/doc/images/klondike.png differ diff --git a/doc/version.texi b/doc/version.texi new file mode 100644 index 0000000..f78634c --- /dev/null +++ b/doc/version.texi @@ -0,0 +1,3 @@ +@set VERSION 1.0.90 +@set UPDATED 1 July 2026 +@set YEAR 2026 diff --git a/hooks/pre-commit b/hooks/pre-commit new file mode 100644 index 0000000..bf5662b --- /dev/null +++ b/hooks/pre-commit @@ -0,0 +1,37 @@ +#!/usr/bin/env sh +# hooks/pre-commit -- regenerate README.md from README.org on commit. +# +# When README.org (or build.el) is part of the commit, re-run the batch +# Org -> Markdown export and stage the refreshed README.md so it travels +# in the same commit. GitHub and MELPA render Markdown better than Org. +# +# Lightweight by design: no sentinel file, no post-commit --amend. If +# nothing relevant changed, the hook exits immediately. +# +# Install: make hooks (or: ln -s ../../hooks/pre-commit .git/hooks/pre-commit) +# +# Set EMACS in the environment if the Emacs binary is not named "emacs" +# on the PATH git sees (common on Windows/MSYS2). + +set -e + +REPO_ROOT="$(git rev-parse --show-toplevel)" +cd "$REPO_ROOT" + +# Only act when README.org or the exporter itself is staged. +if ! git diff --cached --name-only | grep -Eq '^(README\.org|build\.el)$'; then + exit 0 +fi + +EMACS_BIN="${EMACS:-emacs}" +if ! command -v "$EMACS_BIN" >/dev/null 2>&1; then + echo "pre-commit: WARNING: '$EMACS_BIN' not found; README.md not regenerated." >&2 + echo "pre-commit: set EMACS to your Emacs binary, or run 'make readme'." >&2 + exit 0 +fi + +echo "pre-commit: regenerating README.md from README.org" +"$EMACS_BIN" -Q --batch -l build.el + +git add README.md +exit 0