-
Notifications
You must be signed in to change notification settings - Fork 1
/
devel.but
4777 lines (3589 loc) · 199 KB
/
devel.but
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\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}
\cfg{html-contents-filename}{index.html}
\cfg{html-template-filename}{%k.html}
\cfg{html-index-filename}{docindex.html}
\cfg{html-leaf-level}{1}
\cfg{html-contents-depth-0}{1}
\cfg{html-contents-depth-1}{3}
\cfg{html-leaf-contains-contents}{true}
\define{dash} \u2013{-}
\title Developer documentation for Simon Tatham's puzzle collection
This is a guide to the internal structure of Simon Tatham's Portable
Puzzle Collection (henceforth referred to simply as \q{Puzzles}),
for use by anyone attempting to implement a new puzzle or port to a
new platform.
This guide is believed correct as of r6190. Hopefully it will be
updated along with the code in future, but if not, I've at least
left this version number in here so you can figure out what's
changed by tracking commit comments from there onwards.
\C{intro} Introduction
The Puzzles code base is divided into four parts: a set of
interchangeable front ends, a set of interchangeable back ends, a
universal \q{middle end} which acts as a buffer between the two, and
a bunch of miscellaneous utility functions. In the following
sections I give some general discussion of each of these parts.
\H{intro-frontend} Front end
The front end is the non-portable part of the code: it's the bit
that you replace completely when you port to a different platform.
So it's responsible for all system calls, all GUI interaction, and
anything else platform-specific.
The current front ends in the main code base are for Windows, GTK
and MacOS X; I also know of a third-party front end for PalmOS.
The front end contains \cw{main()} or the local platform's
equivalent. Top-level control over the application's execution flow
belongs to the front end (it isn't, for example, a set of functions
called by a universal \cw{main()} somewhere else).
The front end has complete freedom to design the GUI for any given
port of Puzzles. There is no centralised mechanism for maintaining
the menu layout, for example. This has a cost in consistency (when I
\e{do} want the same menu layout on more than one platform, I have
to edit two pieces of code in parallel every time I make a change),
but the advantage is that local GUI conventions can be conformed to
and local constraints adapted to. For example, MacOS X has strict
human interface guidelines which specify a different menu layout
from the one I've used on Windows and GTK; there's nothing stopping
the OS X front end from providing a menu layout consistent with
those guidelines.
Although the front end is mostly caller rather than the callee in
its interactions with other parts of the code, it is required to
implement a small API for other modules to call, mostly of drawing
functions for games to use when drawing their graphics. The drawing
API is documented in \k{drawing}; the other miscellaneous front end
API functions are documented in \k{frontend-api}.
\H{intro-backend} Back end
A \q{back end}, in this collection, is synonymous with a \q{puzzle}.
Each back end implements a different game.
At the top level, a back end is simply a data structure, containing
a few constants (flag words, preferred pixel size) and a large
number of function pointers. Back ends are almost invariably callee
rather than caller, which means there's a limitation on what a back
end can do on its own initiative.
The persistent state in a back end is divided into a number of data
structures, which are used for different purposes and therefore
likely to be switched around, changed without notice, and otherwise
updated by the rest of the code. It is important when designing a
back end to put the right pieces of data into the right structures,
or standard midend-provided features (such as Undo) may fail to
work.
The functions and variables provided in the back end data structure
are documented in \k{backend}.
\H{intro-midend} Middle end
Puzzles has a single and universal \q{middle end}. This code is
common to all platforms and all games; it sits in between the front
end and the back end and provides standard functionality everywhere.
People adding new back ends or new front ends should generally not
need to edit the middle end. On rare occasions there might be a
change that can be made to the middle end to permit a new game to do
something not currently anticipated by the middle end's present
design; however, this is terribly easy to get wrong and should
probably not be undertaken without consulting the primary maintainer
(me). Patch submissions containing unannounced mid-end changes will
be treated on their merits like any other patch; this is just a
friendly warning that mid-end changes will need quite a lot of
merits to make them acceptable.
Functionality provided by the mid-end includes:
\b Maintaining a list of game state structures and moving back and
forth along that list to provide Undo and Redo.
\b Handling timers (for move animations, flashes on completion, and
in some cases actually timing the game).
\b Handling the container format of game IDs: receiving them,
picking them apart into parameters, description and/or random seed,
and so on. The game back end need only handle the individual parts
of a game ID (encoded parameters and encoded game description);
everything else is handled centrally by the mid-end.
\b Handling standard keystrokes and menu commands, such as \q{New
Game}, \q{Restart Game} and \q{Quit}.
\b Pre-processing mouse events so that the game back ends can rely
on them arriving in a sensible order (no missing button-release
events, no sudden changes of which button is currently pressed,
etc).
\b Handling the dialog boxes which ask the user for a game ID.
\b Handling serialisation of entire games (for loading and saving a
half-finished game to a disk file, or for handling application
shutdown and restart on platforms such as PalmOS where state is
expected to be saved).
Thus, there's a lot of work done once by the mid-end so that
individual back ends don't have to worry about it. All the back end
has to do is cooperate in ensuring the mid-end can do its work
properly.
The API of functions provided by the mid-end to be called by the
front end is documented in \k{midend}.
\H{intro-utils} Miscellaneous utilities
In addition to these three major structural components, the Puzzles
code also contains a variety of utility modules usable by all of the
above components. There is a set of functions to provide
platform-independent random number generation; functions to make
memory allocation easier; functions which implement a balanced tree
structure to be used as necessary in complex algorithms; and a few
other miscellaneous functions. All of these are documented in
\k{utils}.
\H{intro-structure} Structure of this guide
There are a number of function call interfaces within Puzzles, and
this guide will discuss each one in a chapter of its own. After
that, \k{writing} discusses how to design new games, with some
general design thoughts and tips.
\C{backend} Interface to the back end
This chapter gives a detailed discussion of the interface that each
back end must implement.
At the top level, each back end source file exports a single global
symbol, which is a \c{const struct game} containing a large number
of function pointers and a small amount of constant data. This
structure is called by different names depending on what kind of
platform the puzzle set is being compiled on:
\b On platforms such as Windows and GTK, which build a separate
binary for each puzzle, the game structure in every back end has the
same name, \cq{thegame}; the front end refers directly to this name,
so that compiling the same front end module against a different back
end module builds a different puzzle.
\b On platforms such as MacOS X and PalmOS, which build all the
puzzles into a single monolithic binary, the game structure in each
back end must have a different name, and there's a helper module
\c{list.c} (constructed automatically by the same Perl script that
builds the \cw{Makefile}s) which contains a complete list of those
game structures.
On the latter type of platform, source files may assume that the
preprocessor symbol \c{COMBINED} has been defined. Thus, the usual
code to declare the game structure looks something like this:
\c #ifdef COMBINED
\c #define thegame net /* or whatever this game is called */
\e iii iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
\c #endif
\c
\c const struct game thegame = {
\c /* lots of structure initialisation in here */
\e iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
\c };
Game back ends must also internally define a number of data
structures, for storing their various persistent state. This chapter
will first discuss the nature and use of those structures, and then
go on to give details of every element of the game structure.
\H{backend-structs} Data structures
Each game is required to define four separate data structures. This
section discusses each one and suggests what sorts of things need to
be put in it.
\S{backend-game-params} \c{game_params}
The \c{game_params} structure contains anything which affects the
automatic generation of new puzzles. So if puzzle generation is
parametrised in any way, those parameters need to be stored in
\c{game_params}.
Most puzzles currently in this collection are played on a grid of
squares, meaning that the most obvious parameter is the grid size.
Many puzzles have additional parameters; for example, Mines allows
you to control the number of mines in the grid independently of its
size, Net can be wrapping or non-wrapping, Solo has difficulty
levels and symmetry settings, and so on.
A simple rule for deciding whether a data item needs to go in
\c{game_params} is: would the user expect to be able to control this
data item from either the preset-game-types menu or the \q{Custom}
game type configuration? If so, it's part of \c{game_params}.
\c{game_params} structures are permitted to contain pointers to
subsidiary data if they need to. The back end is required to provide
functions to create and destroy \c{game_params}, and those functions
can allocate and free additional memory if necessary. (It has not
yet been necessary to do this in any puzzle so far, but the
capability is there just in case.)
\c{game_params} is also the only structure which the game's
\cw{compute_size()} function may refer to; this means that any
aspect of the game which affects the size of the window it needs to
be drawn in must be stored in \c{game_params}. In particular, this
imposes the fundamental limitation that random game generation may
not have a random effect on the window size: game generation
algorithms are constrained to work by starting from the grid size
rather than generating it as an emergent phenomenon. (Although this
is a restriction in theory, it has not yet seemed to be a problem.)
\S{backend-game-state} \c{game_state}
While the user is actually playing a puzzle, the \c{game_state}
structure stores all the data corresponding to the current state of
play.
The mid-end keeps \c{game_state}s in a list, and adds to the list
every time the player makes a move; the Undo and Redo functions step
back and forth through that list.
Therefore, a good means of deciding whether a data item needs to go
in \c{game_state} is: would a player expect that data item to be
restored on undo? If so, put it in \c{game_state}, and this will
automatically happen without you having to lift a finger. If not
\dash for example, the deaths counter in Mines is precisely
something that does \e{not} want to be reset to its previous state
on an undo \dash then you might have found a data item that needs to
go in \c{game_ui} instead.
During play, \c{game_state}s are often passed around without an
accompanying \c{game_params} structure. Therefore, any information
in \c{game_params} which is important during play (such as the grid
size) must be duplicated within the \c{game_state}. One simple
method of doing this is to have the \c{game_state} structure
\e{contain} a \c{game_params} structure as one of its members,
although this isn't obligatory if you prefer to do it another way.
\S{backend-game-drawstate} \c{game_drawstate}
\c{game_drawstate} carries persistent state relating to the current
graphical contents of the puzzle window. The same \c{game_drawstate}
is passed to every call to the game redraw function, so that it can
remember what it has already drawn and what needs redrawing.
A typical use for a \c{game_drawstate} is to have an array mirroring
the array of grid squares in the \c{game_state}; then every time the
redraw function was passed a \c{game_state}, it would loop over all
the squares, and physically redraw any whose description in the
\c{game_state} (i.e. what the square needs to look like when the
redraw is completed) did not match its description in the
\c{game_drawstate} (i.e. what the square currently looks like).
\c{game_drawstate} is occasionally completely torn down and
reconstructed by the mid-end, if the user somehow forces a full
redraw. Therefore, no data should be stored in \c{game_drawstate}
which is \e{not} related to the state of the puzzle window, because
it might be unexpectedly destroyed.
The back end provides functions to create and destroy
\c{game_drawstate}, which means it can contain pointers to
subsidiary allocated data if it needs to. A common thing to want to
allocate in a \c{game_drawstate} is a \c{blitter}; see
\k{drawing-blitter} for more on this subject.
\S{backend-game-ui} \c{game_ui}
\c{game_ui} contains whatever doesn't fit into the above three
structures!
A new \c{game_ui} is created when the user begins playing a new
instance of a puzzle (i.e. during \q{New Game} or after entering a
game ID etc). It persists until the user finishes playing that game
and begins another one (or closes the window); in particular,
\q{Restart Game} does \e{not} destroy the \c{game_ui}.
\c{game_ui} is useful for implementing user-interface state which is
not part of \c{game_state}. Common examples are keyboard control
(you wouldn't want to have to separately Undo through every cursor
motion) and mouse dragging. See \k{writing-keyboard-cursor} and
\k{writing-howto-dragging}, respectively, for more details.
Another use for \c{game_ui} is to store highly persistent data such
as the Mines death counter. This is conceptually rather different:
where the Net cursor position was \e{not important enough} to
preserve for the player to restore by Undo, the Mines death counter
is \e{too important} to permit the player to revert by Undo!
A final use for \c{game_ui} is to pass information to the redraw
function about recent changes to the game state. This is used in
Mines, for example, to indicate whether a requested \q{flash} should
be a white flash for victory or a red flash for defeat; see
\k{writing-flash-types}.
\H{backend-simple} Simple data in the back end
In this section I begin to discuss each individual element in the
back end structure. To begin with, here are some simple
self-contained data elements.
\S{backend-name} \c{name}
\c const char *name;
This is a simple ASCII string giving the name of the puzzle. This
name will be used in window titles, in game selection menus on
monolithic platforms, and anywhere else that the front end needs to
know the name of a game.
\S{backend-winhelp} \c{winhelp_topic}
\c const char *winhelp_topic;
This member is used on Windows only, to provide online help.
Although the Windows front end provides a separate binary for each
puzzle, it has a single monolithic help file; so when a user selects
\q{Help} from the menu, the program needs to open the help file and
jump to the chapter describing that particular puzzle.
Therefore, each chapter in \c{puzzles.but} is labelled with a
\e{help topic} name, similar to this:
\c \cfg{winhelp-topic}{games.net}
And then the corresponding game back end encodes the topic string
(here \cq{games.net}) in the \c{winhelp_topic} element of the game
structure.
\H{backend-params} Handling game parameter sets
In this section I present the various functions which handle the
\c{game_params} structure.
\S{backend-default-params} \cw{default_params()}
\c game_params *(*default_params)(void);
This function allocates a new \c{game_params} structure, fills it
with the default values, and returns a pointer to it.
\S{backend-fetch-preset} \cw{fetch_preset()}
\c int (*fetch_preset)(int i, char **name, game_params **params);
This function is used to populate the \q{Type} menu, which provides
a list of conveniently accessible preset parameters for most games.
The function is called with \c{i} equal to the index of the preset
required (numbering from zero). It returns \cw{FALSE} if that preset
does not exist (if \c{i} is less than zero or greater than the
largest preset index). Otherwise, it sets \c{*params} to point at a
newly allocated \c{game_params} structure containing the preset
information, sets \c{*name} to point at a newly allocated C string
containing the preset title (to go on the \q{Type} menu), and
returns \cw{TRUE}.
If the game does not wish to support any presets at all, this
function is permitted to return \cw{FALSE} always.
\S{backend-encode-params} \cw{encode_params()}
\c char *(*encode_params)(const game_params *params, int full);
The job of this function is to take a \c{game_params}, and encode it
in a string form for use in game IDs. The return value must be a
newly allocated C string, and \e{must} not contain a colon or a hash
(since those characters are used to mark the end of the parameter
section in a game ID).
Ideally, it should also not contain any other potentially
controversial punctuation; bear in mind when designing a string
parameter format that it will probably be used on both Windows and
Unix command lines under a variety of exciting shell quoting and
metacharacter rules. Sticking entirely to alphanumerics is the
safest thing; if you really need punctuation, you can probably get
away with commas, periods or underscores without causing anybody any
major inconvenience. If you venture far beyond that, you're likely
to irritate \e{somebody}.
(At the time of writing this, all existing games have purely
alphanumeric string parameter formats. Usually these involve a
letter denoting a parameter, followed optionally by a number giving
the value of that parameter, with a few mandatory parts at the
beginning such as numeric width and height separated by \cq{x}.)
If the \c{full} parameter is \cw{TRUE}, this function should encode
absolutely everything in the \c{game_params}, such that a subsequent
call to \cw{decode_params()} (\k{backend-decode-params}) will yield
an identical structure. If \c{full} is \cw{FALSE}, however, you
should leave out anything which is not necessary to describe a
\e{specific puzzle instance}, i.e. anything which only takes effect
when a new puzzle is \e{generated}. For example, the Solo
\c{game_params} includes a difficulty rating used when constructing
new puzzles; but a Solo game ID need not explicitly include the
difficulty, since to describe a puzzle once generated it's
sufficient to give the grid dimensions and the location and contents
of the clue squares. (Indeed, one might very easily type in a puzzle
out of a newspaper without \e{knowing} what its difficulty level is
in Solo's terminology.) Therefore, Solo's \cw{encode_params()} only
encodes the difficulty level if \c{full} is set.
\S{backend-decode-params} \cw{decode_params()}
\c void (*decode_params)(game_params *params, char const *string);
This function is the inverse of \cw{encode_params()}
(\k{backend-encode-params}). It parses the supplied string and fills
in the supplied \c{game_params} structure. Note that the structure
will \e{already} have been allocated: this function is not expected
to create a \e{new} \c{game_params}, but to modify an existing one.
This function can receive a string which only encodes a subset of
the parameters. The most obvious way in which this can happen is if
the string was constructed by \cw{encode_params()} with its \c{full}
parameter set to \cw{FALSE}; however, it could also happen if the
user typed in a parameter set manually and missed something out. Be
prepared to deal with a wide range of possibilities.
When dealing with a parameter which is not specified in the input
string, what to do requires a judgment call on the part of the
programmer. Sometimes it makes sense to adjust other parameters to
bring them into line with the new ones. In Mines, for example, you
would probably not want to keep the same mine count if the user
dropped the grid size and didn't specify one, since you might easily
end up with more mines than would actually fit in the grid! On the
other hand, sometimes it makes sense to leave the parameter alone: a
Solo player might reasonably expect to be able to configure size and
difficulty independently of one another.
This function currently has no direct means of returning an error if
the string cannot be parsed at all. However, the returned
\c{game_params} is almost always subsequently passed to
\cw{validate_params()} (\k{backend-validate-params}), so if you
really want to signal parse errors, you could always have a \c{char
*} in your parameters structure which stored an error message, and
have \cw{validate_params()} return it if it is non-\cw{NULL}.
\S{backend-free-params} \cw{free_params()}
\c void (*free_params)(game_params *params);
This function frees a \c{game_params} structure, and any subsidiary
allocations contained within it.
\S{backend-dup-params} \cw{dup_params()}
\c game_params *(*dup_params)(const game_params *params);
This function allocates a new \c{game_params} structure and
initialises it with an exact copy of the information in the one
provided as input. It returns a pointer to the new duplicate.
\S{backend-can-configure} \c{can_configure}
\c int can_configure;
This boolean data element is set to \cw{TRUE} if the back end
supports custom parameter configuration via a dialog box. If it is
\cw{TRUE}, then the functions \cw{configure()} and
\cw{custom_params()} are expected to work. See \k{backend-configure}
and \k{backend-custom-params} for more details.
\S{backend-configure} \cw{configure()}
\c config_item *(*configure)(const game_params *params);
This function is called when the user requests a dialog box for
custom parameter configuration. It returns a newly allocated array
of \cw{config_item} structures, describing the GUI elements required
in the dialog box. The array should have one more element than the
number of controls, since it is terminated with a \cw{C_END} marker
(see below). Each array element describes the control together with
its initial value; the front end will modify the value fields and
return the updated array to \cw{custom_params()} (see
\k{backend-custom-params}).
The \cw{config_item} structure contains the following elements:
\c char *name;
\c int type;
\c char *sval;
\c int ival;
\c{name} is an ASCII string giving the textual label for a GUI
control. It is \e{not} expected to be dynamically allocated.
\c{type} contains one of a small number of \c{enum} values defining
what type of control is being described. The meaning of the \c{sval}
and \c{ival} fields depends on the value in \c{type}. The valid
values are:
\dt \c{C_STRING}
\dd Describes a text input box. (This is also used for numeric
input. The back end does not bother informing the front end that the
box is numeric rather than textual; some front ends do have the
capacity to take this into account, but I decided it wasn't worth
the extra complexity in the interface.) For this type, \c{ival} is
unused, and \c{sval} contains a dynamically allocated string
representing the contents of the input box.
\dt \c{C_BOOLEAN}
\dd Describes a simple checkbox. For this type, \c{sval} is unused,
and \c{ival} is \cw{TRUE} or \cw{FALSE}.
\dt \c{C_CHOICES}
\dd Describes a drop-down list presenting one of a small number of
fixed choices. For this type, \c{sval} contains a list of strings
describing the choices; the very first character of \c{sval} is used
as a delimiter when processing the rest (so that the strings
\cq{:zero:one:two}, \cq{!zero!one!two} and \cq{xzeroxonextwo} all
define a three-element list containing \cq{zero}, \cq{one} and
\cq{two}). \c{ival} contains the index of the currently selected
element, numbering from zero (so that in the above example, 0 would
mean \cq{zero} and 2 would mean \cq{two}).
\lcont{
Note that for this control type, \c{sval} is \e{not} dynamically
allocated, whereas it was for \c{C_STRING}.
}
\dt \c{C_END}
\dd Marks the end of the array of \c{config_item}s. All other fields
are unused.
The array returned from this function is expected to have filled in
the initial values of all the controls according to the input
\c{game_params} structure.
If the game's \c{can_configure} flag is set to \cw{FALSE}, this
function is never called and need not do anything at all.
\S{backend-custom-params} \cw{custom_params()}
\c game_params *(*custom_params)(const config_item *cfg);
This function is the counterpart to \cw{configure()}
(\k{backend-configure}). It receives as input an array of
\c{config_item}s which was originally created by \cw{configure()},
but in which the control values have since been changed in
accordance with user input. Its function is to read the new values
out of the controls and return a newly allocated \c{game_params}
structure representing the user's chosen parameter set.
(The front end will have modified the controls' \e{values}, but
there will still always be the same set of controls, in the same
order, as provided by \cw{configure()}. It is not necessary to check
the \c{name} and \c{type} fields, although you could use
\cw{assert()} if you were feeling energetic.)
This function is not expected to (and indeed \e{must not}) free the
input \c{config_item} array. (If the parameters fail to validate,
the dialog box will stay open.)
If the game's \c{can_configure} flag is set to \cw{FALSE}, this
function is never called and need not do anything at all.
\S{backend-validate-params} \cw{validate_params()}
\c char *(*validate_params)(const game_params *params, int full);
This function takes a \c{game_params} structure as input, and checks
that the parameters described in it fall within sensible limits. (At
the very least, grid dimensions should almost certainly be strictly
positive, for example.)
Return value is \cw{NULL} if no problems were found, or
alternatively a (non-dynamically-allocated) ASCII string describing
the error in human-readable form.
If the \c{full} parameter is set, full validation should be
performed: any set of parameters which would not permit generation
of a sensible puzzle should be faulted. If \c{full} is \e{not} set,
the implication is that these parameters are not going to be used
for \e{generating} a puzzle; so parameters which can't even sensibly
\e{describe} a valid puzzle should still be faulted, but parameters
which only affect puzzle generation should not be.
(The \c{full} option makes a difference when parameter combinations
are non-orthogonal. For example, Net has a boolean option
controlling whether it enforces a unique solution; it turns out that
it's impossible to generate a uniquely soluble puzzle with wrapping
walls and width 2, so \cw{validate_params()} will complain if you
ask for one. However, if the user had just been playing a unique
wrapping puzzle of a more sensible width, and then pastes in a game
ID acquired from somebody else which happens to describe a
\e{non}-unique wrapping width-2 puzzle, then \cw{validate_params()}
will be passed a \c{game_params} containing the width and wrapping
settings from the new game ID and the uniqueness setting from the
old one. This would be faulted, if it weren't for the fact that
\c{full} is not set during this call, so Net ignores the
inconsistency. The resulting \c{game_params} is never subsequently
used to generate a puzzle; this is a promise made by the mid-end
when it asks for a non-full validation.)
\H{backend-descs} Handling game descriptions
In this section I present the functions that deal with a textual
description of a puzzle, i.e. the part that comes after the colon in
a descriptive-format game ID.
\S{backend-new-desc} \cw{new_desc()}
\c char *(*new_desc)(const game_params *params, random_state *rs,
\c char **aux, int interactive);
This function is where all the really hard work gets done. This is
the function whose job is to randomly generate a new puzzle,
ensuring solubility and uniqueness as appropriate.
As input it is given a \c{game_params} structure and a random state
(see \k{utils-random} for the random number API). It must invent a
puzzle instance, encode it in string form, and return a dynamically
allocated C string containing that encoding.
Additionally, it may return a second dynamically allocated string in
\c{*aux}. (If it doesn't want to, then it can leave that parameter
completely alone; it isn't required to set it to \cw{NULL}, although
doing so is harmless.) That string, if present, will be passed to
\cw{solve()} (\k{backend-solve}) later on; so if the puzzle is
generated in such a way that a solution is known, then information
about that solution can be saved in \c{*aux} for \cw{solve()} to
use.
The \c{interactive} parameter should be ignored by almost all
puzzles. Its purpose is to distinguish between generating a puzzle
within a GUI context for immediate play, and generating a puzzle in
a command-line context for saving to be played later. The only
puzzle that currently uses this distinction (and, I fervently hope,
the only one which will \e{ever} need to use it) is Mines, which
chooses a random first-click location when generating puzzles
non-interactively, but which waits for the user to place the first
click when interactive. If you think you have come up with another
puzzle which needs to make use of this parameter, please think for
at least ten minutes about whether there is \e{any} alternative!
Note that game description strings are not required to contain an
encoding of parameters such as grid size; a game description is
never separated from the \c{game_params} it was generated with, so
any information contained in that structure need not be encoded
again in the game description.
\S{backend-validate-desc} \cw{validate_desc()}
\c char *(*validate_desc)(const game_params *params, const char *desc);
This function is given a game description, and its job is to
validate that it describes a puzzle which makes sense.
To some extent it's up to the user exactly how far they take the
phrase \q{makes sense}; there are no particularly strict rules about
how hard the user is permitted to shoot themself in the foot when
typing in a bogus game description by hand. (For example, Rectangles
will not verify that the sum of all the numbers in the grid equals
the grid's area. So a user could enter a puzzle which was provably
not soluble, and the program wouldn't complain; there just wouldn't
happen to be any sequence of moves which solved it.)
The one non-negotiable criterion is that any game description which
makes it through \cw{validate_desc()} \e{must not} subsequently
cause a crash or an assertion failure when fed to \cw{new_game()}
and thence to the rest of the back end.
The return value is \cw{NULL} on success, or a
non-dynamically-allocated C string containing an error message.
\S{backend-new-game} \cw{new_game()}
\c game_state *(*new_game)(midend *me, const game_params *params,
\c const char *desc);
This function takes a game description as input, together with its
accompanying \c{game_params}, and constructs a \c{game_state}
describing the initial state of the puzzle. It returns a newly
allocated \c{game_state} structure.
Almost all puzzles should ignore the \c{me} parameter. It is
required by Mines, which needs it for later passing to
\cw{midend_supersede_game_desc()} (see \k{backend-supersede}) once
the user has placed the first click. I fervently hope that no other
puzzle will be awkward enough to require it, so everybody else
should ignore it. As with the \c{interactive} parameter in
\cw{new_desc()} (\k{backend-new-desc}), if you think you have a
reason to need this parameter, please try very hard to think of an
alternative approach!
\H{backend-states} Handling game states
This section describes the functions which create and destroy
\c{game_state} structures.
(Well, except \cw{new_game()}, which is in \k{backend-new-game}
instead of under here; but it deals with game descriptions \e{and}
game states and it had to go in one section or the other.)
\S{backend-dup-game} \cw{dup_game()}
\c game_state *(*dup_game)(const game_state *state);
This function allocates a new \c{game_state} structure and
initialises it with an exact copy of the information in the one
provided as input. It returns a pointer to the new duplicate.
\S{backend-free-game} \cw{free_game()}
\c void (*free_game)(game_state *state);
This function frees a \c{game_state} structure, and any subsidiary
allocations contained within it.
\H{backend-ui} Handling \c{game_ui}
\S{backend-new-ui} \cw{new_ui()}
\c game_ui *(*new_ui)(const game_state *state);
This function allocates and returns a new \c{game_ui} structure for
playing a particular puzzle. It is passed a pointer to the initial
\c{game_state}, in case it needs to refer to that when setting up
the initial values for the new game.
\S{backend-free-ui} \cw{free_ui()}
\c void (*free_ui)(game_ui *ui);
This function frees a \c{game_ui} structure, and any subsidiary
allocations contained within it.
\S{backend-encode-ui} \cw{encode_ui()}
\c char *(*encode_ui)(const game_ui *ui);
This function encodes any \e{important} data in a \c{game_ui}
structure in string form. It is only called when saving a
half-finished game to a file.
It should be used sparingly. Almost all data in a \c{game_ui} is not
important enough to save. The location of the keyboard-controlled
cursor, for example, can be reset to a default position on reloading
the game without impacting the user experience. If the user should
somehow manage to save a game while a mouse drag was in progress,
then discarding that mouse drag would be an outright \e{feature}.
A typical thing that \e{would} be worth encoding in this function is
the Mines death counter: it's in the \c{game_ui} rather than the
\c{game_state} because it's too important to allow the user to
revert it by using Undo, and therefore it's also too important to
allow the user to revert it by saving and reloading. (Of course, the
user could edit the save file by hand... But if the user is \e{that}
determined to cheat, they could just as easily modify the game's
source.)
\S{backend-decode-ui} \cw{decode_ui()}
\c void (*decode_ui)(game_ui *ui, const char *encoding);
This function parses a string previously output by \cw{encode_ui()},
and writes the decoded data back into the provided \c{game_ui}
structure.
\S{backend-changed-state} \cw{changed_state()}
\c void (*changed_state)(game_ui *ui, const game_state *oldstate,
\c const game_state *newstate);
This function is called by the mid-end whenever the current game
state changes, for any reason. Those reasons include:
\b a fresh move being made by \cw{interpret_move()} and
\cw{execute_move()}
\b a solve operation being performed by \cw{solve()} and
\cw{execute_move()}
\b the user moving back and forth along the undo list by means of
the Undo and Redo operations
\b the user selecting Restart to go back to the initial game state.
The job of \cw{changed_state()} is to update the \c{game_ui} for
consistency with the new game state, if any update is necessary. For
example, Same Game stores data about the currently selected tile
group in its \c{game_ui}, and this data is intrinsically related to
the game state it was derived from. So it's very likely to become
invalid when the game state changes; thus, Same Game's
\cw{changed_state()} function clears the current selection whenever
it is called.
When \cw{anim_length()} or \cw{flash_length()} are called, you can
be sure that there has been a previous call to \cw{changed_state()}.
So \cw{changed_state()} can set up data in the \c{game_ui} which will
be read by \cw{anim_length()} and \cw{flash_length()}, and those
functions will not have to worry about being called without the data
having been initialised.
\H{backend-moves} Making moves
This section describes the functions which actually make moves in
the game: that is, the functions which process user input and end up
producing new \c{game_state}s.
\S{backend-interpret-move} \cw{interpret_move()}
\c char *(*interpret_move)(const game_state *state, game_ui *ui,
\c const game_drawstate *ds,
\c int x, int y, int button);
This function receives user input and processes it. Its input
parameters are the current \c{game_state}, the current \c{game_ui}
and the current \c{game_drawstate}, plus details of the input event.
\c{button} is either an ASCII value or a special code (listed below)
indicating an arrow or function key or a mouse event; when
\c{button} is a mouse event, \c{x} and \c{y} contain the pixel
coordinates of the mouse pointer relative to the top left of the
puzzle's drawing area.
(The pointer to the \c{game_drawstate} is marked \c{const}, because
\c{interpret_move} should not write to it. The normal use of that
pointer will be to read the game's tile size parameter in order to
divide mouse coordinates by it.)
\cw{interpret_move()} may return in three different ways:
\b Returning \cw{NULL} indicates that no action whatsoever occurred
in response to the input event; the puzzle was not interested in it
at all.
\b Returning the empty string (\cw{""}) indicates that the input
event has resulted in a change being made to the \c{game_ui} which
will require a redraw of the game window, but that no actual
\e{move} was made (i.e. no new \c{game_state} needs to be created).
\b Returning anything else indicates that a move was made and that a
new \c{game_state} must be created. However, instead of actually
constructing a new \c{game_state} itself, this function is required
to return a string description of the details of the move. This
string will be passed to \cw{execute_move()}
(\k{backend-execute-move}) to actually create the new
\c{game_state}. (Encoding moves as strings in this way means that
the mid-end can keep the strings as well as the game states, and the
strings can be written to disk when saving the game and fed to
\cw{execute_move()} again on reloading.)
The return value from \cw{interpret_move()} is expected to be
dynamically allocated if and only if it is not either \cw{NULL}
\e{or} the empty string.
After this function is called, the back end is permitted to rely on
some subsequent operations happening in sequence:
\b \cw{execute_move()} will be called to convert this move
description into a new \c{game_state}
\b \cw{changed_state()} will be called with the new \c{game_state}.
This means that if \cw{interpret_move()} needs to do updates to the
\c{game_ui} which are easier to perform by referring to the new
\c{game_state}, it can safely leave them to be done in
\cw{changed_state()} and not worry about them failing to happen.
(Note, however, that \cw{execute_move()} may \e{also} be called in
other circumstances. It is only \cw{interpret_move()} which can rely
on a subsequent call to \cw{changed_state()}.)
The special key codes supported by this function are:
\dt \cw{LEFT_BUTTON}, \cw{MIDDLE_BUTTON}, \cw{RIGHT_BUTTON}
\dd Indicate that one of the mouse buttons was pressed down.
\dt \cw{LEFT_DRAG}, \cw{MIDDLE_DRAG}, \cw{RIGHT_DRAG}
\dd Indicate that the mouse was moved while one of the mouse buttons
was still down. The mid-end guarantees that when one of these events
is received, it will always have been preceded by a button-down
event (and possibly other drag events) for the same mouse button,
and no event involving another mouse button will have appeared in
between.
\dt \cw{LEFT_RELEASE}, \cw{MIDDLE_RELEASE}, \cw{RIGHT_RELEASE}
\dd Indicate that a mouse button was released. The mid-end
guarantees that when one of these events is received, it will always
have been preceded by a button-down event (and possibly some drag
events) for the same mouse button, and no event involving another
mouse button will have appeared in between.
\dt \cw{CURSOR_UP}, \cw{CURSOR_DOWN}, \cw{CURSOR_LEFT},
\cw{CURSOR_RIGHT}
\dd Indicate that an arrow key was pressed.
\dt \cw{CURSOR_SELECT}
\dd On platforms which have a prominent \q{select} button alongside
their cursor keys, indicates that that button was pressed.
In addition, there are some modifiers which can be bitwise-ORed into
the \c{button} parameter:
\dt \cw{MOD_CTRL}, \cw{MOD_SHFT}
\dd These indicate that the Control or Shift key was pressed
alongside the key. They only apply to the cursor keys, not to mouse
buttons or anything else.
\dt \cw{MOD_NUM_KEYPAD}
\dd This applies to some ASCII values, and indicates that the key
code was input via the numeric keypad rather than the main keyboard.
Some puzzles may wish to treat this differently (for example, a
puzzle might want to use the numeric keypad as an eight-way
directional pad), whereas others might not (a game involving numeric
input probably just wants to treat the numeric keypad as numbers).
\dt \cw{MOD_MASK}
\dd This mask is the bitwise OR of all the available modifiers; you
can bitwise-AND with \cw{~MOD_MASK} to strip all the modifiers off
any input value.
\S{backend-execute-move} \cw{execute_move()}
\c game_state *(*execute_move)(const game_state *state, char *move);
This function takes an input \c{game_state} and a move string as
output from \cw{interpret_move()}. It returns a newly allocated
\c{game_state} which contains the result of applying the specified
move to the input game state.
This function may return \cw{NULL} if it cannot parse the move
string (and this is definitely preferable to crashing or failing an
assertion, since one way this can happen is if loading a corrupt
save file). However, it must not return \cw{NULL} for any move
string that really was output from \cw{interpret_move()}: this is
punishable by assertion failure in the mid-end.
\S{backend-can-solve} \c{can_solve}
\c int can_solve;
This boolean field is set to \cw{TRUE} if the game's \cw{solve()}
function does something. If it's set to \cw{FALSE}, the game will
not even offer the \q{Solve} menu option.
\S{backend-solve} \cw{solve()}