ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf/match.pm
(Generate patch)

Comparing deliantra/server/lib/cf/match.pm (file contents):
Revision 1.20 by root, Tue Oct 20 05:57:08 2009 UTC vs.
Revision 1.26 by root, Fri Mar 26 01:04:44 2010 UTC

1#
2# This file is part of Deliantra, the Roguelike Realtime MMORPG.
3#
4# Copyright (©) 2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5#
6# Deliantra is free software: you can redistribute it and/or modify it under
7# the terms of the Affero GNU General Public License as published by the
8# Free Software Foundation, either version 3 of the License, or (at your
9# option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the Affero GNU General Public License
17# and the GNU General Public License along with this program. If not, see
18# <http://www.gnu.org/licenses/>.
19#
20# The authors can be reached via e-mail to <support@deliantra.net>
21#
22
1=head1 NAME 23=head1 NAME
2 24
3cf::match - object matching language 25cf::match - object matching language
4 26
5=head1 DESCRIPTION 27=head1 DESCRIPTION
92Not that C<not> only negates a condition and not the whole match 114Not that C<not> only negates a condition and not the whole match
93expressions, thus 115expressions, thus
94 116
95 not applied in inv 117 not applied in inv
96 118
97is true if there is I<any> non-object in the inventory. To negate a whole 119is true if there is I<any> non-applied object in the inventory. To negate
98match, you have to use a sub-match. To check whether there is I<no> 120a whole match, you have to use a sub-match: To check whether there is
99applied object in someones inventory, write this: 121I<no> applied object in someones inventory, write this:
100 122
101 not (applied in inv) 123 not (applied in inv)
102 124
103Example: match applied weapons. 125Example: match applied weapons.
104 126
105 applied type=WEAPON 127 applied type=WEAPON
106 128
107Example: match horns or rods. 129Example: match horns or rods.
108 130
109 type=HORN or type=ROD 131 type=HORN or type=ROD
132
133Example: see if the originator is a player.
134
135 type=PLAYER of originator
110 136
111=item in ... 137=item in ...
112 138
113The in operator takes the context set and modifies it in various ways. As 139The in operator takes the context set and modifies it in various ways. As
114a less technical description, think of the C<in> as being a I<look into> 140a less technical description, think of the C<in> as being a I<look into>
136 162
137=item in map 163=item in map
138 164
139Replaces all objects by the objects that are on the same mapspace as them. 165Replaces all objects by the objects that are on the same mapspace as them.
140 166
167=item in head
168
169Replaces all objects by their head objects.
170
141=item in <condition> 171=item in <condition>
142 172
143Finds all context objects matching the condition, and then puts their 173Finds all context objects matching the condition, and then puts their
144inventories into the context set. 174inventories into the context set.
145 175
297=item any 327=item any
298 328
299This simply evaluates to true, and simply makes matching I<any> object a 329This simply evaluates to true, and simply makes matching I<any> object a
300bit easier to read. 330bit easier to read.
301 331
332=item none
333
334This simply evaluates to false, and simply makes matching I<never> a bit
335easier to read.
336
302=item has(condition) 337=item has(condition)
303 338
304True iff the object has a matching inventory object. 339True iff the object has a matching inventory object.
305 340
306=item count(match) 341=item count(match)
330 365
331 match = chain 366 match = chain
332 | chain 'of' root 367 | chain 'of' root
333 root = 'object' | 'self' | 'source' | 'originator' 368 root = 'object' | 'self' | 'source' | 'originator'
334 chain = condition 369 chain = condition
335 | chain also deep 'in' set 370 | chain also deep 'in' modifier
336 also = nothing | 'also' 371 also = nothing | 'also'
337 deep = nothing | 'deep' 372 deep = nothing | 'deep'
338 set = 'inv' | 'env' | 'arch' | 'map' 373 modifier ='inv' | 'env' | 'arch' | 'map' | 'head'
339 374
340 empty = 375 nothing =
341 376
342 # boolean matching condition 377 # boolean matching condition
343 378
344 condition = factor 379 condition = factor
345 | factor 'and'? condition 380 | factor 'and'? condition
353 operator = '=' | '==' | '!=' | '<' | '<=' | '>' | '>=' 388 operator = '=' | '==' | '!=' | '<' | '<=' | '>' | '>='
354 389
355 expr = flag 390 expr = flag
356 | sattr 391 | sattr
357 | aattr '[' <constant> ']' 392 | aattr '[' <constant> ']'
393 | 'stat.' statattr
358 | special 394 | special
359 | func '(' args ')' 395 | func '(' args ')'
360 | '{' perl code block '}' 396 | '{' perl code block '}'
361 397
362 func = <any function name> 398 func = <any function name>
363 sattr = <any scalar object attribute> 399 sattr = <any scalar object attribute>
364 aattr = <any array object attribute> 400 aattr = <any array object attribute>
365 flag = <any object flag> 401 flag = <any object flag>
402 statattr = <any stat attribute: exp, food, str, dex, hp, maxhp...>
366 special = <any ()-less "function"> 403 special = <any ()-less "function">
367 404
368 constant = <number> | '"' <string> '"' | <uppercase cf::XXX name> 405 constant = <number> | '"' <string> '"' | <uppercase cf::XXX name>
369 args = <depends on function> 406 args = <depends on function>
370 407
419 456
420 our %special = ( 457 our %special = (
421 any => sub { 458 any => sub {
422 1 459 1
423 }, 460 },
461 none => sub {
462 0
463 },
424 ); 464 );
425 465
426 sub constant { 466 sub constant {
427 ws; 467 ws;
428 468
435 die "number, string or uppercase constant name expected\n"; 475 die "number, string or uppercase constant name expected\n";
436 } 476 }
437 477
438 our $flag = $cf::REFLECT{object}{flags}; 478 our $flag = $cf::REFLECT{object}{flags};
439 our $sattr = $cf::REFLECT{object}{scalars}; 479 our $sattr = $cf::REFLECT{object}{scalars};
480 # quick hack to support archname, untested
481 $sattr->{archname} = "W";
440 our $aattr = $cf::REFLECT{object}{arrays}; 482 our $aattr = $cf::REFLECT{object}{arrays};
483 our $lattr = $cf::REFLECT{living}{scalars};
441 484
442 sub expr { 485 sub expr {
443 # ws done by factor 486 # ws done by factor
444 my $res; 487 my $res;
445 488
447 # perl 490 # perl
448 491
449 my $expr = $1; 492 my $expr = $1;
450 493
451 $res .= $expr =~ /\{([^;]+)\}/ ? $1 : "do $expr"; 494 $res .= $expr =~ /\{([^;]+)\}/ ? $1 : "do $expr";
495
496 } elsif (/\Gstats\.([A-Za-z0-9_]+)/gc) {
497
498 if (exists $lattr->{$1}) {
499 $res .= "\$_->stats->$1";
500 } elsif (exists $lattr->{"\u$1"}) {
501 $res .= "\$_->stats->\u$1";
502 } else {
503 die "living statistic name expected (str, pow, hp, sp...)\n";
504 }
452 505
453 } elsif (/\G([A-Za-z0-9_]+)/gc) { 506 } elsif (/\G([A-Za-z0-9_]+)/gc) {
454 507
455 if (my $func = $func{$1}) { 508 if (my $func = $func{$1}) {
456 /\G\s*\(/gc 509 /\G\s*\(/gc
568 my $res = condition; 621 my $res = condition;
569 622
570 # if nothing follows, we have a simple condition, so 623 # if nothing follows, we have a simple condition, so
571 # optimise a comon case. 624 # optimise a comon case.
572 if ($defctx eq '$_' and /\G\s*(?=\)|$)/gc) { 625 if ($defctx eq '$_' and /\G\s*(?=\)|$)/gc) {
573 warn "shortcut<$res>$wantarray\n";#d#
574 return $wantarray 626 return $wantarray
575 ? "$res ? \$_ : ()" 627 ? "$res ? \$_ : ()"
576 : $res; 628 : $res;
577 } 629 }
578 630
585 my $deep = /\Gdeep\s+/gc + 0; 637 my $deep = /\Gdeep\s+/gc + 0;
586 638
587 if (/\Gin\s+/gc) { 639 if (/\Gin\s+/gc) {
588 my $expand; 640 my $expand;
589 641
590 if (/\G(inv|env|map|arch)\b/gc) { 642 if (/\G(inv|env|map|arch|head)\b/gc) {
591 if ($1 eq "inv") { 643 if ($1 eq "inv") {
592 $expand = "map \$_->inv,"; 644 $expand = "map \$_->inv,";
593 } elsif ($1 eq "env") { 645 } elsif ($1 eq "env") {
594 $expand = "map \$_->env // (),"; 646 $expand = "map \$_->env // (),";
647 } elsif ($1 eq "head") {
648 $expand = "map \$_->head,";
649 $deep = 0; # infinite loop otherwise
595 } elsif ($1 eq "arch") { 650 } elsif ($1 eq "arch") {
596 $expand = "map \$_->arch,"; 651 $expand = "map \$_->arch,";
597 $deep = 0; # infinite loop otherwise 652 $deep = 0; # infinite loop otherwise
598 } elsif ($1 eq "map") { 653 } elsif ($1 eq "map") {
599 $expand = "map \$_->map->at (\$_->x, \$_->y),"; 654 $expand = "map \$_->map->at (\$_->x, \$_->y),";
661 716
662 $res 717 $res
663} 718}
664 719
665if (0) {#d# 720if (0) {#d#
666 die parse 1, 'applied in inv'; 721 die parse 1, 'stats.pow';
667 exit 0; 722 exit 0;
668} 723}
669 724
670our %CACHE; 725our %CACHE;
671 726

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines