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