Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -44,10 +44,11 @@ static char lastimage_processing,changed,all_flushed; static Value vstack[VSTACKSIZE]; static int vstackptr; static const char*traceprefix; static Uint8 current_key; +static Value quiz_obj; #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]) @@ -1150,20 +1151,19 @@ 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) { + if(s) { switch(v.t) { case TY_NUMBER: t+=v.u; break; case TY_CLASS: t++; 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; n=p; @@ -1185,11 +1185,13 @@ objects=0; gameover=0; } const char*execute_turn(int key) { - Uint32 n; + Uint32 m,n; + Value v; + int i; if(!key) return 0; if(setjmp(my_env)) return my_error; changed=0; key_ignored=0; all_flushed=0; @@ -1199,23 +1201,46 @@ for(n=0;ndistance=0; objects[n]->oflags&=~(OF_KEYCLEARED|OF_DONE); if(objects[n]->anim) objects[n]->anim->count=0; } - + // Input phase + m=VOIDLINK; + v=NVALUE(0); + if(!quiz_obj.t) { + n=lastobj; + while(n!=VOIDLINK) { + i=classes[objects[n]->class]->cflags; + if(i&CF_INPUT) v=send_message(VOIDLINK,n,MSG_KEY,NVALUE(key),v,NVALUE(0)); + if(i&CF_PLAYER) m=n; + n=objects[n]->prev; + } + } else { + n=quiz_obj.u; + if(objects[n]->generation!=quiz_obj.t) n=VOIDLINK; + quiz_obj=NVALUE(0); + //TODO + v=send_message(VOIDLINK,n,MSG_KEY,NVALUE(key),NVALUE(0),NVALUE(1)); + } current_key=0; - if(key_ignored) return changed?"Invalid use of IgnoreKey":0; + if(key_ignored) { + quiz_obj=NVALUE(0); + return changed?"Invalid use of IgnoreKey":0; + } move_number++; + // Beginning phase + if(!all_flushed) broadcast(m,0,MSG_BEGIN_TURN,m==VOIDLINK?NVALUE(objects[m]->x):NVALUE(0),m==VOIDLINK?NVALUE(objects[m]->y):NVALUE(0),v,0); 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; if(main_options['t']) printf("[Level %d restarted]\n",level_id); memcpy(globals,initglobals,sizeof(globals)); + quiz_obj=NVALUE(0); gameover=0; changed=0; key_ignored=0; all_flushed=0; lastimage_processing=0; Index: game.c ================================================================== --- game.c +++ game.c @@ -18,10 +18,12 @@ #include "cursorshapes.h" #include "names.h" static volatile Uint8 timerflag; static int exam_scroll; +static Uint8*inputs; +static int inputs_size,inputs_count; static void redraw_game(void) { char buf[32]; SDL_Rect r; int x,y; @@ -136,10 +138,13 @@ SDL_Flip(screen); } static void begin_level(int id) { const char*t; + free(inputs); + inputs=0; + inputs_size=inputs_count=0; t=load_level(id)?:init_level(); if(t) { gameover=-1; screen_message(t); } else { @@ -382,11 +387,16 @@ } static int game_command(int prev,int cmd,int number,int argc,sqlite3_stmt*args,void*aux) { switch(cmd) { case '\' ': // Play a move - return number; + if(inputs_count>=inputs_size) { + inputs=realloc(inputs,inputs_size+=32); + if(!inputs) fatal("Allocation failed\n"); + } + inputs[inputs_count++]=number; + return 0; case '^E': // Edit return -2; case '^Q': // Quit return -1; case '^o': // List objects @@ -425,10 +435,20 @@ SDL_PushEvent(&ev); } timerflag=1; return n; } + +static inline void input_move(Uint8 k) { + const char*t=execute_turn(k); + if(t) { + screen_message(t); + gameover=-1; + return; + } + //TODO: Record this move, if applicable +} void run_game(void) { int i; SDL_Event ev; set_caption(); @@ -466,11 +486,16 @@ if(i==-2) { main_options['e']=1; SDL_SetTimer(0,0); return; } + if(inputs_count) { + //TODO: Check for solution replay + for(i=0;i