Index: class.c ================================================================== --- class.c +++ class.c @@ -1767,13 +1767,13 @@ if(tokent!=TF_INT || tokenv<0 || tokenv>32) ParseError("Expected number from 0 to 32"); if(tokenv) AddInst2(OP_POPUPARGS,tokenv); else AddInst(OP_POPUP); nxttok(); if(tokent!=TF_CLOSE) ParseError("Unterminated (PopUp)\n"); break; - case OP_PATTERN: case OP_PATTERNS: - case OP_PATTERN_C: case OP_PATTERNS_C: - case OP_PATTERN_E: case OP_PATTERNS_E: + case OP_PATTERN: case OP_PATTERNS: case OP_PATTERNC: + case OP_PATTERN_C: case OP_PATTERNS_C: case OP_PATTERNC_C: + case OP_PATTERN_E: case OP_PATTERNS_E: case OP_PATTERNC_E: AddInst(tokenv); cl->codes[ptr]=peep=parse_pattern(cla,ptr+1,hash); ptr=peep; break; case OP_BROADCAST: Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -2837,10 +2837,20 @@ Like ,P but push all found objects, or pushes nothing if not found. =P* Like =P but push all found objects, or pushes nothing if not found. +Pc + Like P* but pushes only the number of matches (zero if none are found), + rather than all of the objects. + +,Pc + Like ,P* but pushes only the number of matches. + +=Pc + Like =P* but pushes only the number of matches. + Inside the pattern, the following commands are allowed (although the commands that push stuff to the stack should not be used in the patterns with P* or ,P* or =P*): @@ -2873,14 +2883,16 @@ , Fail if there are any objects having the specified flag here. + - Push the matched object to the stack. + Push the matched object to the stack. (For the counting modes, instead + unconditionally increments the total.) - - Push zero to the stack. + Push zero to the stack. (For the counting modes, instead unconditionally + decrements the total.) * Update the current choice point with the location and direction. / Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -2483,16 +2483,17 @@ Uint8 d=objects[obj]->dir; Uint32 un=VOIDLINK; Uint32 n=VOIDLINK; Uint32 m; Uint16 g; + Uint32 total=0; Value v; ChoicePoint cp[MAXCHOICE]; Uint8 cpi=0; Uint16 ccl=objects[obj]->class; Uint8 cim=objects[obj]->image; - if(!x) return VOIDLINK; + if(!x) goto stop; cp->depth=vstackptr; again: switch(code[ptr++]) { case 0 ... 7: n=VOIDLINK; x+=x_delta[code[ptr-1]]; @@ -2538,21 +2539,21 @@ else if(v.u) Throw("Invalid return value from message in pattern matching"); } else if(v.t>TY_MAXTYPE) { n=v_object(v); x=objects[n]->x; y=objects[n]->y; - if(!x) return VOIDLINK; + if(!x) goto stop; } else { Throw("Type mismatch"); } m=objects[m]->up; } break; case OP_ADD: if(vstackptr>=VSTACKSIZE-1) Throw("Stack overflow"); m=(n==VOIDLINK?obj_bottom_at(x,y):n); - Push(OVALUE(m)); + if(all==2) total++; else Push(OVALUE(m)); break; case OP_AGAIN: if(cp[cpi].ptr!=ptr+1) { if(cpi>=MAXCHOICE-1) Throw("Choice overflow"); cpi++; @@ -2630,11 +2631,11 @@ goto fail; } else if(v.t>TY_MAXTYPE) { n=v_object(v); x=objects[n]->x; y=objects[n]->y; - if(!x) return VOIDLINK; + if(!x) goto stop; } else { Throw("Type mismatch"); } break; case OP_HEIGHT: @@ -2672,11 +2673,11 @@ Push(NVALUE(x)); Push(NVALUE(y)); break; case OP_MARK: if(vstackptr>=VSTACKSIZE-1) Throw("Stack overflow"); - Push(UVALUE(0,TY_MARK)); + if(all!=2) Push(UVALUE(0,TY_MARK)); break; case OP_MUL: cp[cpi].x=x; cp[cpi].y=y; cp[cpi].dir=d; @@ -2720,11 +2721,16 @@ break; case OP_RET: if(all) { if(vstackptr>=VSTACKSIZE-1) Throw("Stack overflow"); if(n==VOIDLINK) n=obj_bottom_at(x,y); - Push(OVALUE(n)); + if(all!=2) { + Push(OVALUE(n)); + } else { + if(un==VOIDLINK && n!=VOIDLINK) total++; + else if(un!=VOIDLINK) return total+(n==VOIDLINK?1:0); + } goto fail; } else if(un==VOIDLINK) { return n==VOIDLINK?obj_bottom_at(x,y):n; } else { return VOIDLINK; @@ -2743,11 +2749,11 @@ cp[cpi-1].dir=4; cp[cpi-2].dir=6; break; case OP_SUB: if(vstackptr>=VSTACKSIZE-1) Throw("Stack overflow"); - Push(NVALUE(0)); + if(all==2) total--; else Push(NVALUE(0)); break; case OP_THEN: // This opcode does nothing break; case OP_TRACE: @@ -2764,31 +2770,35 @@ fail: if(!all) { if(vstackptrdepth) Throw("Stack underflow in pattern matching"); vstackptr=cp[cpi].depth; } - if(!cpi) return un; + if(!cpi) return (all==2?total+(un==VOIDLINK?0:1):un); x=cp[cpi].x; y=cp[cpi].y; d=cp[cpi].dir; ptr=cp[cpi].ptr; n=VOIDLINK; cpi--; goto again; + stop: + return (all==2?total:VOIDLINK); } static Uint32 v_pattern_anywhere(Uint16*code,int ptr,char all) { int i; Uint32 n; + Uint32 t=0; for(i=0;i>12)&15; @@ -3500,10 +3510,13 @@ case OP_PATTERN_C: StackReq(1,1); i=code[ptr++]; j=v_object(Pop()); if(j!=VOIDLINK) j=v_pattern(code,ptr,j,0); ptr=i; Push(OVALUE(j)); break; case OP_PATTERN_E: StackReq(0,1); i=code[ptr++]; j=v_pattern_anywhere(code,ptr,0); ptr=i; Push(OVALUE(j)); break; case OP_PATTERNS: StackReq(0,1); i=code[ptr++]; v_pattern(code,ptr,obj,1); ptr=i; break; case OP_PATTERNS_C: StackReq(1,1); i=code[ptr++]; j=v_object(Pop()); if(j!=VOIDLINK) v_pattern(code,ptr,j,1); ptr=i; break; case OP_PATTERNS_E: StackReq(0,1); i=code[ptr++]; v_pattern_anywhere(code,ptr,1); ptr=i; break; + case OP_PATTERNC: StackReq(0,1); i=code[ptr++]; j=v_pattern(code,ptr,obj,2); ptr=i; Push(NVALUE(j)); break; + case OP_PATTERNC_C: StackReq(1,1); i=code[ptr++]; j=v_object(Pop()); if(j!=VOIDLINK) j=v_pattern(code,ptr,j,2); else j=0; Push(NVALUE(j)); ptr=i; break; + case OP_PATTERNC_E: StackReq(0,1); i=code[ptr++]; j=v_pattern_anywhere(code,ptr,2); ptr=i; Push(NVALUE(j)); break; case OP_PICK: StackReq(0,1); t1=Pop(); Numeric(t1); if(t1.u>=vstackptr) Throw("Stack index out of range"); t1=vstack[vstackptr-t1.u-1]; Push(t1); break; case OP_PLAYER: StackReq(0,1); if(classes[o->class]->cflags&CF_PLAYER) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_PLAYER_C: StackReq(1,1); GetClassFlagOf(CF_PLAYER); break; case OP_PLUSMOVE: StackReq(1,1); t1=Pop(); Numeric(t1); i=defer_move(obj,t1.u,1); Push(NVALUE(i)); break; case OP_PLUSMOVE_C: StackReq(2,1); t1=Pop(); Numeric(t1); i=v_object(Pop()); i=defer_move(i,t1.u,1); Push(NVALUE(i)); break; Index: instruc ================================================================== --- instruc +++ instruc @@ -332,10 +332,11 @@ DotProduct ; Pattern matching -,=Pattern "P" -,=PatternS "P*" +-,=PatternC "Pc" -Rook -Bishop -Queen -cut Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -499,32 +499,36 @@ #define OP_PATTERN_EC 39165 #define OP_PATTERNS 33022 #define OP_PATTERNS_C 35070 #define OP_PATTERNS_E 37118 #define OP_PATTERNS_EC 39166 -#define OP_ROOK 33023 -#define OP_BISHOP 33024 -#define OP_QUEEN 33025 -#define OP_CUT 33026 -#define OP_BIZARRO 33027 -#define OP_BIZARRO_C 35075 -#define OP_BIZARRO_E 37123 -#define OP_BIZARRO_EC 39171 -#define OP_BIZARROSWAP 33028 -#define OP_BIZARROSWAP_D 41220 -#define OP_SWAPWORLD 33029 -#define OP_ABSTRACT 33030 -#define OP_SUPER 33031 -#define OP_SUPER_C 35079 -#define OP_FUNCTION 33032 -#define OP_LOCAL 33033 -#define OP_LABEL 33034 -#define OP_STRING 33035 -#define OP_INT16 33036 -#define OP_INT32 33037 -#define OP_DISPATCH 33038 -#define OP_USERFLAG 33039 +#define OP_PATTERNC 33023 +#define OP_PATTERNC_C 35071 +#define OP_PATTERNC_E 37119 +#define OP_PATTERNC_EC 39167 +#define OP_ROOK 33024 +#define OP_BISHOP 33025 +#define OP_QUEEN 33026 +#define OP_CUT 33027 +#define OP_BIZARRO 33028 +#define OP_BIZARRO_C 35076 +#define OP_BIZARRO_E 37124 +#define OP_BIZARRO_EC 39172 +#define OP_BIZARROSWAP 33029 +#define OP_BIZARROSWAP_D 41221 +#define OP_SWAPWORLD 33030 +#define OP_ABSTRACT 33031 +#define OP_SUPER 33032 +#define OP_SUPER_C 35080 +#define OP_FUNCTION 33033 +#define OP_LOCAL 33034 +#define OP_LABEL 33035 +#define OP_STRING 33036 +#define OP_INT16 33037 +#define OP_INT32 33038 +#define OP_DISPATCH 33039 +#define OP_USERFLAG 33040 #ifdef HEROMESH_CLASS static const Op_Names op_names[]={ {"*",8486945}, {"+",8421407}, {"+Move",10584262}, @@ -534,11 +538,11 @@ {".",10518528}, {"/",8486946}, {"/mod",8486948}, {"ANHH",8389393}, {"ARRIVED",8389124}, -{"Abstract",8683782}, +{"Abstract",8683783}, {"Animate",8552604}, {"AnimateDead",8552605}, {"Arg1",8552580}, {"Arg2",8552581}, {"Arg3",8552582}, @@ -559,13 +563,13 @@ {"BRRREEET",8389395}, {"BRRRT",8389394}, {"BUZZER",8389419}, {"BWEEP",8389396}, {"Background",8683662}, -{"Bishop",8683776}, -{"Bizarro",8618243}, -{"BizarroSwap",10518788}, +{"Bishop",8683777}, +{"Bizarro",8618244}, +{"BizarroSwap",10518789}, {"Broadcast",10518687}, {"BroadcastAnd",8421536}, {"BroadcastAndEx",8421537}, {"BroadcastEx",10518691}, {"BroadcastList",8421540}, @@ -722,23 +726,24 @@ {"P*",8880382}, {"PLAYERMOVING",8389133}, {"POSTINIT",8389138}, {"POUR",8389377}, {"POWER",8389386}, +{"Pc",8880383}, {"Player",8487037}, {"PopUp",8421587}, -{"Queen",8683777}, +{"Queen",8683778}, {"Quiz",8487061}, {"R",9437198}, {"RATCHET1",8389417}, {"RATCHET2",8389411}, {"RATTLE",8389402}, {"RB",9437197}, {"RF",9437199}, {"Rel",8487125}, {"Replace",10518742}, -{"Rook",8683775}, +{"Rook",8683776}, {"S",9437190}, {"SE",9437191}, {"SMALL_POP",8389388}, {"SPLASH",8389376}, {"STEAM",8389423}, @@ -757,12 +762,12 @@ {"Sharp",8618076}, {"Shovable",8618078}, {"Sound",8421595}, {"Stealthy",8618103}, {"Strength",9142361}, -{"Super",8487175}, -{"SwapWorld",8421637}, +{"Super",8487176}, +{"SwapWorld",8421638}, {"Sweep",8421596}, {"SweepEx",8421597}, {"Synchronize",8421598}, {"TAHTASHH",8389408}, {"THMP_thmp",8389404}, @@ -845,11 +850,11 @@ {"c?",8421436}, {"case",8683544}, {"chain",8421545}, {"clear",8421619}, {"count",8421618}, -{"cut",8683778}, +{"cut",8683779}, {"cz?",8421437}, {"dup",8421377}, {"else",8683530}, {"eq",8421427}, {"eq2",8421428}, @@ -900,7 +905,7 @@ {"tuck",8421380}, {"uniq",8421620}, {"until",8749070}, {"while",8749071}, }; -#define N_OP_NAMES 376 +#define N_OP_NAMES 377 #endif Index: misc/compare/puzzlescript.doc ================================================================== --- misc/compare/puzzlescript.doc +++ misc/compare/puzzlescript.doc @@ -329,11 +329,11 @@ defining winning conditions like PuzzleScript might be implemented, but currently it is not implemented.) Also, some of the features listed in the GitHub issue tracker for PuzzleScript and PuzzleScript+ are already implemented in Free Hero Mesh, -although some are planned to be implemented, are unnecessary (for whatever -reasons), or are deliberately not implemented. There are also many features -that PuzzleScript does not have. +although some are planned to be implemented, or are unnecessary (for +whatever reasons), or are deliberately not implemented. There are also many +features that PuzzleScript does not have. Certainly further improvements are also possible, too.