Exit/direction listing (tricky!)

Posted by Jakevanderpuy on Sun 16 Jan 2005 05:26 PM — 9 posts, 35,550 views.

#0
Basically, the problem I'm having is that when it comes to directions on my mud my mind flips east and west because of the way that the "Obvious exits:" exit/direction listing looks. I want to switch around the way it looks.


Example text sent by mud:
A circle of stones
            What was once a twisted, dark wood is now a crystal
    sss    landscape.  All of the trees have lost their foliage, and have
    -*s    been layered in a thick, glistening cover of ice.  The ground has
    vss    been covered in heavy snow, which refuses to show any signs of
           melting, despite the scorching temperatures.  Mixed in the snowy
landscape is the occassional frozen animal, frozen with a look of
terror to it.   It's clear, cool, and there is absolutely no wind.
Obvious exits: n e s w nw ne sw se rift
     A magical rift is glowing violently in the mid-air.
     A set of rune-inscribed stones frame the center of the clearing here.


So, the mud sends this line:
Obvious exits: n e s w nw ne sw se rift


Sometimes there are other exits like the rift listed above, or doorways and so forth. It'd be nice to just grab those while parsing the direction listing and tack them onto the new listing.

I know I'll need a trigger to do this, and I'll match on "Obvious exits:" Not entirely sure what kind of trigger, or if I'll be sending this to script or what, though.

I want to change the direction listing to look like the following:

Obvious exits: sw nw w n s e ne se



The main problems I'm having is that the exit listing isn't constant. Some rooms only have certain exits from them, like the following.

Foyer
  This small, spartanly furnished room serves as a guard post for the guard
house.  A legionnaire is posted here to make sure only authorized people
enter the barracks.  The only other feature is a large banner on the north
wall.
  Obvious exits: n(closed) w rift
     A pair of shin guards lies here unused.
     You see a pair of shoulder guards lying in the dirt.
     A metallic helm with a leather strap lies here.
     A collared shirt of chain mail lies here in a pile.
     A long barbed spear lies here shining on the ground.
     The corpse of a centaur is lying here.
     A magical rift is glowing violently in the mid-air.
(Ethereal) The ghost of a stern male human is flying here.
(Ethereal) The ghost of a rugged male centaur is flying here.
A legionnaire corporal is here on duty.


The second problem lies in figuring out how to parse for extra exits like "rift" and "door" and tack them onto the final "Obvious exits:" listing.
United Kingdom #1
Partial solution (because I just worked out that gmatch exists and I can't be btohered to re-write it :p):

Trigger:

<triggers>
  <trigger
   enabled="y"
   match="^ ? ?Obvious exits\: (.*)$"
   omit_from_output="y"
   regexp="y"
   script="OnObviousExits"
   sequence="95"
  >
  </trigger>
</triggers>



Scriptfile:

function explode(d,p)
	--p="abcd defg hijk lmnp"
	t={}
	ll=0
	while true do
		l=string.find(p,d,ll+1,true)
		if l~=nil then
			table.insert(t, string.sub(p,ll,l-1))
			ll=l+string.len(d)
		else
			table.insert(t, string.sub(p,ll))
			break
		end
	end
	--print_r(t)
	return t
end

function preg_replace(pat,with,p)
	while true do
		a=rex.new(pat) -- compile regexp
		x,y,t=a:match(p) -- match regexp
		if (x~=nil and y~=nil) then -- if we matched then
			p=string.sub(p,0,x-1).. with .. string.sub(p,y+1) -- rebuild the string
		else
			break
		end
	end
	return p
end

function table_contains(t,p)
	for a,v in pairs(t) do if v==p then return true end end
	return false
end

function OnObviousExits (name, trig_line, wildcards)
	a=wildcards[1]
	ss="Obvious exits: "
	a=preg_replace("\(.*?\)","", a) -- Remove the ()ed terms.
	t=explode(" ",a)
	if (table_contains(t,"sw")) then ss = ss .. "sw " end
	if (table_contains(t,"nw")) then ss = ss .. "nw " end
	if (table_contains(t,"w")) then ss = ss .. "w " end
	if (table_contains(t,"n")) then ss = ss .. "n " end
	if (table_contains(t,"s")) then ss = ss .. "s " end
	if (table_contains(t,"e")) then ss = ss .. "e " end
	if (table_contains(t,"ne")) then ss = ss .. "ne " end
	if (table_contains(t,"se")) then ss = ss .. "se " end
	a=preg_replace("\b(?:n|e|s|w|nw|ne|se|sw)\b","", a)
	ss = ss .. a
	Note(preg_replace("[ ][ ]+"," ",ss))
end
Amended on Mon 17 Jan 2005 04:31 AM by Faux
USA #2
I could be mistaken, but I believe that your table contains isn't necessary. I think you can just test the key's value against nil; if the value is nil the table does not contain it, and if non-nil, then the table does contain it. No need to iterate over the whole table.
United Kingdom #3
That doesn't work because of the way I've written explode (the way PHP explode works).

It returns an array like... t={"This","is","an","array"}, which is the same as... t={0="This",1="is",2="an",3="array"}.

Because of this, t["This"] == nil.

The only way to do it that way would to be to re-write explode so that it used something like.. table.insert(t,VALUE,true), meaning that it does actually use the VALUE as the key, instead of the value.

This'd return an array like.. t={"This"=true,"is"=true,"an"=true,"array"=true}.

ie. t["This"] == true.

Because of that extension to table.insert that I didn't know about, that isn't too hard to change, but I prefer to stick with pre-defined functions if at all possbile.
USA #4
What do you mean by 'predefined functions' that you want to stick with? Aren't you writing your own here anyhow?

Now that I think about it, even doing t.this = true wouldn't work, because you would lose the ordering of the array. Sure, you'd get a list of tokens, but they'd not necessarily be sorted the way you'd want them to i.e. the order in which they appear in the split text. Explode... what a funny name. :-) I betray my Perlness by using split and join, I suppose. :)

Anyhow that'll teach me to check out what kind of array the function is processing before making comments. :P
United Kingdom #5
Pre-defined functions are things that are already in my script file :)

And, on the split thing, it took me about 10 minutes to remember the name of the perl-compatiable version of explode (http://www.php.net/preg_split). Bah ;p
Greece #6
The PHP docs are about the best I've seen on a language, download the huge CHM file (I think that's what they call it), it's easy to find anything in there.
United Kingdom #7
I'd agree, I have the chm too, but searching neither the website nor the manual for "preg explode" (http://uk2.php.net/manual-lookup.php?pattern=preg+explode) nor the manual told me what I wanted to know.

Australia Forum Administrator #8
You can easily swap them from a number/value to key/true like this:


tbl = { "nick", "is", "a", "person" }

tbl2 = {}  --> new table

for _, v in tbl do tbl2 [v] = true end  --> convert table

print "tbl = "  
tprint (tbl)

print "tbl2 = "
tprint (tbl2)

Output
tbl = 
1=nick
2=is
3=a
4=person

tbl2 = 
a=true
person=true
is=true
nick=true



And, I think it would be quicker and neater than scanning the other table many times.