Render SVG card faces in the trick games and Bridge
Route cg-trick's shared render (the South hand and the current trick) through cg-svg-hand-svg, showing legal plays as hint rings; this covers Hearts, Spades, Whist, Oh Hell, Euchre, Pitch, and Briscola at once. Do the same in cg-bridge for the hand, the trick, and the exposed dummy. Plain-text rows remain the terminal/batch fallback. Suite still 109/109.
This commit is contained in:
parent
a464f1cfc4
commit
51eceb205e
2 changed files with 97 additions and 32 deletions
55
cg-bridge.el
55
cg-bridge.el
|
|
@ -46,6 +46,7 @@
|
|||
(require 'cl-lib)
|
||||
(require 'eieio)
|
||||
(require 'cg-core)
|
||||
(require 'cg-svg)
|
||||
|
||||
(defconst cg-bridge-ranks
|
||||
["2" "3" "4" "5" "6" "7" "8" "9" "10" "J" "Q" "K" "A"]
|
||||
|
|
@ -481,6 +482,24 @@ vulnerability, and TRICKS the declarer side's trick count. Keys:
|
|||
out))
|
||||
(if out (mapconcat #'identity (nreverse out) " ") "(no calls yet)")))
|
||||
|
||||
(defcustom cg-bridge-svg-cards t
|
||||
"When non-nil, draw cards as SVG images on a graphical display."
|
||||
:type 'boolean :group 'card-games)
|
||||
|
||||
(defun cg-bridge--spec (card)
|
||||
"Return the cg-svg display spec (RANK-STRING . SUIT) for CARD."
|
||||
(cons (aref cg-bridge-ranks (cdr card)) (car card)))
|
||||
|
||||
(cl-defun cg-bridge--svg-row (cards &key cursor hints)
|
||||
"Return a one-image SVG row for CARDS with CURSOR and HINTS indices."
|
||||
(propertize "*" 'display
|
||||
(cg-svg-image
|
||||
(cg-svg-hand-svg (mapcar #'cg-bridge--spec cards)
|
||||
:cursor cursor :hints hints
|
||||
:overlap (if (> (length cards) 11)
|
||||
(max 0 (- cg-svg-card-width 26)) 0))
|
||||
(cg-scale))))
|
||||
|
||||
(cl-defmethod cg-render ((game cg-bridge-game))
|
||||
"Return a propertized depiction of the Bridge GAME."
|
||||
(let* ((out '()) (phase (cg-get game :phase)) (cursor (cg-get game :cursor)))
|
||||
|
|
@ -511,16 +530,22 @@ vulnerability, and TRICKS the declarer side's trick count. Keys:
|
|||
(cg-get game :tricks))
|
||||
out)
|
||||
(when (and (cg-get game :exposed) (cg-get game :dummy))
|
||||
(push (format "\n Dummy (%s):\n%s"
|
||||
(aref cg-bridge-seat-names (cg-get game :dummy))
|
||||
(cg-bridge--hand-by-suit (cg-bridge--hand game (cg-get game :dummy))))
|
||||
out))
|
||||
(push (format "\n Dummy (%s):\n "
|
||||
(aref cg-bridge-seat-names (cg-get game :dummy))) out)
|
||||
(if (and cg-bridge-svg-cards (display-graphic-p))
|
||||
(push (cg-bridge--svg-row
|
||||
(cg-bridge--sort (cg-bridge--hand game (cg-get game :dummy)))) out)
|
||||
(push (cg-bridge--hand-by-suit (cg-bridge--hand game (cg-get game :dummy))) out)))
|
||||
(push "\n Trick: " out)
|
||||
(if (cg-get game :trick)
|
||||
(dolist (p (reverse (cg-get game :trick)))
|
||||
(cond
|
||||
((null (cg-get game :trick)) (push "(empty)" out))
|
||||
((and cg-bridge-svg-cards (display-graphic-p))
|
||||
(push (concat (mapconcat (lambda (p) (aref cg-bridge-seat-names (car p)))
|
||||
(reverse (cg-get game :trick)) " ") " ") out)
|
||||
(push (cg-bridge--svg-row (mapcar #'cdr (reverse (cg-get game :trick)))) out))
|
||||
(t (dolist (p (reverse (cg-get game :trick)))
|
||||
(push (format "%s:%s " (aref cg-bridge-seat-names (car p))
|
||||
(cg-bridge-card-string (cdr p))) out))
|
||||
(push "(empty)" out))
|
||||
(cg-bridge-card-string (cdr p))) out))))
|
||||
(push "\n" out)))
|
||||
;; the human's hand (South), or the seat being played from when it is dummy
|
||||
(let* ((act (if (and (eq phase 'play) (memq (cg-get game :turn)
|
||||
|
|
@ -533,7 +558,15 @@ vulnerability, and TRICKS the declarer side's trick count. Keys:
|
|||
((= act 0) " (you)")
|
||||
(t " (dummy, you play)")))
|
||||
out)
|
||||
(if (eq phase 'play)
|
||||
(cond
|
||||
((and (eq phase 'play) cg-bridge-svg-cards (display-graphic-p))
|
||||
(let ((hi '()) (i 0))
|
||||
(dolist (c hand)
|
||||
(when (and (= (cg-get game :turn) act) (cg-bridge--legal-play-p game act c))
|
||||
(push i hi))
|
||||
(setq i (1+ i)))
|
||||
(push (cg-bridge--svg-row hand :cursor cursor :hints hi) out)))
|
||||
((eq phase 'play)
|
||||
(let ((i 0))
|
||||
(dolist (c hand)
|
||||
(let ((cs (cg-bridge-card-string c)) (faces nil))
|
||||
|
|
@ -542,8 +575,8 @@ vulnerability, and TRICKS the declarer side's trick count. Keys:
|
|||
(cg-bridge--legal-play-p game act c)) (push 'cg-hint faces))
|
||||
(when (= i cursor) (push 'cg-cursor faces))
|
||||
(push (propertize (format "%4s" cs) 'face (or faces 'default)) out))
|
||||
(setq i (1+ i))))
|
||||
(push (cg-bridge--hand-by-suit hand) out)))
|
||||
(setq i (1+ i)))))
|
||||
(t (push (cg-bridge--hand-by-suit hand) out))))
|
||||
(push (format "\n\n %s\n" (cg-get game :message)) out)
|
||||
(apply #'concat (nreverse out))))
|
||||
|
||||
|
|
|
|||
42
cg-trick.el
42
cg-trick.el
|
|
@ -42,6 +42,7 @@
|
|||
(require 'cl-lib)
|
||||
(require 'eieio)
|
||||
(require 'cg-core)
|
||||
(require 'cg-svg)
|
||||
|
||||
;;;; Cards
|
||||
|
||||
|
|
@ -528,6 +529,24 @@
|
|||
(if bid (format " bid %d" bid) "")
|
||||
(if won (format " won %d" won) ""))))
|
||||
|
||||
(defcustom cg-trick-svg-cards t
|
||||
"When non-nil, draw cards as SVG images on a graphical display."
|
||||
:type 'boolean :group 'card-games)
|
||||
|
||||
(defun cg-trick--spec (card)
|
||||
"Return the cg-svg display spec (RANK-STRING . SUIT) for CARD."
|
||||
(cons (aref cg-trick-ranks (cdr card)) (car card)))
|
||||
|
||||
(cl-defun cg-trick--svg-row (cards &key cursor marks hints)
|
||||
"Return a one-image SVG row for CARDS with CURSOR, MARKS, HINTS indices."
|
||||
(propertize "*" 'display
|
||||
(cg-svg-image
|
||||
(cg-svg-hand-svg (mapcar #'cg-trick--spec cards)
|
||||
:cursor cursor :marks marks :hints hints
|
||||
:overlap (if (> (length cards) 11)
|
||||
(max 0 (- cg-svg-card-width 24)) 0))
|
||||
(cg-scale))))
|
||||
|
||||
(cl-defmethod cg-render ((game cg-trick-game))
|
||||
"Return a propertized string depicting GAME for a text display."
|
||||
(let* ((out (list))
|
||||
|
|
@ -544,15 +563,28 @@
|
|||
(push (cg-trick--seat-line game s) out))
|
||||
;; current trick
|
||||
(push "\n Trick: " out)
|
||||
(if (cg-get game :trick)
|
||||
(dolist (play (reverse (cg-get game :trick)))
|
||||
(cond
|
||||
((null (cg-get game :trick)) (push "(empty)" out))
|
||||
((and cg-trick-svg-cards (display-graphic-p))
|
||||
(push (concat (mapconcat (lambda (p) (aref cg-trick-seat-names (car p)))
|
||||
(reverse (cg-get game :trick)) " ") " ")
|
||||
out)
|
||||
(push (cg-trick--svg-row (mapcar #'cdr (reverse (cg-get game :trick)))) out))
|
||||
(t (dolist (play (reverse (cg-get game :trick)))
|
||||
(push (format "%s:%s " (aref cg-trick-seat-names (car play))
|
||||
(let ((cs (cg-trick-card-string (cdr play))))
|
||||
(if (cg-trick-red-p (cdr play))
|
||||
(propertize cs 'face 'cg-red-suit) cs)))
|
||||
out))
|
||||
(push "(empty)" out))
|
||||
out))))
|
||||
(push "\n\n Your hand (South):\n " out)
|
||||
(if (and cg-trick-svg-cards (display-graphic-p))
|
||||
(let ((mi '()) (hi '()) (i 0)
|
||||
(legalp (and (eq (cg-get game :phase) 'play) (= (cg-get game :turn) 0))))
|
||||
(dolist (c hand)
|
||||
(when (member c marks) (push i mi))
|
||||
(when (and legalp (cg-trick--legal-p game 0 c)) (push i hi))
|
||||
(setq i (1+ i)))
|
||||
(push (cg-trick--svg-row hand :cursor cursor :marks mi :hints hi) out))
|
||||
(let ((i 0))
|
||||
(dolist (c hand)
|
||||
(let* ((cs (cg-trick-card-string c))
|
||||
|
|
@ -561,7 +593,7 @@
|
|||
(when (member c marks) (push 'cg-hint faces))
|
||||
(when (= i cursor) (push 'cg-cursor faces))
|
||||
(push (propertize (format "%4s" cs) 'face (or faces 'default)) out))
|
||||
(setq i (1+ i))))
|
||||
(setq i (1+ i)))))
|
||||
(push (format "\n\n %s\n" (cg-get game :message)) out)
|
||||
(apply #'concat (nreverse out))))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue