Index: TODO ================================================================== --- TODO +++ TODO @@ -30,8 +30,10 @@ * Figure out why the $SeekerCloser class doesn't seem to work properly * Level 232 of SUPERHRO puzzle set (the Lava shouldn't expand? why?) * Display solution comments/timestamp * VCR mode * Portable mode, not needing installing files in home directory + * Maybe not needed? You can override the HOME environment variable + * An alternative is to check argv[0]; if it contains / then don't use HOME * Command-line switch for batch import/export levels * SQL * Implement the GROUP column in the CLASSES table Index: bindings.doc ================================================================== --- bindings.doc +++ bindings.doc @@ -82,10 +82,13 @@ Display values of global variables. '^o' List objects at the specified coordinates, to examine their values. +'^p' + Start or stop slow replay. Any move input also interrupts slow replay. + '^s' Toggle solution replay. 'mi' Import a move list. The argument is a operating system command, that Index: config.doc ================================================================== --- config.doc +++ config.doc @@ -79,10 +79,14 @@ .progress If positive, how many steps between dots in the progress report for the auto testing most. If negative, number of milliseconds to sleep before each level is executed. +.replaySpeed + When the slow replay is used, sets the playback speed; this is a number + of centiseconds between turns from 0 to 255. + .saveSolutions If true, then solutions are saved if you solve a level in less moves than the currently recorded solution (or if no solution is already recorded). This has no effect in read-only mode. Index: default.heromeshrc ================================================================== --- default.heromeshrc +++ default.heromeshrc @@ -127,10 +127,11 @@ ?.gameKey.f7: ^> ?.gameKey.f8: ^s ?.gameKey.tab: ^I ?.gameKey.alt.D: select '^d',$key_xy; ?.gameKey.alt.G: ^g +?.gameKey.alt.P: ^p ! Editor key bindings ?.editKey.1: select 'mr',0; ?.editKey.2: select 'mr',1; ?.editKey.3: select 'mr',2; Index: game.c ================================================================== --- game.c +++ game.c @@ -27,16 +27,21 @@ static int exam_scroll; static Uint8*inputs; static int inputs_size,inputs_count; static Uint8 side_mode=255; static Uint8 should_record_solution; +static Uint8 replay_speed; +static Uint8 replay_time; 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); + optionquery[1]=Q_replaySpeed; + v=xrm_get_resource(resourcedb,optionquery,optionquery,2)?:""; + replay_speed=strtol(v,0,10)?:16; if(main_options['r']) { should_record_solution=0; } else { optionquery[1]=Q_saveSolutions; v=xrm_get_resource(resourcedb,optionquery,optionquery,2)?:""; @@ -287,10 +292,11 @@ } } static void begin_level(int id) { const char*t; + replay_time=0; if(replay_count) save_replay(); inputs_count=0; replay_pos=0; t=load_level(id)?:init_level(); load_replay(); @@ -663,10 +669,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(replay_time) { + replay_time=0; + return -3; + } if(solution_replay) { screen_message("You cannot play your own moves during the solution replay"); return -3; } if(inputs_count>=inputs_size) { @@ -674,10 +684,11 @@ if(!inputs) fatal("Allocation failed\n"); } inputs[inputs_count++]=number; return 0; case '+ ': replay: // Replay + replay_time=0; if(number>replay_count-replay_pos) number=replay_count-replay_pos; if(number<=0) return prev; if(inputs_count+number>=inputs_size) { inputs=realloc(inputs,inputs_size+=number+1); if(!inputs) fatal("Allocation failed\n"); @@ -727,10 +738,13 @@ global_examine(); return prev; case '^o': // List objects list_objects_at(number-65); return prev; + case '^p': // Slow replay + replay_time=replay_time?0:1; + return 0; case '^s': // Toggle solution replay if(replay_count) save_replay(); solution_replay^=1; if(replay_count) replay_count=0,begin_level(level_id); else load_replay(); return 1; @@ -851,10 +865,11 @@ void run_game(void) { int i; SDL_Event ev; set_caption(); replay_count=0; + replay_time=0; if(side_mode==255) setup_game(); begin_level(level_id); redraw_game(); timerflag=0; SDL_SetTimer(10,timer_callback); @@ -870,10 +885,14 @@ show_mouse_xy(&ev); break; case SDL_USEREVENT: if(!gameover && !quiz_text) continue_animation(); timerflag=0; + if(replay_time && !--replay_time && !game_command(1,'+ ',1,0,0,0)) { + replay_time=replay_speed; + goto replay; + } break; case SDL_MOUSEBUTTONDOWN: if(ev.button.x