With the release of MUSHClient 4.40, the lua scripters have access to a new tool: LPEG. How do they
compare to one another? Nick gave us a sample of what LPEG and the RE.lua can do, but I was curious
about a more practical benchmark.
Let's test it against some more practical data.
On the mud I play, 3 Kingdoms, my HP bar looks like:
Some of the considerations I've needed to make in my trigger were:
Since PCRE does not handle recursion well, nor repeated captures, a secondary pass
to actually parse the abilites is needed.
**NB: The benchmark in this test was done thru the rex library in the Lua script engine. It is not indicative of the MushClient C++ implementation of the trigger engine.
The resulting table looks like:
Okay. It works. It's not pretty. The resulting table is mostly flat. Running pcre:match(hp) and the supporting function 100,000 times on my laptop took 12 seconds.
compare to one another? Nick gave us a sample of what LPEG and the RE.lua can do, but I was curious
about a more practical benchmark.
Let's test it against some more practical data.
On the mud I play, 3 Kingdoms, my HP bar looks like:
HP: 1346/1351 K: 497/537 SP: 289/289 V: 91% [[ AG:379 O:362 ab RF PE:238 PH:139 B HS:50 ]] P: 8 T:98% | 811372/2914265 (45%)
Some of the considerations I've needed to make in my trigger were:
- Not all pieces are always there: the "P: #" and the "T:98%" are only present if I'm performing a song, or in combat.
- Everything between the "[[" and "]]" are abilities. They are in no fixed order, nor will the entire section be there if no abilities are up.
Since PCRE does not handle recursion well, nor repeated captures, a secondary pass
to actually parse the abilites is needed.
**NB: The benchmark in this test was done thru the rex library in the Lua script engine. It is not indicative of the MushClient C++ implementation of the trigger engine.
pcre = rex.new [=[^ HP\: (?P<cHP>\d+)\/(?P<mHP>\d+) K\: (?P<cKarma>\d+)\/(?P<mKarma>\d+) SP\: (?P<cSP>\d+)\/(?P<mSP>\d+) V\: (?P<cVoice>\d+)\% (?:[[ (?<Powers>.*?) ]] )?(?P<Performing>P\: (?P<duration>(?:\d+|\*)))? (?P<inCombat>T\:((?P<BadGuyHealth>\d+)\%?|\w+))? \| (?P<GXPtoSpend>\d+)\/(?P<GXPtoNextLevel>\d+) \((?P<GXPtoNextPercent>.+)\%\)$]=]
function ParseHPFlags(wilds)
vars = {mVoice = 100}
vars.ActivePowers={}
for k,v in pairs(wilds) do
vars[k] = tonumber(v) or v
end
percent(vars, "HP")
percent(vars, "SP")
percent(vars, "Karma")
vars.pVoice = vars.cVoice
if vars.Powers then
for Flag,Duration in vars.Powers:gmatch( "([^ :]+):?(%d*)") do
vars.ActivePowers[Flag] = tonumber(Duration) or true
end end
end
function percent(self, val)
self["p" .. val] = math.floor((self["c"..val]/self["m"..val])*100)
end
The resulting table looks like:
tprint(vars) -->
1=1346
2=1351
3=497
4=537
5=289
6=289
7=91
8="AG:379 O:362 ab RF PE:238 PH:139 B HS:50"
9="P: 8"
10=8
11="T:98%"
12="98%"
13=98
14=811372
15=2914265
16=45
"ActivePowers":
"AG"=379
"B"=true
"HS"=50
"O"=362
"PE"=238
"PH"=139
"RF"=true
"ab"=true
"BadGuyHealth"=98
"GXPtoNextLevel"=2914265
"GXPtoNextPercent"=45
"GXPtoSpend"=811372
"Performing"="P: 8"
"Powers"="AG:379 O:362 ab RF PE:238 PH:139 B HS:50"
"cHP"=1346
"cKarma"=497
"cSP"=289
"cVoice"=91
"duration"=8
"inCombat"="T:98%"
"mHP"=1351
"mKarma"=537
"mSP"=289
"mVoice"=100
"pHP"=99
"pKarma"=92
"pSP"=100
"pVoice"=91
Okay. It works. It's not pretty. The resulting table is mostly flat. Running pcre:match(hp) and the supporting function 100,000 times on my laptop took 12 seconds.