<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE MudletPackage>
<MudletPackage version="1.0">
    <TriggerPackage>
        <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
            <name>Mudlet Mapper</name>
            <script></script>
            <triggerType>0</triggerType>
            <conditonLineDelta>0</conditonLineDelta>
            <mStayOpen>0</mStayOpen>
            <mCommand></mCommand>
            <packageName></packageName>
            <mFgColor>#ff0000</mFgColor>
            <mBgColor>#ffff00</mBgColor>
            <mSoundFile></mSoundFile>
            <colorTriggerFgColor>#000000</colorTriggerFgColor>
            <colorTriggerBgColor>#000000</colorTriggerBgColor>
            <regexCodeList/>
            <regexCodePropertyList/>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Have to swim</name>
                <script>mmp.swim()</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>There's water ahead of you. You'll have to swim in that direction to make it through.</string>
                    <string>There's water ahead of you. You'll have to swim in that direction to make it </string>
                    <string>There's water ahead of you. You'll have to SWIM </string>
                    <string>You'll have to swim to make it through the water in that direction.</string>
                    <string>The water is too deep for you to walk that way, you must swim.</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>3</integer>
                    <integer>3</integer>
                    <integer>2</integer>
                    <integer>3</integer>
                    <integer>3</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Rubble at the exit</name>
                <script>mmp.customwalkdelay(2)</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>You begin to slowly clamber over the rubble that blocks your way.</string>
                    <string>You begin to slowly clamber over a pile of rubble that blocks your way.</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>3</integer>
                    <integer>3</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Too quick</name>
                <script>if mmp.autowalking then
  mmp.deleteLineP()
end</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>99</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>Now now, don't be so hasty!</string>
                    <string>You can not move that fast!</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>3</integer>
                    <integer>3</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Hobbling</name>
                <script>mmp.customwalkdelay(2)</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>You slowly hobble</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>2</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Frozen</name>
                <script>mmp.customwalkdelay(2)</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>You begin moving your frozen body slowly</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>2</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>People here</name>
                <script>mmp.pdb_lastupdate = {}</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>1</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>You see the following people here:</string>
                    <string>1</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>3</integer>
                    <integer>5</integer>
                </regexCodePropertyList>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="yes" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Person</name>
                    <script>for i = 1, #matches, 2 do
  mmp.pdb[matches[i]] = mmp.currentroomname
  mmp.pdb_lastupdate[matches[i]] = true
  raiseEvent(&quot;mmapper updated pdb&quot;)
end</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#aaff00</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>([A-Z][a-z]+)</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Retardation/aeon walk delay</name>
                <script>mmp.customwalkdelay(2)</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>You move sluggishly into action.</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>3</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Scent (Achaea+Imperian)</name>
                <script>mmp.roomEcho(matches[2]) </script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>^You detect traces of scent from (.+)\.$</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>1</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Alertness (Achaea+Imperian)</name>
                <script>mmp.alertness = mmp.alertness or {}

for k, v in pairs (gmcp.Room.Info.exits) do
  if mmp.roomexists(v) and matches[3]:lower() == getRoomName(v):lower() and mmp.anytolong(k) then
    mmp.alertness[mmp.anytolong(k)] = mmp.alertness[mmp.anytolong(k)] or {}
    mmp.alertness[mmp.anytolong(k)][#mmp.alertness[mmp.anytolong(k)]+1] = matches[2]
    deleteLine()
  end
end

local currentroomname = mmp.currentroomname
if string.ends(currentroomname, &quot; (road)&quot;) then
	currentroomname = string.sub(currentroomname, 1, (#currentroomname-7))
end

if matches[3] == currentroomname then
  mmp.alertness.here = mmp.alertness.here or {}
  mmp.alertness.here[#mmp.alertness.here+1] = matches[2]
  deleteLine()
end

mmp.pdb[matches[2]] = matches[3]
mmp.pdb_lastupdate[matches[2]] = true

enableTrigger&quot;Mudlet Mapper prompt trigger&quot;</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>^Your enhanced senses inform you that (\w+) has entered (.+?)(?: nearby)?\.$</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>1</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="no" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Mudlet Mapper prompt trigger</name>
                <script>-- to be enabled by functions that need it and disabled after it's done. Sort of like a cheap prompttrigger from Svo.

-- handle alertness
if mmp.alertness then

  if svo and svo.showprompt then selectCurrentLine() replace&quot;&quot;
  elseif mm and mm.showprompt then selectCurrentLine() replace&quot;&quot;
  end

  for direction, people in pairs(mmp.alertness) do
    cecho(&quot;&lt;red&gt;[&lt;cyan&gt;&quot; .. direction .. &quot; &lt;red&gt;- &lt;white&gt;&quot; .. ((svo and svo.concatand) and svo.concatand(people) or table.concat(people, ', ')) .. &quot; (&quot;..#people..&quot;)&lt;red&gt;]\n&quot;)
  end

  if svo and svo.showprompt then svo.showprompt()
  elseif mm and mm.showprompt then mm.showprompt()
  end

  mmp.alertness = nil
  raiseEvent(&quot;mmapper updated pdb&quot;)
end

disableTrigger&quot;Mudlet Mapper prompt trigger&quot;</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>return isPrompt()</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>4</integer>
                </regexCodePropertyList>
            </Trigger>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Wormhole</name>
                <script>mmp.customwalkdelay(4)</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>You hurl yourself forwards through the air, and sure enough a swirling vortex of colours springs into existence to swallow you.</string>
                    <string>You reach out with the vibrating stick to probe for a wormhole, and as it connects with one, you are sucked through.</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>3</integer>
                    <integer>3</integer>
                </regexCodePropertyList>
            </Trigger>
            <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Achaea</name>
                <script></script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList/>
                <regexCodePropertyList/>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Login</name>
                    <script>raiseEvent(&quot;mmp logged in&quot;, &quot;Achaea&quot;)
mmp.game = &quot;achaea&quot;
mmp.echo(&quot;We're connected to Achaea.&quot;)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Password correct. Welcome to Achaea.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Local area farsee</name>
                    <script>mmp.locateAndEchoSide(multimatches[2][3], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You see that </string>
                        <string>^You see that (\w+) is at (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Entering wilderness</name>
                    <script>mmp.customwalkdelay(6)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>99</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You begin to look for that place to enter the wilderness. It's around here somewhere!</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Icon enter/leave</name>
                    <script>mmp.customwalkdelay(10)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>1</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You reach out and touch a powerful Icon. For a moment, nothing happens, but soon you feel a humming deep inside you.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Underworld root</name>
                    <script>mmp.customwalkdelay(2)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>As you touch a huge grey root, you feel dark energies coursing up your hand and throughout your body.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Mindsense</name>
                    <script>mmp.locateAndEcho(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You seek out the mind of</string>
                        <string>^You seek out the mind of \w+ and an image of (.+) appears in your mind\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Destroyed room</name>
                    <script>mmp.customwalkdelay(3)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Your movement is slowed as you move through the decimated remains.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Underworld entry</name>
                    <script>mmp.customwalkdelay(3)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>A huge grey root numbs your fingertips as you reach out to touch it.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Angel sense</name>
                    <script>local t = mmp.getnums(multimatches[2][2], true)
if not t then return end
if #t == 1 then
	cecho(&quot; &lt;orange_red&gt;(&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;)&quot;)
else
	cecho(&quot; &lt;orange_red&gt;Maybe (&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;)&quot;)
end
echo &quot; &quot;; mmp.echonums(multimatches[2][2])

mmp.temp_room = multimatches[2][2]</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>100</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Your guardian angel senses </string>
                        <string>^Your guardian angel senses .+? at (.+?),</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Each person</name>
                        <script>mmp.pdb[matches[2]] = mmp.temp_room
mmp.pdb_lastupdate[matches[2]] = true</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string> is with (\w+)\.$</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Stop</name>
                        <script>setTriggerStayOpen(&quot;Angel sense&quot;, 0)
mmp.temp_room = nil
raiseEvent(&quot;mmapper updated pdb&quot;)</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>99</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>return isPrompt()</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>4</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Dragonsense</name>
                    <script>mmp.locateAndEchoSide(multimatches[2][3], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>1</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Tapping into the unfathomable depths of your power, you sense that</string>
                        <string>Tapping into the unfathomable depths of your power, you sense that (\w+) is at (.+?), in (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Defilement</name>
                    <script>mmp.locateAndEchoSide(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>(Order): </string>
                        <string>^\(Order\): \w+'s Herald says, &quot;A shrine is being defiled at (.+)!&quot;$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Defiled</name>
                    <script>mmp.locateAndEcho(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>(Order):</string>
                        <string>^\(Order\): \w+'s Herald says, &quot;A shrine has been destroyed at (.+)!&quot;$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>View </name>
                    <script>mmp.locateAndEcho(multimatches[2][3], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You see</string>
                        <string>^You see (\w+) at (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Elementalism scry</name>
                    <script>mmp.locateAndEcho(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You create a pool of water in the air in front of you, and look through it, sensing</string>
                        <string>You create a pool of water in the air in front of you, and look through it, sensing \w+ at (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="no" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Parse wholist</name>
                    <script>-- this trigger should be off by default. It's inefficient and gets auto-enabled
-- when you check 'who'
mmp.locateAndEcho(matches[3], matches[2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>99</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>^(\w+) +\((.+)\)$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Piety on astralform</name>
                    <script>mmp.customwalkdelay(3)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>A rite of piety slows your movement as it pulls at your ephemeral body.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Angel presences</name>
                    <script>disableTrigger(&quot;Angel sense&quot;)

mmp.pdb_lastupdate = {}</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>100</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You bid your guardian angel to seek out life presences nearby.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Each person</name>
                        <script>mmp.locateAndEchoSide(matches[3], matches[2])</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^Your guardian angel senses (\w+) at (.+?),</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Stop (angel presences</name>
                        <script>setTriggerStayOpen(&quot;Angel presences&quot;, 0)
enableTrigger(&quot;Angel sense&quot;)</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>return isPrompt()</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>4</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Annwyn circle</name>
                    <script>mmp.customwalkdelay(12)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>The melody of a strange song rises unbidden to your lips as you skip around the circle of mushrooms.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Scrying bowl</name>
                    <script>mmp.locateAndEcho(multimatches[3][2], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>1</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You dip your fingers into the cool water of the bowl, willing it to reveal the location of</string>
                        <string>^You dip your fingers into the cool water of the bowl, willing it to reveal the location of (\w+)\.$</string>
                        <string>^An image of .+? appears reflected within the bowl, shifting with the rippling water to display (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Occultist entities</name>
                    <script></script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>1000</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>The following entities reside on the Prime Material plane:</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Each doppleganger</name>
                        <script>mmp.locateAndEcho(matches[3], matches[2])</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^(\w+) is at (.+)\.$</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Stop</name>
                        <script>setTriggerStayOpen(&quot;Occultist entities&quot;, 0)</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>return isPrompt()</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>4</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Party traces/locaters</name>
                    <script></script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>(Party):</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>regex (party locate)</name>
                        <script>mmp.locateAndEcho(matches[3], matches[2])</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^\(Party\): \w+ says, &quot;(\w+) moved to (.+)\.&quot;$</string>
                            <string>^\(Party\): \w+ says, &quot;(\w+) is at (.+), in .+\.&quot;</string>
                            <string>^\(Party\): \w+ says, &quot;Trace: (\w+) moved to (.+)\.&quot;</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                            <integer>1</integer>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Arena event (Achaea)</name>
                    <script>mmp.pdb_lastupdate = {}</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>3</conditonLineDelta>
                    <mStayOpen>1000</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Current event</string>
                        <string>Player               Location</string>
                        <string>----------------------------------------------------------------------</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>3</integer>
                        <integer>3</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Each person</name>
                        <script>echo((&quot; &quot;):rep(60-#line))
echo&quot;(&quot; mmp.echonums(matches[3]) echo&quot;)&quot;

mmp.pdb[matches[2]] = matches[3]
mmp.pdb_lastupdate[matches[2]] = true</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^(\w+) +(.+)$</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Stop (arena event)</name>
                        <script>setTriggerStayOpen(&quot;Arena event (Achaea)&quot;, 0)

raiseEvent(&quot;mmapper updated pdb&quot;)</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>return isPrompt()</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>4</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Angel trace</name>
                    <script>selectCurrentLine() replace(&quot;&quot;)
cecho(&quot;&lt;grey&gt;Angel trace: &lt;a_darkcyan&gt;&quot;..multimatches[2][2]..&quot;&lt;grey&gt; moved to &lt;a_darkcyan&gt;&quot; .. multimatches[2][3])
mmp.locateAndEchoInternal(multimatches[2][3], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Your guardian angel reports that</string>
                        <string>^Your guardian angel reports that (\w+) has moved to (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="no" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>KoTH (mudlet mapper)</name>
                    <script>mmp.pdb_lastupdate = {}</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>5</conditonLineDelta>
                    <mStayOpen>1000</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Current event: King of the Hill</string>
                        <string>5</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                        <integer>5</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Each person</name>
                        <script>echo((&quot; &quot;):rep(60-#line))
echo&quot;(&quot; mmp.echonums(matches[3]) echo&quot;)&quot;

mmp.pdb[matches[2]] = matches[3]
mmp.pdb_lastupdate[matches[2]] = true</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^(\w+) .+? ([A-Z][a-z ]+?)$</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Stop (koth)</name>
                        <script>setTriggerStayOpen(&quot;KoTH (mudlet mapper)&quot;, 0)

raiseEvent(&quot;mmapper updated pdb&quot;)</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>return isPrompt()</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>4</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Fullsense (mudlet mapper)</name>
                    <script>mmp.pdb_lastupdate = {}</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>100</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You seek out all mental presences within your reach:</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Each person</name>
                        <script>echo((&quot; &quot;):rep(60-#line))
echo&quot;(&quot; mmp.echonums(matches[3]) echo&quot;)&quot;

mmp.pdb[matches[2]] = matches[3]
mmp.pdb_lastupdate[matches[2]] = true</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^You sense (\w+) at (.+)\.$</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Stop</name>
                        <script>setTriggerStayOpen(&quot;Fullsense (mudlet mapper)&quot;, 0)

raiseEvent(&quot;mmapper updated pdb&quot;)</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>return isPrompt()</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>4</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
            </TriggerGroup>
            <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Aetolia</name>
                <script></script>
                <triggerType>0</triggerType>
                <conditonLineDelta>1</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList/>
                <regexCodePropertyList/>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Login</name>
                    <script>raiseEvent(&quot;mmp logged in&quot;, &quot;Aetolia&quot;)
mmp.game = &quot;aetolia&quot;</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>99</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Password correct. Welcome to Aetolia.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
            </TriggerGroup>
            <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Lusternia</name>
                <script></script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList/>
                <regexCodePropertyList/>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Login</name>
                    <script>raiseEvent(&quot;mmp logged in&quot;, &quot;Lusternia&quot;)
mmp.game = &quot;lusternia&quot;</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>5</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>     .____                      __                           .__</string>
                        <string>     |    |     __ __   _______/  |_   ____  _______   ____  |__|_____</string>
                        <string>     |    |    |  |  \ /  ___/\   __\_/ __ \ \_  __ \ /    \ |  |\__  \</string>
                        <string>     |    |___ |  |  / \___ \  |  |  \  ___/  |  | \/|   |  \|  | / __ \_</string>
                        <string>     |_______ \|____/ /____  &gt; |__|   \___  &gt; |__|   |___|  /|__|(____  /</string>
                        <string>             \/            \/             \/              \/          \/</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                        <integer>3</integer>
                        <integer>3</integer>
                        <integer>3</integer>
                        <integer>3</integer>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>mmp Lusternia Scent</name>
                    <script>mmp.tempscent = {}
mmp.pdb_lastupdate = {}
</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>99</conditonLineDelta>
                    <mStayOpen>100</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You scent at the air, your skilled nose picking up the faint traces of others in the surrounding area.</string>
                        <string>You snort and snuffle at the air, sensing through a ridiculous pig nose upon your face the faint traces of others in the surrounding area.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                        <integer>3</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Got line</name>
                        <script>--deleteLine()

selectString(line, 1) replace&quot;&quot;

-- get the name
cecho(&quot;&lt;green&gt;&quot;..matches[2]..&quot;&lt;reset&gt;: &quot;)

-- ids
mmp.echonums(matches[3])

-- pad spaces so we have aligned roomname
echo(string.rep(&quot; &quot;, 25 - #getCurrentLine()))

-- and finally, the roomname
echo(matches[3])


if mmp.tempscent[matches[3]] then
	mmp.tempscent[matches[3]][#mmp.tempscent[matches[3]]+1] = matches[2]
else
	mmp.tempscent[matches[3]] = {matches[2]}
end

-- save in our person tracking db
mmp.pdb[matches[2]] = matches[3]
mmp.pdb_lastupdate[matches[2]] = true</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^You make out the scent of (\w+) coming from (.+)\.$</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Stop capturing</name>
                        <script>setTriggerStayOpen(&quot;mmp Lusternia Scent&quot;, 0)

--[[for area, names in pairs(mmp.tempscent) do
	for _, name in ipairs(names) do

-- get the name
cecho(&quot;\n&lt;green&gt;&quot;..name..&quot;&lt;reset&gt;: &quot;)

-- ids
mmp.echonums(area)

-- pad spaces so we have aligned roomname
echo(string.rep(&quot; &quot;, 25))

-- and finally, the roomname
echo(area)
end
end]]


raiseEvent(&quot;mmapper updated pdb&quot;)</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>return isPrompt()</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>4</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Deathsight</name>
                    <script>mmp.locateAndEcho(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You see the death occur at</string>
                        <string>^You see the death occur at (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Wildnodes nodes</name>
                    <script>mmp.locateAndEcho(matches[2]:sub(1,1):lower()..string.sub(matches[2], 2))</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>99</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>^\(Planted\) Node \d+ - (.*)\.$</string>
                        <string>^ +Node \d+ - (.*)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Window search</name>
                    <script>mmp.locateAndEcho(matches[4], matches[2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>39</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>^You open up a window in the cosmic fabric and search out (\w+). Through the cosmic window, you see (\w+) at (.+?)(?: \(.*\))?\.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Scry search</name>
                    <script>mmp.locateAndEcho(multimatches[2][3], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>1</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>^You rub .* and it begins to glow with a pulsating light\.$</string>
                        <string>Within the enchanted item, an image forms of (\w+) at (.+?)(?: \(.*\))?\.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Map artefact</name>
                    <script>mmp.gotoRoom(multimatches[4][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>3</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>As you inscribe the name of </string>
                        <string>^As you inscribe the name of \w+ with a flourish, lines crawl across the surface of the map, centered upon (.*)\.$</string>
                        <string>You see the following in detail:</string>
                        <string>v(\d+)</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                        <integer>3</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>map scry</name>
                    <script>mmp.locateAndEcho(multimatches[2][3], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>As you inscribe the name of</string>
                        <string>^As you inscribe the name of (\w+) with a flourish, lines crawl across the surface of the map, centered upon (.*)\.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>World events</name>
                    <script>mmp.locateAndEcho(matches[1])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>^The Staff of Ascension is at (.*)\.$</string>
                        <string>^The Purple Hamster of Chaos is at (.*)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Seeing stone</name>
                    <script>mmp.locateAndEcho(multimatches[3][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>3</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You gaze into a seeing stone.</string>
                        <string>1</string>
                        <string>^(.*)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                        <integer>5</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Birdseye</name>
                    <script>mmp.locateAndEcho(multimatches[2][3], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>From your vantage point in the sky, your crow senses perceive that</string>
                        <string>^From your vantage point in the sky, your crow senses perceive that (\w+) is (.*) within the vicinity of (.*)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Bond look</name>
                    <script>mmp.locateAndEcho(multimatches[3][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>3</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>^You look through the mind of (.*)\:$</string>
                        <string>1</string>
                        <string>^(.*)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                        <integer>5</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Pyramid probe #</name>
                    <script>local t = mmp.getnums(multimatches[2][2])
if not t then return end

echo&quot;\n&quot;

if #t == 1 then
	cecho(&quot;&lt;red&gt;From your knowledge, that room is in &lt;orange_red&gt;&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;&lt;red&gt;.&quot;)
else
	cecho(&quot;&lt;red&gt;From your knowledge, that room might be in &lt;orange_red&gt;&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;&lt;red&gt;.&quot;)
end</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You lightly caress a button on a paradox puzzle pyramid and suddenly a hazy image of</string>
                        <string>^You lightly caress a button on a paradox puzzle pyramid and suddenly a hazy image of (.*) flashes momentarily in front of you\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Pentagon probe #</name>
                    <script>local t = mmp.getnums(multimatches[2][2])
if not t then return end

echo&quot;\n&quot;

if #t == 1 then
	cecho(&quot;&lt;red&gt;From your knowledge, that room is in &lt;orange_red&gt;&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;&lt;red&gt;.&quot;)
else
	cecho(&quot;&lt;red&gt;From your knowledge, that room might be in &lt;orange_red&gt;&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;&lt;red&gt;.&quot;)
end</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You lightly caress a button on a paradox puzzle pentagon and suddenly a hazy image of</string>
                        <string>^You lightly caress a button on a paradox puzzle pentagon and suddenly a hazy image of (.+) \(room \#\d+\) flashes momentarily in front of you\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Pyramid port</name>
                    <script>local t = mmp.getnums(multimatches[2][2])
if not t then return end

echo&quot;\n&quot;

if #t == 1 then
	cecho(&quot;&lt;red&gt;Porting to &lt;orange_red&gt;&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;&lt;red&gt;.&quot;)
else
	cecho(&quot;&lt;red&gt;Might be porting to &lt;orange_red&gt;&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;&lt;red&gt;.&quot;)
end	</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Your hands become a blur as you twist and turn a paradox puzzle pyramid until each side is made up of the same colour, solving the puzzle in mere moments. Suddenly the image of</string>
                        <string>^Your hands become a blur as you twist and turn a paradox puzzle pyramid until each side is made up of the same colour, solving the puzzle in mere moments. Suddenly the image of (.*) appears in the back of your mind and you feel drawn towards it\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Pyramid probe</name>
                    <script></script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>99</conditonLineDelta>
                    <mStayOpen>4</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You lightly caress a few buttons on a paradox puzzle pyramid and suddenly a series of hazy images flashes momentarily in front of you.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Each location</name>
                        <script>local t = mmp.getnums(matches[2])
if not t then return end

if #t == 1 then
	cecho(&quot;&lt;red&gt; (in &lt;orange_red&gt;&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;&lt;red&gt;)&quot;)
else
	cecho(&quot;&lt;red&gt; (might be in &lt;orange_red&gt;&quot;..mmp.areatabler[getRoomArea(t[1])]..&quot;&lt;red&gt;)&quot;)
end</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^Puzzle point \d+ is set to (.+) \(</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Astrology scry</name>
                    <script>mmp.locateAndEcho(multimatches[2][3], multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Gazing up at the sky, you bring the image of</string>
                        <string>^Gazing up at the sky, you bring the image of (\w+) into your mind's eye and overlay it on the constellations\. The power of the stars manifests as an image of (.+?) forms before your eyes\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Tierstone</name>
                    <script>mmp.locateAndEcho(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>1</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You gaze into a glittering tierstone.</string>
                        <string>^\w+ is at (.+?) in (.*)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Quicksand</name>
                    <script>mmp.customwalkdelay(4)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You struggle slowly through the quicksand as you move</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Gravity</name>
                    <script>mmp.customwalkdelay(4)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>The dragging force of a war shrine of</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Crow spy</name>
                    <script>mmp.locateAndEcho(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>An image of</string>
                        <string>^An image of \w+ (?:entering|leaving) (.+?) appears in the centre of the nest\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Crow spy remote</name>
                    <script>mmp.locateAndEcho(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Your nest projects into your head an image</string>
                        <string>^Your nest projects into your head an image of \w+ (?:entering|exiting) (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
            </TriggerGroup>
            <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Imperian</name>
                <script></script>
                <triggerType>0</triggerType>
                <conditonLineDelta>99</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList/>
                <regexCodePropertyList/>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Login</name>
                    <script>raiseEvent(&quot;mmp logged in&quot;, &quot;Imperian&quot;)
mmp.game = &quot;imperian&quot;</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Password correct. Welcome to Imperian.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Wormholes</name>
                    <script>local room1 = mmp.roomEcho(multimatches[2][2])
local room2 = mmp.roomEcho(multimatches[2][3])
selectCurrentLine()
replace(&quot;&quot;)
mmp.echon(&quot;Stable wormhole between &quot; .. room1)
mmp.roomEcho(room1)
echo(&quot; and &quot; .. room2)
mmp.roomEcho(room2)
echo(&quot;.\n&quot;)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You sense a stable wormhole between</string>
                        <string>^You sense a stable wormhole between (.+?) and (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Personal wormholes</name>
                    <script>selectCurrentLine()
replace(&quot;&quot;)
mmp.echon(&quot;Personal wormhole at &quot; .. multimatches[2][2])
mmp.roomEcho(multimatches[2][2])
echo(&quot;. It is attached to &quot; .. multimatches[2][3] .. &quot;.\n&quot;)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You sense a personal wormhole at</string>
                        <string>^You sense a personal wormhole at (.+). It is attached to (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="no" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Parse wholist</name>
                    <script>selectCaptureGroup(2)
replace(&quot;&quot;)
mmp.roomEcho(matches[3])
 </script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>.+( \- [A-Z].+?\s*?) \- (.+)</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Trap went off</name>
                    <script>selectCurrentLine()
replace(&quot;&quot;)
mmp.echon(&quot;Your trap at &quot; .. multimatches[2][2])
mmp.roomEcho(multimatches[2][2])
echo(&quot; was set off by &quot; .. multimatches[2][3] .. &quot;!!!\n&quot;)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Your alarm at</string>
                        <string>^Your alarm at \'(.+)\' has been set off by (\w+)\!$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Trap List</name>
                    <script>-- the first pattern is not blank, there are spaces there

selectCurrentLine()
replace(&quot;&quot;)
echo(&quot;[&quot; .. multimatches[2][2] .. &quot;] (&quot; .. multimatches[2][3] .. &quot;) at &quot; .. multimatches[2][4])
mmp.roomEcho(multimatches[2][4]) </script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>   </string>
                        <string>^   (\w+) \((\w+)\) at (.+)$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="no" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Scout</name>
                    <script>-- bad, overzealous trigger - the pattern needs to be improved
mmp.roomEcho(multimatches[2][2]) </script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>   </string>
                        <string>^   .+ at (.+)$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Hunt</name>
                    <script>selectCurrentLine()
replace(&quot;&quot;)
cecho(&quot;&lt;chocolate&gt;&quot; .. matches[2] .. &quot;&lt;grey&gt; moved to &lt;sienna&gt;&quot; .. matches[3] .. &quot;, &lt;white&gt;&quot; ..matches[4])
mmp.roomEcho(matches[3]) </script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>^You sense that (\w+) has entered (.+)\, (.+)\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Sewer grate</name>
                    <script>mmp.enterGrate()</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>A sewer grate prevents you from moving down into the sewers.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Caravan</name>
                    <script>mmp.customwalkdelay(15)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You begin leading a caravan</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                    </regexCodePropertyList>
                </Trigger>
            </TriggerGroup>
            <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Midkemia Online</name>
                <script></script>
                <triggerType>0</triggerType>
                <conditonLineDelta>99</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList/>
                <regexCodePropertyList/>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Login</name>
                    <script>raiseEvent(&quot;mmp logged in&quot;, &quot;Midkemia Online&quot;)
mmp.game = &quot;mko&quot;</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Password correct. Welcome to Midkemia Online.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Fording</name>
                    <script>mmp.customwalkdelay(3)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You ford the water towards the </string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                    </regexCodePropertyList>
                </Trigger>
            </TriggerGroup>
            <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Lithmeria</name>
                <script></script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList/>
                <regexCodePropertyList/>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Login</name>
                    <script>raiseEvent(&quot;mmp logged in&quot;, &quot;Lithmeria&quot;)
mmp.game = &quot;lithmeria&quot;
mmp.echo(&quot;We're connected to Lithmeria.&quot;)</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>Welcome to your account!</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
            </TriggerGroup>
            <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Wall</name>
                <script>mmp.failpath()</script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList>
                    <string>A wall blocks your way.</string>
                </regexCodeList>
                <regexCodePropertyList>
                    <integer>3</integer>
                </regexCodePropertyList>
            </Trigger>
            <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Doors</name>
                <script></script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList/>
                <regexCodePropertyList/>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Closing doors</name>
                    <script></script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>1</conditonLineDelta>
                    <mStayOpen>1</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You open the door to the</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                    </regexCodePropertyList>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Lack of piety</name>
                        <script>mmp.failpath()</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^You try to open the door to the (\w+) but find it slams closed in your face, symbolic of your lack of piety\.$</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Slam Shut</name>
                        <script>mmp.failpath()</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>1</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>The door slams shut!</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>3</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Denied entry</name>
                        <script>mmp.failpath()</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>The door suddenly slams shut, denying you entry.</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>3</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>CIJ</name>
                        <script>mmp.failpath()</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>A section of the door slides aside, and a rubber-gloved fist on a spring pops out and punches you in the nose!</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>3</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Springs back</name>
                        <script>mmp.failpath()</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>The door budges, and then springs immediately back into place.</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>3</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Bolted</name>
                        <script>mmp.failpath()</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>^The door to the (\w+) is closed forcefully fromthe other side and the sound of a bolt being slammed home makes your lack of admittance clear\.$</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>1</integer>
                        </regexCodePropertyList>
                    </Trigger>
                    <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                        <name>Mhaldor council room</name>
                        <script>mmp.failpath()</script>
                        <triggerType>0</triggerType>
                        <conditonLineDelta>0</conditonLineDelta>
                        <mStayOpen>0</mStayOpen>
                        <mCommand></mCommand>
                        <packageName></packageName>
                        <mFgColor>#ff0000</mFgColor>
                        <mBgColor>#ffff00</mBgColor>
                        <mSoundFile></mSoundFile>
                        <colorTriggerFgColor>#000000</colorTriggerFgColor>
                        <colorTriggerBgColor>#000000</colorTriggerBgColor>
                        <regexCodeList>
                            <string>The door closes swiftly with a loud 'BANG'!</string>
                        </regexCodeList>
                        <regexCodePropertyList>
                            <integer>3</integer>
                        </regexCodePropertyList>
                    </Trigger>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Door closed</name>
                    <script>mmp.failpath()</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>2</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You open the door to the</string>
                        <string>return isPrompt()</string>
                        <string>^The door to the \w+ closes with a click\.$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>4</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Failed to open Door</name>
                    <script>mmp.failpath()</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You are not carrying a key for this door.</string>
                        <string>This door has been magically locked shut.</string>
                        <string>Not recognising you as cast or crew, stagehands firmly close the door on you.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                        <integer>3</integer>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Door Locked</name>
                    <script>mmp.unlockDoor()</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>The door is locked.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Door in the way</name>
                    <script>mmp.openDoor()</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>There is a door in the way, to the</string>
                        <string>There is a door in the way.</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>3</integer>
                    </regexCodePropertyList>
                </Trigger>
            </TriggerGroup>
            <TriggerGroup isActive="yes" isFolder="yes" isTempTrigger="no" isMultiline="no" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                <name>Wormholes</name>
                <script></script>
                <triggerType>0</triggerType>
                <conditonLineDelta>0</conditonLineDelta>
                <mStayOpen>0</mStayOpen>
                <mCommand></mCommand>
                <packageName></packageName>
                <mFgColor>#ff0000</mFgColor>
                <mBgColor>#ffff00</mBgColor>
                <mSoundFile></mSoundFile>
                <colorTriggerFgColor>#000000</colorTriggerFgColor>
                <colorTriggerBgColor>#000000</colorTriggerBgColor>
                <regexCodeList/>
                <regexCodePropertyList/>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Worm Sources</name>
                    <script>deleteLine()
local from = multimatches[2][2]
local to = multimatches[2][3]

cecho(&quot;\nYou see connections between &quot;..from..&quot; (&quot;)
mmp.echonums(from)
cecho(&quot;) and &quot;..to..&quot; (&quot;)
mmp.echonums(to)
cecho(&quot;)&quot;)
</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You sense a connection between</string>
                        <string>^You sense a connection between (.*) and (.*).$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
                <Trigger isActive="yes" isFolder="no" isTempTrigger="no" isMultiline="yes" isPerlSlashGOption="no" isColorizerTrigger="no" isFilterTrigger="no" isSoundTrigger="no" isColorTrigger="no" isColorTriggerFg="no" isColorTriggerBg="no">
                    <name>Worm seek</name>
                    <script>mmp.locateAndEcho(multimatches[2][2])</script>
                    <triggerType>0</triggerType>
                    <conditonLineDelta>0</conditonLineDelta>
                    <mStayOpen>0</mStayOpen>
                    <mCommand></mCommand>
                    <packageName></packageName>
                    <mFgColor>#ff0000</mFgColor>
                    <mBgColor>#ffff00</mBgColor>
                    <mSoundFile></mSoundFile>
                    <colorTriggerFgColor>#000000</colorTriggerFgColor>
                    <colorTriggerBgColor>#000000</colorTriggerBgColor>
                    <regexCodeList>
                        <string>You sense a wormhole leading to</string>
                        <string>^You sense a wormhole leading to (.*).$</string>
                    </regexCodeList>
                    <regexCodePropertyList>
                        <integer>2</integer>
                        <integer>1</integer>
                    </regexCodePropertyList>
                </Trigger>
            </TriggerGroup>
        </TriggerGroup>
    </TriggerPackage>
    <TimerPackage>
        <TimerGroup isActive="yes" isFolder="yes" isTempTimer="no" isOffsetTimer="no">
            <name>Mudlet Mapper</name>
            <script></script>
            <command></command>
            <packageName></packageName>
            <time>00:00:00.000</time>
            <Timer isActive="yes" isFolder="no" isTempTimer="no" isOffsetTimer="no">
                <name>Check for updates periodically</name>
                <script>mmp.checkforupdate()</script>
                <command></command>
                <packageName></packageName>
                <time>01:00:00.000</time>
            </Timer>
        </TimerGroup>
    </TimerPackage>
    <AliasPackage>
        <AliasGroup isActive="yes" isFolder="yes">
            <name>Mudlet Mapper</name>
            <script>mudlet = mudlet or {}; mudlet.mapper_script = true</script>
            <command></command>
            <packageName></packageName>
            <regex></regex>
            <Alias isActive="yes" isFolder="no">
                <name>Go to ID or area</name>
                <script>local where = matches[2]
local gallop
if command:ends(&quot;gallop&quot;) then
  gallop = &quot;gallop&quot;
  where = where:sub(1, -8)
elseif command:ends(&quot;sprint&quot;) then
  gallop = &quot;sprint&quot;
  where = where:sub(1, -8)
elseif command:ends(&quot;dash&quot;) then
  gallop = &quot;dash&quot;
  where = where:sub(1, -6)
elseif command:ends(&quot;runaway&quot;) then
  gallop = &quot;runaway&quot;
  where = where:sub(1, -9)
elseif command:ends(&quot;glide&quot;) then
  gallop = &quot;glide&quot;
  where = where:sub(1, -7)
end

-- goto room ID
if tonumber(where) then
	mmp.gotoRoom(where, gallop)
else
	-- goto area
    local split = where:split(&quot; &quot;)
    if tonumber(split[#split]) then
        mmp.gotoArea(where:sub(1, -#(split[#split])-2), tonumber(split[#split]), gallop)
    else
        mmp.gotoArea(where, nil, gallop)
    end
end</script>
                <command></command>
                <packageName></packageName>
                <regex>^goto (.+)$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>View roomID or area</name>
                <script>local where = matches[2]

if not where then
	centerview(mmp.currentroom)
elseif tonumber(where) then -- view a room ID
	centerview(where)
else -- view an area
	mmp.viewArea (where)
end</script>
                <command></command>
                <packageName></packageName>
                <regex>^mmap ?(.+)?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Toggle pause</name>
                <script>mmp.pause(matches[2])</script>
                <command></command>
                <packageName></packageName>
                <regex>^mpp(?:\s?(on|off))?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Stop walking</name>
                <script>mmp.stop()</script>
                <command></command>
                <packageName></packageName>
                <regex>^mstop$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Option</name>
                <script>if not matches[2] then
	mmp.settings:showAllOptions()
	return
end

local val = matches[4]
if val == &quot;true&quot; or val == &quot;yes&quot; or val == &quot;on&quot; then val = true end
if val == &quot;false&quot; or val == &quot;no&quot; or val == &quot;off&quot; then val = false end

mmp.settings:setOption(matches[3], val)</script>
                <command></command>
                <packageName></packageName>
                <regex>^mconfig( (\w+) (.*))?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Display area for lock/unlock</name>
                <script>mmp.doLockArea(matches[2])</script>
                <command></command>
                <packageName></packageName>
                <regex>^arealock(?: (.*))?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Add a room label</name>
                <script>mmp.roomLabel(matches[2])</script>
                <command></command>
                <packageName></packageName>
                <regex>^room label (.+)$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>View/delete area labels</name>
                <script>mmp.areaLabels(matches[2])</script>
                <command></command>
                <packageName></packageName>
                <regex>^area labels ?(.+)?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Room find</name>
                <script>mmp.roomFind(matches[2])</script>
                <command></command>
                <packageName></packageName>
                <regex>^(?:rf|room find) (.+)$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Room look</name>
                <script>mmp.roomLook(matches[2])</script>
                <command></command>
                <packageName></packageName>
                <regex>^(?:rl|room look)(?: (.+))?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Room list</name>
                <script>mmp.echoRoomList(matches[2] or mmp.areatabler[getRoomArea(mmp.currentroom)])</script>
                <command></command>
                <packageName></packageName>
                <regex>^room list(?: (.+))?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Area list</name>
                <script>mmp.echoAreaList()</script>
                <command></command>
                <packageName></packageName>
                <regex>^area list$</regex>
            </Alias>
            <AliasGroup isActive="yes" isFolder="yes">
                <name>mm Mapping</name>
                <script></script>
                <command></command>
                <packageName></packageName>
                <regex></regex>
                <Alias isActive="yes" isFolder="no">
                    <name>Manually set the room coordinates</name>
                    <script>-- want the current room, but we're lost
if matches[2] == '' and (not mmp.currentroom or not mmp.roomexists(mmp.currentroom)) then mmp.echo(&quot;Don't know where we are at the moment.&quot;) return end

-- want another room, but it doesn't actually exist
if matches[2] ~= '' and not mmp.roomexists(matches[2]) then mmp.echo(&quot;v&quot;..matches[2]..&quot; doesn't exist.&quot;) return end

local m = matches[3]
local rid, rname = (matches[2] ~= &quot;&quot; and matches[2] or mmp.currentroom),
  (matches[2] ~= &quot;&quot; and getRoomName(matches[2]) or mmp.currentroomname)
local x,y,z

local function set() -- small func to set things
  setRoomCoordinates(rid, x, y, z)
  mmp.echo(string.format(&quot;%s (%d) is now at %dx, %dy, %dz.\n&quot;, rname, rid, x,y,z))
  centerview(rid)
end

-- let's be flexible and allow several ways if giving an arg
-- rc x y z
x,y,z = string.match(m, &quot;(%-?%d+) (%-?%d+) (%-?%d+)&quot;)
if x then
  set(); return
end

-- rc xx? yy? zz?
x,y,z = string.match(m, &quot;(%-?%d+)x&quot;), string.match(m, &quot;(%-?%d+)y&quot;), string.match(m, &quot;(%-?%d+)z&quot;)
if x or y or z then
  -- merge w/ old coords if any are missing
  local ox, oy, oz = getRoomCoordinates(rid)
  x = x or ox; y = y or oy; z = z or oz
  set(); return
end

-- rc left/west, right/east, ...
local ox, oy, oz = getRoomCoordinates(rid)
local has = table.contains
for w in string.gmatch(m, &quot;%a+&quot;) do
  if has({&quot;west&quot;, &quot;left&quot;, &quot;w&quot;, &quot;l&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy); z = (z or oz)
  elseif has({&quot;east&quot;, &quot;right&quot;, &quot;e&quot;, &quot;r&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy); z = (z or oz)
  elseif has({&quot;north&quot;, &quot;top&quot;, &quot;n&quot;, &quot;t&quot;}, w) then
    x = (x or ox); y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;south&quot;, &quot;bottom&quot;, &quot;s&quot;, &quot;b&quot;}, w) then
    x = (x or ox); y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;northwest&quot;, &quot;topleft&quot;, &quot;nw&quot;, &quot;tl&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;northeast&quot;, &quot;topright&quot;, &quot;ne&quot;, &quot;tr&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;southeast&quot;, &quot;bottomright&quot;, &quot;se&quot;, &quot;br&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;southwest&quot;, &quot;bottomleft&quot;, &quot;sw&quot;, &quot;bl&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;up&quot;, &quot;u&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) + 1
  elseif has({&quot;down&quot;, &quot;d&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) - 1
  end

end
if x then set(); return end

mmp.echo([[Where do you want to move the room to?
  You can use direct coordinates or relative directions.]])</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^(?:rc|room coords) (?:v(\d+) )?(.+)$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Add a special exit</name>
                    <script>-- spe clear and spe list match on this
if matches[2] == &quot;clear&quot; or matches[2] == &quot;list&quot; then return end

-- need the current room, but we're lost
if not mmp.currentroom or not mmp.roomexists(mmp.currentroom) then mmp.echo(&quot;Don't know where we are at the moment.&quot;) return end

local otherroom = tonumber(matches[2]) or mmp.relativeroom(mmp.currentroom, matches[2])

-- need the another room, but it doesn't actually exist
if not otherroom or not mmp.roomexists(otherroom) then mmp.echo(matches[2]..&quot; doesn't exist.&quot;) return end

addSpecialExit(mmp.currentroom, tonumber(otherroom), matches[3])
addSpecialExit(mmp.currentroom, tonumber(otherroom), matches[3])
mmp.echo(string.format(&quot;Added special exit with command '%s' to %s (%d).&quot;, matches[3], getRoomName(otherroom), otherroom))
centerview(mmp.currentroom)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^(?:spe|exit special) (\w+) (.+)$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>List special exits</name>
                    <script>mmp.listSpecialExits(matches[2])</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^spe list(?: (.+))?$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Clear all special exits</name>
                    <script>-- want the current room, but we're lost
if not matches[2] and (not mmp.currentroom or not mmp.roomexists(mmp.currentroom)) then mmp.echo(&quot;Don't know where we are at the moment.&quot;) return end

-- want another room, but it doesn't exist
if matches[2] and tonumber(matches[2]) and not mmp.roomexists(matches[2]) then mmp.echo(&quot;v&quot;..matches[2]..&quot; doesn't exist.&quot;) return end

-- or a relative one
if matches[2] and not tonumber(matches[2]) and not mmp.relativeroom(mmp.currentroom, matches[2]) then mmp.echo(&quot;There is no room &quot;..matches[2].. &quot; of us.&quot;) return end

local rid = (not matches[2] and mmp.currentroom or (tonumber(matches[2]) or mmp.relativeroom(mmp.currentroom, matches[2])))

clearSpecialExits(rid)
mmp.echo(string.format(&quot;Cleared all special exits in %s (%d).\n&quot;, getRoomName(rid), rid))</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^(?:spe clear|exit special clear) ?(\w+)?$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Create a room</name>
                    <script>local m = matches[2]
local rid, rname
if mmp.roomexists(mmp.currentroom) then
  rid, rname = mmp.currentroom, mmp.currentroomname
end
local x,y,z

local function set(newid) -- small func to set things
  local rid = newid or createRoomID()
  addRoom(rid)
  setRoomCoordinates(rid, x, y, z)
  if mmp.roomexists(mmp.currentroom) then setRoomArea(rid, getRoomArea(mmp.currentroom)) end
  if mmp.roomexists(mmp.currentroom) then setRoomEnv(rid, getRoomEnv(mmp.currentroom)) end
  setExit(mmp.currentroom, rid, m)
  mmp.echo(string.format(&quot;Created new room (%d) at %dx, %dy, %dz.\n&quot;, rid, x,y,z))
  centerview(mmp.roomexists(mmp.currentroom) and mmp.currentroom or rid)
  if not mmp.roomexists(mmp.currentroom) then mmp.currentroom = rid; mmp.currentroomname = &quot;&quot; end
end

-- let's be flexible and allow several ways if giving an arg
-- rc v# x y z
newid, x,y,z = string.match(m, &quot;v(%d+) (%-?%d+) (%-?%d+) (%-?%d+)&quot;)
if x then
  set(newid); return
end

-- rc x y z
x,y,z = string.match(m, &quot;(%-?%d+) (%-?%d+) (%-?%d+)&quot;)
if x then
  set(); return
end


if not rid then
  mmp.echo(&quot;Don't know where we are at the moment in order to use relative coordinates.&quot;)
  return
end

-- rc xx? yy? zz?
x,y,z = string.match(m, &quot;(%-?%d+)x&quot;), string.match(m, &quot;(%-?%d+)y&quot;), string.match(m, &quot;(%-?%d+)z&quot;)
if x or y or z then
  -- merge w/ old coords if any are missing
  local ox, oy, oz = getRoomCoordinates(rid)
  x = x or ox; y = y or oy; z = z or oz
  set(); return
end

-- rc left/west, right/east, ...
local ox, oy, oz = getRoomCoordinates(rid)
local has = table.contains
for w in string.gmatch(m, &quot;%a+&quot;) do
  if has({&quot;west&quot;, &quot;left&quot;, &quot;w&quot;, &quot;l&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy); z = (z or oz)
  elseif has({&quot;east&quot;, &quot;right&quot;, &quot;e&quot;, &quot;r&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy); z = (z or oz)
  elseif has({&quot;north&quot;, &quot;top&quot;, &quot;n&quot;, &quot;t&quot;}, w) then
    x = (x or ox); y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;south&quot;, &quot;bottom&quot;, &quot;s&quot;, &quot;b&quot;}, w) then
    x = (x or ox); y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;northwest&quot;, &quot;topleft&quot;, &quot;nw&quot;, &quot;tl&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;northeast&quot;, &quot;topright&quot;, &quot;ne&quot;, &quot;tr&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;southeast&quot;, &quot;bottomright&quot;, &quot;se&quot;, &quot;br&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;southwest&quot;, &quot;bottomleft&quot;, &quot;sw&quot;, &quot;bl&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;up&quot;, &quot;u&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) + 1
  elseif has({&quot;down&quot;, &quot;d&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) - 1
  end

end
if x then set(); return end

mmp.echo([[Where do you want to move the room to?
  You can use direct coordinates or relative directions.]])</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^(?:rlc|room create) (.+)?$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Create a link between two rooms</name>
                    <script>-- need the current room, but we're lost
if not mmp.currentroom or not mmp.roomexists(mmp.currentroom) then mmp.echo(&quot;Don't know where we are at the moment.&quot;) return end

-- make sure the dir is valid
local dir = mmp.anytolong(matches[3])
if not dir then mmp.echo(matches[3]..&quot; isn't a valid normal exit.&quot;) return end

-- if we don't give a room number, then we want to auto-locate an appropriate room nearby.
local otherroom
if matches[2] == &quot;&quot; then
  local w = matches[3]
  local ox, oy, oz, x,y,z = getRoomCoordinates(mmp.currentroom)
  local has = table.contains
  if has({&quot;west&quot;, &quot;left&quot;, &quot;w&quot;, &quot;l&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy); z = (z or oz)
  elseif has({&quot;east&quot;, &quot;right&quot;, &quot;e&quot;, &quot;r&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy); z = (z or oz)
  elseif has({&quot;north&quot;, &quot;top&quot;, &quot;n&quot;, &quot;t&quot;}, w) then
    x = (x or ox); y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;south&quot;, &quot;bottom&quot;, &quot;s&quot;, &quot;b&quot;}, w) then
    x = (x or ox); y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;northwest&quot;, &quot;topleft&quot;, &quot;nw&quot;, &quot;tl&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;northeast&quot;, &quot;topright&quot;, &quot;ne&quot;, &quot;tr&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;southeast&quot;, &quot;bottomright&quot;, &quot;se&quot;, &quot;br&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;southwest&quot;, &quot;bottomleft&quot;, &quot;sw&quot;, &quot;bl&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;up&quot;, &quot;u&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) + 1
  elseif has({&quot;down&quot;, &quot;d&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) - 1
  end

  local carea = getRoomArea(mmp.currentroom)
  if not carea then mmp.echo(&quot;Don't know what area are we in.&quot;) return end

  otherroom = select(2, next(getRoomsByPosition(carea,x,y,z)))

  if not otherroom then
    mmp.echo(&quot;There isn't a room to the &quot;..w..&quot; that I see - try with an exact room id.&quot;) return
  end

else
  if not mmp.roomexists(matches[2]) then -- check that an explicit other room ID is valid
    mmp.echo(&quot;A room with id &quot;..matches[2].. &quot; doesn't exist.&quot;) return
  else
    otherroom = tonumber(matches[2])
  end
end

if setExit(mmp.currentroom, otherroom, matches[3]) then
  if not matches[4] then setExit(otherroom, mmp.currentroom, mmp.ranytolong(matches[3])) end

  mmp.echo(string.format(&quot;Linked %s (%d) to %s (%d) via a %s%s exit.&quot;,
    (getRoomName(mmp.currentroom) ~= &quot;&quot; and getRoomName(mmp.currentroom) or &quot;''&quot;), mmp.currentroom, (getRoomName(otherroom) ~= &quot;&quot; and getRoomName(otherroom) or &quot;''&quot;), otherroom, (matches[4] and &quot;one-way &quot; or ''), matches[3]))
else
  mmp.echo(&quot;Couldn't create an exit.&quot;)
end
centerview(mmp.currentroom)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^(?:rlk|room link) ?(\d+)? (\w+)( one)?$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Delete a room</name>
                    <script>-- want the current room, but we're lost
if not matches[2] and (not mmp.currentroom or not mmp.roomexists(mmp.currentroom)) then mmp.echo(&quot;Don't know where we are at the moment.&quot;) return end

-- want another room, but it doesn't exist
if matches[2] and tonumber(matches[2]) and not mmp.roomexists(matches[2]) then mmp.echo(&quot;v&quot;..matches[2]..&quot; doesn't exist.&quot;) return end

-- or a relative one
if matches[2] and not tonumber(matches[2]) and not mmp.relativeroom(mmp.currentroom, matches[2]) then mmp.echo(&quot;There is no room &quot;..matches[2].. &quot; of us.&quot;) return end

local rid = (not matches[2] and mmp.currentroom or (tonumber(matches[2]) or mmp.relativeroom(mmp.currentroom, matches[2])))

local n = getRoomName(rid)
deleteRoom(rid)
mmp.echo(string.format(&quot;Deleted the %s (%d) room.\n&quot;, (n ~= &quot;&quot; and n or &quot;''&quot;), rid))
centerview(mmp.currentroom)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^(?:rld|room delete) ?(\w+)?$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Delete a link</name>
                    <script>-- need the current room, but we're lost
if not mmp.currentroom or not mmp.roomexists(mmp.currentroom) then mmp.echo(&quot;Don't know where we are at the moment.&quot;) return end

-- make sure the dir is valid
local dir = mmp.anytolong(matches[2])
if not dir then mmp.echo(matches[2]..&quot; isn't a valid normal exit.&quot;) return end

-- gone already?
if not getRoomExits(mmp.currentroom)[dir] then mmp.echo(dir..&quot; link doesn't exist already.&quot;) end

-- locate the room on the other end, so we can unlink it from there as well if necessary
local otherroom
if getRoomExits(getRoomExits(mmp.currentroom)[dir])[mmp.ranytolong(dir)] then
  otherroom = getRoomExits(mmp.currentroom)[dir]
end

if setExit(mmp.currentroom, -1, dir) then
  if otherroom then
    if setExit(otherroom, -1, mmp.ranytolong(dir)) then
      mmp.echo(string.format(&quot;Deleted the %s exit from %s (%d).&quot;,
        dir, getRoomName(mmp.currentroom), mmp.currentroom))
     else mmp.echo(&quot;Couldn't delete the incoming exit.&quot;) end
  else
    mmp.echo(string.format(&quot;Deleted the one-way %s exit from %s (%d).&quot;,
      dir, getRoomName(mmp.currentroom), mmp.currentroom))
  end
else
  mmp.echo(&quot;Couldn't delete the outgoing exit.&quot;)
end
centerview(mmp.currentroom)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^(?:urlk|room unlink) (\w+)$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Move room to another area</name>
                    <script>mmp.roomArea(matches[2], matches[3])</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^room area (?:v(\d+) )?(.+)$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Set a room character</name>
                    <script>local room = matches[3] or mmp.currentroom
room = tonumber(room) or mmp.relativeroom(mmp.currentroom, room)
if not room or not mmp.roomexists(room) then
  mmp.echo(&quot;Sorry - which room do you want to put this character in? I don't know where you are at the moment, if you want to do the current room.&quot;)
  return
end

local char = matches[2]

if char == &quot;clear&quot; then
  setRoomChar(room, ' ')
  mmp.echo(&quot;Cleared the character from &quot;..room..&quot; (&quot;..getRoomName(room)..&quot;)&quot;)
else
  setRoomChar(room, char)
  mmp.echo(&quot;Set the &quot;..char:sub(1,1)..&quot; character on &quot;..room..&quot; (&quot;..getRoomName(room)..&quot;)&quot;)
end
centerview(mmp.currentroom)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^rcc ([^ ]+)(?: (\w+))?$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Set room weight</name>
                    <script>local weight = tonumber(matches[3]), room
if matches[2] == '' then room = mmp.currentroom
else
  room = tonumber(matches[2]) or mmp.relativeroom(mmp.currentroom, matches[2])
end

if not room or not mmp.roomexists(room) then
  mmp.echo(&quot;Sorry - which room do you want to set the weight on? I don't know where you are at the moment, if you want to do the current room.&quot;)
  return
end

if not weight then
  mmp.echo(&quot;What weight do you want to set on #&quot;..room..&quot;?&quot;)
end

local oldweight = getRoomWeight(room)
setRoomWeight(room, weight)

if weight &gt; oldweight then
  mmp.echo(&quot;Increased the room weight on #&quot;..room..&quot; (&quot;..getRoomName(room)..&quot;) by &quot;..(weight-oldweight)..&quot; to &quot;..weight..&quot; - making it less desirable to travel through.&quot;)
elseif weight &lt; oldweight then
  mmp.echo(&quot;Decreased the room weight on #&quot;..room..&quot; (&quot;..getRoomName(room)..&quot;) by &quot;..(oldweight-weight)..&quot; to &quot;..weight..&quot; - making it more desirable to travel through.&quot;)
else
  mmp.echo(&quot;The room weight on #&quot;..room..&quot; (&quot;..getRoomName(room)..&quot;) is already &quot;..weight..&quot;.&quot;)
end</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^rw(?: (\w+))? (\d+)$</regex>
                </Alias>
                <Alias isActive="no" isFolder="no">
                    <name>-- (area functions)</name>
                    <script></script>
                    <command></command>
                    <packageName></packageName>
                    <regex></regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Create an area</name>
                    <script>local t = getAreaTable(); local tr = {}; for k,v in pairs(t) do tr[v] = k end
local newid = table.maxn(tr) + 1

setAreaName( newid, matches[2] )
mmp.echo(string.format(&quot;Created new area %s (%d)&quot;, matches[2], newid))
centerview(mmp.currentroom)
raiseEvent(&quot;mmp areas changed&quot;)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^area add (.+)$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Delete an area</name>
                    <script>mmp.deleteArea(matches[2])</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^area delete (.+)$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Rename an area</name>
                    <script>mmp.renameArea(matches[2])</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^area rename (.+)$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>List continents</name>
                    <script>local tmp = getRoomUserData(1, &quot;areaContinents&quot;)
local continents = {}

if tmp ~= &quot;&quot; then
  continents = yajl.to_value(tmp)
end

if not next(continents) then mmp.echo(&quot;No continents known.&quot;)
else
  for continent, areadata in pairs(continents) do
    mmp.echo(continent..&quot; continent:&quot;)
    
    for _, areaid in ipairs(areadata) do
      cecho(&quot;  &quot;..getRoomAreaName(areaid)..&quot;\n&quot;)
    end
  end
end</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^(?:acl|area continents)$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Add area to continent</name>
                    <script>-- ac continent [optional area]

local continent = matches[2]:title()
local area
if not matches[3] then area = getRoomArea(mmp.currentroom)
elseif tonumber(matches[3]) then
  area = tonumber(matches[3])
  if getRoomAreaName(area) == -1 then area = nil end
else
  local areas = getAreaTable()

  for karea, id in pairs(areas) do if karea:lower():find(matches[3]:lower(), 1, true) then area = id break end end
end

if not area then mmp.echo(matches[3]..&quot; isn't a known area. Which one do you want to set?&quot;) return end

local tmp = getRoomUserData(1, &quot;areaContinents&quot;)
local continents = {}

if tmp ~= &quot;&quot; then
  continents = yajl.to_value(tmp)
end


if not continents[continent] and mmp.addingcontinent ~= continent then
  mmp.addingcontinent = continent
  mmp.echo(&quot;Continent &quot;..continent..&quot; isn't known so far - would you like to make a new one? Do this command again if so.&quot;)
  return
end

mmp.addingcontinent = nil

continents[continent] = continents[continent] or {}

-- have to use this instead of contains and index_of, because those count keys as well - and we don't want that
local function index_of(data, areaID)
  for i = 1, #data do
    if data[i] == areaID then return i end
  end

  return -1
end

if index_of(continents[continent], area) ~= -1 then
  mmp.echo(getRoomAreaName(area)..&quot; is already known as being on the &quot;..continent..&quot; continent.&quot;)
  return
else
  continents[continent][#continents[continent]+1] = area -- not a key, because yajl will put a ton of null's.
  mmp.echo(&quot;Recorded that &quot;..getRoomAreaName(area)..&quot; is on the &quot;..continent..&quot; continent.&quot;)

  -- remove from other areas if moving
  for kcontinent, data in pairs(continents) do
    if kcontinent ~= continent then
      local i = index_of(continents[kcontinent], area)
      if i ~= -1 then
        table.remove(continents[kcontinent], i)
        if not next(continents[kcontinent]) then continents[kcontinent] = nil end
        mmp.echo(&quot;De-listed &quot;..getRoomAreaName(area)..&quot; from the &quot;..kcontinent..&quot; continent.&quot;)
      end
    end
  end
end

local toserialize = yajl.to_string(continents)
setRoomUserData(1, &quot;areaContinents&quot;, toserialize)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^ac ([\w']+)(?: (.+))?$</regex>
                </Alias>
                <Alias isActive="no" isFolder="no">
                    <name>-- (dangerous functions)</name>
                    <script></script>
                    <command></command>
                    <packageName></packageName>
                    <regex></regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Clear the map completely</name>
                    <script>if not mmp.map_delete_warning then
  mmp.echo(&quot;Are you really, really, really sure you want to delete all of the map to go to a blank state? Do the command again if you're certain.&quot;)
  mmp.map_delete_warning = true
  return
end

mmp.echo(&quot;Okay, deleting...&quot;)

tempTimer(.1, function()
  for name, id in pairs(getAreaTable()) do
    deleteArea(tonumber(id))
  end

  mmp.echo(&quot;Deleted everything. It's all gone.&quot;)
  mmp.map_delete_warning = nil
  centerview(1)
end)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^map delete all$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Delete shop stockroom exits</name>
                    <script>mmp.echo(&quot;Deleting all known stockroom exits (rooms with $ and a down exit)&quot;)
local c = 0

for area, areaname in pairs(mmp.areatabler) do
  local rooms = getAreaRooms(area) or {}
  for i = 0, #rooms do
    local char = getRoomChar(rooms[i] or 0)
    if char == '$' then 
      local exits = getRoomExits(rooms[i] or 0) -- retrieve after $, more efficient

      if exits.down then
        setExit(rooms[i], -1, 'down')
        mmp.echo(string.format(&quot;Deleted the stockroom exit at %s (#%d in %s)&quot;, getRoomName(rooms[i]), rooms[i], mmp.areatabler[getRoomArea(rooms[i])]))
        c = c + 1
      end
    end

  end
end

mmp.echo(string.format(&quot;Deleted %s known stockroom exit%s.&quot;, c, (c ~= 1 and 's' or '')))
centerview(mmp.currentroom)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^delete known stockrooms$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Clear continent data</name>
                    <script>if not mmp.wipingcontinents then
  mmp.wipingcontinents = true
  mmp.echo(&quot;Are you sure you want to wipe all continent data? If yes, do this again.&quot;)
  return
end
mmp.wipingcontinents = nil

local toserialize = yajl.to_string{}
setRoomUserData(1, &quot;areaContinents&quot;, toserialize)
mmp.echo(&quot;Wiped all continents data.&quot;)</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^clear continent data$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Delete suffixed periods</name>
                    <script>mmp.echo(&quot;Deleting removing all periods at the end of room names...&quot;)
local c = 0

for area, areaname in pairs(mmp.areatabler) do
  local rooms = getAreaRooms(area) or {}
  for i = 0, #rooms do
    local name = getRoomName(rooms[i] or 0)
    if string.ends(name, &quot;.&quot;) then
      name = string.sub(name, 1, (#name-1))
      setRoomName(rooms[i], name)
      mmp.echo(string.format(&quot;Patched up room #%s - '%s'&quot;, rooms[i], name))
      c = c + 1
    end
  end
end

mmp.echo(string.format(&quot;Fixed up %s room%s.&quot;, c, (c ~= 1 and 's' or '')))</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^delete suffixed periods$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Find single exits</name>
                    <script>local c = 0

for area, id in pairs(getAreaTable()) do
  for _, roomid in pairs(getAreaRooms(id)) do
    local exits = getRoomExits(roomid)
    for dir, otherroom in pairs(exits) do
      local otherexits = getRoomExits(otherroom)
      if not table.contains(otherexits, roomid) then
        echoLink(string.format(&quot;%s -&gt; %s is oneway (%s-&gt;%s type)\n&quot;, roomid, otherroom, 
          (mmp.envidsr and mmp.envidsr[getRoomEnv(roomid)] or &quot;?&quot;),
          (mmp.envidsr and mmp.envidsr[getRoomEnv(otherroom)] or &quot;?&quot;)),
        [[mmp.gotoRoom(]]..roomid..[[)]], &quot;Click to go to the start room &quot;..roomid, true)
        c = c + 1
     end
    end
  end
end

mmp.echo(string.format(&quot;Found %s oneways.%s&quot;, c, (c &gt; 10 and &quot; Have fun. Click on lines to go to the rooms.&quot; or &quot;&quot;)))</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^find single exits$</regex>
                </Alias>
                <Alias isActive="yes" isFolder="no">
                    <name>Show char marks</name>
                    <script>local c = 0
local m = {}

for area, id in pairs(getAreaTable()) do
  for _, roomid in pairs(getAreaRooms(id)) do
    local c = getRoomChar(roomid)
    if c ~= '' then
      m[c] = m[c] or {}
      m[c][#m[c]+1] = roomid
    end
  end
end

for letter, rooms in pairs(m) do
  table.sort(rooms)
  mmp.echo(&quot;Rooms with the &lt;blue&gt;&quot;..letter..&quot;&lt;reset&gt; character on them:&quot;)
  for i = 1, #rooms do
    echo(string.format(&quot;  %-5s %s\n&quot;, rooms[i], getRoomName(rooms[i])))
  end
end</script>
                    <command></command>
                    <packageName></packageName>
                    <regex>^show char marks$</regex>
                </Alias>
            </AliasGroup>
            <Alias isActive="yes" isFolder="no">
                <name>Toggle mapping mode</name>
                <script>if (matches[2] and matches[2] == &quot;on&quot;) or (not matches[2] and not mmp.editing) then
  mmp.editing = true
  enableAlias(&quot;mm Mapping&quot;)

  mmp_regenerate_areas()
  mmp.highlight_unfinished_rooms()

  mmp.echo(&quot;Mapping mode enabled. Happy mapping!&quot;)
elseif (matches[2] and matches[2] == &quot;off&quot;) or (not matches[2] and mmp.editing) then
  mmp.editing = false
  disableAlias(&quot;mm Mapping&quot;)
  mmp.echo(&quot;Mapping mode disabled.&quot;)
end</script>
                <command></command>
                <packageName></packageName>
                <regex>^(?:mc|map create) ?(on|off)?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Save a map</name>
                <script>local function s(loc)
    if not saveMap(loc) then
      mmp.echo(&quot;Couldn't save the map :(&quot;)
    else
      if loc ~= &quot;&quot; then mmp.echo(&quot;Map saved.&quot;) else mmp.echo(&quot;Saved the default map.&quot;) end
    end
end

if not saveMap then
  mmp.echo(&quot;Your Mudlet can't save maps. Please upgrade it!&quot;)
else
  if matches[2] and matches[2] == &quot;custom&quot; then
    s(invokeFileDialog(false, &quot;Please select the folder to save the map in and hit Open&quot;)..&quot;/Mudlet map from &quot;..os.date(&quot;%A %d, %b '%y&quot;)..&quot;.dat&quot;)
  elseif matches[2] then
	s(getMudletHomeDir()..&quot;/map/&quot;..matches[2])
  else
    s(&quot;&quot;)
  end
end</script>
                <command></command>
                <packageName></packageName>
                <regex>^map save(?: (.+))?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Load a map</name>
                <script>local function s(loc)
    if not loadMap(loc) then
      mmp.echo(&quot;Couldn't save the map :(&quot;)
    else
      if loc ~= &quot;&quot; then mmp.echo(&quot;Map loaded.&quot;) else mmp.echo(&quot;Loaded the default map.&quot;) end
    end
end

if not loadMap then
  mmp.echo(&quot;Your Mudlet can't load maps. Please upgrade it!&quot;)
else
  if matches[2] and matches[2] == &quot;custom&quot; then
    s(invokeFileDialog(true, &quot;Please select the map file and click Open to load it&quot;))
  elseif matches[2] then
	s(getMudletHomeDir()..&quot;/map/&quot;..matches[2])
  else
    s(&quot;&quot;)
  end
end</script>
                <command></command>
                <packageName></packageName>
                <regex>^map load(?: (.+))?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Get dirs</name>
                <script>if not matches[2] and not matches[3] then
  mmp.echo(&quot;Where do you want to showpath to?&quot;)
elseif matches[2] and not matches[3] then
  mmp.echoPath(mmp.currentroom, matches[2])
else
  mmp.echoPath(matches[2], matches[3])
end</script>
                <command></command>
                <packageName></packageName>
                <regex>^showpath(?: (\d+))?(?: (\d+))?$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Check wholist</name>
                <script>enableTrigger(&quot;Parse wholist&quot;)
send(&quot;who b&quot;)
tempTimer(10, [[disableTrigger'Parse wholist']])</script>
                <command></command>
                <packageName></packageName>
                <regex>^who b$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Add Room Mark</name>
                <script>local tmp = getRoomUserData(1, &quot;gotoMapping&quot;)
local maptable = {}

if tmp ~= &quot;&quot; then
  maptable = yajl.to_value(tmp)
end

local location, markname
if tonumber(matches[2]) then
  location = matches[2]; markname = matches[3]
else
  location = matches[3]; markname = matches[2]
end

-- can't allow mark name to ne a number - yajl then generates a giant table of null's
if tonumber(markname) then
  mmp.echo(&quot;The mark name can't be a number.&quot;) return
end

maptable[markname] = location
local tmp2 = yajl.to_string(maptable)

if not mmp.roomexists(1) then
  addRoom(1)
end

setRoomUserData(1, &quot;gotoMapping&quot;, tmp2)
mmp.echo(string.format(&quot;Room mark for '%s' set to room %s.&quot;, markname, location))</script>
                <command></command>
                <packageName></packageName>
                <regex>^room mark (\w+) (\w+)$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Remove Room Mark</name>
                <script>local tmp= getRoomUserData(1, &quot;gotoMapping&quot;)
if tmp~=&quot;&quot; then
  local maptable=yajl.to_value(tmp)
  if not maptable[matches[2]] then mmp.echo(&quot;Don't have such a mark in the db.&quot;) return end

  maptable[matches[2]]=nil
  local tmp2=yajl.to_string(maptable)
  setRoomUserData(1, &quot;gotoMapping&quot;, tmp2)
  mmp.echo(&quot;Removed the &quot;..matches[2]..&quot; mark.&quot;)
else
  mmp.echo(&quot;We don't have any marks stored anyway.&quot;)
end</script>
                <command></command>
                <packageName></packageName>
                <regex>^room unmark (\w+)$</regex>
            </Alias>
            <Alias isActive="yes" isFolder="no">
                <name>Display Room Marks</name>
                <script>local tmp= getRoomUserData(1, &quot;gotoMapping&quot;)
if tmp~=&quot;&quot; then
	local maptable=yajl.to_value(tmp)
    mmp.echo(&quot;Known marks in this map:&quot;)
    if next(maptable) then
      for k,v in pairs(maptable) do echo(string.format(&quot;  %-21s  %s\n&quot;, tostring(k), tostring(v))) end
    else
      echo(&quot;  (none)\n&quot;)
    end
else
	mmp.echo(&quot;No marks are recorded in this map.&quot;)
end</script>
                <command></command>
                <packageName></packageName>
                <regex>^room marks$</regex>
            </Alias>
        </AliasGroup>
    </AliasPackage>
    <ActionPackage/>
    <ScriptPackage>
        <ScriptGroup isActive="yes" isFolder="yes">
            <name>Mudlet Mapper</name>
            <packageName></packageName>
            <script>mudlet = mudlet or {}; mudlet.mapper_script = true</script>
            <eventHandlerList/>
            <Script isActive="yes" isFolder="no">
                <name>Create Option Table</name>
                <packageName></packageName>
                <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------

function createOption(startingValue, onChangeFunc, allowedVarTypes, use)
	if allowedVarTypes then -- make sure our starting Value follows type rules
		if not table.contains(allowedVarTypes, type(startingValue)) then
			echo(&quot;Starting type is not of allowed type!\n&quot;)
			display(allowedVarTypes)
			echo(&quot;type: &quot; .. type(startingValue) .. &quot;\n&quot;)
			return
		end
	end

	local option = {
		value = startingValue,
		onChange = onChangeFunc,
		allowedVarTypes = allowedVarTypes,
		use = use or &quot;&quot;
	}

	return option
end

function createOptionsTable(defaultTable)
	local index = {} -- index to store the default table at in our proxy table


	local proxyTable = {} -- This is the table that is returned to the user

	proxyTable.disp = echo

	proxyTable.dispDefaultWriteError = function()
		echo(&quot;Can't overwrite default options. Please use the SetOption function to change the value\n&quot;)
	end

	proxyTable.dispOption = function(opt, val)
		if not opt or not val then return end
		echo(&quot;Name: &quot; .. string.title(opt) .. string.rep(&quot; &quot;, 10 - string.len(opt)))
		echo(&quot;Val: &quot; .. tostring(val.value))
		echo(string.rep(&quot; &quot;, 10 - string.len(tostring(val.value))) ..  &quot;- &quot; .. val.use .. &quot;\n&quot;)
	end

	function proxyTable:showAllOptions()
		proxyTable.disp(&quot;Available options: \n&quot;)
		for k, v in pairs(self[index]) do
			self.dispOption(k, v)
		end
		echo(&quot;\n&quot;)
		for k, v in pairs(self[&quot;_customOptions&quot;]) do
			self.dispOption(k, v)
		end

	end

	function proxyTable:getAllOptions()
		local t = {}
		for k, v in pairs(self[index]) do
			t[k] = v.value
		end

		return t
	end

   function proxyTable:setOption(option, value, silent)
		if self[option] == nil then
			proxyTable.disp(&quot;No such option!\n&quot;)
			return
		end

		-- otherwise, set the option
		if self[&quot;_customOptions&quot;][option] then
			if not table.contains(self[&quot;_customOptions&quot;][option].allowedVarTypes, type(value)) then
				proxyTable.disp(&quot;You can't set '&quot; .. option .. &quot;' to that!\n&quot;)
				return
			end
			self[&quot;_customOptions&quot;][option].value = value
			if self[&quot;_customOptions&quot;][option].onChange then
				self[&quot;_customOptions&quot;][option].onChange(option, value)
			end
		else
			if not table.contains(self[index][option].allowedVarTypes, type(value)) then
				proxyTable.disp(&quot;You can't set '&quot; .. option .. &quot;' to that!\n&quot;)
				return
			end
			rawset(self[index][option], &quot;value&quot;, value)
			local opt = rawget(self[index], option)
			if opt.onChange  and not silent then opt.onChange(option, value) end
		end
	end


	proxyTable._customOptions = {}

	local mt = {
		__index = function(t, k)
			local custOp = rawget(t, &quot;_customOptions&quot;)
			if custOp[k] then
			 	local opt = custOp[k]
				if opt then return opt.value else return nil end
			else
				local opt = t[index][k]
				if opt then return opt.value else return nil end
			end
		end,

		__newindex = function (t, k, v)
			if t[index][k] then
				proxyTable.dispDefaultWriteError()
			else
				t[&quot;_customOptions&quot;][k] = v
			end
		end
	}


	proxyTable[index] = defaultTable

	setmetatable(proxyTable, mt)

	return proxyTable

end</script>
                <eventHandlerList/>
            </Script>
            <Script isActive="yes" isFolder="no">
                <name>speedwalking</name>
                <packageName></packageName>
                <script>-- mmp = mudlet mapper namespace
mmp = mmp or {
  paused = false,
  autowalking = false,
  currentroom = false,
  currentroomname = false,
  firstRun = true,
  specials = {}
}

speedWalkWatch = createStopWatch()

-- populated by Mudlet from getPath() and gotoRoom()
speedWalkPath = speedWalkPath or {}
speedWalkDir = speedWalkDir or {}
speedWalkCounter = 0

-- actually used by the mapper for walking
mmp.speedWalkPath = mmp.speedWalkPath or {}
mmp.speedWalkDir = mmp.speedWalkDir or {}


local newversion = &quot;12.12.3&quot;
if mmp.version and mmp.version ~= newversion then 
  if not mmp.game then mmp.echo(&quot;Mapper script updated - Thanks! I don't know what game are you connected to, though - so please reconnect, if you could.&quot;)
  else mmp.echo(&quot;Mapper script updated - thanks! You don't need to restart.&quot;) end
end
mmp.version = newversion

function mmp.startup()
  if not mmp.firstRun then
    return
  end

  local private_settings = {}
  private_settings[&quot;dash&quot;] = createOption(false, mmp.changeBoolFunc, { &quot;boolean&quot; }, &quot;Use Dash?&quot;)
  private_settings[&quot;gallop&quot;] = createOption(false, mmp.changeBoolFunc, { &quot;boolean&quot; }, &quot;Use Gallop?&quot;)
  private_settings[&quot;sprint&quot;] = createOption(false, mmp.changeBoolFunc, { &quot;boolean&quot; }, &quot;Use Sprint?&quot;)
  private_settings[&quot;runaway&quot;] = createOption(false, mmp.changeBoolFunc, { &quot;boolean&quot; }, &quot;Use Jester Runaway?&quot;)
  private_settings[&quot;updatemap&quot;] = createOption(true, mmp.changeUpdateMap, { &quot;boolean&quot; }, &quot;Check for new maps?&quot;)
  private_settings[&quot;lockpathways&quot;] = createOption(true, mmp.lockPathways, { &quot;boolean&quot; }, &quot;Lock pathway exits?&quot;)
  private_settings[&quot;lockwormholes&quot;] = createOption(true, mmp.lockWormholes, { &quot;boolean&quot; }, &quot;Lock all wormholes?&quot;)
  private_settings[&quot;locksewers&quot;] = createOption(false, mmp.lockSewers, { &quot;boolean&quot; }, &quot;Lock all sewers?&quot;)
  private_settings[&quot;lockspecials&quot;] = createOption(false, mmp.lockSpecials, { &quot;boolean&quot; }, &quot;Lock all special exits?&quot;)
  private_settings[&quot;crowdmap&quot;] = createOption(false, mmp.chageMapSource, { &quot;boolean&quot; }, &quot;Use a crowd-sourced map instead of IREs default?&quot;)
  private_settings[&quot;caravan&quot;] = createOption(false, mmp.changeBoolFunc,{ &quot;boolean&quot; }, &quot;Walk caravans?&quot;)
  private_settings[&quot;showcmds&quot;] = createOption(true, mmp.changeBoolFunc, { &quot;boolean&quot; }, &quot;Show walking commands?&quot;)
  private_settings[&quot;shackle&quot;] = createOption(false, mmp.changeBoolFunc, { &quot;boolean&quot; }, &quot;Take off shackle?&quot;)
  private_settings[&quot;duanathar&quot;] = createOption(false, mmp.setDuanathar, { &quot;boolean&quot; }, &quot;Use Eagle Wings in Achaea?&quot;)
  private_settings[&quot;duanatharan&quot;] = createOption(false, mmp.setDuanatharan, { &quot;boolean&quot; }, &quot;Use Atavian Wings in Achaea?&quot;)
  private_settings[&quot;winglanguage&quot;] = createOption(&quot;&quot;, mmp.setWingsLanguage, { &quot;string&quot; }, &quot;Speak non-default language for wings:&quot;)
  private_settings[&quot;removewings&quot;] = createOption(true, mmp.setWingsRemoval, { &quot;boolean&quot; }, &quot;Remove Wings after using them?&quot;)
  private_settings[&quot;slowwalk&quot;] = createOption(false, mmp.setSlowWalk, { &quot;boolean&quot; }, &quot;Walk slowly instead of as quick as possible?&quot;)


  mmp.settings = createOptionsTable(private_settings)
  mmp.settings.disp = mmp.echo

  mmp.game = false

  mmp.settings.dispOption = function(opt, val) 
    cecho(&quot;&lt;green&gt;&quot; .. val.use .. &quot;&lt;white&gt; (&quot; ..opt..&quot;) &quot; .. string.rep(&quot; &quot;, 50 - val.use:len() - opt:len()) .. tostring(val.value) .. &quot;\n&quot;) 
  end

  mmp.settings.dispDefaultWriteError = function()
    mmp.echo(&quot;Please use the mconfig alias to set options!&quot;)
  end

  raiseEvent(&quot;mmp areas changed&quot;)
  mmp.firstRun = false
  mmp.echon(&quot;Mudlet Mapper script for IREs (&quot;..tostring(mmp.version)..&quot;) loaded! (&quot;)
  echoLink(&quot;homepage&quot;,&quot;(openUrl or openURL)'http://wiki.mudlet.org/w/IRE_mapping_script'&quot;, &quot;Clicky clicky to read up on what's this about&quot;)
  echo(&quot;)\n&quot;)
end

function mmp.setmovetimer(time)
  if mmp.movetimer then killTimer(mmp.movetimer) end
  if mmp.settings.slowwalk then return end

  mmp.movetimer = tempTimer(getNetworkLatency()+(time or 0.5), function ()
    mmp.movetimer = false
    mmp.move()
  end)
end

-- moves to the next room we need to.
function mmp.move()
  if mmp.paused or not mmp.autowalking or mmp.movetimer or not mmp.canmove() then return end
  -- sometimes it's 0 - default to 1
  if speedWalkCounter == 0 then speedWalkCounter = 1 end

  local cmd
  if mmp.settings[&quot;caravan&quot;] then cmd = &quot;lead caravan &quot;..mmp.speedWalkDir[speedWalkCounter]
  else
    cmd = mmp.speedWalkDir[speedWalkCounter]
  end
  
  cmd = cmd or ''

  -- timeout before loadstring, so it can set its own if it would like to.
  mmp.setmovetimer()

  if string.starts(cmd, &quot;script:&quot;) then 
    cmd = string.gsub( cmd, &quot;script:&quot;, &quot;&quot; ) loadstring(cmd)()
    if mmp.settings.showcmds then cecho(string.format(&quot;&lt;red&gt;(&lt;maroon&gt;%d - &lt;dark_slate_grey&gt;%s&lt;red&gt;)&quot;, #mmp.speedWalkDir - speedWalkCounter + 1, &quot;&lt;script&gt;&quot;)) end
  else 
    send(cmd, false)
    if mmp.settings.showcmds then cecho(string.format(&quot;&lt;red&gt;(&lt;maroon&gt;%d - &lt;dark_slate_grey&gt;%s&lt;red&gt;)&quot;, #mmp.speedWalkDir - speedWalkCounter + 1, cmd)) end
  end
end

function mmp.swim()
  -- not going anywhere? don't do anything
  if not mmp.speedWalkDir[speedWalkCounter] then return end

  send(&quot;swim &quot; .. mmp.speedWalkDir[speedWalkCounter], false)
  if mmp.settings.showcmds then cecho(string.format(&quot;&lt;red&gt;(&lt;maroon&gt;%d - &lt;dark_slate_grey&gt;swim %s&lt;red&gt;)&quot;, #mmp.speedWalkDir - speedWalkCounter + 1, mmp.speedWalkDir[speedWalkCounter])) end

  mmp.setmovetimer(2.5)
end

function mmp.enterGrate()
  -- not going anywhere? don't do anything
  if not mmp.speedWalkDir[speedWalkCounter] then return end

  send(&quot;enter grate &quot; .. mmp.speedWalkDir[speedWalkCounter], false)
  if mmp.settings.showcmds then cecho(string.format(&quot;&lt;red&gt;(&lt;maroon&gt;%d - &lt;dark_slate_grey&gt;enter grate %s&lt;red&gt;)&quot;, #mmp.speedWalkDir - speedWalkCounter + 1, mmp.speedWalkDir[speedWalkCounter])) end

  mmp.setmovetimer(2.5)
end

function mmp.openDoor()
  -- not going anywhere? don't do anything
  if not mmp.speedWalkDir[speedWalkCounter] then return end

  send(&quot;open door &quot; .. mmp.speedWalkDir[speedWalkCounter], false)
  if mmp.settings.showcmds then cecho(string.format(&quot;&lt;red&gt;(&lt;maroon&gt;%d - &lt;dark_slate_grey&gt;open door %s&lt;red&gt;)&quot;, #mmp.speedWalkDir - speedWalkCounter + 1, mmp.speedWalkDir[speedWalkCounter])) end

  mmp.setmovetimer(getNetworkLatency())
end

function mmp.unlockDoor()
  -- not going anywhere? don't do anything
  if not mmp.speedWalkDir[speedWalkCounter] then return end

  send(&quot;unlock door &quot; .. mmp.speedWalkDir[speedWalkCounter], false)
  if mmp.settings.showcmds then cecho(string.format(&quot;&lt;red&gt;(&lt;maroon&gt;%d - &lt;dark_slate_grey&gt;unlock door %s&lt;red&gt;)&quot;, #mmp.speedWalkDir - speedWalkCounter, mmp.speedWalkDir[speedWalkCounter])) end

  mmp.setmovetimer(getNetworkLatency())
end

function mmp.customwalkdelay(delay)
  mmp.setmovetimer(getNetworkLatency()+delay)
end

function mmp.stop()
  mmp.speedWalkPath = {}
  mmp.speedWalkDir = {}
  speedWalkCounter = 0
  stopStopWatch(speedWalkWatch)
  --if mmp.movetimer then killTimer( mmp.movetimer ) end
  mmp.autowalking = false

  -- clear all the temps we've got
  for trigger, ID in pairs(mmp.specials) do
    killTrigger(ID)
  end
  mmp.specials = {}

  mmp.echo(&quot;Stopped walking.&quot;)
  raiseEvent(&quot;mmapper stopped&quot;)
  if mmp.settings.shackle then expandAlias(&quot;wear shackle&quot;) end
end

-- Aetolia and Lusternia support showing balances in GMCP. This is easy to support, so we do!
-- if we can't move, setup a polling timer to prompt walking when we can again.
-- popular systems that expose balance &amp; equilibrium values can be added here as well, perhaps though a similarly-named function.
function mmp.canmove(fromtimer)
  if mapper_can_move and mapper_can_move() then
	if fromtimer then
      mmp.move()
    else return true end
  elseif mapper_can_move then
    tempTimer(0.2, [[mmp.canmove(true)]])
    return false
  end

  if not gmcp.Char then return true end

  if (gmcp.Char and
    (not gmcp.Char.Vitals.balance or gmcp.Char.Vitals.balance == &quot;1&quot;) and
    (not gmcp.Char.Vitals.equilibrium or gmcp.Char.Vitals.equilibrium == &quot;1&quot;) and
    (not gmcp.Char.Vitals.right_arm or gmcp.Char.Vitals.right_arm == &quot;1&quot;) and
    (not gmcp.Char.Vitals.left_arm or gmcp.Char.Vitals.left_arm == &quot;1&quot;) and
    (not gmcp.Char.Vitals.right_leg or gmcp.Char.Vitals.right_leg == &quot;1&quot;) and
    (not gmcp.Char.Vitals.left_leg or gmcp.Char.Vitals.left_leg == &quot;1&quot;) and
    (not gmcp.Char.Vitals.psisuper or gmcp.Char.Vitals.psisuper ~= &quot;0&quot;) and
    (not gmcp.Char.Vitals.psisub or gmcp.Char.Vitals.psisub ~= &quot;0&quot;) and
    (not gmcp.Char.Vitals.psiid or gmcp.Char.Vitals.psiid ~= &quot;0&quot;) and
    (not gmcp.Char.Balance or gmcp.Char.Balance.List.balance == &quot;1&quot;) and
    (not gmcp.Char.Balance or gmcp.Char.Balance.List.equilibrium == &quot;1&quot;) and
    (not gmcp.Char.Balance or gmcp.Char.Balance.List.rarm == &quot;1&quot;) and
    (not gmcp.Char.Balance or gmcp.Char.Balance.List.larm == &quot;1&quot;) and
    (not gmcp.Char.Balance or gmcp.Char.Balance.List.legs == &quot;1&quot;) and
    (not gmcp.Char.Vitals.prone or (gmcp.Char.Vitals.prone == &quot;0&quot; or gmcp.Char.Vitals.prone == 0))
  ) then
	if fromtimer then
      mmp.move()
    else return true end
  else
    tempTimer(0.2, [[mmp.canmove(true)]])
    return false
  end
end

local oldnum
function speedwalking( event, num )
  local num = tonumber(num) or tonumber(gmcp.Room.Info.num)
  mmp.previousroom = mmp.currentroom
  mmp.currentroom = num
  mmp.currentroomname = getRoomName(num)

  -- track if we're inside or outside, if possible
  if gmcp.Room then
    if mmp.inside and not table.contains(gmcp.Room.Info.details, &quot;indoors&quot;) then
      mmp.inside = false
      raiseEvent(&quot;mmapper went outside&quot;)
    elseif not mmp.inside and table.contains(gmcp.Room.Info.details, &quot;indoors&quot;) then
      mmp.inside = true
      raiseEvent(&quot;mmapper went inside&quot;)
    end
    -- the event could cancel speedwalking - in this case quit
    if mmp.ignore_speedwalking then
      mmp.ignore_speedwalking = nil
      return
    end
  end
  if oldnum == num then return else oldnum = num end

  if not mmp.autowalking then return end

  if mmp.movetimer then killTimer(mmp.movetimer); mmp.movetimer = false end

  if num == mmp.speedWalkPath[#mmp.speedWalkPath] then
    local walktime = stopStopWatch(speedWalkWatch)
    mmp.echo(string.format(&quot;We've arrived! Took us %.1fs.\n&quot;, walktime))
    raiseEvent(&quot;mmapper arrived&quot;)
    if mmp.settings.shackle then expandAlias(&quot;wear shackle&quot;) end
    mmp.speedWalkPath = {}
    mmp.speedWalkDir = {}
    speedWalkCounter = 0
    mmp.autowalking = false
  elseif mmp.speedWalkPath[speedWalkCounter] == num then
    speedWalkCounter = speedWalkCounter + 1
    mmp.move()
  elseif #mmp.speedWalkPath&gt; 0 then -- ended up somewhere we didn't want to be?
    speedWalkMoved = false
    -- re-calculate path then
    mmp.echo(&quot;Ended up off the path, recalculating a new path...&quot;)
    local destination = mmp.speedWalkPath[#mmp.speedWalkPath]
    if not mmp.getPath(num, destination) then
      mmp.echo(string.format(&quot;Don't know how to get to %d (%s) anymore :(&quot;,
        destination, getRoomName(destination)))
    else
		mmp.gotoRoom (destination)
    end
  end
end

function mmp.gotoRoom (where, dashtype)
  if not where or not tonumber(where) then
    mmp.echo(&quot;Where do you want to go to?&quot;) return end

  if tonumber(where) == mmp.currentroom then
    mmp.echo(&quot;We're already at &quot;..where..&quot;!&quot;)
   raiseEvent(&quot;mmapper arrived&quot;)
   return
  end

  local madeduanathar, madeduanatharan

  local function getcmd(word)
    return mmp.settings.removewings and 
      [[script:sendAll(&quot;wear wings&quot;, &quot;say *]]..(mmp.settings.winglanguage)..[[ ]]..word..[[&quot;, &quot;remove wings&quot;, false)]]
      or
      [[script:send(&quot;say *]]..(mmp.settings.winglanguage)..[[ ]]..word..[[&quot;, false)]]
  end

  if mmp.game == &quot;achaea&quot; and (mmp.settings.duanathar or mmp.settings.duanatharan) and gmcp.Room and not table.contains(gmcp.Room.Info.details, &quot;indoors&quot;) and mmp.oncontinent(getRoomArea(mmp.currentroom), &quot;Prime&quot;) then
    if mmp.settings.duanatharan then
      addSpecialExit(mmp.currentroom, 4882, getcmd(&quot;duanatharan&quot;))
      addSpecialExit(mmp.currentroom, 3885, getcmd(&quot;duanathar&quot;))
      mmp.clearpathcache() -- clear cache so mmp.getPath accounts for the new way
      madeduanatharan = true
    else
      addSpecialExit(mmp.currentroom, 3885, getcmd(&quot;duanathar&quot;))
      mmp.clearpathcache() -- clear cache so mmp.getPath accounts for the new way
      madeduanathar = true
    end
  end

  -- if getPath worked, then the dirs and room #'s tables were populated for us
  if not mmp.getPath(mmp.currentroom, tonumber(where)) then
    mmp.echo(&quot;Don't know how to get there (&quot;..tostring(where)..&quot;) from here :(&quot;)
    mmp.speedWalkPath = {}
    mmp.speedWalkDir = {}
    speedWalkCounter = 0
    raiseEvent(&quot;mmapper failed path&quot;)
    if mmp.settings.shackle then expandAlias(&quot;wear shackle&quot;) end
    if madeduanatharan then mmp.clearspecials{4882, 3885} elseif madeduanathar then mmp.clearspecials{3885} end
    return
  end

  doSpeedWalk(dashtype)
  if madeduanatharan then mmp.clearspecials{4882, 3885} elseif madeduanathar then mmp.clearspecials{3885} end
end

function mmp.gotoArea (where, number, dashtype, exact)
  if not where or not type(where)==&quot;string&quot; then
    mmp.echo(&quot;Where do you want to go to?&quot;) return end

  number = tonumber(number)
  local tmp = getRoomUserData(1, &quot;gotoMapping&quot;)
  if not tmp or tmp == '' then tmp = &quot;[]&quot; end

  local maptable = yajl.to_value(tmp)

  local goto = maptable[where]
  if goto then
  	mmp.gotoRoom(goto, dashtype)
  	return
  end

  local possibleRooms, shortestPath, shortestBorder = {}, {}, 0

  local areaid, msg, multiples = mmp.findAreaID(where, exact)
  if areaid then
     possibleRooms = mmp.getAreaBorders(areaid)

  elseif not areaid and #multiples &gt; 0 then
    if number and number&lt;=#multiples then
        mmp.gotoArea(multiples[number], nil, dashtype, true)
        return
    end
    mmp.echo(&quot;Which area would you like to go to?&quot;)
    fg(&quot;DimGrey&quot;)
    for key, areaname in ipairs(multiples) do
      echo&quot;  &quot;; echoLink(key .. &quot;) &quot;, 'mmp.gotoArea(&quot;'..areaname..'&quot;, nil, '..(dashtype and '&quot;'..dashtype..'&quot;' or &quot;nil&quot;)..', true)', &quot;Click to go to &quot;..areaname, true)
        setUnderline(true) echoLink(areaname, 'mmp.gotoArea(&quot;'..areaname..'&quot;, nil, '..(dashtype and '&quot;'..dashtype..'&quot;' or &quot;nil&quot;)..', true)', &quot;Click to go to &quot;..areaname, true) setUnderline(false) echo&quot;\n&quot;
    end
    resetFormat()
    return
  else
    mmp.echo(string.format(&quot;Don't know of any area named '%s'.&quot;, where))
    return
  end

  for id, _ in pairs(possibleRooms) do
    if mmp.getPath(mmp.currentroom, tonumber(id)) then
      if shortestBorder==0 or #shortestPath &gt; #speedWalkPath then
        shortestPath = speedWalkPath
        shortestBorder = tonumber(id)
      end
    end
  end

  if shortestBorder == 0 then
    mmp.echo(&quot;Don't know how to get there from here :(&quot;)
    mmp.speedWalkPath = {}
    mmp.speedWalkDir = {}
    speedWalkCounter = 0
    raiseEvent(&quot;mmapper failed path&quot;)
    return
  end

  mmp.gotoRoom(shortestBorder, dashtype)
end

function doSpeedWalk(dashtype)
  mmp.speedWalkDir = speedWalkDir
  mmp.speedWalkPath = speedWalkPath

  resetStopWatch(speedWalkWatch)
  startStopWatch(speedWalkWatch)
  if mmp.settings[&quot;gallop&quot;] or mmp.settings[&quot;dash&quot;] or mmp.settings.sprint or dashtype then
    mmp.fixPath(mmp.currentroom, mmp.speedWalkPath[#mmp.speedWalkPath],
      (mmp.settings[&quot;gallop&quot;] and &quot;gallop&quot;) or (mmp.settings[&quot;dash&quot;] and &quot;dash&quot;) or (mmp.settings.sprint and &quot;sprint&quot;) or (mmp.settings.runaway and &quot;runaway&quot;) or dashtype)
  end

  mmp.fixSpecialExits(mmp.speedWalkDir)

  if #mmp.speedWalkPath == 0 then
    mmp.echo(&quot;Couldn't find a path to the destination :(&quot;)
    raiseEvent(&quot;mmapper failed path&quot;)
    if mmp.settings.shackle then expandAlias(&quot;wear shackle&quot;) end
    return
  end

  mmp.autowalking = true

  -- this is a fix: convert nums to actual numbers
  for i = 1, #mmp.speedWalkPath do
    mmp.speedWalkPath[i] = tonumber(mmp.speedWalkPath[i])
  end

  if mmp.settings.shackle then expandAlias(&quot;remove shackle&quot;) end
  if not mmp.paused then
    mmp.echon(&quot;Starting speedwalk from &quot;..(atcp.RoomNum or gmcp.Room.Info.num)..&quot; to &quot;) echoLink(mmp.speedWalkPath[#mmp.speedWalkPath], 'gotoRoom &quot;' .. mmp.speedWalkPath[#mmp.speedWalkPath].. '&quot;', 'Go to ' .. mmp.speedWalkPath[#mmp.speedWalkPath]) echo(&quot;: &quot;)
    speedWalkCounter = 1
    if mmp.canmove() then mmp.move() else echo(&quot;(when we get balance back / aren't hindered)&quot;) end
  else
    mmp.echo(&quot;Will go to &quot;..mmp.speedWalkPath[#mmp.speedWalkPath]..&quot; as soon as the mapper is unpaused.&quot;)
  end
end

function mmp.failpath()
  if mmp.movetimer then
    local walktime = stopStopWatch(speedWalkWatch)
    mmp.echo(string.format(&quot;Can't continue further! Took us %.1fs to get here.\n&quot;, walktime))
  end

  raiseEvent(&quot;mmapper failed path&quot;)
  if mmp.settings.shackle then expandAlias(&quot;wear shackle&quot;) end
  mmp.speedWalkPath = {}
  mmp.speedWalkDir = {}
  speedWalkCounter = 0
  if mmp.movetimer then killTimer( mmp.movetimer ); mmp.movetimer = nil end
end

function mmp.changeBoolFunc(name, option)
  local en
  if option then en = &quot;will now use&quot; else en = &quot;will no longer use&quot; end
  mmp.echo(&quot;&lt;green&gt;Okay, the mapper &quot; .. en .. &quot; &lt;white&gt;&quot; .. name .. &quot;&lt;green&gt;!&quot;)
end

function mmp.fixPath(rFrom,rTo,dashtype)
  local currentPath, currentIds = {}, {}
  local dRef = {[&quot;n&quot;] = &quot;north&quot;, [&quot;e&quot;] = &quot;east&quot;, [&quot;s&quot;] = &quot;south&quot;, [&quot;w&quot;] = &quot;west&quot;}
  if not getPath(rFrom,rTo) then return false end

  -- Logic: Look for a direction repeated at least two times.
  -- count the number of times it repeats, then look that many rooms ahead.
  -- if that room also contains the direction we're headed, just travel that many directions.
  -- otherwise, dash.

  local repCount = 1
  local index = 1
  local dashExaust = false
  while mmp.speedWalkDir[index] do
    dashExaust = false
    repCount = 1
    while mmp.speedWalkDir[index+repCount] == mmp.speedWalkDir[index] do
      repCount = repCount + 1
      if repCount == 11 then
        dashExaust = true
        break
      end
    end
    if repCount &gt; 1 then
      -- Found direction repitition. Calculate dash path.
      local exits = getRoomExits(mmp.speedWalkPath[index+(repCount-1)])
      local pname = &quot;&quot;
      for word in mmp.speedWalkDir[index]:gmatch(&quot;%w&quot;) do pname = pname .. (dRef[word] or word) end
      if not exits[pname] or dashExaust then
        -- Final room in this direction does not continue, dash!
        table.insert(currentPath,string.format(&quot;%s %s&quot;,dashtype,mmp.speedWalkDir[index]))
        currentIds[#currentIds+1] = mmp.speedWalkPath[index+repCount-1]
      else
        -- Final room in this direction continues onwards, don't dash
        for i = 1,repCount do
          table.insert(currentPath,mmp.speedWalkDir[index])
          currentIds[#currentIds+1] = mmp.speedWalkPath[index+i-1]
        end
      end
      index = index + repCount
    else
      -- No repetition, just add the direction.
      table.insert(currentPath,mmp.speedWalkDir[index])
      currentIds[#currentIds+1] = mmp.speedWalkPath[index]
      index = index + 1
    end
  end

  mmp.speedWalkDir = currentPath
  mmp.speedWalkPath = currentIds
  return true
end

-- a certain version of the mapper gave us special exits prepended with 0 or 1 in the command
-- depending on if it was locked. Need to remove these before we can use them
function mmp.fixSpecialExits(directions)
  for i = 1, #directions do
    if directions[i]:match(&quot;^%d&quot;) then directions[i] = directions[i]:sub(2) end
  end
end

-- cleanup function to remove the temp special exit we made - only way to remove specials in Mudlet atm is by clearing them all
function mmp.clearspecials(ignorerooms)
  local t = getSpecialExits(mmp.currentroom)
  clearSpecialExits(mmp.currentroom)

  for connectingroom, exits in pairs(t) do
    if not table.contains(ignorerooms,connectingroom) then -- don't re-add this one back as it's our temp
      for command, locked in pairs(exits) do
        --debug echo: mmp.echo(&quot;need to re-link this room to &quot;..connectingroom..&quot; with &quot;..command..&quot; that is &quot;..(locked == &quot;1&quot; and &quot;locked&quot; or &quot;unlocked&quot;)..&quot;.&quot;)
        addSpecialExit(mmp.currentroom, connectingroom, command)
        if locked == &quot;1&quot; then lockSpecialExit(mmp.currentroom, connectingroom, command, true) end
      end
    end
  end
end</script>
                <eventHandlerList>
                    <string>RoomNum</string>
                    <string>gmcp.Room.Info</string>
                </eventHandlerList>
            </Script>
            <Script isActive="yes" isFolder="no">
                <name>Utilities</name>
                <packageName></packageName>
                <script>function mmp.echo(what)
  what = what or &quot;&quot;
  moveCursorEnd(&quot;main&quot;) if getCurrentLine() ~= &quot;&quot; then echo&quot;\n&quot; end
  decho(&quot;&lt;112,229,0&gt;(&lt;73,149,0&gt;mapper&lt;112,229,0&gt;): &lt;255,255,255&gt;&quot;)
  cecho(what)
  echo(&quot;\n&quot;)
end

function mmp.echon(what)
  moveCursorEnd(&quot;main&quot;) if getCurrentLine() ~= &quot;&quot; then echo&quot;\n&quot; end
  decho(&quot;&lt;112,229,0&gt;(&lt;73,149,0&gt;mapper&lt;112,229,0&gt;): &lt;255,255,255&gt;&quot;)
  cecho(what)
end

function mmp.deleteLineP()
  deleteLine()
  tempLineTrigger(1,1,[[
    if isPrompt() then deleteLine() end
  ]])
end

function mmp.pause(what)
  assert(what == nil or what == &quot;on&quot; or what == &quot;off&quot;, &quot;mmp.pause wants 'on', 'off' or nothing as an argument&quot;)

  if what == &quot;on&quot; or (what == nil and not mmp.paused) then
    mmp.paused = true
  elseif  what == &quot;off&quot; or (what == nil and mmp.paused) then
    mmp.paused = false
  end

  mmp.echo(&quot;Speedwalking &quot; .. (mmp.paused and &quot;paused&quot; or &quot;unpaused&quot;) .. &quot;.&quot;)
  if not mmp.paused then mmp.move() end
end

function mmp.getnums(roomname, exact)
  local t = (not exact and mmp.searchRoom or mmp.searchRoomExact)(roomname)

  if not next(t) then
    return nil end

  local result = {}

  if not tonumber(select(2, next(t))) then
    for roomid,_ in pairs(t) do
      if roomid ~= 0 then result[#result+1] = tonumber(roomid) end
    end
  else
    for _,roomid in pairs(t) do
      if roomid ~= 0 then result[#result+1] = tonumber(roomid) end
    end
  end

  return result
end

-- for a given room name, we'll echo all the vnums
function mmp.echonums(roomname)
  local t = mmp.searchRoomExact(roomname)

  if not next(t) then
    echo &quot;?&quot; return nil end

  -- transform the kv table into a table of tables for cleaner code.
    -- + perhaps Mudlet in future will give this us anyway, sorted by relevancy
  local dt = {}
  for roomid,room in pairs(t) do
    dt[#dt+1] = {name = room, id = roomid}
  end

  -- we can have nothing if we asked for exact match
  if not dt[1] then echo &quot;?---&quot; return end

  -- display first three ids. Can't really nicely table.concat them.
  echoLink(dt[1].id, 'mmp.gotoRoom('..dt[1].id..')', string.format(&quot;Go to %s (%s)&quot;, dt[1].id, dt[1].name))
  if not dt[2] then return end

  echo&quot;, &quot;
  echoLink(dt[2].id, 'mmp.gotoRoom('..dt[2].id..')', string.format(&quot;Go to %s (%s)&quot;, dt[2].id, dt[2].name))
  if not dt[3] then return end

  echo&quot;, &quot;
  echoLink(dt[3].id, 'mmp.gotoRoom('..dt[3].id..')', string.format(&quot;Go to %s (%s)&quot;, dt[3].id, dt[3].name))
  if not dt[4] then return end

  echo&quot;, ...&quot;
end

function mmp.roomEcho(query)
  local result = mmp.searchRoom(query)

  if not tonumber(select(2, next(result))) then
    for roomid, roomname in pairs(result) do roomid = tonumber(roomid)
      cecho(&quot;&lt;DarkSlateGrey&gt; (&lt;blue&gt;&quot;)
      echoLink(roomid, 'mmp.gotoRoom('..roomid..')', string.format(&quot;Go to %s (%s)&quot;, roomid, tostring(roomname)))
      cecho(&quot;&lt;DarkSlateGrey&gt;)&quot;)
    end

  else
    for roomname, roomid in pairs(result) do roomid = tonumber(roomid)
      cecho(&quot;&lt;DarkSlateGrey&gt; (&lt;blue&gt;&quot;)
      echoLink(roomid, 'mmp.gotoRoom('..roomid..')', string.format(&quot;Go to %s (%s)&quot;, roomid, tostring(roomname)))
      cecho(&quot;&lt;DarkSlateGrey&gt;)&quot;)
    end
  end
end


-- searchRoom with a cache!
local cache = {}
setmetatable(cache, {__mode = &quot;kv&quot;}) -- weak keys/values = it'll periodically get cleaned up by gc

function mmp.searchRoom(what)
  local result = cache[what]
  if not result then
    result = searchRoom(what)
    local realResult = {}
    for key, value in pairs(type(result) == &quot;table&quot; and result or {}) do
        -- both ways, because searchRoom can return either id-room name or the reverse
        if type(key) == &quot;string&quot; then
          realResult[key:ends(&quot; (road)&quot;) and key:sub(1, -8) or key] = value
        else
          realResult[key] = value:ends(&quot; (road)&quot;) and value:sub(1, -8) or value
        end
    end
    cache[what] = realResult
    result = realResult
  end
  return result
end

local function endswith(s, suffix)
    return s:sub(#s - #suffix + 1) == suffix
end

function mmp.searchRoomExact(what)
  local roomTable = mmp.searchRoom(what)
  local realResult = {}
  what = what:lower()
  for key, value in pairs (roomTable) do
    if type(key) == &quot;string&quot; and (key:lower() == what or (endswith(key, '.') and key:sub(1, -2) == what)) then
        realResult[key:ends(&quot; (road)&quot;) and key:sub(1, -8) or key] = value
    elseif type(value) == &quot;string&quot; and (value:lower() == what or (endswith(value, '.') and value:sub(1, -2) == what)) then
        realResult[key] = value:ends(&quot; (road)&quot;) and value:sub(1, -8) or value
    end
  end
  if (table.is_empty(realResult)) then
    return roomTable
  else
    return realResult
  end
end

function mmp.roomWhoFind(query)
  if query:ends('.') then query = query:sub(1,-2) end
  local result = mmp.searchRoomExact(query)

  if type(result) == &quot;string&quot; or not next(result) then
    cecho(&quot;&lt;CadetBlue&gt;  You have no recollection of any room with that name.&quot;) return end

  if not tonumber(select(2, next(result))) then -- old style
    for roomid, roomname in pairs(result) do roomid = tonumber(roomid)
      cecho(string.format(&quot;  &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt; (&lt;blue&gt;&quot;,
        tostring(roomname)))
      echoLink(roomid, 'mmp.gotoRoom('..roomid..')', string.format(&quot;Go to %s (%s)&quot;, roomid, tostring(roomname)))
      cecho(string.format(&quot;&lt;DarkSlateGrey&gt;) &lt;white&gt;%s&lt;DarkSlateGrey&gt;.\n&quot;, tostring(mmp.areatabler[getRoomArea(roomid)])))
    end

  else -- new style
    for roomname, roomid in pairs(result) do roomid = tonumber(roomid)
      cecho(string.format(&quot;  &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt; (&lt;blue&gt;&quot;,
        tostring(roomname)))
      echoLink(roomid, 'mmp.gotoRoom('..roomid..')', string.format(&quot;Go to %s (%s)&quot;, roomid, tostring(roomname)))
      cecho(string.format(&quot;&lt;DarkSlateGrey&gt;) &lt;white&gt;%s&lt;DarkSlateGrey&gt;.\n&quot;, tostring(mmp.areatabler[getRoomArea(roomid)])))
    end
  end
end

-- DOES NOT ACCOUNT FOR CHANGING THE MAP YET (within a profile load), because we don't know when it happens
local getpathcache = {}
setmetatable(getpathcache, {__mode = &quot;kv&quot;}) -- weak keys/values = it'll periodically get cleaned up by gc

function mmp.getPath(from, to)
  assert(tonumber(from) and tonumber(to), &quot;mmp.getPath: both from and to have to be room IDs&quot;)

  local key = string.format(&quot;%s_%s&quot;, from, to)
  local resulttbl = getpathcache[key]

  -- not in cache?
  if not resulttbl then
    local boolean = getPath(from, to)
    -- save it into the cache &amp; send away
    getpathcache[key] = {boolean, mmp.speedWalkDir, mmp.speedWalkPath}
    return boolean
  end

  -- or if it is, retrieve &amp; send away
  mmp.speedWalkDir = getpathcache[key][2]
  mmp.speedWalkPath = getpathcache[key][3]
  return getpathcache[key][1]
end

function mmp.clearpathcache() getpathcache = {} end

function mmp.roomFind(query)
  if query:ends('.') then query = query:sub(1,-2) end
  local result = mmp.searchRoom(query)

  if type(result) == &quot;string&quot; or not next(result) then
    cecho(&quot;&lt;grey&gt;You have no recollection of any room with that name.&quot;) return end

  cecho(&quot;&lt;DarkSlateGrey&gt;You know the following relevant rooms:\n&quot;)


  if not tonumber(select(2, next(result))) then -- old style
    for roomid, roomname in pairs(result) do roomid = tonumber(roomid)
      cecho(string.format(&quot;  &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt; (&lt;blue&gt;&quot;,
        tostring(roomname)))
      echoLink(roomid, 'mmp.gotoRoom('..roomid..')', string.format(&quot;Go to %s (%s)&quot;, roomid, tostring(roomname)))
      cecho(string.format(&quot;&lt;DarkSlateGrey&gt;) in the &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt;.&quot;, tostring(mmp.areatabler[getRoomArea(roomid)])))
            fg(&quot;DarkSlateGrey&quot;) echoLink(&quot; &gt; Show path\n&quot;, [[mmp.echoPath(mmp.currentroom, ]]..roomid..[[)]], &quot;Display directions&quot;, true) resetFormat()
    end

  else -- new style
    for roomname, roomid in pairs(result) do roomid = tonumber(roomid)
      cecho(string.format(&quot;  &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt; (&lt;blue&gt;&quot;,
        tostring(roomname)))
      echoLink(roomid, 'mmp.gotoRoom('..roomid..')', string.format(&quot;Go to %s (%s)&quot;, roomid, tostring(roomname)))
      cecho(string.format(&quot;&lt;DarkSlateGrey&gt;) in the &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt;.&quot;, tostring(mmp.areatabler[getRoomArea(roomid)])))
      fg(&quot;DarkSlateGrey&quot;) echoLink(&quot; &gt; Show path\n&quot;, [[mmp.echoPath(mmp.currentroom, ]]..roomid..[[)]], &quot;Display directions&quot;, true) resetFormat()
    end
  end

  cecho(string.format(&quot;  &lt;DarkSlateGrey&gt;%d rooms found.\n&quot;, table.size(result)))
end

function mmp.findAreaID(areaname, exact)
  local areaname = areaname:lower()
  local list = getAreaTable()

  -- iterate over the list of areas, matching them with substring match.
  -- if we get match a single area, then return it's ID, otherwise return
  -- 'false' and a message that there are than one are matches
  local returnid, fullareaname, multipleareas = nil, nil, {}
  for area, id in pairs(list) do
    if (not exact and area:lower():find(areaname, 1, true)) or (exact and areaname == area:lower()) then
      returnid = id; fullareaname = area; multipleareas[#multipleareas+1] = area
    end
  end

  if #multipleareas == 1 then
    return returnid, fullareaname
  else
    return nil, nil, multipleareas
  end
end

function mmp.echoRoomList(areaname, exact)
  local id, msg, multiples = mmp.findAreaID(areaname, exact)
  if id then
    local roomlist, endresult = getAreaRooms(id) or {}, {}

    -- obtain a room list for each of the room IDs we got
    for _, id in pairs(roomlist) do
      endresult[id] = getRoomName(id)
    end

  -- sort room IDs so we can display them in order
    table.sort(roomlist)

    -- now display something half-decent looking
    cecho(string.format(
      &quot;&lt;DarkSlateGrey&gt;List of all rooms in &lt;grey&gt;%s&lt;DarkSlateGrey&gt; (&lt;grey&gt;%d&lt;DarkSlateGrey&gt;):\n&quot;, msg, table.size(endresult)))
    for _, roomid in ipairs(roomlist) do
    local roomname = endresult[roomid]
      fg(&quot;blue&quot;) echoLink(string.format(&quot;%6s&quot;, roomid), 'mmp.gotoRoom('..roomid..')', string.format(&quot;Go to %s (%s)&quot;, roomid, tostring(roomname)), true)
       cecho(string.format(&quot;&lt;DarkSlateGrey&gt;: &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt;.\n&quot;, roomname))
    end
  elseif not id and #multiples &gt; 0 then
    mmp.echo(&quot;For which area would you want to list rooms for?&quot;)

  fg(&quot;DimGrey&quot;)
    for _, areaname in ipairs(multiples) do
      echo&quot;  &quot;; setUnderline(true) echoLink(areaname, 'mmp.echoRoomList(&quot;'..areaname..'&quot;, true)', &quot;Click to view the room list for &quot;..areaname, true) setUnderline(false) echo&quot;\n&quot;
    end
  resetFormat()
  else
    mmp.echo(string.format(&quot;Don't know of any area named '%s'.&quot;, areaname))
  end
end

function mmp.echoAreaList()
  local list = getAreaTable()
  local ids, rlist = {}, {}
  for area, id in pairs(list) do
    if id ~= 0 then ids[#ids+1] = id; rlist[id] = area end end
  table.sort(ids)

  cecho(string.format(
      &quot;&lt;DarkSlateGrey&gt;List of all areas we know of (click to view room list):\n&quot;))
  for _, id in pairs(ids) do
    cecho(string.format(&quot;&lt;blue&gt;%s%d &quot;, string.rep(&quot; &quot;, (6-#tostring(id))), id))
    fg(&quot;DarkSlateGrey&quot;) echoLink(rlist[id], 'mmp.echoRoomList(&quot;'..rlist[id]..'&quot;, true)', &quot;View the room list for &quot;..rlist[id], true) echo(&quot;\n&quot;)
  end
end

function mmp.clearLabels(areaid)
  local function clearlabels(areaid)
    local t = getMapLabels(areaid)
    if type(t) ~= &quot;table&quot; then return end

    for labelid, _ in pairs(t) do deleteMapLabel(areaid, labelid) end
  end

  if areaid == &quot;map&quot; then
    for areaid in pairs(mmp.areatabler) do
      clearlabels(areaid)
    end

    mmp.echo(&quot;Cleared labels in all of the map.&quot;)
    return
  end

  clearlabels(areaid)
  mmp.echo(string.format(&quot;Cleared all labels in '%s'.&quot;, mmp.areatabler[areaid]))
end

function mmp.roomLook(input)

  -- we can do a report with a number
  local function handle_number(num)
    -- compile all available data
    if not mmp.roomexists(num) then mmp.echo(num..&quot; doesn't seem to exist.&quot;) return end
    local s, areanum = pcall(getRoomArea,num)
    if not s then mmp.echo(areanum); return; end

    local exits = getRoomExits(num)
    local name = getRoomName(num)
    local islocked = roomLocked(num)
    local weight = (getRoomWeight(num) and getRoomWeight(num) or &quot;?&quot;) -- getRoomWeight is buggy in one of the versions, is actually linked to setRoomWeight and thus returns nil
    local coords = {getRoomCoordinates(num)}
    local specexits = getSpecialExits(num)
    local env = getRoomEnv(num)
    local envname = (mmp.envidsr and mmp.envidsr[env]) or &quot;?&quot;

    -- generate a report
    mmp.echo(string.format(&quot;Room: %s #: %d area: %s (%d)&quot;,
      name, num, tostring(mmp.areatabler[areanum]), areanum))

    mmp.echo(string.format(&quot;Coordinates: x:%d, y:%d, z:%d, locked: %s, weight: %s&quot;, coords[1], coords[2], coords[3], (islocked and &quot;yep&quot; or &quot;nope&quot;), tostring(weight)))

    mmp.echo(string.format(&quot;Environment: %s (%d)%s&quot;, tostring(envname), env, (getRoomUserData(num, &quot;indoors&quot;) ~= '' and &quot;, indoors&quot; or '')))

    mmp.echo(string.format(&quot;Exits (%d):&quot;, table.size(exits)))
    for exit, leadsto in pairs(exits) do
      echo(string.format(&quot;  %s -&gt; %s (%d)%s\n&quot;, exit, getRoomName(leadsto), leadsto,
        ((getRoomArea(leadsto) or &quot;?&quot;) == areanum and &quot;&quot;
        or &quot; (in &quot;..(mmp.areatabler[getRoomArea(leadsto)] or &quot;?&quot;)..&quot;)&quot;)))
    end

    -- display special exits if we got any
    if next(specexits) then
      mmp.echo(string.format(&quot;Special exits (%d):&quot;,table.size(specexits)))

      for leadsto, command in pairs(specexits) do
        if type(command) == &quot;string&quot; then
          echo(string.format(&quot;  %s -&gt; %s (%d)\n&quot;, command, getRoomName(leadsto), leadsto))
        else -- new format - exit name, command
          for cmd, locked in pairs(command) do
            if locked == '1' then
              cecho(string.format(&quot;&lt;DarkSlateGrey&gt;  %s -&gt; %s (%d) (locked)\n&quot;, cmd, getRoomName(leadsto), leadsto))
            else
              echo(string.format(&quot;  %s -&gt; %s (%d)\n&quot;, cmd, getRoomName(leadsto), leadsto))
            end
          end
        end
      end
    end

    -- actions we can do. This will be a short menu of sorts for actions
    mmp.echo(&quot;Stuff you can do:&quot;)
    echo&quot;  &quot; echo(&quot;Clear all labels &quot;) echoLink(&quot;(in area)&quot;, 'mmp.clearLabels('..areanum..')', '') echo&quot; &quot; echoLink(&quot;(whole map)&quot;, 'mmp.clearLabels(&quot;map&quot;)', '') echo&quot;\n&quot;
    echo&quot;  &quot; echoLink(&quot;Check for all updates&quot;, 'mmp.echo(&quot;Checking...&quot;) mmp.checkforupdate()', '')
    echo&quot; &quot; echoLink(&quot;(force map)&quot;, [[
      if io.exists(getMudletHomeDir()..&quot;/map downloads/current&quot;) then
        local s,m = os.remove(getMudletHomeDir()..&quot;/map downloads/current&quot;)
        if not s then mmp.echo(&quot;Couldn't delete '&quot;..getMudletHomeDir()..&quot;/map downloads/current' file: &quot;..tostring(m)..&quot;.&quot;) end
      end
      mmp.echo(&quot;Re-downloading the latest map... please make sure you have the map open.&quot;)
      mmp.checkforupdate()
    ]], &quot;Re-download the map regardless if you have latest&quot;)
    echo&quot;\n&quot;	
  end

  -- see if we can do anything with the name
  local function handle_name(name)
    local result = mmp.searchRoom(name)

    if type(result) == &quot;string&quot; then
      cecho(&quot;&lt;grey&gt;You have no recollection of any room with that name.&quot;) return end

    -- if we got one result, then act on it
    if table.size(result) == 1 then
      if type(next(result)) == &quot;number&quot; then
        handle_number(next(result))
      else
        handle_number(select(2, next(result)))
      end
      return
    end

    -- if not, then ask the user to clarify which one would they want
    mmp.echo(&quot;Which room specifically would you like to look up?&quot;)
    if not select(2, next(result)) or not tonumber(select(2, next(result))) then
      for roomid, roomname in pairs(result) do roomid = tonumber(roomid)
        cecho(string.format(&quot;  &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt; (&lt;blue&gt;&quot;,
          tostring(roomname)))
        echoLink(roomid, 'mmp.roomLook('..roomid..')', string.format(&quot;View room details for %s (%s)&quot;, roomid, tostring(roomname)))
        cecho(string.format(&quot;&lt;DarkSlateGrey&gt;) in the &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt;.\n&quot;, tostring(mmp.areatabler[getRoomArea(roomid)])))
      end

    else
      for roomname, roomid in pairs(result) do roomid = tonumber(roomid)
        cecho(string.format(&quot;  &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt; (&lt;blue&gt;&quot;,
          tostring(roomname)))
        echoLink(roomid, 'mmp.roomLook('..roomid..')', string.format(&quot;View room details for %s (%s)&quot;, roomid, tostring(roomname)))
        cecho(string.format(&quot;&lt;DarkSlateGrey&gt;) in the &lt;LightSlateGray&gt;%s&lt;DarkSlateGrey&gt;.\n&quot;, tostring(mmp.areatabler[getRoomArea(roomid)])))
      end
    end
  end

  if not input then
    if not mmp.roomexists(mmp.currentroom) then
      mmp.echo(mmp.currentroom.. &quot; doesn't seem to be mapped yet.&quot;)
      mmp.echo(&quot;Stuff you can do:&quot;)
      echo&quot;  &quot; echoLink(&quot;Check for all updates&quot;, 'mmp.echo(&quot;Checking...&quot;) mmp.checkforupdate()', '') 
      echo&quot; &quot; echoLink(&quot;(force map)&quot;, [[
      local s,m = os.remove(getMudletHomeDir()..&quot;/map downloads/current&quot;)
        if io.exists(getMudletHomeDir()..&quot;/map downloads/current&quot;) then
          local s,m = os.remove(getMudletHomeDir()..&quot;/map downloads/current&quot;)
          if not s then mmp.echo(&quot;Couldn't delete '&quot;..getMudletHomeDir()..&quot;/map downloads/current' file: &quot;..tostring(m)..&quot;.&quot;) end
        end
        mmp.echo(&quot;Re-downloading the latest map...&quot;)
        mmp.checkforupdate()
      ]], &quot;Re-download the map regardless if you have latest&quot;)
      echo&quot;\n&quot;
    else input = mmp.currentroom end
  end

  if tonumber(input) then
    handle_number(tonumber(input))
  else
    handle_name(input)
  end

  mmp.echo(string.format(&quot;version %s.&quot;, tostring(mmp.version)))
end

function mmp.roomexists(num)
  if not num then return false end
  if roomExists then return roomExists(num) end

  local s,m = pcall(getRoomArea, tonumber(num))
  return (s and true or false)
end

-- translates n to north and so forth
function mmp.anytolong(exit)
  local t = {
    n = &quot;north&quot;,
    e = &quot;east&quot;,
    s = &quot;south&quot;,
    w = &quot;west&quot;,
    ne = &quot;northeast&quot;,
    se = &quot;southeast&quot;,
    sw = &quot;southwest&quot;,
    nw = &quot;northwest&quot;,
    u = &quot;up&quot;,
    d = &quot;down&quot;,
    i = &quot;in&quot;,
    o = &quot;out&quot;,
    [&quot;in&quot;] = &quot;in&quot;
  }

  for s, l in pairs(t) do t[l] = l end

  return t[exit]
end

function mmp.anytoshort(exit)
  local t = {
    n = &quot;north&quot;,
    e = &quot;east&quot;,
    s = &quot;south&quot;,
    w = &quot;west&quot;,
    ne = &quot;northeast&quot;,
    se = &quot;southeast&quot;,
    sw = &quot;southwest&quot;,
    nw = &quot;northwest&quot;,
    u = &quot;up&quot;,
    d = &quot;down&quot;,
    [&quot;in&quot;] = &quot;in&quot;,
    out = &quot;out&quot;
  }
  local rt = {}
  for s,l in pairs(t) do
    rt[l] = s; rt[s] = s
  end

  return rt[exit]
end


function mmp.ranytolong(exit)
  local t = {
    n = &quot;south&quot;,
    north = &quot;south&quot;,
    e = &quot;west&quot;,
    east = &quot;west&quot;,
    s = &quot;north&quot;,
    south = &quot;north&quot;,
    w = &quot;east&quot;,
    west = &quot;east&quot;,
    ne = &quot;southwest&quot;,
    northeast = &quot;southwest&quot;,
    se = &quot;northwest&quot;,
    southeast = &quot;northwest&quot;,
    sw = &quot;northeast&quot;,
    southwest = &quot;northeast&quot;,
    nw = &quot;southeast&quot;,
    northwest = &quot;southeast&quot;,
    u = &quot;down&quot;,
    up = &quot;down&quot;,
    d = &quot;up&quot;,
    down = &quot;up&quot;,
    i = &quot;out&quot;,
    [&quot;in&quot;] = &quot;out&quot;,
    o = &quot;in&quot;,
    out = &quot;in&quot;
  }

  return t[exit]
end

-- returns nil or the room number relative to this one
function mmp.relativeroom(from, dir)
  if not mmp.roomexists(from) then return end

  local exits = getRoomExits(tonumber(from))
  return exits[mmp.anytolong(dir)]
end

function mmp.deleteArea(name, exact)
  local id, fname, ma = mmp.findAreaID(name, exact)

  if id then
    deleteArea(id)
    mmp.echo(string.format(&quot;Deleted %s (%d).&quot;, fname, id))
    centerview(mmp.currentroom)
  elseif next(ma) then
    mmp.echo(&quot;Which one of these specifically would you like to delete?&quot;)

    fg(&quot;DimGrey&quot;)
    for _,name in ipairs(ma) do
    echo &quot;  &quot; setUnderline(true) echoLink(name, [[mmp.deleteArea(&quot;]]..name..[[&quot;, true)]], &quot;Delete &quot;..name, true) setUnderline(false) echo&quot;\n&quot;
    end
    resetFormat()
    else
      mmp.echo(&quot;Don't know of that area.&quot;)
  end

  raiseEvent(&quot;mmp areas changed&quot;)
end

function mmp.renameArea(name, exact)
  if not (mmp.currentroom or getRoomArea(mmp.currentroom)) then
    mmp.echo(&quot;Don't know what area are we in at the moment, to rename it.&quot;)
  else
  setAreaName(getRoomArea(mmp.currentroom), name)
  mmp.echo(string.format(&quot;Renamed %s to %s (%d).&quot;, mmp.areatabler[getRoomArea(mmp.currentroom)], name, getRoomArea(mmp.currentroom)))
  centerview(mmp.currentroom)
  end

  raiseEvent(&quot;mmp areas changed&quot;)
end

function mmp.roomArea(otherroom, name, exact)
    local id,fname,ma
    if tonumber(name) then id = tonumber(name); fname = mmp.areatabler[id]
    else id, fname, ma = mmp.findAreaID(name, exact) end

    if otherroom ~= &quot;&quot; and not mmp.roomexists(otherroom) then
      mmp.echo(&quot;Room id &quot;..otherroom..&quot; doesn't seem to exist.&quot;)
      return
    elseif otherroom == &quot;&quot; and not mmp.roomexists(mmp.currentroom) then
      mmp.echo(&quot;Don't know where we are at the moment.&quot;)
      return
    end

   otherroom = otherroom ~= &quot;&quot; and otherroom or mmp.currentroom

  if id then
    setRoomArea(otherroom, id)
    mmp.echo(string.format(&quot;Moved %s to %s (%d).&quot;, (getRoomName(otherroom) ~= &quot;&quot; and getRoomName(otherroom) or &quot;''&quot;), fname, id))
    centerview(otherroom)
  elseif next(ma) then
    mmp.echo(&quot;Into which area exactly would you like to move the room?&quot;)

    fg(&quot;DimGrey&quot;)
    for _,name in ipairs(ma) do
    echo &quot;  &quot; setUnderline(true) echoLink(name, [[mmp.roomArea('', &quot;]]..name..[[&quot;, true)]], &quot;Move the room to &quot;..name, true) setUnderline(false) echo&quot;\n&quot;
    end
    resetFormat()
    else
      mmp.echo(&quot;Don't know of that area.&quot;)
  end
end

function mmp.getAreaBorders(areaid)

    local roomlist, endresult = getAreaRooms(areaid), {}
    -- sometimes getAreaRooms can give us no result :(
    if not roomlist then mmp.echo(&quot;Sorry, seems we can't go there - getAreaRooms(&quot;..areaid..&quot;) didn't give us any results (Mudlet problem - redownloading the map might help fix it)&quot;) return end

    -- obtain a room list for each of the room IDs we got
    for _, id in pairs(roomlist) do
      local exits = getRoomExits(id)
      for _, to in pairs(exits) do
        if not table.contains(roomlist, to) then
          endresult[id] = getRoomName(id)
        end
      end
      local specialexits = getSpecialExitsSwap(id)
      for _, to in pairs(specialexits) do
        if not table.contains(roomlist, to) then
          endresult[id] = getRoomName(id)
        end
      end
    end


    return endresult
end

function mmp.locateAndEcho(room, person)
    local t = mmp.searchRoomExact(room)

    echo &quot;  (&quot;
    mmp.echonums(room, true)
    echo &quot;)&quot;

	-- lowercase results
	for k,v in pairs(t) do if tonumber(k) then t[k] = v:lower() else t[k:lower()] = v end end

    if not (t[room:lower()] or table.contains(t, room:lower())) then return end

    echo&quot;\n&quot;
    if table.size(t) == 1 then
      local k,v = next(t)
      cecho(&quot;&lt;red&gt;From your knowledge, that room is in &lt;orange_red&gt;&quot;..(mmp.areatabler[getRoomArea(type(k) == &quot;number&quot; and k or v)] or &quot;?&quot;)..&quot;&lt;red&gt;.&quot;)
    else
      local k,v = next(t)
    local areas = {}
      if type(k) == &quot;number&quot; then
        for k, _ in pairs(t) do
          areas[mmp.areatabler[getRoomArea(k)] or &quot;?&quot;] = true
        end
      else
        for _, k in pairs(t) do
          areas[mmp.areatabler[getRoomArea(k)] or &quot;?&quot;] = true
        end
      end

      local flattened_areas = {}
      for k, _ in pairs(areas) do
        if k ~= &quot;&quot; then flattened_areas[#flattened_areas+1] = k end
      end

      cecho(&quot;&lt;red&gt;From your knowledge, that room might be in &lt;orange_red&gt;&quot;..table.concat(flattened_areas, &quot;, or &quot;)..&quot;&lt;red&gt;.&quot;)
    end

   if person then
      mmp.pdb[person] = room
      mmp.pdb_lastupdate[person] = true
      raiseEvent(&quot;mmapper updated pdb&quot;)
   end
end

function mmp.locateAndEchoSide(room, person)
    local t = mmp.searchRoomExact(room)

    echo &quot;  (&quot;
    mmp.echonums(room, true)
    echo &quot;)&quot;

	-- lowercase results
	for k,v in pairs(t) do if tonumber(k) then t[k] = v:lower() else t[k:lower()] = v end end

    if not (t[room:lower()] or table.contains(t, room:lower())) then return end

    --echo&quot;\n&quot;
    if table.size(t) == 1 then
      local k,v = next(t)
      cecho(&quot;&lt;red&gt;  (&quot;..(mmp.areatabler[getRoomArea(type(k) == &quot;number&quot; and k or v)] or &quot;?&quot;)..&quot;)&quot;)
    else
      local k,v = next(t)
    local areas = {}
      if type(k) == &quot;number&quot; then
        for k, _ in pairs(t) do
          areas[mmp.areatabler[getRoomArea(k)] or &quot;?&quot;] = true
        end
      else
        for _, k in pairs(t) do
          areas[mmp.areatabler[getRoomArea(k)] or &quot;?&quot;] = true
        end
      end

      local flattened_areas = {}
      for k, _ in pairs(areas) do
        if k ~= &quot;&quot; then flattened_areas[#flattened_areas+1] = k end
      end

      cecho(&quot;&lt;red&gt; (&quot;..table.concat(flattened_areas, &quot;, &quot;)..&quot;)&quot;)
    end

   if person then
      mmp.pdb[person] = room
      mmp.pdb_lastupdate[person] = true
      raiseEvent(&quot;mmapper updated pdb&quot;)
   end
end

function mmp.locateAndEchoInternal(room, person)
    local t = mmp.searchRoomExact(room)



	-- lowercase results
	for k,v in pairs(t) do if tonumber(k) then t[k] = v:lower() else t[k:lower()] = v end end

    if not (t[room:lower()] or table.contains(t, room:lower())) then return end

    --echo&quot;\n&quot;
    if table.size(t) == 1 then
      local k,v = next(t)
      cecho(&quot;&lt;red&gt; in &quot;..(mmp.areatabler[getRoomArea(type(k) == &quot;number&quot; and k or v)] or &quot;?&quot;)..&quot;.&quot;)
    else
      local k,v = next(t)
    local areas = {}
      if type(k) == &quot;number&quot; then
        for k, _ in pairs(t) do
          areas[mmp.areatabler[getRoomArea(k)] or &quot;?&quot;] = true
        end
      else
        for _, k in pairs(t) do
          areas[mmp.areatabler[getRoomArea(k)] or &quot;?&quot;] = true
        end
      end

      local flattened_areas = {}
      for k, _ in pairs(areas) do
        if k ~= &quot;&quot; then flattened_areas[#flattened_areas+1] = k end
      end

      cecho(&quot;&lt;red&gt; in &quot;..table.concat(flattened_areas, &quot;, &quot;)..&quot;.&quot;)
    end

	echo &quot;  (&quot;
    mmp.echonums(room, true)
    echo &quot;)&quot;

   if person then
      mmp.pdb[person] = room
      mmp.pdb_lastupdate[person] = true
      raiseEvent(&quot;mmapper updated pdb&quot;)
   end
end

function mmp.viewArea (where, exact)
  if not where or not type(where)==&quot;string&quot; then
    mmp.echo(&quot;Which area would you like to view?&quot;) return end


  local areaid, msg, multiples = mmp.findAreaID(where, exact)
  if areaid then
    -- center on the first room ID, which typically is the start of an area
    local rooms = getAreaRooms(areaid) or {}
    if not rooms[1] then mmp.echo(&quot;The area has no rooms in it.&quot;) else
    centerview(rooms[1]) end

  elseif not areaid and #multiples &gt; 0 then
    mmp.echo(&quot;Which area would you like to view exactly?&quot;)
    fg(&quot;DimGrey&quot;)
    for _, areaname in ipairs(multiples) do
      echo&quot;  &quot;; setUnderline(true) echoLink(areaname, 'mmp.viewArea(&quot;'..areaname..'&quot;, true)', &quot;Click to view &quot;..areaname, true) setUnderline(false) echo&quot;\n&quot;
    end
    resetFormat()
    return
  else
    mmp.echo(string.format(&quot;Don't know of any area named '%s'.&quot;, where))
    return
  end
end

-- room label the room I'm in
-- room label 342 this is a label in room 342
-- room label green this is a green label where I'm at
-- room label green black this is a green to black label where I'm at
-- room label 34 green black this is a green to black label at room 34
-- how it works: split input string into tokens by space, then determine
-- what to do by checking first few tokens, and finally call the local
-- function with the proper arguments
function mmp.roomLabel(input)
  if not createMapLabel then
    mmp.echo(&quot;Your Mudlet doesn't support createMapLabel() yet - please update to 2.0-test3 or better.&quot;) return
  end

  local tk = input:split(&quot; &quot;)
  local room, fg, bg, message = mmp.currentroom, &quot;yellow&quot;, &quot;red&quot;, &quot;Some room label&quot;

  -- input always have to be something, so tk[1] at least always exists
  if tonumber(tk[1]) then
    room = tonumber(table.remove(tk, 1)) -- remove the number, so we're left with the colors or msg
  end

  -- next: is this a foreground color?
  if tk[1] and color_table[tk[1]] then
    fg = table.remove(tk, 1)
  end

  -- next: is this a backround color?
  if tk[1] and color_table[tk[1]] then
    bg = table.remove(tk, 1)
  end

  -- the rest would be our message
  if tk[1] then
    message = table.concat(tk, &quot; &quot;)
  end

  -- if we haven't provided a room ID and we don't know where we are yet, we can't make a label
  if not room then
    mmp.echo(&quot;We don't know where we are to make a label here.&quot;) return
  end

  local x,y = getRoomCoordinates(room)
  local f1,f2,f3 = unpack(color_table[fg])
  local b1,b2,b3 = unpack(color_table[bg])

  -- finally: do it :)

  local lid = createMapLabel(getRoomArea(room), message, x, y, f1,f2,f3, b1,b2,b3)
  mmp.echo(string.format(&quot;Created new label #%d '%s' in %s.&quot;, lid, message, getRoomAreaName(getRoomArea(room))))
end

function mmp.areaLabels (where, exact)
  if not getMapLabels then
    mmp.echo(&quot;Your Mudlet doesn't support getMapLabels() yet - please update to 2.0-test3 or better.&quot;) return
  end

  if (not where or not type(where)==&quot;string&quot;) and not mmp.currentroom then
    mmp.echo(&quot;For which area would you like to view labels?&quot;) return end

  if not where then
  exact = true
    where = getRoomAreaName(getRoomArea(mmp.currentroom))
  end

  local areaid, msg, multiples = mmp.findAreaID(where, exact)
  if areaid then
    local t = getMapLabels(areaid)
    if type(t) ~= &quot;table&quot; or not next(t) then
      mmp.echo(string.format(&quot;'%s' doesn't seem to have any labels.&quot;, getRoomAreaName(areaid)))
      return
    end

    mmp.echo(string.format(&quot;Area labels for '%s'&quot;, getRoomAreaName(areaid)))
    for labelid, labeltext in pairs(t) do
      fg(&quot;DimGrey&quot;)
      echo(string.format(&quot;  %d) %s (&quot;, labelid, labeltext))
      fg&quot;orange_red&quot; setUnderline(true) echoLink('delete', string.format('deleteMapLabel(%d, %d); mmp.echo(&quot;Deleted label #'..labelid..'&quot;)', areaid, labelid), &quot;Delete label #&quot;..labelid..&quot; from &quot;..getRoomAreaName(areaid))
      setUnderline(false) echo&quot;)\n&quot;
    end
    resetFormat()

  elseif not areaid and #multiples &gt; 0 then
    mmp.echo(&quot;Which area would you like to view exactly?&quot;)
    fg(&quot;DimGrey&quot;)
    for _, areaname in ipairs(multiples) do
      echo&quot;  &quot;; setUnderline(true) echoLink(areaname, 'mmp.areaLabels(&quot;'..areaname..'&quot;, true)', &quot;Click to view labels in &quot;..areaname, true) setUnderline(false) echo&quot;\n&quot;
    end
    resetFormat()
    return
  else
    mmp.echo(string.format(&quot;Don't know of any area named '%s'.&quot;, where))
    return
  end
end

function mmp.echoPath(from, to)
	assert(tonumber(from) and tonumber(to), &quot;mmp.getPath: both from and to have to be room IDs&quot;)
	if mmp.getPath(from, to) then
		mmp.echo(&quot;&lt;white&gt;Directions from &lt;yellow&gt;&quot; .. string.upper(searchRoom(from)) .. &quot; &lt;white&gt;to &lt;yellow&gt;&quot; .. string.upper(searchRoom(to)) .. &quot;&lt;white&gt;:&quot;)
		mmp.echo(table.concat(speedWalkDir, &quot;, &quot;))
		return mmp.speedWalkDir
	end
end

function mmp.listSpecialExits(filter)
  local c = 0

  mmp.echo(&quot;Listing special exits...&quot;)
  for area, areaname in pairs(mmp.areatabler) do
    local rooms = getAreaRooms(area) or {}
    for i = 0, #rooms do
      local exits = getSpecialExits(rooms[i] or 0)

       if exits and next(exits) then
         for exit, cmd in pairs(exits) do
           if type(cmd) == &quot;table&quot; then cmd = next(cmd) end
           if cmd:match(&quot;^%d&quot;) then cmd = cmd:sub(2) end

           if not filter or cmd:lower():find(filter, 1, true) then
            if getRoomArea(exit) ~= area then
              cecho(string.format(&quot;&lt;dark_slate_grey&gt;%s &lt;LightSlateGray&gt;(%d, in %s)&lt;dark_slate_grey&gt; &lt;MediumSlateBlue&gt;-&gt; &lt;coral&gt;%s -&lt;MediumSlateBlue&gt;&gt;&lt;dark_slate_grey&gt; %s &lt;LightSlateGray&gt;(%d, in %s)\n&quot;, getRoomName(rooms[i]), rooms[i], areaname,
                cmd, getRoomName(exit), exit, mmp.areatabler[getRoomArea(exit)] or '?'))
            else
              cecho(string.format(&quot;&lt;dark_slate_grey&gt;%s &lt;LightSlateGray&gt;(%d)&lt;dark_slate_grey&gt; &lt;MediumSlateBlue&gt;-&gt; &lt;coral&gt;%s &lt;MediumSlateBlue&gt;-&gt;&lt;dark_slate_grey&gt; %s &lt;LightSlateGray&gt;(%d)&lt;dark_slate_grey&gt; in %s\n&quot;, getRoomName(rooms[i]), rooms[i], cmd, getRoomName(exit), exit, areaname))
            end
            c = c + 1
           end
         end
       end
    end
  end

  mmp.echo(string.format(&quot;%d exits listed%s.&quot;, c, (not filter and '' or &quot;, with for the filter '&quot;..filter..&quot;'&quot;)))
end

function mmp.doLock (what, lock, filter)
  mmp.echo(string.format(&quot;%s all %s...&quot;, (lock and &quot;Locking&quot; or &quot;Unlocking&quot;), what))
  local c = 0

  for area in pairs(mmp.areatabler) do
    local rooms = getAreaRooms(area) or {}
    for i = 0, #rooms do
      local exits = getSpecialExits(rooms[i] or 0)

       if exits and next(exits) then
         for exit, cmd in pairs(exits) do
           if type(cmd) == &quot;table&quot; then cmd = next(cmd) end

           if (not filter and not (cmd:lower():find(&quot;pathfind&quot;, 1, true) or cmd:lower():find(&quot;worm warp&quot;, 1, true) or cmd:lower():find(&quot;enter grate&quot;, 1, true))) or (filter and cmd:lower():find(filter, 1, true)) then
             lockSpecialExit(rooms[i], exit, cmd, lock)
             c = c + 1
           end
         end
       end
    end
  end

  mmp.echo(string.format(&quot;%s %s known %s.&quot;, (lock and &quot;Locked&quot; or &quot;Unlocked&quot;), c, what))
  return c
end

function mmp.lockPathways()
  local lock = mmp.settings.lockpathways and true or false
  mmp.doLock(&quot;pathways&quot;, lock, &quot;pathfind&quot;)
end

function mmp.lockSewers()
  local lock = mmp.settings.locksewers and true or false
  return mmp.doLock(&quot;sewer grates&quot;, lock, &quot;enter grate&quot;)
end

function mmp.lockWormholes()
  local lock = mmp.settings.lockwormholes and true or false
  return mmp.doLock(&quot;wormholes&quot;, lock, &quot;worm warp&quot;)
end
tempTimer(0, function() if mmp.firstRun then mmp.lockWormholes() end end)

function mmp.lockSpecials()
  local lock = mmp.settings.lockspecials and true or false
  mmp.doLock(&quot;special exits&quot;, lock)
end

function mmp.setDuanathar()
  mmp.clearpathcache() -- clear the cache so it'll use wings or will stop using wings

  if mmp.settings.duanathar then mmp.echo(&quot;Okay, will see about using Eagle wings when you goto somewhere while outside!&quot;)
  else mmp.echo(&quot;Won't use Eagle wings anymore.&quot;) end
end

function mmp.setDuanatharan()
  mmp.clearpathcache() -- clear the cache so it'll use wings or will stop using wings

  if mmp.settings.duanatharan then mmp.echo(&quot;Okay, will see about using Atavian wings (both duanathar and duanatharan) when you goto somewhere while outside!&quot;)
  else mmp.echo(&quot;Won't use Atavian wings anymore.&quot;) end
end

function mmp.chageMapSource()
  local use = mmp.settings.crowdmap and true or false
  if use and not mmp.game or mmp.game ~= &quot;achaea&quot; then
    mmp.echo(&quot;Sorry - the crowdsourced map is only available for use in Achaea. If you'd like to help start one for your game, please post at http://forums.mudlet.org/viewtopic.php?f=13&amp;t=1696. If you are playing Achaea, then it is likely that you just downloaded the script - and it doens't know what you are playing. Reconnect and it'll know.&quot;)
    mmp.settings.crowdmap = false
  elseif use and not loadMap then
   mmp.echo(&quot;Sorry - your Mudlet is too old and can't load maps. Please update: http://forums.mudlet.org/viewtopic.php?f=5&amp;t=1874&quot;)
   mmp.settings.crowdmap = false
  elseif use then
    mmp.echo(&quot;Will use the crowdsourced map for updates instead!&quot;)
    mmp.checkforupdate()
  else
    mmp.echo(&quot;Will use the default Achaea map for updates.&quot;)
  end
end

function mmp.setWingsLanguage()
  mmp.echo(&quot;Alright, will say Duanathar and Duanathar in &quot;..mmp.settings.winglanguage:title()..&quot;.&quot;)
end

function mmp.setWingsRemoval()
  mmp.echo(&quot;Okay - &quot;..(mmp.settings.removewings and &quot;will&quot; or &quot;won't&quot;)..&quot; remove wings after using them.&quot;)
end

function mmp.setSlowWalk()
  if mmp.settings.slowwalk then
    mmp.echo(&quot;Will walk 'slowly' - that is, only try to move in a direction once per room, and move again once we've arrived. This will make us better walkers when it's very laggy, as we won't spam directions unnecessarily and miss certain turns - but it does mean that if we fail to move for some reason, we won't retry again either at all.&quot;)
  else
    mmp.echo(&quot;Will walk as quick as we can!&quot;)
  end
end

-- patches welcome to finish this function.
function mmp.removecontinent(area, continent)
  local tmp = getRoomUserData(1, &quot;areaContinents&quot;)
  local continents = {}

  if tmp ~= &quot;&quot; then
    continents = yajl.to_value(tmp)
  end

  if not next(continents) then return nil, &quot;no continents are known&quot; end
  if not continents[continent] then return nil, &quot;no such continent is recorded&quot; end
 
end

function mmp.indexof_valueonly(data, value)
  for i = 1, #data do
    if data[i] == value then return i end
  end

  return false
end

-- checks if given area ID is on the given continent. Returns true only if certainly knows
function mmp.oncontinent(areaid, continent)
  local tmp = getRoomUserData(1, &quot;areaContinents&quot;)
  if tmp == &quot;&quot; then return end

  local continents = yajl.to_value(tmp)
  if not continents[continent] then return end
  
  return mmp.indexof_valueonly(continents[continent], areaid)
end

function mmp.highlight_unfinished_rooms()
	if not mmp.areatable then return end
	for a,b in pairs (mmp.areatable) do
		local roomList = getAreaRooms(b) or {}
		for c,d in pairs (roomList) do
			if (getRoomName(d) == &quot;&quot;) then
				local fgr,fgg,fgb = unpack(color_table.red)
				local bgr,bgg,bgb = unpack(color_table.blue)
				highlightRoom(d, fgr,fgg,fgb,bgr,bgg,bgb, 1, 100, 100)
			end
		end
	end
end</script>
                <eventHandlerList/>
            </Script>
            <Script isActive="yes" isFolder="no">
                <name>Person tracking</name>
                <packageName></packageName>
                <script>--[[
mmp will have 2 person tracking databases:
- mmp.pdb  =  used to store the last known location of a person
- mmp.pdb_lastupdate  =  used to store the output of the last locating command

Both databases work with the person's name as key and the location name as value.

]]
mmp.pdb = mmp.pdb or {}
mmp.pdb_lastupdate = mmp.pdb_lastupdate or {}

function mmp.is_here(who)
  return (mmp.pdb[who] and mmp.pdb[who] == mmp.currentroomname) and true or false
end</script>
                <eventHandlerList/>
            </Script>
            <Script isActive="yes" isFolder="no">
                <name>Lock Area</name>
                <packageName></packageName>
                <script>-- Lock Area

mmp.locked = mmp.locked or {}
mmp.lastLockSearch = mmp.lastLockSearch or nil

function mmp.doLockArea(search)
	local areaList
	if search ~= nil then
		local r = rex.new(string.lower(search))
		mmp.lastLockSearch = search
		for name, id in pairs(getAreaTable()) do
			if r:match(string.lower(name)) then
				areaList = areaList or {}
				areaList[name] = id
			end
		end
		if areaList == nil then
			mmp.echo(&quot;'&quot; .. search .. &quot;' did not match any known areas!&quot;)
			return
		end
	else
		mmp.lastLockSearch = nil
		areaList = getAreaTable()
	end

	for name, id in pairs(areaList) do
		mmp.echon(name .. string.rep(&quot; &quot;, 40 - string.len(name)))
		if not mmp.locked[id] then
			setFgColor(0, 200, 0)
			setUnderline(true)
			echoLink(&quot;Lock!&quot;, [[mmp.lockArea( ']] .. name:gsub(&quot;'&quot;, [[\']]) .. [[', true )]], &quot;Click to lock area '&quot; .. name .. &quot;'&quot;, true)
		else
			setFgColor(200, 0, 0)
			setUnderline(true)
			echoLink(&quot;Unlock!&quot;, [[mmp.lockArea( ']] .. name:gsub(&quot;'&quot;, [[\']]) .. [[', false )]], &quot;Click to unlock area '&quot; .. name .. &quot;'&quot;, true)
		end
	end

	if not search then
		echo&quot;\n\n&quot; mmp.echo(&quot;Use &lt;green&gt;arealock &lt;area&gt;&lt;white&gt; to filter areas.&quot;)
	end
end

function mmp.lockArea(name, lock, dontreshow)
	local areas = getAreaTable()
	local rooms = getAreaRooms(areas[name]) or {}
	for _, room in pairs(rooms) do
		lockRoom(room, lock)
	end

	mmp.locked[areas[name]] = lock and true or nil
	if lock then
		mmp.echo(&quot;Area '&quot; .. name .. &quot;' locked!&quot;)
	else
		mmp.echo(&quot;Area '&quot; .. name .. &quot;' unlocked!&quot;)
	end

	if not dontreshow then mmp.doLockArea(mmp.lastLockSearch) end
end


</script>
                <eventHandlerList/>
            </Script>
            <Script isActive="yes" isFolder="no">
                <name>Center view via GMCP</name>
                <packageName></packageName>
                <script></script>
                <eventHandlerList/>
                <Script isActive="yes" isFolder="no">
                    <name>mmp_center_roominfo</name>
                    <packageName></packageName>
                    <script>function mmp_center_roominfo()
	centerview(gmcp.Room.Info.num)
end</script>
                    <eventHandlerList>
                        <string>gmcp.Room</string>
                    </eventHandlerList>
                </Script>
            </Script>
            <Script isActive="yes" isFolder="no">
                <name>Fix setExit</name>
                <packageName></packageName>
                <script>do
local oldsetExit = setExit

local exitmap = {
  n = 1,
  north = 1,
  ne = 2,
  northeast = 2,
  nw = 3,
  northwest = 3,
  e = 4,
  east = 4,
  w = 5,
  west = 5,
  s = 6,
  south = 6,
  se = 7,
  southeast = 7,
  sw = 8,
  southwest = 8,
  u = 9,
  up = 9,
  d = 10,
  down = 10,
  [&quot;in&quot;] = 11,
  out = 12
}

function setExit(from, to, direction)
  if type(direction) == &quot;string&quot; and not exitmap[direction] then return false end

  return oldsetExit(from, to, type(direction) == &quot;string&quot; and exitmap[direction] or direction)
end
end</script>
                <eventHandlerList/>
            </Script>
            <Script isActive="yes" isFolder="no">
                <name>Fix exit locking funcs</name>
                <packageName></packageName>
                <script>do
local oldlockExit = lockExit
local oldhasExitLock = hasExitLock

local exitmap = {
  n = 1,
  north = 1,
  ne = 2,
  northeast = 2,
  nw = 3,
  northwest = 3,
  e = 4,
  east = 4,
  w = 5,
  west = 5,
  s = 6,
  south = 6,
  se = 7,
  southeast = 7,
  sw = 8,
  southwest = 8,
  u = 9,
  up = 9,
  d = 10,
  down = 10,
  [&quot;in&quot;] = 11,
  out = 12
}

function lockExit(from, direction, status)
  if type(direction) == &quot;string&quot; and not exitmap[direction] then return false end

  return oldlockExit(from, type(direction) == &quot;string&quot; and exitmap[direction] or direction, status)
end

function hasExitLock(from, direction)
  if type(direction) == &quot;string&quot; and not exitmap[direction] then return false end

  return oldhasExitLock(from, type(direction) == &quot;string&quot; and exitmap[direction] or direction)
end
end</script>
                <eventHandlerList/>
            </Script>
            <ScriptGroup isActive="yes" isFolder="yes">
                <name>mm Mapping</name>
                <packageName></packageName>
                <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                <eventHandlerList/>
                <Script isActive="yes" isFolder="no">
                    <name>mmp_mapping_newroom</name>
                    <packageName></packageName>
                    <script>--mmp_mapping_newroom
local function makeroom(oldid, newid, x,y,z)
  assert(x and y and z, &quot;makeroom: need all 3 coordinates&quot;)
  addRoom(newid)
  setRoomCoordinates(newid, x, y, z)
  setRoomArea(newid, getRoomArea(oldid))

  local fgr,fgg,fgb = unpack(color_table.red)
  local bgr,bgg,bgb = unpack(color_table.blue)
  highlightRoom(newid, fgr,fgg,fgb,bgr,bgg,bgb, 1, 100, 100)

  if mmp.envids[gmcp.Room.Info.environment] then
    setRoomEnv(newid, mmp.envids[gmcp.Room.Info.environment])
  else setRoomEnv(newid, getRoomEnv(oldid)) end

  return string.format(&quot;Created new room %d at %dx,%dy,%dz.&quot;, newid, x,y,z)
end

-- gives the reverse shifted coordinates, ie asking for the sw exit + coords will give the coords at ne
local function getshiftedcoords(original,ox,oy,oz)
  local x,y,z
  local has = table.contains

  -- reverse the exit
  w = mmp.ranytolong(original)

  if has({&quot;west&quot;, &quot;left&quot;, &quot;w&quot;, &quot;l&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy); z = (z or oz)
  elseif has({&quot;east&quot;, &quot;right&quot;, &quot;e&quot;, &quot;r&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy); z = (z or oz)
  elseif has({&quot;north&quot;, &quot;top&quot;, &quot;n&quot;, &quot;t&quot;}, w) then
    x = (x or ox); y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;south&quot;, &quot;bottom&quot;, &quot;s&quot;, &quot;b&quot;}, w) then
    x = (x or ox); y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;northwest&quot;, &quot;topleft&quot;, &quot;nw&quot;, &quot;tl&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;northeast&quot;, &quot;topright&quot;, &quot;ne&quot;, &quot;tr&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy) + 1; z = (z or oz)
  elseif has({&quot;southeast&quot;, &quot;bottomright&quot;, &quot;se&quot;, &quot;br&quot;}, w) then
    x = (x or ox) + 1; y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;southwest&quot;, &quot;bottomleft&quot;, &quot;sw&quot;, &quot;bl&quot;}, w) then
    x = (x or ox) - 1; y = (y or oy) - 1; z = (z or oz)
  elseif has({&quot;up&quot;, &quot;u&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) + 1
  elseif has({&quot;down&quot;, &quot;d&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) - 1
  elseif has({&quot;in&quot;, &quot;i&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) - 1
  elseif has({&quot;out&quot;, &quot;o&quot;}, w) then
    x = (x or ox); y = (y or oy); z = (z or oz) + 1
  else
    mmp.echo(&quot;Don't know where to shift the coordinates for a &quot;..tostring(w)..&quot; (&quot;..tostring(original)..&quot;) exit.&quot;)
  end

  return x,y,z
end

function mmp_mapping_newroom(_, num)
local s,m = xpcall(function ()
  if not mmp.editing then return end
  if not gmcp.Room then
    mmp.echo(&quot;You need to have GMCP turned on (see preferences on a recent Mudlet) for mapping stuff.&quot;)
    return
  end

  local num = tonumber(num) or tonumber(gmcp.Room.Info.num)
  local currentexits = gmcp.Room.Info.exits
  local s = &quot;&quot;

  if not mmp.roomexists(num) then
    -- two-step method: if we can't determine a link via GMCP, we'll do it via last dir
    -- see if we can create and link this room with an existing one
    for exit, id in pairs(currentexits) do
      if mmp.roomexists(id) then
        s = makeroom(id, num, getshiftedcoords(exit, getRoomCoordinates(id)))
      end
    end

  end

  -- if we created it, and some data could be filled in
  if mmp.roomexists(num) then
    -- update room name
    local rootroomname = gmcp.Room.Info.name
    if string.starts(rootroomname, &quot;Flying above &quot;) then
      rootroomname = string.sub(rootroomname, -(#rootroomname-13))
    end
    if string.starts(rootroomname, &quot;The ruins of &quot;) then
      rootroomname = string.sub(rootroomname, -(#rootroomname-13))
    end
    if string.ends(rootroomname, &quot; (road)&quot;) then
      rootroomname = string.sub(rootroomname, 1, (#rootroomname-7))
    end
    if string.ends(rootroomname, &quot;.&quot;) then
      rootroomname = string.sub(rootroomname, 1, (#rootroomname-1))
    end

    if getRoomName(num):lower() ~= string.lower(rootroomname) then
      setRoomName(num, rootroomname)
      unHighlightRoom(num)
      s = s .. (#s &gt; 0 and &quot; &quot; or &quot;&quot;) .. &quot;Updated room name to '&quot;..rootroomname..&quot;'.&quot;
    end

    -- autolink exits
    local x = getRoomExits(num) or {}
    -- check for missing exits
    for exit, id in pairs(currentexits) do
      if id == 0 then
        s = s .. (#s &gt; 0 and &quot; &quot; or &quot;&quot;) .. &quot;Can't link to the &quot;..exit..&quot;, it leads to a room with ID 0 (and that's not supported yet).&quot;
      else
        if not x[mmp.anytolong(exit)] then
          if not mmp.roomexists(id) then
            s = makeroom(num, id, getshiftedcoords(mmp.ranytolong(exit), getRoomCoordinates(num)))
          end
          if setExit(num, id, exit) then
            s = s .. (#s &gt; 0 and &quot; &quot; or &quot;&quot;) .. &quot;Added missing exit &quot;..exit..&quot; to &quot;..(getRoomName(id) ~= &quot;&quot; and getRoomName(id) or &quot;''&quot;)..&quot; (&quot;..id..&quot;).&quot;
          else
            s = s .. (#s &gt; 0 and &quot; &quot; or &quot;&quot;) .. string.format(&quot;Failed to link %d withh %d via %s exit for some reason :/&quot;, num, id, exit)
          end
        end
      end
    end

    -- check for unexisting exits
    if mmp.settings[&quot;autoclear&quot;] then
      for exit, id in pairs(getRoomExits(num)) do
        if not currentexits[mmp.anytoshort(exit)] then
          setExit(num, -1, exit)
          s = s .. (#s &gt; 0 and &quot; &quot; or &quot;&quot;) .. exit .. &quot; exit to &quot;..id..&quot; doesn't actually exist, removed it.&quot;
        end
      end
    end

    -- check for environment update, if we have environments mapped out
    if mmp.envids[gmcp.Room.Info.environment] and mmp.envids[gmcp.Room.Info.environment] ~= getRoomEnv(num) then
      setRoomEnv(num, mmp.envids[gmcp.Room.Info.environment])
      s = s .. (#s &gt; 0 and &quot; &quot; or &quot;&quot;) .. &quot;Updated environment name to &quot;..gmcp.Room.Info.environment..&quot;.&quot;
    end

    -- check indoors status
    local indoors = table.contains(gmcp.Room.Info.details, &quot;indoors&quot;)
    if indoors and getRoomUserData(num, &quot;indoors&quot;) == '' then
      setRoomUserData(num, &quot;indoors&quot;, &quot;y&quot;)
      s = s .. (#s &gt; 0 and &quot; &quot; or &quot;&quot;) .. &quot;Updated room to be indoors.&quot;
    elseif not indoors and getRoomUserData(num, &quot;indoors&quot;) ~= '' then
      setRoomUserData(num, &quot;indoors&quot;, &quot;&quot;)
      s = s .. (#s &gt; 0 and &quot; &quot; or &quot;&quot;) .. &quot;Updated room to be outdoors.&quot;
    end
  end

  if #s &gt; 0 then mmp.echo(s); centerview(mmp.currentroom) end
end, function (error)
  mmp.echo(&quot;Oops! Has a small problem (&quot;..error..&quot;).&quot;)
  echo&quot;  &quot; echoLink(&quot;view steps&quot;, 'echo[['..debug.traceback()..']]', &quot;View steps of code that led up to it&quot;)
end)
if not s then mmp.echo(m) end
end</script>
                    <eventHandlerList>
                        <string>gmcp.Room.Info</string>
                        <string>RoomNum</string>
                    </eventHandlerList>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>mmp_track_exits</name>
                    <packageName></packageName>
                    <script>function mmp_track_exits(_, cmd)
  if not mmp.editing then return end

  local dir = mmp.anytolong(cmd)
  if not dir then return end

  mmp.lastdir = dir
end</script>
                    <eventHandlerList>
                        <string>sysDataSendRequest</string>
                    </eventHandlerList>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>mmp_save_options</name>
                    <packageName></packageName>
                    <script>function mmp_save_options()
	local saveTable = {
		locked_areas = mmp.locked,
		options = mmp.settings:getAllOptions()
	}

	if string.char(getMudletHomeDir():byte()) == &quot;/&quot; then _sep = &quot;/&quot; else  _sep = &quot;\\&quot; end
	local saveFile = getMudletHomeDir() ..  _sep .. &quot;mapper.options.lua&quot;

	table.save(saveFile, saveTable)
end</script>
                    <eventHandlerList>
                        <string>sysExitEvent</string>
                    </eventHandlerList>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>mmp_load_options</name>
                    <packageName></packageName>
                    <script>function mmp_load_options()
	local loadTable = mmp_load_locks()

	if loadTable.options then
		for k, v in pairs(loadTable.options) do
			mmp.settings:setOption(k, v, true)
		end
	end
end

function mmp_load_locks()
	local loadTable = {}

	if string.char(getMudletHomeDir():byte()) == &quot;/&quot; then _sep = &quot;/&quot; else  _sep = &quot;\\&quot; end
	local loadFile = getMudletHomeDir() ..  _sep .. &quot;mapper.options.lua&quot;

	table.load(loadFile, loadTable)

	if loadTable.locked_areas then
		mmp.locked = loadTable.locked_areas
	end

	for area in pairs(mmp.locked) do
		local rooms = getAreaRooms(area)
		for _, roomid in pairs(rooms or {}) do
			lockRoom(roomid, true)
		end
	end

	return loadTable
end</script>
                    <eventHandlerList>
                        <string>sysLoadEvent</string>
                    </eventHandlerList>
                </Script>
            </ScriptGroup>
            <Script isActive="yes" isFolder="no">
                <name>mmp_regenerate_areas</name>
                <packageName></packageName>
                <script>function mmp_regenerate_areas()
  -- cached data
  mmp.areatable = getAreaTable() -- this translates an area name to an ID
  mmp.areatabler = {} -- this translates an ID to an area name

  local t = getAreaTable()
  for k,v in pairs(t) do
    mmp.areatabler[tonumber(v)] = k
  end
end</script>
                <eventHandlerList>
                    <string>mmp areas changed</string>
                    <string>sys2DMapLoad</string>
                    <string>sys3DMapLoad</string>
                </eventHandlerList>
            </Script>
            <Script isActive="yes" isFolder="no">
                <name>mmp_relock_areas</name>
                <packageName></packageName>
                <script>function mmp_relock_areas()
	for area in pairs(mmp.locked) do
		local rooms = getAreaRooms(area) or {}
		for _, roomid in pairs(rooms) do
			lockRoom(roomid, true)
		end
	end
end</script>
                <eventHandlerList>
                    <string>sysMapLoad</string>
                </eventHandlerList>
            </Script>
            <ScriptGroup isActive="yes" isFolder="yes">
                <name>Game-specific</name>
                <packageName></packageName>
                <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                <eventHandlerList/>
                <Script isActive="yes" isFolder="no">
                    <name>Achaea</name>
                    <packageName></packageName>
                    <script></script>
                    <eventHandlerList/>
                    <Script isActive="yes" isFolder="no">
                        <name>register_achaeas_envdata</name>
                        <packageName></packageName>
                        <script>function register_achaeas_envdata(_, game)
  if game ~= &quot;Achaea&quot; then return end

  mmp.envids =
  {
    Path = 11,
    Sewer = 23,
    Freshwater = 22,
    [&quot;Natural underground&quot;] = 3,
    [&quot;Magma Caves&quot;] = 31,
    Polar = 27,
    Nothing = 0,
    [&quot;Constructed underground&quot;] = 2,
    Ruins = 32,
    Blighted = 29,
    Forest = 4,
    Tundra = 16,
    [&quot;Tsol'aa city&quot;] = 19,
    [&quot;Dwarven city&quot;] = 18,
    Jungle = 17,
    Ocean = 20,
    River = 10,
    Mountains = 14,
    [&quot;Deep Ocean&quot;] = 24,
    Desert = 6,
    Garden = 21,
    Swamp = 15,
    Road = 12,
    Water = 30,
    Grasslands = 7,
    Valley = 13,
    Reef = 25,
    Hills = 9,
    Vessel = 36,
    Beach = 5,
    Urban = 8,
    Trees = 28,
    [&quot;Ocean floor&quot;] = 34
  }

  mmp.envidsr = {};
  for name, id in pairs(mmp.envids) do mmp.envidsr[id] = name end
end</script>
                        <eventHandlerList>
                            <string>mmp logged in</string>
                        </eventHandlerList>
                    </Script>
                    <Script isActive="yes" isFolder="no">
                        <name>mmapper_achaea_went_outside</name>
                        <packageName></packageName>
                        <script>-- track whenever we need to use wings when we get outside!
function mmapper_achaea_went_outside()
local s,m = pcall(function()

  if not mmp.autowalking or not (mmp.settings.duanathar or mmp.settings.duanatharan) or mmp.game ~= &quot;achaea&quot; or 
    (mmp.currentroom == mmp.speedWalkPath[#mmp.speedWalkPath]) or
    not mmp.oncontinent(getRoomArea(mmp.currentroom), &quot;Prime&quot;) then return end

  -- repath, maybe that'll allow us to use wings now.
  local madeduanatharan, madeduanathar

  local function getcmd(word)
    return mmp.settings.removewings and 
      [[script:sendAll(&quot;wear wings&quot;, &quot;say *]]..(mmp.settings.winglanguage)..[[ ]]..word..[[&quot;, &quot;remove wings&quot;, false)]]
      or
      [[script:send(&quot;say *]]..(mmp.settings.winglanguage)..[[ ]]..word..[[&quot;, false)]]
  end

    if mmp.settings.duanatharan then
      addSpecialExit(mmp.currentroom, 4882, getcmd(&quot;duanatharan&quot;))
      addSpecialExit(mmp.currentroom, 3885, getcmd(&quot;duanathar&quot;))
      mmp.clearpathcache() -- clear cache so mmp.getPath accounts for the new way
      madeduanatharan = true
    else
      addSpecialExit(mmp.currentroom, 3885, getcmd(&quot;duanathar&quot;))
      mmp.clearpathcache() -- clear cache so mmp.getPath accounts for the new way
      madeduanathar = true
    end

  mmp.getPath(mmp.currentroom, mmp.speedWalkPath[#mmp.speedWalkPath]) -- don't need to check return value since that fact shouldnt've changed
  
  -- if our path didn't change, re-instate it as it was (since the new path starts from this room that we checked at)
  if speedWalkDir[1]:find(&quot;duanathar&quot;, 1, true) then
    speedWalkCounter = 0
    mmp.echo(&quot;We got outside - going to shortcut with wings.&quot;)
    mmp.gotoRoom(mmp.speedWalkPath[#mmp.speedWalkPath])
    mmp.ignore_speedwalking = true
  end

  if madeduanatharan then mmp.clearspecials{4882, 3885} elseif madeduanathar then mmp.clearspecials{3885} end
end)
if not s then display(m) end
end</script>
                        <eventHandlerList>
                            <string>mmapper went outside</string>
                        </eventHandlerList>
                    </Script>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>Aetolia</name>
                    <packageName></packageName>
                    <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                    <eventHandlerList/>
                    <Script isActive="yes" isFolder="no">
                        <name>register_aetolias_envdata</name>
                        <packageName></packageName>
                        <script>function register_aetolias_envdata(_, game)
  if game ~= &quot;Aetolia&quot; then return end

  mmp.envids =
  {
    Chaos = 1,
    [&quot;Constructed underground&quot;] = 2,
    [&quot;Natural underground&quot;] = 3,
    Forest = 4,
    Beach = 5,
    Desert = 6,
    Grasslands = 7,
    Urban = 8,
    Hills = 9,
    River = 10,
    Path = 11,
    Road = 12,
    Valley = 13,
    Mountains = 14,
    Swamp = 15,
    Tundra = 16,
    Jungle = 17,
    [&quot;Tsol'aa city&quot;] = 19,
    Ocean = 20,
    Garden = 21,
    Freshwater = 22,
    Sewer = 23,
    [&quot;Deep ocean&quot;] = 24,
    Reef = 25,
    Ruins = 26,
    Village = 27,
    [&quot;Underwater city&quot;] = 28,
    Temple = 29,
    Ice = 30,
    Graveyard = 31,
    Mines = 32,
    Onboard = 33,
    Canyon = 34,
    [&quot;within a tree&quot;] = 36,
    Crater = 37,
    lava = 39,
    [&quot;lifeless sands&quot;] = 54,
    [&quot;a bridge&quot;] = 55,
    [&quot;logged forest&quot;] = 56,
    [&quot;camp site&quot;] = 57,
    Shadows = 58,
    Castle = 61,
    [&quot;Airship wreckage&quot;] = 62,
    Ethereal = 67,
    Cavern = 69,
    grotto = 70,
  }

  mmp.envidsr = {};
  for name, id in pairs(mmp.envids) do mmp.envidsr[id] = name end
end</script>
                        <eventHandlerList>
                            <string>mmp logged in</string>
                        </eventHandlerList>
                    </Script>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>Lusternia</name>
                    <packageName></packageName>
                    <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                    <eventHandlerList/>
                    <Script isActive="yes" isFolder="no">
                        <name>register_lusternias_envdata</name>
                        <packageName></packageName>
                        <script>function register_lusternias_envdata(_, game)
  if game ~= &quot;Lusternia&quot; then return end

  mmp.envids =
  {
    darkness = 1,
    [&quot;constructed underground&quot;] = 2,
    [&quot;natural underground&quot;] = 3,
    forest = 4,
    beach = 5,
    desert = 6,
    grasslands = 7,
    urban = 8,
    hills = 9,
    river = 10,
    path = 11,
    road = 12,
    valley = 13,
    mountains = 14,
    swamp = 15,
    tundra = 16,
    jungle = 17,
    flesh = 18,
    ruins = 19,
    ocean = 20,
    garden = 21,
    freshwater = 22,
    sewer = 23,
    [&quot;deep ocean&quot;] = 24,
    reef = 25,
    polar = 27,
    trees = 28,
    wasteland = 29,
    farmlands = 30,
    volcanic = 32,
    divine = 33,
    netherworld = 34,
    astral = 35,
    aether = 36,
    clouds = 37,
    concordance = 38,
    chaos = 39,
  }

  mmp.envidsr = {};
  for name, id in pairs(mmp.envids) do mmp.envidsr[id] = name end
end</script>
                        <eventHandlerList>
                            <string>mmp logged in</string>
                        </eventHandlerList>
                    </Script>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>Imperian</name>
                    <packageName></packageName>
                    <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                    <eventHandlerList/>
                    <Script isActive="yes" isFolder="no">
                        <name>register_imperians_envdata</name>
                        <packageName></packageName>
                        <script>function register_imperians_envdata(_, game)
  if game ~= &quot;Imperian&quot; then return end
  mmp.envids =
  {
    [&quot;Dark Forest&quot;] = 1,
    [&quot;Constructed underground&quot;] = 2,
    [&quot;Natural underground&quot;] = 3,
    Forest = 4,
    Beach = 5,
    Desert = 6,
    Grasslands = 7,
    Urban = 8,
    Hills = 9,
    River = 10,
    Path = 11,
    Road = 12,
    Valley = 13,
    Mountains = 14,
    Swamp = 15,
    Tundra = 16,
    Jungle = 17,
    [&quot;Dwarven city&quot;] = 18,
    [&quot;Sylayan city&quot;] = 19,
    Ocean = 20,
    Garden = 21,
    Freshwater = 22,
    Sewer = 23,
    [&quot;Deep Ocean&quot;] = 24,
    [&quot;Vast Ocean&quot;] = 26,
    Polar = 27,
    Underworld = 28,
    Docks = 30,
    Warrens = 31,
    Crags = 32,
    Acropolis = 33,
    [&quot;Tainted Underground&quot;] = 35,
    [&quot;Underground Lake&quot;] = 36,
    Ruins = 37,
    [&quot;Desert Ruins&quot;] = 38,
    [&quot;Tainted Water&quot;] = 39,
    Farmland = 41,
    Academia = 42,
    [&quot;Forestal Council&quot;] = 44,
    Graveyard = 46,
    Village = 47,
    transportation = 48,
    Pond = 49,
    Nobility = 50,
    [&quot;Noble Chambers&quot;] = 51,
    [&quot;Noble Bar&quot;] = 53,
    Church = 54,
    Village = 55,
    [&quot;Lake of Fire&quot;] = 56,
    Temple = 57,
    [&quot;Blackened Lands&quot;] = 58,
    Volcano = 59,
    [&quot;Blackstone Keep&quot;] = 62,
    Catacombs = 63,
    [&quot;Wetlands Village&quot;] = 64,
    [&quot;Blackstone Dungeon&quot;] = 65,
    [&quot;Arcane Temple&quot;] = 66,
    Cliffs = 67,
    [&quot;a sheltered dell&quot;] = 68,
    [&quot;within a tent&quot;] = 69,
    quarry = 70,
    garrison = 71,
    pyramid = 72,
    bog = 73,
    Blighted = 74,
    Villa = 75,
    [&quot;Frozen Bog&quot;] = 76,
    [&quot;Rocky Shore&quot;] = 77,
    Scrublands = 78,
    Tower = 79,
  }

  mmp.envidsr = {};
  for name, id in pairs(mmp.envids) do mmp.envidsr[id] = name end
end</script>
                        <eventHandlerList>
                            <string>mmp logged in</string>
                        </eventHandlerList>
                    </Script>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>Midmekia Online</name>
                    <packageName></packageName>
                    <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                    <eventHandlerList/>
                    <Script isActive="yes" isFolder="no">
                        <name>register_midkemias_envdata</name>
                        <packageName></packageName>
                        <script>function register_midkemias_envdata(_, game)
  if game ~= &quot;Midkemia Online&quot; then return end
  mmp.envids =
  {
    [&quot;constructed underground&quot;] = 2,
    [&quot;natural underground&quot;] = 3,
    forest = 4,
    beach = 5,
    grasslands = 7,
    urban = 8,
    hills = 9,
    river = 10,
    path = 11,
    road = 12,
    valley = 13,
    mountains = 14,
    swamp = 15,
    tundra = 16,
    ocean = 18,
    garden = 19,
    [&quot;fresh water&quot;] = 20,
    sewers = 21,
    reef = 23,
    ruins = 24,
    village = 25,
    temple = 26,
    ice = 27,
    mines = 28,
    canyon = 29,
    plains = 30,
    farmlands = 31,
    volcanic = 32,
    [&quot;shores of Lake Moraelin&quot;] = 33,
  }

  mmp.envidsr = {};
  for name, id in pairs(mmp.envids) do mmp.envidsr[id] = name end
end</script>
                        <eventHandlerList>
                            <string>mmp logged in</string>
                        </eventHandlerList>
                    </Script>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>Lithmeria</name>
                    <packageName></packageName>
                    <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                    <eventHandlerList/>
                    <Script isActive="yes" isFolder="no">
                        <name>register_lithmerias_envdata</name>
                        <packageName></packageName>
                        <script>function register_lithmerias_envdata(_, game)
  if game ~= &quot;Lithmeria&quot; then return end

  mmp.envids =
  {
		beach = 11,
		shallowwater = 4,
		river = 4,
		water = 4,
		[&quot;deep water&quot;] = 4,
		bridge = 6,
		ocean = 4,
		underground = 8,
		cliffs = 1,
		mountain = 1,
		plains = 3,
		forest = 2,
		road = 6,
		urban = 8,
		building = 13,
		tundra = 7,
		swamp = 2,
		jungle = 10,
		desert = 11,
        highway = 6,
        path = 6,
  }
  for name, number in pairs(mmp.envids) do
    mmp.envids[name] = number+256 -- adjust for in-built colors
  end

  mmp.envidsr = {};
  for name, id in pairs(mmp.envids) do mmp.envidsr[id] = name end
end</script>
                        <eventHandlerList>
                            <string>mmp logged in</string>
                        </eventHandlerList>
                    </Script>
                </Script>
            </ScriptGroup>
            <ScriptGroup isActive="yes" isFolder="yes">
                <name>Test / one-time things</name>
                <packageName></packageName>
                <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                <eventHandlerList/>
                <Script isActive="no" isFolder="no">
                    <name>mmp_grabenvid</name>
                    <packageName></packageName>
                    <script>function mmp_grabenvid()
  if not mmp.envids[gmcp.Room.Info.environment] then
    mmp.envids[gmcp.Room.Info.environment] = getRoomEnv(mmp.currentroom)
    mmp.echo(string.format(&quot;Remembered environment %s as %d&quot;, gmcp.Room.Info.environment, mmp.envids[gmcp.Room.Info.environment]))
  end
end

function mmp.getMaxID()
  local roomIDs = {}
  for area, _ in pairs(mmp.areatabler) do
    local ok, t = pcall(getAreaRooms, area)
    if ok then
      for _, id in pairs(t or {}) do
        roomIDs[id] = true
      end
    end
  end

  return table.maxn(roomIDs)
end

function mmp.getUnknownEnvs()
  local maxid, missing = mmp.getMaxID(), {}

  for i = 1, maxid do
    if mmp.roomexists(i) then
      if not table.contains(mmp.envids, getRoomEnv(i)) and not table.contains(missing, getRoomEnv(i)) then
        mmp.echo(string.format(&quot;Missing env %d from room %d ('%s' in '%s')&quot;,
          tostring(getRoomEnv(i)), i, tostring(getRoomName(i)), tostring(mmp.areatabler[getRoomArea(i)])))
        missing[i] = getRoomEnv(i)
      end
    end
  end
end</script>
                    <eventHandlerList>
                        <string>gmcp.Room.Info</string>
                    </eventHandlerList>
                </Script>
            </ScriptGroup>
            <ScriptGroup isActive="yes" isFolder="yes">
                <name>Check for map updates</name>
                <packageName></packageName>
                <script>-------------------------------------------------
--         Put your Lua functions here.        --
--                                             --
-- Note that you can also use external Scripts --
-------------------------------------------------
</script>
                <eventHandlerList/>
                <Script isActive="yes" isFolder="no">
                    <name>mmp_downloaded_file</name>
                    <packageName></packageName>
                    <script> function mmp_downloaded_file(_, filename)
local s,m = pcall(function()
  if not io.exists(filename) then return end

  if filename == tostring(mmp.mapperfile) then   -- mapper script version
	mmp.checkingupdates = false

    local f, s = io.open(filename)
    if f then s = f:read(&quot;*l&quot;):trim(); io.close(f) end
    
    if s ~= tostring(mmp.version) then
      mmp.newmapperversion = s
      mmp.retrievechangelog()
    end

  elseif filename == tostring(mmp.changelogfile) then   -- changelog for the mapper script
	mmp.checkingupdates = false

    local f, s = io.open(filename)
    if f then s = f:read(&quot;*a&quot;); io.close(f) end

    local changelog = string.match(s, [[&lt;div class=&quot;information&quot;&gt;(.-)&lt;/div]])
    changelog = string.gsub(changelog, &quot;Â&quot;, '')
    changelog = string.gsub(changelog, &quot;&lt;br/&gt;&quot;, '\n')
    changelog = string.gsub(changelog, &quot;&amp;#39;&quot;, &quot;'&quot;)
    mmp.echon(&quot;&quot;)
    echoLink(&quot;The mapper script was updated! Would you like to download the update? Click here if so.&quot;, &quot;mmp.downloadmapperscript()&quot;, &quot;Changelog for the latest (&quot;..tostring(mmp.version)..&quot; -&gt; &quot;..tostring(mmp.newmapperversion)..&quot;) update:\n&quot;..changelog, true)

  elseif filename == mmp.crowdchangelogfile then   -- changelog for the crowdmap
    local f, s = io.open(filename)
    if f then s = f:read(&quot;*a&quot;); io.close(f) end

    -- make environment
    local env = {} -- add functions you know are safe here

    -- run code under environment [Lua 5.1]
    local function run(untrusted_code)
      if untrusted_code:byte(1) == 27 then return nil, &quot;binary bytecode prohibited&quot; end
      local untrusted_function, message = loadstring(untrusted_code)
      if not untrusted_function then return nil, message end
      setfenv(untrusted_function, env)
      return pcall(untrusted_function)
    end

    run(s)

	mmp.crowdchangelog = env.changelog

    mmp.echon(&quot;The public map was &quot;)
    echoLink(&quot;updated&quot;, '', &quot;New version: &quot;..tostring(mmp.newversion)..&quot;, previous version: &quot;..(mmp.oldversion or &quot;(none)&quot;), true)
    echo(&quot; (&quot;)
    echoLink(&quot;changelog&quot;, &quot;mmp.showcrowdchangelog()&quot;, 'View the full changelog for mappers')
    echo(&quot;)\n&quot;)

    mmp.downloadcrowdmap(mmp.newversion)

  elseif filename == mmp.crowdmapfile then    -- crowdmap map
    mmp.echo(&quot;Map downloaded, loading it in...&quot;)

    local tmp = getRoomUserData(1, &quot;gotoMapping&quot;)
    local oldmaptable = {}

    if tmp ~= &quot;&quot; then
      oldmaptable = yajl.to_value(tmp)
    end

    local ok = loadMap(filename)

    if ok then
      local wc = mmp.lockWormholes()
	  local ws = mmp.lockSewers()
      if mmp.game == &quot;achaea&quot; and wc == 0 and ws == 0 then -- in achaea, using crowdmap, if we didn't get any special exits - it means Mudlet needs to be updated
        mmp.echo(&quot;Sorry, it seems your Mudlet isn't compatible with the new crowdmap format - and the map cannot be loaded fully. Please update your Mudlet: http://svo.vadisystems.com/2012/08/crowdmap-fix-in-achaea/&quot;)
        return
      end
      
      mmp.echo(&quot;Map loaded fine - enjoy!&quot;)

      tmp = getRoomUserData(1, &quot;gotoMapping&quot;)
      local newmaptable = {}
      
      if tmp ~= &quot;&quot; then
        newmaptable = yajl.to_value(tmp)
      end

      for k,v in pairs(oldmaptable) do newmaptable[k] = v end
      setRoomUserData(1, &quot;gotoMapping&quot;, yajl.to_string(newmaptable))
      mmp.echo(&quot;Marks from the old map migrated successfully.&quot;)
    else
      mmp.echon(&quot;Map failed to load - you need to have the mapper open. Please open it, and then &quot;)
      echoLink(&quot;click here&quot;, [[
        local tmp = getRoomUserData(1, &quot;gotoMapping&quot;)
        local oldmaptable = {}
        if tmp ~= &quot;&quot; then
          oldmaptable = yajl.to_value(tmp)
        end

        local ok = loadMap(']]..filename..[[')
        if ok then
        local wc = mmp.lockWormholes()
	    local ws = mmp.lockSewers()
        if mmp.game == &quot;achaea&quot; and wc == 0 and ws == 0 then -- in achaea, using crowdmap, if we didn't get any special exits - it means Mudlet needs to be updated
          mmp.echo(&quot;Sorry, it seems your Mudlet isn't compatible with the new crowdmap format - and the map cannot be loaded fully. Please update your Mudlet: http://svo.vadisystems.com/2012/08/crowdmap-fix-in-achaea/&quot;)
          return
        end
        
        mmp.echo(&quot;Map loaded successfully!&quot;)

          tmp = getRoomUserData(1, &quot;gotoMapping&quot;)
          local newmaptable = {}      
          if tmp ~= &quot;&quot; then
            newmaptable = yajl.to_value(tmp)
          end
          for k,v in pairs(oldmaptable) do newmaptable[k] = v end
          setRoomUserData(1, &quot;gotoMapping&quot;, yajl.to_string(newmaptable))
          mmp.echo(&quot;Marks from the old map migrated successfully.&quot;)
        else mmp.echo(&quot;Nope, didn't work. Open the map and try again?&quot;) end
      ]], 
      &quot;Click here to try loading the map again&quot;)
      echo(&quot; to try loading it in again.\n&quot;)
    end

  elseif filename == tostring(mmp.downloadedscript) then   -- new mapper script xml downloaded
	mmp.checkingupdates = false

    mmp.echo(&quot;Your mapper script was downloaded to '&quot;..filename..&quot;' - uninstall the current copy and install the new one now!&quot;)

  elseif filename == tostring(mmp.mapfile) then   -- map version #, either IRE's or crowd
	mmp.checkingupdates = false

    local function needupdate(currentmd5, oldmd5)
      if not mmp.settings.crowdmap then
        mmp.echon(&quot;The games map was &quot;)
        echoLink(&quot;updated&quot;, '', &quot;New MD5: &quot;..tostring(currentmd5)..&quot;, previous MD5: &quot;..(oldmd5 or &quot;(none)&quot;), true)
        echo(&quot; - you should update yours! Go to Settings -&gt; Special Options tab and click on the button there. Once you've updated, &quot;)
        echoLink(&quot;click here&quot;, &quot;mmp.updatedmap('&quot;..currentmd5..&quot;')&quot;, &quot;Click here to quiet the update reminder&quot;)
        echo(&quot; to remove the reminder.&quot;)
      else
        mmp.newversion, mmp.oldversion = currentmd5, oldmd5
        mmp.retrievecrowdchangelog()
      end
    end

    local f, s = io.open(filename)
    if f then s = f:read(&quot;*a&quot;); io.close(f) end
    local currentmd5 = string.match(s, &quot;([a-z0-9]+)  map%.xml&quot;)

    -- using crowdsourced map
    if not currentmd5 then
      currentmd5 = s:trim()
    end

	os.remove(filename)

    -- never checked yet?
    if not io.exists(getMudletHomeDir()..&quot;/map downloads/current&quot;) then needupdate(currentmd5) return end

    -- otherwise read old file and check
    local f, s = io.open(getMudletHomeDir()..&quot;/map downloads/current&quot;)
    if f then s = f:read(&quot;*a&quot;); io.close(f) end

    if s ~= currentmd5 then needupdate(currentmd5, s) end
  end
end)
if not s then display(m) end
end</script>
                    <eventHandlerList>
                        <string>sysDownloadDone</string>
                    </eventHandlerList>
                </Script>
                <Script isActive="yes" isFolder="no">
                    <name>Check for updates</name>
                    <packageName></packageName>
                    <script>local downloadfolder = getMudletHomeDir()..&quot;/map downloads/&quot;
local whereisit

-- this should get called at start and every hour after that
function mmp.checkforupdate()
  if not mmp.game or mmp.checkingupdates then return end

  local game = (mmp.game == &quot;mko&quot;) and &quot;midkemiaonline&quot; or mmp.game
  mmp.mapfile = downloadfolder..&quot;MD5&quot;
  mmp.mapperfile = downloadfolder..&quot;mapper&quot;

  if not downloadFile then
    mmp.echo(&quot;Your version of Mudlet doesn't support downloading files - please upgrade to 2.0+&quot;)
  else
    if not lfs.attributes(downloadfolder) then
      if lfs and lfs.mkdir then
         local t,s = lfs.mkdir(downloadfolder)
         if not t and s ~= &quot;File exists&quot; then mmp.echo(&quot;Couldn't make the '&quot;..downloadfolder..&quot;' folder; &quot;..s) return end
      else
        mmp.echo(&quot;Sorry, but you need LuaFileSystem (lfs) installed, or have the '&quot;..downloadfolder..&quot;' folder exist.&quot;)
        return
      end
    end

    if mmp.settings.crowdmap and mmp.game and mmp.game == &quot;achaea&quot; then
      downloadFile(mmp.mapfile, &quot;http://dl.dropbox.com/s/iqk5bf905iox0k9/version.txt?dl=1&quot;)
    else
      downloadFile(mmp.mapfile, &quot;http://www.&quot;..game..&quot;.com/maps/MD5SUM&quot;)
    end

    downloadFile(mmp.mapperfile, &quot;http://bazaar.launchpad.net/~mudlet-makers/mudlet/mapper-lua/download/head:/version-20110910005237-2917fpevgi4koxqk-1/version&quot;)
	mmp.checkingupdates = true
  end
end

-- called by the user when the map is updated to register the fact that it was
function mmp.updatedmap(currentmd5)
  assert(currentmd5, &quot;need md5 sum to write to file&quot;)

  local f,err = io.open(downloadfolder..&quot;current&quot;, &quot;w&quot;)
  if not f then return mmp.echo(&quot;Couldn't write to the update file, because: &quot;..err) end
  f:write(currentmd5)
  f:close()

  local t = {&quot;Go you for updating!&quot;, &quot;Thanks for updating the map!&quot;, &quot;Alright, map updated!&quot;}
  mmp.echo(t[math.random(1, #t)])
end

-- downloads the latest changelog for the mapper if it was updated
function mmp.retrievechangelog()
  mmp.changelogfile = downloadfolder..&quot;changelog&quot;

  downloadFile(mmp.changelogfile, &quot;http://bazaar.launchpad.net/~mudlet-makers/mudlet/mapper-lua/files&quot;)
end

function mmp.retrievecrowdchangelog()
  mmp.crowdchangelogfile = downloadfolder..&quot;crowdchangelogfile&quot;

  downloadFile(mmp.crowdchangelogfile, &quot;http://dl.dropbox.com/s/pu51s482csta8zj/changelog.txt?dl=1&quot;)
end

-- downloads the public crowdsources map!
function mmp.downloadmapperscript()
  local downloadlocationfile = downloadfolder..&quot;savepath&quot;
  local downloadlocation
  local exists = lfs.attributes

  -- somewhat complicated thing to nicely deal with all scenarios.
  if not exists(downloadlocationfile) then
    downloadlocation = whereisit()
    if not downloadlocation then return end
  end

  if not downloadlocation then
    local f, s = io.open(downloadlocationfile)
    if f then downloadlocation = f:read(&quot;*a&quot;); io.close(f) end


    if not exists(downloadlocation) then
      downloadlocation = whereisit()
      if not downloadlocation or not exists(downloadlocation) then return end
    end
  end


  mmp.downloadedscript = downloadlocation..&quot;/mudlet-mapper.xml&quot;
  downloadFile(mmp.downloadedscript, &quot;http://bazaar.launchpad.net/~mudlet-makers/mudlet/mapper-lua/download/head:/mudletmapper.xml-20100916000616-71kbxngi7b3nybta-1/mudlet-mapper.xml&quot;)

  local f,err = io.open(downloadlocationfile, &quot;w&quot;)
  if not f then return mmp.echo(&quot;Couldn't write to the location file, because: &quot;..err) end
  f:write(downloadlocation)
  f:close()
  mmp.echo(&quot;Okay, downloading the mapper script...&quot;)
end

function mmp.downloadcrowdmap(newversion)
  mmp.crowdmapfile = downloadfolder..&quot;crowdmap&quot;

  local f,err = io.open(downloadfolder..&quot;current&quot;, &quot;w&quot;)
  if not f then return mmp.echo(&quot;Couldn't write to the update file, because: &quot;..err) end
  f:write(newversion)
  f:close()


  downloadFile(mmp.crowdmapfile, &quot;http://dl.dropbox.com/s/sbj9f1s1l4h7otg/map?dl=1&quot;)

  mmp.echo(&quot;Downloading the latest public map... please make sure you have the map open.&quot;)
end

function mmp.showcrowdchangelog()
  mmp.echo(&quot;Public map changelog:&quot;)

  if not mmp.crowdchangelog then mmp.echo(&quot;(none yet)&quot;) return end

  for k,v in ipairs(mmp.crowdchangelog) do
    cecho(string.format(&quot;  %s) %s\n&quot;, k,v:gsub(&quot;\t&quot;, &quot;     &quot;)))
  end
end

whereisit = function()
  local path = invokeFileDialog(false, &quot;Where should we save the file? Select a folder and click Open&quot;)

  if path == &quot;&quot; then return nil else return path end
end</script>
                    <eventHandlerList/>
                    <Script isActive="yes" isFolder="no">
                        <name>mmp_checkupdatestart</name>
                        <packageName></packageName>
                        <script>function mmp_checkupdatestart(...)
  if mmp.settings.updatemap then
    tempTimer(math.random(3, 10), mmp.checkforupdate)
  end
end

function mmp.changeUpdateMap()
  if mmp.settings.updatemap then
    mmp.echo(&quot;Will check for new map updates.&quot;)
    enableTimer&quot;Check for updates periodically&quot;
    mmp_checkupdatestart()
  else
    mmp.echo(&quot;Won't check for new map updates.&quot;)
    disableTimer&quot;Check for updates periodically&quot;
  end
end</script>
                        <eventHandlerList>
                            <string>mmp logged in</string>
                        </eventHandlerList>
                    </Script>
                </Script>
                <Script isActive="no" isFolder="no">
                    <name>mmp_see_dl_errors</name>
                    <packageName></packageName>
                    <script>-- this should be off by default
function mmp_see_dl_errors(...)
  display{...}
end</script>
                    <eventHandlerList>
                        <string>sysDownloadError</string>
                    </eventHandlerList>
                </Script>
            </ScriptGroup>
            <Script isActive="yes" isFolder="no">
                <name>Initialize</name>
                <packageName></packageName>
                <script>mmp.startup()</script>
                <eventHandlerList/>
            </Script>
        </ScriptGroup>
    </ScriptPackage>
    <KeyPackage/>
</MudletPackage>
