summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/chinesechess/chinesechess.sty
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/chinesechess/chinesechess.sty')
-rw-r--r--macros/latex/contrib/chinesechess/chinesechess.sty539
1 files changed, 343 insertions, 196 deletions
diff --git a/macros/latex/contrib/chinesechess/chinesechess.sty b/macros/latex/contrib/chinesechess/chinesechess.sty
index 6ddb58b836..2a2db971ed 100644
--- a/macros/latex/contrib/chinesechess/chinesechess.sty
+++ b/macros/latex/contrib/chinesechess/chinesechess.sty
@@ -19,21 +19,18 @@
%%
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\RequirePackage{expl3}
-\ProvidesExplPackage{chinesechess}{2022-04-29}{v1.0.0}
+\ProvidesExplPackage{chinesechess}{2022-05-06}{v1.1.0}
{Typeset Chinese chess with l3draw}
\RequirePackage { l3keys2e, l3draw, xparse }
-% 保证TeXLive的向下兼容
+% 测量盒子总高度(保证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 棋盘类型、棋子类型等外观选项
@@ -56,10 +53,10 @@
% 棋谱排版命令用户接口
% #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)
+% 红棋:K=帅,A=仕,E/B=相,R=车,C=砲,N/H=马,P=兵,
+% 黑棋:k=将,a=士,e/b=象,r=車,c=炮,n/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:
@@ -75,29 +72,43 @@
% 定义棋子字符常量
\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} }, % 卒
+ { K } { 帥 }, % 帥\__cchess_symbol:n {"5E25}
+ { A } { 仕 }, % 仕\__cchess_symbol:n {"4ED5}
+ { E } { 相 }, % 相\__cchess_symbol:n {"76F8}
+ { B } { 相 }, % 相\__cchess_symbol:n {"76F8}
+ { H } { 马 }, % 马\__cchess_symbol:n {"9A6C}
+ { N } { 马 }, % 马\__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}
+ { b } { 象 }, % 象\__cchess_symbol:n {"8C61}
+ { h } { 馬 }, % 馬\__cchess_symbol:n {"99AC}
+ { n } { 馬 }, % 馬\__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 }
}
+
+% 棋子字符设置命令
+% #1 棋子编号及字符
+% K=帅,A=仕,B/E=相,R=车,C=砲,N/H=马,P=兵
+% k=将,a=士,b/e=象,r=車,c=炮,n/h=馬,p=卒
+\NewDocumentCommand{\piecechar}{ m m }
+ {
+ \__cchess_piece_char_setup:nn { #1 } { #2 }
+ }
+
% 打谱环境初始化(仅用于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)
+% 红棋:K=帅,A=仕,E/B=相,R=车,C=砲,N/H=马,P=兵,
+% 黑棋:k=将,a=士,e/b=象,r=車,c=炮,n/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
@@ -110,20 +121,20 @@
% 打谱环境中的棋子布置命令(仅用于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)
+% #2 棋子位置列表
+% 红棋:K=帅,A=仕,E/B=相,R=车,C=砲,N/H=马,P=兵,
+% 黑棋:k=将,a=士,e/b=象,r=車,c=炮,n/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)
+% #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 }
@@ -133,9 +144,10 @@
% #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)
+% 红棋:K=帅,A=仕,E/B=相,R=车,C=砲,N/H=马,P=兵,
+% 黑棋:k=将,a=士,e/b=象,r=車,c=炮,n/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 }
@@ -167,13 +179,37 @@
\group_end:
}
+% 打谱棋谱输出用户接口
+% #1 每行输出步数
+% #2 棋谱交叉引用label
+% 参考雾月的回复:https://ask.latexstudio.net/ask/question/7430.html
+\NewDocumentCommand{\printman}{ O{} >{\TrimSpaces} m } % 去掉两侧空格
+ {
+ \group_begin:
+ \keys_set:nn { cchess } { #1 }
+ \__cchess_setman_print:n { #2 }
+ \group_end:
+ }
+
+% 棋子输出用户接口
+% #1 棋子字体字号
+% #2 棋子编码
+% 红棋:K=帅,A=仕,E/B=相,R=车,C=砲,N/H=马,P=兵,
+% 黑棋:k=将,a=士,e/b=象,r=車,c=炮,n/h=馬,p=卒
+\NewDocumentCommand{\getpiece}{ O{\normalsize} m }
+ {
+ \group_begin:
+ \__cchess_getpiece_handle:nn {#1} { #2 }
+ \group_end:
+ }
-% ==========棋子字符定义=====================
+% ==========棋子字符常量定义=====================
% 读取符号
\cs_new:Npn \__cchess_symbol:n #1
{
- \tex_char:D #1
- \scan_stop:
+ #1
+ % \tex_char:D #1
+ % \scan_stop:
}
% 棋子符号定义
@@ -233,30 +269,39 @@
% 出于对国际象棋棋手意识习惯的兼容性设计
% 相 B ,也可兼容使用 E,
% 马N, 也可兼容使用 H 代替
+% 在此,为兼容性考虑使用B/E同时表示相,使用H/N同时表示马
+% 在使用时,可以任意选择习惯的名称
+
% 判断红黑棋子英文单字母名称的正则表达式
\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 }
+\regex_set:Nn \l__capital_regex { [KAEBRCHNP] }
+
+% 棋子英文单字母名称列表
+\clist_const:Nn \c__cchess_pieces_name_clist { K,A,E,B,R,C,H,N,P,k,a,e,b,r,c,h,n,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 }, % 卒
+ { K } { 帥 }, % 帥"5E25
+ { A } { 仕 }, % 仕"4ED5
+ { E } { 相 }, % 相"76F8
+ { B } { 相 }, % 相"76F8
+ { H } { 马 }, % 马"9A6C
+ { N } { 马 }, % 马"9A6C
+ { R } { 车 }, % 车"8F66
+ { C } { 砲 }, % 砲"7832
+ { P } { 兵 }, % 兵"5175
+ { k } { 將 }, % 將"5C07
+ { a } { 士 }, % 士"58EB
+ { e } { 象 }, % 象"8C61
+ { b } { 象 }, % 象"8C61
+ { h } { 馬 }, % 馬"99AC
+ { n } { 馬 }, % 馬"99AC
+ { r } { 車 }, % 車"8ECA
+ { c } { 炮 }, % 炮"70AE
+ { p } { 卒 }, % 卒"5352
}
{ \__cchess_piece_define:nn #1 }
@@ -268,8 +313,8 @@
{ #1 } { \use:c { c__cchess_ #1 _tl } }
}
-% 在棋子编码列表中添加n表示空(null)棋子
-\clist_push:Nn \c__cchess_pieces_name_clist { n }
+% 在棋子编码列表中添加z表示空棋子
+\clist_push:Nn \c__cchess_pieces_name_clist { z }
% 定义棋子盒子容器
\clist_map_inline:Nn \c__cchess_pieces_name_clist
@@ -277,7 +322,7 @@
\coffin_new:c { l__cchess_piece_ #1 _coffin }
}
% 将空棋子盒子容器置空
-\hcoffin_gset:Nn \l__cchess_piece_n_coffin { \phantom{空} }
+\hcoffin_gset:Nn \l__cchess_piece_z_coffin { \phantom{a} }
% 棋盘盒子容器
\coffin_new:N \l__cchess_board_coffin
@@ -311,11 +356,11 @@
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. }
@@ -331,20 +376,20 @@
{
\coffin_new:c { l__cchess_board_piece_ #1 _ ##1 _coffin }
\hcoffin_gset:cn { l__cchess_board_piece_ #1 _ ##1 _coffin }
- { \phantom{空} }
+ { \phantom{a} }
}
}
-\coffin_new:N \l__cchess_board_piece_n_coffin
-\hcoffin_gset:Nn \l__cchess_board_piece_n_coffin { \phantom{空} }
+\coffin_new:N \l__cchess_board_piece_z_coffin
+\hcoffin_gset:Nn \l__cchess_board_piece_z_coffin { \phantom{a} }
-% 红方棋盘坐标字母与竖线标位对应关系
+% 红方棋盘坐标字母与红棋竖线标位对应关系
\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,
@@ -358,7 +403,7 @@
5 = 五, 6 = 六, 7 = 七, 8 = 八, 9 = 九
}
-% 棋谱文字说明列表(如车一进二等)
+% 棋谱记录列表(如车一进二等)
\clist_new:N \l__cchess_manual_clist
% 棋子外框盒子容器
@@ -393,16 +438,21 @@
% 棋子缩放比例
\tl_new:N \l__cchess_piece_scale_tl
% 待处理棋子字符
-\tl_new:N \l__cchess_pieces_tl
+\tl_new:N \l__cchess_pieces_tl
% 棋子字符格式
-\tl_new:N \l__cchess_piece_char_format_tl
+\tl_new:N \l__cchess_piece_char_format_tl
% 棋盘背景图片名称
-\tl_new:N \l__cchess_board_background_tl
+\tl_new:N \l__cchess_board_background_tl
% 棋子字符字形类型(实线、虚线等)
-\int_new:N \l__cchess_charstroke_type_int
+\int_new:N \l__cchess_charstroke_type_int
+
+% 打谱环境棋谱标签
+\tl_new:N \l__cchess_setman_label_tl
+% 打谱结果每行棋谱步数
+\int_new:N \l__cchess_mans_per_line_int
% 打谱环境用计数器
-% \int_new:N \c@cchessman
+\newcounter{setman}
% 增加两个临时int变量
\int_new:N \l_tmpc_int
@@ -415,7 +465,8 @@
% 棋子盒子由l3draw实现,
-% 棋子外围盒子及缩放设计思路来自zitie宏包(\url{https://www.ctan.org/pkg/zitie})。
+% 棋子外围盒子及缩放设计思路来自zitie宏包
+% (\url{https://www.ctan.org/pkg/zitie})。
% =============颜色处理函数=============
% 填充色辅助函数
@@ -448,11 +499,11 @@
\coffin_ht:N #1 + \coffin_dp:N #1
}
-% 计算基字符外框大小(外接正方形边长和外接圆半径)
+% 计算外框大小(外接正方形边长和外接圆半径)
\cs_new:Npn \__cchess_calc_piece_box_size:
{
- % 设置基字符格式的基字符盒子
- \hbox_set:Nn \l_tmpa_box { 将 }
+ % 设置计算基础盒子
+ \hbox_set:Nn \l_tmpa_box { xx }
% 盒子宽度
\dim_set:Nn \l_tmpa_dim
@@ -491,31 +542,16 @@
% =============构造棋子函数=============
% 字符盒子构造类型函数名称生成函数
-% 名称中6个参数分别表示:
-% #1 左下角x坐标
-% #2 左下角y坐标
-% #3 右上角x坐标
-% #4 右上角y坐标
-% #5 x方向缩放比例(扩展保留参数)
-% #6 y方向缩放比例(扩展保留参数)
+% #1 缩放比例
\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方向缩放比例(扩展保留参数)
+% #1 缩放比例
\cs_new_nopar:Npn \__cchess_piece_box_type_c:n #1
{
- \use:c
- {
- __cchess_piece_box_construct_type_ #1 :n
- }
+ \use:c { __cchess_piece_box_construct_type_ #1 :n }
}
% 字符盒子构造类型函数内部生成器函数
@@ -647,25 +683,21 @@
% =============构造棋盘函数=============
% 棋盘部件构造函数函数名称生成函数
% 名称中2个参数分别表示:
-% #1 x方向缩放比例(暂未使用保留参数)
-% #2 y方向缩放比例(暂未使用保留参数)
+% #1 x方向缩放比例(暂未使用, 保留参数)
+% #2 y方向缩放比例(暂未使用, 保留参数)
\cs_new_nopar:Npn \__cchess_board_type:n #1
{
__cchess_board_construct_type_ #1 :nn
}
-% 字符盒子构造类型函数名称命令生成函数
% 名称命令中2个参数分别表示:
-% #1 x方向缩放比例(暂未使用保留参数)
-% #2 y方向缩放比例(暂未使用保留参数)
+% #1 x方向缩放比例(暂未使用, 保留参数)
+% #2 y方向缩放比例(暂未使用, 保留参数)
\cs_new_nopar:Npn \__cchess_board_type_c:n #1
{
- \use:c
- {
- __cchess_board_construct_type_ #1 :nn
- }
+ \use:c { __cchess_board_construct_type_ #1 :nn }
}
-% 字符盒子构造类型函数生成器内部函数
+% 棋盘类型函数生成器内部函数
% #1 类型名称
\cs_new:Npn \__cchess_new_board_private_construct:nn #1
{
@@ -675,7 +707,7 @@
\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
{
@@ -687,10 +719,10 @@
\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:
@@ -787,7 +819,7 @@
\draw_scope_end:
}
-% 兵、炮标志
+% 兵、炮标志(半棋盘)
\__cchess_new_board_private_construct:nn { __semipos }
{
\hcoffin_set:Nn \l_tmpa_coffin
@@ -867,7 +899,7 @@
\draw_scope_end:
}
-% 象位线
+% 象位虚线
\__cchess_new_board_private_construct:nn { __elephantcross }
{
\draw_scope_begin:
@@ -910,8 +942,8 @@
\color_select:n { cchessboardlinecolor }
- \hcoffin_set:Nn \l_char_tmpa_coffin { 河 }
- \hcoffin_set:Nn \l_char_tmpb_coffin { 楚 }
+ \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 { 界 }
@@ -924,7 +956,7 @@
\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 }
@@ -933,7 +965,8 @@
\fp_to_dim:n { \fp_eval:n { \gridsize * 0.45 } }
}
- \clist_map_inline:Nn \l_tmpa_clist
+ % 缩放盒子容器
+ \clist_map_inline:nn { a, b, c, d }
{
\coffin_scale:cnn { l_char_tmp ##1 _coffin }
{
@@ -945,17 +978,26 @@
% 排版文字
\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_path_scope_begin:
+ \draw_transform_shift:n { \gridsize * 2, \gridsize * 4.5 }
+ \draw_transform_shift:n { -\gridsize / 2, 0pt }
+ \draw_coffin_use:cnn { l_char_tmpb_coffin } { hc } { vc }
+ \draw_path_scope_end:
+ \draw_path_scope_begin:
+ \draw_transform_shift:n { \gridsize * 2, \gridsize * 4.5 }
+ \draw_transform_shift:n { \gridsize / 2, 0pt }
+ \draw_coffin_use:cnn { l_char_tmpa_coffin } { hc } { vc }
+ \draw_path_scope_end:
+ \draw_path_scope_begin:
+ \draw_transform_shift:n { \gridsize * 6, \gridsize * 4.5 }
+ \draw_transform_shift:n { -\gridsize / 2, 0pt }
+ \draw_coffin_use:cnn { l_char_tmpc_coffin } { hc } { vc }
+ \draw_path_scope_end:
+ \draw_path_scope_begin:
+ \draw_transform_shift:n { \gridsize * 6, \gridsize * 4.5 }
+ \draw_transform_shift:n { \gridsize / 2, 0pt }
+ \draw_coffin_use:cnn { l_char_tmpd_coffin } { hc } { vc }
+ \draw_path_scope_end:
\draw_scope_end:
}
@@ -1255,13 +1297,18 @@
% =============棋子文字设置函数=============
% 设置棋子的文字
% 红棋编码用大写字母,默认:
-% K=帅,A=仕,E=相,R=车,C=砲,H=马,P=兵
+% K=帅,A=仕,E/B=相,R=车,C=砲,H/N=马,P=兵
% 黑棋编码用小字字母,默认:
-% k=将,a=士,e=象,r=車,c=炮,h=馬,p=卒
+% k=将,a=士,e/b=象,r=車,c=炮,h/n=馬,p=卒
% #1 棋子编码
% #2 棋子字符
\cs_new_nopar:Npn \__cchess_piece_char_setup:nn #1#2
{
+ \clist_if_in:NnF \c__cchess_pieces_name_clist { #1 }
+ {
+ \msg_error:nnx { cchess } { piecename-exists } { #1 }
+ }
+
\prop_gput:Nnn \c__cchess_board_pieces_alph_name_prop
{ #1 } { #2 }
}
@@ -1310,21 +1357,10 @@
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:
- },
+ % 棋盘背景图片
+ boardbg .tl_set:N = \l__cchess_board_background_tl ,
+ boardbg .initial:n = {} ,
- % 边框类型
- 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}
@@ -1340,6 +1376,22 @@
width .dim_set:N = \l__cchess_manual_width_dim ,
height .dim_set:N = \l__cchess_manual_height_dim ,
+ % 设置棋子字符
+ 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} }
+ },
+
% 字符边框线宽
boxlinewd .dim_set:N = \l__cchess_box_linewidth_dim ,
boxlinewd .initial:n = 0.4pt ,
@@ -1434,9 +1486,13 @@
{ \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 = {} ,
+ % 打谱环境交叉引用标签
+ label .tl_gset:N = \l__cchess_setman_label_tl ,
+ label .initial:n = {} ,
+
+ % 每行棋谱步数
+ mansperline .tl_gset:N = \l__cchess_mans_per_line_int ,
+ mansperline .initial:n = 2 ,
unknown .code:n = { \msg_error:nn { cchess } { unknown-option } }
}
@@ -1448,7 +1504,7 @@
piecefont = \kaishu,
piecetype = ooo,
boardtype = x+tn,
- resize = none,
+ resize = none,
}
% 选项设置用户接口
@@ -1491,7 +1547,7 @@
% 缩放棋子盒子容器
\coffin_resize:Nnn \l__cchess_piece_coffin { \piecesize }{ \piecesize }
- % 复制结果以备后续使用
+ % 保存结果
\coffin_gset_eq:cN
{ l__cchess_piece_ ##1 _coffin } \l__cchess_piece_coffin
}
@@ -1531,17 +1587,17 @@
}
% =============创建棋子占位coffins=============
- % 缩放空白棋子(n---null)
-\cs_new:Nn \__cchess_board_piece_n_resize:
+ % 缩放空白棋子
+\cs_new:Nn \__cchess_board_piece_z_resize:
{
- \coffin_resize:Nnn \l__cchess_piece_n_coffin { \piecesize } { \piecesize }
+ \coffin_resize:Nnn \l__cchess_piece_z_coffin { \piecesize } { \piecesize }
}
-% 执行缩放
-\__cchess_board_piece_n_resize:
+% 缩放空白棋子
+\__cchess_board_piece_z_resize:
% 将棋子盒子容器布置到棋盘指定位置(用于棋谱和棋盘排版)
% #1 棋子参数
-% 棋子参数的形式为{0,0}{k},{0,1}{K},注意需要包含大括号,
+% 棋子参数的形式为{{0,0}{k},{0,1}{K}},注意需要包含大括号,
% 不同棋子之间用英文逗号分隔
\cs_new:Npn \__cchess_board_piece_pos_construct:n #1
{
@@ -1550,7 +1606,7 @@
\draw_begin:
% 在四个角布置空白棋子实现占位(用于撑满棋子画布)
\clist_set:Nn \l_tmpa_clist
- { {0, 0}{n}, {8, 0}{n}, {0, 9}{n}, {8, 9}{n}}
+ { {0, 0}{z}, {8, 0}{z}, {0, 9}{z}, {8, 9}{z}}
\clist_map_inline:Nn \l_tmpa_clist
{
\__cchess_piece_set_handle:nn ##1
@@ -1575,7 +1631,7 @@
% 如果文件名不为空则载入图片,否则创建一个空盒子容器
\tl_if_empty:NTF \l__cchess_board_background_tl
{
- \phantom{将}
+ \phantom{a}
}{
\includegraphics{\l__cchess_board_background_tl}
}
@@ -1670,6 +1726,43 @@
}
}
+% 在正文中排版棋子
+\cs_new:Npn \__cchess_getpiece_handle:nn #1#2
+ {
+ % 构建红黑各7个棋子
+ \__cchess_pieces_construct:
+
+ % 设置指定格式的基字符盒子
+ \hbox_set:Nn \l_tmpa_box { #1 将 }
+
+ % 盒子高度
+ \dim_set:Nn \l_tmpa_dim
+ {
+ \box_ht_plus_dp:N \l_tmpa_box
+ }
+
+ % 棋子高度
+ \dim_set:Nn \l_tmpb_dim
+ {
+ \__cchess_coffin_ht_plus_dp:N \l__cchess_piece_K_coffin
+ }
+
+ % 缩放棋子
+ \coffin_scale:cnn { l__cchess_piece_ #2 _coffin }
+ {
+ \dim_ratio:nn { \l_tmpa_dim } { \l_tmpb_dim }
+ }{
+ \dim_ratio:nn { \l_tmpa_dim } { \l_tmpb_dim }
+ }
+
+ % 盒子深度
+ \dim_set:Nn \l_tmpb_dim { \box_dp:N \l_tmpa_box }
+
+ % 输出盒子(下沉深度距离)
+ \coffin_typeset:cnnnn { l__cchess_piece_ #2 _coffin }
+ { l } { b } { 0pt } { -\l_tmpb_dim }
+ }
+
% =============排版棋谱=============
% 棋谱排版
\cs_new:Npn \__cchess_manual_output:n #1
@@ -1820,12 +1913,14 @@
}
\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
+ \coffin_resize:Nnn \l__cchess_board_piece_z_coffin
{ \piecesize } { \piecesize }
% 其它棋子,按行(a-i)列(a-j)编号命名。
@@ -1912,8 +2007,8 @@
}
% 棋子占位替换函数
-% #1 x方向数字型坐标值(a-i)
-% #2 y方向数字型坐标值(a-j)
+% #1 横向字符型坐标值(a-i)
+% #2 纵向字符型坐标值(a-j)
% #3 棋子名称(单英文字母)
\cs_new:Npn \__cchess_piece_replace:nnn #1#2#3
{
@@ -1958,14 +2053,14 @@
}
% 棋子删除函数
-% #1 x方向数字型坐标值(a-i)
-% #2 y方向数字型坐标值(a-j)
+% #1 横向字符型坐标值(a-i)
+% #2 纵方向字符型坐标值(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
+ \l__cchess_board_piece_z_coffin
}
\cs_generate_variant:Nn \__cchess_piece_remove:nn {VV}
@@ -2028,10 +2123,10 @@
}
% 棋子移动函数
-% #1 原位置x方向数字型坐标值(a-i)
-% #2 原位置y方向数字型坐标值(a-j)
-% #3 新位置x方向数字型坐标值(a-i)
-% #4 新位置y方向数字型坐标值(a-j)
+% #1 原位置横向字符型坐标值(a-i)
+% #2 原位置纵向字符型坐标值(a-j)
+% #3 新位置横向字符型坐标值(a-i)
+% #4 新位置纵向字符型坐标值(a-j)
% #5 棋子名称(单英文字母)
\cs_new:Npn \__cchess_piece_move:nnnnn #1#2#3#4#5
{
@@ -2050,14 +2145,14 @@
% 生成打谱棋谱记录
% TODO:暂未实现纵向同类棋子前后判断
-% #1 原位置x方向数字型坐标值(a-i)
-% #2 原位置y方向数字型坐标值(a-j)
-% #3 新位置x方向数字型坐标值(a-i)
-% #4 新位置y方向数字型坐标值(a-j)
+% #1 原位置横向字符型坐标值(a-i)
+% #2 原位置纵向字符型坐标值(a-j)
+% #3 新位置横向字符型坐标值(a-i)
+% #4 新位置纵向字符型坐标值(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
@@ -2226,6 +2321,11 @@
\tl_use:N \l_tmpa_tl
}
+% 定义\label命令的变体函数
+%\label { #1 }
+\cs_set_eq:NN \__cchess_setman_label:n \label
+\cs_generate_variant:Nn \__cchess_setman_label:n { x }
+
% 打谱环境后处理函数
\cs_new:Nn \__cchess_setcchessman_post_setup:
{
@@ -2257,36 +2357,27 @@
% 星号环境需要输出打谱记录
\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 }
+ % 递增计数器
+ \refstepcounter{setman}
+ % 设置label标签
+ \__cchess_setman_label:x { \l__cchess_setman_label_tl }
- % 构建打谱记录垂直盒子容器
- \vcoffin_set:Nnn \l_tmpa_coffin { \l_tmpa_dim }
+ % 构造临时文件
+ \iow_open:Nn \g_tmpa_iow
{
- % 遍历打谱记录列表,输出打谱记录
- \bool_until_do:nn { \clist_if_empty_p:N \l__cchess_manual_clist }
- {
- % 取消首行缩进
- \noindent
- \clist_pop:NN \l__cchess_manual_clist \l_tmpa_tl
+ \c_sys_jobname_str\l__cchess_setman_label_tl\thesetman .man
+ }
- \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
- }
- }
+ % 遍历打谱记录列表,输出打谱记录到临时文件
+ \bool_until_do:nn { \clist_if_empty_p:N \l__cchess_manual_clist }
+ {
+ \clist_pop:NN \l__cchess_manual_clist \l_tmpa_tl
+ \tl_set:Nx \l_tmpb_tl {\l_tmpa_tl}
+ \iow_now:Nx \g_tmpa_iow { \l_tmpb_tl }
}
- % 拼装打谱记录盒子容器到结果容器
- \coffin_join:NnnNnnnn \l__cchess_manual_coffin
- { l } { t } \l_tmpa_coffin { r } { t } { -10pt } { -\piecesize }
+ % 关闭文件
+ \iow_close:N \g_tmpa_iow
}
% 输出结果盒子容器
@@ -2294,4 +2385,60 @@
{ l }{ b } { 0pt } { 0pt }
}
+% 参考雾月的回复:https://ask.latexstudio.net/ask/question/7430.html
+% LaTeX3 并未定义 \use_i:nnnnn
+\cs_set:Npn \use_i:nnnnn #1#2#3#4#5 {#1}
+
+% 打谱棋谱排版描述处理
+\cs_new:Npn \__cchess_setman_print:n #1
+ {
+ % 根据棋谱label构建文件名
+ \cs_if_exist:cTF { r@#1 }
+ {
+ % 这一步是得到 ref,它保存在 \r@#1 中。
+ % \r@#1 有两项,当使用 hyperref 时,
+ % \r@#1 有 5 项,这里使用 \empty 统一解决
+ \tl_set:Nx \l_tmpa_tl
+ {
+ \c_sys_jobname_str
+ #1 \exp_args:NNc \exp_after:wN \use_i:nnnnn { r@ #1 }
+ \c_empty_tl \c_empty_tl \c_empty_tl .man
+ }
+
+ % 打开文件读取数据并输出结果
+ \ior_open:NnTF \g_tmpb_ior { \l_tmpa_tl }
+ {
+ % 循环计数
+ \int_set:Nn \l_tmpa_int { 1 }
+ % 循环读取一行棋谱
+ \ior_str_map_variable:NNn \g_tmpb_ior \l_tmpb_str
+ {
+ % 转换为token
+ \tl_set_rescan:Nno \l_tmpb_tl
+ {
+ \char_set_catcode_letter:N \_
+ \char_set_catcode_letter:N :
+ }{ \l_tmpb_str }
+
+ % 输出结果
+ \tl_use:N \l_tmpb_tl
+
+ % 根据每行步数确定输出\quad或是\par
+ \int_set:Nn \l_tmpb_int
+ {
+ \int_mod:nn { \l_tmpa_int } { \l__cchess_mans_per_line_int }
+ }
+ \int_compare:nNnTF { \l_tmpb_int } = { 0 }
+ { \par } { \quad }
+
+ \int_incr:N \l_tmpa_int
+ }
+ }
+ { \msg_error:nnx { cchess } { file-not-found } { \l_tmpa_tl } }
+
+ % 关闭文件
+ \iow_close:N \g_tmpa_ior
+ }{ \G@refundefinedtrue }% 引用未定义
+ }
+
\endinput