pymud 0.20.2a5__py3-none-any.whl → 0.20.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pymud/pkuxkx.py CHANGED
@@ -1,156 +1,156 @@
1
- # 示例脚本:如何在PyMud中玩PKUXKX
2
-
3
- import webbrowser
4
- from pymud import Alias, Trigger, SimpleCommand, Timer, SimpleTrigger, SimpleAlias
5
-
6
- # 在PyMud中,使用#load {filename}可以加载对应的配置作为脚本文件以提供支撑。支持多脚本加载
7
- # 本示例脚本对PyMud支持的变量(Variable)、触发器(Trigger,包含单行与多行触发)、别名(Alias)、定时器(Timer)、命令(Command,本示例中使用了SimpleCommand子类)都进行了代码示例
8
- # 使用#load {filename}加载的配置文件中,若有一个类型名为Coniguration,则在#load操作时,会自动创建此类型;若没有Configuration类,则仅将文件引入
9
- # 例如,加载本文件指定的配置,则使用 #load pymud.pkuxkx即可
10
-
11
- # PyMud中,触发器Trigger、别名Alias、命令Command,都是匹配对象(MatchObject)的子类,使用同一种处理逻辑
12
- # 匹配对象,意味着有匹配的pattern。在匹配对象成功后,会调用对象的onSuccess方法
13
- # Trigger、Alias仅有成功,即仅onSuccess方法会被调用,该方法参数参考了MushClient,会传递name, line, wildcards三个参数,含义与MushClient相同;
14
-
15
-
16
- class Configuration:
17
-
18
- # hpbrief long情况下的含义
19
- HP_KEYS = (
20
- "combat_exp", "potential", "max_neili", "neili", "max_jingli", "jingli",
21
- "max_qi", "eff_qi", "qi", "max_jing", "eff_jing", "jing",
22
- "vigour/qi", "vigour/yuan", "food", "water", "fighting", "busy"
23
- )
24
-
25
- # 类的构造函数,传递参数session,是会话本身
26
- def __init__(self, session) -> None:
27
- self.session = session
28
- self._triggers = {}
29
- self._commands = {}
30
- self._aliases = {}
31
- self._timers = {}
32
-
33
- self._initTriggers()
34
- self._initCommands()
35
- self._initAliases()
36
- self._initTimers()
37
-
38
- def _initTriggers(self):
39
- '''
40
- 初始化触发器。
41
- 本示例中创建了2个触发器,分别对应fullme的链接触发自动打开浏览器访问该网址,以及hpbrief命令的触发器
42
- '''
43
- # Trigger的构造函数中,给定的位置参数仅有session(会话)和pattern(匹配模式)两个,其他所有参数都是使用命名参数进行实现
44
- # 支持的命名参数详细可参见 BaseObject与MatchObject 的构造方法,此处简单列举
45
- # id : 唯一标识,不指定时自动生成
46
- # group : 组名,不指定时为空
47
- # enabled : 使能状态,默认True
48
- # priority : 优先级,默认100,越小越高
49
- # oneShot : 单次匹配,默认False
50
- # ignoreCase : 忽略大小写,默认False
51
- # isRegExp : 正则表达式模式,默认True
52
- # keepEval : 持续匹配,默认False
53
- # raw : 原始匹配方式,默认False。原始匹配方式下,不对VT100下的ANSI颜色进行解码,因此可以匹配颜色;正常匹配仅匹配文本
54
-
55
- # 1. fullme的链接对应的触发器,匹配URL
56
- # 当匹配成功后,调用ontri_webpage
57
- self._triggers["tri_webpage"] = self.tri_webpage = Trigger(self.session, id = 'tri_webpage', patterns = r'^http://fullme.pkuxkx.net/robot.php.+$', group = "sys", onSuccess = lambda id, line, wildcards: webbrowser.open(line))
58
- # 2. fullme的链接对应的触发器,因为要进行多行匹配(3行),因此匹配模式pattern为3个正则表达式模式构成的元组(所有列表类型均可识别),无需像MushClient一样要指定multiline标识和linesToMatch数量
59
- # 当匹配成功后,调用ontri_hpbrief
60
- # 特别说明:此处的hpbrief触发匹配,需要set hpbrief long后才可以支持
61
- self._triggers["tri_hp"] = self.tri_hp = Trigger(self.session, id = 'tri_hpbrief', patterns = (r'^[> ]*#(\d+.?\d*[KM]?),(\d+),(\d+),(\d+),(\d+),(\d+)$', r'^[> ]*#(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)$', r'^[> ]*#(\d+),(\d+),(-?\d+),(-?\d+),(\d+),(\d+)$',), group = "sys", onSuccess = self.ontri_hpbrief)
62
-
63
- # 3. 现在支持简单Trigger了,例如
64
- self._triggers["tri_gem"] = SimpleTrigger(self.session ,r'^[> ]*从.+身上.+[◎☆★].+', "pack gem", group = "sys")
65
-
66
- self.session.addTriggers(self._triggers)
67
-
68
-
69
- def _initCommands(self):
70
- '''初始化命令,本示例中创建了1个命令,支持hpbrief命令'''
71
-
72
- # Command是异步执行的命令,可以理解为Alias+Trigger+Timer的组合。在MUD中发出一条命令后,会有成功、失败、超时的不同状态,在这三种状态下,会分别调用onSuccess、onFailure、onTimeout方法
73
- # 举个Command的应用例子说明:加入把移动(s/e/n/w等等)实现为一个Command。
74
- # 1. 当向某个方向移动时,成功的时候会移动到下一个房间;
75
- # 2. 不成功的时候,会出现“这个方向没有出路”等描述;
76
- # 3. 而当角色处于晕倒状态时,移动命令是不会有任何反应的,超出设定超时时间之后,会调用onTimeout
77
- # 在上述实现情况下,我们在执行命令时,可以明确的根据命令的执行结果再判断下一步该做什么
78
- # 本示例使用了简单命令SimpleCommand,其在MatchObject的基础上,增加了以下参数:
79
- # 1. succ_tri: 命令执行成功时的触发器,不能为空
80
- # 2. fail_tri: 命令执行失败时的触发器,可以为空
81
- # 3. retry_tri: 需要重新尝试命令的触发器,可以为空(仍以移动为例,当向某个方向移动,出现“你现在正忙着呢”之后,可以在等待2s之后,再次尝试该命令,知道到达最大尝试次数
82
-
83
- # 命令可以同步调用,也可以在异步函数(async)中使用await语法异步调用
84
- # 例如,下面的hpbrief可以在这样使用:
85
- # self.session.exec_command("hpbrief")
86
- # self.session.exec_command_after(2, "hpbrief")
87
- # await self.cmd_hpbrief.execute("hpbrief")
88
-
89
- # 异步实现意味着,在函数实现过程中可以以循环实现,而不是以回调实现,有利于代码的可读性
90
- # 假设已经实现了一个 cmd_move 的 Command,现在要从ct 执行"s;s;w"行走指令到达春来茶馆,然后根据当前的hpbrief结果判断是否需要drink,然后走回中央广场,可以在函数中这样实现:
91
- # async def gotodrink(self):
92
- # for step in "s;s;w".split(";"):
93
- # await self.cmd_move.execute(step)
94
- # await self.cmd_hpbrief.execute("hpbrief")
95
- # await asyncio.sleep(1)
96
- # water = self.session.getVariable("water")
97
- # if int(water) < 300:
98
- # self.session.writeline("drink")
99
- # await asyncio.sleep(1)
100
- # for step in "e;n;n".split(";"):
101
- # await self.cmd_move.execute(step)
102
-
103
-
104
- self._commands['cmd_hpbrief'] = self.cmd_hpbrief = SimpleCommand(self.session, id = "cmd_hpbrief", patterns = "^hpbrief$", succ_tri = self.tri_hp, group = "status", onSuccess = self.oncmd_hpbrief)
105
- self.session.addCommands(self._commands)
106
-
107
- def _initAliases(self):
108
- '''初始化别名,本示例中创建了1个别名,是get xxx from corpse'''
109
-
110
- # get xxx from corpse的别名操作,匹配成功后会自动调用getfromcorpse函数
111
- # 例如, gp silver 相当于 get silver from corpse
112
- self._aliases['ali_get'] = Alias(self.session, r"^gp\s(.+)$", id = "ali_get", onSuccess = self.getfromcorpse)
113
-
114
- # 3. 现在支持简单Alias了,在其中也可以支持#wait(缩写为#wa操作)等待,当然,Trigger也支持
115
- # 从扬州中心广场到西门的行走,每步中间插入100ms等待
116
- self._aliases["ali_yz_xm"] = SimpleAlias(self.session ,'^yz_xm$', "w;#wa 100;w;#wa 100;w;#wa 100;w", group = "sys")
117
-
118
- self.session.addAliases(self._aliases)
119
-
120
- def _initTimers(self):
121
- '''初始化定时器,本示例中创建了1个定时器,每隔2秒打印信息'''
122
-
123
- self._timers["tm_test"] = self.tm_test = Timer(self.session, timeout = 2, id = "tm_test", onSuccess = self.onTimer)
124
- self.session.addTimers(self._timers)
125
-
126
- def getfromcorpse(self, name, line, wildcards):
127
- cmd = f"get {wildcards[0]} from corpse"
128
- self.session.writeline(cmd)
129
-
130
- def onTimer(self, name, *args, **kwargs):
131
- self.session.info("每2秒都会打印本信息", "定时器测试")
132
-
133
- def ontri_hpbrief(self, name, line, wildcards):
134
- self.session.setVariables(self.HP_KEYS, wildcards)
135
-
136
- def oncmd_hpbrief(self, name, cmd, line, wildcards):
137
- # 为了节省服务器资源,应使用hpbrief来代替hp指令
138
- # 但是hpbrief指令的数据看起来太麻烦,所以将hpbrief的一串数字输出成类似hp的样式
139
- # ┌───个人状态────────────────────┬─────────────────────────────┐
140
- # │【精神】 1502 / 1502 [100%] │【精力】 4002 / 4002 (+ 0) │
141
- # │【气血】 2500 / 2500 [100%] │【内力】 5324 / 5458 (+ 0) │
142
- # │【真气】 0 / 0 [ 0%] │【禅定】 101% [正常] │
143
- # │【食物】 222 / 400 [缺食] │【潜能】 36,955 │
144
- # │【饮水】 247 / 400 [缺水] │【经验】 2,341,005 │
145
- # ├─────────────────────────────┴─────────────────────────────┤
146
- # │【状态】 健康、怒 │
147
- # └────────────────────────────────────────────北大侠客行────────┘
148
- var1 = self.session.getVariables(("jing", "effjing", "maxjing", "jingli", "maxjingli"))
149
- line1 = "【精神】 {0:<8} [{5:3.0f}%] / {1:<8} [{2:3.0f}%] |【精力】 {3:<8} / {4:<8} [{6:3.0f}%]".format(var1[0], var1[1], 100 * float(var1[1]) / float(var1[2]), var1[3], var1[4], 100 * float(var1[0]) / float(var1[2]), 100 * float(var1[3]) / float(var1[4]))
150
- var2 = self.session.getVariables(("qi", "effqi", "maxqi", "neili", "maxneili"))
151
- line2 = "【气血】 {0:<8} [{5:3.0f}%] / {1:<8} [{2:3.0f}%] |【内力】 {3:<8} / {4:<8} [{6:3.0f}%]".format(var2[0], var2[1], 100 * float(var2[1]) / float(var2[2]), var2[3], var2[4], 100 * float(var2[0]) / float(var2[2]), 100 * float(var2[3]) / float(var2[4]))
152
- var3 = self.session.getVariables(("food", "water", "exp", "pot", "fighting", "busy"))
153
- line3 = "【食物】 {0:<4} 【饮水】{1:<4} 【经验】{2:<9} 【潜能】{3:<10}【{4}】【{5}】".format(var3[0], var3[1], var3[2], var3[3], "未战斗" if var3[4] == "0" else "战斗中", "不忙" if var3[5] == "0" else "忙")
154
- self.session.info(line1, "状态")
155
- self.session.info(line2, "状态")
156
- self.session.info(line3, "状态")
1
+ # 示例脚本:如何在PyMud中玩PKUXKX
2
+
3
+ import webbrowser
4
+ from pymud import Alias, Trigger, SimpleCommand, Timer, SimpleTrigger, SimpleAlias
5
+
6
+ # 在PyMud中,使用#load {filename}可以加载对应的配置作为脚本文件以提供支撑。支持多脚本加载
7
+ # 本示例脚本对PyMud支持的变量(Variable)、触发器(Trigger,包含单行与多行触发)、别名(Alias)、定时器(Timer)、命令(Command,本示例中使用了SimpleCommand子类)都进行了代码示例
8
+ # 使用#load {filename}加载的配置文件中,若有一个类型名为Coniguration,则在#load操作时,会自动创建此类型;若没有Configuration类,则仅将文件引入
9
+ # 例如,加载本文件指定的配置,则使用 #load pymud.pkuxkx即可
10
+
11
+ # PyMud中,触发器Trigger、别名Alias、命令Command,都是匹配对象(MatchObject)的子类,使用同一种处理逻辑
12
+ # 匹配对象,意味着有匹配的pattern。在匹配对象成功后,会调用对象的onSuccess方法
13
+ # Trigger、Alias仅有成功,即仅onSuccess方法会被调用,该方法参数参考了MushClient,会传递name, line, wildcards三个参数,含义与MushClient相同;
14
+
15
+
16
+ class Configuration:
17
+
18
+ # hpbrief long情况下的含义
19
+ HP_KEYS = (
20
+ "combat_exp", "potential", "max_neili", "neili", "max_jingli", "jingli",
21
+ "max_qi", "eff_qi", "qi", "max_jing", "eff_jing", "jing",
22
+ "vigour/qi", "vigour/yuan", "food", "water", "fighting", "busy"
23
+ )
24
+
25
+ # 类的构造函数,传递参数session,是会话本身
26
+ def __init__(self, session) -> None:
27
+ self.session = session
28
+ self._triggers = {}
29
+ self._commands = {}
30
+ self._aliases = {}
31
+ self._timers = {}
32
+
33
+ self._initTriggers()
34
+ self._initCommands()
35
+ self._initAliases()
36
+ self._initTimers()
37
+
38
+ def _initTriggers(self):
39
+ '''
40
+ 初始化触发器。
41
+ 本示例中创建了2个触发器,分别对应fullme的链接触发自动打开浏览器访问该网址,以及hpbrief命令的触发器
42
+ '''
43
+ # Trigger的构造函数中,给定的位置参数仅有session(会话)和pattern(匹配模式)两个,其他所有参数都是使用命名参数进行实现
44
+ # 支持的命名参数详细可参见 BaseObject与MatchObject 的构造方法,此处简单列举
45
+ # id : 唯一标识,不指定时自动生成
46
+ # group : 组名,不指定时为空
47
+ # enabled : 使能状态,默认True
48
+ # priority : 优先级,默认100,越小越高
49
+ # oneShot : 单次匹配,默认False
50
+ # ignoreCase : 忽略大小写,默认False
51
+ # isRegExp : 正则表达式模式,默认True
52
+ # keepEval : 持续匹配,默认False
53
+ # raw : 原始匹配方式,默认False。原始匹配方式下,不对VT100下的ANSI颜色进行解码,因此可以匹配颜色;正常匹配仅匹配文本
54
+
55
+ # 1. fullme的链接对应的触发器,匹配URL
56
+ # 当匹配成功后,调用ontri_webpage
57
+ self._triggers["tri_webpage"] = self.tri_webpage = Trigger(self.session, id = 'tri_webpage', patterns = r'^http://fullme.pkuxkx.net/robot.php.+$', group = "sys", onSuccess = lambda id, line, wildcards: webbrowser.open(line))
58
+ # 2. fullme的链接对应的触发器,因为要进行多行匹配(3行),因此匹配模式pattern为3个正则表达式模式构成的元组(所有列表类型均可识别),无需像MushClient一样要指定multiline标识和linesToMatch数量
59
+ # 当匹配成功后,调用ontri_hpbrief
60
+ # 特别说明:此处的hpbrief触发匹配,需要set hpbrief long后才可以支持
61
+ self._triggers["tri_hp"] = self.tri_hp = Trigger(self.session, id = 'tri_hpbrief', patterns = (r'^[> ]*#(\d+.?\d*[KM]?),(\d+),(\d+),(\d+),(\d+),(\d+)$', r'^[> ]*#(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)$', r'^[> ]*#(\d+),(\d+),(-?\d+),(-?\d+),(\d+),(\d+)$',), group = "sys", onSuccess = self.ontri_hpbrief)
62
+
63
+ # 3. 现在支持简单Trigger了,例如
64
+ self._triggers["tri_gem"] = SimpleTrigger(self.session ,r'^[> ]*从.+身上.+[◎☆★].+', "pack gem", group = "sys")
65
+
66
+ self.session.addTriggers(self._triggers)
67
+
68
+
69
+ def _initCommands(self):
70
+ '''初始化命令,本示例中创建了1个命令,支持hpbrief命令'''
71
+
72
+ # Command是异步执行的命令,可以理解为Alias+Trigger+Timer的组合。在MUD中发出一条命令后,会有成功、失败、超时的不同状态,在这三种状态下,会分别调用onSuccess、onFailure、onTimeout方法
73
+ # 举个Command的应用例子说明:加入把移动(s/e/n/w等等)实现为一个Command。
74
+ # 1. 当向某个方向移动时,成功的时候会移动到下一个房间;
75
+ # 2. 不成功的时候,会出现“这个方向没有出路”等描述;
76
+ # 3. 而当角色处于晕倒状态时,移动命令是不会有任何反应的,超出设定超时时间之后,会调用onTimeout
77
+ # 在上述实现情况下,我们在执行命令时,可以明确的根据命令的执行结果再判断下一步该做什么
78
+ # 本示例使用了简单命令SimpleCommand,其在MatchObject的基础上,增加了以下参数:
79
+ # 1. succ_tri: 命令执行成功时的触发器,不能为空
80
+ # 2. fail_tri: 命令执行失败时的触发器,可以为空
81
+ # 3. retry_tri: 需要重新尝试命令的触发器,可以为空(仍以移动为例,当向某个方向移动,出现“你现在正忙着呢”之后,可以在等待2s之后,再次尝试该命令,知道到达最大尝试次数
82
+
83
+ # 命令可以同步调用,也可以在异步函数(async)中使用await语法异步调用
84
+ # 例如,下面的hpbrief可以在这样使用:
85
+ # self.session.exec_command("hpbrief")
86
+ # self.session.exec_command_after(2, "hpbrief")
87
+ # await self.cmd_hpbrief.execute("hpbrief")
88
+
89
+ # 异步实现意味着,在函数实现过程中可以以循环实现,而不是以回调实现,有利于代码的可读性
90
+ # 假设已经实现了一个 cmd_move 的 Command,现在要从ct 执行"s;s;w"行走指令到达春来茶馆,然后根据当前的hpbrief结果判断是否需要drink,然后走回中央广场,可以在函数中这样实现:
91
+ # async def gotodrink(self):
92
+ # for step in "s;s;w".split(";"):
93
+ # await self.cmd_move.execute(step)
94
+ # await self.cmd_hpbrief.execute("hpbrief")
95
+ # await asyncio.sleep(1)
96
+ # water = self.session.getVariable("water")
97
+ # if int(water) < 300:
98
+ # self.session.writeline("drink")
99
+ # await asyncio.sleep(1)
100
+ # for step in "e;n;n".split(";"):
101
+ # await self.cmd_move.execute(step)
102
+
103
+
104
+ self._commands['cmd_hpbrief'] = self.cmd_hpbrief = SimpleCommand(self.session, id = "cmd_hpbrief", patterns = "^hpbrief$", succ_tri = self.tri_hp, group = "status", onSuccess = self.oncmd_hpbrief)
105
+ self.session.addCommands(self._commands)
106
+
107
+ def _initAliases(self):
108
+ '''初始化别名,本示例中创建了1个别名,是get xxx from corpse'''
109
+
110
+ # get xxx from corpse的别名操作,匹配成功后会自动调用getfromcorpse函数
111
+ # 例如, gp silver 相当于 get silver from corpse
112
+ self._aliases['ali_get'] = Alias(self.session, r"^gp\s(.+)$", id = "ali_get", onSuccess = self.getfromcorpse)
113
+
114
+ # 3. 现在支持简单Alias了,在其中也可以支持#wait(缩写为#wa操作)等待,当然,Trigger也支持
115
+ # 从扬州中心广场到西门的行走,每步中间插入100ms等待
116
+ self._aliases["ali_yz_xm"] = SimpleAlias(self.session ,'^yz_xm$', "w;#wa 100;w;#wa 100;w;#wa 100;w", group = "sys")
117
+
118
+ self.session.addAliases(self._aliases)
119
+
120
+ def _initTimers(self):
121
+ '''初始化定时器,本示例中创建了1个定时器,每隔2秒打印信息'''
122
+
123
+ self._timers["tm_test"] = self.tm_test = Timer(self.session, timeout = 2, id = "tm_test", onSuccess = self.onTimer)
124
+ self.session.addTimers(self._timers)
125
+
126
+ def getfromcorpse(self, name, line, wildcards):
127
+ cmd = f"get {wildcards[0]} from corpse"
128
+ self.session.writeline(cmd)
129
+
130
+ def onTimer(self, name, *args, **kwargs):
131
+ self.session.info("每2秒都会打印本信息", "定时器测试")
132
+
133
+ def ontri_hpbrief(self, name, line, wildcards):
134
+ self.session.setVariables(self.HP_KEYS, wildcards)
135
+
136
+ def oncmd_hpbrief(self, name, cmd, line, wildcards):
137
+ # 为了节省服务器资源,应使用hpbrief来代替hp指令
138
+ # 但是hpbrief指令的数据看起来太麻烦,所以将hpbrief的一串数字输出成类似hp的样式
139
+ # ┌───个人状态────────────────────┬─────────────────────────────┐
140
+ # │【精神】 1502 / 1502 [100%] │【精力】 4002 / 4002 (+ 0) │
141
+ # │【气血】 2500 / 2500 [100%] │【内力】 5324 / 5458 (+ 0) │
142
+ # │【真气】 0 / 0 [ 0%] │【禅定】 101% [正常] │
143
+ # │【食物】 222 / 400 [缺食] │【潜能】 36,955 │
144
+ # │【饮水】 247 / 400 [缺水] │【经验】 2,341,005 │
145
+ # ├─────────────────────────────┴─────────────────────────────┤
146
+ # │【状态】 健康、怒 │
147
+ # └────────────────────────────────────────────北大侠客行────────┘
148
+ var1 = self.session.getVariables(("jing", "effjing", "maxjing", "jingli", "maxjingli"))
149
+ line1 = "【精神】 {0:<8} [{5:3.0f}%] / {1:<8} [{2:3.0f}%] |【精力】 {3:<8} / {4:<8} [{6:3.0f}%]".format(var1[0], var1[1], 100 * float(var1[1]) / float(var1[2]), var1[3], var1[4], 100 * float(var1[0]) / float(var1[2]), 100 * float(var1[3]) / float(var1[4]))
150
+ var2 = self.session.getVariables(("qi", "effqi", "maxqi", "neili", "maxneili"))
151
+ line2 = "【气血】 {0:<8} [{5:3.0f}%] / {1:<8} [{2:3.0f}%] |【内力】 {3:<8} / {4:<8} [{6:3.0f}%]".format(var2[0], var2[1], 100 * float(var2[1]) / float(var2[2]), var2[3], var2[4], 100 * float(var2[0]) / float(var2[2]), 100 * float(var2[3]) / float(var2[4]))
152
+ var3 = self.session.getVariables(("food", "water", "exp", "pot", "fighting", "busy"))
153
+ line3 = "【食物】 {0:<4} 【饮水】{1:<4} 【经验】{2:<9} 【潜能】{3:<10}【{4}】【{5}】".format(var3[0], var3[1], var3[2], var3[3], "未战斗" if var3[4] == "0" else "战斗中", "不忙" if var3[5] == "0" else "忙")
154
+ self.session.info(line1, "状态")
155
+ self.session.info(line2, "状态")
156
+ self.session.info(line3, "状态")