diff options
author | Karl Berry <karl@freefriends.org> | 2022-05-04 20:49:56 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-05-04 20:49:56 +0000 |
commit | 2753bb759be14523fd794eb733d6b06649d35c5e (patch) | |
tree | 7efa70c708fd6fd455ae24a9fe408c749b98fbd3 | |
parent | e816a42d94e18eb4a35500e78097073182cd3b76 (diff) |
chinesechess (4may22)
git-svn-id: svn://tug.org/texlive/trunk@63224 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/chinesechess/README.md | 143 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/chinesechess/bg01.png | bin | 0 -> 740338 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/chinesechess/bg02.png | bin | 0 -> 2978426 bytes | |||
-rwxr-xr-x | Master/texmf-dist/doc/latex/chinesechess/build.sh | 8 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/chinesechess/chinesechess.pdf | bin | 0 -> 4072654 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/chinesechess/chinesechess.tex | 887 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/chinesechess/chinesechess.sty | 2297 | ||||
-rwxr-xr-x | Master/tlpkg/bin/tlpkg-ctan-check | 2 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/chinesechess.tlpsrc | 0 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/collection-games.tlpsrc | 1 |
10 files changed, 3337 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/latex/chinesechess/README.md b/Master/texmf-dist/doc/latex/chinesechess/README.md new file mode 100644 index 00000000000..6e3077d2aaa --- /dev/null +++ b/Master/texmf-dist/doc/latex/chinesechess/README.md @@ -0,0 +1,143 @@ +Chinese chess manual writing package based on l3draw +======= + +`chinesechess` is a LaTeX3 package developed based on l3draw, which provides macros and environment for Chinese chess manual writing. + +You can read the manual (in Chinese) for more details and examples. + +Contributing +------------ + +<!-- 1. github repository: --> +<!-- 1. repository: [chinesechess](https://github.com/registor/chinesechess) --> +<!-- 2. Issues and pull requests are welcome. [issue](https://github.com/registor/chinesechess/issues) or [pull request](https://github.com/registor/chinesechess/pulls). --> +<!-- --> +1. gitee repository: + 1. repository: [chinesechess](https://gitee.com/nwafu_nan/chinesechess) + 2. Issues and pull requests are welcome. [issue](https://gitee.com/nwafu_nan/chinesechess/issues) or [pull request](https://gitee.com/nwafu_nan/chinesechess/pulls). + +基于l3draw的中国象棋棋谱排版宏包 +======= + +`chinesechess`是一个基于l3draw用LaTeX3开发的中国象棋棋谱排版宏包,它提供了用于排版中国象棋棋谱的命令和环境。 + +可以通过阅读宏包手册以了解该宏包更多的使用细节和使用样例。 + +## 排版示例 + +```latex +% 由于fandol字体无红棋的砲字,因此请选用合适的字体 +% K=帅,A=仕,E=相,R=车,C=砲,H=马,P=兵, k=将,a=士,e=象,r=車,c=炮,h=馬,p=卒 +% 水平定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8) +% 垂直定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8),j(9) +% 棋子定位时,可以混合使用字母和数字,以下示例使用混合输入 +% 强烈建议在实际使用中使用纯字母或纯数字定位 + +% 输出带所有棋子的棋盘命令 +\cchessboard +% 若仅需要输出不带棋子的棋盘,请使用带星命令 +\cchessboard* + +% 排版棋谱命令 +\cchessman{ {{4,0}{K}}, {{2,2}{p}}, {{1,7}{C}}, {{4,9}{k}} } + +% 排版打谱过程的环境 +\begin{setcchessman}[boardtype=x+tn] + % 残局初始化 + \init{ {{4,0}{K}}, {{2,2}{p}}, + {{1,7}{C}}, {{4,9}{k}} } + % 添加棋子 + \set{e,d}{P} \set{8,g}{h} + % 删除棋子 + \del{4,3} + % 移动棋子 + \mov{C}{b,h}{b,b} + \mov{p}{2,2}{3,2} +\end{setcchessman} + +% 可以使用带星号的打谱环境,同时将行棋过程按棋谱描述同时输出 +% 但此时需要注意排版版面限制问题。 +\begin{setcchessman*}[boardtype=x+tn] + % 残局初始化 + \init{ {{4,0}{K}}, {{2,2}{p}}, + {{1,7}{C}}, {{4,9}{k}} } + % 添加棋子 + \set{e,d}{P} \set{8,g}{h} + % 删除棋子 + \del{4,3} + % 移动棋子 + \mov{C}{b,h}{b,b} + \mov{p}{2,2}{3,2} + \mov{K}{4,0}{4,1} + \mov{h}{8,6}{6,7} + \mov{K}{4,1}{3,1} + \mov{h}{6,7}{5,5} +\end{setcchessman*} +``` +## 使用方法 + +宏包中可以设置棋谱外观。 + +```tex +\cchessset{ + boardtype = x+tn +} +``` + +宏包可用选项有: +- `gridsize` 棋盘单元格尺寸(需有长度单位) +- `boardtype` 棋盘类型,可以有x--简约型,x+--带兵、炮位标记和九宫线,x+t--带兵、炮位和九宫线及楚河汉界,x+tn--带兵、炮位、九宫线、楚河汉界及数字线位,x+Xtn--带兵、炮位、九宫线、象位线及楚河汉界 +- `boardlinewd` 棋盘线条宽度 +- `boardlinecolor` 棋盘线条颜色 +- `boardbg` 棋盘背景图片路径及文件名 +- `resize` 缩放类型,可以有none(默认)--无缩放,real--按指定实际尺寸或比例缩放(需要同时指定width/height/xscale/yscale参数值) +- `piecechar` 棋子字符 +- `piecefont` 棋子字符字体 +- `piecetype` 棋子类型,可以有o--简约型,oo--带双线边框无阴影型,ooo--立体型 +- `boxlinewd` 棋子边框线线宽 +- `boxcolor` 棋子边框颜色 +- `redpiece` 红棋文字颜色 +- `blkpiece` 黑棋文字颜色 +- `lower` 棋子背景颜色 +- `donut` 棋子环带颜色 +- `redupper` 红棋棋子颜色 +- `blkupper` 黑棋棋子颜色 +- `shadow` 棋子阴影颜色 +- `charstroke` 棋子文字笔划类型,可以有none,solid--实线轮廓,whide--白色填充,bold--加粗选择(默认),invisible-—隐藏笔划。 + +注意:`\init`、`\set`、`\del`和`\mov`这四个命令只能用于`setcchessman`环境及其星号环境中。 + +## 参与贡献 +--------------------- + +<!-- 1. github仓库: --> +<!-- (1). 仓库地址: [chinesechess](https://github.com/registor/chinesechess) --> +<!-- (2). Issues和PR: [issue](https://github.com/registor/chinesechess/issues) or [pull request](https://github.com/registor/chinesechess/pulls). --> + +1. gitee仓库: + (1). 仓库地址: [chinesechess](https://gitee.com/nwafu_nan/chinesechess) + (2). Issues and PR: [issue](https://gitee.com/nwafu_nan/chinesechess/issues) or [pull request](https://gitee.com/nwafu_nan/chinesechess/pulls). + +Copyright and Licence +--------------------- + + Copyright (C) 2020-2022 by Nan Geng <nangeng@nwafu.edu.cn> + ---------------------------------------------------------------------- + + This work may be distributed and/or modified under the + conditions of the LaTeX Project Public License, either + version 1.3c of this license or (at your option) any later + version. This version of this license is in + http://www.latex-project.org/lppl/lppl-1-3c.txt + and the latest version of this license is in + http://www.latex-project.org/lppl.txt + and version 1.3 or later is part of all distributions of + LaTeX version 2005/12/01 or later. + + This work has the LPPL maintenance status "maintained". + + The Current Maintainer of this work is Nan Geng. + + This package consists of chinesechess.sty, chinesechess.tex and README.md(this file), + and the derived files chinesechess.pdf. + diff --git a/Master/texmf-dist/doc/latex/chinesechess/bg01.png b/Master/texmf-dist/doc/latex/chinesechess/bg01.png Binary files differnew file mode 100644 index 00000000000..d8f0599f414 --- /dev/null +++ b/Master/texmf-dist/doc/latex/chinesechess/bg01.png diff --git a/Master/texmf-dist/doc/latex/chinesechess/bg02.png b/Master/texmf-dist/doc/latex/chinesechess/bg02.png Binary files differnew file mode 100644 index 00000000000..fa6fb51be55 --- /dev/null +++ b/Master/texmf-dist/doc/latex/chinesechess/bg02.png diff --git a/Master/texmf-dist/doc/latex/chinesechess/build.sh b/Master/texmf-dist/doc/latex/chinesechess/build.sh new file mode 100755 index 00000000000..91d492c0323 --- /dev/null +++ b/Master/texmf-dist/doc/latex/chinesechess/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +xelatex chinesechess.tex &&\ +makeindex -s gind.ist -o chinesechess.ind chinesechess.idx &&\ +makeindex -s gglo.ist -o chinesechess.gls chinesechess.glo &&\ +xelatex chinesechess.tex &&\ +xelatex chinesechess.tex &&\ +xelatex chinesechess.tex diff --git a/Master/texmf-dist/doc/latex/chinesechess/chinesechess.pdf b/Master/texmf-dist/doc/latex/chinesechess/chinesechess.pdf Binary files differnew file mode 100644 index 00000000000..22951bd3dbd --- /dev/null +++ b/Master/texmf-dist/doc/latex/chinesechess/chinesechess.pdf diff --git a/Master/texmf-dist/doc/latex/chinesechess/chinesechess.tex b/Master/texmf-dist/doc/latex/chinesechess/chinesechess.tex new file mode 100644 index 00000000000..9220174cc84 --- /dev/null +++ b/Master/texmf-dist/doc/latex/chinesechess/chinesechess.tex @@ -0,0 +1,887 @@ +\documentclass[full]{l3doc} +\usepackage[scheme=chinese]{ctex} +\usepackage{enumitem} +\usepackage{indentfirst} +\usepackage{titling} +\usepackage{geometry} +\usepackage{graphicx} +\usepackage{fontawesome5} +\usepackage{fancyvrb-ex} +\usepackage{chinesechess} +\cchessset{piecechar={C}{炮}} + +\IndexPrologue + { + \section*{Index} + \markboth{Index}{Index} + \addcontentsline{toc}{section}{Index} + The~italic~numbers~denote~the~pages~where~the~ + corresponding~entry~is~described,~ + numbers~underlined~point~to~the~definition,~ + all~others~indicate~the~places~where~it~is~used. + } + +\newcommand\tikzmark[1]{\tikz \coordinate[overlay, remember picture] (#1);} + +\geometry{ + left=4.5cm, + right=2cm, + top=2cm, + bottom=2cm, +} +\hypersetup { + CJKbookmarks, + bookmarksopen, + bookmarksopenlevel=3, + pdfstartview=FitH, + pdfinfo = { + Title = 中国象棋排版宏包 , + Subject = A LaTeX3 package , + Author = 耿楠 + } +} + +\DoNotIndex{\begin, \end} +\setlength{\parskip}{\medskipamount} +\DeclareDocumentEnvironment { noteen } { +b } { + \par\textbf{\textsf{NOTE:~}}#1\par +} {} +\DeclareDocumentEnvironment { notezh } { +b } { + \par\textbf{\textsf{注意:~}}#1\par +} {} + +\AtEndDocument{ + \newgeometry{ + left=2cm, + right=2cm, + top=2cm, + bottom=2cm + } + \PrintIndex +} + +\ExplSyntaxOn +\dim_new:N \l__my_syntax_dim +\box_new:N \g__my_syntax_box +\NewDocumentEnvironment { Syntax } { s } + { + \dim_set:Nn \l__my_syntax_dim + { \textwidth } + \hbox_gset:Nw \g__my_syntax_box + \small \ttfamily + \begin{minipage}[t]{\l__my_syntax_dim} + \raggedright\obeyspaces\obeylines + } + { + \end{minipage} + \hbox_gset_end: + \IfValueF { #1 } { \smallskip } + \box_use_drop:N \g__my_syntax_box + \smallskip + } + +\DeclareDocumentEnvironment { Description } { o +b } { + \hbox_set:Nn \l_tmpa_box { #1 } + \dim_set:Nn \l_tmpa_dim { \box_wd:N \l_tmpa_box } + \begin{itemize}[labelwidth=\l_tmpa_dim, align=left] + #2 + \end{itemize} +} { } + +\keys_define:nn { cchess/doc } { + opt .tl_set:N = \l_opt_tl, + desc .tl_set:N = \l_desc_tl, + init .tl_set:N = \l_init_tl, + init .initial:n = init-none, +} + +\box_new:N \l__option_box +\NewDocumentEnvironment { option } { m +b } { + \keys_set:nn { cchess/doc } { #1 } + \hbox_set:Nw \l__option_box + \small \ttfamily + \begin{minipage}[t]{\textwidth} + \obeyspaces\obeylines + \textcolor{red}{ + \l_opt_tl + \exp_args:Nx\SpecialOptionIndex{\l_opt_tl} + } + {~}\l_desc_tl + \hfill( + \tl_if_eq:NnTF \l_init_tl { init-none } { no~value } + { 初始值:~\texttt{\l_init_tl} } + ) + \end{minipage} + \hbox_gset_end: + \box_use_drop:N \l__option_box + #2 + % \vspace*{-4ex} + \medskip +} { } + +\DeclareDocumentCommand \opt { O{} m } + { \__codedoc_cmd:no {#1} { #2 } } +\ExplSyntaxOff + +\def\vers{\texttt{v1.0.0} } + +\begin{document} +\title{ + 中国象棋棋谱排版\\\pkg{chinesechess} 宏包 + % \rlap{\makebox[4cm][r]{ + % \normalsize $\Longrightarrow$ \color{red} + % \protect\hyperlink{en}{English Version} + % \protect\hypertarget{zh}{} + % }} +} +\author{\textit{耿楠} \texttt{<nangeng@nwafu.edu.cn>}} +\date{\the\year 年\the\month 月\the\day 日\qquad \vers +% \thanks{\url{https://github.com/registor/chinesechess}} +\thanks{\url{https://gitee.com/nwafu_nan/chinesechess}} +} +\maketitle + +{\small +\tableofcontents +} +\newpage + +\begin{documentation} + +\section{引言} + +\pkg{chinesechess}是一个基于\pkg{l3draw}用\pkg{Expl3}开发的 +中国象棋排版宏包。它提供了\tn{cchessboard} 全棋盘、 +\tn{cchessbord*}空白棋盘和\tn{cchessman}棋谱排版命令。同时, +该宏包还提供了用于打谱的排版环境\env{setcchessman},在该环境 +中,可以通过环境专用命令\tn{init}初始化棋谱状态,\tn{set}在 +指定位置布置棋子,\tn{del}删除指定位置的棋子,\tn{mov}实现 +棋子的移动,从而实现打谱操作,并在环境结束后以最终状态排版棋谱。 +另外,也可以通过星号环境\env{setcchessman*}实现棋谱的文本描述 +输出。 + +棋子、棋盘、背景等外观可以通过命令、环境选项或\tn{cchessset}% +命令进行设置。 + +\section{用户接口} + +\subsection{\tn{cchessboard}棋盘排版命令} + +\begin{function}{\cchessboard} + \begin{syntax} + \cs{cchessboard} \oarg{外观选项} + \cs{cchessboard*} \oarg{外观选项} + \end{syntax} +\end{function} + + 按设置的\oarg{外观选项}输出带有32个红黑棋子,并布置于初始位置 + 的棋盘。 + + 在\oarg{外观选项}中可以通过key-value的方式设置棋子、棋盘的颜色、 + 字体、字号、线宽等外观。 + + 通过\oarg{外观选项}设置的外观参数仅对当前命令局部有效, + + 其星号版本命令用于无棋子棋盘。 + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.68\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + height=4.8cm} + \cchessboard\quad + \cchessboard* +\end{SideBySideExample} + +\subsection{\tn{cchessman}棋谱排版命令}\label{subsec-cchessman} + +\begin{function}{\cchessman} + \begin{syntax} + \cs{cchessman} \oarg{外观选项} \marg{棋子列表} + \end{syntax} +\end{function} + + 按设置的\oarg{外观选项},将在\marg{棋子列表}中指定棋子排版于棋盘的 + 指定位置。 + + \marg{棋子列表}中各个棋子用大括号分组后用英文逗号进行分隔,每个棋子 + 由用大括号括起来的棋子位置与棋子编码组成。 + + 棋子位置由英文逗号分隔的纵横坐标确定,其中,纵向坐标用英文小写字母 + a--j或阿拉伯数字0--9分别表示棋盘纵向10个交点;横向坐标用英文小写字母 + a--i或阿拉伯数字0--8分别表示棋盘横向的9个交点。 + + \textbf{\textsf{注意: }}可以混合使用棋子坐标表示方法,但强烈建议使用 + 单一字母法或数字表示棋子坐标。 + + 棋子编码采用大写字母表示红棋,小写字母表示黑棋,具体如表% + \ref{tab-piececode}所示。 + + \begin{table}[!htbp] + \centering + \caption{棋子编码规则}\label{tab-piececode} + \begin{tabular}{cc||cc} + \hline + 编码 & 红棋 & 编码 & 黑棋\\\hline + K & 帥 & k & 將 \\ + A & 仕 & a & 士 \\ + E & 相 & e & 象 \\ + H & 马 & h & 馬 \\ + R & 车 & r & 車 \\ + C & 炮 & c & 炮 \\ + P & 兵 & p & 卒 \\\hline + \end{tabular} + \end{table} + + 例如,一个完整的\marg{棋子列表}为: + + |{{4,0}{K}}, {{2,2}{p}}, {{1,7}{C}}, {{4,9}{k}}| + + 在\oarg{外观选项}中可以通过key-value的方式设置棋子、棋盘的颜色、 + 字体、字号、线宽等外观。 + + 通过\oarg{外观选项}设置的外观参数仅对当前命令局部有效, + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.50\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.90\linewidth} + \cchessman{ {{4,0}{K}}, {{2,2}{p}}, + {{1,7}{C}}, {{4,9}{k}} + } +\end{SideBySideExample} + +\subsection{\env{setcchessman}打谱排版环境} + +\begin{function}{setcchessman} + \begin{syntax} + \tn{begin}|{setcchessman}|\oarg{外观选项} + ..... + \tn{end}|{setcchessman}| + \tn{begin}|{setcchessman*}|\oarg{外观选项} + ..... + \tn{end}|{setcchessman*}| + \end{syntax} +\end{function} + + 按设置的\oarg{外观选项}对打谱结果进行排版。 + + 在打谱排版环境\env{setcchessman}中,可以通过专用命令\tn{init}% + 初始化棋谱状态(残局),\tn{set}在指定位置布置棋子,\tn{del}删除 + 指定位置的棋子,\tn{mov}实现棋子的移动,从而实现打谱操作。 + 在环境结束后以最终打谱状态排版棋谱。 + + 星号环境\env{setcchessman*}会同时排版棋谱的文本描述(如:车一进二等)。 + + 在\oarg{外观选项}中可以通过key-value的方式设置棋子、棋盘的颜色、 + 字体、字号、线宽等外观。 + + 通过\oarg{外观选项}设置的外观参数仅对当前命令局部有效, + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.48\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.90\linewidth} + \begin{setcchessman} + % 残局初始化 + \init{ {{4,0}{K}}, {{2,2}{p}}, + {{1,7}{C}}, {{4,9}{k}} } + % 添加棋子 + \set{e,d}{P} \set{8,g}{h} + % 删除棋子 + \del{4,3} + % 移动棋子 + \mov{C}{b,h}{b,b} \mov{p}{2,2}{3,2} + \mov{K}{4,0}{4,1} \mov{h}{8,6}{6,7} + \mov{K}{4,1}{3,1} \mov{h}{6,7}{5,5} + \end{setcchessman} +\end{SideBySideExample} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.45\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.30\linewidth} + \begin{setcchessman*} + % 残局初始化 + \init{ {{4,0}{K}}, {{2,2}{p}}, + {{1,7}{C}}, {{4,9}{k}} } + % 添加棋子 + \set{e,d}{P} \set{8,g}{h} + % 删除棋子 + \del{4,3} + % 移动棋子 + \mov{C}{b,h}{b,b} \mov{p}{2,2}{3,2} + \mov{K}{4,0}{4,1} \mov{h}{8,6}{6,7} + \mov{K}{4,1}{3,1} \mov{h}{6,7}{5,5} + \end{setcchessman*} +\end{SideBySideExample} + +\subsection{打谱专用命令} + +\subsubsection{\tn{init}棋谱初始化命令} + +\begin{function}{\init} + \begin{syntax} + \cs{init} \marg{棋子列表} + \end{syntax} +\end{function} + + 用于将在\marg{棋子列表}中指定的所有棋子布置于棋盘的指定位置。 + + \marg{棋子列表}中的棋子表示方法与第\ref{subsec-cchessman}小节 + 中的说明相同。 + + \textbf{\textsf{注意: }}该命令只能用于\env{setcchessman}环境中。 + +\subsubsection{\tn{set}棋子布置命令} + +\begin{function}{\set} + \begin{syntax} + \cs{set} \marg{棋子} + \end{syntax} +\end{function} + + 用于将在\marg{棋子}中指定的棋子布置于棋盘的指定位置。 + + \marg{棋子}中的棋子表示方法与第\ref{subsec-cchessman}小节 + 中的说明相同。 + + \textbf{\textsf{注意: }}该命令只能用于\env{setcchessman}环境中。 + +\subsubsection{\tn{del}棋子删除命令} + +\begin{function}{\del} + \begin{syntax} + \cs{del} \marg{棋盘坐标} + \end{syntax} +\end{function} + + 用于删除\marg{棋盘坐标}中指定坐标处的棋子。 + + \marg{棋盘坐标}中的表示方法与第\ref{subsec-cchessman}小节 + 中的说明相同。 + + \textbf{\textsf{注意: }}该命令只能用于\env{setcchessman}环境中。 + +\subsubsection{\tn{mov}棋子移动命令} + +\begin{function}{\mov} + \begin{syntax} + \cs{mov} \marg{棋子编码}\marg{原棋盘坐标}\marg{新棋盘坐标} + \end{syntax} +\end{function} + + 用于将\marg{棋子编码}中指定的棋子从\marg{原棋盘坐标}移动到% + \marg{新棋盘坐标}。 + + \marg{棋子编码}、\marg{原棋盘坐标}和\marg{新棋盘坐标}中采用 + 棋子与棋盘坐标表示方法与第\ref{subsec-cchessman}小节中的说明相同。 + + \textbf{\textsf{注意: }}该命令只能用于\env{setcchessman}环境中。 + +\subsection{\tn{resetpiece}棋子字符复位命令} + +\begin{function}{\resetpiece} + \begin{syntax} + \cs{resetpiece} + \end{syntax} +\end{function} + + 将棋子字符复位到默认字符。 + +\subsection{\tn{cchessset}外观设置命令} + +\begin{function}{\cchessset} + \begin{syntax} + \cs{cchessset} \marg{外观选项} + \end{syntax} +\end{function} + + 通过\marg{外观选项}中的key-value方式设置棋子、棋盘的文字、 + 字体、颜色、线宽、背景等排版外观。 + + 通过\cs{cchessset}\marg{外观选项}设置的外观参数对后续所有 + 棋谱排版命令有效, + +\section{外观选项} + +在\pkg{chinesechess}宏包中,棋子与棋盘的文本、字体、颜色、背景等 +外观可以通过不同\oarg{外观选项}进行设置。\oarg{外观选项}可以在 +命令或环境的可选项中进行局部设置,也可以通过\cs{cchessset}命令 +进行全局设置。 + +\subsection{棋盘} + +\subsubsection{单元格尺寸} + +\begin{option}{ opt = gridsize, desc = {= \meta{棋盘格尺寸}}, init=10mm } + 设置棋盘单元格尺寸。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.90\linewidth} + \cchessboard[gridsize=15mm] +\end{SideBySideExample} + +\bigskip + +\subsubsection{棋盘类型} + +\begin{option}{ opt = boardtype, desc = {= \meta{棋盘类型}}, init=x+tn } + 设置棋盘类型,目前支持: +\end{option} + + \begin{Description}[a] + \item |x|---有九宫对角线,无兵炮位置标志。 + \item |x+|---有九宫对角线和兵炮位置标志。 + \item |x+t|---有九宫对角线、兵炮位置标志和楚河汉界。 + \item |x+tn|---有九宫对角线、兵炮位置标志、楚河汉界和纵线标位数字。 + \item |x+Xtn|---有九宫对角线、兵炮位置标志、楚河汉界、纵线标位数字和象位虚线。 + \end{Description} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.54\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.35\linewidth} + \cchessboard*[boardtype=x]\quad + \cchessboard*[boardtype=x+]\\ + \cchessboard*[boardtype=x+t]\quad + \cchessboard*[boardtype=x+tn]\\ + \cchessboard*[boardtype=x+Xtn] +\end{SideBySideExample} + +\bigskip + +\subsubsection{棋盘线线宽} + +\begin{option}{ opt = boardlinewd, desc = {= \meta{棋盘线宽}}, init=0.4pt } + 设置棋盘线线宽。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.56\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.90\linewidth} + \cchessboard*[boardlinewd=1.0pt] +\end{SideBySideExample} + +\bigskip + +\subsubsection{棋盘线颜色} + +\begin{option}{ opt = boardlinecolor, desc = {= \meta{棋盘线颜色}}, init=black } + 设置棋盘线颜色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.55\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.90\linewidth} + \cchessboard*[boardlinecolor=red] +\end{SideBySideExample} + +\bigskip + +\subsubsection{棋盘背景} + +\begin{option}{ opt = boardbg, desc = {= \meta{棋盘背景}}, init=init-none } + 设置棋盘背景图的插图文件路径及文件名。 +\end{option} + + \textbf{\textsf{注意: }}使用该选项时,需要在导言区添加|\usepackage{grpahicx}|命令。 + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.55\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.35\linewidth} + \cchessboard*[boardbg=bg01]\quad + \cchessboard*[boardbg=bg02] +\end{SideBySideExample} + +\bigskip + +\subsection{棋谱缩放} + +\subsubsection{缩放方式} + +\begin{option}{ opt = resize, desc = {= \meta{棋谱缩放方式}}, init=none } + 设置最终棋谱输出时的整体缩放方式,目前支持: +\end{option} + + \begin{Description}[a] + \item |none|---无缩放。 + \item |real|---按指定的width、height、xscale或yscale进行缩放。 + \end{Description} + +\bigskip + +\subsubsection{横向缩放因子} + +\begin{option}{ opt = xscale, desc = {= \meta{x方向缩放系数}}, init=1 } + 设置x方向缩放系数,需要配合|resize|缩放方式参数一起使用。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.48\linewidth,gobble=2] + \centering + \cchessboard[resize=real, xscale=0.5] +\end{SideBySideExample} + + +\bigskip + +\subsubsection{纵向缩放因子} + +\begin{option}{ opt = yscale, desc = {= \meta{y方向缩放系数}}, init=1 } + 设置y方向缩放系数,需要配合|resize|缩放方式参数一起使用。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.70\linewidth,gobble=2] + \centering + \cchessboard[% + resize=real, + yscale=0.5] +\end{SideBySideExample} + +\bigskip + +\subsubsection{横向尺寸} + +\begin{option}{ opt = width, desc = {= \meta{宽度}}, init=init-none } + 设置输出宽度,需要配合|resize|缩放方式参数一起使用。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.65\linewidth,gobble=2] + \centering + \cchessboard[resize=real, + width=7cm] +\end{SideBySideExample} + +\bigskip + +\subsubsection{纵向尺寸} + +\begin{option}{ opt = height, desc = {= \meta{高度}}, init=init-none } + 设置输出高度,需要配合|resize|缩放方式参数一起使用。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.65\linewidth,gobble=2] + \centering + \cchessboard[resize=real, + height=6cm] +\end{SideBySideExample} + + \textbf{\textsf{说明: }}缩放纵/横参数可以混合使用。 + +\bigskip + +\subsection{棋子} + +\subsubsection{字符} + +\begin{option}{ opt = piecechar, desc = {= \meta{棋子字符}}, + init=\{K\}\{帥\} } + 设置棋子字符,用两组大括号分别指定棋子编码和棋子字符。 + 其中,棋子编码见表\ref{tab-piececode}。 +\end{option} + + \textbf{\textsf{注意: }}使用该选项时,在能需要在导言区添加字体, + 如|\usepackage{fontawesome5}|命令。 + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.55\linewidth,gobble=2] + %\usepackage{fontawesome5} + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + % gridsize=10mm, + width=.90\linewidth} + \cchessboard[% + piecechar={K}{\faChessKing}, + piecechar={A}{\faShield*}, + piecechar={E}{\faChessBishop}, + piecechar={H}{\faChessKnight}, + piecechar={R}{\faChessRook}, + piecechar={C}{\faBomb}, + piecechar={P}{\faChessPawn}, + piecechar={k}{\faChessQueen}, + piecechar={a}{\faShield*}, + piecechar={e}{\faChessBishop}, + piecechar={h}{\faChessKnight}, + piecechar={r}{\faChessRook}, + piecechar={c}{\faBomb}, + piecechar={p}{\faChessPawn}, + boardlinecolor=red] +\end{SideBySideExample} + +\bigskip + +\resetpiece +\cchessset{piecechar={C}{炮}} + +\subsubsection{颜色} + +\begin{option}{ opt = piecefont, desc = {= \meta{棋子字符字体}}, init=\cs{kaishu} } + 设置棋子字符字体。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.55\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.90\linewidth} + \cchessboard[piecefont=\sffamily] +\end{SideBySideExample} + +\bigskip + +\subsubsection{边框类型} + +\begin{option}{ opt = piecetype, desc = {= \meta{棋子边框类型}}, init=|ooo| } + 设置棋子外框类型,目前支持: +\end{option} + + \begin{Description}[a] + \item |o|---实心填充圆(小写英文字母``|o|'')。 + \item |oo|---双同心实心圆。 + \item |ooo|---双同心实心圆叠加阴影错位圆。 + \end{Description} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.55\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.40\linewidth} + \cchessboard[piecetype=o]\quad + \cchessboard[piecetype=oo]\\ + \cchessboard[piecetype=ooo] +\end{SideBySideExample} + +\bigskip + +\subsubsection{边框线宽} + +\begin{option}{ opt = boxlinewd, desc = {= \meta{棋子外框线宽度}}, init=0.4pt } + 设置棋子外框线线宽。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[boxlinewd=0.8pt] +\end{SideBySideExample} + +\bigskip + +\subsubsection{边框颜色} + +\begin{option}{ opt = boxcolor, desc = {= \meta{棋子外框线颜色}}, init=black } + 设置棋子外框线颜色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[boxcolor=white] +\end{SideBySideExample} + +\bigskip + +\subsubsection{红棋颜色} + +\begin{option}{ opt = redpiece, desc = {= \meta{红棋棋子字符颜色}}, init=red } + 设置红棋棋子字符颜色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[redpiece=white] +\end{SideBySideExample} + +\bigskip + +\subsubsection{黑棋颜色} + +\begin{option}{ opt = blkpiece, desc = {= \meta{黑棋棋子字符颜色}}, init=black } + 设置黑棋棋子字符颜色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[blkpiece=white] +\end{SideBySideExample} + +\bigskip + +\subsubsection{背景圆填充色} + +\begin{option}{ opt = lower, desc = {= \meta{棋子背景圆填充色}}, init=init-none } + 设置棋子背景圆填充色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[lower=black] +\end{SideBySideExample} + +\bigskip + +\subsubsection{表面圆环填充色} + +\begin{option}{ opt = donut, desc = {= \meta{棋子表面圆环填充色}}, init=init-none } + 设置棋子表面圆环填充色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[donut=red] +\end{SideBySideExample} + +\bigskip + +\subsubsection{红棋表面圆填充色} + +\begin{option}{ opt = redupper, desc = {= \meta{红棋棋子表面圆填充色}}, init=init-none } + 设置红棋棋子表面圆填充色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[redupper=red, + redpiece=white] +\end{SideBySideExample} + +\bigskip + +\subsubsection{黑棋表面圆填充色} + +\begin{option}{ opt = blkupper, desc = {= \meta{黑棋棋子表面圆填充色}}, init=init-none } + 设置黑棋棋子表面圆填充色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[blkupper=black, + blkpiece=white] +\end{SideBySideExample} + +\bigskip + +\subsubsection{阴影错位圆填充色} + +\begin{option}{ opt = shadow, desc = {= \meta{棋子阴影错位圆填充色}}, init=init-none } + 设置棋子阴影错位圆填充色。 +\end{option} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.60\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[shadow=red!80] +\end{SideBySideExample} + +\bigskip + +\subsubsection{笔划} + +\begin{option}{ opt = scharstroke, desc = {= \meta{棋子字符笔划类型}}, init=bold } + 设置棋子字符笔划类型。 +\end{option} + + \begin{Description}[a] + \item |none|---原字体默认笔划。 + \item |solid|---实线笔划轮廓,笔划内部透明,颜色使用字符颜色。 + \item |white|---实线白色笔划轮廓,笔划内部用白色填充。 + \item |bold|---加粗笔划,颜色使用字符颜色。 + \item |invisible|---隐藏笔划。 + \end{Description} + +\begin{SideBySideExample}[frame=single,numbers=left, + xrightmargin=.58\linewidth,gobble=2] + \centering + % 为便排版,进行缩放 + \cchessset{resize=real, + width=.95\linewidth} + \cchessboard[charstroke=white, + redupper=red,blkupper=black] +\end{SideBySideExample} + +% \bigskip + +% \title{ +% \pkg{chinesechess} package for writing Chinese chess +% \rlap{\makebox[4cm][r]{ +% \normalsize $\Longrightarrow$ \color{red} +% \protect\hyperlink{zh}{中文版本} +% \protect\hypertarget{en}{} +% }} +% } +% \author{Nan Geng \texttt{<nangeng@nwafu.edu.cn>}} +% \date{\today\qquad \vers} +% \maketitle +% +% \section{Introduction} +% +% \section{Interface} +% +% \section{options} + +\end{documentation} + +\end{document} diff --git a/Master/texmf-dist/tex/latex/chinesechess/chinesechess.sty b/Master/texmf-dist/tex/latex/chinesechess/chinesechess.sty new file mode 100644 index 00000000000..6ddb58b8368 --- /dev/null +++ b/Master/texmf-dist/tex/latex/chinesechess/chinesechess.sty @@ -0,0 +1,2297 @@ +%% Copyright (C) 2020-2022 by Nan Geng <nangeng@nwafu.edu.cn> +%% -------------------------------------------------------------------------- +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either +%% version 1.3c of this license or (at your option) any later +%% version. This version of this license is in +%% http://www.latex-project.org/lppl/lppl-1-3c.txt +%% and the latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of +%% LaTeX version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status "maintained". +%% +%% The Current Maintainer of this work is Nan Geng. +%% +%% -------------------------------------------------------------------------- +%% +\NeedsTeXFormat{LaTeX2e}[2020/10/01] +\RequirePackage{expl3} +\ProvidesExplPackage{chinesechess}{2022-04-29}{v1.0.0} + {Typeset Chinese chess with l3draw} + +\RequirePackage { l3keys2e, l3draw, xparse } + +% 保证TeXLive的向下兼容 +\cs_if_free:NT \box_ht_plus_dp:N + { + \cs_new_protected:Npn \box_ht_plus_dp:N #1 + { \tex_dimexpr:D \box_ht:N #1 + \box_dp:N #1 \scan_stop: } + } + +% 可以使用>{\SplitArgument{1}{~}}分割参数,如: +% \NewDocumentCommand{\cchessboard}{ s >{\SplitArgument{1}{,}}O{10mm,10mm} } +% +% 棋盘排版命令用户接口 +% #1 星号命令,是否输出棋子 +% #2 棋盘类型、棋子类型等外观选项 +\NewDocumentCommand{\cchessboard}{ s O{} } + { + \group_begin: + % 星号命令是否带棋子 + \IfBooleanTF{ #1 } + { + \bool_set_false:N \l__cchess_board_pieces_bool + }{ + \bool_set_true:N \l__cchess_board_pieces_bool + } + % 选项设置 + \keys_set:nn { cchess } { #2 } + \__cchess_board_output: + \group_end: + } + +% 棋谱排版命令用户接口 +% #1 棋盘类型、棋子类型等外观选项 +% #2 棋子位置列表 +% 棋子字母汉字对照表(取xq.sty中的定义) +% K=帅,A=仕,E=相,R=车,C=砲,H=马,P=兵, k=将,a=士,e=象,r=車,c=炮,h=馬,p=卒 +% 水平定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8) +% 垂直定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8),j(9) +\NewDocumentCommand{\cchessman}{ O{} m } + { + \group_begin: + % 选项设置 + \keys_set:nn { cchess } { #1 } + \__cchess_manual_output:n { #2 } + \group_end: + } + +% 棋子字符复位 +\NewDocumentCommand{\resetpiece}{} + { + % 定义棋子字符常量 + \clist_map_inline:nn + { + { K } {\__cchess_symbol:n {"5E25} }, % 帥 + { A } {\__cchess_symbol:n {"4ED5} }, % 仕 + { E } {\__cchess_symbol:n {"76F8} }, % 相 + { H } {\__cchess_symbol:n {"9A6C} }, % 马 + { R } {\__cchess_symbol:n {"8F66} }, % 车 + { C } {\__cchess_symbol:n {"7832} }, % 砲 + { P } {\__cchess_symbol:n {"5175} }, % 兵 + { k } {\__cchess_symbol:n {"5C07} }, % 將 + { a } {\__cchess_symbol:n {"58EB} }, % 士 + { e } {\__cchess_symbol:n {"8C61} }, % 象 + { h } {\__cchess_symbol:n {"99AC} }, % 馬 + { r } {\__cchess_symbol:n {"8ECA} }, % 車 + { c } {\__cchess_symbol:n {"70AE} }, % 炮 + { p } {\__cchess_symbol:n {"5352} }, % 卒 + } + { \__cchess_piece_char_setup:nn ##1 } + } +% 打谱环境初始化(仅用于setcchessman环境中) +% #1 棋子位置列表 +% 棋子字母汉字对照表(取xq.sty中的定义) +% K=帅,A=仕,E=相,R=车,C=砲,H=马,P=兵, k=将,a=士,e=象,r=車,c=炮,h=馬,p=卒 +% 水平定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8) +% 垂直定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8),j(9) +\NewDocumentCommand{\init}{ m } + { + % 临时clist + \clist_set:Nn \l_tmpa_clist { #1 } + + % 替换占位盒子内容 + \clist_map_inline:Nn \l_tmpa_clist + { \__cchess_piece_replace_handle:nn ##1 } + } + +% 打谱环境中的棋子布置命令(仅用于setcchessman环境中) +% #1 棋子位置 +% #2 棋子名称(单个英文字母) +% 棋子字母汉字对照表(取xq.sty中的定义) +% K=帅,A=仕,E=相,R=车,C=砲,H=马,P=兵, k=将,a=士,e=象,r=車,c=炮,h=馬,p=卒 +% 水平定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8) +% 垂直定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8),j(9) +\NewDocumentCommand{\set}{ m m } + { + \__cchess_piece_replace_handle:nn { #1 } { #2 } + } + +% 删除打谱环境中的棋子(仅用于setcchessman环境中) +% #1 棋子位置 +% 水平定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8) +% 垂直定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8),j(9) +\NewDocumentCommand{\del}{ m } + { + \__cchess_piece_remove_handle:n { #1 } + } + +% 移动打谱环境中的棋子(仅用于setcchessman环境中) +% #1 棋子名称(单个英文字母) +% #2 棋子当前位置 +% #3 棋子目的位置 +% K=帅,A=仕,E=相,R=车,C=砲,H=马,P=兵, k=将,a=士,e=象,r=車,c=炮,h=馬,p=卒 +% 水平定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8) +% 垂直定位: a(0),b(1),c(2),d(3),e(4),f(5),g(6),h(7),i(8),j(9) +\NewDocumentCommand{\mov}{ m m m } + { + \__cchess_piece_move_handle:nnn { #1 } { #2 } { #3 } + } + +% 打谱排版环境用户接口 +% #1 棋盘类型、棋子类型等外观选项 +\NewDocumentEnvironment{ setcchessman }{ O{} +b } + { + \group_begin: + \bool_set_false:N \l__cchess_with_setman_bool + \keys_set:nn { cchess } { #1 } + \__cchess_setcchessman_pre_setup:n { #2 } + }{ + \__cchess_setcchessman_post_setup: + \group_end: + } + +% 打谱排版星号环境用户接口,用于同时输出棋谱描述 +% #1 棋盘类型、棋子类型等外观选项 +\NewDocumentEnvironment{ setcchessman* }{ O{} +b } + { + \group_begin: + \bool_set_true:N \l__cchess_with_setman_bool + \keys_set:nn { cchess } { #1 } + \__cchess_setcchessman_pre_setup:n { #2 } + }{ + \__cchess_setcchessman_post_setup: + \group_end: + } + + +% ==========棋子字符定义===================== +% 读取符号 +\cs_new:Npn \__cchess_symbol:n #1 + { + \tex_char:D #1 + \scan_stop: + } + +% 棋子符号定义 +\cs_new_protected:Npn \__cchess_piece_define:nn #1#2 + { + \tl_const:cn { c__cchess_ #1 _tl } { \__cchess_symbol:n { #2 } } + } + +% ==========变量定义===================== +% 绘制棋盘时是否带有棋子标志 +\bool_new:N \l__cchess_board_pieces_bool +\bool_new:N \l__cchess_with_setman_bool + +% 棋子类型 +\tl_new:N \l__cchess_piece_box_type_tl +% 棋子类型列表 +\clist_new:N \g__cchess_piece_box_list_clist +% 棋盘类型 +\tl_new:N \l__cchess_board_type_tl +% 棋盘类型列表 +\clist_new:N \g__cchess_board_list_clist + +% 缩放方式 +\tl_new:N \l__cchess_resize_method_tl +% 缩放方式列表 +\clist_new:N \g__cchess_resize_method_clist + +% 棋谱输出宽度 +\dim_new:N \l__cchess_manual_width_dim +% 棋谱输出高度 +\dim_new:N \l__cchess_manual_height_dim +% 棋盘宽度 +\dim_new:N \l__cchess_board_width_dim +% 棋盘高度 +\dim_new:N \l__cchess_board_height_dim +% 棋盘线线宽 +\dim_new:N \l__cchess_board_linewidth_dim +% 辅线线宽 +\dim_new:N \l__cchess_cross_linewidth_dim +% 辅线间距 +\dim_new:N \l__cchess_cross_sep_dim +% 棋子字符正方形外接圆半径 +\dim_new:N \l__cchess_piece_box_radius_dim +% 棋子外框线线宽 +\dim_new:N \l__cchess_box_linewidth_dim +% 临时尺寸变量 +\dim_new:N \l__cchess_tmpa_dim +\dim_new:N \l__cchess_tmpb_dim +\dim_new:N \l__cchess_tmpc_dim +\dim_new:N \l__cchess_tmpd_dim + +% 棋子容器 +% 当前中国象棋主流软件的棋子代码,多沿用: +% K A B N R C P +% 帅 仕 相 马 车 炮 兵 +% (红方用大写字母,黑方小写) +% 出于对国际象棋棋手意识习惯的兼容性设计 +% 相 B ,也可兼容使用 E, +% 马N, 也可兼容使用 H 代替 +% 判断红黑棋子英文单字母名称的正则表达式 +\regex_new:N \l__capital_regex +\regex_set:Nn \l__capital_regex { [KAERCHP] } +% 判断棋子英文单字母名称的正则表达式 +\clist_const:Nn \c__cchess_pieces_name_clist { K,A,E,R,C,H,P,k,a,e,r,c,h,p } +\msg_new:nnn { cchess } { piecename-exists } { The~ piece~ name~ `#1~ not~ exists. } + +% 定义棋子字符常量 +\clist_map_inline:nn + { + { K } { "5E25 }, % 帥 + { A } { "4ED5 }, % 仕 + { E } { "76F8 }, % 相 + { H } { "9A6C }, % 马 + { R } { "8F66 }, % 车 + { C } { "7832 }, % 砲 + { P } { "5175 }, % 兵 + { k } { "5C07 }, % 將 + { a } { "58EB }, % 士 + { e } { "8C61 }, % 象 + { h } { "99AC }, % 馬 + { r } { "8ECA }, % 車 + { c } { "70AE }, % 炮 + { p } { "5352 }, % 卒 + } + { \__cchess_piece_define:nn #1 } + +% 定义棋子编码与字符对照属性表 +\prop_new:N \c__cchess_board_pieces_alph_name_prop +\clist_map_inline:Nn \c__cchess_pieces_name_clist + { + \prop_put:NnV \c__cchess_board_pieces_alph_name_prop + { #1 } { \use:c { c__cchess_ #1 _tl } } + } + +% 在棋子编码列表中添加n表示空(null)棋子 +\clist_push:Nn \c__cchess_pieces_name_clist { n } + +% 定义棋子盒子容器 +\clist_map_inline:Nn \c__cchess_pieces_name_clist + { + \coffin_new:c { l__cchess_piece_ #1 _coffin } + } +% 将空棋子盒子容器置空 +\hcoffin_gset:Nn \l__cchess_piece_n_coffin { \phantom{空} } + +% 棋盘盒子容器 +\coffin_new:N \l__cchess_board_coffin +% 棋盘背景盒子容器 +\coffin_new:N \l__cchess_board_background_coffin + +% 棋谱容器 +\coffin_new:N \l__cchess_manual_coffin + +% 判断是否为字母位置的正则表达式 +\regex_new:N \l__alph_regex +\regex_set:Nn \l__alph_regex { [a-j] } + +% 棋子位置字母与数字对应关系 +\prop_const_from_keyval:Nn \c__cchess_board_pos_alph_num_prop + { + a = 0, b = 1, c = 2 , d = 3, e = 4, + f = 5, g = 6, h = 7, i = 8, j = 9 + } + +\coffin_new:N \l__cchess_board_pieces_pos_coffin + +% 判断是否为数值位置的正则表达式 +\regex_new:N \l__digit_regex +\regex_set:Nn \l__digit_regex { [0-9] } + +% 棋子位置数字与字母对应关系 +\prop_const_from_keyval:Nn \c__cchess_board_pos_num_alph_prop + { + 0 = a, 1 = b, 2 = c, 3 = d, 4 = e, + 5 = f, 6 = g, 7 = h, 8 = i, 9 = j + } + +% 判断是水平方向位置合法性的正则表达式 +\clist_const:Nn \c__cchess_pos_x_index_clist + { a,b,c,d,e,f,g,h,i,0,1,2,3,4,5,6,7,8 } +\msg_new:nnn { cchess } { posx-exists } { The~ x~ index~ `#1~ not~ exists. } +% 判断是垂直方向位置合法性的正则表达式 +\clist_const:Nn \c__cchess_pos_y_index_clist + { a,b,c,d,e,f,g,h,i,j,0,1,2,3,4,5,6,7,8,9 } +\msg_new:nnn { cchess } { posy-exists } { The~ y~ index~ `#1~ not~ exists. } + +% 棋子占位盒子容器 +\clist_const:Nn \c__cchess_board_pos_x_clist + { a,b,c,d,e,f,g,h,i } +\clist_const:Nn \c__cchess_board_pos_y_clist + { a,b,c,d,e,f,g,h,i,j } +\clist_map_inline:Nn \c__cchess_board_pos_x_clist + { + \clist_map_inline:Nn \c__cchess_board_pos_y_clist + { + \coffin_new:c { l__cchess_board_piece_ #1 _ ##1 _coffin } + \hcoffin_gset:cn { l__cchess_board_piece_ #1 _ ##1 _coffin } + { \phantom{空} } + } + } +\coffin_new:N \l__cchess_board_piece_n_coffin +\hcoffin_gset:Nn \l__cchess_board_piece_n_coffin { \phantom{空} } + +% 红方棋盘坐标字母与竖线标位对应关系 +\prop_const_from_keyval:Nn \c__cchess_board_red_x_idx_prop + { + a = 九, b = 八, c = 七 , d = 六, e = 五, + f = 四, g = 三, h = 二, i = 一 + } + +% 黑方棋盘坐标字母与竖线标位对应关系 +\prop_const_from_keyval:Nn \c__cchess_board_black_x_idx_prop + { + a = 1, b = 2, c = 3 , d = 4, e = 5, + f = 6, g = 7, h = 8, i = 9 + } + +% 英文数字与中文数字的对应关系 +\prop_const_from_keyval:Nn \c__cchess_board_pos_arabic_zh_prop + { + 0 = 〇, 1 = 一, 2 = 二, 3 = 三, 4 = 四, + 5 = 五, 6 = 六, 7 = 七, 8 = 八, 9 = 九 + } + +% 棋谱文字说明列表(如车一进二等) +\clist_new:N \l__cchess_manual_clist + +% 棋子外框盒子容器 +\coffin_new:N \l__cchess_box_coffin +% 棋子盒子容器 +\coffin_new:N \l__cchess_piece_coffin +% 楚河汉界盒子容器 +\coffin_new:N \l__cchess_char_a_coffin +\coffin_new:N \l__cchess_char_b_coffin +\coffin_new:N \l__cchess_char_c_coffin +\coffin_new:N \l__cchess_char_d_coffin +% 临时盒子容器 +\coffin_new:N \l__cchess_tmpa_coffin +\coffin_new:N \l__cchess_tmpb_coffin +\coffin_new:N \l__cchess_tmpc_coffin +\coffin_new:N \l__cchess_tmpd_coffin + +\clist_set:Nn \l_tmpa_clist { a,b,c,d } +\clist_map_inline:Nn \l_tmpa_clist + { + \coffin_new:c { l_char_tmp #1 _coffin } + } + +% 棋子字符包围盒尺寸 +\dim_new:N \charboxsize +% 棋子字符包围盒尺寸半长 +\dim_new:N \semicharboxsize +% 棋子整体尺寸 +\dim_new:N \piecesize +% 棋盘格子尺寸 +\dim_new:N \gridsize +% 棋子缩放比例 +\tl_new:N \l__cchess_piece_scale_tl +% 待处理棋子字符 +\tl_new:N \l__cchess_pieces_tl +% 棋子字符格式 +\tl_new:N \l__cchess_piece_char_format_tl +% 棋盘背景图片名称 +\tl_new:N \l__cchess_board_background_tl +% 棋子字符字形类型(实线、虚线等) +\int_new:N \l__cchess_charstroke_type_int + +% 打谱环境用计数器 +% \int_new:N \c@cchessman + +% 增加两个临时int变量 +\int_new:N \l_tmpc_int +\int_new:N \l_tmpd_int +\int_new:N \l_tmpe_int +% 增加两个临时tl变量 +\tl_new:N \l_tmpc_tl +\tl_new:N \l_tmpd_tl +\tl_new:N \l_tmpe_tl + + +% 棋子盒子由l3draw实现, +% 棋子外围盒子及缩放设计思路来自zitie宏包(\url{https://www.ctan.org/pkg/zitie})。 + +% =============颜色处理函数============= +% 填充色辅助函数 +\cs_new_nopar:Nn \__cchess_aux_color_boxfill: + { } + +% 颜色命名函数 +% #1 颜色名称 +% #2 颜色表达式 +\cs_set_nopar:Npn \__cchess_color_select:nn #1#2 + { + \color_set:nn {#1} {#2} + } +\cs_generate_variant:Nn \__cchess_color_select:nn {nx} + +% 颜色命名函数 +% #1 颜色名称 +% #2 颜色空间 +% #3 颜色分量值 +\cs_set_nopar:Npn \__cchess_color_select:nnn #1#2#3 + { + \color_set:nnn {#1} {#2} {#3} + } +\cs_generate_variant:Nn \__cchess_color_select:nnn {nnx} + +% =============基础尺寸计算函数============= +% 盒子容器总高度计算函数 +\cs_new_nopar:Npn \__cchess_coffin_ht_plus_dp:N #1 + { + \coffin_ht:N #1 + \coffin_dp:N #1 + } + +% 计算基字符外框大小(外接正方形边长和外接圆半径) +\cs_new:Npn \__cchess_calc_piece_box_size: + { + % 设置基字符格式的基字符盒子 + \hbox_set:Nn \l_tmpa_box { 将 } + + % 盒子宽度 + \dim_set:Nn \l_tmpa_dim + { + \box_wd:N \l_tmpa_box + } + % 盒子高度 + \dim_set:Nn \l_tmpb_dim + { + \box_ht_plus_dp:N \l_tmpa_box + } + + % 正方形边长 + \dim_compare:nNnTF \l_tmpa_dim > \l_tmpb_dim + { + \dim_gset_eq:NN \charboxsize \l_tmpa_dim + } + { + \dim_gset_eq:NN \charboxsize \l_tmpb_dim + } + + \dim_gadd:Nn \charboxsize { 2pt } + + % 包围盒半长 + \dim_gset:Nn \semicharboxsize + { + \fp_to_dim:n { \fp_eval:n { \charboxsize / 2 } } + } + + % 外接圆半径 + \dim_gset:Nn \l__cchess_piece_box_radius_dim + { + \fp_to_dim:n { \fp_eval:n { \charboxsize * sqrt(2)/ 2 } } + } + } + +% =============构造棋子函数============= +% 字符盒子构造类型函数名称生成函数 +% 名称中6个参数分别表示: +% #1 左下角x坐标 +% #2 左下角y坐标 +% #3 右上角x坐标 +% #4 右上角y坐标 +% #5 x方向缩放比例(扩展保留参数) +% #6 y方向缩放比例(扩展保留参数) +\cs_new_nopar:Npn \__cchess_piece_box_type:n #1 + { + __cchess_piece_box_construct_type_ #1 :n + } +% 字符盒子构造类型函数名称命令生成函数 +% 名称命令中6个参数分别表示: +% #1 左下角x坐标 +% #2 左下角y坐标 +% #3 右上角x坐标 +% #4 右上角y坐标 +% #5 x方向缩放比例(扩展保留参数) +% #6 y方向缩放比例(扩展保留参数) +\cs_new_nopar:Npn \__cchess_piece_box_type_c:n #1 + { + \use:c + { + __cchess_piece_box_construct_type_ #1 :n + } + } + +% 字符盒子构造类型函数内部生成器函数 +% #1 类型名称 +\cs_new:Npn \__cchess_new_piece_box_private_construct:nn #1 + { + % 类似\cs_new:cn __cchess_piece_box_construct_type_none:n + \cs_new:cn { \__cchess_piece_box_type:n {#1} } + } +\cs_generate_variant:Nn \__cchess_new_piece_box_private_construct:nn { V } +\cs_generate_variant:Nn \__cchess_new_piece_box_private_construct:nn { x } + +% 字符盒子构造类型函数生成器函数 +% #1 类型名称 +\cs_new:Npn \__cchess_new_piece_box_construct:nn #1 + { + % 将类型名称记入clist + \clist_put_right:Nn \g__cchess_piece_box_list_clist {#1} + % 类似\cs_new:cn __cchess_piece_box_construct_type_none:n + \cs_new:cn { \__cchess_piece_box_type:n {#1} } + } +\cs_generate_variant:Nn \__cchess_new_piece_box_construct:nn { V } +\cs_generate_variant:Nn \__cchess_new_piece_box_construct:nn { x } + +% 定义字符边框盒子类型内部函数 +% 无边框 +\__cchess_new_piece_box_construct:nn { none } { } + +% 填充外接圆 +\__cchess_new_piece_box_private_construct:nn { __outerfilledcircle } + { + \draw_scope_begin: + \color_fill:n { lowerbgboxfill } + \draw_path_circle:nn { \semicharboxsize, \semicharboxsize } + { \l__cchess_piece_box_radius_dim*#1 } + \draw_path_use_clear:n { fill } + \draw_scope_end: + } + +% 底层填充外接圆 +\__cchess_new_piece_box_private_construct:nn { __outerlowerfilledcircle } + { + \draw_scope_begin: + \color_fill:n { lowerbgboxfill } + \draw_path_circle:nn { \semicharboxsize, \semicharboxsize } + { \l__cchess_piece_box_radius_dim*#1 } + \draw_path_use_clear:n { fill } + \draw_scope_end: + } + +% 顶层填充外接圆 +\__cchess_new_piece_box_private_construct:nn { __outerupperfilledcircle } + { + \draw_scope_begin: + \color_fill:n { upperbgboxfill } + \draw_path_circle:nn { \semicharboxsize, \semicharboxsize } + { \l__cchess_piece_box_radius_dim*#1 } + \draw_path_use_clear:n { fill } + \draw_scope_end: + } + +% 圆环层填充外接圆 +\__cchess_new_piece_box_private_construct:nn { __outerdonutfilledcircle } + { + \draw_scope_begin: + \color_fill:n { donutboxfill } + \draw_path_circle:nn { \semicharboxsize, \semicharboxsize } + { \l__cchess_piece_box_radius_dim*#1 } + \draw_path_use_clear:n { fill } + \draw_scope_end: + } + +% 阴影填充外接圆 +\__cchess_new_piece_box_private_construct:nn { __outershadowfilledcircle } + { + \draw_scope_begin: + \color_fill:n { shadowboxfill } + \draw_transform_shift:n { \charboxsize*0.1, -\charboxsize*0.1 } + \draw_path_circle:nn { \semicharboxsize, \semicharboxsize } + { \l__cchess_piece_box_radius_dim*#1 } + \draw_path_use_clear:n { fill } + \draw_scope_end: + } + +% 外接圆边框 +\__cchess_new_piece_box_private_construct:nn { __outercirclebox } + { + \draw_scope_begin: + \color_stroke:n { cchesspieceboxcolor } + \draw_path_circle:nn { \semicharboxsize, \semicharboxsize } + { \l__cchess_piece_box_radius_dim*#1 } + \draw_path_use_clear:n { stroke } + \draw_scope_end: + } + +% 填充外接圆叠加外接圆边框 +\__cchess_new_piece_box_construct:nn { o } + { + \__cchess_piece_box_type_c:n { __outerupperfilledcircle } {#1} + \__cchess_piece_box_type_c:n { __outercirclebox } {#1} + } + +% 填充外接圆叠加同心82%外接圆边框 +\__cchess_new_piece_box_construct:nn { oo } + { + \__cchess_piece_box_type_c:n { __outerupperfilledcircle } {#1} + \__cchess_piece_box_type_c:n { __outercirclebox } {#1} + \__cchess_piece_box_type_c:n { __outercirclebox } {0.82} + } + +% 3同心圆叠加(阴影) +\__cchess_new_piece_box_construct:nn { ooo } + { + % 绘制填充外接圆阴影 + \__cchess_piece_box_type_c:n { __outershadowfilledcircle } {1.0} + % 绘制填充外接圆外圈背景 + \__cchess_piece_box_type_c:n { __outerlowerfilledcircle } {1.0} + % 绘制填充外接边环背景 + \__cchess_piece_box_type_c:n { __outerdonutfilledcircle } {0.88} + % 绘制填充外接圆内圈背景 + \__cchess_piece_box_type_c:n { __outerupperfilledcircle } {0.72} + % 绘制双边刻环线 + \__cchess_piece_box_type_c:n { __outercirclebox } {0.88} + \__cchess_piece_box_type_c:n { __outercirclebox } {0.72} + } + +\msg_new:nnn { cchess } { box-exists } { The~ box~ type~ `#1~ not~ exists. } + +% =============构造棋盘函数============= +% 棋盘部件构造函数函数名称生成函数 +% 名称中2个参数分别表示: +% #1 x方向缩放比例(暂未使用保留参数) +% #2 y方向缩放比例(暂未使用保留参数) +\cs_new_nopar:Npn \__cchess_board_type:n #1 + { + __cchess_board_construct_type_ #1 :nn + } +% 字符盒子构造类型函数名称命令生成函数 +% 名称命令中2个参数分别表示: +% #1 x方向缩放比例(暂未使用保留参数) +% #2 y方向缩放比例(暂未使用保留参数) +\cs_new_nopar:Npn \__cchess_board_type_c:n #1 + { + \use:c + { + __cchess_board_construct_type_ #1 :nn + } + } + +% 字符盒子构造类型函数生成器内部函数 +% #1 类型名称 +\cs_new:Npn \__cchess_new_board_private_construct:nn #1 + { + % 类似\cs_new:cn __cchess_board_construct_type_none:nn + \cs_new:cn { \__cchess_board_type:n {#1} } + } +\cs_generate_variant:Nn \__cchess_new_board_private_construct:nn { V } +\cs_generate_variant:Nn \__cchess_new_board_private_construct:nn { x } + +% 字符盒子构造类型函数生成器函数 +% #1 类型名称 +\cs_new:Npn \__cchess_new_board_construct:nn #1 + { + % 将类型名称记入clist + \clist_put_right:Nn \g__cchess_board_list_clist {#1} + % 类似\cs_new:cn __cchess_board_construct_type_none:nn + \cs_new:cn { \__cchess_board_type:n {#1} } + } +\cs_generate_variant:Nn \__cchess_new_board_construct:nn { V } +\cs_generate_variant:Nn \__cchess_new_board_construct:nn { x } + +% 无棋盘 +\__cchess_new_board_construct:nn { none } { } + +% 半部棋盘 +\__cchess_new_board_private_construct:nn { __semiboard } + { + \draw_scope_begin: + \color_stroke:n { cchessboardlinecolor } + % 绘制棋盘网格 + \draw_path_grid:nnnn { \gridsize } { \gridsize } + { 0, 0 } { \gridsize * 8, \gridsize * 4 } + + % 绘制半长边格线 + \draw_path_moveto:n { 0 , \gridsize * 4 } + \draw_path_lineto:n { 0 , \gridsize * 4.5 } + \draw_path_moveto:n { \gridsize * 8, \gridsize * 4 } + \draw_path_lineto:n { \gridsize * 8, \gridsize * 4.5 } + + \draw_path_use_clear:n { stroke } + \draw_scope_end: + } + +% 兵、炮4分位标志(右上) +\__cchess_new_board_private_construct:nn { __quaterpos } + { + % 计算标志长度 + \dim_set:Nn \l_tmpa_dim + { \fp_to_dim:n { \fp_eval:n { \gridsize * 0.10 } } } + + \draw_scope_begin: + \color_stroke:n { cchessboardlinecolor } + \draw_path_scope_begin: + \draw_linewidth:n { \l__cchess_cross_linewidth_dim } + \draw_path_moveto:n { 0pt , \l_tmpa_dim } + \draw_path_lineto:n { 0pt , 0pt } + \draw_path_lineto:n { \l_tmpa_dim, 0pt } + \draw_path_use_clear:n { stroke } + \draw_path_scope_end: + \draw_scope_end: + } + +% 兵、炮全位标志 +\__cchess_new_board_private_construct:nn { __fullpos } + { + \draw_scope_begin: + \draw_path_scope_begin: + \draw_transform_shift:n { \l__cchess_cross_sep_dim, \l__cchess_cross_sep_dim } + \__cchess_board_type_c:n { __quaterpos } {#1} {#2} + \draw_path_scope_end: + \draw_path_scope_begin: + \draw_transform_shift:n { -\l__cchess_cross_sep_dim, \l__cchess_cross_sep_dim } + \draw_transform_rotate:n { 90 } + \__cchess_board_type_c:n { __quaterpos } {#1} {#2} + \draw_path_scope_end: + \draw_path_scope_begin: + \draw_transform_shift:n { -\l__cchess_cross_sep_dim, -\l__cchess_cross_sep_dim } + \draw_transform_rotate:n { 180 } + \__cchess_board_type_c:n { __quaterpos } {#1} {#2} + \draw_path_scope_end: + \draw_path_scope_begin: + \draw_transform_shift:n { \l__cchess_cross_sep_dim, -\l__cchess_cross_sep_dim } + \draw_transform_rotate:n { 270 } + \__cchess_board_type_c:n { __quaterpos } {#1} {#2} + \draw_path_scope_end: + \draw_scope_end: + } + +% 右向兵半位标志 +\__cchess_new_board_private_construct:nn { __rightsemipos } + { + \draw_scope_begin: + \draw_path_scope_begin: + \draw_transform_shift:n { \l__cchess_cross_sep_dim, \l__cchess_cross_sep_dim } + \__cchess_board_type_c:n { __quaterpos } {#1} {#2} + \draw_path_scope_end: + \draw_path_scope_begin: + \draw_transform_shift:n { \l__cchess_cross_sep_dim, -\l__cchess_cross_sep_dim } + \draw_transform_rotate:n { -90 } + \__cchess_board_type_c:n { __quaterpos } {#1} {#2} + \draw_path_scope_end: + \draw_scope_end: + } + +% 左向兵半位标志 +\__cchess_new_board_private_construct:nn { __leftsemipos } + { + \draw_scope_begin: + \draw_path_scope_begin: + \draw_transform_shift:n { -\l__cchess_cross_sep_dim, \l__cchess_cross_sep_dim } + \draw_transform_rotate:n { 90 } + \__cchess_board_type_c:n { __quaterpos } {#1} {#2} + \draw_path_scope_end: + \draw_path_scope_begin: + \draw_transform_shift:n { -\l__cchess_cross_sep_dim, -\l__cchess_cross_sep_dim } + \draw_transform_rotate:n { 180 } + \__cchess_board_type_c:n { __quaterpos } {#1} {#2} + \draw_path_scope_end: + \draw_scope_end: + } + +% 兵、炮标志 +\__cchess_new_board_private_construct:nn { __semipos } + { + \hcoffin_set:Nn \l_tmpa_coffin + { + \draw_scope_begin: + % 绘制兵、炮定位标志 + \clist_map_variable:nNn {{1,2},{7,2},{2,3},{4,3},{6,3}} \l_tmpa_tl + { + \clist_set:NV \l_tmpa_clist \l_tmpa_tl + \dim_set:Nn \l_tmpa_dim + { + \fp_to_dim:n + { + \fp_eval:n { \gridsize * \clist_item:Nn \l_tmpa_clist { 1 } } + } + } + \dim_set:Nn \l_tmpb_dim + { + \fp_to_dim:n + { + \fp_eval:n { \gridsize * \clist_item:Nn \l_tmpa_clist { 2 } } + } + } + \draw_path_scope_begin: + \draw_transform_shift:n { \l_tmpa_dim, \l_tmpb_dim } + \__cchess_board_type_c:n { __fullpos } {#1} {#2} + \draw_path_scope_end: + } + + \draw_path_scope_begin: + \draw_transform_shift:n { 0, \gridsize * 3 } + \__cchess_board_type_c:n { __rightsemipos } {#1} {#2} + \draw_path_scope_end: + + \draw_path_scope_begin: + \draw_transform_shift:n { \gridsize * 8, \gridsize * 3 } + \__cchess_board_type_c:n { __leftsemipos } {#1} {#2} + \draw_path_scope_end: + + \draw_scope_end: + } + % 使用盒子容器 + \draw_path_scope_begin: + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + \draw_path_scope_end: + } + +% 无兵、炮标志全棋盘 +\__cchess_new_board_private_construct:nn { __semiboardwithpos } + { + \hcoffin_set:Nn \l_tmpa_coffin + { + \__cchess_board_type_c:n { __semiboard } {#1} {#2} + \__cchess_board_type_c:n { __semipos } {#1} {#2} + } + % 使用盒子容器 + \draw_path_scope_begin: + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + \draw_path_scope_end: + } + +% 九宫对角线 +\__cchess_new_board_private_construct:nn { __dguardcross } + { + \draw_scope_begin: + \color_stroke:n { cchessboardlinecolor } + \draw_path_scope_begin: + \draw_linewidth:n { \l__cchess_cross_linewidth_dim } + \draw_transform_shift:n { \gridsize * 3, 0 } + + \draw_path_moveto:n { 0 , \gridsize * 2 } + \draw_path_lineto:n { \gridsize * 2, 0 } + \draw_path_moveto:n { 0 , 0 } + \draw_path_lineto:n { \gridsize * 2, \gridsize * 2 } + \draw_path_use_clear:n { stroke } + \draw_path_scope_end: + \draw_scope_end: + } + +% 象位线 +\__cchess_new_board_private_construct:nn { __elephantcross } + { + \draw_scope_begin: + \color_stroke:n { cchessboardlinecolor } + \draw_path_scope_begin: + \draw_linewidth:n { \l__cchess_cross_linewidth_dim } + \draw_dash_pattern:nn { 0.5mm , 0.5mm , 0.5mm , 0.5mm } { 0cm } + \draw_path_moveto:n { \gridsize * 2, 0 } + \draw_path_lineto:n { \gridsize * 6, \gridsize * 4 } + \draw_path_lineto:n { \gridsize * 8, \gridsize * 2 } + \draw_path_lineto:n { \gridsize * 6, 0 } + \draw_path_lineto:n { \gridsize * 2, \gridsize * 4 } + \draw_path_lineto:n { 0 , \gridsize * 2 } + \draw_path_lineto:n { \gridsize * 2, 0 } + \draw_path_use_clear:n { stroke } + \draw_path_scope_end: + \draw_scope_end: + } + +% 带炮、兵位标志和九宫对角线的半棋盘 +\__cchess_new_board_private_construct:nn { __semiboardposdguardcross } + { + \hcoffin_set:Nn \l_tmpa_coffin + { + \__cchess_board_type_c:n { __semiboardwithpos } {#1} {#2} + \__cchess_board_type_c:n { __dguardcross } {#1} {#2} + } + % 使用盒子容器 + \draw_path_scope_begin: + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + \draw_path_scope_end: + } + +% 使用盒子容器函数变体 +\cs_generate_variant:Nn \draw_coffin_use:Nnn { c } + +% 构建楚河汉界 +\__cchess_new_board_private_construct:nn { __midseptext } + { + + \color_select:n { cchessboardlinecolor } + + \hcoffin_set:Nn \l_char_tmpa_coffin { 河 } + \hcoffin_set:Nn \l_char_tmpb_coffin { 楚 } + \hcoffin_set:Nn \l_char_tmpc_coffin { 漢 } + \hcoffin_set:Nn \l_char_tmpd_coffin { 界 } + + \clist_map_inline:nn { a, b } + { + \coffin_rotate:cn { l_char_tmp ##1 _coffin } { -90 } + } + \clist_map_inline:nn { c, d } + { + \coffin_rotate:cn { l_char_tmp ##1 _coffin } { 90 } + } + + % 测量盒子容器总高度(用内切圆则不需要) + \dim_set:Nn \l_tmpa_dim + { \__cchess_coffin_ht_plus_dp:N \l_char_tmpa_coffin } + + \dim_set:Nn \l_tmpb_dim + { + \fp_to_dim:n { \fp_eval:n { \gridsize * 0.45 } } + } + + \clist_map_inline:Nn \l_tmpa_clist + { + \coffin_scale:cnn { l_char_tmp ##1 _coffin } + { + \dim_ratio:nn { \l_tmpb_dim } { \l_tmpa_dim } + }{ + \dim_ratio:nn { \l_tmpb_dim } { \l_tmpa_dim } + } + } + + % 排版文字 + \draw_scope_begin: + \int_set:Nn \l_tmpa_int { 1 } + \clist_map_inline:Nn \l_tmpa_clist + { + \draw_path_scope_begin: + \draw_transform_shift:n + { \gridsize * \l_tmpa_int, \gridsize * 4.5 } + \draw_coffin_use:cnn { l_char_tmp ##1 _coffin } { hc } { vc } + \draw_path_scope_end: + \int_incr:N \l_tmpa_int + \int_incr:N \l_tmpa_int + } + \draw_scope_end: + } + +% 构建数字标识 +\__cchess_new_board_private_construct:nn { __tbnumtext } + { + \dim_set:Nn \l__cchess_tmpc_dim + { + \fp_to_dim:n { \fp_eval:n { \gridsize * 9 + \gridsize * 0.7 } } + } + \dim_set:Nn \l__cchess_tmpd_dim + { + \fp_to_dim:n { \fp_eval:n { -\gridsize * 0.7 } } + } + + \color_select:n { cchessboardlinecolor } + + \clist_set:Nn \l_tmpa_clist { 1,2,3,4,5,6,7,8,9 } + \clist_set:Nn \l_tmpb_clist { 九,八,七,六,五,四,三,二,一 } + + \hcoffin_set:Nn \l_tmpa_coffin { 五 } + + % 测量盒子容器总高度 + \dim_set:Nn \l_tmpa_dim + { \__cchess_coffin_ht_plus_dp:N \l_tmpa_coffin } + + \dim_set:Nn \l_tmpb_dim + { + \fp_to_dim:n { \fp_eval:n { \gridsize * 0.25 } } + } + + \draw_scope_begin: + \int_set:Nn \l_tmpa_int { 0 } + \clist_map_inline:Nn \l_tmpa_clist + { + \clist_pop:NN \l_tmpb_clist \l_tmpa_tl + \hcoffin_set:Nn \l_tmpa_coffin { ##1 } + \hcoffin_set:Nn \l_tmpb_coffin { \l_tmpa_tl } + \coffin_scale:Nnn \l_tmpa_coffin + { + \dim_ratio:nn { \l_tmpb_dim } { \l_tmpa_dim } + }{ + \dim_ratio:nn { \l_tmpb_dim } { \l_tmpa_dim } + } + \coffin_scale:Nnn \l_tmpb_coffin + { + \dim_ratio:nn { \l_tmpb_dim } { \l_tmpa_dim } + }{ + \dim_ratio:nn { \l_tmpb_dim } { \l_tmpa_dim } + } + + \draw_path_scope_begin: + \draw_transform_shift:n + { \gridsize * \l_tmpa_int, \l__cchess_tmpc_dim } + \draw_coffin_use:Nnn \l_tmpa_coffin { hc } { vc } + \draw_path_scope_end: + + \draw_path_scope_begin: + \draw_transform_shift:n + { \gridsize * \l_tmpa_int, \l__cchess_tmpd_dim } + \draw_coffin_use:Nnn \l_tmpb_coffin { hc } { vc } + \draw_path_scope_end: + + \int_incr:N \l_tmpa_int + } + \draw_scope_end: + } + +% 无兵、炮标志全棋盘 +\__cchess_new_board_construct:nn { x } + { + \hcoffin_set:Nn \l_tmpa_coffin + { + \__cchess_board_type_c:n { __semiboard } {#1} {#2} + \__cchess_board_type_c:n { __dguardcross } {#1} {#2} + } + % 下半部 + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + + % 上半部 + \draw_path_scope_begin: + \draw_transform_shift:n { \gridsize * 8, \gridsize * 9 } + \draw_transform_rotate:n { 180 } + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + \draw_path_scope_end: + } + +% 有兵、炮标志全棋盘 +\__cchess_new_board_construct:nn { x+ } + { + \hcoffin_set:Nn \l_tmpa_coffin + { + \__cchess_board_type_c:n { __semiboardwithpos } {#1} {#2} + \__cchess_board_type_c:n { __dguardcross } {#1} {#2} + } + % 下半部 + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + + % 上半部 + \draw_path_scope_begin: + \draw_transform_shift:n { \gridsize * 8, \gridsize * 9 } + \draw_transform_rotate:n { 180 } + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + \draw_path_scope_end: + } + +% 有兵、炮标志全棋盘 +\__cchess_new_board_construct:nn { x+t } + { + \hcoffin_set:Nn \l_tmpa_coffin + { + \__cchess_board_type_c:n { __semiboardwithpos } {#1} {#2} + \__cchess_board_type_c:n { __dguardcross } {#1} {#2} + } + % 下半部 + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + + % 上半部 + \draw_path_scope_begin: + \draw_transform_shift:n { \gridsize * 8, \gridsize * 9 } + \draw_transform_rotate:n { 180 } + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + \draw_path_scope_end: + \__cchess_board_type_c:n { __midseptext } {#1} {#2} + } + +% 有兵、炮标志全棋盘 +\__cchess_new_board_construct:nn { x+tn } + { + \hcoffin_set:Nn \l_tmpa_coffin + { + \__cchess_board_type_c:n { __semiboardwithpos } {#1} {#2} + \__cchess_board_type_c:n { __dguardcross } {#1} {#2} + } + % 下半部 + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + + % 上半部 + \draw_path_scope_begin: + \draw_transform_shift:n { \gridsize * 8, \gridsize * 9 } + \draw_transform_rotate:n { 180 } + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + \draw_path_scope_end: + \__cchess_board_type_c:n { __midseptext } {#1} {#2} + \__cchess_board_type_c:n { __tbnumtext } {#1} {#2} + } + +% 有兵、炮标志和象位线的全棋盘 +\__cchess_new_board_construct:nn { x+Xtn } + { + \hcoffin_set:Nn \l_tmpa_coffin + { + \__cchess_board_type_c:n { __semiboardwithpos } {#1} {#2} + \__cchess_board_type_c:n { __dguardcross } {#1} {#2} + \__cchess_board_type_c:n { __elephantcross } {#1} {#2} + } + % 下半部 + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + + % 上半部 + \draw_path_scope_begin: + \draw_transform_shift:n { \gridsize * 8, \gridsize * 9 } + \draw_transform_rotate:n { 180 } + \draw_coffin_use:Nnn \l_tmpa_coffin { l } { b } + \draw_path_scope_end: + \__cchess_board_type_c:n { __midseptext } {#1} {#2} + \__cchess_board_type_c:n { __tbnumtext } {#1} {#2} + } + +\msg_new:nnn { cchess } { board-exists } { The~ board~ type~ `#1~ not~ exists. } + +% =============缩放处理函数============= +% 缩放类型名称生成函数 +\cs_new_nopar:Npn \__cchess_resize:n #1 + { + __cchess_processor_resize_ #1 :w + } + +% 缩放类型函数名称命令生成函数 +\cs_new_nopar:Npn \__cchess_resize_c:n #1 + { + \use:c + { + __cchess_processor_resize_ #1 :w + } + } + +% 缩放代码生成函数 +% #1 dim长度变量1 +% #2 dim长度变量2 +% #3 缩放代码1 +% #4 缩放代码2 +% #5 缩放代码3 +% #6 缩放代码4 +% 如果 #1 > 0 且 #2 > 0 ,取#3代码 +% 如果 #1 > 0 且 #2 <= 0,取#4代码 +% 如果 #1 <= 0 且 #2 > 0 ,取#5代码 +% 如果 #1 <= 0 且 #2 <= 0,取#6代码 +\cs_new:Npn \__cchess_dim_gezero_dispatch:NNnnnn #1#2 #3#4#5#6 + { + \dim_compare:nNnTF #1 > \c_zero_dim + { + \dim_compare:nNnTF #2 > \c_zero_dim + { #3 } { #4 } + } + { + \dim_compare:nNnTF #2 > \c_zero_dim + { #5 } { #6 } + } + } + +% 缩放代码生成函数(分别按高宽、高度、宽度或实际尺寸缩放) +\cs_new:Npn \__cchess_force_size_dispatch:nnnn % both, height, width, none + { + % \dim_show:N \l__cchess_manual_width_dim + \__cchess_dim_gezero_dispatch:NNnnnn \l__cchess_manual_height_dim + \l__cchess_manual_width_dim + } + +% 构造缩放类型 +\cs_new:Npn \__cchess_new_resize_method:nn #1 + { + \clist_put_right:Nn \g__cchess_resize_method_clist {#1} + \cs_new:cpn { \__cchess_resize:n {#1} } + } + +% 无缩放 +\__cchess_new_resize_method:nn { none } { } + +% 按实际参数缩放 +\__cchess_new_resize_method:nn { real } + { + \__cchess_force_size_dispatch:nnnn + {% 盒子宽高缩放 + \coffin_resize:Nnn \l__cchess_manual_coffin + \l__cchess_manual_width_dim + \l__cchess_manual_height_dim + } + {% 指定高度为比例缩放 + \coffin_scale:Nnn \l__cchess_manual_coffin + { + \dim_ratio:nn { \l__cchess_manual_height_dim } + { \__cchess_coffin_ht_plus_dp:N \l__cchess_manual_coffin } + } + { + \dim_ratio:nn { \l__cchess_manual_height_dim } + { \__cchess_coffin_ht_plus_dp:N \l__cchess_manual_coffin } + } + } + {% 指定宽度为比例缩放 + \coffin_scale:Nnn \l__cchess_manual_coffin + { + \dim_ratio:nn { \l__cchess_manual_width_dim } + { \coffin_wd:N \l__cchess_manual_coffin } + } + { + \dim_ratio:nn { \l__cchess_manual_width_dim } + { \coffin_wd:N \l__cchess_manual_coffin } + } + } + {% 实际宽、高比例缩放 + \coffin_scale:Nnn \l__cchess_manual_coffin + { \l__cchess_x_scale_tl } + { \l__cchess_y_scale_tl } + } + } +\msg_new:nnn { cchess } { resize-type } { using~ `#1'~ resize. } + +% 笔画设置函数 +\cs_new:Npn \__cchess_pieces_stroke:nn #1#2 + { + \special { pdf:code ~ q ~ #1 } #2 \special { pdf:code ~ Q } + } +% 笔画构造函数 +\cs_new_protected:Npn \__cchess_pieces_stroke_construct:n #1 + { + \int_case:nn {\l__cchess_charstroke_type_int} + { + {1}{ #1 } + {2}{ + \__cchess_pieces_stroke:nn { 1~Tr~0.25~w~[]~0~d~1~J } {#1} + } + {3}{ + \__cchess_pieces_stroke:nn { 2~Tr~0.25~w~[]~0~d~1~J~1~1~1~RG~1~1~1~rg } {#1} + } + {4}{ + \__cchess_pieces_stroke:nn { 2~Tr~0.25~w } {#1} + } + {5}{ + \__cchess_pieces_stroke:nn { 3 ~ Tr } {#1} + } + } + } +\cs_generate_variant:Nn \__cchess_pieces_stroke_construct:n { V } +\cs_generate_variant:Nn \__cchess_pieces_stroke_construct:n { x } + +% =============棋子文字设置函数============= +% 设置棋子的文字 +% 红棋编码用大写字母,默认: +% K=帅,A=仕,E=相,R=车,C=砲,H=马,P=兵 +% 黑棋编码用小字字母,默认: +% k=将,a=士,e=象,r=車,c=炮,h=馬,p=卒 +% #1 棋子编码 +% #2 棋子字符 +\cs_new_nopar:Npn \__cchess_piece_char_setup:nn #1#2 + { + \prop_gput:Nnn \c__cchess_board_pieces_alph_name_prop + { #1 } { #2 } + } + +% key_value选项设计 +\keys_define:nn { cchess } + { + % 缩放参数 + gridsize .code:n = { \dim_set:Nn \gridsize { #1 } + % 棋子尺寸 + \dim_set:Nn \piecesize + { + \fp_to_dim:n { \fp_eval:n { \gridsize * 0.9 } } + } + } , + gridsize .initial:n = 10mm , + % 棋盘类型 + boardtype .code:n = { \exp_args:NNx \clist_if_in:NnTF + \g__cchess_board_list_clist {#1} + { \tl_set:Nx \l__cchess_board_type_tl {#1} } + { \msg_error:nnx { cchess } { board-exists } {#1} } + }, + % 棋盘线线宽 + boardlinewd .code:n = { \dim_set:Nn \l__cchess_board_linewidth_dim {#1} + % 九宫线与象位线线宽 + \dim_gset:Nn \l__cchess_cross_linewidth_dim + { + \fp_to_dim:n + { + \fp_eval:n { \l__cchess_board_linewidth_dim * 0.50 } + } + } + % 炮兵位置线与棋盘线间距 + \dim_gset:Nn \l__cchess_cross_sep_dim + { + \fp_to_dim:n + { + \fp_eval:n { \l__cchess_board_linewidth_dim * 1.80 } + } + } + }, + boardlinewd .initial:n = 0.4pt , + + % 棋盘线颜色 + boardlinecolor .code:n = { \__cchess_color_select:nn { cchessboardlinecolor } {#1} } , + boardlinecolor .initial:n = black , + boardlinecolor* .code:n = { \__cchess_color_select:nnn { cchessboardlinecolor } #1 } , + + % 设置棋子字符 + piecechar .code:n = { \__cchess_piece_char_setup:nn #1 }, + piecechar .initial:n = {K}{\c__cchess_K_tl} , + + % 字符格式 + piecefont .code:n = { \tl_set:Nn \l__cchess_piece_char_format_tl {#1} + \__cchess_calc_piece_box_size: + }, + + % 边框类型 + piecetype .code:n = { \exp_args:NNx \clist_if_in:NnTF + \g__cchess_piece_box_list_clist {#1} + { \tl_set:Nx \l__cchess_piece_box_type_tl {#1} } + { \msg_error:nnx { cchess } { box-exists } {#1} } + }, + % 缩放方式 + resize .code:n = { \exp_args:NNx \clist_if_in:NnTF + \g__cchess_resize_method_clist {#1} + { \tl_set:Nx \l__cchess_resize_method_tl {#1} } + { \msg_error:nnx { cchess } { resize-method } {#1} } + }, + % 缩放参数 + xscale .tl_set:N = \l__cchess_x_scale_tl , + xscale .initial:n = 1 , + yscale .tl_set:N = \l__cchess_y_scale_tl , + yscale .initial:n = 1 , + scale .meta:n = { xscale = #1 , yscale = #1 } , + width .dim_set:N = \l__cchess_manual_width_dim , + height .dim_set:N = \l__cchess_manual_height_dim , + + % 字符边框线宽 + boxlinewd .dim_set:N = \l__cchess_box_linewidth_dim , + boxlinewd .initial:n = 0.4pt , + + % 边框线颜色 + boxcolor .code:n = { \__cchess_color_select:nn { cchesspieceboxcolor } {#1} } , + boxcolor .initial:n = black , + boxcolor* .code:n = { \__cchess_color_select:nnn { cchesspieceboxcolor } #1 } , + % 字符颜色 + redpiece .code:n = { \__cchess_color_select:nn { cchessredpiececolor } {#1} } , + redpiece .initial:n = red , + redpiece* .code:n = { \__cchess_color_select:nnn { cchessredpiececolor } #1 } , + blkpiece .code:n = { \__cchess_color_select:nn { cchessblkpiececolor } {#1} } , + blkpiece .initial:n = black , + blkpiece* .code:n = { \__cchess_color_select:nnn { cchessblkpiececolor } #1 } , + + % 棋子背景底层填充颜色 + lower .code:n = { \exp_args:Nx \tl_if_empty:nTF {#1} + { + \__cchess_color_select:nn { lowerbgboxfill } + { yellow!70!red } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { yellow!70!red } } + }{ \__cchess_color_select:nn { lowerbgboxfill } { #1 } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { #1 } } + } + } , + lower .initial:n = {} , + + % 无反色时上层盒子背景填充颜色 + donut .code:n = { \exp_args:Nx \tl_if_empty:nTF {#1} + { + \__cchess_color_select:nn { donutboxfill } + { yellow!80!black } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { yellow!80!black } } + }{ \__cchess_color_select:nn { donutboxfill } { #1 } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { #1 } } + } + } , + donut .initial:n = {} , + + % 棋子背景底层填充颜色 + redupper .code:n = { \exp_args:Nx \tl_if_empty:nTF {#1} + { + \__cchess_color_select:nn { redupperbgboxfill } + { yellow!70!red } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { yellow!70!red } } + }{ \__cchess_color_select:nn { redupperbgboxfill } { #1 } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { #1 } } + } + } , + redupper .initial:n = {} , + + % 棋子背景底层填充颜色 + blkupper .code:n = { \exp_args:Nx \tl_if_empty:nTF {#1} + { + \__cchess_color_select:nn { blkupperbgboxfill } + { yellow!70!red } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { yellow!70!red } } + }{ \__cchess_color_select:nn { blkupperbgboxfill } { #1 } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { #1 } } + } + } , + blkupper .initial:n = {} , + + % 盒子阴影填充颜色 + shadow .code:n = { \exp_args:Nx \tl_if_empty:nTF {#1} + { + \__cchess_color_select:nn { shadowboxfill } + { black!35!white } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { black!35!white } } + }{ \__cchess_color_select:nn { shadowboxfill } { #1 } + \cs_set_nopar:Npn \__cchess_aux_color_boxfill: + { \color_fill:n { #1 } } + } + } , + shadow .initial:n = {} , + + % 笔画参数 + charstroke .choice:, + charstroke .value_required:n = true, + charstroke .choices:nn = + { none, solid, white, bold, invisible } + { \int_set_eq:NN \l__cchess_charstroke_type_int \l_keys_choice_int }, + charstroke .initial:n = bold, + + % 棋盘背景图片 + boardbg .tl_set:N = \l__cchess_board_background_tl , + boardbg .initial:n = {} , + + unknown .code:n = { \msg_error:nn { cchess } { unknown-option } } + } +\msg_new:nnn { cchess } { unknown-option } + { package~ option~ "\l_keys_key_tl"~ is~ unknown. } + +\keys_set:nn { cchess } + { + piecefont = \kaishu, + piecetype = ooo, + boardtype = x+tn, + resize = none, + } + +% 选项设置用户接口 +\NewDocumentCommand \cchessset { m } + { + \keys_set:nn { cchess } {#1} + } + +% =============创建棋子coffins============= +% 黑白棋子字符颜色及棋子颜色选择 +\cs_new:Npn \__cchess_pieces_color_select:n #1 + { + \regex_match:NnTF \l__capital_regex { #1 } + { + \color_set_eq:nn { cchesspiececolor } { cchessredpiececolor } + \color_set_eq:nn { upperbgboxfill } { redupperbgboxfill } + }{ + \color_set_eq:nn { cchesspiececolor } { cchessblkpiececolor } + \color_set_eq:nn { upperbgboxfill } { blkupperbgboxfill } + } + } + +% 构建棋子盒子容器 +\cs_new:Nn \__cchess_pieces_construct: + { + \group_begin: + \prop_map_inline:Nn \c__cchess_board_pieces_alph_name_prop + { + % 选择颜色 + \__cchess_pieces_color_select:n { ##1 } + % 棋子文字 + \tl_gset:Nx \l__cchess_piece_tl { ##2 } + + % 构建棋子盒子容器 + \hcoffin_set:Nn \l__cchess_piece_coffin + { + \__cchess_piece_construct:N \l__cchess_piece_tl + } + + % 缩放棋子盒子容器 + \coffin_resize:Nnn \l__cchess_piece_coffin { \piecesize }{ \piecesize } + + % 复制结果以备后续使用 + \coffin_gset_eq:cN + { l__cchess_piece_ ##1 _coffin } \l__cchess_piece_coffin + } + \group_end: + } + +% 构造带圈字符 +% #1 需要处理的字符(串)变量 +\cs_new:Npn \__cchess_piece_construct:N #1 + { + % 按指定颜色和格式构造棋子字符盒子容器 + \hcoffin_gset:Nn \l__cchess_box_coffin + { + \color_select:n { cchesspiececolor } + \tl_use:N \l__cchess_piece_char_format_tl + % 笔划处理 + \__cchess_pieces_stroke_construct:n { #1 } + } + + % 构造构造棋子字符盒子容器边框 + \__cchess_single_box_construct: + } + +% 字符盒子及边框组合盒子容器构造函数 +\cs_new:Npn \__cchess_single_box_construct: + { + % 绘制字符外框并拼装结果 + \draw_begin: + \draw_linewidth:n { \l__cchess_box_linewidth_dim } + + \draw_path_scope_begin: + \__cchess_piece_box_type_c:n { \l__cchess_piece_box_type_tl } { 1.0 } + \draw_transform_shift:n {\charboxsize / 2.0, \charboxsize / 2.0 } + \draw_coffin_use:Nnn \l__cchess_box_coffin { hc } { vc } + \draw_path_scope_end: + \draw_end: + } + +% =============创建棋子占位coffins============= + % 缩放空白棋子(n---null) +\cs_new:Nn \__cchess_board_piece_n_resize: + { + \coffin_resize:Nnn \l__cchess_piece_n_coffin { \piecesize } { \piecesize } + } +% 执行缩放 +\__cchess_board_piece_n_resize: + +% 将棋子盒子容器布置到棋盘指定位置(用于棋谱和棋盘排版) +% #1 棋子参数 +% 棋子参数的形式为{0,0}{k},{0,1}{K},注意需要包含大括号, +% 不同棋子之间用英文逗号分隔 +\cs_new:Npn \__cchess_board_piece_pos_construct:n #1 + { + \hcoffin_gset:Nn \l__cchess_board_pieces_pos_coffin + { + \draw_begin: + % 在四个角布置空白棋子实现占位(用于撑满棋子画布) + \clist_set:Nn \l_tmpa_clist + { {0, 0}{n}, {8, 0}{n}, {0, 9}{n}, {8, 9}{n}} + \clist_map_inline:Nn \l_tmpa_clist + { + \__cchess_piece_set_handle:nn ##1 + } + + % 在指定位置布置棋子 + \clist_set:Nn \l_tmpa_clist { #1 } + \clist_map_inline:Nn \l_tmpa_clist + { + \__cchess_piece_set_handle:nn ##1 + } + \draw_end: + } + } + +% =============创建棋盘背景coffin============= +% 载入背景图片 +\cs_new:Nn \__cchess_board_backgroud_construct: + { + \hcoffin_set:Nn \l__cchess_board_background_coffin + { + % 如果文件名不为空则载入图片,否则创建一个空盒子容器 + \tl_if_empty:NTF \l__cchess_board_background_tl + { + \phantom{将} + }{ + \includegraphics{\l__cchess_board_background_tl} + } + } + } + +% 组装背景图片 +\cs_new:Nn \__cchess_board_assemble: + { + % 计算棋盘+棋子后的总宽和总高 + \dim_gset:Nn \l_tmpa_dim + { + \coffin_wd:N \l__cchess_manual_coffin + } + \dim_gset:Nn \l_tmpb_dim + { + \__cchess_coffin_ht_plus_dp:N \l__cchess_manual_coffin + } + + % 放大一个棋子的长度 + \dim_add:Nn \l_tmpa_dim { \piecesize / 2 } + \dim_add:Nn \l_tmpb_dim { \piecesize / 2 } + + % 构建背景图片coffin + \__cchess_board_backgroud_construct: + + % 缩放背景图片coffin + \coffin_resize:Nnn \l__cchess_board_background_coffin + { \l_tmpa_dim } { \l_tmpb_dim } + + % 绘制总边框外线 + \hcoffin_set:Nn \l__cchess_tmpa_coffin + { + \draw_begin: + \draw_linewidth:n { \l__cchess_board_linewidth_dim * 2 } + \draw_path_rectangle:nn + { 0pt, 0pt } { \l_tmpa_dim * 0.99, \l_tmpb_dim * 0.99 } + \draw_path_use_clear:n { draw } + \draw_end: + } + + % 绘制总边框内线 + \hcoffin_set:Nn \l__cchess_tmpb_coffin + { + \draw_begin: + \draw_linewidth:n { \l__cchess_board_linewidth_dim * 1 } + \draw_path_rectangle:nn + { 0pt, 0pt } { \l_tmpa_dim * 0.97, \l_tmpb_dim * 0.97 } + \draw_path_use_clear:n { draw } + \draw_end: + } + + % 拼装结果 + \hcoffin_set:Nn \l__cchess_manual_coffin + { + \draw_begin: + \draw_path_scope_begin: + \draw_transform_shift:n { \l_tmpa_dim / 2, \l_tmpa_dim / 2 } + \draw_coffin_use:Nnn \l__cchess_board_background_coffin { hc } { vc } + \draw_coffin_use:Nnn \l__cchess_tmpa_coffin { hc } { vc } + \draw_coffin_use:Nnn \l__cchess_tmpb_coffin { hc } { vc } + \draw_coffin_use:Nnn \l__cchess_manual_coffin { hc } { vc } + \draw_path_scope_end: + \draw_end: + } + + } + +% =============创建棋盘coffins============= +\cs_new:Nn \__cchess_board_construct: + { + % 按指定类型创建棋盘 + \hcoffin_set:Nn \l__cchess_board_coffin + { + \draw_begin: + \draw_linewidth:n { \l__cchess_board_linewidth_dim } + + \draw_path_scope_begin: + \__cchess_board_type_c:n { \l__cchess_board_type_tl } { 1.0 } { 1.0 } + \draw_path_scope_end: + \draw_end: + } + + % 计算棋盘总宽和总高 + \dim_gset:Nn \l__cchess_board_width_dim + { + \coffin_wd:N \l__cchess_board_coffin + } + \dim_gset:Nn \l__cchess_board_height_dim + { + \__cchess_coffin_ht_plus_dp:N \l__cchess_board_coffin + } + } + +% =============排版棋谱============= +% 棋谱排版 +\cs_new:Npn \__cchess_manual_output:n #1 + { + % 构建棋盘 + \__cchess_board_construct: + + % 构建红黑各7个棋子 + \__cchess_pieces_construct: + + % 构建棋子画布盒子容器 + \__cchess_board_piece_pos_construct:n { #1 } + + % 将棋盘与棋子画布居中对齐后进行拼装 + \hcoffin_set:Nn \l__cchess_manual_coffin + { + \draw_begin: + \draw_path_scope_begin: + \draw_transform_shift:n + { + \l__cchess_board_width_dim / 2, + \l__cchess_board_height_dim / 2 + } + \draw_coffin_use:Nnn \l__cchess_board_coffin { hc } { vc } + \draw_coffin_use:Nnn \l__cchess_board_pieces_pos_coffin { hc } { vc } + \draw_path_scope_end: + \draw_end: + } + + % 按指定方式进行缩放 + \__cchess_resize_c:n { \l__cchess_resize_method_tl } + + % 添加背景和外框 + \__cchess_board_assemble: + + % 输出结果 + \coffin_typeset:Nnnnn \l__cchess_manual_coffin + { l }{ b } { 0pt } { 0pt } + } + +% 排版棋盘 +\cs_new:Nn \__cchess_board_output: + { + % 创建棋盘 + \__cchess_board_construct: + + % 是否需要棋子 + \bool_if:NT \l__cchess_board_pieces_bool + { + % 构建红黑各7个棋子 + \__cchess_pieces_construct: + + % 创建32个棋子画布盒子容器 + \__cchess_board_piece_pos_construct:n + { + { {0,0}{R} }, { {1,0}{H} }, { {2,0}{E} }, { {3,0}{A} }, { {4,0}{K} }, + { {5,0}{A} }, { {6,0}{E} }, { {7,0}{H} }, { {8,0}{R} }, + { {1,2}{C} }, { {7,2}{C} }, + { {0,3}{P} }, { {2,3}{P} }, { {4,3}{P} }, { {6,3}{P} }, { {8,3}{P} }, + { {0,9}{r} }, { {1,9}{h} }, { {2,9}{e} }, { {3,9}{a} }, { {4,9}{k} }, + { {5,9}{a} }, { {6,9}{e} }, { {7,9}{h} }, { {8,9}{r} }, + { {1,7}{c} }, { {7,7}{c} }, + { {0,6}{p} }, { {2,6}{p} }, { {4,6}{p} }, { {6,6}{p} }, { {8,6}{p} } + } + } + + % 拼装结果 + \hcoffin_set:Nn \l__cchess_manual_coffin + { + \draw_begin: + \draw_path_scope_begin: + \draw_transform_shift:n + { + \l__cchess_board_width_dim / 2, + \l__cchess_board_height_dim / 2 + } + \draw_coffin_use:Nnn \l__cchess_board_coffin { hc } { vc } + \bool_if:NT \l__cchess_board_pieces_bool + { + \draw_coffin_use:Nnn \l__cchess_board_pieces_pos_coffin { hc } { vc } + } + \draw_path_scope_end: + \draw_end: + } + + % 按指定方式缩放 + \__cchess_resize_c:n { \l__cchess_resize_method_tl } + + % 添加背景和外框 + \__cchess_board_assemble: + + % 输出结果 + \coffin_typeset:Nnnnn \l__cchess_manual_coffin + { l }{ b } { 0pt } { 0pt } + } + +% 设置正则匹配函数变体函数 +\cs_generate_variant:Nn \regex_match:NnT { NV } +\cs_generate_variant:Nn \regex_match:NnF { NV } + +% 利用正则匹配和属性表, +% 将字母或数字表示的棋子坐标转换为数字表示 +\cs_new:Npn \__cchess_piece_set_handle:nn #1#2 + { + \clist_set:Nn \l_tmpa_clist { #1 } + \clist_pop:NN \l_tmpa_clist \l_tmpa_tl + \clist_pop:NN \l_tmpa_clist \l_tmpb_tl + + % 判断输入合法性 + \clist_if_in:NVF \c__cchess_pos_x_index_clist \l_tmpa_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpa_tl } + } + \clist_if_in:NVF \c__cchess_pos_y_index_clist \l_tmpb_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpb_tl } + } + \clist_if_in:NnF \c__cchess_pieces_name_clist { #2 } + { + \msg_error:nnx { cchess } { piecename-exists } { #2 } + } + + % 转换坐标为数字 + \regex_match:NVT \l__alph_regex \l_tmpa_tl + { + \prop_get:NVN \c__cchess_board_pos_alph_num_prop \l_tmpa_tl \l_tmpa_tl + } + + \regex_match:NVT \l__alph_regex \l_tmpb_tl + { + \prop_get:NVN \c__cchess_board_pos_alph_num_prop \l_tmpb_tl \l_tmpb_tl + } + + % 用数字坐标定位布置棋子 + \__cchess_piece_set:VVn \l_tmpa_tl \l_tmpb_tl { #2 } + } + +% 在指定位置布置棋子 +% #1 x方向数字型坐标值(0-8) +% #2 y方向数字型坐标值(0-9) +% #3 棋子名称(单英文字母) +\cs_new:Npn \__cchess_piece_set:nnn #1#2#3 + { + \draw_path_scope_begin: + \draw_transform_shift:n { \gridsize * #1, \gridsize * #2 } + \draw_coffin_use:cnn { l__cchess_piece_ #3 _coffin } { hc } { vc } + \draw_path_scope_end: + } +\cs_generate_variant:Nn \__cchess_piece_set:nnn {VV} + +% ===采用棋子替换方式创建棋子画布coffin(用于打谱排版)=== +% 缩放棋子盒子容器 +\cs_new:Nn \__cchess_board_pieces_resize: + { + % 空白棋子 + \coffin_resize:Nnn \l__cchess_board_piece_n_coffin + { \piecesize } { \piecesize } + + % 其它棋子,按行(a-i)列(a-j)编号命名。 + \clist_map_inline:Nn \c__cchess_board_pos_x_clist + { + \clist_map_inline:Nn \c__cchess_board_pos_y_clist + { + \coffin_resize:cnn { l__cchess_board_piece_ ##1 _ ####1 _coffin } + { \piecesize } { \piecesize } + } + } + } + +% 创建字母行列编号命名棋子的占位棋子画布 +\cs_new:Nn \__cchess_board_pieces_seat: + { + % 缩放占位棋子 + \__cchess_board_pieces_resize: + + % 利用双重循环创建棋子画布 + \hcoffin_gset:Nn \l__cchess_board_pieces_pos_coffin + { + \draw_begin: + \int_zero:N \l_tmpa_int + % 扫描a-i横向位置编号列表 + \clist_map_inline:Nn \c__cchess_board_pos_x_clist + { + \int_zero:N \l_tmpb_int + % 扫描a-j纵向位置编号列表 + \clist_map_inline:Nn \c__cchess_board_pos_y_clist + { + \draw_path_scope_begin: + % 坐标平移 + \draw_transform_shift:n + { \gridsize * \l_tmpa_int, \gridsize * \l_tmpb_int } + % 布置棋子 + \draw_coffin_use:cnn + { l__cchess_board_piece_ ##1 _ ####1 _coffin } { hc } { vc } + \draw_path_scope_end: + \int_incr:N \l_tmpb_int + } + \int_incr:N \l_tmpa_int + } + \draw_end: + } + } + +% 棋子画布棋子替换句柄函数 +% 利用正则匹配和属性表, +% 将字母或数字表示的棋子坐标转换为字母表示 +\cs_new:Npn \__cchess_piece_replace_handle:nn #1#2 + { + \clist_set:Nn \l_tmpa_clist { #1 } + \clist_pop:NN \l_tmpa_clist \l_tmpa_tl + \clist_pop:NN \l_tmpa_clist \l_tmpb_tl + + % 判断输入合法性 + \clist_if_in:NVF \c__cchess_pos_x_index_clist \l_tmpa_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpa_tl } + } + \clist_if_in:NVF \c__cchess_pos_y_index_clist \l_tmpb_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpb_tl } + } + \clist_if_in:NnF \c__cchess_pieces_name_clist { #2 } + { + \msg_error:nnx { cchess } { piecename-exists } { #2 } + } + + % 转换坐标为字母 + \regex_match:NVT \l__digit_regex \l_tmpa_tl + { + \prop_get:NVN \c__cchess_board_pos_num_alph_prop \l_tmpa_tl \l_tmpa_tl + } + + \regex_match:NVT \l__digit_regex \l_tmpb_tl + { + \prop_get:NVN \c__cchess_board_pos_num_alph_prop \l_tmpb_tl \l_tmpb_tl + } + + % 用字母坐标定位布置棋子 + \__cchess_piece_replace:VVn \l_tmpa_tl \l_tmpb_tl { #2 } + } + +% 棋子占位替换函数 +% #1 x方向数字型坐标值(a-i) +% #2 y方向数字型坐标值(a-j) +% #3 棋子名称(单英文字母) +\cs_new:Npn \__cchess_piece_replace:nnn #1#2#3 + { + \coffin_gset_eq:cc + { l__cchess_board_piece_ #1 _ #2 _coffin } + { l__cchess_piece_ #3 _coffin } + } +\cs_generate_variant:Nn \__cchess_piece_replace:nnn {VV} + +% 棋子删除句柄函数 +% 利用正则匹配和属性表, +% 将字母或数字表示的棋子坐标转换为字母表示 +\cs_new:Npn \__cchess_piece_remove_handle:n #1 + { + \clist_set:Nn \l_tmpa_clist { #1 } + \clist_pop:NN \l_tmpa_clist \l_tmpa_tl + \clist_pop:NN \l_tmpa_clist \l_tmpb_tl + + % 判断输入合法性 + \clist_if_in:NVF \c__cchess_pos_x_index_clist \l_tmpa_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpa_tl } + } + \clist_if_in:NVF \c__cchess_pos_y_index_clist \l_tmpb_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpb_tl } + } + + % 转换坐标为字母 + \regex_match:NVT \l__digit_regex \l_tmpa_tl + { + \prop_get:NVN \c__cchess_board_pos_num_alph_prop \l_tmpa_tl \l_tmpa_tl + } + + \regex_match:NVT \l__digit_regex \l_tmpb_tl + { + \prop_get:NVN \c__cchess_board_pos_num_alph_prop \l_tmpb_tl \l_tmpb_tl + } + + % 用字母坐标定位布置棋子 + \__cchess_piece_remove:VV \l_tmpa_tl \l_tmpb_tl + } + +% 棋子删除函数 +% #1 x方向数字型坐标值(a-i) +% #2 y方向数字型坐标值(a-j) +% #3 棋子名称(单英文字母) +\cs_new:Npn \__cchess_piece_remove:nn #1#2 + { + \coffin_gset_eq:cN + { l__cchess_board_piece_ #1 _ #2 _coffin } + \l__cchess_board_piece_n_coffin + } +\cs_generate_variant:Nn \__cchess_piece_remove:nn {VV} + +% 棋子移动句柄函数 +% 利用正则匹配和属性表, +% 将字母或数字表示的棋子坐标转换为字母表示 +\cs_new:Npn \__cchess_piece_move_handle:nnn #1#2#3 + { + \clist_set:Nn \l_tmpa_clist { #2 } + \clist_pop:NN \l_tmpa_clist \l_tmpa_tl + \clist_pop:NN \l_tmpa_clist \l_tmpb_tl + \clist_set:Nn \l_tmpa_clist { #3 } + \clist_pop:NN \l_tmpa_clist \l_tmpc_tl + \clist_pop:NN \l_tmpa_clist \l_tmpd_tl + + % 判断输入合法性 + \clist_if_in:NVF \c__cchess_pos_x_index_clist \l_tmpa_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpa_tl } + } + \clist_if_in:NVF \c__cchess_pos_y_index_clist \l_tmpb_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpb_tl } + } + \clist_if_in:NVF \c__cchess_pos_x_index_clist \l_tmpc_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpc_tl } + } + \clist_if_in:NVF \c__cchess_pos_y_index_clist \l_tmpd_tl + { + \msg_error:nnx { cchess } { piecename-exists } { \l_tmpd_tl } + } + \clist_if_in:NnF \c__cchess_pieces_name_clist { #1 } + { + \msg_error:nnx { cchess } { piecename-exists } { #1 } + } + + % 转换坐标为字母 + \regex_match:NVT \l__digit_regex \l_tmpa_tl + { + \prop_get:NVN \c__cchess_board_pos_num_alph_prop \l_tmpa_tl \l_tmpa_tl + } + \regex_match:NVT \l__digit_regex \l_tmpb_tl + { + \prop_get:NVN \c__cchess_board_pos_num_alph_prop \l_tmpb_tl \l_tmpb_tl + } + \regex_match:NVT \l__digit_regex \l_tmpc_tl + { + \prop_get:NVN \c__cchess_board_pos_num_alph_prop \l_tmpc_tl \l_tmpc_tl + } + + \regex_match:NVT \l__digit_regex \l_tmpd_tl + { + \prop_get:NVN \c__cchess_board_pos_num_alph_prop \l_tmpd_tl \l_tmpd_tl + } + + % 用字母坐标定位布置棋子 + \__cchess_piece_move:VVVVn + \l_tmpa_tl \l_tmpb_tl \l_tmpc_tl \l_tmpd_tl { #1 } + } + +% 棋子移动函数 +% #1 原位置x方向数字型坐标值(a-i) +% #2 原位置y方向数字型坐标值(a-j) +% #3 新位置x方向数字型坐标值(a-i) +% #4 新位置y方向数字型坐标值(a-j) +% #5 棋子名称(单英文字母) +\cs_new:Npn \__cchess_piece_move:nnnnn #1#2#3#4#5 + { + % 删除原位置棋子 + \__cchess_piece_remove:nn { #1 } { #2 } + % 在新位置布置棋子 + \__cchess_piece_replace:nnn { #3 } { #4 } { #5 } + + % 生成打谱棋谱记录 + \bool_if:NT \l__cchess_with_setman_bool + { + \__cchess_piece_manual_str_construct:nnnnn { #1 }{ #2 }{ #3 }{ #4 }{ #5 } + } + } +\cs_generate_variant:Nn \__cchess_piece_move:nnnnn {VVVV} + +% 生成打谱棋谱记录 +% TODO:暂未实现纵向同类棋子前后判断 +% #1 原位置x方向数字型坐标值(a-i) +% #2 原位置y方向数字型坐标值(a-j) +% #3 新位置x方向数字型坐标值(a-i) +% #4 新位置y方向数字型坐标值(a-j) +% #5 棋子名称(单英文字母) +\cs_new:Npn \__cchess_piece_manual_str_construct:nnnnn #1#2#3#4#5 + { + % 将字母坐标数据转换为整数坐标 + \prop_get:NnN \c__cchess_board_pos_alph_num_prop { #1 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_pos_alph_num_prop { #2 } \l_tmpb_tl + \prop_get:NnN \c__cchess_board_pos_alph_num_prop { #3 } \l_tmpc_tl + \prop_get:NnN \c__cchess_board_pos_alph_num_prop { #4 } \l_tmpd_tl + \int_set:Nn \l_tmpa_int { \l_tmpa_tl } + \int_set:Nn \l_tmpb_int { \l_tmpb_tl } + \int_set:Nn \l_tmpc_int { \l_tmpc_tl } + \int_set:Nn \l_tmpd_int { \l_tmpd_tl } + + % 行棋分析 + \int_compare:nNnTF { \l_tmpc_int } = { \l_tmpa_int } + { % 纵向移动 + \int_compare:nNnTF { \l_tmpd_int } > { \l_tmpb_int } + { + % 坐标向上 + \int_set:Nn \l_tmpe_int { \l_tmpd_int - \l_tmpb_int } + \tl_set:Nx \l_tmpe_tl { \int_use:N \l_tmpe_int } + \regex_match:NnTF \l__capital_regex { #5 } + { % 红棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_red_x_idx_prop { #1 } \l_tmpb_tl + \prop_get:NVN \c__cchess_board_pos_arabic_zh_prop \l_tmpe_tl \l_tmpc_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 进 + \l_tmpc_tl + } + }{ % 黑棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_black_x_idx_prop { #1 } \l_tmpb_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 退 + \int_use:N \l_tmpe_int + } + } + }{ % 坐标向下 + \int_set:Nn \l_tmpe_int { \l_tmpb_int - \l_tmpd_int } + \tl_set:Nx \l_tmpe_tl { \int_use:N \l_tmpe_int } + \regex_match:NnTF \l__capital_regex { #5 } + { % 红棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_red_x_idx_prop { #1 } \l_tmpb_tl + \prop_get:NVN \c__cchess_board_pos_arabic_zh_prop \l_tmpe_tl \l_tmpc_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 退 + \l_tmpc_tl + } + }{ % 黑棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_black_x_idx_prop { #1 } \l_tmpb_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 进 + \int_use:N \l_tmpe_int + } + } + } + }{ % 非纵向移动 + \int_compare:nNnTF { \l_tmpd_int } = { \l_tmpb_int } + { % 水平移动 + \regex_match:NnTF \l__capital_regex { #5 } + { % 黑棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_red_x_idx_prop { #1 } \l_tmpb_tl + \prop_get:NnN \c__cchess_board_red_x_idx_prop { #3 } \l_tmpc_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 平 + \l_tmpc_tl + } + }{ % 红棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_black_x_idx_prop { #1 } \l_tmpb_tl + \prop_get:NnN \c__cchess_board_black_x_idx_prop { #3 } \l_tmpc_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 平 + \l_tmpc_tl + } + } + }{ % 非纵非横向移动 + \int_compare:nNnTF { \l_tmpd_int } > { \l_tmpb_int } + { % 纵向向上 + \regex_match:NnTF \l__capital_regex { #5 } + { % 红棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_red_x_idx_prop { #1 } \l_tmpb_tl + \prop_get:NnN \c__cchess_board_red_x_idx_prop { #3 } \l_tmpc_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 进 + \l_tmpc_tl + } + }{ % 黑棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_black_x_idx_prop { #1 } \l_tmpb_tl + \prop_get:NnN \c__cchess_board_black_x_idx_prop { #3 } \l_tmpc_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 退 + \l_tmpc_tl + } + } + }{ % 纵向向下 + \regex_match:NnTF \l__capital_regex { #5 } + { % 红棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_red_x_idx_prop { #1 } \l_tmpb_tl + \prop_get:NnN \c__cchess_board_red_x_idx_prop { #3 } \l_tmpc_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 退 + \l_tmpc_tl + } + }{ % 黑棋 + \prop_get:NnN \c__cchess_board_pieces_alph_name_prop { #5 } \l_tmpa_tl + \prop_get:NnN \c__cchess_board_black_x_idx_prop { #1 } \l_tmpb_tl + \prop_get:NnN \c__cchess_board_black_x_idx_prop { #3 } \l_tmpc_tl + \clist_put_right:Nx \l__cchess_manual_clist + { + \l_tmpa_tl + \l_tmpb_tl + 进 + \l_tmpc_tl + } + } + } + } + } + } +\cs_generate_variant:Nn \__cchess_piece_manual_str_construct:nnnnn {VVVV} + +% 打谱环境前处理函数 +% #1 打谱命令 +\cs_new:Npn \__cchess_setcchessman_pre_setup:n #1 + { + % 构建棋盘 + \__cchess_board_construct: + % 构建红黑各7个棋子 + \__cchess_pieces_construct: + + % 删除环境中的代码中的空白 + \tl_set:Nn \l_tmpa_tl { #1 } + \tl_remove_all:Nn \l_tmpa_tl {~} + % 执行环境中的代码 + \tl_use:N \l_tmpa_tl + } + +% 打谱环境后处理函数 +\cs_new:Nn \__cchess_setcchessman_post_setup: + { + % 布置棋子 + \__cchess_board_pieces_seat: + + % 将棋盘与打谱结果盒子容器居中对齐后进行拼装 + \hcoffin_set:Nn \l__cchess_manual_coffin + { + \draw_begin: + \draw_path_scope_begin: + \draw_transform_shift:n + { + \l__cchess_board_width_dim / 2, + \l__cchess_board_height_dim / 2 + } + \draw_coffin_use:Nnn \l__cchess_board_coffin { hc } { vc } + \draw_coffin_use:Nnn \l__cchess_board_pieces_pos_coffin { hc } { vc } + \draw_path_scope_end: + \draw_end: + } + + % 缩放拼装结果 + \__cchess_resize_c:n { \l__cchess_resize_method_tl } + + % 添加背景和外框 + \__cchess_board_assemble: + + % 星号环境需要输出打谱记录 + \bool_if:NT \l__cchess_with_setman_bool + { + % 测量打谱记录盒子水平尺寸 + \hcoffin_set:Nn \l_tmpa_coffin { 车九平八\quad 车九平八} + \dim_set:Nn \l_tmpa_dim { \coffin_wd:N \l_tmpa_coffin } + + % 构建打谱记录垂直盒子容器 + \vcoffin_set:Nnn \l_tmpa_coffin { \l_tmpa_dim } + { + % 遍历打谱记录列表,输出打谱记录 + \bool_until_do:nn { \clist_if_empty_p:N \l__cchess_manual_clist } + { + % 取消首行缩进 + \noindent + \clist_pop:NN \l__cchess_manual_clist \l_tmpa_tl + + \clist_if_empty:NTF \l__cchess_manual_clist + { + \l_tmpa_tl + }{ + \clist_pop:NN \l__cchess_manual_clist \l_tmpb_tl + \l_tmpa_tl + \quad + \l_tmpb_tl + \par + } + } + } + + % 拼装打谱记录盒子容器到结果容器 + \coffin_join:NnnNnnnn \l__cchess_manual_coffin + { l } { t } \l_tmpa_coffin { r } { t } { -10pt } { -\piecesize } + } + + % 输出结果盒子容器 + \coffin_typeset:Nnnnn \l__cchess_manual_coffin + { l }{ b } { 0pt } { 0pt } + } + +\endinput diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 25d8b1a9eb9..9cc3b100858 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -176,7 +176,7 @@ my @TLP_working = qw( chemnum chemplants chemschemex chemsec chemstyle cherokee chess chess-problem-diagrams chessboard chessfss chet chextras chhaya chicago chicagoa chicago-annote chickenize - chifoot childdoc chinese-jfm chivo + chifoot childdoc chinese-jfm chinesechess chivo chkfloat chklref chletter chngcntr chordbars chordbox chronology chronosys chs-physics-report chscite churchslavonic cinzel circ circledsteps circledtext circuit-macros circuitikz diff --git a/Master/tlpkg/tlpsrc/chinesechess.tlpsrc b/Master/tlpkg/tlpsrc/chinesechess.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/tlpsrc/chinesechess.tlpsrc diff --git a/Master/tlpkg/tlpsrc/collection-games.tlpsrc b/Master/tlpkg/tlpsrc/collection-games.tlpsrc index fdfdfd59404..2f26bdf36bd 100644 --- a/Master/tlpkg/tlpsrc/collection-games.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-games.tlpsrc @@ -9,6 +9,7 @@ depend chess depend chess-problem-diagrams depend chessboard depend chessfss +depend chinesechess depend crossword depend crosswrd depend egameps |