--- 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 {