-
Notifications
You must be signed in to change notification settings - Fork 0
/
devel.but
6210 lines (4641 loc) · 257 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 \cw{git} commit
\cw{a2212e82aa2f4b9a4ee22783d6fed2761c213432}. 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 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 N 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 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 MacOS 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; for handling application shutdown
and restart on platforms such as PalmOS where state is expected to be
saved; for storing the previous game in order to undo and redo across
a New Game event).
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} which constructs a complete list of those game structures
from a header file generated by CMake.
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 (other than the magnification level) 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, then you might
have found a data item that needs to go in \c{game_ui} instead.
Two quite different examples of this:
\b if the game provides an interface for making moves by moving a
cursor around the grid with the keyboard and pressing some other key
when you get to a square you want to change, then the location of that
cursor belongs in \c{game_ui}, because the player will want to undo
one \e{square change} at a time, not one \e{cursor movement} at a
time.
\b Mines tracks the number of times you opened a mine square and died.
Every time you do that, you can only continue the game by pressing
Undo. So the deaths counter belongs in \c{game_ui}, because otherwise,
it would revert to 0 every time you undid your mistaken move.
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}, but describing what
was drawn in the window on the most recent redraw. This is used to
identify the squares that need redrawing next time, by deciding what
the new value in that array should be, and comparing it to what was
drawn last time. See \k{writing-howto-redraw} for more on this
subject.
\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}.
There are various things that you might store in \c{game_ui}, which
are conceptually different from each other, but I haven't yet found a
need to split them out into smaller sub-structures for different
purposes:
\dt Transient UI state:
\dd Storing a piece of UI state in \c{game_state} means that you can
only update it by appending a move to the undo chain. Some UI state
shouldn't really be treated this way. For example, if your puzzle has
a keyboard-controlled cursor, you probably don't want every cursor
movement to be an undoable action, because the history of where the
cursor went just isn't interesting. More likely the cursor should just
move freely, and the only undoable actions are the ones where you
modify the element under the cursor. So you'd store the cursor
position in \c{game_ui} rather than \c{game_state}. See
\k{writing-keyboard-cursor} for more details.
\lcont{ Another example of this is the state of an ongoing mouse drag.
If there's an undoable action involved, it will probably occur when
the drag is released. In between, you still need to store state that
the redraw function will use to update the display \dash and that can
live in \c{game_ui}. See \k{writing-howto-dragging} for more details
of this. }
\dt Persistent UI state:
\dd An example of this is the counter of deaths in Mines or Inertia.
This shouldn't be reverted by pressing Undo, for the opposite reason
to the cursor position: the cursor position is too boring to store the
history of, but the deaths counter is too \e{important}!
\dt Information about recent changes to the game state:
\dd 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}.
\dt User preferences:
\dd Any user preference about display or UI handled by
\cw{get_prefs()} and \cw{set_prefs()} will need to live in
\c{game_ui}, because that's the structure that those functions access.
\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} and \c{htmlhelp_topic}
\c const char *winhelp_topic, *htmlhelp_topic;
These members are 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.
This code base still supports the legacy \cw{.HLP} Windows Help format
as well as the less old \cw{.CHM} HTML Help format. The two use
different methods of identifying topics, so you have to specify both.
Each chapter about a puzzle in \c{puzzles.but} is labelled with a
\e{help topic} name for Windows Help, which typically appears just
after the \cw{\\C} chapter title paragraph, similar to this:
\c \C{net} \i{Net}
\c
\c \cfg{winhelp-topic}{games.net}
But HTML Help is able to use the Halibut identifier for the chapter
itself, i.e. the keyword that appears in braces immediatey after the
\cw{\\C}.
So the corresponding game back end encodes the \c{winhelp-topic}
string (here \cq{games.net}) in the \c{winhelp_topic} element of the
game structure, and puts the chapter identifier (here \cq{net}) in the
\c{htmlhelp_topic} element. For example:
\c const struct game thegame = {
\c "Net", "games.net", "net",
\c // ...
\c };
\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 bool (*fetch_preset)(int i, char **name, game_params **params);
This function is one of the two APIs a back end can provide 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.
If the game wants to return presets in the form of a hierarchical menu
instead of a flat list (and, indeed, even if it doesn't), then it may
set this function pointer to \cw{NULL}, and instead fill in the
alternative function pointer \cw{preset_menu}
(\k{backend-preset-menu}).
\S{backend-preset-menu} \cw{preset_menu()}
\c struct preset_menu *(*preset_menu)(void);
This function is the more flexible of the two APIs by which a back end
can define a collection of preset game parameters.
This function simply returns a complete menu hierarchy, in the form of
a \c{struct preset_menu} (see \k{midend-get-presets}) and further
submenus (if it wishes) dangling off it. There are utility functions
described in \k{utils-presets} to make it easy for the back end to
construct this menu.
If the game has no need to return a hierarchy of menus, it may instead
opt to implement the \cw{fetch_preset()} function (see
\k{backend-fetch-preset}).
The game need not fill in the \c{id} fields in the preset menu
structures. The mid-end will do that after it receives the structure
from the game, and before passing it on to the front end.
\S{backend-encode-params} \cw{encode_params()}
\c char *(*encode_params)(const game_params *params, bool full);
The job of this function is to take a \c{game_params}, and encode it
in a printable ASCII 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, most 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 bool can_configure;
This 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 used by
this function:
\c const char *name;
\c int type;
\c union { /* type-specific fields */ } u;
\e iiiiiiiiiiiiiiiiiiiiiiiiii
\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 usable member of the
union field \c{u} depends on \c{type}. The valid type 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.)
\lcont{
For controls of this type, \c{u.string} contains a single field
\c char *sval;
which stores a dynamically allocated string representing the contents
of the input box.
}
\dt \c{C_BOOLEAN}
\dd Describes a simple checkbox.
\lcont{
For controls of this type, \c{u.boolean} contains a single field
\c bool bval;
}
\dt \c{C_CHOICES}
\dd Describes a drop-down list presenting one of a small number of
fixed choices.
\lcont{
For controls of this type, \c{u.choices} contains two fields:
\c const char *choicenames;
\c int selected;
\c{choicenames} 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{selected} 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}).
Note that \c{u.choices.choicenames} is \e{not} dynamically allocated,
unlike \c{u.string.sval}.
}
\dt \c{C_END}
\dd Marks the end of the array of \c{config_item}s. There is no
associated member of the union field \c{u} for this type.
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 can be \cw{NULL}.
\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 can be \cw{NULL}.
\S{backend-get-prefs} \cw{get_prefs()}
\c config_item *(*get_prefs)(game_ui *ui);
This function works very like \cw{configure()}, but instead of
receiving a \c{game_params} and returning GUI elements describing the
data in it, this function receives a \c{game_ui} and returns GUI
elements describing any user preferences stored in that.
This function should only deal with fields of \c{game_ui} that are
user-settable preferences. In-game state like cursor position and
mouse drags, or per-game state like death counters, are nothing to do
with this function.
If there are no user preferences, you can set both this function
pointer and \c{set_prefs} to \cw{NULL}.
If you implement these functions, you must also ensure that your
game's \cw{new_ui()} function can be called with a null \c{game_state}
pointer. (See \k{backend-new-ui}.)
In every \c{config_item} returned from this function, you must set an
additional field beyond the ones described in \k{backend-configure}:
\c const char *kw;
This should be an identifying keyword for the user preference in
question, suitable for use in configuration files. That means it
should remain stable, even if the user-facing wording in the \c{name}
field is reworded for clarity. If it doesn't stay stable, old
configuration files will not be read correctly.
For \c{config_item}s of type \cw{C_CHOICES}, you must also set an
extra field in \c{u.choices}:
\c const char *choicekws;
This has the same structure as the \c{choicenames} field (a list of
values delimited by the first character in the whole string), and it
provides an identifying keyword for each individual choice in the
list, in the same order as the entries of \c{choicenames}.
\S{backend-set-prefs} \cw{set_prefs()}
\c void (*set_prefs)(game_ui *ui, const config_item *cfg);
This function is the counterpart to \cw{set_prefs()}, as
\cw{custom_params()} is to \cw{configure()}. It receives an array of
\c{config_item}s which was originally created by \cw{get_prefs()},
with the controls' values updated from user input, and it should
transcribe the new settings into the provided \c{game_ui}.
If there are no user preferences, you can set both this function
pointer and \c{get_prefs} to \cw{NULL}.
\S{backend-validate-params} \cw{validate_params()}
\c const char *(*validate_params)(const game_params *params,
\c bool 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, bool 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 printable ASCII 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 const char *(*validate_desc)(const game_params *params,
\c 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.
Usually, this function 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.
However, if the puzzle defines \c{get_prefs()} and \c{set_prefs()}
functions, then this function may also be called with
\cw{state==NULL}. In this situation it must still allocate a
\c{game_ui} which can be used by \c{get_prefs()} and \c{set_prefs()},
although it need not be usable for actually playing a 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 printable ASCII 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.)
The \cw{encode_ui()} function is optional. If a back-end doesn't need
this function it can just set the pointer to \cw{NULL}.
\S{backend-decode-ui} \cw{decode_ui()}
\c void (*decode_ui)(game_ui *ui, const char *encoding,
\c const game_state *state);
This function parses a string previously output by \cw{encode_ui()},
and writes the decoded data back into the freshly-created \c{game_ui}
structure provided. If the string is invalid, the function should do
the best it can, which might just mean not changing the \c{game_ui}
structure at all. This might happen if a save file is corrupted, or
simply from a newer version that encodes more \c{game_ui} data. The
current \c{game_state} is provided in case the function needs to
refer to it for validation.
Like \cw{encode_ui()}, \cw{decode_ui()} is optional. If a back-end
doesn't need this function it can just set the pointer to \cw{NULL}.
\S{backend-changed-state} \cw{changed_state()}
\c void (*changed_state)(game_ui *ui, const game_state *oldstate,