Index: game.c ================================================================== --- game.c +++ game.c @@ -18,10 +18,11 @@ #include "cursorshapes.h" #include "names.h" Uint8*replay_list; Uint16 replay_size,replay_count,replay_pos,replay_mark; +Uint8 solution_replay=255; static volatile Uint8 timerflag; static int exam_scroll; static Uint8*inputs; static int inputs_size,inputs_count; @@ -30,10 +31,11 @@ static void setup_game(void) { const char*v; optionquery[1]=Q_showInventory; v=xrm_get_resource(resourcedb,optionquery,optionquery,2)?:""; side_mode=boolxrm(v,1); + solution_replay=0; } static void redraw_game(void) { char buf[32]; SDL_Rect r; @@ -106,11 +108,11 @@ } else { // Move list snprintf(buf,8,"%5d",replay_pos); draw_text(8,52,buf,0xF0,0xF9); snprintf(buf,8,"%5d",replay_count); - draw_text(8,screen->h-8,buf,0xF0,0xFC); + draw_text(8,screen->h-8,buf,0xF0,solution_replay?0xFA:0xFC); for(y=44,x=replay_pos-(screen->h-68)/32;;x++) { y+=16; if(y+24>screen->h) break; if(x>=0 && x0xFFFF?0xFFFF:sz); } @@ -209,29 +211,56 @@ replay_list[sz-3]=replay_mark; replay_list[sz-2]=replay_count>>8; replay_list[sz-1]=replay_count; write_userstate(FIL_LEVEL,level_id,sz,replay_list); } + +static void load_replay(void) { + long sz; + int i; + free(replay_list); + if(solution_replay) { + replay_list=read_lump(FIL_SOLUTION,level_id,&sz); + // Solution format: version (16-bits), flag (8-bits), user name (null-terminated), timestamp (64-bits), move list + if(sz>3) { + i=replay_list[0]|(replay_list[1]<<8); + if(i!=level_version) goto notfound; + i=3; + if(replay_list[2]&1) { + while(i=sz || sz-i>0xFFFF) goto notfound; + replay_size=(sz>0xFFFF?0xFFFF:sz); + memmove(replay_list,replay_list+i,replay_count=sz-i); + replay_mark=0; + } else { + goto notfound; + } + } else { + replay_list=read_userstate(FIL_LEVEL,level_id,&sz); + if(sz>=2) { + replay_size=(sz>0xFFFF?0xFFFF:sz); + replay_count=(replay_list[sz-2]<<8)|replay_list[sz-1]; + if(sz-replay_count>=4) replay_mark=(replay_list[replay_count]<<8)|replay_list[replay_count+1]; else replay_mark=0; + } else { + notfound: + replay_count=replay_mark=replay_size=0; + free(replay_list); + replay_list=0; + } + } +} static void begin_level(int id) { const char*t; - long sz; - if(replay_count) end_level(); + if(replay_count) save_replay(); inputs_count=0; replay_pos=0; t=load_level(id)?:init_level(); - free(replay_list); - replay_list=read_userstate(FIL_LEVEL,level_id,&sz); - if(sz>=2) { - replay_size=(sz>0xFFFF?0xFFFF:sz); - replay_count=(replay_list[sz-2]<<8)|replay_list[sz-1]; - if(sz-replay_count>=4) replay_mark=(replay_list[replay_count]<<8)|replay_list[replay_count+1]; else replay_mark=0; - } else { - replay_count=replay_mark=replay_size=0; - free(replay_list); - replay_list=0; - } + load_replay(); if(t) { gameover=-1; screen_message(t); } else { gameover=0; @@ -486,10 +515,14 @@ } static int game_command(int prev,int cmd,int number,int argc,sqlite3_stmt*args,void*aux) { switch(cmd) { case '\' ': // Play a move + if(solution_replay) { + screen_message("You cannot play your own moves during the solution replay"); + return -3; + } if(inputs_count>=inputs_size) { inputs=realloc(inputs,inputs_size+=32); if(!inputs) fatal("Allocation failed\n"); } inputs[inputs_count++]=number; @@ -542,10 +575,15 @@ describe_at(number-65); return prev; case '^o': // List objects list_objects_at(number-65); return prev; + case '^s': // Toggle solution replay + solution_replay^=1; + replay_count=0; + if(replay_count) begin_level(level_id); else load_replay(); + return 1; case 'go': // Select level begin_level(number); return 1; default: return prev; @@ -660,11 +698,11 @@ timerflag=0; // ensure we have not missed a timer event break; } } quit: - end_level(); + save_replay(); exit(0); } void locate_me(int x,int y) { Uint8 c=7; Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -256,10 +256,11 @@ // == game == extern Uint8*replay_list; extern Uint16 replay_size,replay_count,replay_pos,replay_mark; +extern Uint8 solution_replay; void run_game(void); void locate_me(int x,int y); // == edit ==