aboutsummaryrefslogtreecommitdiff
path: root/HACKING.but
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2005-07-28 17:12:18 +0000
committerSimon Tatham <anakin@pobox.com>2005-07-28 17:12:18 +0000
commitf44e4acd4a4216700ef8094cc4ae7251c6f4cdc6 (patch)
tree9197be9cb79d693e14ff613a25607663ef44c3c1 /HACKING.but
parentcc06b70328faf5a9c9806bd1108636f98846cd3b (diff)
downloadpuzzles-f44e4acd4a4216700ef8094cc4ae7251c6f4cdc6.zip
puzzles-f44e4acd4a4216700ef8094cc4ae7251c6f4cdc6.tar.gz
puzzles-f44e4acd4a4216700ef8094cc4ae7251c6f4cdc6.tar.bz2
puzzles-f44e4acd4a4216700ef8094cc4ae7251c6f4cdc6.tar.xz
Shiny new developer documentation to replace the old sketchy HACKING
guide. [originally from svn r6142]
Diffstat (limited to 'HACKING.but')
-rw-r--r--HACKING.but182
1 files changed, 0 insertions, 182 deletions
diff --git a/HACKING.but b/HACKING.but
deleted file mode 100644
index 6bf9785..0000000
--- a/HACKING.but
+++ /dev/null
@@ -1,182 +0,0 @@
-\cfg{text-indent}{0}
-\cfg{text-width}{72}
-\cfg{text-title-align}{left}
-\cfg{text-chapter-align}{left}
-\cfg{text-chapter-numeric}{true}
-\cfg{text-chapter-suffix}{. }
-\cfg{text-chapter-underline}{-}
-\cfg{text-section-align}{0}{left}
-\cfg{text-section-numeric}{0}{true}
-\cfg{text-section-suffix}{0}{. }
-\cfg{text-section-underline}{0}{-}
-\cfg{text-section-align}{1}{left}
-\cfg{text-section-numeric}{1}{true}
-\cfg{text-section-suffix}{1}{. }
-\cfg{text-section-underline}{1}{-}
-\cfg{text-versionid}{0}
-
-\title Hacking guide for Simon Tatham's puzzle collection
-
-\C{newpuz} Guide to writing a new puzzle
-
-Start by copying \cw{nullgame.c}. This contains all the function
-definitions and stubs that should be necessary to at least compile.
-Some things are fine as they are unless you do something that
-requires a change (for example, \cw{dup_params()} can usually be
-left as it is since game parameters often don't have any
-variable-size elements that need to be dynamically allocated); other
-things are sure to need changing (for example, the params structure
-is likely to need to contain at least one actual variable). Anything
-marked \q{FIXME} really needs changing before you have a working
-game.
-
-\e{DO NOT EDIT THE MAKEFILES.} Edit \c{Recipe} instead, and then
-re-run \cw{mkfiles.pl}. The individual makefiles are automatically
-generated by this mechanism, so editing them directly will not
-produce a usable patch.
-
-\H{newpuz-arch} General architecture tips
-
-Think carefully about which data structures need to contain which
-parts of the game information.
-
-\b \c{game_state} should contain everything that holds the current
-state of play in a specific game. The mid-end maintains one of these
-for every move the player has made, and moves back and forwards
-along the list when you use Undo and Redo. So anything you would
-expect to have restored when you undo needs to go in this state.
-
-\b \c{game_params} should contain parameters the user can set before
-generating a new game. For example, if the game is played on a grid
-of variable size, \cw{game_params} contains the grid size.
-(\cw{game_state} will \e{also} need to contain the grid size. You
-might even wish to have \cw{game_state} contain a \cw{game_params}
-member.)
-
-\b \c{game_ui} contains aspects of the game's user interface which
-are not expected to be restored in an undo operation. For example,
-if you have a basically mouse-clicky sort of game (such as Net) but
-you want to provide a cursor which can be moved with the arrow keys,
-then putting the location of the cursor in \c{game_ui} is
-reasonable. Or if the game allows you to drag things around the
-display, then the current state of dragging is something that can go
-in \c{game_ui}. Simple games don't need a \cw{game_ui} structure at
-all.
-
-\b \c{game_drawstate} contains things you know about the current
-state of the game's display. For example, if your display is made up
-of tiles and you want to redraw as few as possible, you might want
-to have \c{game_drawstate} contain a description of the last tile
-you drew at every position, so that you can compare it to the new
-tile and avoid redrawing tiles that haven't changed.
-
-\H{newpuz-params} Notes on parameters
-
-You need to define a textual format for the game parameters (the part
-before the \q{:} or \q{#} in descriptive and random IDs respectively).
-
-The per-game parameter encoding function \cw{encode_params()} is
-passed an argument \c{full}. This serves two purposes:
-
-\b You can suppress inclusion of parameters that only affect game
-generation, and thus would have no effect in a descriptive ID, in the
-ID displayed by \q{Game -> Specific} if \c{full} is \cw{FALSE}.
-
-\b You can ensure that a particular parameter entered as part of a
-game ID does not persist when a new puzzle is generated, for instance
-if you think that a player would not want it to persist beyond a
-single game. An example is the \q{expansion factor} in Rectangles.
-
-When generating a new puzzle instance, give some thought to the order
-in which parameters are processed. For example, the order of grid
-generation in Net is:
-
-\b First the game sets up a valid completed Net grid.
-
-\b Then it makes a list of every edge with no connection across it.
-These edges are eligible to become barriers.
-
-\b Then the grid is shuffled by randomly rotating every tile.
-
-\b Then the game multiplies the number of barrier-candidate edges by
-the barrier probability in order to decide how many barriers to
-create.
-
-\b Finally, it picks that many edges out of the barrier candidate
-list, removing each edge from the list as it selects it.
-
-The effect of this is that the actual barrier locations are chosen
-\e{last}, which means that if you change the barrier rate and then
-enter the same random number seed, \e{only} the barriers change.
-Furthermore, if you do this, the barrier sets will be nested (i.e.
-the version with more barriers will contain every barrier from the
-one with fewer), so that selecting 10 barriers and then 20 barriers
-will not give a user 30 pieces of information, only 20.
-
-\H{newpuz-descid} Notes on descriptive IDs
-
-The descriptive game ID is the part that comes after the colon in the
-ID accessed through \q{Game -> Specific}. It does not need to be
-especially concise, but it should be designed to remain compatible
-with new versions of the puzzle.
-
-Try to imagine all the things a user might want to use the descriptive
-ID for, and build as much capability into it as possible. At a minimum,
-you need to be able to generate one of these given a random number
-source; however, if auto-generation capability is limited, give some
-thought to the possibility of a user making up their own descriptive
-IDs. This property is particularly useful if the puzzle is an
-implementation of a well-known game, in which case existing instances
-of the puzzle might be available which a user might want to transcribe
-into game seeds in order to play them conveniently.
-
-\H{newpuz-redraw} Designing a drawing routine
-
-Front end implementations are required to remember all data drawn by
-the game. That is, a game redraw routine MUST never be called simply
-because part of the game window was briefly obscured; the front end
-is required to remember what the game last drew in that area of the
-window, and redraw it itself without bothering the game module.
-
-Many games will need some form of animation when transferring
-between one \cw{game_state} and the next. This is achieved by having
-\cw{game_anim_length()} analyse two adjacent game states, decide how
-long the linking animation between them should last, and return this
-duration in seconds. Then \cw{game_redraw()} will be passed the two
-game states plus an indication of how far through the animation it
-is, and can do its drawing appropriately.
-
-\e{Be aware that you will be required to animate on undo}. If you
-are at game state A and the user makes a move creating game state B,
-then your redraw function will be passed both states A and B, in
-that order, and will be expected to animate between them if your
-game needs animation. However, if the user then hits Undo, your
-redraw function will be passed states B and A, in \e{that} order,
-and will be expected to perform the reverse animation.
-
-This is easy enough for some games. In Fifteen, for example, it's
-simply a matter of examining the two game states to work out what
-has changed between them, and drawing each tile some proportion of
-the way between its starting and finishing positions.
-
-In Sixteen, things are more difficult. You could examine the grid to
-work out which tiles had been moved and decide which way they had
-been moved, but this would be disconcerting to the user in some
-cases. In a 2xN game of Sixteen, rotating a two-tile row left or
-right has the same end result but should look different during the
-enimation; so the Sixteen \cw{game_state} in fact stores an extra
-piece of information giving the direction of the last move. So when
-making a normal move, \cw{game_redraw()} can know which way round it
-is expected to animate a two-tile rotation.
-
-However, even this doesn't fix the undo case. When
-\cw{game_redraw()} is passed a pair of game states in the right
-chronological order, the second one contains the direction field
-which corresponds to the actual difference between the states.
-However, when it is passed a pair of states in the opposite order
-due to an undo, it should be looking in the \e{first} one to find
-the direction field.
-
-For this reason, in the redraw functions you are provided with an
-extra argument \c{dir} which tells you which state was chronologically
-first; \c{dir} is +1 for a normal move and -1 for an undo.