Since the split into random and descriptive IDs, the section on game seeds has
[sgt/puzzles] / HACKING.but
1 \cfg{text-indent}{0}
2 \cfg{text-width}{72}
3 \cfg{text-title-align}{left}
4 \cfg{text-chapter-align}{left}
5 \cfg{text-chapter-numeric}{true}
6 \cfg{text-chapter-suffix}{. }
7 \cfg{text-chapter-underline}{-}
8 \cfg{text-section-align}{0}{left}
9 \cfg{text-section-numeric}{0}{true}
10 \cfg{text-section-suffix}{0}{. }
11 \cfg{text-section-underline}{0}{-}
12 \cfg{text-section-align}{1}{left}
13 \cfg{text-section-numeric}{1}{true}
14 \cfg{text-section-suffix}{1}{. }
15 \cfg{text-section-underline}{1}{-}
16 \cfg{text-versionid}{0}
17
18 \title Hacking guide for Simon Tatham's puzzle collection
19
20 \C{newpuz} Guide to writing a new puzzle
21
22 Start by copying \cw{nullgame.c}. This contains all the function
23 definitions and stubs that should be necessary to at least compile.
24 Some things are fine as they are unless you do something that
25 requires a change (for example, \cw{dup_params()} can usually be
26 left as it is since game parameters often don't have any
27 variable-size elements that need to be dynamically allocated); other
28 things are sure to need changing (for example, the params structure
29 is likely to need to contain at least one actual variable). Anything
30 marked \q{FIXME} really needs changing before you have a working
31 game.
32
33 \e{DO NOT EDIT THE MAKEFILES.} Edit \c{Recipe} instead, and then
34 re-run \cw{mkfiles.pl}. The individual makefiles are automatically
35 generated by this mechanism, so editing them directly will not
36 produce a usable patch.
37
38 \H{newpuz-arch} General architecture tips
39
40 Think carefully about which data structures need to contain which
41 parts of the game information.
42
43 \b \c{game_state} should contain everything that holds the current
44 state of play in a specific game. The mid-end maintains one of these
45 for every move the player has made, and moves back and forwards
46 along the list when you use Undo and Redo. So anything you would
47 expect to have restored when you undo needs to go in this state.
48
49 \b \c{game_params} should contain parameters the user can set before
50 generating a new game. For example, if the game is played on a grid
51 of variable size, \cw{game_params} contains the grid size.
52 (\cw{game_state} will \e{also} need to contain the grid size. You
53 might even wish to have \cw{game_state} contain a \cw{game_params}
54 member.)
55
56 \b \c{game_ui} contains aspects of the game's user interface which
57 are not expected to be restored in an undo operation. For example,
58 if you have a basically mouse-clicky sort of game (such as Net) but
59 you want to provide a cursor which can be moved with the arrow keys,
60 then putting the location of the cursor in \c{game_ui} is
61 reasonable. Or if the game allows you to drag things around the
62 display, then the current state of dragging is something that can go
63 in \c{game_ui}. Simple games don't need a \cw{game_ui} structure at
64 all.
65
66 \b \c{game_drawstate} contains things you know about the current
67 state of the game's display. For example, if your display is made up
68 of tiles and you want to redraw as few as possible, you might want
69 to have \c{game_drawstate} contain a description of the last tile
70 you drew at every position, so that you can compare it to the new
71 tile and avoid redrawing tiles that haven't changed.
72
73 \H{newpuz-params} Notes on parameters
74
75 You need to define a textual format for the game parameters (the part
76 before the \q{:} or \q{#} in descriptive and random IDs respectively).
77
78 The per-game parameter encoding function \cw{encode_params()} is
79 passed an argument \c{full}. This serves two purposes:
80
81 \b You can suppress inclusion of parameters that only affect game
82 generation, and thus would have no effect in a descriptive ID, in the
83 ID displayed by \q{Game -> Specific} if \c{full} is \cw{FALSE}.
84
85 \b You can ensure that a particular parameter entered as part of a
86 game ID does not persist when a new puzzle is generated, for instance
87 if you think that a player would not want it to persist beyond a
88 single game. An example is the \q{expansion factor} in Rectangles.
89
90 When generating a new puzzle instance, give some thought to the order
91 in which parameters are processed. For example, the order of grid
92 generation in Net is:
93
94 \b First the game sets up a valid completed Net grid.
95
96 \b Then it makes a list of every edge with no connection across it.
97 These edges are eligible to become barriers.
98
99 \b Then the grid is shuffled by randomly rotating every tile.
100
101 \b Then the game multiplies the number of barrier-candidate edges by
102 the barrier probability in order to decide how many barriers to
103 create.
104
105 \b Finally, it picks that many edges out of the barrier candidate
106 list, removing each edge from the list as it selects it.
107
108 The effect of this is that the actual barrier locations are chosen
109 \e{last}, which means that if you change the barrier rate and then
110 enter the same random number seed, \e{only} the barriers change.
111 Furthermore, if you do this, the barrier sets will be nested (i.e.
112 the version with more barriers will contain every barrier from the
113 one with fewer), so that selecting 10 barriers and then 20 barriers
114 will not give a user 30 pieces of information, only 20.
115
116 \H{newpuz-descid} Notes on descriptive IDs
117
118 The descriptive game ID is the part that comes after the colon in the
119 ID accessed through \q{Game -> Specific}. It does not need to be
120 especially concise, but it should be designed to remain compatible
121 with new versions of the puzzle.
122
123 Try to imagine all the things a user might want to use the descriptive
124 ID for, and build as much capability into it as possible. At a minimum,
125 you need to be able to generate one of these given a random number
126 source; however, if auto-generation capability is limited, give some
127 thought to the possibility of a user making up their own descriptive
128 IDs. This property is particularly useful if the puzzle is an
129 implementation of a well-known game, in which case existing instances
130 of the puzzle might be available which a user might want to transcribe
131 into game seeds in order to play them conveniently.
132
133 \H{newpuz-redraw} Designing a drawing routine
134
135 Front end implementations are required to remember all data drawn by
136 the game. That is, a game redraw routine MUST never be called simply
137 because part of the game window was briefly obscured; the front end
138 is required to remember what the game last drew in that area of the
139 window, and redraw it itself without bothering the game module.
140
141 Many games will need some form of animation when transferring
142 between one \cw{game_state} and the next. This is achieved by having
143 \cw{game_anim_length()} analyse two adjacent game states, decide how
144 long the linking animation between them should last, and return this
145 duration in seconds. Then \cw{game_redraw()} will be passed the two
146 game states plus an indication of how far through the animation it
147 is, and can do its drawing appropriately.
148
149 \e{Be aware that you will be required to animate on undo}. If you
150 are at game state A and the user makes a move creating game state B,
151 then your redraw function will be passed both states A and B, in
152 that order, and will be expected to animate between them if your
153 game needs animation. However, if the user then hits Undo, your
154 redraw function will be passed states B and A, in \e{that} order,
155 and will be expected to perform the reverse animation.
156
157 This is easy enough for some games. In Fifteen, for example, it's
158 simply a matter of examining the two game states to work out what
159 has changed between them, and drawing each tile some proportion of
160 the way between its starting and finishing positions.
161
162 In Sixteen, things are more difficult. You could examine the grid to
163 work out which tiles had been moved and decide which way they had
164 been moved, but this would be disconcerting to the user in some
165 cases. In a 2xN game of Sixteen, rotating a two-tile row left or
166 right has the same end result but should look different during the
167 enimation; so the Sixteen \cw{game_state} in fact stores an extra
168 piece of information giving the direction of the last move. So when
169 making a normal move, \cw{game_redraw()} can know which way round it
170 is expected to animate a two-tile rotation.
171
172 However, even this doesn't fix the undo case. When
173 \cw{game_redraw()} is passed a pair of game states in the right
174 chronological order, the second one contains the direction field
175 which corresponds to the actual difference between the states.
176 However, when it is passed a pair of states in the opposite order
177 due to an undo, it should be looking in the \e{first} one to find
178 the direction field.
179
180 For this reason, in the redraw functions you are provided with an
181 extra argument \c{dir} which tells you which state was chronologically
182 first; \c{dir} is +1 for a normal move and -1 for an undo.