| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- #nop vim: set filetype=tt:;
- /*
- 本文件属于 PaoTin++ 的一部分。
- PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
- 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
- */
- #nop 本文件是 xtintin 的一部分,实现了一些方向和路径运算函数;
- ///=== {
- ///// 方向和路径运算函数:
- //
- // #@ dir.Name <方向全拼|方向缩写> [<严格模式>]
- // 给出指定方向的中文名称。方向可以通过英文单词或者英文单词的缩写给出。
- //
- // EXAMPLE: \@dir.Name{eastup}
- // RESULT: {东上}
- //
- // EXAMPLE: \@dir.Name{eu}
- // RESULT: {东上}
- //
- // EXAMPLE: \@dir.Name{enter}
- // RESULT: {进去}
- //
- // EXAMPLE: \@dir.Name{eastup;1}
- // RESULT: {东上}
- //
- // EXAMPLE: \@dir.Name{eu;1}
- // RESULT: {东上}
- //
- // EXAMPLE: \@dir.Name{enter;1}
- // RESULT: {进去}
- //
- // EXAMPLE: \@dir.Name{open door}
- // RESULT: {open door}
- //
- // EXAMPLE: \@dir.Name{open door;1}
- // RESULT: {}
- // };
- #func {dir.Name} { #return @__dir_convert_dir__{name; %1; %2}; };
- ///=== {
- // #@ dir.Short <方向全拼> [<严格模式>]
- // 给出方向对应的英文单词缩写。
- //
- // EXAMPLE: \@dir.Short{eastup}
- // RESULT: {eu}
- //
- // EXAMPLE: \@dir.Short{eu}
- // RESULT: {eu}
- //
- // EXAMPLE: \@dir.Short{enter}
- // RESULT: {enter}
- //
- // EXAMPLE: \@dir.Short{open door}
- // RESULT: {open door}
- //
- // EXAMPLE: \@dir.Short{eastup;1}
- // RESULT: {eu}
- //
- // EXAMPLE: \@dir.Short{eu;1}
- // RESULT: {eu}
- //
- // EXAMPLE: \@dir.Short{enter;1}
- // RESULT: {enter}
- //
- // EXAMPLE: \@dir.Short{open door;1}
- // RESULT: {}
- // };
- #func {dir.Short} { #return @__dir_convert_dir__{short; %1; %2}; };
- ///=== {
- // #@ dir.Long <方向缩写> [<严格模式>]
- // 给出方向对应的英文单词全拼。
- //
- // EXAMPLE: \@dir.Long{eu}
- // RESULT: {eastup}
- //
- // EXAMPLE: \@dir.Long{eastup}
- // RESULT: {eastup}
- //
- // EXAMPLE: \@dir.Long{out}
- // RESULT: {out}
- //
- // EXAMPLE: \@dir.Long{open door}
- // RESULT: {open door}
- //
- // EXAMPLE: \@dir.Long{eu;1}
- // RESULT: {eastup}
- //
- // EXAMPLE: \@dir.Long{eastup;1}
- // RESULT: {eastup}
- //
- // EXAMPLE: \@dir.Long{out;1}
- // RESULT: {out}
- //
- // EXAMPLE: \@dir.Long{open door;1}
- // RESULT: {}
- // };
- #func {dir.Long} { #return @__dir_convert_dir__{long; %1; %2}; };
- ///=== {
- // #@ dir.Reverse <方向> [<严格模式>]
- // 给出方向对应的相反方向。
- //
- // EXAMPLE: \@dir.Reverse{eu}
- // RESULT: {wd}
- //
- // EXAMPLE: \@dir.Reverse{eastup}
- // RESULT: {westdown}
- //
- // EXAMPLE: \@dir.Reverse{enter}
- // RESULT: {out}
- //
- // EXAMPLE: \@dir.Reverse{open door}
- // RESULT: {open door}
- //
- // EXAMPLE: \@dir.Reverse{eu;1}
- // RESULT: {wd}
- //
- // EXAMPLE: \@dir.Reverse{eastup;1}
- // RESULT: {westdown}
- //
- // EXAMPLE: \@dir.Reverse{enter;1}
- // RESULT: {out}
- //
- // EXAMPLE: \@dir.Reverse{open door;1}
- // RESULT: {}
- //
- ///// 以上函数中,凡是支持严格模式参数的,如果严格模式为 true,则给错误方向给出空字符串结果。
- // };
- #func {dir.Reverse} {
- #if { "%1" == "enter{| .*}" } {
- #return {out};
- };
- #else {
- #return @__dir_convert_dir__{reverse; %1; %2};
- };
- };
- ///=== {
- // #@ dir.IsDir <方向全拼|方向缩写>
- // 检查参数是否是一个合格的方向指令。
- //
- // EXAMPLE: \@dir.IsDir{eu}
- // RESULT: {1}
- //
- // EXAMPLE: \@dir.IsDir{eastup}
- // RESULT: {1}
- //
- // EXAMPLE: \@dir.IsDir{enter}
- // RESULT: {1}
- //
- // EXAMPLE: \@dir.IsDir{open door}
- // RESULT: {0}
- // };
- #func {dir.IsDir} {
- #local cmd {%0};
- #if { "@dir.Name{{$cmd};1}" == "" } {
- #return 0;
- };
- #else {
- #return 1;
- };
- };
- ///=== {
- // #@ dir.Type <方向指令>
- // 计算方向指令的类型。方向指令有几大类:
- // - 标准出口(exit): 标准出口应当是一个小写字母拼写形式的出口
- // - 隐藏出口(hidden): 规定全大写字母拼写形式的出口为隐藏出口
- // - 动态出口(dynamic): 规定首字母大写拼写形式的出口为动态出口
- // - 非标指令(ad-hoc): 如果方向指令转换为小写之后,不是标准出口,则为非标指令
- //
- // EXAMPLE: \@dir.Type{north}
- // RESULT: {exit}
- //
- // EXAMPLE: \@dir.Type{NORTH}
- // RESULT: {hidden}
- //
- // EXAMPLE: \@dir.Type{North}
- // RESULT: {dynamic}
- //
- // EXAMPLE: \@dir.Type{open door}
- // RESULT: {ad-hoc}
- // };
- #func {dir.Type} {
- #local dir {%0};
- #local exit {@str.ToLower{$dir}};
- #if { ! @dir.IsDir{$exit} } {
- #return {ad-hoc};
- };
- #elseif { "$dir" == "{[A-Z]+}" } {
- #return {hidden};
- };
- #elseif { "$dir" == "{[A-Z][a-z]+}" } {
- #return {dynamic};
- };
- #else {
- #return {exit};
- };
- };
- ///=== {
- // #@ dir.ToCmd <方向指令> [<模式>]
- // 根据方向指令的类别,生成对应的命令。
- // 可选的模式用来生成特殊情形下的命令,例如推车程序。
- //
- // EXAMPLE: \@dir.ToCmd{north}
- // RESULT: {go north}
- //
- // EXAMPLE: \@dir.ToCmd{NORTH}
- // RESULT: {north}
- //
- // EXAMPLE: \@dir.ToCmd{North}
- // RESULT: {go north}
- //
- // EXAMPLE: \@dir.ToCmd{open door}
- // RESULT: {open door}
- //
- // EXAMPLE: \@dir.ToCmd{north;ganche}
- // RESULT: {gan che to north}
- //
- // EXAMPLE: \@dir.ToCmd{NORTH;ganche}
- // RESULT: {gan che to north}
- //
- // EXAMPLE: \@dir.ToCmd{North;ganche}
- // RESULT: {gan che to north}
- //
- // EXAMPLE: \@dir.ToCmd{ride;ganche}
- // RESULT: {ride}
- // };
- #func {dir.ToCmd} {
- #local dir {%1};
- #local mode {@default{%2;go}};
- #local type {@dir.Type{$dir}};
- #if { "$mode" == "go" } {
- #switch {"$type"} {
- #case {"exit"} {#return {go $dir}};
- #case {"hidden"} {#return {@str.ToLower{$dir}}};
- #case {"dynamic"} {#return {go @str.ToLower{$dir}}};
- #case {"ad-hoc"} {#return {$dir}};
- #default {#return {$dir}};
- };
- };
- #elseif { "$mode" == "ganche" } {
- #switch {"$type"} {
- #case {"exit"} {#return {gan che to $dir}};
- #case {"hidden"} {#return {gan che to @str.ToLower{$dir}}};
- #case {"dynamic"} {#return {gan che to @str.ToLower{$dir}}};
- #case {"ad-hoc"} {#return {$dir}};
- #default {#return {$dir}};
- };
- };
- };
- ///=== {
- // #@ path.Reverse <路径>
- // 给出路径对应的反向路径。
- //
- // EXAMPLE: \@path.Reverse{n;e;s;w}
- // RESULT: {e;n;w;s}
- //
- // EXAMPLE: \@path.Reverse{north;east;south;west}
- // RESULT: {east;north;west;south}
- //
- // EXAMPLE: \@path.Reverse{north;east;hp;south;west}
- // RESULT: {east;north;hp;west;south}
- // };
- #func {path.Reverse} {
- #local path {%0};
- #local newPath {};
- #local step {};
- #foreach {$path} {step} {
- #list newPath insert {1} {@dir.Reverse{$step}};
- };
- #return {@slist.FromList{$newPath}};
- };
- ///=== {
- // #@ path.Simplify <路径>
- // 化简路径。返回化简后的新路径。
- //
- // EXAMPLE: \@path.Simplify{north;north;north;east;west;south}
- // RESULT: {north;north}
- //
- // EXAMPLE: \@path.Simplify{north;north;north;east;south;west}
- // RESULT: {north;north;north;east;south;west}
- //
- // EXAMPLE: \@path.Simplify{n;n;n;e;w;s}
- // RESULT: {n;n}
- //
- // EXAMPLE: \@path.Simplify{n;n;n;e;s;w}
- // RESULT: {n;n;n;e;s;w}
- //
- // EXAMPLE: \@path.Simplify{n;n;n;e;hp;w;s}
- // RESULT: {n;n;n;e;hp;w;s}
- //
- // };
- #func {path.Simplify} {
- #local path {@list.FromSlist{%0}};
- #local count {&path[]};
- #if { $count == 0 } {
- #return {};
- };
- #local idx {1};
- #while { $idx < $count } {
- #local current {$path[$idx]};
- #local next {$path[@math.Eval{$idx + 1}]};
- #if { "@dir.Long{$current}" !== "@dir.Reverse{@dir.Long{$next}}" } {
- #math idx {$idx + 1};
- #continue;
- };
- #list path delete $idx 2;
- #local idx {@math.Max{1;@math.Eval{$idx - 2}}};
- #local count {@math.Eval{$count - 2}};
- };
- #return {@slist.FromList{$path}};
- };
- ///=== {
- // ## path.Compact <路径>
- // 压缩路径。返回后的新路径。
- //
- // EXAMPLE: \@path.Compact{north;north;north;east;south;south;west}
- // RESULT: {#3 north;east;south;south;west}
- //
- // EXAMPLE: \@path.Compact{n;n;n;e;s;s;w}
- // RESULT: {#3 n;e;s;s;w}
- // };
- #func {path.Compact} {
- #local path {%0};
- #local newPath {};
- #local step {};
- #local last {};
- #local count {};
- #foreach {$path;} {step} {
- #if { "$last" == "$step" } {
- #math count {$count + 1};
- };
- #else {
- #if { "$last" != "" } {
- #if { $count > 2 } {
- #list newPath add {#$count $last};
- };
- #else {
- #local tmp {};
- #loop 1 {$count} {tmp} {
- #list newPath add {$last};
- };
- };
- };
- #local last {$step};
- #local count {1};
- };
- #if { "$step" == "" } {
- #break;
- };
- };
- #return {@slist.FromList{$newPath}};
- };
- ///=== {
- // #@ path.Long <路径>
- // 返回长版本的路径。路径中的每个方向命令都会被扩展成完整的单词。
- //
- // EXAMPLE: \@path.Long{n;n;n;e;w;s}
- // RESULT: {north;north;north;east;west;south}
- // };
- #func {path.Long} {
- #return {@fp.Transform{{%0};{\@dir.Long{VALUE}}}};
- };
- ///=== {
- // #@ path.Short <路径>
- // 返回长版本的路径。路径中的每个方向命令都会被简化。
- //
- // EXAMPLE: \@path.Short{north;north;north;east;south;west}
- // RESULT: {n;n;n;e;s;w}
- // };
- #func {path.Short} {
- #return {@fp.Transform{{%0};{\@dir.Short{VALUE}}}};
- };
- #var xtt.dir.table {
- {east} {{name}{正东} {short}{e} {long}{east} {reverse}{west} }
- {west} {{name}{正西} {short}{w} {long}{west} {reverse}{east} }
- {south} {{name}{正南} {short}{s} {long}{south} {reverse}{north} }
- {north} {{name}{正北} {short}{n} {long}{north} {reverse}{south} }
- {e} {{name}{正东} {short}{e} {long}{east} {reverse}{w} }
- {w} {{name}{正西} {short}{w} {long}{west} {reverse}{e} }
- {s} {{name}{正南} {short}{s} {long}{south} {reverse}{n} }
- {n} {{name}{正北} {short}{n} {long}{north} {reverse}{s} }
- {northeast} {{name}{东北} {short}{ne} {long}{northeast} {reverse}{southwest}}
- {southeast} {{name}{东南} {short}{se} {long}{southeast} {reverse}{northwest}}
- {northwest} {{name}{西北} {short}{nw} {long}{northwest} {reverse}{southeast}}
- {southwest} {{name}{西南} {short}{sw} {long}{southwest} {reverse}{northeast}}
- {ne} {{name}{东北} {short}{ne} {long}{northeast} {reverse}{sw} }
- {se} {{name}{东南} {short}{se} {long}{southeast} {reverse}{nw} }
- {nw} {{name}{西北} {short}{nw} {long}{northwest} {reverse}{se} }
- {sw} {{name}{西南} {short}{sw} {long}{southwest} {reverse}{ne} }
- {up} {{name}{正上} {short}{u} {long}{up} {reverse}{down} }
- {down} {{name}{正下} {short}{d} {long}{down} {reverse}{up} }
- {u} {{name}{正上} {short}{u} {long}{up} {reverse}{d} }
- {d} {{name}{正下} {short}{d} {long}{down} {reverse}{u} }
- {eastup} {{name}{东上} {short}{eu} {long}{eastup} {reverse}{westdown} }
- {westup} {{name}{西上} {short}{wu} {long}{westup} {reverse}{eastdown} }
- {southup} {{name}{南上} {short}{su} {long}{southup} {reverse}{northdown}}
- {northup} {{name}{北上} {short}{nu} {long}{northup} {reverse}{southdown}}
- {eu} {{name}{东上} {short}{eu} {long}{eastup} {reverse}{wd} }
- {wu} {{name}{西上} {short}{wu} {long}{westup} {reverse}{ed} }
- {su} {{name}{南上} {short}{su} {long}{southup} {reverse}{nd} }
- {nu} {{name}{北上} {short}{nu} {long}{northup} {reverse}{sd} }
- {eastdown} {{name}{东下} {short}{ed} {long}{eastdown} {reverse}{westup} }
- {westdown} {{name}{西下} {short}{wd} {long}{westdown} {reverse}{eastup} }
- {southdown} {{name}{南下} {short}{sd} {long}{southdown} {reverse}{northup} }
- {northdown} {{name}{北下} {short}{nd} {long}{northdown} {reverse}{southup} }
- {ed} {{name}{东下} {short}{ed} {long}{eastdown} {reverse}{wu} }
- {wd} {{name}{西下} {short}{wd} {long}{westdown} {reverse}{eu} }
- {sd} {{name}{南下} {short}{sd} {long}{southdown} {reverse}{nu} }
- {nd} {{name}{北下} {short}{nd} {long}{northdown} {reverse}{su} }
- {out} {{name}{出去} {short}{out} {long}{out} {reverse}{enter} }
- {enter} {{name}{进去} {short}{enter} {long}{enter} {reverse}{out} }
- };
- #func {__dir_convert_dir__} {
- #local field {%1};
- #local dir {%2};
- #local restricted {%3};
- #if { "$dir" == "" } {
- #return {};
- };
- #local entry ${xtt.dir.table[$dir]};
- #if { "$entry" == "" } {
- #if { @isTrue{$restricted} } {
- #return {};
- };
- #else {
- #return {$dir};
- };
- };
- #else {
- #return {$entry[$field]};
- };
- };
|