Mercurial > hg > batmud > misc
changeset 187:18b142c83761 misc
Some major refactoring, added code for parsing 'identify' spell output (and other related data) to produce Item/Weapon/Armour templates.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 24 Jan 2011 18:45:09 +0200 |
parents | e23ea99e7aa8 |
children | 31ac75a88dee |
files | log2npctemplate.pl |
diffstat | 1 files changed, 396 insertions(+), 94 deletions(-) [+] |
line wrap: on
line diff
--- a/log2npctemplate.pl Mon Jan 17 21:14:36 2011 +0200 +++ b/log2npctemplate.pl Mon Jan 24 18:45:09 2011 +0200 @@ -15,6 +15,8 @@ # 5) Fight and kill monster. # 6) run log2npctemplate.pl < logfile.log > output.txt # +# 7) command id +# # Notes # ===== # - You must have spellname translator, preferably one with format: @@ -31,6 +33,8 @@ my $opt_debug = 0; # 1 = enable debug output my $opt_pkills_crop = 60; my $opt_outfile; +my $opt_identify = 1; +my $opt_npc = 1; # Define the regular expression to match any outputs of "say" @@ -65,11 +69,26 @@ ); +# Stat name translations +my @statTransTable = ( + sub { return $_[0] =~ s/^ability at the (skill|spell) (.+)$/$2/ }, + sub { return $_[0] =~ s/^mental regeneration$/spr/g }, + sub { return $_[0] =~ s/^physical regeneration$/hpr/g }, +# sub { return $_[0] =~ s///g }, +); + + ### Options while (defined(my $arg = shift)) { if ($arg eq "-d") { $opt_debug++; } + elsif ($arg eq "-i") { + $opt_identify = 0; + } + elsif ($arg eq "-n") { + $opt_npc = 0; + } elsif ($arg eq "-o") { $opt_outfile = shift or die("Output file option -o requires an argument.\n"); } @@ -79,6 +98,8 @@ -o <filename> Output filename. -d Enable debug mode. + -i Disable identify parser. + -n Disable NPC parser. "); } @@ -91,25 +112,42 @@ } +### Translate stats +sub trans_stat($) +{ + my ($s) = @_; + foreach my $pat (@statTransTable) { + return $s if ($pat->($s)); + } + return $s; +} + + ### Globals my %monsters = (); my %aligns = (); my %spells = (); my %races = (); my %areas = (); +my %ids = (); my $line = 0; -my ($mob_sname, $mob_sdesc, $mob_ldesc, $mob_area, $mob_cont, $mob_line); -my $mob_eqs = { }; + +my $mob_sdesc; +my $mob = { }; my $state = 0; +my $id_tale; +my $id_tale2; +my $id = {}; -### Convert spellchants array + +### Convert spellchants array to regexp my $spellregexps = join("|", map { s/ (his|its|her) / ... /g; $_ } @spellchants); ### Change parsing state -sub setstate($$) +sub set_state($$) { return unless ($_[0] != $state); print STDERR "STATE = $_[0], old = $state\n" if ($opt_debug > 1); @@ -121,6 +159,250 @@ } +sub parse_npc($) +{ + my ($s) = @_; + + if ($state == 1) { + if ($s =~ /^You prod (.+?) like a stray cow\.$/o) { + # Get 'short name' + $$mob{"sname"} = $1; + } elsif ($s =~ /^You are in '.*?' in (.+?) on the continent of ([A-Z][a-z]+). \(Coordinates: (\d+)x, (\d+)y\)$/o) { + # Area, continent + $$mob{"area"} = $1; + $$mob{"cont"} = $2; + + $areas{$1}{"cont"} = $2; + $areas{$1}{"x"} = $3; + $areas{$1}{"y"} = $4; + } elsif ($s =~ /^You are in '.*?', which is on the continent of ([A-Z][a-z]+). \(Coordinates: (\d)+x, (\d)+y\)$/o) { + # Area, continent + $$mob{"area"} = $1; + $$mob{"cont"} = $1; + + $areas{$1}{"cont"} = $1; + $areas{$1}{"x"} = $2; + $areas{$1}{"y"} = $3; + } elsif ($s =~ /^You $sayregex '(-\?\?-|--\?\?--\?\?--\?\?--\?\?--)\.'$/o) { + set_state(2, $s); + } else { + set_state(-1, $s); + } + } + elsif ($state == 2) { + # Mostly just grab shortdesc here + if ($s =~ /^You $sayregex '(-==-|-=-=-=-=-=-=-=-=-)\.'$/o) { + set_state(3, $s); + } elsif ($s =~ /^(He|She|It) +\[[a-z]+\] \([0-9-]+\%\)/o) { + set_state(-1, $s); + } elsif ($s =~ /^You $sayregex /o) { + set_state(-1, $s); + } else { + $mob_sdesc = $s; + } + } + elsif ($state == 3) { + if ($s =~ /^ +([a-zA-Z ,-]+?)'s equipment:$/o) { + # End of long desc + set_state(4, $s); + } elsif ($s =~ /^(He|She|It) +\[[a-z]+\] \([0-9-]+\%\)$/o || + $s =~ /^(He|She|It) is (in (a )?)?(excellent shape|good shape|slightly hurt|noticeably hurt|not in a good shape|bad shape|very bad shape|near death)/o) { + # End of long desc + set_state(4, $s); + } elsif ($s =~ /^You $sayregex /o) { + set_state(-1, $s); + } else { + # Collect long desc + $$mob{"ldesc"} .= $s." "; + } + } + elsif ($state == 4) { + if ($s =~ /^You $sayregex '====*'?\.'$/o) { + # Finished, submit information to hash + $monsters{$mob_sdesc} = $mob; + set_state(0, $s); + } elsif ($s =~ /^([A-Z][a-z, ]+): (.*)$/o) { + # Collect EQ and slot information + $$mob{"eqs"}{$1} = $2; + } elsif ($s =~ /^([A-Z][a-z, ]+)\s+\(partially hidden\)\s*: (.*)$/o) { + # Collect EQ and slot information + $$mob{"eqs"}{$1} = $2; + } elsif ($s =~ /^ +([a-zA-Z -]+?)'s equipment:$/o) { + # Ignore this line + } elsif ($s =~ /^((It|She|He) has a blueish black kiss on ... cheek\.|(It|She|He) suffers from scourge\.|Some glittering red mist is surrounding this creature.|Nothing\.|(It|He|She) has a faint ring of .+ magic mist around ... neck\.)$/o) { + # Ignore various useless lines such as holz markings + } else { + # Error. + set_state(-1, $s); + } + } +} + + +sub parse_identify($) +{ + my ($s) = @_; + + if ($state == 10) { + if ($s =~ /^You $sayregex '-#-\.'$/o) { + set_state(11, $s); + } + elsif ($s =~ /^:\s*(\d+\.\d+)\s+(.+)$/) { + # Weigh in kgs, and sdesc. Will have to match these later. + $$id{"kg"}{$2} = $1; + $$id{"full"} = $2; + } + } + elsif ($state == 11) { + if ($s =~ /^It is surrounded by .+? glow\.$|^It is labeled as|^This item is a present from santa to /) { + # Just skip these + } + elsif ($s =~ /You $sayregex '-!-\.'$/o) { + set_state(12, $s); + } + elsif ($s =~ /^It contains a tale;$/) { + $id_tale = 1; + } + elsif ($s =~ /^This (.+?) is in .+? condition\.$/) { + $$id{"type"} = $1; + } + elsif ($s =~ /^These (.+?) are in .+? condition\.$/) { + $$id{"type"} = $1; + } + elsif ($s =~ /^It looks (light weight|a bit heavy|heavy|very very heavy|very light weight|very heavy|ridiculously heavy)\.$/) { + $$id{"weight"} = $1; + } + else { + if ($id_tale) { + $$id{"tale"} .= $s." "; + } else { + my $len = length($s); + $$id{"ldesc"} .= $s; + if (defined($$id{"len"}) && $len + $$id{"len"} < 79) { + $$id{"ldesc"} .= "\n"; + } else { + $$id{"ldesc"} .= " "; + } + $$id{"len"} = $len; + } + } + } + elsif ($state == 12) { + if ($s =~ /^The following messages seem to vibrate from (.+?):$/o) { + $$id{"sdesc"} = $1; + set_state(13, $s); + } + } + elsif ($state == 13) { + if ($s =~ /^It is called (.+)\.$/) { + $$id{"handles"} = $1; + $id_tale2 = 0; + } + elsif ($s =~ /^It takes the following slots: (.+)\.$/) { + $$id{"slots"} = $1; + $id_tale2 = 0; + } + elsif ($s =~ /^A halo of purity surrounds it\.$/) { + push(@{$$id{"stats"}}, "[[:category:halo of purity|good wear only]]"); + $$id{"cat"}{"halo of purity"} = 1; + $id_tale2 = 0; + } + elsif ($s =~ /^An aura of blackness surrounds it\.$/) { + push(@{$$id{"stats"}}, "[[:category:aura of darkness|evil wear only]]"); + $$id{"cat"}{"aura of darkness"} = 1; + $id_tale2 = 0; + } + elsif ($s =~ /^It will (.+?) (improve|reduce) your (.+?)\.$/) { + my ($amt, $imp, $stat) = ($1, $2, $3); + push(@{$$id{"stats"}}, ($imp eq "improve" ? "+" : "-").$amt." ".trans_stat($stat)); + $$id{"cat"}{trans_stat($stat)} = 1 if ($imp eq "improve"); + $id_tale2 = 0; + } + elsif ($s =~ /^It will (raise|lower) your (.+?)\.$/) { + my $imp = $1; + my $stat = substr($2, 0, 3); + push(@{$$id{"stats"}}, ($imp eq "raise" ? "+" : "-").$stat); + $$id{"cat"}{$stat} = 1 if ($imp eq "raise"); + $id_tale2 = 0; + } + elsif ($s =~ /^It contains a tale;$/) { + $id_tale2 = 1; + } + elsif ($s =~ /^(.+?) did the heroic deed to bring this piece of equipment before you (.+)$/) { + my $info = $2; + $$id{""} = ""; + + # Parse the big data blob + if ($info =~ /It is ([A-Za-z -]+), ([A-Za-z -]+),/) { + $$id{"weight2"} = $1; + $$id{"size"} = $2; + } + + if ($info =~ /of ([A-Za-z ]+) quality/) { + $$id{"quality"} = $1; + } + + if ($info =~ /(emits darkness|emits light)/) { + push(@{$$id{"stats"}}, $1); + $$id{"cat"}{$1} = 1; + } + + if ($info =~ /made of,? ?(.+?), (feather|worth)/) { + @{$$id{"materials"}} = split(/\s*,\s*/, $1); + my $qmat = $$id{"materials"}[0]; + my $qmax = -1; + foreach my $mat (@{$$id{"materials"}}) { + if ($mat =~ /^(\d+)% (.+)$/) { + if ($1 >= $qmax) { + $qmax = $1; + $qmat = $2; + } + } + } + $$id{"material"} = $qmat; + $$id{"cat"}{$qmat} = 1; + } + + # Check for nun relics + if ($$id{"full"} =~ / \(holy\)/) { + $$id{"cat"}{"relic"} = 1; + } + + # Set item class + $$id{"class"} = "Item"; + if ($info =~ /The weapon skill to best use this in combat/) { + $$id{"class"} = "Weapon"; + } elsif (defined($$id{"type"}) && $$id{"type"} ne "") { + $$id{"class"} = "Armour"; + } + + # Check if the weight data is for FW'd item + if ($$id{"full"} =~ / <(yellow|green|white) glow>$/) { + $$id{"kg"} = ""; + $$id{"weight"} = ""; + } else { + if (defined($$id{"kg"}{$$id{"full"}})) { + $$id{"kg"} = $$id{"kg"}{$$id{"full"}}; + } else { + $$id{"kg"} = ""; + } + } + + # Submit data + $ids{$$id{"full"}} = $id; + set_state(0, $s); + } + else { + if ($id_tale2) { + $$id{"tale"} .= $s." "; + } else { + push(@{$$id{"other"}}, $s); + } + } + } +} + + ### ### Main parsing loop ### @@ -136,7 +418,8 @@ { # Grab cast spells $spells{$1}{$line} = lc($3); - } elsif ($s =~ /\| \d\d:\d\d +(\d+): (.+?) +\|$/) { + } + elsif ($s =~ /\| \d\d:\d\d +(\d+): (.+?) +\|$/) { # Grab exp worth my $exp = $1; my $tmp = $2; @@ -150,105 +433,124 @@ $monsters{$sdesc}{"exp"} = $exp; } } - } elsif ($s =~ /^\[\d\d:\d\d:\d\d\] hp/ || $s =~ /^You laugh out loud\.$/) { - # Ignore - } elsif ($s =~ /^You see nothing special\.$/o) { - setstate(0, $s); - } elsif ($state == 0 && $s =~ /^You $sayregex '-+ .+? -+\.'$/o) { - setstate(1, $s); - $mob_sname = ""; + } + elsif ($s =~ /^\[\d\d:\d\d:\d\d\] hp|^You laugh out loud\.$|^Dunk dunk$/) { + # Ignore these lines + } + elsif ($s =~ /^You see nothing special\.$/o) { + # Reset parsing state if the target obviously didn't exist + set_state(0, $s); + } + elsif ($state == 0 && $s =~ /^You $sayregex '-+ .+? -+\.'$/o) { + next unless ($opt_npc); + # Beginning of NPC info block + set_state(1, $s); + undef($mob); $mob_sdesc = ""; - $mob_ldesc = ""; - $mob_area = ""; - $mob_cont = ""; - $mob_line = $line; - undef($mob_eqs); - } elsif ($state == 1) { - if ($s =~ /^You prod (.+?) like a stray cow\.$/o) { - # Get 'short name' - $mob_sname = $1; - } elsif ($s =~ /^You are in '.*?' in (.+?) on the continent of ([A-Z][a-z]+). \(Coordinates: (\d+)x, (\d+)y\)$/o) { - # Area, continent - $mob_area = $1; - $mob_cont = $2; - - $areas{$1}{"cont"} = $2; - $areas{$1}{"x"} = $3; - $areas{$1}{"y"} = $4; - } elsif ($s =~ /^You are in '.*?', which is on the continent of ([A-Z][a-z]+). \(Coordinates: (\d)+x, (\d)+y\)$/o) { - # Area, continent - $mob_area = $1; - $mob_cont = $1; - - $areas{$1}{"cont"} = $1; - $areas{$1}{"x"} = $2; - $areas{$1}{"y"} = $3; - } elsif ($s =~ /^You $sayregex '(-\?\?-|--\?\?--\?\?--\?\?--\?\?--)\.'$/o) { - setstate(2, $s); - } else { - setstate(-1, $s); - } - } elsif ($state == 2) { - if ($s =~ /^You $sayregex '(-==-|-=-=-=-=-=-=-=-=-)\.'$/o) { - setstate(3, $s); - } elsif ($s =~ /^(He|She|It) +\[[a-z]+\] \([0-9-]+\%\)/o) { - setstate(-1, $s); - } elsif ($s =~ /^You $sayregex /o) { - setstate(-1, $s); - } else { - $mob_sdesc = $s; - } - } elsif ($state == 3) { - if ($s =~ /^ +([a-zA-Z ,-]+?)'s equipment:$/o) { - # End of long desc - setstate(4, $s); - } elsif ($s =~ /^(He|She|It) +\[[a-z]+\] \([0-9-]+\%\)$/o || - $s =~ /^(He|She|It) is (in (a )?)?(excellent shape|good shape|slightly hurt|noticeably hurt|not in a good shape|bad shape|very bad shape|near death)/o) { - # End of long desc - setstate(4, $s); - } elsif ($s =~ /^You $sayregex /o) { - setstate(-1, $s); - } else { - # Collect long desc - $mob_ldesc .= $s." "; - } - } elsif ($state == 4) { - if ($s =~ /^You $sayregex '====*'?\.'$/o) { - # Finished, submit information to hash - $monsters{$mob_sdesc}{"line"} = $mob_line; - $monsters{$mob_sdesc}{"eqs"} = $mob_eqs; - $monsters{$mob_sdesc}{"sname"} = $mob_sname; - $monsters{$mob_sdesc}{"ldesc"} = $mob_ldesc; - $monsters{$mob_sdesc}{"area"} = $mob_area; - $monsters{$mob_sdesc}{"cont"} = $mob_cont; - setstate(0, $s); - } elsif ($s =~ /^([A-Z][a-z, ]+): (.*)$/o) { - # Collect EQ and slot information - $mob_eqs->{$1} = $2; - } elsif ($s =~ /^([A-Z][a-z, ]+)\s+\(partially hidden\)\s*: (.*)$/o) { - # Collect EQ and slot information - $mob_eqs->{$1} = $2; - } elsif ($s =~ /^ +([a-zA-Z -]+?)'s equipment:$/o) { - # Ignore this line - } elsif ($s =~ /^((It|She|He) has a blueish black kiss on ... cheek\.|(It|She|He) suffers from scourge\.|Some glittering red mist is surrounding this creature.|Nothing\.|(It|He|She) has a faint ring of .+ magic mist around ... neck\.)$/o) { - # Ignore various useless lines such as holz markings - } else { - setstate(-1, $s); - } - } elsif ($s =~ /^(.+?) is (a bit good|a bit evil|evil|good|neutral)\.$/o) { + $$mob{"line"} = $line; + } + elsif ($state == 0 && $s =~ /^You $sayregex '-ID-\.'$/o) { + next unless ($opt_identify); + # Beginning of identify info block + set_state(10, $s); + $id = {}; + undef($id); + $id_tale = 0; + $id_tale2 = 0; + $$id{"line"} = $line; + } + elsif ($state > 0 && $state < 10) { + # States for NPC parsing + parse_npc($s); + } + elsif ($state >= 10) { + parse_identify($s); + } + elsif ($s =~ /^(.+?) is (a bit good|a bit evil|evil|good|neutral)\.$/o) { # Grab detect alignment $aligns{$1}{$line} = $2; - } elsif ($s =~ /^([A-Za-z][A-Za-z\ .-]+?)\ is an? ([a-z-]+)\.$/o) { + } + elsif ($s =~ /^([A-Za-z][A-Za-z\ .-]+?)\ is an? ([a-z-]+)\.$/o) { # Grab detect race $races{$1}{$line} = $2; - } elsif ($s =~ /^You $sayregex /o) { - setstate(0, $s); + } + elsif ($s =~ /^You $sayregex /o) { + # Error, reset parsing state + set_state(0, $s); } } ### -### Print out the NPO information +### Print out item/identify information +### +foreach my $sdesc (sort { $a cmp $b } keys %ids) { + my $item = $ids{$sdesc}; + my $name = $$item{"sdesc"}; + $name =~ s/ labeled as .*$//; + my $qdesc = $name; + if ($$item{"full"} =~ / <(red|purple|white) glow>$/) { + $name .= " <red glow>"; + } + + print "---------------------------\n". + $qdesc."\n\n". + "{{ Infobox ".$$item{"class"}."\n". + "| name = ".$name."\n". + "| description = ".$$item{"ldesc"}."\n"; + + if (defined($$item{"tale"}) && $$item{"tale"} ne "") { + print "| tale = ".$$item{"tale"}."\n"; + } + + if (defined($$item{"type"})) { + print "| type = ".$$item{"type"}."\n"; + } + + if (defined($$item{"stats"})) { + print "| stats = ".join(", ", @{$$item{"stats"}})."\n"; + } else { + print "| stats = \n"; + } + + print + "| weight = ".$$item{"weight"}."\n". + "| kg = ".$$item{"kg"}."\n". + "| sacvalue = \n". + "| handles = ".$$item{"handles"}."\n"; + + if (defined($$item{"materials"})) { + print "| material = ".join(", ", @{$$item{"materials"}})."\n"; + } + + print + "| size = ".$$item{"size"}."\n". + "| quality = ".$$item{"quality"}."\n". + "| from = \n"; + + if ($$item{"class"} eq "Weapon") { + print + "| wep1 = \n". + "| wep2 = \n"; + } + + if (defined($$item{"other"})) { + print "| other = ".join("\n", @{$$item{"other"}})."\n"; + } + + print + "}}\n"; + + foreach my $cat (keys %{$$item{"cat"}}) { + print "[[Category:$cat]]\n"; + } + + print "---------------------\n"; +} + + +### +### Print out the NPC information ### foreach my $sdesc (sort { $a cmp $b } keys %monsters) { my $mob = $monsters{$sdesc};