1 /* -*- c++ -*- 2 FILE: History.h 3 RCS REVISION: $Revision: 1.18 $ 4 5 COPYRIGHT: (c) 1999 -- 2003 Melinda Green, Don Hatch, and Jay Berkenbilt - Superliminal Software 6 7 LICENSE: Free to use and modify for non-commercial purposes as long as the 8 following conditions are adhered to: 9 1) Obvious credit for the source of this code and the designs it embodies 10 are clearly made, and 11 2) Ports and derived versions of 4D Magic Cube programs are not distributed 12 without the express written permission of the authors. 13 14 DESCRIPTION: 15 This class implements move history including marks and 16 bidirectional movements. 17 */ 18 19 #ifndef HISTORY_H 20 #define HISTORY_H 21 22 #include <stdio.h> 23 24 // RESERVED MARKS 25 // 26 // The marks defined below are reserved for special internal use. 27 // 28 // Special behavior for macros: when a macro is applied, the 29 // MACRO_START mark is placed in the history. When the macro is 30 // finished, the MACRO_END mark is placed in the history. This allows 31 // for fast undo over macros. 32 // 33 // Special behavior for full scrambles: when a full scramble is 34 // performed, the SCRAMBLE_BOUNDARY mark is placed in the history. It 35 // then takes special action on the part of the user to undo past this 36 // mark. 37 // 38 // A user could confound this by manually inserting a reserved mark in 39 // the logfile, but we won't worry about that case for now. The 40 // interface for creating marks should exclude creation of the marks 41 // defined below. 42 #define MARK_MACRO_OPEN ((int)'[') 43 #define MARK_MACRO_CLOSE ((int)']') 44 #define MARK_SCRAMBLE_BOUNDARY ((int)'|') 45 46 class Preferences; 47 48 class History { 49 private: 50 Preferences& preferences; 51 class PolygonManager4D *polymgr; 52 int length; 53 int debug; 54 struct historynode { 55 int stickerid; 56 int dir; 57 int slicesmask; 58 int mark; 59 struct historynode *prev, *next; /* doubly linked list */ 60 }; 61 struct historynode *first, *last, *current; 62 int isSane(); 63 void deleteNode( struct historynode *node); 64 void insertNode(struct historynode *node_to_insert_before, 65 int stickerid, int dir, int slicesmask, int mark); 66 struct historynode* getPrevious(); 67 int size(); 68 69 int goBackwardsTowardsMark(int mark, /* INPUT */ 70 struct stickerspec *sticker, /* OUTPUT */ 71 int *Dir, /* OUTPUT */ 72 int *Slicesmask); /* OUTPUT */ 73 int goForwardsTowardsMark(int mark, /* INPUT */ 74 struct stickerspec *sticker, /* OUTPUT */ 75 int *Dir, /* OUTPUT */ 76 int *Slicesmask); /* OUTPUT */ 77 78 int atMark(int mark); 79 80 81 public: 82 83 History(Preferences&, class PolygonManager4D *polymgr); 84 85 ~History(); 86 87 // length = -1 means no change to length 88 void reset(int length = -1); 89 90 void deleteLast(); 91 92 void destroy(); 93 94 void append(int stickerid, int dir, int slicesmask); 95 96 /* 97 * If there is a "current", delete it and everything after it. 98 */ 99 void truncate(); 100 101 /* 102 * Set current to be the beginning of the list. 103 */ 104 void goToBeginning(); 105 106 void goToEnd(); 107 108 /* 109 * Put a single move into the history. 110 * This clears the history after 111 * the current point, so a "redo" is impossible afterwards. 112 */ 113 void apply(struct stickerspec *sticker, int dir, int slicesmask); 114 115 /* 116 * Truncate (i.e. delete everything past current), 117 * remove non-moves (marks), 118 * merge rotates, 119 * put rotates before the twists, 120 * put opposite-face twists in canonical order, 121 * merge same-face twists. 122 * This is usually done in preparation for a "cheat" solve. 123 * 124 * FIX THIS-- this should be done on the fly, as the cheat-solve is happening 125 * (doing it like this causes a long wait if the history is long). 126 */ 127 void compress(); 128 129 /* 130 * Back up one move in the history, returning a move 131 * that would undo the last move. 132 * Returns 1 on success, 0 if there is nothing to undo. 133 */ 134 int undo( 135 struct stickerspec *sticker, /* OUTPUT */ 136 int *Dir, /* OUTPUT */ 137 int *Slicesmask); /* OUTPUT */ 138 139 /* 140 * Go forward one move in the history, returning the move 141 * to redo. This is only valid if a move was undone. 142 * Returns 1 on success, 0 if there is nothing to redo. 143 */ 144 int redo( 145 struct stickerspec *sticker, /* OUTPUT */ 146 int *Dir, /* OUTPUT */ 147 int *Slicesmask); /* OUTPUT */ 148 149 /* 150 * Clear the history 151 */ 152 void clear(); 153 154 /* 155 * Mark current position with the given string (only uses the first character). 156 */ 157 void mark(int mark); 158 159 /* 160 * Executes a history_undo or history_redo and returns 1 on success. 161 * Returns 0 if already at the mark, 162 * -1 if no such mark. 163 */ 164 int goTowardsMark(int mark, /* INPUT */ 165 struct stickerspec *sticker, /* OUTPUT */ 166 int *Dir, /* OUTPUT */ 167 int *Slicesmask, /* OUTPUT */ 168 bool forwards_first = false); 169 170 /* 171 * Make a note that the puzzle is currently in a solved state 172 * so that hitting the "cheat" button will not make it go past 173 * this state. Actually this is probably not necessary since 174 * the program can check by itself. 175 */ 176 void noteSolved(); 177 178 void dump(FILE *fp); 179 180 int read(FILE *fp); 181 182 int countTwists(); 183 184 int atMacroOpen(); 185 186 int atMacroClose(); 187 188 int atScrambleBoundary(); 189 }; 190 191 #endif 192 193 // Local Variables: 194 // c-basic-offset: 4 195 // c-comment-only-line-offset: 0 196 // c-file-offsets: ((defun-block-intro . +) (block-open . 0) (substatement-open . 0) (statement-cont . +) (statement-case-open . +4) (arglist-intro . +) (arglist-close . +) (inline-open . 0)) 197 // indent-tabs-mode: nil 198 // End: 199