Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -25,10 +25,11 @@ Uint32 firstobj=VOIDLINK; Uint32 lastobj=VOIDLINK; Uint32 playfield[64*64]; Uint8 pfwidth,pfheight; Sint8 gameover,key_ignored; +Uint8 generation_number_inc; typedef struct { Uint16 msg; Uint32 from; Value arg1,arg2,arg3; @@ -83,10 +84,15 @@ Object*o=0; if(!c || !cl || cl->cflags&(CF_GROUP|CF_NOCLASS2)) goto bad; o=calloc(1,sizeof(Object)+cl->uservars*sizeof(Value)); if(!o) fatal("Allocation failed\n"); o->class=c; + if(generation_number_inc) { + generation_number_inc=0; + ++generation_number; + if(generation_number<=TY_MAXTYPE) goto bad; + } o->generation=generation_number; #define C(x) o->x=cl->x; C(height) C(weight) C(climb) C(density) C(volume) C(strength) C(arrivals) C(departures) C(temperature) C(shape) C(shovable) C(oflags) C(sharp[0]) C(sharp[1]) C(sharp[2]) C(sharp[3]) @@ -118,10 +124,26 @@ return n; bad: free(o); return VOIDLINK; } + +void objtrash(Uint32 n) { + Object*o=objects[n]; + if(!o) return; + if(o->down==VOIDLINK) 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; + o->down=o->up=VOIDLINK; + if(firstobj==n) firstobj=o->next; + if(lastobj==n) lastobj=o->prev; + if(o->prev) objects[o->prev]->next=o->next; + if(o->next) objects[o->next]->prev=o->prev; + free(o); + objects[n]=0; + generation_number_inc=1; +} static inline int v_bool(Value v) { switch(v.t) { case TY_NUMBER: return v.u!=0; case TY_SOUND: case TY_USOUND: Throw("Cannot convert sound to boolean"); @@ -219,17 +241,29 @@ objects=0; gameover=0; } const char*execute_turn(int key) { - // Set key=0 for initialization if(setjmp(my_env)) return my_error; changed=0; key_ignored=0; lastimage_processing=0; vstackptr=0; if(key_ignored && changed) return "Invalid use of IgnoreKey"; if(key_ignored && changed) return "Invalid use of IgnoreKey"; + if(generation_number<=TY_MAXTYPE) return "Too many generations of objects"; + return 0; +} + +const char*init_level(void) { + if(setjmp(my_env)) return my_error; + gameover=0; + changed=0; + key_ignored=0; + lastimage_processing=0; + vstackptr=0; + + if(generation_number<=TY_MAXTYPE) return "Too many generations of objects"; return 0; } Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -191,16 +191,19 @@ extern Value globals[0x800]; extern Uint32 firstobj,lastobj; extern Uint32 playfield[64*64]; extern Uint8 pfwidth,pfheight; extern Sint8 gameover,key_ignored; +extern Uint8 generation_number_inc; void pfunlink(Uint32 n); void pflink(Uint32 n); Uint32 objalloc(Uint16 c); +void objtrash(Uint32 n); void annihilate(void); const char*execute_turn(int key); +const char*init_level(void); // == game == void run_game(void); Index: main.c ================================================================== --- main.c +++ main.c @@ -214,10 +214,11 @@ if(!buf) return "Cannot find level"; free(level_title); level_title=0; annihilate(); 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; pfwidth=(*p++&63)+1; pfheight=(*p++&63)+1;