#nop vim: set filetype=tt:; /* 本文件属于 PaoTin++ 的一部分。 PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp ) 享有并保留一切法律权利 你可以在遵照 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]}; }; };