Contents
Intro
piecepackr allows one to alter the appearance of one’s board game pieces through the use of configuration lists. Here is an example:
library("grid")
library("piecepackr")
dark_colorscheme <- list(suit_color="darkred,black,darkgreen,darkblue,black",
invert_colors.suited=TRUE)
piecepack_suits <- list(suit_text="\U0001f31e,\U0001f31c,\U0001f451,\u269c,\uaa5c", # 🌞,🌜,👑,⚜,꩜
suit_fontfamily="Noto Emoji,Noto Sans Symbols2,Noto Emoji,Noto Sans Symbols,Noto Sans Cham",
suit_cex="0.6,0.7,0.75,0.9,0.9")
traditional_ranks <- list(use_suit_as_ace=TRUE, rank_text=",a,2,3,4,5")
cfg <- c(piecepack_suits, dark_colorscheme, traditional_ranks)
gp_text <- gpar(fontsize=25, fontface="bold")
grid.text("grid.piece('preview_layout')", x=0.25, y=0.90, gp=gp_text)
pushViewport(viewport(x=0.25, y=0.43, width=inch(6)))
grid.piece("preview_layout")
popViewport()
grid.text("grid.piece('preview_layout', cfg=cfg)", x=0.75, y=0.90, gp=gp_text)
pushViewport(viewport(x=0.75, y=0.43, width=inch(6)))
grid.piece("preview_layout", cfg=cfg)
popViewport()

Configuration list example
There are lot more examples of customizing piecepack piece appearances with configuration lists in the Print & Play demos.
Although one can further customize the appearance of one’s board game pieces through the use of custom grob functions the default piecepackr grob function uses the configuration list to determine a board game component’s shape, “primary” symbol,”directional mark” symbol, and gridlines (if any). This program uses the abstraction that every board game component has a “component_side” name (like belt_face), a suit, a rank, a primary symbol, a directional mark symbol, and embellishments like border lines, grid lines, and padding. On top of the normal “suited” piecepack suits this program also recognizes an extra “unsuit” suit which is used to configure “neutral” components like tile backs and coin faces. Although the primary and directional mark symbols can be configured directly (i.e. tile_face.ps_fontsize) they are often configured indirectly by specifying various “suit” and “rank” symbol configurations (i.e. rank_cex).
Configurations are often allowed to be comma-separated to be able to specify different values for different suits or ranks e.g. background_color=white or background_color=pink,grey,grey,pink,white (note how the last [5th] element specifies that the “unsuit” background color should be “white”).
Configuration cascading
The configurations in this program “cascade” (sort of like in “Cascading Style Sheets”). A style configuration has the following format:
style_name(.suit)(.rank)(.component)
The configuration “cascade” priorities are as follows:
- Direct styles have priority over indirect styles e.g. dm_text has priority over suit_text.tile_face for which symbol is used in the corner of the tile face and in turn suit_fontfamily has priority over fontfamily for which fonts are used on the coin back. This is because indirect styles are only used to a generate reasonable default if a direct style cannot be found.
- Then if there is a tie .component_side has priority over .component which has priority over no component specification e.g. dm_text.saucer_back has priority over dm_text.saucer which has priority over just dm_text.
- Then if there is still a tie .r# has priority over no rank specification e.g. invert_colors.r1 has priority over invert_colors.
- Then if there is still a tie .s# has priority over .suited / .unsuited which has priority over no suit specification e.g. invert_colors.s2 has priority over invert_colors.suited has priority over just invert_colors.
Table of configuration list styles
name | description | indirect setters | comma-separated |
---|---|---|---|
ps_text | “primary symbol” text | suit_text, rank_text, use_suit_as_ace | |
ps_fontface | fontface of “primary symbol” symbol | suit_fontface, rank_fontface, fontface, use_suit_as_ace | |
ps_fontfamily | font of “primary symbol” symbol | suit_fontfamily, rank_fontfamily, fontfamily, use_suit_as_ace | |
ps_fontsize | fontsize of “primary symbol” symbol | ||
ps_cex | Multiplier to apply to the “primary symbol” fontsize (cumulative with cex) | suit_cex, rank_cex, use_suit_as_ace | |
ps_t | Angle (in degrees) of polar coordinates of “primary symbol” (from center) | suit | |
ps_r | Radius from center (relative units) of polar coordinates of “primary symbol” | suit | |
ps_color | Color of “primary symbol” | suit_color, background_color, invert_colors | |
dm_text | “directional mark” text | suit_text | suit |
dm_fontface | font of “directional mark” | suit_fontface, fontface | suit |
dm_fontfamily | font of “directional mark” | suit_fontfamily, fontfamily | suit |
dm_fontsize | fontsize of “directional mark” | ||
dm_cex | Multiplier to apply to the “directional mark” fontsize (cumulative with cex) | suit_cex | suit |
dm_t | Angle (in degrees) of polar coordinates of “directional mark” symbol (from center) | suit | |
dm_r | Radius from center (relative units) of polar coordinates of “directional mark” | suit | |
dm_color | Color of “directional mark” symbol | suit_color, background_color, invert_colors | suit |
shape | Shape of component: either rect, circle, halma, kite, pyramid, concave# or convex# where # is the number of outside polygon vertices | ||
shape_t | If shape is concave# or convex# then angle of first vertex (in degrees) of the polygon | ||
shape_r | If shape is concave# then how far from the center are the inner vertices (from 0 to 0.5) | ||
background_color | Background color of the component | suit_color, invert_colors | suit |
invert_colors | Should we switch the background color with the suit color? | ||
border_color | Color of the border of the component | suit | |
border_lex | Multiplier to apply to the default border line width | ||
gridline_color | Color of the gridlines | suit_color, background_color, invert_colors | suit |
gridline_lex | Multiplier to apply to the default grid line width | ||
edge_color | Which color to use for the edge of the piece when drawn with an oblique projection. | suit_color, background_color | suit |
annotation_color | What color to suggest for annotating graphics | ||
mat_color | Color of the “matting” | suit_color, background_color, invert_colors | suit |
mat_width | Width of the “matting” (from 0.0 to 1.0) | padding | |
suit_text | Suit symbols to use as “primary” symbol or “directional mark” | suit | |
suit_fontface | Font(s) of the suit symbols | fontface | suit |
suit_fontfamily | Font(s) of the suit symbols | fontfamily | suit |
suit_cex | Multiplier to apply to the suit symbols fontsize | suit | |
suit_color | Suit colors | suit | |
rank_text | Rank symbols to use as “primary” symbol | suit_text, use_suit_as_ace | rank |
rank_fontface | Font(s) of the rank symbols | suit_fontface, use_suit_as_ace, fontface | rank |
rank_fontfamily | Font(s) of the rank symbols | suit_fontfamily, use_suit_as_ace, fontfamily | rank |
rank_cex | Multiplier to apply to the rank symbols fontsize | suit_cex, use_suit_as_ace | rank |
use_suit_as_ace | Boolean for whether the suit symbol should be used for the ‘ace’ rank | ||
cex | Multiplier to apply to all the fontsizes | ||
fontfamily | Default font ‘family’ | ||
fontface | Default font ‘face’ | ||
n_ranks | Number of ranks | rank_text | |
n_suits | Number of suits | suit_text | |
coin_arrangement | Number of degrees the direction of the bottom of the coin differs from top of coin | ||
die_arrangement | Arrangement of dice (for use in 3D projections and paper Print & Play arrangements). Either "counter_up", "counter_down", "opposites_sum_to_5", or (a comma-separated string of) the integers 1, 2, 3, 4, 5, and 6 (in any order) with each integer optionally followed by ^ (default), <, v, or >. | ||
width | Width of component in inches | ||
height | Height of component in inches | width | |
depth | Depth of the component in inches | width | |
grob_fn | Which grob function to use to make a 2D grob of the game piece. | ||
grob_with_bleed_fn | Which function to use to make a grob of the game piece with a “bleed”. Introduced in v1.10. | ||
op_grob_fn | Which function to use to make a 3D grob of the game piece when the piece is drawn with an oblique projection. Introduced in v1.3. | ||
obj_fn | Which function to use to save Wavefront OBJ file of the game piece (which is used by default piece() and piece3d() functions). Introduced in v1.4. | ||
rayrender_fn | Which function to use to create game pieces for use with rayrender graphic system (via piece() function). Introduced in v1.4. | ||
rayvertex_fn | Which function to use to create game pieces for use with rayvertex graphic system (via piece_mesh() function). Introduced in v1.9. | ||
rgl_fn | Which function to use to draw game pieces in rgl graphic system (via piece3d() function). Introduced in v1.4. | ||
title | Title of the piecepack | ||
description | Description of the piecepack | ||
credit | Additional credits | ||
copyright | Additional copyrights | ||
spdx_id | [SPDX Identifier](https://spdx.org/licenses/) for the graphical design license. Introduced in v1.10. | ||
lacks_rank | Which “piece_side“‘s should we assume don’t vary by rank. Introduced in v1.7. | ||
lacks_suit | Which “piece_side“‘s should we assume don’t vary by suit. Introduced in v1.7. | ||
shadow_fn | Which function to use to make a grob of the edges of the game piece when the piece is drawn with a 3D oblique projection. Deprecated in v1.3 (use op_grob_fn instead). Removed in v1.10. |
Configuration List R6 Object
If you will be drawing lots of piecepack images you should use the pp_cfg function to create a configuration list R6 object. It (on-the-fly) builds a cache so it really speeds up future component drawing.
cfg <- pp_cfg(cfg)
Storing/sharing configuration lists
One can export configuration lists using R’s RData binary format and the save command and re-load them back in with the load command. Simple configuration lists can alternatively be stored in plaintext using formats like JSON (i.e. via the jsonlite package).
save(cfg, file="my_cfg.RData")
load("my_cfg.RData")
This website offers for download demo_cfgs.RData which contains every Print & Play demos configuration list.
download.file("https://trevorldavis.com/piecepackr/share/demo_cfgs.RData")
cfgs <- new.env()
load("demo_cfgs.RData", envir=cfgs)
names(cfgs)
## [1] "default1_cutlines" "chess2_borders" "dual4_cutlines" ## [4] "zodiac_cn1_borders" "dingbats1_borders" "zodiac_cn2_cutlines" ## [7] "chess2_cutlines" "dingbats2_cutlines" "chess5_bleed" ## [10] "orthodox2_bleed" "dual2_bleed" "dingbats2_borders" ## [13] "dual6_cutlines" "chess4_cutlines" "orthodox2_borders" ## [16] "orthodox1_cutlines" "default1_borders" "dual1_cutlines" ## [19] "orthodox3_cutlines" "dual5_bleed" "dingbats1_bleed" ## [22] "chess1_bleed" "default1_bleed" "zodiac_cn2_bleed" ## [25] "rainbow1_bleed" "chess1_cutlines" "orthodox3_borders" ## [28] "dingbats1_cutlines" "dual3_cutlines" "rainbow1_cutlines" ## [31] "dual3_bleed" "reversi1_bleed" "chess4_bleed" ## [34] "chess5_cutlines" "chess3_borders" "chess4_borders" ## [37] "chess1_borders" "dual5_cutlines" "zodiac_cn2_borders" ## [40] "reversi1_cutlines" "zodiac_cn1_cutlines" "dingbats2_bleed" ## [43] "dual6_bleed" "chess2_bleed" "dual1_bleed" ## [46] "orthodox1_bleed" "orthodox3_bleed" "zodiac_cn1_bleed" ## [49] "chess5_borders" "chess3_cutlines" "dual2_cutlines" ## [52] "orthodox2_cutlines" "orthodox1_borders" "rainbow2_cutlines" ## [55] "reversi1_borders" "dual4_bleed" "chess3_bleed" ## [58] "rainbow2_bleed"
print(cfgs$dual5_cutlines)
## $background_color : grey70 ## $copyright : © 2019 Trevor L Davis. Some Rights Reserved. ## $credit : ● This piecepack uses characters from the font Quivira. Public Domain., http://www.quivira-font.com/ ## $description : ## $fontfamily : Quivira ## $invert_colors.suited : TRUE ## $lacks_rank : tile_back,coin_back,card_back,pawn_face,pawn_back,belt_face,saucer_face,saucer_back,suitdie_face ## $lacks_suit : tile_back,saucer_back,coin_face,card_back ## $n_ranks : 6 ## $n_suits : 4 ## $rank_text : ,a,2,3,4,5 ## $spdx_id : CC-BY-SA-4.0 ## $suit_color : black,black,black,black,grey40 ## $suit_text : ,,,, ## $title : Swiss-suited (Black) ## $use_suit_as_ace : TRUE
grid.piece("preview_layout", cfg=cfgs$dual5_cutlines)

Preview of ‘dual5_cutlines’ configuration from ‘demo_cfgs.RData’
pushViewport(viewport(width=inch(6), height=inch(4)))
grid.piece("tile_face", rank=1:6,
cfg=paste0("dual", 1:6, "_cutlines"), envir=cfgs,
x=inch(rep(c(1,3,5), 2)), y=inch(rep(c(1,3), each=3)))
popViewport()

Can use multiple configurations stored in an environment at the same time