Index: TODO ================================================================== --- TODO +++ TODO @@ -1,10 +1,9 @@ * Sound effects * Compressed wave sounds (?) * Numeric sounds (?) * Game engine features - * Multiple connected objects moving as a unit * String data (partially implemented) * A ,PopUp command to use a popup with arguments starting from a mark * Returning a class from COLLIDE/COLLIDEBY to transform * Coordinate input (may be suitable for some kind of games) * Possibility to define auto-generation levels mode @@ -41,11 +40,11 @@ * Optional hypertext help * Compressed class definitions (?) * Option to auto display level titles * Testing * Bizarro world - * Deferred movement + * Connection movement (it is partially tested, already) * Sweep, SweepEx, HitMe * Overriding order of execution * Conversion from other games * DOS Hero Hearts * Berusky Index: class.c ================================================================== --- class.c +++ class.c @@ -2093,10 +2093,11 @@ case OP_USERSTATE: cl->oflags|=OF_USERSTATE; break; case OP_BIZARRO: cl->oflags|=OF_BIZARRO; break; case OP_SHOVABLE: cl->shovable=0x55; break; case OP_USERFLAG: class_user_flag(cl); break; case OP_ABSTRACT: cl->cflags|=CF_GROUP; break; + case OP_CONNECTION: cl->oflags|=OF_CONNECTION; break; case 0x4000 ... 0x7FFF: set_super_class(cl,ptr); ptr=2; break; default: ParseError("Invalid directly inside of a class definition\n"); } } else if(Tokenf(TF_CLOSE)) { break; @@ -2605,10 +2606,21 @@ strcpy(tokenstr,"(Control)"); control_class=look_class_name(); if(!(classes[control_class]->cflags&CF_NOCLASS1)) ParseError("Conflicting definition of (Control) class\n"); class_definition(control_class,vst); break; + case OP_CONNECTION: + nxttok(); + if(!(tokent&TF_NAME) || tokenv!=OP_STRING) ParseError("String literal expected\n"); + for(i=0;tokenstr[i];i++) switch(tokenstr[i]) { + case 't': conn_option|=0x02; break; + case 'w': conn_option|=0x01; break; + default: ParseError("Unrecognized (Connection) option\n"); + } + nxttok(); + if(tokent!=TF_CLOSE) ParseError("Expected close parenthesis\n"); + break; case OP_LEVELTABLE: level_table_definition(); break; default: ParseError("Invalid top level definition: %s\n",tokenstr); Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -269,10 +269,16 @@ (CodePage ) Define the code page, from 1 to 8388607. If not specified, then the default code page is used. +(Connection ) + Set options for connected movement. The string can include any + combination of the below letters: + "t" = Use two HIT/HITBY passes, skipping shove/sharp for first pass. + "w" = Use the total weight of the group instead of each one separately. + (Control ) Define the control class. The format is the same like other class definitions, except that Image and Abstract are not allowed. An object of this class is automatically created when initializing the level, at X and Y coordinates both zero, and cannot otherwise be @@ -399,10 +405,13 @@ ,Compatible Sets the Compatible flag for this class, but removes the restriction of some variables limited to 16-bits. +Connection + Sets the Connection flag for this class. + (DefaultImage ) Each entry is either a number of an image in this class, or two numbers in parentheses giving a range of images, or () to indicate that there are no default images. This specifies which images can be used in objects of this class which are initially present on @@ -648,10 +657,11 @@ BLOCKED COLLIDE COLLIDEBY COLLIDING CONFLICT + CONNECT CREATE CREATED DEPARTED DESTROY DESTROYED @@ -896,10 +906,17 @@ Compatible : bool [c] [ro] The compatibility flag. Class definitions imported from EKS Hero Mesh always set this flag; in new puzzle sets it is normally not set. +Connection : bool [c] + If this flag is set, then moving this object by the use of the Move + instruction will try to move an entire connected group of objects, + instead of only one. This changes some of the behaviour and will + cause additional messages to be sent, too. Deferred movement is not + possible if this flag is set. + Density : int16/int32 [c] Determines the order that objects are stacked within each cell. When an object is moved or created, its Density is compared with the Density of the objects already present at that location, in order to insert it into the stack of objects there, at the top, bottom, or middle, where lesser @@ -1008,10 +1025,11 @@ move or to not trigger even though it did move. Moving : bool This flag indicates that a deferred movement is scheduled for this object. The direction of movement is specified by the Dir variable. + This flag is also used for connected movement, for a different purpose. Player : bool [c] [ro] If this object is the player. This is used implicitly as the From of some messages sent by the game engine, and has a few other purposes. (Normally, a level should have exactly one object of such a class, @@ -1031,11 +1049,14 @@ Sharp : int16 [c] [d] When one object tries to move into another object, the Hard and Sharp values for the sides that are touching will be compared. If the Sharp value for one is greater than the Hard of the other, then the object - with insufficient Hardness is destroyed. + with insufficient Hardness is destroyed. If the object that is trying + to move has the Connection flag, it cannot be destroyed due to running + into something sharp, but may still destroy other things if it is sharp + enough to do so (whether or not the other thing has a Connection flag). Shovable : int16 [c] Defines what directions the object may be shoved, where bit0 means east, bit2 means north, bit4 means west, and bit6 means south. Bit1, bit3, bit5, and bit7 can be used for diagonal shoving. Higher bits are @@ -1330,10 +1351,23 @@ ,Coloc ( obj1 obj2 -- bool ) True if the two specified objects are in the same place, or false otherwise. Always false if the object is destroyed, or if one object is in the bizarro world and the other one isn't. + +Connect ( -- ) ** + Adds this object to the connection list; has no effect if this object + is already in the connection list or has the Moving, Destroyed, or + Bizarro flags set, or does not have the Connection flag. This will + also set the Moving and VisualOnly flag of this object; it will + automatically clear the Moving flag after it is handled, and will + restore the old value of VisualOnly. This should not be used outside + of the CONNECT message. + +,Connect ( obj -- ) ** + Similar to Connect but for a specified object, instead of necessarily + this object. Control ( -- obj ) Push the control object to the stack. (If no control class is defined, then there will be no control object and this will be zero.) @@ -1402,10 +1436,21 @@ link is zero then it will be the same as ret. ,exec ( link -- ) Go to a link and then continue executing from here afterward. If the link is zero then this instruction does nothing. + +FakeMove ( dir -- result ) ** + Similar to IntMove but omits many capabilities, including the actual + movement. This is the same as a function used internally to deal with + HIT/HITBY for connection movement. If the HIT or HITBY message returns + a mark, then it is added like using Connect (if the object's flags + allow it) and then the return value will be 2. + +,FakeMove ( obj dir -- result ) ** + Works like FakeMove but you can specify a different object instead of + the current one. Finished ( -- number ) Returns the value of an internal flag which tells it that the beginning and ending phases should be skipped. This is a 8-bit number; zero means don't skip them, and any other number means it does. When the game engine @@ -2145,10 +2190,20 @@ Called during scheduling of a deferred move if it is already currently scheduled to move but in a different direction. Arg1 is the direction that it is trying to schedule the move in. If the return value is false then the schedule fails; if true, then it succeeds. +CONNECT + Should use the ,Connect instruction to add additional objects to the + connection group; it will then send this message to those objects too. + If the return value is true, then the movement fails, and none of the + objects in the group will move. The Inertia of this object is set + automatically before calling this message; it can change the Inertia + before returning if it wants a different value for Inertia. Arg1 is + the number of objects in the group previously to this one, Arg2 is the + direction of movement, and Arg3 is the total Weight so far. + CREATE Sent when the object is created by the Create instruction. This is done after the object is created, but before sending any other messages. The From is the object that created it. The return value will be used as the Arg3 of the SUNK and CREATED messages it might send if appropriate. From @@ -2254,11 +2309,15 @@ MOVING Called when the object is about to be moved (whether due to Move, MoveTo, JumpTo, or any other reason). From is the object that caused the move, and Arg1 and Arg2 are the target X and Y coordinates. If the - return value is true, then the move is aborted. + return value is true, then the move is aborted. From will be zero if + it is the first pass of checking if it can be moved due to Connection; + in that case, if all first passes are successful then it will try again + the second pass with From set to the first object of the group, and + this second time they will actually be moved. PLAYERMOVING If an object with the Player flag is about to move, then after the MOVING message is sent, PLAYERMOVING is sent to all objects. From is the object which is moving, Arg1 and Arg2 are where it will be moved to, @@ -2290,12 +2349,18 @@ Some descriptions below are marked with an asterisk. If the Compatible flag is set for the object that returned this value, then all bits with the asterisk in the below descriptions are masked out (bit15 is only masked out for Compatible objects for diagonal movement). +(If the Connection flag is set for the object that is moving, then the +Compatible flag is ignored for the purpose of HIT/HITBY bits, but is not +ignored for other purposes.) + bit0 - Do not send the HITBY message to the target object. + Do not send the HITBY message to the target object. If the moving object + has the Connection flag, then this bit is set in Arg3, but this does not + prevent sending the HITBY message unless the return value also has bit0. bit1 Do not destroy either object due to hardness/sharpness. bit2 @@ -2302,10 +2367,11 @@ Do not attempt to shove the target object. bit3 Abort the move attempt immediately. Do not send any more HIT or HITBY messages, do not check hardness/sharpness, and do nothing else either. + This bit is also set in Arg3 if the object can't move due to Volume. bit4 Do not send the HITBY message to the target object or to any further objects at the target location. @@ -2313,14 +2379,17 @@ Do not destroy either object due to hardness/sharpness, nor should any further objects at the target location be destroyed due to sharpness. bit6 Do not attempt to shove the target object, nor attempt to shove any - other objects at the target location. + other objects at the target location. (If you are using the two pass + HIT/HITBY for connection movement, then this bit will automatically + be set during the first pass.) bit7 * - Do not attempt sliding. + Do not attempt sliding. (This bit is always set in Arg3 if it is due + to Connection, and always prevents sliding in this case.) bit8 Abort after sending the HITBY message. bit9 @@ -2335,17 +2404,21 @@ bit12 * If the move attempt fails, pretend it was successful, even though the object hasn't actually moved. This means that the result of Move will be 1 and that the MOVED message will trigger; it does not trigger any - ARRIVED, DEPARTED, FLOATED, or SUNK, nor does it set Distance. + ARRIVED, DEPARTED, FLOATED, or SUNK, nor does it set Distance. (If the + moving object has the Connection flag, then this does not stop it from + moving; it will move anyways if this flag is set.) bit13 * Abort before actually moving the object and before trying sliding. bit14 * - Do not set the Moved flag even if successful. + Do not set the Moved flag even if successful. (If you are using two pass + HIT/HITBY for connection movement, then this bit will automatically be + set in most cases during the first pass.) bit15 (*) Try again after trying shoving (whether or not the shoving is successful). If it tries to shove an object and it is successful, then it will automatically set this bit and automatically try again. @@ -2416,11 +2489,18 @@ Available for your own use. The return value of HITBY can also be an object instead of a number. In this case, a warp occurs. The movement is restarted, using the specified object as the origin of the movement, and that object's direction as the -direction of movement. +direction of movement. (This is not allowed if bit0 of Arg3 is set; in +that case, it is an error.) + +If the moving object has the Connection flag (and bit0 is set in Arg3), +then the return value of HIT or HITBY may be a mark. In this case, it +makes the object "sticky", adding it to the list of objects to be moved +as a part of the same connection group. (Returning a mark if bit0 of +Arg3 is not set is an error.) === Pattern matching === Where an instruction is expected, you can have pattern matching. This can Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -40,16 +40,23 @@ Value*array_data; Uint16 ndeadanim; DeadAnimation*deadanim; Uint8 no_dead_anim; Uint32 max_trigger; +Uint8 conn_option; typedef struct { Uint16 msg; Uint32 from; Value arg1,arg2,arg3; } MessageVars; + +typedef struct { + Uint32 obj; + Uint16 id; + Uint8 visual; +} Connection; static jmp_buf my_env; static const char*my_error; static MessageVars msgvars; static Uint8 lastimage_processing,changed,all_flushed; @@ -58,10 +65,13 @@ static const char*traceprefix; static Uint8 current_key; static Value quiz_obj; static Value traced_obj; static Uint32 control_obj=VOIDLINK; +static Connection conn[VSTACKSIZE]; +static int nconn,pconn; +static Uint8 conn_dir; #define Throw(x) (my_error=(x),longjmp(my_env,1)) #define StackReq(x,y) do{ if(vstackptr<(x)) Throw("Stack underflow"); if(vstackptr-(x)+(y)>=VSTACKSIZE) Throw("Stack overflow"); }while(0) #define Push(x) (vstack[vstackptr++]=(x)) #define Pop() (vstack[--vstackptr]) @@ -949,10 +959,272 @@ if(!(m&(m-1))) return 0; if(!(o->shovable&(1<x+x_delta[d2],o->y+y_delta[d2])<=o->climb) return 1; return vol+volume_at(o->x+x_delta[d2],o->y+y_delta[d2])<=max_volume; } + +static int move_dir(Uint32 from,Uint32 obj,Uint32 dir); + +static void add_connection(Uint32 obj) { + Object*o=objects[obj]; + if(nconn==VSTACKSIZE) Throw("Connection limit overflow"); + if((o->oflags^OF_CONNECTION)&(OF_MOVING|OF_DESTROYED|OF_CONNECTION|OF_BIZARRO)) return; + conn[nconn].obj=obj; + conn[nconn].id=nconn; // used for stable sorting + conn[nconn].visual=(o->oflags&OF_VISUALONLY)?1:0; + o->oflags|=OF_MOVING|OF_VISUALONLY; + nconn++; +} + +static int fake_move_dir(Uint32 obj,Uint32 dir,Uint8 no) { + // This is similar to move_dir, but specialized for the HIT/HITBY processing in connected_move. + // Note that this may result in calling the real move_dir due to shoving. + Object*o; + Object*oE; + Object*oF; + Uint32 objE,objF,objLF,objRF; + Uint32 hit=0; + Uint32 vol; + Value v; + if(StackProtection()) Throw("Call stack overflow during movement"); + if(obj==VOIDLINK) return 0; + o=objects[obj]; + restart: + if(hit&0x100000) dir=o->dir; + objF=obj_dir(obj,dir); + if(objF==VOIDLINK) goto fail; + if(hit) hit=0x800|(hit&0x10000000); + oF=objects[objF]; + objLF=obj_dir(obj,(dir+1)&7); + objRF=obj_dir(obj,(dir-1)&7); + if(height_at(oF->x,oF->y)<=o->climb) hit|=0x200000; + if(no) { + if((vol=classes[oF->class]->collisionLayers) && obj_layer_at(vol,oF->x,oF->y)!=VOIDLINK) goto fail; + hit|=0x4066; + } + if(dir&1) { + // Diagonal movement + hit|=0x80000; + vol=o->volume; + if(objLF!=VOIDLINK) vol+=volume_at(objects[objLF]->x,objects[objLF]->y); + if(objRF!=VOIDLINK) vol+=volume_at(objects[objRF]->x,objects[objRF]->y); + if(vol<=max_volume) { + objE=objF; + while(objE!=VOIDLINK) { + if(o->oflags&OF_DESTROYED) break; + oE=objects[objE]; + if(oE->height>0) { + hit&=0xFC287040; + v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit|0x81)); + if(v.t==TY_MARK) goto sticky; + if(v.t) Throw("Type mismatch in HIT/HITBY"); + hit|=v.u; + if(hit&8) goto fail; + if(!(hit&0x11)) { + v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(hit|0x81)); + if(v.t==TY_MARK) goto sticky; + if(v.t) Throw("Type mismatch in HIT/HITBY"); + hit|=v.u; + if(hit&8) goto fail; + } + } + // Shoving + if(!(hit&0x44) && (oE->shovable&(1<inertia>=oE->weight && !(oE->oflags&OF_VISUALONLY)) { + oE->inertia=o->inertia; + if(move_dir(obj,objE,dir)) { + if(!(oE->oflags&OF_DESTROYED)) o->inertia=oE->inertia; + hit|=0x8000; + if(hit&0x800000) goto restart; + } + } + objE=obj_below(objE); + } + if((hit&0x48000)==0x8000) goto restart; + if((hit&0x200000) && !(hit&0x402008)) { + if((hit&0x20000) || oF) goto success; else goto fail; + } + } else { + // Volume is too much; hit the objects it won't go between + if(o->oflags&OF_DESTROYED) goto fail; + objE=objLF; + while(objE!=VOIDLINK) { + oE=objects[objE]; + if(oE->height>0) { + v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(0x80089)); + if(v.t==TY_MARK) goto sticky; + if(v.t) Throw("Type mismatch in HIT/HITBY"); + if(!(v.u&1)) v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(v.u|0x80089)); + if(v.t==TY_MARK) goto sticky; + if(v.t==TY_SOUND || v.t==TY_USOUND) Throw("Type mismatch in HIT/HITBY"); + } + objE=obj_below(objE); + } + if(o->oflags&OF_DESTROYED) goto fail; + objE=objRF; + while(objE!=VOIDLINK) { + oE=objects[objE]; + if(oE->height>0) { + v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(0x80089)); + if(v.t==TY_MARK) goto sticky; + if(v.t) Throw("Type mismatch in HIT/HITBY"); + if(!(v.u&1)) v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(v.u|0x80089)); + if(v.t==TY_MARK) goto sticky; + if(v.t==TY_SOUND || v.t==TY_USOUND) Throw("Type mismatch in HIT/HITBY"); + } + objE=obj_below(objE); + } + } + } else { + // Orthogonal movement + if(!oF) goto fail; + objE=objF; + while(objE!=VOIDLINK) { + if(o->oflags&OF_DESTROYED) break; + oE=objects[objE]; + if(oE->height>0) { + hit&=~7; + // HIT/HITBY messages + v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit|0x81)); + if(v.t==TY_MARK) goto sticky; + if(v.t) Throw("Type mismatch in HIT/HITBY"); + hit|=v.u; + if(hit&8) goto fail; + if(!(hit&0x11)) { + v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(hit|0x81)); + if(v.t==TY_MARK) goto sticky; + if(v.t) Throw("Type mismatch in HIT/HITBY"); + hit|=v.u; + } + if(hit&0x108) goto fail; + // Hardness/sharpness + if(!(hit&0x22)) { + if(o->sharp[dir>>1]>oE->hard[(dir^4)>>1] && !v_bool(destroy(obj,objE,2))) hit|=0x8004; + } + if(hit&0x200) goto fail; + } + // Shoving + if(!(hit&0x44) && (oE->shovable&(1<inertia>=oE->weight && !(oE->oflags&OF_VISUALONLY)) { + oE->inertia=o->inertia; + if(move_dir(obj,objE,dir)) { + if(!(oE->oflags&OF_DESTROYED)) o->inertia=oE->inertia; + hit|=0x8000; + if(hit&0x800000) goto restart; + } + } + if(hit&0x400) goto fail; + objE=obj_below(objE); + } + if(hit&0x2008) goto fail; + if((hit&0x48000)==0x8000) goto restart; + if((hit&0x200000) && !(hit&0x400000)) goto success; + } + fail: if(hit&0x1000) goto success; o->inertia=0; return 0; + success: return 1; + sticky: add_connection(objE); return 2; +} + +static int compare_connection(const void*v1,const void*v2) { + // Ensure that the sorting is stable. + const Connection*c1=v1; + const Connection*c2=v2; + Object*o1=objects[c1->obj]; + Object*o2=objects[c2->obj]; + switch(conn_dir) { + case 0: case 1: return (o2->x-o1->x)?:(o1->y-o2->y)?:c2->id-c1->id; // E, NE + case 2: case 3: return (o1->y-o2->y)?:(o1->x-o2->x)?:c2->id-c1->id; // N, NW + case 4: case 5: return (o1->x-o2->x)?:(o2->y-o1->y)?:c2->id-c1->id; // W, SW + case 6: case 7: return (o2->y-o1->y)?:(o2->x-o1->x)?:c2->id-c1->id; // S, SE + } +} + +static int connected_move(Uint32 obj,Uint8 dir) { + Object*o; + Uint32 n; + Sint32 inertia=objects[obj]->inertia; + Sint32 weight=0; + int first=nconn; + int last; + int i,j; + if(nconn!=pconn) Throw("Improper nested connected move"); + // Find and add all connections + add_connection(obj); + for(i=first;iinertia=inertia; + if(v_bool(send_message(obj,n,MSG_CONNECT,NVALUE(i-first),NVALUE(dir),NVALUE(weight)))) goto fail; + weight+=objects[n]->weight; + } + if(conn_option&0x01) { + for(i=first;iinertiaweight; + } + } else { + weight=objects[conn[first].obj]->weight; + } + last=pconn=nconn; + // Check HIT/HITBY; may shove other objects + if(conn_option&0x02) { + for(i=first;idir=dir,1); + if(!j) goto fail; + if(j==2) { + if(nconn==pconn) Throw("This object cannot be sticky"); + i=pconn; + goto loop1; + } + } + } + for(i=first;iinertia=inertia; + j=fake_move_dir(n,o->dir=dir,0); + if(!j) goto fail; + if((conn_option&0x01) && !(o->oflags&OF_DESTROYED)) inertia=o->inertia; + if(j==2) { + if(nconn==pconn) Throw("This object cannot be sticky"); + i=pconn; + goto loop1; + } + } + // Check if each object in the group is movable + for(i=first;ix+x_delta[dir]),NVALUE(o->y+y_delta[dir]),NVALUE(0)))) goto fail; + if(classes[o->class]->cflags&CF_PLAYER) { + n=lastobj; + while(n!=VOIDLINK) { + if(v_bool(send_message(conn[i].obj,n,MSG_PLAYERMOVING,NVALUE(o->x+x_delta[dir]),NVALUE(o->y+y_delta[dir]),NVALUE(0)))) goto fail; + n=objects[n]->prev; + } + } + if(j=classes[o->class]->collisionLayers) { + if(obj_layer_at(j,o->x+x_delta[dir],o->y+y_delta[dir])!=VOIDLINK) goto fail; + } + } + // Move everything in the group + conn_dir=dir; + qsort(conn+first,last-first,sizeof(Connection),compare_connection); + for(i=first;ioflags&=~OF_VISUALONLY; + if(move_to(obj,n,o->x+x_delta[dir],o->y+y_delta[dir])) o->oflags|=OF_MOVED; + } + // Done + j=1; goto done; + fail: j=0; + done: + for(i=first;ioflags&=~OF_MOVING; + if(conn[i].visual) o->oflags|=OF_VISUALONLY; else o->oflags&=~OF_VISUALONLY; + } + pconn=nconn=first; + return j; +} static int move_dir(Uint32 from,Uint32 obj,Uint32 dir) { // This function is complicated, and there may be mistakes. Object*o; Object*oE; @@ -965,10 +1237,11 @@ if(StackProtection()) Throw("Call stack overflow during movement"); if(obj==VOIDLINK) return 0; oW=o=objects[objW=obj]; o->dir=dir=resolve_dir(obj,dir); if(o->weight>o->inertia) goto fail; + if(o->oflags&OF_CONNECTION) return connected_move(obj,dir); o->inertia-=o->weight; restart: if(hit&0x100000) dir=o->dir; objF=obj_dir(objW,dir); if(objF==VOIDLINK) goto fail; @@ -987,11 +1260,11 @@ objE=objF; while(objE!=VOIDLINK) { if(o->oflags&(OF_DESTROYED|OF_VISUALONLY)) break; oE=objects[objE]; if(oE->height>0) { - hit&=0xFC287000; + hit&=0xFC287040; v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit)); if(v.t) Throw("Type mismatch in HIT/HITBY"); hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xC0090F7F:-1L); if(hit&8) goto fail; if(!(hit&0x11)) { @@ -1206,11 +1479,11 @@ Uint8 x,y; Value v; if(StackProtection()) Throw("Call stack overflow during movement"); if(obj==VOIDLINK || obj==control_obj) return 0; o=objects[obj]; - if(o->oflags&(OF_DESTROYED|OF_BIZARRO)) return 0; + if(o->oflags&(OF_DESTROYED|OF_BIZARRO|OF_CONNECTION)) return 0; dir=resolve_dir(obj,dir); x=o->x+x_delta[dir]; y=o->y+y_delta[dir]; if(x<1 || x>pfwidth || y<1 || y>pfheight) return 0; if(plus) { if(o->oflags&OF_MOVING) { @@ -2498,10 +2771,16 @@ case OP_COLLISIONLAYERS_C: StackReq(1,1); i=v_object(Pop()); if(i==VOIDLINK) Push(NVALUE(0)); else Push(NVALUE(classes[objects[i]->class]->collisionLayers)); break; case OP_COLOC: StackReq(1,1); t1=Pop(); i=colocation(obj,v_object(t1)); Push(NVALUE(i)); break; case OP_COLOC_C: StackReq(2,1); t1=Pop(); t2=Pop(); i=colocation(v_object(t1),v_object(t2)); Push(NVALUE(i)); break; case OP_COMPATIBLE: StackReq(0,1); if(classes[o->class]->cflags&CF_COMPATIBLE) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_COMPATIBLE_C: StackReq(1,1); GetClassFlagOf(CF_COMPATIBLE); break; + case OP_CONNECT: NoIgnore(); add_connection(obj); break; + case OP_CONNECT_C: NoIgnore(); StackReq(1,0); i=v_object(Pop()); if(i!=VOIDLINK) add_connection(i); break; + case OP_CONNECTION: StackReq(0,1); if(o->oflags&OF_CONNECTION) Push(NVALUE(1)); else Push(NVALUE(0)); break; + case OP_CONNECTION_C: StackReq(1,1); GetFlagOf(OF_CONNECTION); break; + case OP_CONNECTION_E: NoIgnore(); StackReq(1,0); if(v_bool(Pop())) o->oflags|=OF_CONNECTION; else o->oflags&=~OF_CONNECTION; break; + case OP_CONNECTION_EC: NoIgnore(); StackReq(2,0); SetFlagOf(OF_CONNECTION); break; case OP_CONTROL: StackReq(0,1); Push(OVALUE(control_obj)); break; case OP_COPYARRAY: NoIgnore(); StackReq(2,0); t2=Pop(); t1=Pop(); v_copy_array(t1,t2); break; case OP_COUNT: StackReq(1,2); i=v_count(); Push(NVALUE(i)); break; case OP_CREATE: NoIgnore(); StackReq(5,1); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_create(obj,t1,t2,t3,t4,t5)); break; case OP_CREATE_D: NoIgnore(); StackReq(5,0); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_create(obj,t1,t2,t3,t4,t5); break; @@ -2549,10 +2828,12 @@ case OP_DUP: StackReq(1,2); t1=Pop(); Push(t1); Push(t1); break; case OP_EQ: StackReq(2,1); t2=Pop(); t1=Pop(); Push(NVALUE(v_equal(t1,t2)?1:0)); break; case OP_EQ2: StackReq(4,1); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(NVALUE(v_equal(t1,t3)?(v_equal(t2,t4)?1:0):0)); break; case OP_EXEC: StackReq(1,0); t1=Pop(); i=convert_link(t1,obj,code); if(i==0xFFFF) return; code=classes[i>>16]->codes; ptr=i&0xFFFF; break; case OP_EXEC_C: StackReq(1,0); t1=Pop(); i=convert_link(t1,obj,code); if(i!=0xFFFF) execute_program(classes[i>>16]->codes,i&0xFFFF,obj); break; + case OP_FAKEMOVE: NoIgnore(); StackReq(1,1); t1=Pop(); Numeric(t1); Push(NVALUE(fake_move_dir(obj,resolve_dir(obj,t1.u),0))); break; + case OP_FAKEMOVE_C: NoIgnore(); StackReq(2,1); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i==VOIDLINK) Push(NVALUE(0)); else Push(NVALUE(fake_move_dir(i,resolve_dir(i,t1.u),0))); break; case OP_FINISHED: StackReq(0,1); Push(NVALUE(all_flushed)); break; case OP_FINISHED_E: StackReq(1,0); t1=Pop(); Numeric(t1); all_flushed=t1.u; break; case OP_FLIP: v_flip(); break; case OP_FLUSHCLASS: NoIgnore(); StackReq(1,0); t1=Pop(); if(t1.t==TY_CLASS) flush_class(t1.u); else if(t1.t==TY_NUMBER && t1.s==-1) flush_all(); else if(t1.t) Throw("Type mismatch"); break; case OP_FLUSHOBJ: NoIgnore(); flush_object(obj); break; @@ -2948,10 +3229,11 @@ nlevelstrings=0; free(deadanim); deadanim=0; ndeadanim=0; control_obj=VOIDLINK; + nconn=pconn=0; } static inline int try_sharp(Uint32 n1,Uint32 n2) { Object*o=objects[n1]; Object*p=objects[n2]; Index: game.c ================================================================== --- game.c +++ game.c @@ -379,11 +379,11 @@ static inline void exam_flags(int y,Uint16 v) { y=(y-exam_scroll)*8; if(y<0 || y>screen->h-8) return; draw_text(0,y,"Flags:",0xF0,0xF7); - draw_text(200,y,"--- --- --- --- --- --- --- --- --- --- ---",0xF0,0xF8); + draw_text(200,y,"--- --- --- --- --- --- --- --- --- --- --- --- --- ---",0xF0,0xF8); if(v&OF_INVISIBLE) draw_text(200,y,"Inv",0xF0,0xFF); if(v&OF_VISUALONLY) draw_text(232,y,"Vis",0xF0,0xFF); if(v&OF_STEALTHY) draw_text(264,y,"Stl",0xF0,0xFF); if(v&OF_BUSY) draw_text(296,y,"Bus",0xF0,0xFF); if(v&OF_USERSTATE) draw_text(328,y,"Ust",0xF0,0xFF); @@ -391,10 +391,13 @@ if(v&OF_MOVED) draw_text(392,y,"Mov",0xF0,0xFF); if(v&OF_DONE) draw_text(424,y,"Don",0xF0,0xFF); if(v&OF_KEYCLEARED) draw_text(456,y,"Key",0xF0,0xFF); if(v&OF_DESTROYED) draw_text(488,y,"Des",0xF0,0xFF); if(v&OF_BIZARRO) draw_text(520,y,"Biz",0xF0,0xFF); + if(v&OF_CONNECTION) draw_text(552,y,"Con",0xF0,0xFF); + if(v&OF_MOVING) draw_text(584,y,"Mvi",0xF0,0xFF); + if(v&OF_ORDERED) draw_text(616,y,"Ord",0xF0,0xFF); } static inline void exam_hardsharp(const char*t,int y,Uint16*v) { int i; char buf[16]; Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -36,11 +36,11 @@ #define ZVALUE(x) UVALUE(x,TY_STRING) #define OVALUE(x) ((x)==VOIDLINK?NVALUE(0):UVALUE(x,objects[x]->generation)) #define ValueTo64(v) (((sqlite3_int64)((v).u))|(((sqlite3_int64)((v).t))<<32)) #define ValueEq(x,y) ((x).t==(y).t && (x).u==(y).u) -#define N_MESSAGES 25 +#define N_MESSAGES 26 extern const char*const standard_message_names[]; extern const char*const standard_sound_names[]; extern const char*const heromesh_key_names[256]; extern sqlite3*userdb; @@ -147,10 +147,11 @@ #define OF_DESTROYED 0x0200 #define OF_BIZARRO 0x0400 #define OF_MOVED2 0x0800 #define OF_MOVING 0x1000 #define OF_ORDERED 0x2000 +#define OF_CONNECTION 0x4000 typedef struct { const char*name; const char*edithelp; // not present if CF_GROUP const char*gamehelp; // not present if CF_GROUP @@ -301,10 +302,11 @@ extern Value*array_data; extern Uint16 ndeadanim; extern DeadAnimation*deadanim; extern Uint8 no_dead_anim; extern Uint32 max_trigger; +extern Uint8 conn_option; const unsigned char*value_string_ptr(Value v); void pfunlink(Uint32 n); void pflink(Uint32 n); Uint32 objalloc(Uint16 c); Index: instruc ================================================================== --- instruc +++ instruc @@ -183,10 +183,11 @@ ,=VisualOnly ,=Stealthy ,=Moved ,=Moving ,=Done +,=Connection ,Destroyed ,Player ,Compatible ,CollisionLayers Self @@ -231,15 +232,17 @@ BroadcastSum ; Broadcast, but result is sum of return values BroadcastSumEx chain ,Chebyshev ,Coloc +,Connect .Create Data DelInventory Delta .,Destroy +,FakeMove FlushClass ,FlushObj GetInventory HeightAt HitMe Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -265,236 +265,244 @@ #define OP_MOVING_EC 39030 #define OP_DONE 32887 #define OP_DONE_C 34935 #define OP_DONE_E 36983 #define OP_DONE_EC 39031 -#define OP_DESTROYED 32888 -#define OP_DESTROYED_C 34936 -#define OP_PLAYER 32889 -#define OP_PLAYER_C 34937 -#define OP_COMPATIBLE 32890 -#define OP_COMPATIBLE_C 34938 -#define OP_COLLISIONLAYERS 32891 -#define OP_COLLISIONLAYERS_C 34939 -#define OP_SELF 32892 -#define OP_MSG 32893 -#define OP_FROM 32894 -#define OP_ARG1 32895 -#define OP_ARG1_E 36991 -#define OP_ARG2 32896 -#define OP_ARG2_E 36992 -#define OP_ARG3 32897 -#define OP_ARG3_E 36993 -#define OP_MOVENUMBER 32898 -#define OP_MOVENUMBER_E 36994 -#define OP_LEVEL 32899 -#define OP_KEY 32900 -#define OP_FINISHED 32901 -#define OP_FINISHED_E 36997 -#define OP_BACKGROUND 32902 -#define OP_CODEPAGE 32903 -#define OP_ORDER 32904 -#define OP_CONTROL 32905 -#define OP_LEVELTABLE 32906 -#define OP_INPUT 32907 -#define OP_QUIZ 32908 -#define OP_INPLACE 32909 -#define OP_DEFAULTIMAGE 32910 -#define OP_HELP 32911 -#define OP_EDITORHELP 32912 -#define OP_OTHERS 32913 -#define OP_SUBS 32914 -#define OP_ANIMATE 32915 -#define OP_ANIMATE_E 37011 -#define OP_ANIMATEDEAD 32916 -#define OP_ANIMATEDEAD_E 37012 -#define OP_ASSASSINATE 32917 -#define OP_ASSASSINATE_C 34965 -#define OP_BROADCAST 32918 -#define OP_BROADCAST_D 41110 -#define OP_BROADCASTAND 32919 -#define OP_BROADCASTANDEX 32920 -#define OP_BROADCASTCLASS 32921 -#define OP_BROADCASTEX 32922 -#define OP_BROADCASTEX_D 41114 -#define OP_BROADCASTLIST 32923 -#define OP_BROADCASTLISTEX 32924 -#define OP_BROADCASTSUM 32925 -#define OP_BROADCASTSUMEX 32926 -#define OP_CHAIN 32927 -#define OP_CHEBYSHEV 32928 -#define OP_CHEBYSHEV_C 34976 -#define OP_COLOC 32929 -#define OP_COLOC_C 34977 -#define OP_CREATE 32930 -#define OP_CREATE_D 41122 -#define OP_DATA 32931 -#define OP_DELINVENTORY 32932 -#define OP_DELTA 32933 -#define OP_DESTROY 32934 -#define OP_DESTROY_C 34982 -#define OP_DESTROY_D 41126 -#define OP_DESTROY_CD 43174 -#define OP_FLUSHCLASS 32935 -#define OP_FLUSHOBJ 32936 -#define OP_FLUSHOBJ_C 34984 -#define OP_GETINVENTORY 32937 -#define OP_HEIGHTAT 32938 -#define OP_HITME 32939 -#define OP_IGNOREKEY 32940 -#define OP_INTMOVE 32941 -#define OP_INTMOVE_C 34989 -#define OP_INTMOVE_D 41133 -#define OP_INTMOVE_CD 43181 -#define OP_JUMPTO 32942 -#define OP_JUMPTO_C 34990 -#define OP_JUMPTO_D 41134 -#define OP_JUMPTO_CD 43182 -#define OP_LOC 32943 -#define OP_LOC_C 34991 -#define OP_LOCATEME 32944 -#define OP_LOCATEME_C 34992 -#define OP_LOSELEVEL 32945 -#define OP_MANHATTAN 32946 -#define OP_MANHATTAN_C 34994 -#define OP_MAXINVENTORY 32947 -#define OP_MOVE 32948 -#define OP_MOVE_C 34996 -#define OP_MOVE_D 41140 -#define OP_MOVE_CD 43188 -#define OP_MOVEPLUS 32949 -#define OP_MOVEPLUS_C 34997 -#define OP_MOVEPLUS_D 41141 -#define OP_MOVEPLUS_CD 43189 -#define OP_MOVETO 32950 -#define OP_MOVETO_C 34998 -#define OP_MOVETO_D 41142 -#define OP_MOVETO_CD 43190 -#define OP_PLUSMOVE 32951 -#define OP_PLUSMOVE_C 34999 -#define OP_PLUSMOVE_D 41143 -#define OP_PLUSMOVE_CD 43191 -#define OP_MINUSMOVE 32952 -#define OP_MINUSMOVE_C 35000 -#define OP_MINUSMOVE_D 41144 -#define OP_MINUSMOVE_CD 43192 -#define OP_NEWX 32953 -#define OP_NEWXY 32954 -#define OP_NEWY 32955 -#define OP_OBJABOVE 32956 -#define OP_OBJABOVE_C 35004 -#define OP_OBJBELOW 32957 -#define OP_OBJBELOW_C 35005 -#define OP_OBJBOTTOMAT 32958 -#define OP_OBJCLASSAT 32959 -#define OP_OBJDIR 32960 -#define OP_OBJDIR_C 35008 -#define OP_OBJLAYERAT 32961 -#define OP_OBJMOVINGTO 32962 -#define OP_OBJTOPAT 32963 -#define OP_POPUP 32964 -#define OP_POPUPARGS 32965 -#define OP_REL 32966 -#define OP_REL_C 35014 -#define OP_SEEK 32967 -#define OP_SEEK_C 35015 -#define OP_SEND 32968 -#define OP_SEND_C 35016 -#define OP_SEND_D 41160 -#define OP_SEND_CD 43208 -#define OP_SENDEX 32969 -#define OP_SENDEX_C 35017 -#define OP_SENDEX_D 41161 -#define OP_SENDEX_CD 43209 -#define OP_SETINVENTORY 32970 -#define OP_SOUND 32971 -#define OP_SWEEP 32972 -#define OP_SWEEPEX 32973 -#define OP_SYNCHRONIZE 32974 -#define OP_TARGET 32975 -#define OP_TARGET_C 35023 -#define OP_TRACE 32976 -#define OP_TRIGGER 32977 -#define OP_TRIGGERAT 32978 -#define OP_VOLUMEAT 32979 -#define OP_WINLEVEL 32980 -#define OP_XDIR 32981 -#define OP_XDIR_C 35029 -#define OP_XYDIR 32982 -#define OP_YDIR 32983 -#define OP_YDIR_C 35031 -#define OP_MARK 32984 -#define OP_TMARK 32985 -#define OP_IN 32986 -#define OP_NIN 32987 -#define OP_MBEGIN 32988 -#define OP_FLIP 32989 -#define OP_COUNT 32990 -#define OP_CLEAR 32991 -#define OP_UNIQ 32992 -#define OP_ARRAY 32993 -#define OP_GETARRAY 32994 -#define OP_INITARRAY 32995 -#define OP_SETARRAY 32996 -#define OP_ARRAYCELL 32997 -#define OP_ARRAYSLICE 32998 -#define OP_COPYARRAY 32999 -#define OP_DOTPRODUCT 33000 -#define OP_PATTERN 33001 -#define OP_PATTERN_C 35049 -#define OP_PATTERN_E 37097 -#define OP_PATTERN_EC 39145 -#define OP_PATTERNS 33002 -#define OP_PATTERNS_C 35050 -#define OP_PATTERNS_E 37098 -#define OP_PATTERNS_EC 39146 -#define OP_ROOK 33003 -#define OP_BISHOP 33004 -#define OP_QUEEN 33005 -#define OP_CUT 33006 -#define OP_BIZARRO 33007 -#define OP_BIZARRO_C 35055 -#define OP_BIZARRO_E 37103 -#define OP_BIZARRO_EC 39151 -#define OP_BIZARROSWAP 33008 -#define OP_BIZARROSWAP_D 41200 -#define OP_SWAPWORLD 33009 -#define OP_ABSTRACT 33010 -#define OP_SUPER 33011 -#define OP_SUPER_C 35059 -#define OP_FUNCTION 33012 -#define OP_LOCAL 33013 -#define OP_LABEL 33014 -#define OP_STRING 33015 -#define OP_INT16 33016 -#define OP_INT32 33017 -#define OP_DISPATCH 33018 -#define OP_USERFLAG 33019 +#define OP_CONNECTION 32888 +#define OP_CONNECTION_C 34936 +#define OP_CONNECTION_E 36984 +#define OP_CONNECTION_EC 39032 +#define OP_DESTROYED 32889 +#define OP_DESTROYED_C 34937 +#define OP_PLAYER 32890 +#define OP_PLAYER_C 34938 +#define OP_COMPATIBLE 32891 +#define OP_COMPATIBLE_C 34939 +#define OP_COLLISIONLAYERS 32892 +#define OP_COLLISIONLAYERS_C 34940 +#define OP_SELF 32893 +#define OP_MSG 32894 +#define OP_FROM 32895 +#define OP_ARG1 32896 +#define OP_ARG1_E 36992 +#define OP_ARG2 32897 +#define OP_ARG2_E 36993 +#define OP_ARG3 32898 +#define OP_ARG3_E 36994 +#define OP_MOVENUMBER 32899 +#define OP_MOVENUMBER_E 36995 +#define OP_LEVEL 32900 +#define OP_KEY 32901 +#define OP_FINISHED 32902 +#define OP_FINISHED_E 36998 +#define OP_BACKGROUND 32903 +#define OP_CODEPAGE 32904 +#define OP_ORDER 32905 +#define OP_CONTROL 32906 +#define OP_LEVELTABLE 32907 +#define OP_INPUT 32908 +#define OP_QUIZ 32909 +#define OP_INPLACE 32910 +#define OP_DEFAULTIMAGE 32911 +#define OP_HELP 32912 +#define OP_EDITORHELP 32913 +#define OP_OTHERS 32914 +#define OP_SUBS 32915 +#define OP_ANIMATE 32916 +#define OP_ANIMATE_E 37012 +#define OP_ANIMATEDEAD 32917 +#define OP_ANIMATEDEAD_E 37013 +#define OP_ASSASSINATE 32918 +#define OP_ASSASSINATE_C 34966 +#define OP_BROADCAST 32919 +#define OP_BROADCAST_D 41111 +#define OP_BROADCASTAND 32920 +#define OP_BROADCASTANDEX 32921 +#define OP_BROADCASTCLASS 32922 +#define OP_BROADCASTEX 32923 +#define OP_BROADCASTEX_D 41115 +#define OP_BROADCASTLIST 32924 +#define OP_BROADCASTLISTEX 32925 +#define OP_BROADCASTSUM 32926 +#define OP_BROADCASTSUMEX 32927 +#define OP_CHAIN 32928 +#define OP_CHEBYSHEV 32929 +#define OP_CHEBYSHEV_C 34977 +#define OP_COLOC 32930 +#define OP_COLOC_C 34978 +#define OP_CONNECT 32931 +#define OP_CONNECT_C 34979 +#define OP_CREATE 32932 +#define OP_CREATE_D 41124 +#define OP_DATA 32933 +#define OP_DELINVENTORY 32934 +#define OP_DELTA 32935 +#define OP_DESTROY 32936 +#define OP_DESTROY_C 34984 +#define OP_DESTROY_D 41128 +#define OP_DESTROY_CD 43176 +#define OP_FAKEMOVE 32937 +#define OP_FAKEMOVE_C 34985 +#define OP_FLUSHCLASS 32938 +#define OP_FLUSHOBJ 32939 +#define OP_FLUSHOBJ_C 34987 +#define OP_GETINVENTORY 32940 +#define OP_HEIGHTAT 32941 +#define OP_HITME 32942 +#define OP_IGNOREKEY 32943 +#define OP_INTMOVE 32944 +#define OP_INTMOVE_C 34992 +#define OP_INTMOVE_D 41136 +#define OP_INTMOVE_CD 43184 +#define OP_JUMPTO 32945 +#define OP_JUMPTO_C 34993 +#define OP_JUMPTO_D 41137 +#define OP_JUMPTO_CD 43185 +#define OP_LOC 32946 +#define OP_LOC_C 34994 +#define OP_LOCATEME 32947 +#define OP_LOCATEME_C 34995 +#define OP_LOSELEVEL 32948 +#define OP_MANHATTAN 32949 +#define OP_MANHATTAN_C 34997 +#define OP_MAXINVENTORY 32950 +#define OP_MOVE 32951 +#define OP_MOVE_C 34999 +#define OP_MOVE_D 41143 +#define OP_MOVE_CD 43191 +#define OP_MOVEPLUS 32952 +#define OP_MOVEPLUS_C 35000 +#define OP_MOVEPLUS_D 41144 +#define OP_MOVEPLUS_CD 43192 +#define OP_MOVETO 32953 +#define OP_MOVETO_C 35001 +#define OP_MOVETO_D 41145 +#define OP_MOVETO_CD 43193 +#define OP_PLUSMOVE 32954 +#define OP_PLUSMOVE_C 35002 +#define OP_PLUSMOVE_D 41146 +#define OP_PLUSMOVE_CD 43194 +#define OP_MINUSMOVE 32955 +#define OP_MINUSMOVE_C 35003 +#define OP_MINUSMOVE_D 41147 +#define OP_MINUSMOVE_CD 43195 +#define OP_NEWX 32956 +#define OP_NEWXY 32957 +#define OP_NEWY 32958 +#define OP_OBJABOVE 32959 +#define OP_OBJABOVE_C 35007 +#define OP_OBJBELOW 32960 +#define OP_OBJBELOW_C 35008 +#define OP_OBJBOTTOMAT 32961 +#define OP_OBJCLASSAT 32962 +#define OP_OBJDIR 32963 +#define OP_OBJDIR_C 35011 +#define OP_OBJLAYERAT 32964 +#define OP_OBJMOVINGTO 32965 +#define OP_OBJTOPAT 32966 +#define OP_POPUP 32967 +#define OP_POPUPARGS 32968 +#define OP_REL 32969 +#define OP_REL_C 35017 +#define OP_SEEK 32970 +#define OP_SEEK_C 35018 +#define OP_SEND 32971 +#define OP_SEND_C 35019 +#define OP_SEND_D 41163 +#define OP_SEND_CD 43211 +#define OP_SENDEX 32972 +#define OP_SENDEX_C 35020 +#define OP_SENDEX_D 41164 +#define OP_SENDEX_CD 43212 +#define OP_SETINVENTORY 32973 +#define OP_SOUND 32974 +#define OP_SWEEP 32975 +#define OP_SWEEPEX 32976 +#define OP_SYNCHRONIZE 32977 +#define OP_TARGET 32978 +#define OP_TARGET_C 35026 +#define OP_TRACE 32979 +#define OP_TRIGGER 32980 +#define OP_TRIGGERAT 32981 +#define OP_VOLUMEAT 32982 +#define OP_WINLEVEL 32983 +#define OP_XDIR 32984 +#define OP_XDIR_C 35032 +#define OP_XYDIR 32985 +#define OP_YDIR 32986 +#define OP_YDIR_C 35034 +#define OP_MARK 32987 +#define OP_TMARK 32988 +#define OP_IN 32989 +#define OP_NIN 32990 +#define OP_MBEGIN 32991 +#define OP_FLIP 32992 +#define OP_COUNT 32993 +#define OP_CLEAR 32994 +#define OP_UNIQ 32995 +#define OP_ARRAY 32996 +#define OP_GETARRAY 32997 +#define OP_INITARRAY 32998 +#define OP_SETARRAY 32999 +#define OP_ARRAYCELL 33000 +#define OP_ARRAYSLICE 33001 +#define OP_COPYARRAY 33002 +#define OP_DOTPRODUCT 33003 +#define OP_PATTERN 33004 +#define OP_PATTERN_C 35052 +#define OP_PATTERN_E 37100 +#define OP_PATTERN_EC 39148 +#define OP_PATTERNS 33005 +#define OP_PATTERNS_C 35053 +#define OP_PATTERNS_E 37101 +#define OP_PATTERNS_EC 39149 +#define OP_ROOK 33006 +#define OP_BISHOP 33007 +#define OP_QUEEN 33008 +#define OP_CUT 33009 +#define OP_BIZARRO 33010 +#define OP_BIZARRO_C 35058 +#define OP_BIZARRO_E 37106 +#define OP_BIZARRO_EC 39154 +#define OP_BIZARROSWAP 33011 +#define OP_BIZARROSWAP_D 41203 +#define OP_SWAPWORLD 33012 +#define OP_ABSTRACT 33013 +#define OP_SUPER 33014 +#define OP_SUPER_C 35062 +#define OP_FUNCTION 33015 +#define OP_LOCAL 33016 +#define OP_LABEL 33017 +#define OP_STRING 33018 +#define OP_INT16 33019 +#define OP_INT32 33020 +#define OP_DISPATCH 33021 +#define OP_USERFLAG 33022 #ifdef HEROMESH_CLASS static const Op_Names op_names[]={ {"*",8486943}, {"+",8421405}, -{"+Move",10584247}, +{"+Move",10584250}, {"-",8421406}, -{"-Move",10584248}, +{"-Move",10584251}, {"-rot",8421382}, {".",10518528}, {"/",8486944}, {"ANHH",8389394}, {"ARRIVED",8389124}, -{"Abstract",8683762}, -{"Animate",8552595}, -{"AnimateDead",8552596}, -{"Arg1",8552575}, -{"Arg2",8552576}, -{"Arg3",8552577}, -{"Array",8683745}, -{"ArrayCell",8421605}, -{"ArraySlice",8421606}, +{"Abstract",8683765}, +{"Animate",8552596}, +{"AnimateDead",8552597}, +{"Arg1",8552576}, +{"Arg2",8552577}, +{"Arg3",8552578}, +{"Array",8683748}, +{"ArrayCell",8421608}, +{"ArraySlice",8421609}, {"Arrivals",8618092}, {"Arrived",8618090}, -{"Assassinate",8487061}, +{"Assassinate",8487062}, {"B",9437196}, {"BANG",8389380}, {"BEDOINGNG",8389406}, {"BEEDEEP",8389404}, {"BEGIN_TURN",8389123}, @@ -503,230 +511,234 @@ {"BOUNCE",8389415}, {"BRRREEET",8389396}, {"BRRRT",8389395}, {"BUZZER",8389420}, {"BWEEP",8389397}, -{"Background",8683654}, -{"Bishop",8683756}, -{"Bizarro",8618223}, -{"BizarroSwap",10518768}, -{"Broadcast",10518678}, -{"BroadcastAnd",8421527}, -{"BroadcastAndEx",8421528}, -{"BroadcastEx",10518682}, -{"BroadcastList",8421531}, -{"BroadcastListEx",8421532}, -{"BroadcastSum",8421533}, -{"BroadcastSumEx",8421534}, +{"Background",8683655}, +{"Bishop",8683759}, +{"Bizarro",8618226}, +{"BizarroSwap",10518771}, +{"Broadcast",10518679}, +{"BroadcastAnd",8421528}, +{"BroadcastAndEx",8421529}, +{"BroadcastEx",10518683}, +{"BroadcastList",8421532}, +{"BroadcastListEx",8421533}, +{"BroadcastSum",8421534}, +{"BroadcastSumEx",8421535}, {"Busy",8618094}, {"CHEEP",8389393}, {"CHYEW",8389392}, {"CLICK",8389388}, {"COLLIDE",8389142}, {"COLLIDEBY",8389141}, {"COLLIDING",8389143}, {"CONFLICT",8389140}, +{"CONNECT",8389145}, {"CREATE",8389121}, {"CREATED",8389137}, -{"Chebyshev",8487072}, +{"Chebyshev",8487073}, {"Class",8486976}, {"Climb",9142356}, -{"CodePage",8683655}, -{"CollisionLayers",8487035}, -{"Coloc",8487073}, -{"Compatible",8487034}, -{"Control",8421513}, -{"CopyArray",8421607}, -{"Create",10518690}, +{"CodePage",8683656}, +{"CollisionLayers",8487036}, +{"Coloc",8487074}, +{"Compatible",8487035}, +{"Connect",8487075}, +{"Connection",8618104}, +{"Control",8421514}, +{"CopyArray",8421610}, +{"Create",10518692}, {"DEEP_POP",8389417}, {"DEPARTED",8389125}, {"DESTROY",8389122}, {"DESTROYED",8389136}, {"DINK",8389390}, {"DOOR",8389378}, {"DRLRLRINK",8389398}, {"DYUPE",8389413}, -{"Data",8421539}, -{"DefaultImage",8683662}, -{"DelInventory",8421540}, -{"Delta",8421541}, +{"Data",8421541}, +{"DefaultImage",8683663}, +{"DelInventory",8421542}, +{"Delta",8421543}, {"Density",9142348}, {"Departed",8618091}, {"Departures",8618093}, -{"Destroy",10584230}, -{"Destroyed",8487032}, +{"Destroy",10584232}, +{"Destroyed",8487033}, {"Dir",8618054}, {"Distance",9142346}, {"Done",8618103}, -{"DotProduct",8421608}, +{"DotProduct",8421611}, {"E",9437184}, {"END_TURN",8389139}, -{"EditorHelp",8683664}, +{"EditorHelp",8683665}, {"F",9437192}, {"FAROUT",8389421}, {"FFFFTT",8389399}, {"FLOATED",8389132}, {"FROG",8389383}, -{"Finished",8552581}, -{"FlushClass",8421543}, -{"FlushObj",8487080}, -{"From",8421502}, +{"FakeMove",8487081}, +{"Finished",8552582}, +{"FlushClass",8421546}, +{"FlushObj",8487083}, +{"From",8421503}, {"GLASS",8389379}, {"GLISSANT",8389419}, -{"GetArray",8421602}, -{"GetInventory",8421545}, +{"GetArray",8421605}, +{"GetInventory",8421548}, {"HAWK",8389425}, {"HEARTBEAT",8389407}, {"HIT",8389134}, {"HITBY",8389135}, {"Hard",8618072}, {"Height",9142354}, -{"HeightAt",8421546}, -{"Help",8683663}, -{"HitMe",8421547}, +{"HeightAt",8421549}, +{"Help",8683664}, +{"HitMe",8421550}, {"INIT",8389120}, -{"IgnoreKey",8421548}, +{"IgnoreKey",8421551}, {"Image",8618055}, -{"InPlace",8683661}, +{"InPlace",8683662}, {"Inertia",9142344}, -{"InitArray",8421603}, -{"Input",8683659}, -{"IntMove",10584237}, +{"InitArray",8421606}, +{"Input",8683660}, +{"IntMove",10584240}, {"Invisible",8618095}, {"JAYAYAYNG",8389416}, {"JUMPED",8389128}, -{"JumpTo",10584238}, +{"JumpTo",10584241}, {"KEWEL",8389422}, {"KEY",8389129}, {"KLECK",8389387}, {"KLINKK",8389385}, -{"Key",8421508}, +{"Key",8421509}, {"KeyCleared",8618096}, {"L",9437194}, {"LASTIMAGE",8389126}, {"LB",9437195}, {"LF",9437193}, {"LOCK",8389408}, {"LOOP",8388610}, -{"Level",8421507}, -{"LevelTable",8683658}, -{"Loc",8487087}, -{"LocateMe",8487088}, -{"LoseLevel",8421553}, +{"Level",8421508}, +{"LevelTable",8683659}, +{"Loc",8487090}, +{"LocateMe",8487091}, +{"LoseLevel",8421556}, {"MOVED",8389127}, {"MOVING",8389130}, -{"Manhattan",8487090}, -{"MaxInventory",8421555}, +{"Manhattan",8487093}, +{"MaxInventory",8421558}, {"Misc1",9142364}, {"Misc2",9142366}, {"Misc3",9142368}, {"Misc4",9142370}, {"Misc5",9142372}, {"Misc6",9142374}, {"Misc7",9142376}, -{"Move",10584244}, -{"Move+",10584245}, -{"MoveNumber",8552578}, -{"MoveTo",10584246}, +{"Move",10584247}, +{"Move+",10584248}, +{"MoveNumber",8552579}, +{"MoveTo",10584249}, {"Moved",8618101}, {"Moving",8618102}, -{"Msg",8421501}, +{"Msg",8421502}, {"N",9437186}, {"NE",9437185}, {"NW",9437187}, -{"NewX",8421561}, -{"NewXY",8421562}, -{"NewY",8421563}, +{"NewX",8421564}, +{"NewXY",8421565}, +{"NewY",8421566}, {"OLDPHONE",8389402}, {"ONCE",8388609}, {"OSC",8388616}, {"OSCLOOP",8388618}, -{"ObjAbove",8487100}, -{"ObjBelow",8487101}, -{"ObjBottomAt",8421566}, -{"ObjClassAt",8421567}, -{"ObjDir",8487104}, -{"ObjLayerAt",8421569}, -{"ObjMovingTo",8421570}, -{"ObjTopAt",8421571}, -{"Order",8683656}, -{"Others",8683665}, -{"P",8880361}, -{"P*",8880362}, +{"ObjAbove",8487103}, +{"ObjBelow",8487104}, +{"ObjBottomAt",8421569}, +{"ObjClassAt",8421570}, +{"ObjDir",8487107}, +{"ObjLayerAt",8421572}, +{"ObjMovingTo",8421573}, +{"ObjTopAt",8421574}, +{"Order",8683657}, +{"Others",8683666}, +{"P",8880364}, +{"P*",8880365}, {"PLAYERMOVING",8389133}, {"POSTINIT",8389138}, {"POUR",8389377}, {"POWER",8389386}, -{"Player",8487033}, -{"PopUp",8421572}, -{"Queen",8683757}, -{"Quiz",8683660}, +{"Player",8487034}, +{"PopUp",8421575}, +{"Queen",8683760}, +{"Quiz",8683661}, {"R",9437198}, {"RATCHET1",8389418}, {"RATCHET2",8389412}, {"RATTLE",8389403}, {"RB",9437197}, {"RF",9437199}, -{"Rel",8487110}, -{"Rook",8683755}, +{"Rel",8487113}, +{"Rook",8683758}, {"S",9437190}, {"SE",9437191}, {"SMALL_POP",8389389}, {"SPLASH",8389376}, {"STEAM",8389424}, {"STOP",8388608}, -{"SUBS",8683666}, +{"SUBS",8683667}, {"SUNK",8389131}, {"SW",9437189}, -{"Seek",8487111}, -{"Self",8421500}, -{"Send",10584264}, -{"SendEx",10584265}, -{"SetArray",8421604}, -{"SetInventory",8421578}, +{"Seek",8487114}, +{"Self",8421501}, +{"Send",10584267}, +{"SendEx",10584268}, +{"SetArray",8421607}, +{"SetInventory",8421581}, {"Shape",8618051}, {"ShapeDir",8618074}, {"Sharp",8618073}, {"Shovable",8618075}, -{"Sound",8421579}, +{"Sound",8421582}, {"Stealthy",8618100}, {"Strength",9142358}, -{"Super",8487155}, -{"SwapWorld",8421617}, -{"Sweep",8421580}, -{"SweepEx",8421581}, -{"Synchronize",8421582}, +{"Super",8487158}, +{"SwapWorld",8421620}, +{"Sweep",8421583}, +{"SweepEx",8421584}, +{"Synchronize",8421585}, {"TAHTASHH",8389409}, {"THMP_thmp",8389405}, {"THWIT",8389384}, {"TICK",8389391}, -{"Target",8487119}, +{"Target",8487122}, {"Temperature",9142337}, -{"Trace",8421584}, -{"Trigger",8421585}, -{"TriggerAt",8421586}, +{"Trace",8421587}, +{"Trigger",8421588}, +{"TriggerAt",8421589}, {"UH_OH",8389382}, {"UNCORK",8389414}, {"UNHH",8389381}, {"UserSignal",8618097}, {"UserState",8618098}, {"VACUUM",8389411}, {"VisualOnly",8618099}, {"Volume",9142350}, -{"VolumeAt",8421587}, +{"VolumeAt",8421590}, {"W",9437188}, {"WAHOO",8389400}, {"WHACK",8389423}, {"Weight",9142352}, -{"WinLevel",8421588}, -{"XDir",8487125}, -{"XYDir",8421590}, +{"WinLevel",8421591}, +{"XDir",8487128}, +{"XYDir",8421593}, {"Xloc",8486980}, -{"YDir",8487127}, +{"YDir",8487130}, {"YEEHAW",8389401}, {"Yloc",8486981}, -{"_",8421592}, +{"_",8421595}, {"a?",8421439}, {"again",8683533}, {"and",8683544}, {"band",8421415}, {"begin",8683532}, @@ -766,27 +778,27 @@ {"bnot",8421418}, {"bor",8421416}, {"bxor",8421417}, {"c?",8421433}, {"case",8683542}, -{"chain",8421535}, -{"clear",8421599}, -{"count",8421598}, -{"cut",8683758}, +{"chain",8421536}, +{"clear",8421602}, +{"count",8421601}, +{"cut",8683761}, {"cz?",8421434}, {"dup",8421377}, {"else",8683530}, {"eq",8421424}, {"eq2",8421425}, {"exec",8486940}, -{"flip",8421597}, +{"flip",8421600}, {"for",8683537}, {"fork",8683545}, {"ge",8486965}, {"gt",8486963}, {"if",8683529}, -{"in",8421594}, +{"in",8421597}, {"is",8421431}, {"land",8421420}, {"le",8486966}, {"link",8683547}, {"lnot",8421423}, @@ -794,18 +806,18 @@ {"lsh",8421413}, {"lt",8486964}, {"lxor",8421422}, {"m?",8421435}, {"max",8486948}, -{"mbegin",8683740}, +{"mbegin",8683743}, {"min",8486947}, {"mod",8486945}, {"n?",8421432}, {"ne",8421426}, {"neg",8421410}, {"next",8683538}, -{"nin",8421595}, +{"nin",8421598}, {"nip",8421379}, {"o?",8421437}, {"or",8683543}, {"over",8421384}, {"oz?",8421438}, @@ -816,13 +828,13 @@ {"rsh",8486950}, {"rtn",8683546}, {"s?",8421436}, {"swap",8421378}, {"then",8683531}, -{"tmark",8421593}, +{"tmark",8421596}, {"tuck",8421380}, -{"uniq",8421600}, +{"uniq",8421603}, {"until",8683534}, {"while",8683535}, }; -#define N_OP_NAMES 352 +#define N_OP_NAMES 356 #endif Index: names.h ================================================================== --- names.h +++ names.h @@ -22,10 +22,11 @@ #define MSG_CONFLICT 20 #define MSG_COLLIDEBY 21 #define MSG_COLLIDE 22 #define MSG_COLLIDING 23 #define MSG_BLOCKED 24 +#define MSG_CONNECT 25 #ifdef HEROMESH_MAIN const char*const standard_message_names[]={ "INIT", "CREATE", "DESTROY", @@ -49,10 +50,11 @@ "CONFLICT", "COLLIDEBY", "COLLIDE", "COLLIDING", "BLOCKED", + "CONNECT", }; #endif #define SND_SPLASH 0 #define SND_POUR 1 #define SND_DOOR 2 Index: names.js ================================================================== --- names.js +++ names.js @@ -27,10 +27,11 @@ 20 = CONFLICT 21 = COLLIDEBY 22 = COLLIDE 23 = COLLIDING 24 = BLOCKED + 25 = CONNECT `.split("\n").map(x=>/^ *([0-9]+) = ([^ ]*) *$/.exec(x)).filter(x=>x); const standard_sound_names=[]; ` SPLASH POUR