Index: class.c ================================================================== --- class.c +++ class.c @@ -2033,10 +2033,11 @@ case OP_QUIZ: cl->cflags|=CF_QUIZ; break; case OP_INVISIBLE: cl->oflags|=OF_INVISIBLE; break; case OP_VISUALONLY: cl->oflags|=OF_VISUALONLY; break; case OP_STEALTHY: cl->oflags|=OF_STEALTHY; break; 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 0x4000 ... 0x7FFF: set_super_class(cl,ptr); ptr=2; break; default: ParseError("Invalid directly inside of a class definition\n"); Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -357,10 +357,15 @@ Define the Arrivals variable for this class. This is twenty-five numbers each of which is either zero or one. They are meant to be on five lines of five numbers each, making a 5x5 matrix, where the centre means this object's location. +Bizarro + Means that objects of this class created using the Create instruction + will be created in the bizarro world by default. (This has no effect on + objects placed in the level editor.) + (Climb ) Define the Climb variable for this class. (CollisionLayers ) Define the CollisionLayers variable for this class. The format is the @@ -834,10 +839,21 @@ also send a ARRIVED message during the trigger phase. You can write all bits of this variable, but only the low 25-bits can be read back; if you write a nonzero number with only the high bits set, then it will still be triggered but will be read back as zero. +Bizarro : bool [c] + Set if this object is in the bizarro world. Objects in the bizarro world + are invisible and intangible, and mostly do not interact with other + objects. However, they can still be accessed/affected by anything that + references it directly, it is still possible to broadcast messages to + them, and they are still affected by most turn-based actions (although + not the compatible part of the trigger phase). Objects in the bizarro + world are effectively stealthy as well, so do not cause messages due to + being moved, created, or destroyed. In some circumstances, attempting + to change this flag will have no effect. + Busy : bool If any object has either the Busy or UserSignal variable set, then the player input is blocked, and the turn may continue. Use this to control the timing of effects in LASTIMAGE blocks. @@ -849,11 +865,11 @@ exceed the Height of all objects at the target location, otherwise it is prevented from moving. CollisionLayers : int8 [c] [ro] Any set bit means no other object with that same bit set in this field - may exist at the same location. + may exist at the same location. (There is no effect in bizarro world.) 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. @@ -1172,10 +1188,18 @@ band ( in1 in2 -- out ) Bitwise AND. (bit ) ( -- number ) Make a number with only the specified bits set, given numbers 0 to 31. + +BizarroSwap ( x y | obj1 obj2 -- number ) ** + Attempt to exchange either two objects (one in the bizarro world, one + not) at the same location or all objects at the specified location into + or out of the bizarro world. If it is successful, then the result is 0. + If unsuccessful due to CollisionLayers, then the result is the bits in + the CollisionLayers which are conflicting; if unsuccessful due to any + other reason then the result will be 256. bnot ( in -- out ) Bitwise NOT. bor ( in1 in2 -- out ) @@ -1739,10 +1763,14 @@ ,Super ( ? -- ? ) Same as Super but return to this code after it is finished. swap ( x y -- y x ) +SwapWorld ( -- ) ** + Exchange the entire game with the bizarro world. Sometimes, this might + fail due to CollisionLayers bits; in this case, it is an error. + Synchronize ( slot startimage -- ) ** Start a synchronized animation. Give the slot number of the animation, and the starting image number. The length and speed are defined in a global definition, and the animation is always a non-oscillating loop. Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -84,30 +84,32 @@ } } void pfunlink(Uint32 n) { Object*o=objects[n]; - if(o->down==VOIDLINK) playfield[o->x+o->y*64-65]=o->up; + Uint32*pf=(o->oflags&OF_BIZARRO?bizplayfield:playfield); + if(o->down==VOIDLINK) pf[o->x+o->y*64-65]=o->up; else objects[o->down]->up=o->up; if(o->up!=VOIDLINK) objects[o->up]->down=o->down; o->down=o->up=VOIDLINK; } void pflink(Uint32 n) { Object*o=objects[n]; + Uint32*pf=(o->oflags&OF_BIZARRO?bizplayfield:playfield); int p=o->x+o->y*64-65; if(p<0) return; - if(playfield[p]==VOIDLINK) { - playfield[p]=n; + if(pf[p]==VOIDLINK) { + pf[p]=n; } else { Sint32 d=o->density; - Uint32 m=playfield[p]; + Uint32 m=pf[p]; Uint32 t=VOIDLINK; while(m!=VOIDLINK && objects[m]->density>=d) t=m,m=objects[m]->up; o->down=t; o->up=m; - if(t!=VOIDLINK) objects[t]->up=n; else playfield[p]=n; + if(t!=VOIDLINK) objects[t]->up=n; else pf[p]=n; if(m!=VOIDLINK) objects[m]->down=n; } } #define OBJECT_ARRAY_BLOCK 256 @@ -210,11 +212,11 @@ } else if(ndeadanim<0x1000 && o->anim && o->anim->status==ANISTAT_VISUAL && !(o->oflags&OF_INVISIBLE)) { if(o->up==VOIDLINK || (objects[o->up]->oflags&OF_DESTROYED)) set_dead_animation(o); } } animfree(o->anim); - if(o->down==VOIDLINK) playfield[o->x+o->y*64-65]=o->up; + if(o->down==VOIDLINK) (o->oflags&OF_BIZARRO?bizplayfield:playfield)[o->x+o->y*64-65]=o->up; else objects[o->down]->up=o->up; if(o->up!=VOIDLINK) objects[o->up]->down=o->down; if(!(o->oflags&OF_DESTROYED)) { if(firstobj==n) firstobj=o->next; if(lastobj==n) lastobj=o->prev; @@ -506,10 +508,11 @@ } static void change_density(Uint32 n,Sint32 v) { Object*o=objects[n]; Uint32 i; + if(o->oflags&OF_BIZARRO) return; if(vdensity) { o->density=v; for(;;) { i=o->up; if(i==VOIDLINK || objects[i]->density<=v) return; @@ -684,10 +687,11 @@ o->image=im; o->dir=d; pflink(n); v=send_message(from,n,MSG_CREATE,NVALUE(0),NVALUE(0),NVALUE(0)); if(o->oflags&OF_DESTROYED) return VOIDLINK; + if(o->oflags&OF_BIZARRO) return n; for(y=0;y<5;y++) for(x=0;x<5;x++) { xx=o->x+x-2; yy=o->y+y-2; if(xx<1 || xx>pfwidth || yy<1 || yy>pfheight) continue; i=x+5*(4-y); m=playfield[xx+yy*64-65]; @@ -726,11 +730,11 @@ if(o->prev!=VOIDLINK) objects[o->prev]->next=o->next; if(o->next!=VOIDLINK) objects[o->next]->prev=o->prev; // This object is not itself removed from the linked list, since it may be destroyed while enumerating all objects } o->oflags|=OF_DESTROYED; - if(why!=8 && !(o->oflags&OF_VISUALONLY)) { + if(why!=8 && !(o->oflags&(OF_VISUALONLY|OF_BIZARRO))) { // Not checking for stealth; stealth only applies to movement, not destruction for(yy=0;yy<5;yy++) for(xx=0;xx<5;xx++) { x=objects[to]->x+xx-2; y=objects[to]->y+yy-2; if(x<1 || x>pfwidth || y<1 || y>pfheight) continue; i=xx+5*(4-yy); @@ -763,14 +767,14 @@ if(v_bool(send_message(n,m,MSG_PLAYERMOVING,NVALUE(x),NVALUE(y),OVALUE(from)))) return 0; m=objects[m]->prev; } } if(!(o->oflags&OF_BIZARRO) && (i=classes[o->class]->collisionLayers) && (xx=collisions_at(x,y)&i)) { - if((i=collide_with(xx,VOIDLINK,x,y,o->class))&0x01) return i&0x04?1:0; + if((i=collide_with(xx,n,x,y,o->class))&0x01) return i&0x04?1:0; } pfunlink(n); - if(!(o->oflags&((classes[o->class]->cflags&CF_COMPATIBLE?OF_VISUALONLY:0)|OF_STEALTHY))) { + if(!(o->oflags&((classes[o->class]->cflags&CF_COMPATIBLE?OF_VISUALONLY:0)|OF_STEALTHY|OF_BIZARRO))) { for(i=25;i>=0;i--) { xx=o->x+Xbit(i); yy=o->y+Ybit(i); if(xx<1 || xx>pfwidth || yy<1 || yy>pfheight) continue; m=playfield[xx+yy*64-65]; while(m!=VOIDLINK) { @@ -781,11 +785,11 @@ } } o->distance+=abs(x-o->x)+abs(y-o->y); o->x=x; o->y=y; - if(!(o->oflags&((classes[o->class]->cflags&CF_COMPATIBLE?OF_VISUALONLY:0)|OF_STEALTHY))) { + if(!(o->oflags&((classes[o->class]->cflags&CF_COMPATIBLE?OF_VISUALONLY:0)|OF_STEALTHY|OF_BIZARRO))) { for(i=25;i>=0;i--) { xx=x+Xbit(i); yy=y+Ybit(i); if(xx<1 || xx>pfwidth || yy<1 || yy>pfheight) continue; m=playfield[xx+yy*64-65]; while(m!=VOIDLINK) { @@ -794,11 +798,11 @@ m=p->up; } } } pflink(n); - if(!(o->oflags&OF_VISUALONLY)) { + if(!(o->oflags&(OF_VISUALONLY|OF_BIZARRO))) { m=objects[n]->up; if(m!=VOIDLINK) { v=send_message(VOIDLINK,n,MSG_SUNK,NVALUE(0),NVALUE(0),NVALUE(0)); while(m!=VOIDLINK) { send_message(n,m,MSG_FLOATED,NVALUE(0),NVALUE(0),v); @@ -1151,10 +1155,97 @@ static inline void flush_all(void) { if(current_key) all_flushed=255; flush_class(0); } + +static void set_bizarro(Uint32 n,Uint32 v) { + Object*o; + Uint8 b; + if(n==VOIDLINK) return; + o=objects[n]; + if(o->oflags&OF_DESTROYED) return; + if(v) { + if(o->oflags&OF_BIZARRO) return; + pfunlink(n); + o->oflags|=OF_BIZARRO; + pflink(n); + } else { + if(!(o->oflags&OF_BIZARRO)) return; + if(b=classes[o->class]->collisionLayers) { + Uint32 m=obj_layer_at(b,o->x,o->y); + if(m!=VOIDLINK && (collide_with(b,n,o->x,o->y,o->class)&0x01)) return; + } + pfunlink(n); + o->oflags&=~OF_BIZARRO; + pflink(n); + } +} + +void swap_world(void) { + Uint32 n; + int i,j,b; + if(!main_options['e']) for(i=0;i<64*pfheight;i++) { + n=playfield[i]; + for(b=0;n!=VOIDLINK;) { + j=classes[objects[n]->class]->collisionLayers; + if(b&j) Throw("SwapWorld attempted while collisions are present"); + b|=j; + n=objects[n]->up; + } + } + for(i=0;i<64*pfheight;i++) { + n=playfield[i]; + playfield[i]=bizplayfield[i]; + bizplayfield[i]=n; + } + for(n=0;noflags^=OF_BIZARRO; +} + +static Uint32 v_bizarro_swap(Value x,Value y) { + Uint32 k,m,n; + Uint8 b,c; + if(x.t==TY_NUMBER && y.t==TY_NUMBER) { + if(x.u<1 || x.u>pfwidth || y.u<1 || y.u>pfheight) return 0x100; + b=c=0; + n=bizplayfield[x.u+y.u*64-65]; + while(n!=VOIDLINK) { + c|=b&classes[objects[n]->class]->collisionLayers; + b|=classes[objects[n]->class]->collisionLayers; + n=objects[n]->up; + } + if(c) return c; + n=playfield[x.u+y.u*64-65]; + while(n!=VOIDLINK) objects[n]->oflags|=OF_BIZARRO,n=objects[n]->up; + m=playfield[x.u+y.u*64-65]=bizplayfield[x.u+y.u*64-65]; + bizplayfield[x.u+y.u*64-65]=n; + while(m!=VOIDLINK) objects[n]->oflags&=~OF_BIZARRO,m=objects[m]->up; + return 0; + } else { + m=v_object(x); + n=v_object(y); + if(m==VOIDLINK || n==VOIDLINK || m==n) return 0x100; + if(objects[m]->x!=objects[n]->x || objects[m]->y!=objects[n]->y) return 0x100; + if((objects[m]->oflags|objects[n]->oflags)&OF_DESTROYED) return 0x100; + if(!((objects[m]->oflags^objects[n]->oflags)&OF_BIZARRO)) return 0x100; + if(objects[n]->oflags&OF_BIZARRO) k=m,m=n,n=k; + if(b=classes[objects[m]->class]->collisionLayers) { + k=obj_layer_at(b,objects[m]->x,objects[m]->y); + if(k!=VOIDLINK && k!=n) { + c=collisions_at(objects[m]->x,objects[m]->y)&b; + if(collide_with(c,m,objects[m]->x,objects[m]->y,objects[m]->class)&0x01) return c; + } + } + pfunlink(m); + pfunlink(n); + objects[m]->oflags^=OF_BIZARRO; + objects[n]->oflags^=OF_BIZARRO; + pflink(m); + pflink(n); + return 0; + } +} static inline Value v_broadcast(Uint32 from,Value c,Value msg,Value arg1,Value arg2,Value arg3,int s) { if(msg.t!=TY_MESSAGE) Throw("Type mismatch"); if(c.t!=TY_CLASS && (c.t!=TY_NUMBER || c.u)) Throw("Type mismatch"); return NVALUE(broadcast(from,c.u,msg.u,arg1,arg2,arg3,s)); @@ -2130,10 +2221,16 @@ case OP_ARRIVED_E: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->arrived=t1.u; break; case OP_ARRIVED_EC: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->arrived=t1.u; break; case OP_ASSASSINATE: NoIgnore(); destroy(obj,obj,8); break; case OP_ASSASSINATE_C: NoIgnore(); StackReq(1,0); i=v_object(Pop()); destroy(obj,i,8); break; case OP_BAND: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u&t2.u)); break; + case OP_BIZARRO: StackReq(0,1); if(o->oflags&OF_BIZARRO) Push(NVALUE(1)); else Push(NVALUE(0)); break; + case OP_BIZARRO_C: StackReq(1,1); GetFlagOf(OF_BIZARRO); break; + case OP_BIZARRO_E: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); set_bizarro(obj,t1.u); break; + case OP_BIZARRO_EC: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); set_bizarro(v_object(Pop()),t1.u); break; + case OP_BIZARROSWAP: NoIgnore(); StackReq(2,1); t2=Pop(); t1=Pop(); i=v_bizarro_swap(t1,t2); Push(NVALUE(i)); break; + case OP_BIZARROSWAP_D: NoIgnore(); StackReq(2,0); t2=Pop(); t1=Pop(); v_bizarro_swap(t1,t2); break; case OP_BNOT: StackReq(1,1); t1=Pop(); Numeric(t1); Push(NVALUE(~t1.u)); break; case OP_BOR: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u|t2.u)); break; case OP_BROADCAST: StackReq(4,1); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_broadcast(obj,t1,t2,t3,t4,NVALUE(0),0)); break; case OP_BROADCAST_D: StackReq(4,0); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_broadcast(obj,t1,t2,t3,t4,NVALUE(0),0); break; case OP_BROADCASTAND: StackReq(4,1); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_broadcast(obj,t1,t2,t3,t4,NVALUE(0),2)); break; @@ -2425,10 +2522,11 @@ case OP_SOUND: StackReq(2,0); t2=Pop(); t1=Pop(); break; // Sound not implemented at this time case OP_SUB: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u-t2.u)); break; case OP_SUPER: i=code[1]; code=classes[i]->codes; ptr=get_message_ptr(i,msgvars.msg); if(ptr==0xFFFF) break; break; case OP_SUPER_C: i=code[1]; j=get_message_ptr(i,msgvars.msg); if(j!=0xFFFF) execute_program(classes[i]->codes,j,obj); break; case OP_SWAP: StackReq(2,2); t1=Pop(); t2=Pop(); Push(t1); Push(t2); break; + case OP_SWAPWORLD: NoIgnore(); swap_world(); break; case OP_SYNCHRONIZE: StackReq(2,0); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); animate_sync(obj,t1.u,t2.u); break; case OP_TARGET: StackReq(0,1); Push(NVALUE(v_target(obj)?1:0)); break; case OP_TARGET_C: StackReq(1,1); i=v_object(Pop()); Push(NVALUE(v_target(i)?1:0)); break; case OP_TEMPERATURE: StackReq(0,1); Push(NVALUE(o->temperature)); break; case OP_TEMPERATURE_C: StackReq(1,1); Push(GetVariableOrAttributeOf(temperature,NVALUE)); break; @@ -2931,15 +3029,20 @@ } // Clock phase n=lastobj; while(n!=VOIDLINK) { o=objects[n]; - if(o->arrived || o->departed) goto trig; - if(o->oflags&OF_MOVED) goto trig; - if(o->anim && (o->anim->status&ANISTAT_LOGICAL) && (o->anim->step[o->anim->lstep].flag&ANI_ONCE)) { - if(o->anim->ltime>=o->anim->step[o->anim->lstep].speed) goto trig; - if(clock>o->anim->step[o->anim->lstep].speed-o->anim->ltime) clock=o->anim->step[o->anim->lstep].speed-o->anim->ltime; + if(o->oflags&OF_BIZARRO) { + o->arrived=o->departed=0; + o->oflags&=~(OF_MOVING|OF_MOVED); + } else { + if(o->arrived || o->departed) goto trig; + if(o->oflags&OF_MOVED) goto trig; + if(o->anim && (o->anim->status&ANISTAT_LOGICAL) && (o->anim->step[o->anim->lstep].flag&ANI_ONCE)) { + if(o->anim->ltime>=o->anim->step[o->anim->lstep].speed) goto trig; + if(clock>o->anim->step[o->anim->lstep].speed-o->anim->ltime) clock=o->anim->step[o->anim->lstep].speed-o->anim->ltime; + } } n=o->prev; } n=lastobj; while(n!=VOIDLINK) { Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -276,10 +276,11 @@ Uint32 objalloc(Uint16 c); void objtrash(Uint32 n); void annihilate(void); const char*execute_turn(int key); const char*init_level(void); +void swap_world(void); // == game == extern Uint8*replay_list; extern Uint16 replay_size,replay_count,replay_pos,replay_mark; Index: instruc ================================================================== --- instruc +++ instruc @@ -305,14 +305,12 @@ -Queen -cut ; Bizarro world ,=Bizarro -.,BizarroSwap +.BizarroSwap SwapWorld -BizarroTopAt -BizarroBottomAt ; Inheritance -Abstract ,Super Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -439,27 +439,23 @@ #define OP_BIZARRO 32997 #define OP_BIZARRO_C 35045 #define OP_BIZARRO_E 37093 #define OP_BIZARRO_EC 39141 #define OP_BIZARROSWAP 32998 -#define OP_BIZARROSWAP_C 35046 #define OP_BIZARROSWAP_D 41190 -#define OP_BIZARROSWAP_CD 43238 #define OP_SWAPWORLD 32999 -#define OP_BIZARROTOPAT 33000 -#define OP_BIZARROBOTTOMAT 33001 -#define OP_ABSTRACT 33002 -#define OP_SUPER 33003 -#define OP_SUPER_C 35051 -#define OP_FUNCTION 33004 -#define OP_LOCAL 33005 -#define OP_LABEL 33006 -#define OP_STRING 33007 -#define OP_INT16 33008 -#define OP_INT32 33009 -#define OP_DISPATCH 33010 -#define OP_USERFLAG 33011 +#define OP_ABSTRACT 33000 +#define OP_SUPER 33001 +#define OP_SUPER_C 35049 +#define OP_FUNCTION 33002 +#define OP_LOCAL 33003 +#define OP_LABEL 33004 +#define OP_STRING 33005 +#define OP_INT16 33006 +#define OP_INT32 33007 +#define OP_DISPATCH 33008 +#define OP_USERFLAG 33009 #ifdef HEROMESH_CLASS static const Op_Names op_names[]={ {"*",8486939}, {"+",8421401}, {"+Move",10584239}, @@ -468,11 +464,11 @@ {"-rot",8421382}, {".",10518528}, {"/",8486940}, {"ANHH",8389394}, {"ARRIVED",8389124}, -{"Abstract",8683754}, +{"Abstract",8683752}, {"Animate",8421516}, {"AnimateDead",8421517}, {"Arg1",8552571}, {"Arg2",8552572}, {"Arg3",8552573}, @@ -495,13 +491,11 @@ {"BUZZER",8389420}, {"BWEEP",8389397}, {"Background",8683650}, {"Bishop",8683746}, {"Bizarro",8618213}, -{"BizarroBottomAt",8421609}, -{"BizarroSwap",10584294}, -{"BizarroTopAt",8421608}, +{"BizarroSwap",10518758}, {"Broadcast",10518671}, {"BroadcastAnd",8421520}, {"BroadcastAndEx",8421521}, {"BroadcastEx",10518675}, {"BroadcastList",8421524}, @@ -675,11 +669,11 @@ {"Sharp",8618069}, {"Shovable",8618071}, {"Sound",8421571}, {"Stealthy",8618096}, {"Strength",9142354}, -{"Super",8487147}, +{"Super",8487145}, {"SwapWorld",8421607}, {"Synchronize",8421572}, {"TAHTASHH",8389409}, {"THMP_thmp",8389405}, {"THWIT",8389384}, @@ -803,7 +797,7 @@ {"tuck",8421380}, {"uniq",8421590}, {"until",8683534}, {"while",8683535}, }; -#define N_OP_NAMES 344 +#define N_OP_NAMES 342 #endif Index: main.c ================================================================== --- main.c +++ main.c @@ -210,10 +210,11 @@ } const char*load_level(int lvl) { // Load level by ID. Returns null pointer if successful, or an error message if it failed. long sz=0; + Uint16 of=0; unsigned char*buf=lvl>=0?read_lump(FIL_LEVEL,lvl,&sz):0; unsigned char*p=buf; unsigned char*end=buf+sz; unsigned char*q; int i,n,x,y,z; @@ -235,25 +236,28 @@ generation_number=TY_MAXTYPE+1; generation_number_inc=0; level_version=p[0]|(p[1]<<8); level_code=p[2]|(p[3]<<8); p+=4; + if(*p&0x80) of=OF_BIZARRO; pfwidth=(*p++&63)+1; pfheight=(*p++&63)+1; while(*p && p=end) goto bad1; level_title=strdup(buf+6); if(!level_title) fatal("Allocation failed\n"); + mru[0]=mru[1]=VOIDLINK; + restart: x=0; y=1; n=0; - mru[0]=mru[1]=VOIDLINK; for(;;) { if(n) { o=objalloc(objects[*mru]->class); if(o==VOIDLINK) goto bad3; + objects[o]->oflags=(objects[o]->oflags&~OF_BIZARRO)|of; objects[o]->image=objects[*mru]->image; objects[o]->misc1=objects[*mru]->misc1; objects[o]->misc2=objects[*mru]->misc2; objects[o]->misc3=objects[*mru]->misc3; objects[o]->dir=objects[*mru]->dir; @@ -263,11 +267,15 @@ pflink(o); --n; } else { if(p>=end) goto bad1; z=*p++; - if(z==0xFF) break; + if(z==0xFF) { + if(!of) break; + of=0; + goto restart; + } if(z&0x20) x=*p++; if(z&0x10) y=*p++; if(z&0x40) x++; if(!x || !y || x>pfwidth || y>pfheight) goto bad2; n=z&0x70?0:1; @@ -274,10 +282,11 @@ if(z&0x80) { // MRU if(mru[n]==VOIDLINK) goto bad1; o=objalloc(objects[mru[n]]->class); if(o==VOIDLINK) goto bad3; + objects[o]->oflags=(objects[o]->oflags&~OF_BIZARRO)|of; objects[o]->image=objects[mru[n]]->image; objects[o]->misc1=objects[mru[n]]->misc1; objects[o]->misc2=objects[mru[n]]->misc2; objects[o]->misc3=objects[mru[n]]->misc3; objects[o]->dir=objects[mru[n]]->dir; @@ -289,10 +298,11 @@ // Not MRU i=*p++; i|=*p++<<8; o=objalloc(i&0x3FFF); if(o==VOIDLINK) goto bad3; + objects[o]->oflags=(objects[o]->oflags&~OF_BIZARRO)|of; if(n!=2) mru[n]=o; if(i&0x8000) { n=objects[o]->class; for(i=0;inimages;i++) { if(classes[n]->images[i]&0x8000) { Index: picedit.c ================================================================== --- picedit.c +++ picedit.c @@ -1,7 +1,7 @@ #if 0 -gcc ${CFLAGS:--s -O2} -c -Wno-multichar picedit.c `sdl-config --cflags` +gcc ${CFLAGS:--s -O2} -c -Wno-multichar -Wno-unused-result picedit.c `sdl-config --cflags` exit #endif /* This program is part of Free Hero Mesh and is public domain. DELETED sounds.js Index: sounds.js ================================================================== --- sounds.js +++ sounds.js @@ -1,72 +0,0 @@ -// This program will read the sounds from HEROFALL.EXE -// The output is written to a Hamster archive to stdout -"use strict"; -const hamarc=require("hamarc"); -const fs=require("fs"); -const out=new hamarc.File(1); -const hdr=Buffer.allocUnsafe(12); -const fil=fs.openSync(process.argv[2],"r"); -const names=` - SPLASH - POUR - DOOR - GLASS - BANG - UNHH - UH_OH - FROG - THWIT - KLINKK - POWER - KLECK - CLICK - SMALL_POP - DINK - TICK - CHYEW - CHEEP - ANHH - BRRRT - BRRREEET - BWEEP - DRLRLRINK - FFFFTT - WAHOO - YEEHAW - OLDPHONE - RATTLE - BEEDEEP - THMP_thmp - BEDOINGNG - HEARTBEAT - LOCK - TAHTASHH - BOOOM - VACUUM - RATCHET2 - DYUPE - UNCORK - BOUNCE - JAYAYAYNG - DEEP_POP - RATCHET1 - GLISSANT - BUZZER - FAROUT - KEWEL - WHACK - STEAM - HAWK -`.split("\n").map(x=>x.trim()).filter(x=>x); -let n=0; -let o=process.argv[3]?parseInt(process.argv[3],16):0x5CD92; -for(;;) { - if(fs.readSync(fil,hdr,0,12,o)<12) break; - if(hdr.toString("ascii",0,4)!="RIFF" || hdr.toString("ascii",8,12)!="WAVE") break; - let len=hdr.readUInt32LE(4); - let buf=Buffer.allocUnsafeSlow(len+8); - fs.readSync(fil,buf,0,len,o); - out.put(names[n]+".WAV",buf); - o+=len+8; - n++; -}