jarlyyn
发表于 2025-5-20 15:53:10
Landmark 定位
public partial class Landmark
{
public string Key { get; set; } = "";
public string Type { get; set; } = "";
public string Value { get; set; } = "";
public string Group { get; set; } = "";
public string Desc { get; set; } = "";
}
给你放用来定位的数据的。
根据key 和Type 唯一,供你的脚本读取
以我非北侠机器为例
let matcherssl = /^象一蓬蓬巨伞般伸向天空,把阳光遮得丝毫也无。尺把厚的松针/
let matchergc = "错节,据传已有千年的树龄,是这座城市的历史见证。树干底部有一个很大"
let matcheryp = "抽屉里散发出来的。神医平一指坐在茶几旁,独自喝着茶,看也不看你一眼。"
let matcherdzm = " 前面就是明教的“地字门”了,这里是明教中女弟子"
这是4个定位用的正则,那完全可以创建 key=房间key,type=regex的定位信息,机器启动时批量加载
当然,北侠也不可能这么简单就能实现一个可用的定位系统
甚至由于北侠这类MUD的特点,我必须实现同一个Key的多种Type的定位信息共存,这样才能通过多种依据定位,避免一不小心被一锅端。
jarlyyn
发表于 2025-5-20 15:57:20
Shortcut 捷径
public class RoomConditionExit : Exit
{
public List<ValueCondition> RoomConditions { get; set; } = [];
}
public partial class Shortcut : RoomConditionExit
{
public string Key { get; set; } = "";
public string Group { get; set; } = "";
public string Desc { get; set; } = "";
}就是一个带Key和房间条件的非固定出口。
这个在北侠可能对大部分人没用。
在有miss或者rideto的mud比较实用点。
jarlyyn
发表于 2025-5-20 15:58:22
Variable 变量
public class Variable
{
public string Key { get; set; } = "";
public string Value { get; set; } = "";
public string Group { get; set; } = "";
public string Desc { get; set; } = "";
}和客户端的变量一样,给脚本用的,爱存啥我不管。
jarlyyn
发表于 2025-5-20 16:04:49
Snapshot 快照
public partial class Snapshot
{
public static Snapshot Create(string key, string type, string value, string group)
{
return new Snapshot()
{
Key = key,
Type = type,
Value = value,
Timestamp = (int)(new DateTimeOffset(DateTime.UtcNow)).ToUnixTimeSeconds(),
Group = group,
};
}
public string Key { get; set; } = "";
public int Timestamp = 0;
public string Group { get; set; } = "";
public string Type { get; set; } = "";
public int Count { get; set; } = 1;
public string Value { get; set; } = "";
}
在北侠很实用的结构吧。
这个理论上就是把扫街的结果,进行存储的原始数据结构。
同Key,Type,Value唯一。
处于扫街结果的常态和节约空间,如果取得了同样的Key,Type,Value,会只更新更新时间,以及Count+1
并提供简单的查找接口。
用途么,就是扫加,把NPC。房间名/房间描述 保存起来。
遇到Task之类的任务,进行查找过滤,或者脚本分析生成合适的定位数据。
理论上不该归我编辑器管,但实际我又用到的一个结构。
jarlyyn
发表于 2025-5-20 16:16:12
好了,基本数据结构到这里了,再来个彩蛋。
对于地图计算来说,基础数据重要,但只依赖基础数据是不够的。
比如我大量引入了标签和条件,这个在哪里设置呢?
所以,在脚本里,肯定要维护个当前环境的数据
public class Environment
{
public List<ValueTag> Tags = [];
public List<ValueCondition> RoomConditions = [];
public List<Room> Rooms = [];
public List<Path> Paths = [];
public List<RoomConditionExit> Shortcuts = [];
public List<string> Whitelist = [];
public List<string> Blacklist = [];
public List<Link> BlockedLinks = [];
public List<CommandCost> CommandCosts = [];
}
[*]Tags,标签列表,用于判断某些出口是否可用
[*]RoomConditions,房间条件列表,用于在规划路线时排除某类房间,比如不走安全房间……
[*]Rooms,额外房间。有些动态的房间信息,比如个人住房,每次重启后更新的迷宫。这些明显不适合放在地图信息里。
[*]Paths,临时出口。配合额外房间使用的。
[*]Shortcuts,额外的捷径,适合能自定义飞行的MUD
[*]Whitelist,白名单模式,只能在指定的房间里规划路径
[*]Blacklist,黑名单模式,不经过指定的房间
[*]BlockedLinks,临时屏蔽房间的出口,排除房间A去房间B的所有路径。适合在杀不过NPC时放弃部分路径/房间。当然,北侠喜欢Guard玩家,这也是很好的解决方式。被Guard一次,我直接把这个出口加进黑名单半小时,您慢慢晾着。
[*]CommandCost 指令耗时的动态修改。说实话,这个只是理论上该有,我没用过。
光光静态的地图是没法应对复杂的MUD设定的。有了完善的环境信息才能尽可能的无视某些蛋疼的设定。
对了,对于实际行走,我还有一个选项结构
public class MapperOptions
{
public int MaxExitCost = 0;
public int MaxTotalCost = 0;
public bool DisableShortcuts = false;
}能设定每个规划的
[*]最大单步耗时,太耗时的出口不走
[*]最大总耗时,超过这个耗时停止规划
[*]禁用捷径,字面意思
总体来说,我追求在静态的地图数据外,还能尽可能的动态的进行调整,不能抱着死地图不放。
jarlyyn
发表于 2025-5-20 16:23:29
API参考
我具体实现的API
List/Insert/Remove系列
维护原始数据
public QueryReuslt? APIQueryPathAny(List<string> from, List<string> target, Context context, MapperOptions options)
多个起点和多个终点之间的路径规划,实际用的最多的是1对多
public QueryReuslt? APIQueryPathAll(string start, List<string> target, Context context, MapperOptions options)
无顺序房间的动态规划,核心,动态查询房间后,通过多次单步模拟行走的方式,计算出遍历路径
public QueryReuslt? APIQueryPathOrdered(string start, List<string> target, Context context, MapperOptions options)
有顺序的动态规划,通过多次单步模拟行走计算
public List<string> APIQueryRegionRooms(string key)
查询区域房间,配合APIQueryPathAll使用
public List<string> APIDilate(List<string> src, int iterations, Context context, MapperOptions options)膨胀房间,具体用途,比如获取扬州的所有房间,然后npc不是会跑么,膨胀3格遍历
public string APITrackExit(string start, string command, Context context, MapperOptions options)
跟踪出口,看会去哪里
public List<Room> APISearchRooms(RoomFilter filter)
根据过滤器,搜索房间
public List<Room> APIFilterRooms(List<string> src, RoomFilter filter)
在限定的房间里过滤房间,比如只找扬州的非安全房间
public void APITakeSnapshot(string key, string type, string value, string group)
拍摄快照,扫街用
public void APITraceLocation(string key, string location)
记录足迹,扫街用
public void APITagRoom(string key, string tag, int value)
给房间打标记,扫街用
public void APISetRoomData(string roomkey, string datakey, string datavalue)
设置房间数据,扫街用
public void APIGroupRoom(string key, string group)
设置房间分组,扫街用
jarlyyn
发表于 2025-5-20 16:24:02
打完收工,准备写lua/js实现
non
发表于 2025-5-22 17:19:59
厉害,看不懂。。。。
bkingdom
发表于 2025-5-22 17:26:40
能不能弄个python呀
shenji
发表于 2025-5-22 17:53:07
jarlyyn 发表于 2025-5-20 04:24 PM
打完收工,准备写lua/js实现
你要说这个我可就不困了