File: hacking.texi

package info (click to toggle)
xconq 7.1.0-7
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 7,056 kB
  • ctags: 7,960
  • sloc: ansic: 88,493; perl: 2,057; sh: 1,766; makefile: 1,110; csh: 81; awk: 47; lisp: 39
file content (1316 lines) | stat: -rw-r--r-- 51,091 bytes parent folder | download
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
@node Hacking Xconq, , Reference Manual, Top

@chapter Hacking Xconq

Although @i{Xconq} and its GDL have considerable power and flexibility
already built in,
you may decide that you want to modify the @i{Xconq} program itself.
You should know what you are doing;
@i{Xconq} is designed to be modifiable, but it is not simple code.
In the past, people have found it easy to make changes,
but much harder to make them correctly!

@i{Xconq} is designed to be portable to different types of user interfaces.
It is based on a kernel-interface architecture, where the semantics of
the game, as documented in the preceding chapters, is part of the kernel,
while the main program and player interaction are specific to each system.

@i{Xconq} is also designed to allow the addition of new AIs.  The default
@code{"mplayer"} AI, while it is flexible and will attempt to play any side
in any game, does not have the depth that is often important to success
in a game.  Its position is that of a generic AI program that can learn to
play any game, given only the rules; while such a program might figure out
how to win at tic-tac-toe or checkers, it is not going to be particularly
good at the subtleties of go or chess.

The @i{Xconq} GDL is also extensible.  This is useful when the basic GDL
does not provide some feature that is essential to a game.

@menu
* Kernel::                      
* Interface::
* Networking::                  
* Miscellany::                  
@end menu

@node Kernel, Interface, Hacking Xconq, Hacking Xconq
 
@section Kernel

The kernel is the part of @i{Xconq} shared by all interfaces.
It does no I/O except to files or for debugging.

Specifically, the kernel supplies the following functionality:
@itemize
@item
Data structure initialization. (@code{init_data_structures})

@item
Game module loading and interpretation. (@code{load_game_module})

@item
Initial player/side setup. (@code{make_trial_assignments})

@item
Synthesis methods. (@code{run_synthesis_methods})

@item
Final player/side setup. (@code{make_assignments})

@item
Game execution. (@code{run_game})

@item
Implementations of unit actions. (@code{prep_*_action})

@item
AI players.

@item
Help Info (@code{get_help_text})

@item
Game saving and scorekeeping.
@end itemize

@menu
* Configuration Options::       
* Porting the Kernel::          
* Writing New Synthesis Methods::  
* Writing New Namers::          
* Writing New AIs::             
* Extending GDL::               
@end menu

@node Configuration Options, Porting the Kernel, Kernel, Kernel

@subsection Configuration Options

There are a small number of options available to alter aspects of
the kernel.  These are defined in @code{kernel/config.h}.

[eventually describe all of them?]

@node Porting the Kernel, Writing New Synthesis Methods, Configuration Options, Kernel

@subsection Porting the Kernel

The kernel should be restricted to ANSI C, and should avoid or optionalize
features not in ``traditional'' C, such like prototypes.
Although the kernel uses stdio,
it does not assume the presence of a console (stdin, stdout, stderr).
For instance, a graphical interface can arrange to disable stdin entirely
and direct stdout/stderr into a file (see the Mac interface sources
for an example).

You should be careful about memory consumption.  In general, the kernel
takes the attitude that if it was worth allocating, it's worth hanging
onto; and so the program does not free much storage.  Also, nearly all
of the allocation happens during startup.  Since a game may run for a
very long time (thousands of turns perhaps), it is important not to
run the risk of exhausting memory at a climactic moment in the game!

Also, the kernel should not exit on its own.  The only permissible
times are when the internal state is so damaged that interface
error-handling routines (see below) cannot be called safely.
Such situations are rare.  If you add something to the kernel
and need to handle error situations, then you should call one
of the interface's error-handling routines.
There are distinct routines for problems during initializations
vs problems while running, and both error and warning routines.
Warning routines may return, so kernel code should be prepared
to continue on, while error routines will never return.

@node Writing New Synthesis Methods, Writing New Namers, Porting the Kernel, Kernel

@subsection Writing New Synthesis Methods

You can add new synthesis methods to @i{Xconq}.
This may be necessary if an external program
does not exist, is unsuitable, or the external program
interface is not available.
Synthesis methods should start out by testing whether or not to run,
and should never assume that any other method has been run before or
after, nor that any particular game module has been loaded.
However, ``tricks'' are usually OK, such as setting a particular global
variable in a particular module only, then having the synthesis method
test whether that global is set.
See the file @code{init.c} for further details.

Synthesis methods that take longer than a second or two to execute
should generate percent-done info for the interface to use,
via the function @code{announce_progress}.
Be aware that most methods will be O(n) or O(n*n) on the
size of the world or the number of units,
so they can take much longer to set up
a large game than a small one.
Players will often go overboard and start up giant games,
so this happens frequently.
Also, @i{Xconq} may be running on a much smaller and slower
machine than what you're using now.

@node Writing New Namers, Writing New AIs, Writing New Synthesis Methods, Kernel

@subsection Writing New Namers

[describe hook and interface]

@node Writing New AIs, Extending GDL, Writing New Namers, Kernel

@subsection Writing New AIs

You can add new types of AIs to @i{Xconq}.
You would do this to add different strategies as well as
to add AIs that are programmed specifically for a single game or
class of games.  (This is useful because the generic AI does not
always understand the appropriate strategy for each game.)

You have to design the object that is the AI's ``mental state''.
If your AI need only react to the immediate situation, then this
object can be very simple, but in general you will need to design
a fairly elaborate structure with a number of substructures.
Since there may be several AIs in a single game, you should be
careful about using globals, and since @i{Xconq} games may often
run for a long time, you should be careful not to consume memory
recklessly.

@itemize
@item
Name.
This is a string, such as @code{"mplayer"}.
It may be displayed to players, so it should not be too cryptic.

@item
Validity function.
This runs after modules are loaded, and during player/side
setup, and decides whether it can be in the given game on the given side.
[have a chain of fallback AIs, or blow off the game?]

@item
Game init function.  This runs before displays are set up, just in case
a display needs to examine the AI's data (for instance to display whether
the AI is friendly or unfriendly).

The game init function should also look for and interpret the contents
of the side's @code{aidata}, if appropriate.  The generic game reading code
fills the slot, but does not interpret the data further.

@item
Turn init function.  This runs after all the units get their acp and mp
for the turn, but before anybody actually gets to move.

@item
Unit order function.  This gets run to decide what the unit should do.
Usually it should be allowed to follow its plan.
[do separate fns for before and after plan execution?]

@item
Event reaction functions. [how many?]

@item
State save function.  This formats state that should be saved into
a Lisp object.  The game saving code then writes this state into
the file so that it can be read in again.  You may not do any
allocation while saving a game however, so if you need space (and
note that even a single cons allocates space), you must have the AI
init routine or some such do the allocation early on, then reuse
the space.

@end itemize

Note that these functions have very few constraints, so you can write them
to work together in various ways.  For instance, an AI can decide whether
to resign once/turn, once/action, or once for each 4 units it moves, every
other turn.

[describe default AI as illustrative example]

@node Extending GDL, , Writing New AIs, Kernel

@subsection Extending GDL

GDL has been designed so as to be relatively easily extensible.
I say ``relatively'' because although it is quite easy to define a new
keyword or table, it is not always so easy to integrate the implementation
code into the kernel correctly.

Instead of actually changing GDL, you can experiment with an addition
by using the @code{extensions} property of unit, material, and terrain types.
In the code, you call @code{get_u_extension}, pass it the type, name
of the property, and a default to return if the value was not given.
In the game definition, the designer would say
@code{(unit town (extensions (my-ext xxx)))}.

[show examples for global, property, table, event, task]

The file @code{gvar.def} defines all the global variables.

The file @code{utype.def} defines all the unit type properties.

From time to time, it may be worthwhile to extend unit objects.
This should be rare, because games may have thousands of units,
and each unit requires at least 100 bytes of storage already,
so you should avoid making them any larger.
Properties of an individual unit are scattered through @code{keyword.def}.
Once the structure slot is added, you just need to add reading and
writing of the value, using the @code{K_@var{xxx}} enum that was
defined with the keyword.  You should attempt to make a reasonable
default and use it to avoid writing out the value, so as to save
time when @i{Xconq} reads a game in.

GDL symbols beginning with @code{zz-} should be reserved for the use
of AI code.  You may want to add some of these, either to serve as a
convenient place for AIs to cache the results of their analyis of a
game, or else as a way for game designers to add ``hints'' for AIs
that know to look at them.

Note that all the @samp{*.def} files together are to define the exact set
of symbols defined by GDL.  You should not add any expedient matching
on symbols or searching for particular symbols without adding them to
an appropriate @samp{.def} file.

@node Interface, Networking, Kernel, Hacking Xconq

@section Interface

The player interface is how actual players interact with the game.
It need not be graphical or even particularly interactive,
in fact it could even be a network server-style interface!
However, this section will concentrate on the construction
of interactive graphical interfaces.

@menu
* Interface Architecture::
* Main Program::                
* Startup Options::             
* Progress Indication::         
* Feedback and Control::        
* Play Commands::                    
* Error Handling::              
* Textual Displays::            
* Display Update::              
* Types of Windows and Panels::  
* Imaging::                     
* Animation::                   
* Game Designer Tools::         
* Porting and Multiple Interfaces::  
* Useful Displays::             
* Useful Options::              
* Debugging Aids::              
* Guidelines and Suggestions::  
@end menu

@node Interface Architecture, Main Program, Interface, Interface

@subsection Interface Architecture

An interface is always compiled in, so it has complete access to the
game state.  However, if your version of @i{Xconq} has any networking
support, the interface should not modify kernel structures directly,
but should instead use kernel routines.  The kernel routines will
forward any state modifications to all other programs participating
in a game, so that everybody's state remains consistent.

A working interface must provide some level of capability in each
of these areas:

@itemize
@item
Main program.
The interface includes the main application and any
system-specific infrastructure, such as event handling.

@item
Interpretation of startup options.
This includes choice of games, variants, and players.

@item
Display of game state.
This includes both textual and graphical displays,
both static and dynamic.

@item
Commands/gestures for unit tasks and actions,
and for general state modifications.

@item
Display update in response to state changes.

@item
Realtime progress.
Some game designs require the interface
to support realtime.

@item
Error handling.
@end itemize

The file @code{skelconq.c} in the @code{kernel} directory is
a good example of a minimum working interface.

Don't let interfaces ever set kernel object values directly, always
go through calls that can be ``siphoned'' for networking.

@node Main Program, Startup Options, Interface Architecture, Interface

@subsection Main Program

The interface provides @code{main()} for @i{Xconq};
this allows maximum flexibility in adapting to different environments.
In a sense, the kernel is a large library that the
interface calls to do game-related operations.

There is a standard set of calls that need to be made during
initialization.  The set changes from time to time, so the
following extract from @file{skelconq} should not be taken as
definitive:
@example
    init_library_path(NULL);
    clear_game_modules();
    init_data_structures();
    parse_command_line(argc, argv, general_options);
    load_all_modules();
    check_game_validity();
    parse_command_line(argc, argv, variant_options);
    set_variants_from_options();
    parse_command_line(argc, argv, player_options);
    set_players_from_options();
    parse_command_line(argc, argv, leftover_options);
    make_trial_assignments();
    calculate_globals();
    run_synth_methods();
    final_init();
    assign_players_to_sides();
    init_displays();
    init_signal_handlers();
    run_game(0);
@end example
Note that this sequence is only straight-through for a simple command
line option program; if you have one or more game setup dialogs, then
you choose which to call based on how the players have progressed
through the dialogs.  The decision points more-or-less correspond to
the different @code{parse_command_line} calls in the example.
You may also need to interleave some interface-specific calls;
for instance, if you want to display side emblems in a player/side
selection dialog, then you will need to arrange for the emblem images
to be loaded and displayable, rather than doing it as part of opening
displays.

Once a game is underway, the interface is basically self-contained,
needing only to call @code{run_game} periodically to keep the
game moving along.  @code{run_game} takes one argument which can
be -1, 0, or 1.  If 1, then one unit gets to do one action, then
the routine returns.  If 0, the calculations are gone through, but
no units can act.  If -1, then all possible units will move before
@code{run_game} returns.  This last case is not recommended for interactive
programs, since moving all units in a large game may take a very long
time; several minutes sometimes, and @code{run_game} may not necessarily
call back to the interface very often.

@node Startup Options, Progress Indication, Main Program, Interface

@subsection Startup Options

Although there are many different ways to get a game started,
you have three main categories of functionality to support:
1) selection of the game to play, 2) setting of variants, and
3) selection of players.  For command-line-using programs,
the file @code{cmdline.c} need only be linked in to provide
all of this functionality.  For graphical interfaces, you will
need to design appropriate dialogs.  This can be a lot of work,
exacerbated by the fact that these dialogs will be the first
things that new @i{Xconq} players see, and will therefore shape
their opinions about the quality of the interface and of the game.

[more detail about what has to be in dialogs?]

Interface code should check all player specs, not proceed with initialization
until these are all valid.

Both standard and nonstandard variants should vanish from or be grayed out
in dialog boxes if irrelevant to a selected game.

@node Progress Indication, Feedback and Control, Startup Options, Interface

@subsection Progress Indication

Some synthesis methods are very slow, and become even
slower when creating large games, so the kernel will announce a slow process,
provide regular updates, and signal when the process is done.  The interface
should display this in some useful way.  In general, progress should always
be displayed, although one could postpone displaying anything until after
the first progress update, calculate an estimated time to completion, and
not display anything if that estimate is for less than a few seconds.
However, this is probably unnecessary.

@itemize
@item
@code{void announce_read_progress()}

The kernel calls this regularly while reading game definitions.
Interfaces running on slow machines should use this to indicate that
everything is still working; for instance, the Mac interface animates
a special cursor that indicates reading is taking place.

@item
@code{void announce_lengthy_process(char *msg)}

The kernel calls this at the beginning of each synthesis.  The argument
is a readable string that the interface can show to players.

@item
@code{void announce_progress(int pctdone)}

The kernel may call this at milestones within a synthesis.
The number ranges from 0 to 100.

@item
@code{void finish_lengthy_process()}

The kernel calls this at the end of a synthesis.

@end itemize

@node Feedback and Control, Play Commands, Progress Indication, Interface

@subsection Feedback and Control

The interface should provide visible feedback for every successful unit
action initiated directly by the player, but it need not do so for failures,
unless they are serious.  It is better to prevent nonsensical input,
for instance by disabling menus and control panel items.  Simple interfaces
such as for character terminals will have to relax these rules somewhat.

Interfaces should enable/disable display of lighting conditions.

@node Play Commands, Error Handling, Feedback and Control, Interface

@subsection Play Commands

There is no single correct way to support direct player control over units.
Although keyboard commands and mouse clicks are obvious choices,
it would be very cool to allow a pen or mouse to sketch a movement plan,
or to be able to give verbal orders...

There is a common set of ASCII keyboard commands that are recommended
for all @i{Xconq} interfaces that use a keyboard.
These are defined in @code{kernel/cmd.def}.
If you use these, @i{Xconq} players will be able to switch platforms
and still use familiar commands.  @code{cmd.def} defines a single character,
a command name, a help string, and a function name,
always in the form @code{do_*}.
However, @code{cmd.def} does not specify arguments, return types,
or behavior of those functions, so each interface must still define
its own command lookup and calling conventions.

If you include @code{cmd.def}, you must then provide definitions for
all the functions that it mentions.  You should also provide some sort
of feedback for commands that are not implemented, or that are not
useful.  Players who are used to another interface will expect to be
able to type the same commands, and can get very confused if the
familiar commands neither work nor complain about not working.
One way to fill in defaults for functions that you don't want to do yet
is to use macros ahead of the inclusion of @code{cmd.def}:
@example
#define do_quit default_empty_do
#define do_save default_empty_do
...

#include "cmd.def"

default_empty_do()
@{
	notify(a_side, "Command not implemented in this interface");
@}
@end example

Prefixed number args should almost always be repetitions.

If already fully fueled, refuel commands should come back immediately.

A quit cmd can always take a player out of the game, but player may have
to agree to resign.  Player can also declare willingness to quit or draw
without actually doing so, then resolution requires that everybody agree.
If quitting but others continuing on, also have option of being a
spectator.  Could have notion of "leaving game without declaring entire
game a draw" for some players.
Allow for a timeout and default vote in case some voters have disappeared
mysteriously.
Must never force a player to stay in.
Add a notion of login/logout so a side can be inactive but untouchable,
possibly freezes entire game if a side is inactive.
1. if one player or no scoring
	confirm, then shut player down
	if one player, then shut game down
2. if side is considered a sure win (how to tell? is effectively a win
condition then) or all sides willing to draw
	confirm, take side out, declare a draw, shut player down
3. if all sides willing to quit
	take entire game down
4. ask about resigning - if yes,
	resign, close display, keep game running
   if no, ask if willing to quit and/or draw, send msg to other sides
Kernel support limited to must_resign_to_quit(side), similar tests.

@node Error Handling, Textual Displays, Play Commands, Interface

@subsection Error Handling

The interface must provide implementations of these error-handling
functions:

@itemize
@item
@code{void low_init_warning(str)}

This is for undesirable but not necessarily
wrong things that happen while setting up a game.  For instance,
if players start out too close or too far from each other, it will
often affect the play of the game adversely, so the kernel issues
a warning, therby giving the prospective players a chance to cancel
the game and start over.  The kernel's warning message should
indicate any likely results of continuing on, so the players can
decide whether or not to chance it.

@item
@code{low_init_error(str)}

This function should indicate a serious and unrecoverable error
during initialization.  It should not return to its caller.

@item
@code{low_run_warning(str)}

Warnings during the game are rare but not unknown.
They are very often due to bugs in @code{Xconq}, so any
occurrence should be investigated further.  It is possible
for some game designs to have latent flaws that may result
in a warning.
In any case, the interface should allow the players to continue
on, to save their game and quit, by calling @code{save_the_game},
or else quit without saving anything.

@item
@code{low_run_error(str)}

In the worst case, @i{Xconq} can get into a situation, such as
memory exhaustion, where there is no way to continue.  The kernel
will then call @code{run_error}, which should inform players that
@i{Xconq} must shut itself down.  They do get the option of saving
the game, and the routine should call @code{save_game_state??} to
do this safely.  This routine should also not return to its caller.

@item
@code{printlisp(obj)}

This is needed to print GDL objects to ``stdout'' or its equivalent.

@end itemize

@node Textual Displays, Display Update, Error Handling, Interface

@subsection Textual Displays

Text can take a long time to read, and can be difficult to provide
in multiple human languages. (What, you thought only English speakers
played @i{Xconq}?  Think again!)
Therefore, text displays in the interfaces should be as minimal as
possible, and derive from strings supplied in the game design,
since they can be altered without rebuilding the entire program.

(@i{Xconq} is not, at the moment, completely localizable,
but that is a design goal.)

@node Display Update, Types of Windows and Panels, Textual Displays, Interface

@subsection Display Update

Usually the interface's display is controlled by the player,
but when @code{run_game} is executing, it will frequently change
the state of an object in a way that needs to be reflected in the
display immediately.  Examples include units leaving or entering
a cell, sides losing or winning, and so forth.  The interface
must define a set of callbacks that will be invoked by the kernel.

@itemize
@item
@code{update_cell_display(side, x, y, rightnow)}

[introduce area (radius or rect) update routines?]

@item
@code{update_side_display(side, side2, rightnow)}

@item
@code{update_unit_display(side, unit, rightnow)}

@item
@code{update_unit_acp_display(side, unit, rightnow)}

@item
@code{update_turn_display(side, rightnow)}

@item
@code{update_action_display(side, rightnow)}

@item
@code{update_action_result_display(side, unit, rslt, rightnow)}

@item
@code{update_fire_at_display(side, unit, unit2, m, rightnow)}

@item
@code{update_fire_at_display(side, unit, x, y, z, m, rightnow)}

@item
@code{update_event_display(side, hevt, rightnow)}

@item
@code{update_all_progress_displays(str, s)}

@item
@code{update_clock_display(side, rightnow)}

@item
@code{update_message_display(side, sender, str, rightnow)}

@item
@code{update_everything()}

@end itemize

Each of these routines has a flag indicating whether the change may be
buffered or not.
To ensure that buffered data is actually onscreen,
the kernel may call @code{flush_display_buffers()},
which the interface must define.

@itemize
@item
@code{flush_display_buffers()}

@end itemize

These may or may not be called on reasonable sides, so the
interface should always check first that @code{side} actually
exists and has an active display.
[If side has a "remote" display, then interface has to forward??
No, because remote copy of game is synchronized and does own
update_xxx calls more-or-less simultaneously]

Note that this is as much as the kernel interests itself in displays.
Map, list, etc drawing and redrawing are under the direct control
of the interface code.

Unix-hosted versions must provide @code{void close_displays()}
for signal handlers to call.

@node Types of Windows and Panels, Imaging, Display Update, Interface

@subsection Types of Windows and Panels

@i{Xconq} is best with a window-style interface, either tiled
or overlapping.  Overlapping is more flexible, but also more
complicated for players.
In the following discussion, "window" will refer to a logically
unified part of the display,
which can be either a distinct window or merely a panel
embedded in some larger window.

The centerpiece window should be a map display.
This will be the most-used window,
since it will typically display more useful information
than any other window.
This means that it must also exhibit very good performance.

When a game starts up, the map display should be centered
on one of the player's units, preferably one close to the
center of all the player's units.

Another recommended window is a list of all the sides and where
they stand in both the current turn and in the game as a whole.
Each side's entry should include its name, a progress bar or
other doneness indicator, and room for all the scores and scorekeepers
that apply to that side.

If possible, you should also implement
some kind of "face" or group of faces/expressions for a side,
so get a barbarian's face to repn a side instead of generic.
Could have interface generate remarks/balloons if face clicked on,
perhaps a reason for feelings, slogan, citation of agreement or broken
agreement, etc.
Need 5 faces for hostile, unfavorable, neutral, favorable, friendly/trusting.

Overall status of side rules:

all grayed: out of game

grayed and x-ed out: lost

???: won

Progress bar rules:

missing: no units or no ai/no display

grayed frame: no acting units

empty solid frame: all acted

part full, black: partly acted

part full, gray: finished turn

@node Imaging, Animation, Types of Windows and Panels, Interface

@subsection Imaging

Imaging is the process of drawing pictorial representations.
Not every interface needs it. For instance the curses interface
is limited to drawing two ASCII characters for each cell,
and its imaging code just has to choose which two to draw.
However, full-color bitmapped displays need more attention
to the process of getting an image onscreen.

No graphical icon should be drawn smaller than about 8x8, unless it's
a text character drawn in two contrasting colors.

Interfaces should cache optimal displays for each mag, not search
for best image each time.

Could allow 1-n "display variants" for all images, and for each orientation of
border and connection.

Imaging variations can be randomly selected by UI,
but must be maintained so redraws are consistent.

Allow the 64 bord/conn combos as single images, also advantage
that all will be drawn at once.

Draw partial cells around edges of a window, to indicate that the world
continues on in that direction.

Interface needs to draw only the terrain (but including connections and
borders) in edge cells.

Could draw grid by blitting large light pattern over world, do by inverting
so is easy to turn on/off.  Do grids by changing hex size only in
unpatterned color?

Draw large hexagon or rect in unseen-color after clearing window to bg
stipple (if unseen-color different).  Polygon should be inside area
covered by edge hexes, so unseen area more obvious.
Make large unseen-pattern that includes question marks?

If picture not defined for a game, use some sort of nondescript image
instead of leaving blank. (small "no picture available" for instance,
like in yearbooks)

To display night, could invert everything (b/w) or do 25/50% black (color)
(let game set, so some games could be all-black at night, nothing visible)
(have day/night coverage for each utype?)
World is totally lit if dimensions < half of world circumference and all
six corners of hexagon have same lighting.  If world totally dark, can draw
darkening mask once for entire map.

To display elevation, use deep blue -> light gray -> dark brown progression,
maybe also contour lines?
To draw contour lines, for each hex, look at each adj hex.  If on other
side of contour's elev, compute interpolated point (in pixels) and save
or draw a line to (one or both of the two) adj hex borders if they also
have the contour line pass through.  Guaranteed that line is part of
overall contour line.  Cheaper approach doesn't interpolate, just draws
to midpoint of hex border (probably OK for small mags).
Could maybe save contour lines once calculated (at each mag, lots of mem).

If multiple connection or border types, the interface should draw them offset
slightly from each other.

@node Animation, Game Designer Tools, Imaging, Interface

@subsection Animation

In addition to basic imaging, you can also support requests
for the playing of animations or @i{movies}.

The kernel just calls @code{schedule_movie} to create one,
and then @code{play_movies} when it is time to run all the
movies that have been scheduled.  It is up to the interface
to do something useful.  Note that the kernel is not aware
of the movies' timing, so it is better not to call @code{run_game}
until all the movies have finished playing.  (Yes, this would
be a good future enhancement!)

@itemize

@item
@code{schedule_movie(side, movie_type, args...)}

@item
@code{play_movies(sidemask)}

Run all of the animations, sounds, etc that were scheduled
previously, for the sides enabled in the side mask.
It is allowable for the interface not to act on any user input
while these are playing.

@end itemize

Several types of movies are predefined, so your interface can
recognize them specially.  These include @code{movie_miss},
@code{movie_hit}, @code{movie_death}, which are scheduled
for the appropriate outcomes of combat.

@node Game Designer Tools, Porting and Multiple Interfaces, Animation, Interface

@subsection Game Designer Tools

An interface is not required to provide any sort of online
designing tools, or even to provide a way to enable the
special design privileges.  Nevertheless, minimal tools
can be very helpful, and you will often find that they are
helpful in debugging the rest of the interface, since you
can use them to construct test cases at any time.

A basic set of design tools should include a way to enable
and disable designing for at least one side, a command to
create units of a given type, and some sort of tool to set
the terrain type at a given location.  A full set would
include ``painting'' tools for all area layers, including
geographical features, materials, weather, side views,
and so forth - about a dozen in all.

A least one level of undo for designer actions is very
desirable, although it may be hard to implement.
A useful rule for layers is to save a layer's previous
state at the beginning of each painting or other modification
action, when the mouse button first goes down.

The designer will often want to save only the part of the game
being worked on, for instance only the units or only the terrain.
The "save game" action should give designers a choice about
what to save.  For units particularly, the designer should be
able to save only some properties of units.  The most basic
properties are type, location, side, and name/number.
The unit id should not be saved by default, but should have
its own option (not clear why).

Note that because game modules are textual and can be
moved easily from one system to another, it is entirely
possible to use one @i{Xconq} (perhaps on a Mac) to design
games to be played on a Unix box under X11, or vice versa.
Transferring the imagery is more difficult, although there
is some support for the process.

@node Porting and Multiple Interfaces, Useful Displays , Game Designer Tools, Interface

@subsection Porting and Multiple Interfaces

In theory, it is possible to compile multiple interfaces
into a single @i{Xconq} program, but this would be hard at best.
They would have to be multiplexed appropriately and not
conflict anywhere in the address space.
Sometimes this is intrinsically impossible;
how could you compile the Mac and X interfaces into the same
program, and would the result be a Mac application, a Unix program,
or what?

@node Useful Displays, Useful Options, Porting and Multiple Interfaces, Interface

@subsection Useful Displays

This is a collection of minor but useful displays that might be worth
adding to an interface.

A ``mouse over'' is a line or two of text that describes what the
mouse/pointer is currently pointing at, and which updates automatically
as the player moves the pointer around.  This is better for high-bandwidth
interfaces, since there may be a lot of updating involved.  The volume
can be reduced slightly by only redisplaying when the mouse moves, or,
better, when what is being looked at changes.  This is probably best done
by recalculating the line of text and then comparing it to what has been
drawn already, although if the display is very fast, you may not save much
in drawing time.  One approx 40-char lines covers basic info, such as
terrain type and unit type; more detail may require multiple long lines.

@node Useful Options, Debugging Aids, Useful Displays, Interface

@subsection Useful Options

A ``follow action'' option scrolls the screen to where the last event
happened, such as combat. [etc]

@node Debugging Aids, Guidelines and Suggestions, Useful Options, Interface

@subsection Debugging Aids

@i{Xconq} is complicated enough that you can't expect to throw together
a complete working interface over the weekend.
Therefore, you should build some debugging aids into the interface.
You can ifdef with the flag @code{DEBUGGING} so as to ensure the code
won't be in final versions.

Display unit id if closeups, toplines, etc, if debugging is on.

@node Guidelines and Suggestions,  , Debugging Aids, Interface

@subsection Guidelines and Suggestions

Although as the interface builder, you are free to make it work in any
way you like, there are a number of basic things you should do.
Some of these are general user interface principles, others are specific
to @i{Xconq}, usually based on experiences with the existing interfaces.
Applying some of these guidelines will require judicious balancing between
consistency with the different version of @i{Xconq} and consistency with
the system you're porting to.

[following items should be better organized, moved in with relevant sections]

Draw single selected unit in a stack larger.

Draw single selected occupant in UR corner next to transport, when at
mags that show both transport and occs.

There should always be some sort of "what's happening now" display
so player doesn't wonder about apparently dead machine.

Image tool should report which type of resource is generating a
given image, so can find which to hack on (report for selected image only).

Interfaces should ensure stability of display choices
if random possibilities, so need to cache local decisions about
appearance of units if multiple images to choose from, choice of
text messages, etc.

Rules of Interaction:
1. Player can get to any unit in any mode.
2. Any player can prevent a turn from completing(/progressing?),
   unless a hard real limit is encountered.
3. All players see each others' general move/activity state, modes, etc.
4. Players can "nudge" each other.
5. Real time limits can be set for sides, turns, and games, both by players
   and by scenarios.

Player should be able to click on a desired unit or image, and effectively
say "take this", either grabs directly or else composes a task to approach
and capture.

Unit closeups should be laid out individually for each type, too much
variability to make a single format reasonable.

Add option where game design can specify use or avoidance of masks
with unit icons.

Player could escape a loss by saving a game, then discarding save.
Mplayers could register suspicion when player saves then quits -
"You're not trying to cheat, are you?" - but can't prevent this.

All interfaces should be able to bring up an "Instructions" window
that informs player(s) about the current game, includes xrefs to all
game design info.  Restrict help to generic and interface info only.

Graph display should graphing of various useful values, such as amounts
of units and materials over time, attitudes of sides, combat, etc.
Maximal is timeline for all sides and units, usually too elaborate but
allow tracking movement for some "important" units.  Note that move
actions may be recorded anyway.

Make specialized dialog for agreements, put name on top, then scrolling list of
terms, then signers, then random bits (public/secret, etc).  Use for proposals
also, so allow for "tentative" signers, desired signers who have not looked at
agreement.  Be able to display truth of each term, but need test to know when
a side can know the truth of a term?

Interfaces should have a ``wake up dummy'' button that can be used by players
who have finished their turn, to prod other players not yet done.

Commands that are irrelevant for a game ought to be grayed out in
help displays, and error messages should identify as completely invalid
(or just not do anything, a la grayed Mac menu shortcuts).

Should be able to drag out a route and have unit follow it (user input
of a complete task sequence).

Hack formatting so that variable-width fonts usually work reasonably.

Add xref buttons to various windows to go to other relevant windows and
focus in.

The current turn or date should be displayed prominently and be visible
somewhere by default.

Add some high-level verbs as commands ("assault Berlin", "bomb London until
destroyed").

Don't draw outline boxes at mags that would let them get outside the hex.

If dating view data, allow it to gray out rather than disappear entirely.
Could even have a "fade time" for unit images...

Even if display is textual, use red text (and other colors) to indicate
dangerous conditions.

Next/prev unit controls should change map focus, even if screen
unaffected.

In general, ability to "select" a unit implies ability to examine,
but not control.  Control implies ability to select, however.

Use a builtin color matching a color name if possible, otherwise
use the imc definition.

Connections may need to be drawn differently in each of the two hexes
they involve, such as straits connecting to a sea.
(what is this supposed to mean?)

If cell cramped for space, show only one material type at a time,
require redraw to show amounts of a different type.

Draw time remaining both digitally and as hourglass, for all time
limits in effect.

Could tie map to follow a specified unit (or to flip there quickly
a la SimAnt).

Have a separate message window from notices, allow broadcasting w/o
specific msg command? (a "talk" window)

Redraw hexes exposed when a unit with a legend moves.
Truncate or move legend if would overlap some other unit/legend.

Put limits on the number of windows of each type, set up so will reuse
windows, except for ones that are "staked down".

Fix border removal so inter-hex boundary pixels are cleaned up also.

Need a specialized window or display to check on current scores
(showing actual situation vs what's still needed).
(Show both scorekeepers actually in force, as well as the others.)
Side display could also display scores relevant to that side.

Every unit plan display should have a place to record notes and general
info about the unit, add a slot to units also.  Use in scenarios.

Need a command for when a player can explicitly change the self-unit.

Players should be able to rename any named object.  The interface should
also provide a button or control to run any namer that might be available
to the unit.

Be able to select unit number display indep of unit name display,
and feature name display indep of unit names.

Don't draw things that xform to 0 pixel areas,
only draw the most important things if 1-4 pixels or so.

If time/effort to do action is > length of game, then interface
can disable that action permanently.

Use moving bar or gray under black to indicate reserve/asleep units.

@node Networking, Miscellany, Interface, Hacking Xconq

@section Networking

@i{Xconq} has been also been designed to allow for different kinds of
networking strategies.

The kernel/interface architecture can be exploited to build
a true server/client @i{Xconq},
by building an ``interface'' that manages IPC connections
and calling this the server, and then writing separate interface
programs that translate data at the other end of the IPC connection
into something that a display could use.
My previous attempt at this (ca 1989) was very slow and buggy,
though, so this is not necessarily an easy thing to write.
The chief problem is in keeping the client's view of thousands
of interlinked objects (units, sides, cells, and so forth)
consistent with the server.
Most existing server/client games work by either restricting
the state to a handful of objects,
or by only handing the client display-prepared data
rather than abstract data,
or by reducing the update interval
to minutes or hours.

[When networking, all kernels must call with same values...]

@node Miscellany, , Networking, Hacking Xconq

@section Miscellany

@menu
* Versioning Standards::        
* Coding Standards::
* Pitfalls::
* Rationale and Future Directions::
@end menu

@node Versioning Standards, Coding Standards, Miscellany, Miscellany

@subsection Versioning Standards

In version @var{7.x.y}, @var{x} should change only
when some documented user-visible aspect of @i{Xconq} changes,
whether in the interface or kernel.
In particular, any additions to GDL, such as a new table or
property, require a new @var{x} version.
@var{y} is reserved for bug-fix releases, which can include
the implementation of features that were documented but not
working correctly or completely.

The macro @code{VERSION} should also include a date in parentheses,
formatted in ``military style'', as in ``8 Jul 1995''.
Be sure to set the date to some approximation of the date of your
most recent change to the sources.

@node Coding Standards, Pitfalls, Versioning Standards, Miscellany

@subsection Coding Standards

The @i{Xconq} sources adhere to a number of coding standards that
you should follow also.  While everyone has their individual style,
it is important to the code's maintenance that the existing style
be preserved.

You should allocate by using @code{xmalloc}.  This routine checks for
allocation validity and gives a useful error message if allocation
fails, it zeroes the block so you can count on the newly allocated
space being in a known state, and it collects statistical data, which
is important to optimization.

There is one exception to this allocation rule, which is that you
may use @code{malloc} if you intend to free the memory shortly.
An example would be temporary working space needed by an interface.
However, you must then check the return result from @code{malloc}
yourself and handle failures appropriately; remember that players
can easily ask for very large games, so it's quite possible that any
given call to @code{malloc} will be unable to allocate the desired
memory.

Always generate a random number by using @code{xrandom}.  This is
a generator of known and consistent properties across all systems
that @i{Xconq} runs on.

Indent by 4, with tabs at 8.  This is effectively what you get in
Emacs if you set @code{c-indent-level} to 4.  System-specific interfaces
need not adhere to this rule..

@node Pitfalls, Rationale and Future Directions, Coding Standards, Miscellany

@subsection Pitfalls

This chapter would not be complete without some discussion of the traps
awaiting the unwary hacker.
The Absolute Number One Hazard in hacking @i{Xconq} is to introduce
code that does not work for @emph{all} game designs.
It is all too easy to assume that, for instance, unit speeds are always
less than 20, or airbases can only be built by infantry, or that worlds
are always randomly-generated.
These sorts of assumptions have caused no end of problems.
Code should test preconditions, especially for dynamically-allocated
game-specified objects, and it should be tested using the various
test scripts in the test directory.

The number two pitfall is to not account for all the possible interfaces.
Not all interfaces have a single ``current unit'' or map window,
and some communicate with multiple players or over a network connection.

You should not assume that your hack is generally valid until you have
tested it against everything in the library and test directories.
The @code{test} directory contains scripts that will be useful for this,
at least to Unix hackers.  See the @code{README} in that directory
for more information.

Another pitfall is to be sloppy about performance.  An algorithm that works
fine in a small world with two sides and 50 units may be painfully slow
in a large game. Or, the algorithm may allocate too much working space
and wind up exhausting memory (this has often happened).
You should familiarize yourself with the algorithms already used in @i{Xconq},
since they have already been debugged and tuned, and many have been written
as generically useful code (see the area-scanning functions in @code{world.c}
for instance).

If your new feature is expensive, then define a global and compute its value
only once, either at the start of the game or when it becomes relevant.
Such a global should be named @code{any_<feature>}.

Similarly, complicated tests on unit types or sides should be calculated
once and cached in a dynamically-allocated array.

You may have noticed that @i{Xconq} sources have been liberally sprinkled
with debugging code, and you may desire to add some yourself.  In this modern
age of computing, powerful source-level debuggers are widely available,
so there is no good reason to add debugging code to do a job that
would be better done by the debugger.  @i{Xconq} debugging output
is generally designed to be useful for understanding average behavior,
changes over time, and ``high-level transients'' such as thrashing in
plan or task execution; information that is difficult to collect using only
a debugger.  When adding new debug output, you should keep this
principle in mind.  Also be aware that some of the automated testing scripts
enable debug output, so if you add something that is uselessly voluminous,
testing output may fill your disk prematurely!

@node Rationale and Future Directions, , Pitfalls, Miscellany

@subsection Rationale and Future Directions

This is where I justify what I've done, and not done.

Please note that although @i{Xconq} has considerable power,
its design was expressly limited to a particular class of two-dimensional
board-like strategy games, and that playability  is emphasized over
generality.  For instance, I avoided the temptation to include a
general-purpose language, since it opens up many difficult issues
and makes it much harder for game designers to produce a desired
game (after all, if game designers wanted to use a general-purpose
programming language, they could just write C code!).  Similarly,
full 3D, realtime maneuvering, continuous terrain, and other such goodies
must await the truly ultimate game system.

The real problem with a general-purpose language is that although
everything is possible, nothing is easy.  Many ``adventure game
writing systems'' have fallen into this trap; they end up being
poor reimplementations of standard programming languages, and the
sole support for adventure gaming amounts to a small program
skeleton and a few library functions.  It would have been easier
just to start with a pre-existing language and just write the
skeleton and libraries!

@i{Xconq}, on the other hand, provides extensive optimized support
for random game setup, large numbers of units, game save/restore,
computer opponents, and many other facets of a game.
Game designers don't have to deal with
the subleties of fractal terrain synthesis, or the ordering of
terrain effects on units, or how to tell the computer opponents
that airbases are sometimes good for refueling but never any
good for transportation, or the myriad of other details that
are wired into @i{Xconq}.
In fact, a complete working game can be set up with less than
a half-page of GDL.

Even so, the current @i{Xconq} design allows for several layers
of extensibility, as was described earlier in this chapter.

There are also several major areas in which @i{Xconq}
could be improved.

Tables should be supplemented with general formulae, although
such formulae will complicate AIs' analyses considerably,
since tables are much easier to scan.  Formula-based game
definition would work much better with AIs that are coded
specifically for the game and compiled in; this is more-or-less
possible now, but there is not yet a good way to keep AIs
from being used in games where they would be inappropriate
(it might be amusing to have a panzer general AI attempting
to play Gettysburg, but the coding would have to be careful
not to try to index nonexistent unit types).

Currently everything is based on a single area of a single world.
This could be extended to multiple areas in the world, perhaps
at different scales, as well as to multiple worlds.

However, even with its limitations, @i{Xconq} has provided,
and will continue to provide, many years of enjoyable playing,
designing, and hacking.  Go to it!