• Some users have recently had their accounts hijacked. It seems that the now defunct EVGA forums might have compromised your password there and seems many are using the same PW here. We would suggest you UPDATE YOUR PASSWORD and TURN ON 2FA for your account here to further secure it. None of the compromised accounts had 2FA turned on.
    Once you have enabled 2FA, your account will be updated soon to show a badge, letting other members know that you use 2FA to protect your account. This should be beneficial for everyone that uses FSFT.

serious PERL help needed

ctstyle

n00b
Joined
Feb 16, 2004
Messages
2
#What needs to be done#
I need something for creating a map for a game. The map will be created by reading a file's
contents, which will be like this

coords(0,0)
{
Title=Library
Description=This is where books can be bought
Other variables=whatver
}

coords(0,1)
{
Title=Hallway
Description=A fuckin hallway
Other variables=whatever
}

It needs to be able to read whatever variables may be inside the function, and put them
into a hash, such that the following is how it will be requested:
ie. $MAPQUERY("0,1",Title)

I would also like to point out that the coords may also contain negative numbers, aka
coords(0,-1) is legal. I'm thinking I will load this all into memory on the program's startup.

any ideas???
 
Just use regexps in a while(<FILE>) type loop. Before the while loop, create an empty hash, let's say "%map", and set some sentinel variable to 0 (let's say "$coords"). Inside the loop, when you encounter something like /^coords\((-?\d+,-?\d+)\)/, then set that sentinel variable to $1. That'll be a key in your hash, and also let you know whether you're actually in an open coords section at all.

Now, when you encounter a line like /(.*?)=(.*?)/ (or maybe /\s*(.*?)\s*=\s*(.*?)\s*/ if you want to flush out spaces around the equals sign), check and see "if ($coords)". If it is, then just set $map{$coords}{$1} = $2. Finally, when you encounter /^}$/, set $coords back to 0, meaning that you've seen the closing section.

When the end of the file is reached, you've got a hash, %map, that contains further hashes representing each of your "rooms". Access it like $map{$coord}{"Title"}, etc. If you want to access it in a more subroutine-like manner, like you said at the end, then just make a trivial subroutine that just sticks its args into the keys positions of the hash.

You can certainly get more involved, but that's the basic idea, at least of one simple way to do it. How much more involved you get depends on how tolerant you want to be of bad input. The above-described method, for example, doesn't even require an opening "{", though one being present won't hurt anything. Dealing with stuff like that is just more of the same, though.
 
Not sure if this works, or if its even what you want.
Code:
#!/usr/bin/perl
open(DATA,"cords");
        @data = <DATA>;
close(DATA);
foreach $line (@data)
{
        if ($line=~/coords\((-?\d+,-?\d+)\)/ && $start != 1)
        {
                $start = 1;
                $coords = $1
        }
        elsif ($start == 1 && $line=~/(\w+)=(.+)/)
        {
                if ($1 eq "Title")
                {
                        $title = $2;
                } else {
                        $maptitle = "map" . $title;
                        $$maptitle{$1} = $2;
                }
        }
        elsif ($line=~/}/)
        {
                $coord{"$coords"} = $title;
                $start = 0;
        }
}
sub mapquery {
        $getCoords = $_[0];
        $maptitle = "map" . $coord{"$getCoords"};
        @getWhat = @_;
        shift(@getWhat);
        foreach $thing (@getWhat)
        {
                $gotten{$thing} = $$maptitle{$thing};
        }
}
#example
&mapquery("0,0",Title,Description);
i'm not in the mood to go see if it works.. but i suppose its an idea.
 
HERE IT IS!

Code:
#!/usr/bin/perl

sub compile_data {

	open(FILE,"map.txt");
	@LINES = <FILE>;
	close(FILE);

	$all = join(' ', @LINES);
	$all =~ s/\n+//g;

	while ($all =~ /<COORDS\((-*\d*),(-*\d*)\)>/) {
		$all =~ s/<COORDS\((-*\d*),(-*\d*)\)>/<!SEARCH_BEGIN>/;
			$x_coord = $1;
			$y_coord = $2;

		$all =~ s/<\/COORDS>/<!SEARCH_END>/;

		$all =~ /<!SEARCH_BEGIN>(.*)<!SEARCH_END>/;
			$content = $1;

		$all =~ s/<!SEARCH_BEGIN>(.*)<!SEARCH_END>//g;

		while ($content =~ /<VAR='\w*'>/) {
			$content =~ s/<VAR='(\w*)'>/!!PING!!/;
				$theVar = $1;

			$content =~ s/<\/VAR>/!!PONG!!/;

			$content =~ s/!!PING!!(.*)!!PONG!!//g;
				$theVarData = $1;

			$MAPQUERY{"$x_coord,$y_coord,$theVar"} = $theVarData;
		}
	}
}

&compile_data;

print "Content-type: text/plain\n\n";
print $MAPQUERY{"0,0,TITLE"} ."\n";
print $MAPQUERY{"-56,-93,DIE"} ."\n"; # notice this shows nothing because Die != DIE;
print $MAPQUERY{"-56,-93,CPU"};

My map.txt file contains nothing special, just plain text with the following format:

Code:
<COORDS(0,0)>
<VAR='TITLE'>Library</VAR>
<VAR='Description'>
This is where books are..and shit.
</VAR>
<VAR='Other'>Free books for those with five finger discounts.</VAR>
</COORDS>

<COORDS(-56,-93)>
<VAR='Die'>Code die!</VAR>
<VAR='Shoe'>rots</VAR>
<VAR='CPU'>the data in each variable can
extend to many lines.</VAR>
</COORDS>

Test it in whatever environment you want. This code was tested on WinXP runing ActivePerl latest version. It should work online through CGI PERL too.
 
Back
Top