% \iffalse meta-comment % dtx/mahjong-tiles-03-tuples.dtx -- tuple helpers for mahjong-tiles % % Copyright (c) 2021 Daniel Schmitz % Copyright (c) 2026 Lilia Chen May Wither % % This file is distributed under the MIT Licence; see LICENCE. % \fi % % \subsection{Tuple helpers} % % \begin{macrocode} %<*package> % ----------------------------------------------------------------------------- % Tuple helpers % Pending tuple: {face}{orientation}{overlay} % Output tuple: {kind}{a}{b}{c}{overlay} % tile = {tile}{face}{suit}{orientation}{overlay}; suit may be m, p, s, z, f, or empty for x and ? % akastack = {akastack}{suit}{level}{ }{overlay}; red-five edge stack % draw = {draw}{face}{suit}{ }{ }; drawn tile rendered sideways above the hand row % gap = {gap}{n}{ }{ }{ }; n means n/7 of one tile width % ----------------------------------------------------------------------------- \cs_new_protected:Npn \__mahjongtiles_pending_put:nn #1#2 { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {#2} { } } } \cs_new_protected:Npn \__mahjongtiles_tile_put:nnnn #1#2#3#4 { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#1} {#2} {#3} {#4} } \bool_set_false:N \l__mahjongtiles_last_concealed_kong_tail_bool } \cs_new_protected:Npn \__mahjongtiles_tile_put:nnn #1#2#3 { \__mahjongtiles_tile_put:nnnn {#1} {#2} {#3} { } } \cs_generate_variant:Nn \__mahjongtiles_tile_put:nnn { Vnn } \cs_generate_variant:Nn \__mahjongtiles_tile_put:nnnn { Vnnn } \cs_new_protected:Npn \__mahjongtiles_tile_put_aka_aware:nnnn #1#2#3#4 { % Keep the source face in the parse tuple. This lets postfix edge syntax % such as 0p""" force red fives even when aka=0; ordinary rendering still % maps 0m/0p/0s to regular fives when aka=0. \__mahjongtiles_tile_put:nnnn {#1} {#2} {#3} {#4} } \cs_new_protected:Npn \__mahjongtiles_tile_put_aka_aware:nnn #1#2#3 { \__mahjongtiles_tile_put_aka_aware:nnnn {#1} {#2} {#3} { } } \cs_generate_variant:Nn \__mahjongtiles_tile_put_aka_aware:nnn { Vnn } \cs_generate_variant:Nn \__mahjongtiles_tile_put_aka_aware:nnnn { Vnnn } \cs_new_protected:Npn \__mahjongtiles_akastack_put:nnn #1#2#3 { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { akastack } {#1} {#2} { } {#3} } \bool_set_false:N \l__mahjongtiles_last_concealed_kong_tail_bool } \cs_new_protected:Npn \__mahjongtiles_gap_put:n #1 { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { gap } {#1} { } { } { } } \bool_set_false:N \l__mahjongtiles_last_concealed_kong_tail_bool } \cs_new_protected:Npn \__mahjongtiles_draw_put:nn #1#2 { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { draw } {#1} {#2} { } { } } \bool_set_false:N \l__mahjongtiles_last_concealed_kong_tail_bool } \cs_generate_variant:Nn \__mahjongtiles_draw_put:nn { VV } \cs_new_protected:Npn \__mahjongtiles_pending_set_last_stack_marker:n #1 { \seq_pop_right:NNTF \l__mahjongtiles_pending_seq \l__mahjongtiles_tmp_tl { \exp_last_unbraced:NV \__mahjongtiles_pending_set_last_stack_marker_aux:nnnn \l__mahjongtiles_tmp_tl {#1} } { \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#1} } } \cs_new_protected:Npn \__mahjongtiles_pending_set_last_stack_marker_aux:nnnn #1#2#3#4 { \str_if_eq:nnTF {#1} {0} { \int_case:nnF {#2} { {0} { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {3} {#3} } } {3} { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {4} {#3} } } {4} { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {5} {#3} } } {5} { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {5} {#3} } } } { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {2} {#3} } } } { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {2} {#3} } } } \cs_new_protected:Npn \__mahjongtiles_pending_set_last_orientation:n #1 { \seq_pop_right:NNTF \l__mahjongtiles_pending_seq \l__mahjongtiles_tmp_tl { \exp_last_unbraced:NV \__mahjongtiles_pending_set_last_orientation_aux:nnnn \l__mahjongtiles_tmp_tl {#1} } { \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#1} } } \cs_new_protected:Npn \__mahjongtiles_pending_set_last_orientation_aux:nnnn #1#2#3#4 { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {#4} {#3} } } \cs_new_protected:Npn \__mahjongtiles_output_apply_stack_marker:n #1 { \seq_pop_right:NNTF \l__mahjongtiles_tiles_seq \l__mahjongtiles_tmp_tl { \exp_last_unbraced:NV \__mahjongtiles_output_apply_stack_marker_aux:nnnnnn \l__mahjongtiles_tmp_tl {#1} } { \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#1} } } \cs_new_protected:Npn \__mahjongtiles_output_apply_stack_marker_aux:nnnnnn #1#2#3#4#5#6 { \str_case:nnF {#1} { { tile } { \str_if_eq:nnTF {#2} {0} { \tl_if_in:nnTF { mps } {#3} { \__mahjongtiles_akastack_put:nnn {#3} {1} {#5} } { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#2} {#3} {2} {#5} } } } { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#2} {#3} {2} {#5} } } } { akastack } { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { akastack } {#2} { \int_min:nn {3} { #3 + 1 } } {#4} {#5} } } } { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { {#1} {#2} {#3} {#4} {#5} } \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#6} } } \cs_new_protected:Npn \__mahjongtiles_output_set_last_orientation:n #1 { \seq_pop_right:NNTF \l__mahjongtiles_tiles_seq \l__mahjongtiles_tmp_tl { \exp_last_unbraced:NV \__mahjongtiles_output_set_last_orientation_aux:nnnnnn \l__mahjongtiles_tmp_tl {#1} } { \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#1} } } \cs_new_protected:Npn \__mahjongtiles_output_set_last_orientation_aux:nnnnnn #1#2#3#4#5#6 { \str_if_eq:nnTF {#1} { tile } { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#2} {#3} {#6} {#5} } } { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { {#1} {#2} {#3} {#4} {#5} } \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#6} } } \cs_new_protected:Npn \__mahjongtiles_set_last_orientation:n #1 { \seq_if_empty:NTF \l__mahjongtiles_pending_seq { \__mahjongtiles_output_set_last_orientation:n {#1} } { \__mahjongtiles_pending_set_last_orientation:n {#1} } } \cs_new_protected:Npn \__mahjongtiles_set_last_stack_marker:n #1 { \seq_if_empty:NTF \l__mahjongtiles_pending_seq { \__mahjongtiles_output_apply_stack_marker:n {#1} } { \__mahjongtiles_pending_set_last_stack_marker:n {#1} } } \cs_new_protected:Npn \__mahjongtiles_pending_set_last_overlay:n #1 { \seq_pop_right:NNTF \l__mahjongtiles_pending_seq \l__mahjongtiles_tmp_tl { \exp_last_unbraced:NV \__mahjongtiles_pending_set_last_overlay_aux:nnnn \l__mahjongtiles_tmp_tl {#1} } { \msg_error:nnn { mahjong-tiles } { missing-overlay-target } {#1} } } \cs_new_protected:Npn \__mahjongtiles_pending_set_last_overlay_aux:nnnn #1#2#3#4 { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {#2} {#4} } } \cs_new_protected:Npn \__mahjongtiles_output_set_last_overlay:n #1 { \seq_pop_right:NNTF \l__mahjongtiles_tiles_seq \l__mahjongtiles_tmp_tl { \exp_last_unbraced:NV \__mahjongtiles_output_set_last_overlay_aux:nnnnnn \l__mahjongtiles_tmp_tl {#1} } { \msg_error:nnn { mahjong-tiles } { missing-overlay-target } {#1} } } \cs_generate_variant:Nn \__mahjongtiles_output_set_last_overlay:n { V } \cs_new_protected:Npn \__mahjongtiles_output_set_last_overlay_aux:nnnnnn #1#2#3#4#5#6 { \str_case:nnF {#1} { { tile } { \tl_if_blank:nF {#6} { \bool_if:NT \l__mahjongtiles_last_concealed_kong_tail_bool { \msg_warning:nnn { mahjong-tiles } { concealed-kong-overlay } {#6} } } \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#2} {#3} {#4} {#6} } } { akastack } { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { akastack } {#2} {#3} {#4} {#6} } } } { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { {#1} {#2} {#3} {#4} {#5} } \msg_error:nnn { mahjong-tiles } { missing-overlay-target } {#6} } } \cs_new_protected:Npn \__mahjongtiles_set_last_overlay:n #1 { \seq_if_empty:NTF \l__mahjongtiles_pending_seq { \__mahjongtiles_output_set_last_overlay:n {#1} } { \__mahjongtiles_pending_set_last_overlay:n {#1} } } % % \end{macrocode} \endinput