Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -11,10 +11,11 @@ #include "sqlite3.h" #include "smallxrm.h" #include "quarks.h" #include "heromesh.h" #include "instruc.h" +#include "names.h" #ifndef VSTACKSIZE #define VSTACKSIZE 0x400 #endif @@ -176,11 +177,11 @@ if(!traceprefix) { optionquery[1]=Q_tracePrefix; traceprefix=xrm_get_resource(resourcedb,optionquery,optionquery,2); if(!traceprefix) traceprefix=""; } - printf("%sTrace : %d : %u %u",traceprefix,vstackptr,t0.t,t0.u); + printf("%s%d : Trace : %d : %u %u",traceprefix,move_number,vstackptr,t0.t,t0.u); if(t0.t>TY_MAXTYPE && t0.ugeneration==t0.t) { o=objects[t0.u]; printf(" [$%s %d %d]",classes[o->class]->name,o->x,o->y); } o=objects[obj]; @@ -229,10 +230,27 @@ case OP_TRACE: StackReq(3,0); trace_stack(obj); break; case OP_WINLEVEL: key_ignored=0; gameover=1; Throw(0); break; default: Throw("Internal error: Unrecognized opcode"); } } + +static void trace_message(Uint32 obj) { + Object*o; + const char*s; + if(!traceprefix) { + optionquery[1]=Q_tracePrefix; + traceprefix=xrm_get_resource(resourcedb,optionquery,optionquery,2); + if(!traceprefix) traceprefix=""; + } + if(msgvars.msg<256) s=standard_message_names[msgvars.msg]; else s=messages[msgvars.msg-256]; + o=msgvars.from==VOIDLINK?0:objects[msgvars.from]; + printf("%s%d : %s : %d : %u %u",traceprefix,move_number,s,vstackptr,o?o->generation:0,o?msgvars.from:0); + if(o) printf(" [$%s %d %d]",classes[o->class]->name,o->x,o->y); + o=objects[obj]; + printf(" : %u %u [$%s %d %d]",o->generation,obj,classes[o->class]->name,o->x,o->y); + printf(" : %u %u : %u %u\n",msgvars.arg1.t,msgvars.arg1.u,msgvars.arg2.t,msgvars.arg2.u,msgvars.arg3.t,msgvars.arg3.u); +} static Value send_message(Uint32 from,Uint32 to,Uint16 msg,Value arg1,Value arg2,Value arg3) { MessageVars saved=msgvars; Uint16 c=objects[to]->class; Uint16 p=get_message_ptr(c,msg); @@ -244,10 +262,15 @@ code=classes[0]->codes; } else { code=classes[c]->codes; } msgvars=(MessageVars){msg,from,arg1,arg2,arg3}; + if(main_options['t']) { + if(from==VOIDLINK || (classes[objects[from]->class]->cflags&CF_TRACEOUT)) { + if((classes[c]->cflags&CF_TRACEIN) && (message_trace[msg>>3]&(1<<(msg&7)))) trace_message(to); + } + } execute_program(code,p,to); msgvars=saved; if(vstackptrstackptr+1) Throw("Message code left too much data on stack"); if(vstackptr==stackptr) { @@ -254,10 +277,46 @@ return NVALUE(0); } else { return Pop(); } } + +static Uint32 broadcast(Uint32 from,int c,Uint16 msg,Value arg1,Value arg2,Value arg3,int s) { + Uint32 t=0; + Uint32 n,p; + Object*o; + Value v; + if(c && !classes[c]->nmsg && (!classes[0] || !classes[0]->nmsg)) { + if(s) return 0; + for(n=0;nclass==c) t++; + return t; + } + if(lastobj==VOIDLINK) return; + n=lastobj; + while(o=objects[n]) { + p=o->prev; + if(!c || o->class==c) { + v=send_message(from,n,msg,arg1,arg2,arg3); + if(s>0) { + switch(v.t) { + case TY_NUMBER: t+=v.u; break; + case TY_CLASS: t++; break; + case TY_MESSAGE: break; + default: + if(v.t<=TY_MAXTYPE) Throw("Invalid return type for BroadcastSum"); + t++; + } + } else { + if(s<0) arg2=v; + t++; + } + } + if(p==VOIDLINK) break; + o=objects[p]; + } + return t; +} void annihilate(void) { Uint32 i; for(i=0;i<64*64;i++) playfield[i]=VOIDLINK; firstobj=lastobj=VOIDLINK; @@ -268,15 +327,20 @@ objects=0; gameover=0; } const char*execute_turn(int key) { + Uint32 n; if(setjmp(my_env)) return my_error; changed=0; key_ignored=0; lastimage_processing=0; vstackptr=0; + for(n=0;ndistance=0; + objects[n]->oflags&=~(OF_KEYCLEARED|OF_DONE); + } 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"; @@ -283,15 +347,17 @@ return 0; } const char*init_level(void) { if(setjmp(my_env)) return my_error; + if(main_options['t']) printf("[Level %d restarted]",level_id); gameover=0; changed=0; key_ignored=0; lastimage_processing=0; vstackptr=0; move_number=0; - + broadcast(0,0,MSG_INIT,NVALUE(0),NVALUE(0),NVALUE(0),0); + broadcast(0,0,MSG_POSTINIT,NVALUE(0),NVALUE(0),NVALUE(0),0); if(generation_number<=TY_MAXTYPE) return "Too many generations of objects"; return 0; } Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -174,11 +174,11 @@ typedef struct { Sint32 height,weight,climb,density,volume,strength,arrivals,departures,temperature; Uint32 arrived,departed,arrived2,departed2,generation; Uint32 up,down,prev,next; // links to other objects - Uint16 class,oflags; + Uint16 class,oflags,distance; Uint16 sharp[4]; Uint16 hard[4]; Uint8 x,y,shape,shovable,image,dir; Value misc1,misc2,misc3,misc4,misc5,misc6,misc7; Value uservars[0]; Index: names.h ================================================================== --- names.h +++ names.h @@ -21,10 +21,11 @@ #define MSG_END_TURN 19 #define MSG_CLEANUP 20 #define MSG_COLLIDING 21 #define MSG_COLLIDE 22 #define MSG_BIZARRO_SWAP 23 +#ifdef HEROMESH_MAIN const char*const standard_message_names[]={ "INIT", "CREATE", "DESTROY", "BEGIN_TURN", @@ -47,10 +48,11 @@ "CLEANUP", "COLLIDING", "COLLIDE", "BIZARRO_SWAP", }; +#endif #define SND_SPLASH 0 #define SND_POUR 1 #define SND_DOOR 2 #define SND_GLASS 3 #define SND_BANG 4 @@ -97,10 +99,11 @@ #define SND_FAROUT 45 #define SND_KEWEL 46 #define SND_WHACK 47 #define SND_STEAM 48 #define SND_HAWK 49 +#ifdef HEROMESH_MAIN const char*const standard_sound_names[]={ "SPLASH", "POUR", "DOOR", "GLASS", @@ -235,5 +238,6 @@ [219]="OBRACKET", [220]="BACKSLASH", [221]="CBRACKET", [222]="QUOTE", }; +#endif Index: names.js ================================================================== --- names.js +++ names.js @@ -138,15 +138,19 @@ [..."ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"].forEach(x=>{ heromesh_key_names[x.charCodeAt()]=x; }); console.log("// Auto-generated! Do not modify directly!"); standard_message_names.forEach(([a,b,c])=>console.log("#define MSG_"+c+" "+b)); +console.log("#ifdef HEROMESH_MAIN"); console.log("const char*const standard_message_names[]={"); standard_message_names.forEach(([a,b,c])=>console.log(" \""+c+"\",")); console.log("};"); +console.log("#endif"); standard_sound_names.forEach((x,y)=>console.log("#define SND_"+x+" "+y)); +console.log("#ifdef HEROMESH_MAIN"); console.log("const char*const standard_sound_names[]={"); standard_sound_names.forEach(x=>console.log(" \""+x+"\",")); console.log("};"); console.log("const char*const heromesh_key_names[256]={"); Object.keys(heromesh_key_names).forEach(x=>console.log(" ["+x+"]=\""+heromesh_key_names[x]+"\",")); console.log("};"); +console.log("#endif");