--- deliantra/server/lib/cf/match.pm 2009/10/20 05:57:08 1.20 +++ deliantra/server/lib/cf/match.pm 2010/08/28 00:05:33 1.28 @@ -1,3 +1,25 @@ +# +# This file is part of Deliantra, the Roguelike Realtime MMORPG. +# +# Copyright (©) 2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team +# +# Deliantra is free software: you can redistribute it and/or modify it under +# the terms of the Affero GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the Affero GNU General Public License +# and the GNU General Public License along with this program. If not, see +# . +# +# The authors can be reached via e-mail to +# + =head1 NAME cf::match - object matching language @@ -94,9 +116,9 @@ not applied in inv -is true if there is I non-object in the inventory. To negate a whole -match, you have to use a sub-match. To check whether there is I -applied object in someones inventory, write this: +is true if there is I non-applied object in the inventory. To negate +a whole match, you have to use a sub-match: To check whether there is +I applied object in someones inventory, write this: not (applied in inv) @@ -108,6 +130,10 @@ type=HORN or type=ROD +Example: see if the originator is a player. + + type=PLAYER of originator + =item in ... The in operator takes the context set and modifies it in various ways. As @@ -138,6 +164,10 @@ Replaces all objects by the objects that are on the same mapspace as them. +=item in head + +Replaces all objects by their head objects. + =item in Finds all context objects matching the condition, and then puts their @@ -201,6 +231,11 @@ but submatches start at the current object, and in this case C can be used to start at the original object once more. +=item of self + +Starts with the object initiating/asking for the match - this is basically +always the object that the match expression is attached to. + =item of source Starts with the I object - this object is sometimes passed to @@ -217,11 +252,6 @@ This object is often identical to the I (e.g. when a player casts a spell, the player is both source and originator). -=item of self - -Starts with the object initiating/asking for the match - this is basically -always the object that the match expression is attached to. - =back =head2 EXPRESSIONS @@ -299,6 +329,11 @@ This simply evaluates to true, and simply makes matching I object a bit easier to read. +=item none + +This simply evaluates to false, and simply makes matching I a bit +easier to read. + =item has(condition) True iff the object has a matching inventory object. @@ -332,12 +367,12 @@ | chain 'of' root root = 'object' | 'self' | 'source' | 'originator' chain = condition - | chain also deep 'in' set + | chain also deep 'in' modifier also = nothing | 'also' deep = nothing | 'deep' - set = 'inv' | 'env' | 'arch' | 'map' + modifier ='inv' | 'env' | 'arch' | 'map' | 'head' - empty = + nothing = # boolean matching condition @@ -355,6 +390,7 @@ expr = flag | sattr | aattr '[' ']' + | 'stat.' statattr | special | func '(' args ')' | '{' perl code block '}' @@ -363,6 +399,7 @@ sattr = aattr = flag = + statattr = special = constant = | '"' '"' | @@ -421,6 +458,9 @@ any => sub { 1 }, + none => sub { + 0 + }, ); sub constant { @@ -437,7 +477,10 @@ our $flag = $cf::REFLECT{object}{flags}; our $sattr = $cf::REFLECT{object}{scalars}; + # quick hack to support archname, untested + $sattr->{archname} = "W"; our $aattr = $cf::REFLECT{object}{arrays}; + our $lattr = $cf::REFLECT{living}{scalars}; sub expr { # ws done by factor @@ -450,6 +493,16 @@ $res .= $expr =~ /\{([^;]+)\}/ ? $1 : "do $expr"; + } elsif (/\Gstats\.([A-Za-z0-9_]+)/gc) { + + if (exists $lattr->{$1}) { + $res .= "\$_->stats->$1"; + } elsif (exists $lattr->{"\u$1"}) { + $res .= "\$_->stats->\u$1"; + } else { + die "living statistic name expected (str, pow, hp, sp...)\n"; + } + } elsif (/\G([A-Za-z0-9_]+)/gc) { if (my $func = $func{$1}) { @@ -570,7 +623,6 @@ # if nothing follows, we have a simple condition, so # optimise a comon case. if ($defctx eq '$_' and /\G\s*(?=\)|$)/gc) { - warn "shortcut<$res>$wantarray\n";#d# return $wantarray ? "$res ? \$_ : ()" : $res; @@ -587,11 +639,14 @@ if (/\Gin\s+/gc) { my $expand; - if (/\G(inv|env|map|arch)\b/gc) { + if (/\G(inv|env|map|arch|head)\b/gc) { if ($1 eq "inv") { $expand = "map \$_->inv,"; } elsif ($1 eq "env") { $expand = "map \$_->env // (),"; + } elsif ($1 eq "head") { + $expand = "map \$_->head,"; + $deep = 0; # infinite loop otherwise } elsif ($1 eq "arch") { $expand = "map \$_->arch,"; $deep = 0; # infinite loop otherwise @@ -663,7 +718,7 @@ } if (0) {#d# - die parse 1, 'applied in inv'; + die parse 1, 'stats.pow'; exit 0; } @@ -672,7 +727,7 @@ sub compile($$) { my ($wantarray, $match) = @_; my $expr = parse $wantarray, $match; - warn "MATCH DEBUG $match,$wantarray => $expr\n";#d# +# warn "MATCH DEBUG $match,$wantarray => $expr\n";#d# $expr = eval " package cf::match::exec; sub {