Index: bindings.doc ================================================================== --- bindings.doc +++ bindings.doc @@ -64,10 +64,17 @@ Rewind to mark. '^>' Replay to mark. +'^-' + Delete one move. + +'^+' + Toggle insertion mode. Insertion mode is automatically reset when + restarting a level or when accessing a different level. + '^I' Toggle the inventory/move-list display. '^M' Set the replay mark position. Index: default.heromeshrc ================================================================== --- default.heromeshrc +++ default.heromeshrc @@ -131,10 +131,12 @@ ?.gameKey.tab: ^I ?.gameKey.alt.G: ^g ?.gameKey.alt.P: ^p ?.gameKey.alt.leftbracket: select 'rs',-5; ?.gameKey.alt.rightbracket: select 'rs',+5; +?.gameKey.delete: ^- +?.gameKey.insert: ^+ ! 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 @@ -30,10 +30,11 @@ static Uint8 side_mode=255; static Uint8 should_record_solution; static Uint8 replay_speed; static Uint8 replay_time; static Uint8 solved; +static Uint8 inserting,saved_inserting; static void record_solution(void); static void setup_game(void) { const char*v; @@ -137,11 +138,11 @@ for(y=44,x=replay_pos-(screen->h-68)/32;;x++) { y+=16; if(y+24>screen->h) break; if(x>=0 && x<replay_count) draw_key(16,y,replay_list[x],0xF8,0xFB); if(x==replay_count) draw_key(16,y,1,0xF0,0xF8); - if(x==replay_pos) draw_text(0,y,"~~",0xF0,0xFE); + if(x==replay_pos) draw_text(0,y,inserting?"I~":"~~",0xF0,0xFE); if(x==replay_mark) draw_text(32,y,"~~",0xF0,0xFD); } SDL_UnlockSurface(screen); } if(quiz_text) draw_popup(quiz_text); @@ -307,10 +308,11 @@ replay_time=0; if(replay_count) save_replay(); inputs_count=0; replay_pos=0; solved=0; + inserting=0; t=load_level(id)?:init_level(); load_replay(); if(t) { gameover=-1; screen_message(t); @@ -695,10 +697,11 @@ if(!inputs) fatal("Allocation failed\n"); } inputs[inputs_count++]=number; return 0; case '+ ': replay: // Replay + saved_inserting=inserting; inserting=0; 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); @@ -706,10 +709,11 @@ } memcpy(inputs+inputs_count,replay_list+replay_pos,number); inputs_count+=number; return 0; case '- ': // Rewind + saved_inserting=inserting; number=replay_pos-number; if(number<0) number=0; //fallthru case '= ': restart: // Restart begin_level(level_id); @@ -727,10 +731,21 @@ goto restart; case '^>': // Replay to mark inputs_count=0; number=replay_mark-replay_pos; goto replay; + case '^-': // Delete move + inputs_count=0; + if(replay_pos==replay_count) return 0; + memmove(replay_list+replay_pos,replay_list+replay_pos+1,replay_count-replay_pos-1); + replay_count--; + if(replay_mark>replay_pos) replay_mark--; + return 0; + case '^+': // Insert moves + inputs_count=0; + inserting^=1; + return 0; case '^E': // Edit return main_options['r']?1:-2; case '^I': // Toggle inventory display side_mode^=1; return prev; @@ -830,10 +845,23 @@ screen_message(t); gameover=-1; return; } if(!key_ignored) { + if(inserting) { + if(replay_pos>=0xFFFE || replay_pos==replay_count) { + inserting=0; + } else { + if(replay_count>=0xFFFE) replay_count=0xFFFD; + if(replay_size<0xFFFF) { + replay_list=realloc(replay_list,replay_size=0xFFFF); + if(!replay_list) fatal("Allocation failed\n"); + } + memmove(replay_list+replay_pos+1,replay_list+replay_pos,replay_count-replay_pos); + replay_count++; + } + } if(replay_pos>=replay_size) { if(replay_size>0xFDFF) replay_size=0xFDFF; if(replay_size+0x200<=replay_pos) fatal("Confusion in input_move function\n"); replay_list=realloc(replay_list,replay_size+=0x200); if(!replay_list) fatal("Allocation failed\n"); @@ -946,10 +974,11 @@ } replay: if(inputs_count) { for(i=0;i<inputs_count && !gameover;i++) if(inputs[i]) input_move(inputs[i]); inputs_count=0; + if(saved_inserting) inserting=1,saved_inserting=0; no_dead_anim=0; if(gameover==1 && should_record_solution) record_solution(); } redraw_game(); timerflag=0; // ensure we have not missed a timer event Index: game.doc ================================================================== --- game.doc +++ game.doc @@ -69,10 +69,18 @@ number of moves. You can set a mark by pushing F5. You can then push F6 or F7 to rewind or replay up to this point. The marks are also saved with each level and is saved in the user cache database too. + +You can also delete moves by pushing the DELETE key (the next move to be +played in the replay list is deleted), or toggle insertion mode by pushing +the INSERT key. While insertion mode is active, the move list displays +"I~" and any new moves entered will be inserted into the current position +in the move list instead of overwriting it. Insertion mode is reset when +restarting a level or accessing a different level, and will be temporarily +disabled while playing back the replay list. You can also import/export move lists. Push CTRL+I to import or CTRL+X to export, and at the prompt type the operating system command which will send the move list to stdout or receive the move list from stdin, for example if you want the file called "Movelist" then you can type "cat @@ -135,12 +143,14 @@ SHIFT+KP - First level ALT+G Inspect globals ALT+P Begin slow replay ALT+[ Increase slow replay speed ALT+] Decrease slow replay speed + INS Toggle insertion mode + DEL Delete a move Mouse (in grid): MIDDLE Describe topmost object RIGHT Inspect objects (main world) SHIFT+RIGHT Inspect objects (bizarro world)