summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2013-09-14 08:13:28 +0200
committerHaru <haru@dotalux.com>2013-11-28 02:34:55 +0100
commit9a802b9147221ec1f31109242be2919f53401fd3 (patch)
tree22c42e57cc03151e0e1aa73f0035c614b73b468e
parentac6ae8c932efbca30ef1650fa5d7bd94ead336f5 (diff)
downloadhercules-9a802b9147221ec1f31109242be2919f53401fd3.tar.gz
hercules-9a802b9147221ec1f31109242be2919f53401fd3.tar.bz2
hercules-9a802b9147221ec1f31109242be2919f53401fd3.tar.xz
hercules-9a802b9147221ec1f31109242be2919f53401fd3.zip
Corrected operator precedence table.
- [ This commit is part of a larger script engine related update ] - Operator precedence rules now closely follow those of languages such as C and derivates/related (C++, Java, PHP, etc.) - Please note that if you had custom scripts with non parenthesized expressions containing bitwise |, &, ^ operators, they may behave incorrectly now (or perhaps they were already behaving incorrectly, since the previous behavior was undocumented). - Added an up to date operator precedence/associativity table in the script documentation. - Added an operator/keyword self-test script in the npc/custom folder, in case if may be of some use for future regression-testing.
-rw-r--r--doc/script_commands.txt91
-rw-r--r--npc/custom/breeder.txt6
-rw-r--r--npc/custom/test.txt416
-rw-r--r--npc/other/arena/arena_aco.txt2
-rw-r--r--npc/scripts_custom.conf4
-rw-r--r--src/map/script.c40
6 files changed, 535 insertions, 24 deletions
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 0912cb556..9186ba714 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -578,6 +578,29 @@ Operators section described below. All operators listed there may be
placed in-front of the '=' sign when modifying variables to perform the
action as required.
+Increment and decrement operators are also provided, for your convenience.
+Pre-increment and pre-decrement operators:
+
+ ++@x; // same as @x = @x + 1
+ --@x; // same as @x = @x - 1
+
+Post-increment and post-decrement operators:
+
+ @x++; // similar to @x = @x + 1
+ @x--; // similar to @x = @x - 1
+
+The difference between pre- and post- increment/decrement operators is that,
+when used in an expression, the pre- ones will be executed before evaluating
+the expression, while the post- ones will be executed after. For example:
+
+ @x = 1;
+ @y = ++@x; // After this line is executed, both @y and @x will be 2
+ @x = 1;
+ @y = @x++; // After this line is executed, @y will be 1, @x will be 2
+
+Note: The pre-increment/pre-decrement operators are, by design, faster (or at
+least not slower) than their respective post- equivalent.
+
Note:
!! Currently the scripting engine does not support directly copying array
@@ -854,6 +877,74 @@ and are the following:
mentioning that ?: has low priority and has to be enclosed with
parenthesis in most (if not all) cases.
+Operator Precedence and Associativity
+
+Operator precedence and associativity work more or less like they do in
+mathematics. The rules can be summarized with the following table:
+
+Precedence | Description | Associativity
+---------------------------------------------------------------------------
+1 (highest) | [] Array subscripting | None
+---------------------------------------------------------------------------
+2 | ++ Increment | None
+ | -- Decrement |
+---------------------------------------------------------------------------
+2 | - Unary minus | Right to left
+ | ! Logical NOT |
+ | ~ Bitwise NOT (One's Complement) |
+---------------------------------------------------------------------------
+3 | * Multiplication | Left to right
+ | / Division |
+ | % Modulo (remainder) |
+---------------------------------------------------------------------------
+4 | + Addition | Left to right
+ | - Subtraction |
+---------------------------------------------------------------------------
+5 | << Bitwise left shift | Left to right
+ | >> Bitwise right shift |
+---------------------------------------------------------------------------
+6 | < Less than | Left to right
+ | <= Less than or equal to |
+ | > Greater than |
+ | >= Greater than or equal to |
+---------------------------------------------------------------------------
+7 | == Equal to | Left to right
+ | != Not equal to |
+---------------------------------------------------------------------------
+8 | & Bitwise AND | Left to right
+---------------------------------------------------------------------------
+9 | ^ Bitwise XOR (exclusive or) | Left to right
+---------------------------------------------------------------------------
+10 | | Bitwise OR (inclusive or) | Left to right
+---------------------------------------------------------------------------
+11 | && Logical AND | Left to right
+---------------------------------------------------------------------------
+12 | || Logical OR | Left to right
+---------------------------------------------------------------------------
+13 | ?: Ternary conditional | Right to left
+---------------------------------------------------------------------------
+14 | = Direct assignment | Right to left
+(lowest) | += Assignment by sum |
+ | -= Assignment by difference |
+ | *= Assignment by product |
+ | /= Assignment by quotient |
+ | %= Assignment by remainder |
+ | <<= Assignment by bitwise left shift |
+ | >>= Assignment by bitwise right shift |
+ | &= Assignment by bitwise AND |
+ | ^= Assignment by bitwise XOR |
+ | |= Assignment by bitwise OR |
+
+Operator precedence means some operators are evaluated before others. For
+example, in 2 + 4 * 5 , the multiplication has higher precedence so 4 * 5 is
+evaluated first yielding 2 + 20 == 22 and not 6 * 5 == 30 .
+
+Operator associativity defines what happens if a sequence of the same
+operators is used one after another: whether the evaluator will evaluate the
+left operations first or the right. For example, in 8 - 4 - 2 , subtraction is
+left associative so the expression is evaluated left to right. 8 - 4 is
+evaluated first making the expression 4 - 2 == 2 and not 8 - 2 == 6 .
+
Labels
------
diff --git a/npc/custom/breeder.txt b/npc/custom/breeder.txt
index 3eef8af0a..0222f5b3a 100644
--- a/npc/custom/breeder.txt
+++ b/npc/custom/breeder.txt
@@ -15,7 +15,7 @@ prontera,124,201,1 script Universal Rental NPC 4_F_JOB_BLACKSMITH,{
message strcharinfo(0),"You must first remove your mount.";
end;
}
- else if ((eaclass()&EAJ_THIRDMASK==EAJ_RANGER) && !countitem(6124)) {
+ else if ((eaclass()&EAJ_THIRDMASK) == EAJ_RANGER && !countitem(6124)) {
if (!checkfalcon() && getskilllv("HT_FALCON") && !checkoption(Option_Wug) && !checkoption(Option_Wugrider)) {
if(select(" ~ Falcon: ~ Warg")==1) setfalcon;
else getitem 6124,1;
@@ -24,7 +24,7 @@ prontera,124,201,1 script Universal Rental NPC 4_F_JOB_BLACKSMITH,{
}
else getitem 6124,1;
}
- else if ((eaclass()&EAJ_THIRDMASK==EAJ_MECHANIC) && !checkcart() && getskilllv("MC_PUSHCART")) {
+ else if ((eaclass()&EAJ_THIRDMASK) == EAJ_MECHANIC && !checkcart() && getskilllv("MC_PUSHCART")) {
if (!checkmadogear() && getskilllv("NC_MADOLICENCE")) {
if(select(" ~ Cart: ~ Mado")==1) setcart;
else setmadogear;
@@ -36,7 +36,7 @@ prontera,124,201,1 script Universal Rental NPC 4_F_JOB_BLACKSMITH,{
else if (!checkcart() && getskilllv("MC_PUSHCART")) setcart;
else if (!checkfalcon() && getskilllv("HT_FALCON") && !checkoption(Option_Wug) && !checkoption(Option_Wugrider)) setfalcon;
else if (!checkriding() && getskilllv("KN_RIDING")) {
- if (eaclass()&EAJ_THIRDMASK==EAJ_RUNE_KNIGHT) setdragon;
+ if ((eaclass()&EAJ_THIRDMASK) == EAJ_RUNE_KNIGHT) setdragon;
else setriding;
}
else if (!checkmadogear() && getskilllv("NC_MADOLICENCE")) setmadogear;
diff --git a/npc/custom/test.txt b/npc/custom/test.txt
new file mode 100644
index 000000000..bfd297f5d
--- /dev/null
+++ b/npc/custom/test.txt
@@ -0,0 +1,416 @@
+//===== Hercules Script ======================================
+//= Script engine self-tests
+//===== By: ==================================================
+//= Haru
+//===== Current Version: =====================================
+//= 1.0
+//===== Description: =========================================
+//= Script to test operators and possibly other elements of
+//= the script engine, useful for regression testing.
+
+- script HerculesSelfTest -1,{
+ end;
+OnCheck:
+ .@msg$ = getarg(0,"Unknown Error");
+ .@val = getarg(1,0);
+ .@ref = getarg(2,1);
+ if (.@val != .@ref) {
+ debugmes "Error: "+.@msg$+": '"+.@val+"' != '"+.@ref+"'";
+ //end;
+ }
+ return;
+OnInit:
+ // Array subscript
+ setarray .@a, 3, 2, 1;
+ callsub(OnCheck, "Array subscript", .@a[2]);
+
+
+ // Increment and decrement operators ++, --
+ .@x = 1;
+ .@y = .@x++; // .@y = .@x; .@x = .@x + 1;
+ callsub(OnCheck, "Suffix increment ++", .@y);
+ callsub(OnCheck, "Suffix increment ++", .@x, 2);
+ .@x = 1;
+ .@y = .@x--; // .@y = .@x; .@x = .@x - 1;
+ callsub(OnCheck, "Suffix decrement --", .@y);
+ callsub(OnCheck, "Suffix decrement --", .@x, 0);
+ .@x = 0;
+ .@y = ++.@x; // .@x = .@x + 1; .@y = .@x;
+ callsub(OnCheck, "Prefix increment ++", .@y);
+ callsub(OnCheck, "Prefix increment ++", .@x);
+ .@x = 2;
+ .@y = --.@x; // .@x = .@x - 1; .@y = .@x;
+ callsub(OnCheck, "Prefix decrement --", .@y);
+ callsub(OnCheck, "Prefix decrement --", .@x);
+
+ // Order of [] and --/++
+ .@a[1] = 0;
+ .@a[1]++; // .@a[1] = .@a[1] + 1;
+ callsub(OnCheck, "Order of [] and ++", .@a[1]);
+ .@a[1] = 2;
+ .@a[1]--; // .@a[1] = .@a[1] - 1;
+ callsub(OnCheck, "Order of [] and --", .@a[1]);
+
+
+ // Unary operators -, !, ~
+ .@x = 1;
+ .@y = -.@x; // .@y = 0 - .@x;
+ callsub(OnCheck, "Unary operator -", .@y, -1);
+ .@x = 1;
+ .@y = !.@x; // if(.@x == 0) .@y = 1; else .@y = 0;
+ callsub(OnCheck, "Unary operator !", .@y, 0);
+ .@x = 0x00000001;
+ .@y = ~.@x; // One's complement of 0x00000001 is 0xfffffffe, which is -2
+ callsub(OnCheck, "Unary operator ~", .@y, -2);
+
+ // Associativity of unary operators -, !, ~
+ .@x = 1;
+ .@y = ~ ! .@x; // .@y = ~(!.@x);
+ callsub(OnCheck, "Associativity of unary ~ and !", .@y, -1);
+ .@x = 0;
+ .@y = - ! .@x; // .@y = -(!.@x);
+ callsub(OnCheck, "Associativity of unary - and !", .@y, -1);
+ .@x = 1;
+ .@y = ~ - .@x; // .@y = ~(-.@x);
+ callsub(OnCheck, "Associativity of unary ~ and -", .@y, 0);
+ .@x = 1;
+ .@y = - ~ .@x; // .@y = -(~.@x);
+ callsub(OnCheck, "Associativity of unary - and ~", .@y, 2);
+
+ // Order of unary -, !, ~ and prefix/suffix ++/--
+ .@x = 2;
+ .@y = - --.@x; // .@y = -(--.@x);
+ callsub(OnCheck, "Order of unary - and prefix --", .@y, -1);
+ callsub(OnCheck, "Order of unary - and prefix --", .@x);
+ .@x = 1;
+ .@y = - .@x--; // .@y = -(.@x--);
+ callsub(OnCheck, "Order of unary - and suffix --", .@y, -1);
+ callsub(OnCheck, "Order of unary - and suffix --", .@x, 0);
+ .@x = 0;
+ .@y = - ++.@x; // .@y = -(++.@x);
+ callsub(OnCheck, "Order of unary - and prefix ++", .@y, -1);
+ callsub(OnCheck, "Order of unary - and prefix ++", .@x);
+ .@x = 1;
+ .@y = - .@x++; // .@y = -(.@x++);
+ callsub(OnCheck, "Order of unary - and suffix ++", .@y, -1);
+ callsub(OnCheck, "Order of unary - and suffix ++", .@x, 2);
+ .@x = 1;
+ .@y = !--.@x; // .@y = !(--.@x);
+ callsub(OnCheck, "Order of unary ! and prefix --", .@y);
+ callsub(OnCheck, "Order of unary ! and prefix --", .@x, 0);
+ .@x = 1;
+ .@y = !.@x--; // .@y = !(.@x--);
+ callsub(OnCheck, "Order of unary ! and suffix --", .@y, 0);
+ callsub(OnCheck, "Order of unary ! and suffix --", .@x, 0);
+ .@x = 0;
+ .@y = !++.@x; // .@y = !(++.@x);
+ callsub(OnCheck, "Order of unary ! and prefix ++", .@y, 0);
+ callsub(OnCheck, "Order of unary ! and prefix ++", .@x);
+ .@x = 0;
+ .@y = !.@x++; // .@y = !(.@x++);
+ callsub(OnCheck, "Order of unary ! and suffix ++", .@y);
+ callsub(OnCheck, "Order of unary ! and suffix ++", .@x);
+ .@x = 2;
+ .@y = ~--.@x; // .@y = ~(--.@x);
+ callsub(OnCheck, "Order of unary ~ and prefix --", .@y, -2);
+ callsub(OnCheck, "Order of unary ~ and prefix --", .@x, 1);
+ .@x = 1;
+ .@y = ~.@x--; // .@y = ~(.@x--);
+ callsub(OnCheck, "Order of unary ~ and suffix --", .@y, -2);
+ callsub(OnCheck, "Order of unary ~ and suffix --", .@x, 0);
+ .@x = 0;
+ .@y = ~++.@x; // .@y = ~(++.@x);
+ callsub(OnCheck, "Order of unary ~ and prefix ++", .@y, -2);
+ callsub(OnCheck, "Order of unary ~ and prefix ++", .@x, 1);
+ .@x = 1;
+ .@y = ~.@x++; // .@y = ~(.@x++);
+ callsub(OnCheck, "Order of unary ~ and suffix ++", .@y, -2);
+ callsub(OnCheck, "Order of unary ~ and suffix ++", .@x, 2);
+
+ // Binary *, /, % operators
+ .@x = 2 * 3; // .@x = 6;
+ callsub(OnCheck, "Binary * operator", .@x, 6);
+ .@x = 7 / 2; // .@x = 3;
+ callsub(OnCheck, "Binary / operator", .@x, 3);
+ .@x = 7 % 2; // .@x = 1;
+ callsub(OnCheck, "Binary % operator", .@x, 1);
+
+ // Associativity of *, /, %
+ .@x = 8 * 3 / 2; // .@x = (8 * 3) / 2;
+ callsub(OnCheck, "Associativity of * and /", .@x, 12);
+
+ // Order of binary *%/ and unary !-~
+ .@x = 2 * ! 3; // .@x = 2 * (!3);
+ callsub(OnCheck, "Order of binary * and unary !", .@x, 0);
+ .@x = ~ 1 * 2; // .@x = (~1) * 2;
+ callsub(OnCheck, "Order of unary ~ and binary *", .@x, -4);
+
+
+ // Binary +, - operators
+ .@x = 1 + 3; // .@x = 4;
+ callsub(OnCheck, "Binary + operator", .@x, 4);
+ .@x = 1 - 3; // .@x = -2;
+ callsub(OnCheck, "Binary - operator", .@x, -2);
+
+ // Associativity of +,-
+ .@x = 0x7fffffff - 0x7ffffff0 + 1; // .@x = (0x7fffffff - 0x7ffffff0) + 1; (without overflow)
+ callsub(OnCheck, "Associativity of + and -", .@x, 16);
+
+ // Order of +, - and *, /, %
+ .@x = 1 + 3 * 2; // .@x = 1 + (3 * 2);
+ callsub(OnCheck, "Order of + and *", .@x, 7);
+
+
+ // << and >> operators
+ .@x = 1<<3; // .@x = 1*2*2*2;
+ callsub(OnCheck, "Left shift << operator", .@x, 8);
+ .@x = 12>>2; // .@x = 12/2/2;
+ callsub(OnCheck, "Right shift >> operator", .@x, 3);
+
+ // Associativity of << and >>
+ .@x = 0x40000000 >> 4 << 2; // .@x = (0x40000000 >> 4) << 2
+ callsub(OnCheck, "Associativity of >> and <<", .@x, 0x10000000);
+
+ // Order of <</>> and +/-
+ .@x = 4 << 2 + 1; // .@x = 4 << (2+1);
+ callsub(OnCheck, "Order of << and +", .@x, 32);
+
+
+ // <, <=, >, >= operators
+ .@x = (1 < 2); // true
+ .@y = (2 < 2); // false
+ callsub(OnCheck, "< operator", .@x);
+ callsub(OnCheck, "< operator", .@y, 0);
+ .@x = (1 <= 2); // true
+ .@y = (2 <= 2); // true
+ callsub(OnCheck, "<= operator", .@x);
+ callsub(OnCheck, "<= operator", .@y);
+ .@x = (2 > 1); // true
+ .@y = (2 > 2); // false
+ callsub(OnCheck, "> operator", .@x);
+ callsub(OnCheck, "> operator", .@y, 0);
+ .@x = (2 >= 1); // true
+ .@y = (2 >= 2); // true
+ callsub(OnCheck, ">= operator", .@x);
+ callsub(OnCheck, ">= operator", .@y);
+
+ // Associativity of <,<=,>,>=
+ .@x = 1 > 0 > 0; // (1 > 0) > 0 --> 1 > 0 --> true
+ callsub(OnCheck, "Associativity of > operators", .@x);
+
+ // Order of >>/<< and </<=/>/>=
+ .@x = 1 < 1 << 2; // .@x = 1 < (1<<2);
+ callsub(OnCheck, "Order of < and <<", .@x);
+
+
+ // ==, != operators
+ .@x = (0 == 0); // true
+ .@y = (1 == 0); // false
+ callsub(OnCheck, "== operator", .@x);
+ callsub(OnCheck, "== operator", .@y, 0);
+ .@x = (1 != 0); // true
+ .@y = (1 != 1); // false
+ callsub(OnCheck, "!= operator", .@x);
+ callsub(OnCheck, "!= operator", .@y, 0);
+
+ // Associativity of ==, !=
+ .@x = (1 == 0 == 0); // (1 == 0) == 0 --> 0 == 0 --> 1
+ .@y = (1 != 0 == 0); // (1 != 0) == 0 --> 1 == 0 --> 0
+ callsub(OnCheck, "Associativity of != and == operators", .@x);
+ callsub(OnCheck, "Associativity of != and == operators", .@y, 0);
+
+ // Order of </<=/>/>= and ==/!=
+ .@x = (1 == 2 > 1); // true
+ .@y = (1 < 2 == 1); // true
+ callsub(OnCheck, "Order of <,>,==", .@x);
+ callsub(OnCheck, "Order of <,>,==", .@y);
+
+
+ // Bitwise & operator
+ .@x = (7&4); // 0111 & 0100 --> 0100
+ .@y = (4&1); // 0100 & 0001 --> 0000
+ callsub(OnCheck, "Bitwise & operator", .@x, 4);
+ callsub(OnCheck, "Bitwise & operator", .@y, 0);
+
+ // Order of & and ==/!=
+ .@x = (4 == 7 & 4); // (4 == 7)&4
+ .@y = (1 & 3 != 1); // 1 & (3 != 1)
+ callsub(OnCheck, "Order of ==/!= and &", .@x, 0);
+ callsub(OnCheck, "Order of ==/!= and &", .@y);
+
+
+ // Bitwise ^ operator
+ .@x = (3^1); // 0011 ^ 0001 --> 0010
+ callsub(OnCheck, "Bitwise ^ operator", .@x, 2);
+
+ // Order of ^ and &
+ .@x = (0 & 2 ^ 2); // (0 & 2) ^ 2 --> (0000 & 0010) | 0010 --> 0000 ^ 0010 --> 0010
+ .@y = (2 ^ 2 & 0); // 2 ^ (2 & 0) --> 0010 | (0010 & 0000) --> 0010 ^ 0000 --> 0010
+ callsub(OnCheck, "Order of ^ and &", .@x, 2);
+ callsub(OnCheck, "Order of ^ and &", .@y, 2);
+
+
+ // Bitwise | operator
+ .@x = (3|4); // 0011 | 0100 --> 0111
+ .@y = (4|1); // 0100 | 0001 --> 0101
+ callsub(OnCheck, "Bitwise | operator", .@x, 7);
+ callsub(OnCheck, "Bitwise | operator", .@y, 5);
+
+ // Order of ^ and |
+ .@x = (2 ^ 2 | 2); // (2 ^ 1) | 4 --> (0010 ^ 0010) | 0010 --> 0000 | 0010 --> 0010
+ .@y = (2 | 2 ^ 2); // 4 | (1 ^ 2) --> 0010 | (0010 ^ 0010) --> 0010 | 0000 --> 0010
+ callsub(OnCheck, "Order of | and ^", .@x, 2);
+ callsub(OnCheck, "Order of | and ^", .@y, 2);
+
+
+ // Logical && operator
+ .@x = (1 && 1); // true
+ .@y = (0 && 1); // false
+ callsub(OnCheck, "Logical && operator", .@x);
+ callsub(OnCheck, "Logical && operator", .@y, 0);
+
+ // Associativity of && and short-circuit
+ .@x = 0;
+ .@y = (1 && 0 && (.@x = 1)); // should short circuit as false before evaluating the assignment
+ //FIXME callsub(OnCheck, "Short-circuit of &&", .@x, 0);
+ callsub(OnCheck, "Associativity of &&", .@y, 0);
+
+ // Order of bitwise | and logical &&
+ .@x = (1 && 0 | 4); // 1 && (0|4)
+ .@y = (4 | 0 && 1); // (4|0) && 1
+ callsub(OnCheck, "Order of && and |", .@x);
+ callsub(OnCheck, "Order of && and |", .@y);
+
+
+ // Logical || operator
+ .@x = (1 || 1); // true
+ .@y = (0 || 1); // true
+ callsub(OnCheck, "Logical || operator", .@x);
+ callsub(OnCheck, "Logical || operator", .@y);
+
+ // Associativity of || and short-circuit
+ .@x = 0;
+ .@y = (1 || 0 || (.@x = 1)); // should short circuit as true before evaluating the assignment
+ //FIXME callsub(OnCheck, "Short-circuit of ||", .@x, 0);
+ callsub(OnCheck, "Associativity of ||", .@y);
+
+ // Order of logical && and ||
+ .@x = (0 && 1 || 1); // (0 && 1) || 1
+ .@y = (1 || 1 && 0); // 1 || (1 && 0)
+ callsub(OnCheck, "Order of && and ||", .@x);
+ callsub(OnCheck, "Order of && and ||", .@y);
+
+ // Ternary conditional operator ?:
+ .@x = (1 ? 2 : 3); // 2
+ .@y = (0 ? 2 : 3); // 3
+ callsub(OnCheck, "Ternary conditional operator", .@x, 2);
+ callsub(OnCheck, "Ternary conditional operator", .@y, 3);
+
+ // Associativity of ?:
+ .@x = (1 ? 2 : 0 ? 3 : 4);
+ .@y = (1 ? 1 ? 2 : 3 : 5);
+ callsub(OnCheck, "Associativity of ?:", .@x, 2);
+ callsub(OnCheck, "Associativity of ?:", .@y, 2);
+
+ // Order of logical || and ternary ?:
+ .@x = (1 ? 0 : 0 || 1); // 1 ? 0 : (0 || 1) --> false
+ callsub(OnCheck, "Order of || and ?:", .@x, 0);
+
+
+ // Assignment operators
+ .@x = 1;
+ callsub(OnCheck, "Direct assignment operator =", .@x);
+ .@x += 7; // 1 + 7
+ callsub(OnCheck, "Assignment by sum +=", .@x, 8);
+ .@x -= 1; // 8 - 1
+ callsub(OnCheck, "Assignment by difference -=", .@x, 7);
+ .@x *= 2; // 7 * 2
+ callsub(OnCheck, "Assignment by product *=", .@x, 14);
+ .@x /= 2; // 14 / 2
+ callsub(OnCheck, "Assignment by quotient /=", .@x, 7);
+ .@x %= 4; // 7 % 4
+ callsub(OnCheck, "Assignment by remainder %=", .@x, 3);
+ .@x <<= 2; // 3 << 2
+ callsub(OnCheck, "Assignment by bitwise left shift <<=", .@x, 12);
+ .@x >>= 1; // 12 >> 1
+ callsub(OnCheck, "Assignment by bitwise right shift >>=", .@x, 6);
+ .@x &= 5; // 6 & 5 (0110 & 0101 --> 0100)
+ callsub(OnCheck, "Assignment by bitwise and &=", .@x, 4);
+ .@x ^= 5; // 4 ^ 5 (0100 ^ 0101 --> 0001)
+ callsub(OnCheck, "Assignment by bitwise xor ^=", .@x, 1);
+ .@x |= 2; // 1 | 2 (0001 | 0010 --> 0011)
+ callsub(OnCheck, "Assignment by bitwise or |=", .@x, 3);
+
+ // Associativity of assignment operators
+ .@x = 0; .@y = 0;
+ .@x = .@y = 1;
+ callsub(OnCheck, "1Associativity of =", .@x);
+ callsub(OnCheck, "2Associativity of =", .@y);
+ .@x = 0; .@y = 1;
+ .@x = .@y += 4;
+ callsub(OnCheck, "3Associativity of =", .@x, 5);
+ callsub(OnCheck, "4Associativity of =", .@y, 5);
+ .@x = 5; .@y = 3;
+ .@z = 8;
+/*
+ * 0001b4 C_NAME setr
+ * 0001b8 C_ARG
+ * 0001b9 C_NAME .@x
+ * 0001bd C_REF
+ * 0001bd C_INT 16
+ * 0001bf C_MUL
+ * 0001c0 C_FUNC
+ * 0001c1 C_EOL
+ */
+ /* FIXME
+ .@x *= (.@y += 1);
+ //set(.@x, .@x * set(.@y, .@y + 1));
+ //.@x = (.@x * (.@y = .@y + 1));
+ */
+/*
+ * 0001c2 C_NAME setr
+ * 0001c6 C_ARG
+ * 0001c7 C_NAME .@x
+ * 0001cb C_REF
+ * 0001cc C_NAME setr
+ * 0001d0 C_ARG
+ * 0001d1 C_NAME .@y
+ * 0001d5 C_REF
+ * 0001d5 C_INT 1
+ * 0001d7 C_ADD
+ * 0001d8 C_FUNC
+ * 0001d9 C_MUL
+ * 0001da C_FUNC
+ * 0001db C_EOL
+ */
+/*
+ * 0001c2 C_NAME setr
+ * 0001c6 C_ARG
+ * 0001c7 C_NAME .@x
+ * 0001cb C_REF
+ * 0001cc C_NAME setr
+ * 0001d0 C_ARG
+ * 0001d1 C_NAME .@y
+ * 0001d4 C_INT 2
+ * 0001d6 C_FUNC
+ * 0001d7 C_MUL
+ * 0001d8 C_FUNC
+ * 0001d9 C_EOL
+ */
+ /*
+ callsub(OnCheck, "5Associativity of =", .@x, 20);
+ callsub(OnCheck, "6Associativity of =", .@y, 4);
+ */
+
+ .@x = 0;
+ if (0)
+ if (1)
+ .@x = 2;
+ else
+ .@x = 3;
+ callsub(OnCheck, "Dangling else", .@x, 0);
+
+ debugmes "Script engine self-test [ PASSED ]";
+}
+
+// vim: set ft=ath :
diff --git a/npc/other/arena/arena_aco.txt b/npc/other/arena/arena_aco.txt
index 725e8c58f..cc0b4b640 100644
--- a/npc/other/arena/arena_aco.txt
+++ b/npc/other/arena/arena_aco.txt
@@ -1084,7 +1084,7 @@ prt_are_in,25,31,3 script Staff#aco-2 1_F_02,{
set .@hour_endaco, .@end_timeaco / 10000;
set .@min_endaco, ((.@end_timeaco % 10000) / 100);
set .@sec_endaco, .@end_timeaco % 100;
- if ((.@hour_startaco == 23) & (.@hour_endaco == 0)) {
+ if ((.@hour_startaco == 23) && (.@hour_endaco == 0)) {
set .@hour_endaco,24;
}
set .@st_to_secaco, ((.@hour_startaco * 3600) + (.@min_startaco * 60) + (.@sec_startaco));
diff --git a/npc/scripts_custom.conf b/npc/scripts_custom.conf
index aeae9e22f..b4283502c 100644
--- a/npc/scripts_custom.conf
+++ b/npc/scripts_custom.conf
@@ -104,3 +104,7 @@
//npc: npc/custom/battleground/bg_kvm01.txt
//npc: npc/custom/battleground/bg_kvm02.txt
//npc: npc/custom/battleground/bg_kvm03.txt
+
+// ----------------------- Misc Scripts -----------------------------
+// Self-test script (for development use only)
+//npc: npc/custom/test.txt
diff --git a/src/map/script.c b/src/map/script.c
index 2c4178d9b..73aaafab2 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -1158,32 +1158,32 @@ const char* script_parse_subexpr(const char* p,int limit) {
if( (op=C_ADD_PRE,p[0]=='+'&&p[1]=='+') || (op=C_SUB_PRE,p[0]=='-'&&p[1]=='-') ) { // Pre ++ -- operators
p=script->parse_variable(p);
} else if( (op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~') ) { // Unary - ! ~ operators
- p=script->parse_subexpr(p+1,10);
+ p=script->parse_subexpr(p+1,11);
script->addc(op);
} else {
p=script->parse_simpleexpr(p);
}
p=script->skip_space(p);
while((
- (op=C_OP3, opl=0,len=1,*p=='?') // ?:
- || (op=C_ADD, opl=8,len=1,*p=='+') // +
- || (op=C_SUB, opl=8,len=1,*p=='-') // -
- || (op=C_MUL, opl=9,len=1,*p=='*') // *
- || (op=C_DIV, opl=9,len=1,*p=='/') // /
- || (op=C_MOD, opl=9,len=1,*p=='%') // %
- || (op=C_LAND, opl=2,len=2,*p=='&' && p[1]=='&') // &&
- || (op=C_AND, opl=6,len=1,*p=='&') // &
- || (op=C_LOR, opl=1,len=2,*p=='|' && p[1]=='|') // ||
- || (op=C_OR, opl=5,len=1,*p=='|') // |
- || (op=C_XOR, opl=4,len=1,*p=='^') // ^
- || (op=C_EQ, opl=3,len=2,*p=='=' && p[1]=='=') // ==
- || (op=C_NE, opl=3,len=2,*p=='!' && p[1]=='=') // !=
- || (op=C_R_SHIFT,opl=7,len=2,*p=='>' && p[1]=='>') // >>
- || (op=C_GE, opl=3,len=2,*p=='>' && p[1]=='=') // >=
- || (op=C_GT, opl=3,len=1,*p=='>') // >
- || (op=C_L_SHIFT,opl=7,len=2,*p=='<' && p[1]=='<') // <<
- || (op=C_LE, opl=3,len=2,*p=='<' && p[1]=='=') // <=
- || (op=C_LT, opl=3,len=1,*p=='<') // <
+ (op=C_OP3, opl=0, len=1,*p=='?') // ?:
+ || (op=C_ADD, opl=9, len=1,*p=='+') // +
+ || (op=C_SUB, opl=9, len=1,*p=='-') // -
+ || (op=C_MUL, opl=10,len=1,*p=='*') // *
+ || (op=C_DIV, opl=10,len=1,*p=='/') // /
+ || (op=C_MOD, opl=10,len=1,*p=='%') // %
+ || (op=C_LAND, opl=2, len=2,*p=='&' && p[1]=='&') // &&
+ || (op=C_AND, opl=5, len=1,*p=='&') // &
+ || (op=C_LOR, opl=1, len=2,*p=='|' && p[1]=='|') // ||
+ || (op=C_OR, opl=3, len=1,*p=='|') // |
+ || (op=C_XOR, opl=4, len=1,*p=='^') // ^
+ || (op=C_EQ, opl=6, len=2,*p=='=' && p[1]=='=') // ==
+ || (op=C_NE, opl=6, len=2,*p=='!' && p[1]=='=') // !=
+ || (op=C_R_SHIFT,opl=8, len=2,*p=='>' && p[1]=='>') // >>
+ || (op=C_GE, opl=7, len=2,*p=='>' && p[1]=='=') // >=
+ || (op=C_GT, opl=7, len=1,*p=='>') // >
+ || (op=C_L_SHIFT,opl=8, len=2,*p=='<' && p[1]=='<') // <<
+ || (op=C_LE, opl=7, len=2,*p=='<' && p[1]=='=') // <=
+ || (op=C_LT, opl=7, len=1,*p=='<') // <
) && opl>limit) {
p+=len;
if(op == C_OP3) {