File: toolkit.html

package info (click to toggle)
ace-of-penguins 1.5~rc2-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 2,532 kB
  • sloc: sh: 13,542; ansic: 9,852; makefile: 249; perl: 36
file content (794 lines) | stat: -rw-r--r-- 33,375 bytes parent folder | download | duplicates (2)
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
<title>The Ace of Penguins Toolkit</title>
<body bgcolor="#e0e0e0" background="penguin.gif" text="#000000">

<h1 align=center>
<img src="title.gif" width=416 height=55 alt="The Ace of Penguins"><br>
Toolkit</h1>

<img src="as.gif" width=93 height=117 alt="" align=right>

<p>The Ace of Penguins Toolkit allows you to create your own solitaire
games pretty easily.  For example, I wrote the first version of
<tt>golf</tt> in about ten minutes (the toolkit was already done at
that point).  My wife watched, and played it when I was done.  I later
added more bells and whistles, but the basic game only took ten
minutes.  </p>

<p>There are some utilities that come with the toolkit that you'll
need to be familiar with in order to build your game.  These tools
allow you to integrate pictures and online help into your program,
much like the Windows(tm) resource compiler.  Graphics are created in
the standard GIF format and integrated into your program with the
<tt>gif2pack</tt> program.  Help is written as a limited HTML file and
integrated with <tt>text2c</tt>.  The toolkit has functions that
access these resources when the program needs them.</p>

<p>All Ace programs use <a href="http://www.libpng.org/pub/png/">the
PNG library</a> and <a
href="http://www.info-zip.org/pub/infozip/zlib/">ZLib</a>.  Your
system may have them installed, otherwise you'll need to download and
install them.</p>

<p>The library consists of three main parts: A collection of standard
images (including, of course, the deck of cards), functionality to
maintain and manipulate the "table" and interface with X, and a set of
functions to create and manipulate "stacks" of cards.</p>

<h2>Getting Started</h2>

<p>Your source file must inlude cards.h from wherever you installed
it.  In my case, I use <tt>#include "cards.h"</tt> and let the
<tt>Makefile</tt> worry about how to tell <tt>gcc</tt> where to
include it from.

<p>Your program should, in <tt>main()</tt>, call three functions:

<pre>
  init_ace(argc, argv);
  init_table(width, height);
  table_loop();
</pre>

Here, <tt>argc</tt> and <tt>argv</tt> are the parameters passed to
<tt>main()</tt> and <tt>width</tt> and <tt>height</tt> are whatever
width and height your window ("table") should be.  You'll probably
want to calculate the initial size of the table based on the sizes of
the cards and margins (they're defined in <tt>cards.h</tt>).  The
<tt>init_*()</tt> calls do everything needed to get the X interface
running.  The <tt>table_loop()</tt> call passes control over to the
Ace library, and does not return.  Instead, the Ace library manages
the X interface, and calls functions you define when user interaction
occurs (see the events section below).

<h2>Makefiles and Linking</h2>

You'll need to add<tt> -lpng -lz -lX11 </tt>to the end of your link line
in your <tt>Makefile</tt>.  You'll also need to link the Ace library,
which for me means adding <tt>../lib/cardlib.a</tt> but you'll need to
do whatever is appropriate for where you installed the library.  For
example, if you copied <tt>cardlib.a</tt> to
<tt>/usr/lib/libcards.a</tt> then you'd add <tt>-lcards</tt> instead.
Note that the card library gets linked before the X libraries.
Example:

<pre>
sol : sol.o sol-help.o sol-img.o
	$(CC) $(CFLAGS) -o $@ $^ -lcards -lpng -lz -lX11
</pre>

Note in the example above that your game will probably consist of at
least three files.  First is the game itself (<tt>sol.o</tt> in this
example).  Next is the help file (<tt>sol-help.o</tt>), which started
as HTML and was converted to C by <tt>text2c</tt>.  Last is the image
library (<tt>sol-img.o</tt>) which is generated from your pngs by
<tt>make-imglib</tt>.  To build these, you'll need rules like this:

<pre>
%-help.c : %.html ../lib/text2c
	../lib/text2c $*_help < $< > $@

%-img.c : %.png
	../lib/make-imglib -i $(srcdir) -n appimglib - $@ $<
</pre>

Of course, you'll need to adjust these for your situation.


<h2>Events</h2>

There are a number of functions that you may define in your program to
add functionality.  Each of these is called when some event happens,
such as a mouse click or exposure.  Here are the events you may define,
with their prototypes:

<dl>

<dt> <tt>void <b>init</b>();</tt>

<dd> This function is called once just after your window appears on
the screen.  You should use this function to set up the pitures,
stacks, and other data you need to initialize once per program run.
What I do is define a second function called start_over() that resets
the game itself, and have init call start_over as the last thing it
does.  That way, I can call start_over from other places also.</p>

<dt> <tt>void <b>redraw</b>()</tt>

<dd> This function is called whenever part of the X window is
"exposed" and needs to be redrawn.  The computer doesn't remember what
was there, it needs to draw it from scratch.  Note that the
put_picture functions are designed to work with this event, so that
they will automatically optimize themselves.  An X clipping region is
also set up for you.  The best way to deal with redraw events is to
redraw the entire window and let the Ace and X libraries worry about
limiting you to the parts that were actually exposed.</p>

<dt> <tt>void <b>resize</b>(int width, int height)</tt>

<dd> If you provide this function, your game becomes resizable, and
you will be responsible for repositioning all the images and stacks
according to the new size.  You will probably need to call
<tt>stack_set_card_size</tt> (and read back the actual sizes with
<tt>stack_get_card_size</tt> and <tt>stack_get_fans</tt>).</p>

<dt> <tt>void <b>key</b>(int k, int x, int y)</tt>

<dd> This function is called each time the user presses a key.  If the
key they pressed is a regular key with an ASCII equivalent (like `h'),
the ASCII code is passed as <tt>k</tt>, otherwise the keyc ode (like
KEY_F(1) or KEY_UP) is passed.  The location of the pointer is passed
as x and y.  If you do not define this function, a default is provided
which exits when the user presses ESC or Ctrl-C.  Your routine should
do a similar check to remain consistent with other Ace programs.</p>

<dt> <tt>void <b>click</b>(int x, int y, int b)</tt>

<dd> This function is called whenever the user presses a mouse button.
the primary button is number 1.  For maximum compatibility, you should
only check to see if the button is 1 or greater than 1, since the
numbering of buttons isn't guaranteed to be standard.</p>

<dt> <tt>void <b>double_click</b>(int x, int y, int b)</tt>

<dd> This function is called when the user double-clicks the mouse.
Note that there will be a click() call for the first click but not for
the second.  If you do not define this function, click() is called for
every click.</p>

<dt> <tt>void <b>drag</b>(int x, int y, int b)</tt>

<dd> This function is called when the user moves the pointer while
holding the button down.</p>

<dt> <tt>void <b>drop</b>(int x, int y, int b)</tt>

<dd> This function is called when the user releases the button.</p>

</dl>



<h2>Table Functions</h2>

<dl>

<dt> <tt><b>CARD_WIDTH</b>,  <b>CARD_HEIGHT</b>, <b>CARD_MARGIN</b></tt>

<dd> These macros define the default size of the cards, and the amount
of space you should allow for between cards and around the edge of the
window.  By using these macros, your program will have the same style
as other programs written with this library.</p>

<dt> <tt><b>CARD_FAN_DOWN</b>, <b>CARD_FAN_RIGHT</b>,
<b>CARD_FAN_TBDOWN</b>, <b>CARD_FAN_TBRIGHT</b></tt>

<dd> These macros define the default offsets to be used when a stack
of cards is "fanned" in a given direction (only down and right are
supported).  The <tt>TB</tt> versions are for a "tiny bit" of fanning;
just enough to hint at the value of the card, whereas the others
offset them enough to clearly see the value of the card.</p>

<dt> <tt>void <b>init_ace</b>(int argc, char **argv)</tt>

<dd> This function initlizes the Ace library.  It processes all
command line options and connects to the display.  After calling this,
the global variables <tt>display_width</tt> and
<tt>display_height</tt> are valid, and <tt>table_width</tt> and
<tt>table_height</tt> are non-zero if the user requested a specific
size on the command line.  If you need to see a command line option,
create an OptionDesc list for your game (see cards.h for details).</p>

<dt> <tt>void <b>init_table</b>(int argc, char **argv, int
table_width, int table_height)</tt>

<dd> This function sets up the interface to X and creates the initial
window.  This function must be called exactly once from
<tt>main()</tt>.</p>

<dt> void <b>table_loop</b>()

<dd> <tt>main()</tt> must call this function as the last thing it
does.  This function will never return.  Once called, the library
starts managing the interaction between the user (via X) and the
program (via events).</p>

<dt> <tt>Picture *<b>get_picture</b>(char *name)</tt>

<dd> This function loads one of the images that you added to your
program with the <tt>make-imglib</tt> program (either the
application-specific ones, or the standard ones).  This function
searches one table prefixed by <tt>imglib</tt> (the standard set) and
one prefixed by <tt>appimglib</tt> (the app-specific set).  Note that
you may call this function at any time, even before
<tt>init_table()</tt>, since the actual conversion of the image to
native X format is deferred until it is needed.  The format of the
<tt>Picture</tt> type is as follows:

<ul>
<li><tt>int w, h;</tt> - the size of the image
</ul>

Note that images may have a non-rectangular shape.  This is
automatically handled by the library.</p>

<dt><tt>void <b>put_picture</b>(Picture *picture, int dx, int dy,
		 int x, int y, int w, int h)</tt>

<dd> This puts a picture onto the screen.  This should only be called
by an event function, since it (like most of these types of functions)
call X routines.  The <tt>picture</tt> is one as returned by
<tt>get_picture</tt>.  The <tt>dx,dy</tt> tells where the upper left
pixel of the picture should be placed on the window (regardless of
what sub-part of the picture you are putting).  The <tt>x,y</tt> and
<tt>w,h</tt> indicate a sub-part of the picture to be shown.  In most
cases, <tt>x,y</tt> will be zero and <tt>w,h</tt> will be the actual
size of the picture.  Note that, during a <tt>redraw</tt> event, the
library knows what part of the window actually needs to be redrawn,
and may not draw your picture (or only draw part of it) if it's not
needed to redraw that part of the picture.</p>

<dt><tt>void <b>put_picture_inverted</b>(Picture *picture, int dx, int dy,
			  int x, int y, int w, int h)</tt>

<dd> Same as <tt>put_picture</tt>, except that the picture is inverted
before putting it.  Some things to note: On 24-bit displays, each RGB
component is separately inverted, but on other displays "inverting"
means only swapping black and white pixels.  Plan your pictures
accordingly.  Also, there is only one inversion cache, so if you have
multiple inverted images, performance will be degraded.</p>

<dt><tt>void <b>set_centered_pic</b>(Picture *picture)</tt>

<dd> This allows the program to tell the library to maintain a single
picture that is displayed centered on the window.  This is used by the
splash, win, and lose pictures.  Pass a <tt>NULL</tt> pointer to
remove the picture.</p>

<dt><tt>Picture *<b>get_centered_pic</b>()</tt>

<dd> This returns the current centered picture, or <tt>NULL</tt> if
none.  My programs use this in the <tt>click</tt> and <tt>key</tt>
events to automatically remove the splash picture on the first event,
and to detect when the user clicks on a win or lose picture.</p>

<dt><tt>void <b>clip</b>(int x, int y, int w, int h)</tt>

<dd> This changes the clipping rectangle.  Most programs won't need
this, since it's set appropriately by the library during exposures.</p>

<dt><tt>void <b>clear</b>(int x, int y, int w, int h)</tt>

<dd> This clears (fills with the table color) a given section of the
window.</p>

<dt><tt>void <b>invalidate</b>(int x, int y, int w, int h)</tt>

<dd>Forces the library to redraw part of the table.  This is different
than just calling <tt>redraw()</tt> because it sets the clipping info,
clears the area, calls redraw, and handles the centered picture.  This
is the preferred way of causing part of the screen to be redrawn.
Your program should alter the information about the layout, then
invalidate the area and let <tt>redraw()</tt> update the screen.</p>

<dt><tt>void <b>invalidate_nc</b>(int x, int y, int w, int h)</tt>

<dd> Same, except that the area is not cleared first.  This is an
optimization for the case where you're adding an image, and you don't
want the screen to flash the background color.</p>

<dt><tt>void <b>invalidate_exposure</b>(int ox, int oy, int ow, int oh,
				int nx, int ny, int nw, int nh)</tt>

<dd>This is a specialty function for the case where you're moving
something from one point to another.  Pass the old and new regions,
and it will invalidate the portion of the old region that isn't
covered by the new region.  You'd then use <tt>invalidate</tt> to
update the new region (or just <tt>put_picture</tt>).  By doing it
this way, you can avoid flickering.</p>

<dt><tt>void <b>flush</b>()</tt>

<dd> This forces all drawing operations to be pushed to the server
immediately, rather than cached.  You should use this between
iterations of an animation to ensure that the server is updating the
screen at a steady pace.</p>

<dt><tt>void <b>beep</b>()</tt>

<dd>It makes a beep.  Go figure.</p>

<dt><tt>void <b>text</b>(char *s, int x, int y)</tt>

<dd> This draws the given string at the given coordinates on the
window.  Note that the coordinates are the lower left corner of the
region the text occupies, not the starting baseline point.  The font
can be assumed to be a monospaced font, with each character occupying
a rectangle of width <tt>font_width</tt> and height
<tt>font_height</tt> (defined in <tt>cards.h</tt>).  This avoids the
messy calculations involving descenders and bearings.</p>

<dt><tt>void <b>help</b>(char *filename, char *text)</tt>

<dd> This invokes the help system.  Pass a file name and a pointer to
the file's data as prepared by <tt>text2c</tt>.  If the file exists,
it is used, else the data is used.  All the events are redirected to
the help system until it decides to give control back.</p>

<dt><tt>void <b>snap_to_grid</b>(int *x, int *y,
		  int step_x, int step_y,
		  int origin_x, int origin_y,
		  int max_distance)</tt>

<dd>This function is a general-purpose grid alignment function.  Pass
the coordinates you want to align as <tt>x</tt> and <tt>y</tt>.  The
grid is determined by the <tt>step</tt> and <tt>origin</tt>
parameters, with the <tt>origin</tt> indicating one of the points to
snap to.  If the given point is more than <tt>max_distance</tt> from
one of the grid points, <tt>x</tt> and <tt>y</tt> are unchanged, else
<tt>x</tt> and <tt>y</tt> are replaced with the closest grid point.
Note that <tt>max_distance</tt> is not a pythagorian distance, it's an
absolute value of the distance along each axis independently (i.e. it
defines a square of side 2*<tt>max_distance</tt> centered on the grid
point, not a circle of radius <tt>max_distance</tt>).</p>

</dl>

<h2>Stack Functions</h2>

<p>The stack functions all deal with stacks of cards.  Each card is
described by a single number that encodes its value, suit, and whether
the card is face up or face down.  <tt>cards.h</tt> provides a number
of macros for dealing with these numbers.  Also, the standard ace
library provides all the images matched up with these numbers, so you
do not need to worry about them.  Each stack is positioned on the
table, and may be neatly piled up or fanned to the right or down.</p>

<p>Note that the type <tt>Stack</tt> is an opaque pointer.  All stacks
are of type <tt>Stack *</tt> but there are no fields you may access
directly.</p>

<dl>

<dt><tt><b>MAKE_CARD</b>(s, v, f)</tt>

<dd> This macro combines the suit (<tt>s</tt>), value (<tt>v</tt>),
and face-upness (<tt>f</tt>) into a single card number.  The suit is
one of <tt>SUIT_HEARTS</tt>, <tt>SUIT_DIAMONDS</tt>,
<tt>SUIT_CLUBS</tt>, or <tt>SUIT_SPADES</tt>.  Note that these are
<tt>0..3</tt>, but don't rely on that.  The value is <tt>1..13</tt>,
but you may use <tt>ACE</tt>, <tt>2..10</tt>, <tt>JACK</tt>,
<tt>QUEEN</tt>, and <tt>KING</tt> as well.  Zero is reserved for "no
card", so a zero value is not used to refer to a card.  The
face-upness is either <tt>FACEUP</tt> or <tt>FACEDOWN</tt>.  The macro
returns the card number.</p>

<dt><tt><b>SUIT</b>(c)</tt>

<dd> Takes a card number and returns its suit (the <tt>SUIT_</tt>
macros above).</p>

<dt><tt><b>COLOR</b>(c)</tt>

<dd>Returns the "color" of a card (red or black).  Note that no
specific color values are defined; the only thing you can do with the
returned value of this macro is compare it to other values returned by
this macro.  In other words, you can tell if two cards are the same or
different colors, but nothing else.</p>

<dt><tt><b>VALUE</b>(c)</tt>

<dd>Returns the value of a card (<tt>ACE</tt>, <tt>2..10</tt>,
<tt>JACK</tt>, <tt>QUEEN</tt>, <tt>KING</tt>).</p>

<dt><tt><b>FACEDOWNP</b>(c)</tt>

<dd> The face-down predicate returns the face-downness of a card.  It
returns either <tt>FACEUP</tt> or <tt>FACEDOWN</tt>.</p>

<dt><tt>Stack *	<b>stack_create</b>(int x, int y)</tt>

<dd> This function creates a stack and positions it on the table.  The
stack is initially empty and is not fanned in any direction (i.e. the
cards are neatly piled upon each other).</p>

<dt><tt>void <b>stack_destroy</b>(Stack *s)</tt>

<dd>This function destroys a stack and frees up the resources it was
using.  Most solitaire-type games won't ever destroy stacks, they'll
just reshuffle the cards among them.</p>

<dt><tt>void <b>stack_set_pictures</b>(Picture **fronts, Picture *back)</tt>

<dd>This function allows the application to specify the pictures to be
used to display the cards.  The <tt>fronts</tt> array is indexed by
the card number (i.e. <tt>MAKE_CARD</tt> with FACEUP); you should
allow for 64 slots in your array.  The <tt>back</tt> picture is for
all face-down cards.  All pictures should be <tt>CARD_WIDTH</tt> by
<tt>CARD_HEIGHT</tt> pixels.</p>

<dt><tt>void <b>stack_load_standard_deck</b>()</tt>

<dd> This function loads all the standard card pictures from the
built-in library.  Most card games should call this once in
<tt>init()</tt>.</p>

<dt><tt>void <b>stack_move</b>(Stack *s, int x, int y)</tt>

<dd> This function moves a stack to a new location on the screen.
While not generally useful to common solitaire games, it is used
internally to drag and drop cards between stacks.</p>

<dt><tt>void <b>stack_set_offset</b>(Stack *s, int which_offset)</tt>

<dd>This function changes the offset for each card in a stack.  By
offsetting cards, the player can view parts of obscured cards, thus
being able to see the value of the card.  Valid values for
<tt>which_offset</tt> are <tt>STACK_OFFSET_NONE</tt>,
<tt>STACK_OFFSET_RIGHT</tt>, <tt>STACK_OFFSET_DOWN</tt>,
<tt>STACK_OFFSET_TBRIGHT</tt>, and <tt>STACK_OFFSET_TBDOWN</tt>.
The <tt>TB</tt> versions are for a "tiny bit" of offset.</p>

<dt><tt>void <b>stack_set_card_size</b>(int width, int height)</tt>

<dd> Request that the card size be changed, such as after a resize.
Note that the values you give are requests - the library may need to
use a different size.  Use <tt>stack_get_card_size</tt> to find out
what was really used.</p>

<dt><tt>void <b>stack_get_card_size</b>(int *width, int *height)</tt>

<dd> Find out how big the current cards are.</p>

<dt><tt>void <b>stack_get_fans</b>(int *down, int *right, int *tbdown,
int *tbright)</tt>

<dd> Get the offsets for fan_down, etc.</p>

<dt><tt>void <b>stack_set_empty_picture</b>(Stack *s, Picture *p)</tt>

<dd> This lets you specify a picture that is drawn when the stack is
empty.  For example, some games want it to look like you're stacking
the cards on top of something.  This is where you specify the
something.  There is a standard picture called <tt>empty.gif</tt> that
simulates a small platform for the cards.</p>

<dt><tt>void <b>stack_redraw</b>()</tt>

<dd> This function should be called from your <tt>redraw()</tt>
function (the default <tt>redraw</tt> does this for you if you don't
specify one yourself).  This causes all stacks to redraw their
cars.</p>

<dt><tt>void <b>stack_peek_card</b>(Stack *s, int n, int show)</tt>

<dd>This function lets the player "peek" at an otherwise obscured
card.  What it does is force that card to be drawn on top of all the
other cards in the stack, regardless of where it is in the stack.
This is used to support the right-mouse button in solitaire, which
lets you see the suit of obscured cards.  Note that this function will
not show you the face of a face-down card.  Note that when <tt>n</tt>
(the index of the card in the stack) is zero, it means the bottom-most
card on the deck (the one closest to the table, not the one closest to
the bottom of your monitor).  The top-most card (the one the player
sees the most of) has the highest number, one less than
<tt>stack_count_cards()</tt> returns.  Pass a non-zero value for
<tt>show</tt> to show the card, or pass zero to put the card back and
show the stack normally.  </p>

<dt><tt>int <b>stack_count_cards</b>(Stack *s)</tt>

<dd> Returns the number of cards in the stack.  Zero means empty.</p>

<dt><tt>int <b>stack_get_card</b>(Stack *s, int n)</tt>

<dd>Returns the number of the given card on the stack (suitable for
the <tt>SUIT</tt>, <tt>COLOR</tt>, and <tt>VALUE</tt> macros, etc).</p>

<dt><tt>void <b>stack_add_card</b>(Stack *s, int c)</tt>

<dd>Adds one card to the top of the given stack.</p>

<dt><tt>int <b>stack_take_card</b>(Stack *s)</tt>

<dd>Removes one card from the top of the stack and returns it.</p>

<dt><tt>void <b>stack_change_card</b>(Stack *s, int n, int c)</tt>

<dd>Changes the given card to the given number.  Note that whan
<tt>n</tt> is zero, that indicates the bottom-most card.  This
function is most often used to change a card from <tt>FACEDOWN</tt> to
<tt>FACEUP</tt>.  </p>

<dt><tt>void <b>stack_shuffle</b>(Stack *s)</tt>

<dd> This function randomizes the sequence of the cards stored in the
stack.  To simulate a deck of cards, you'd create one stack and fill
it with all 52 combinations (or more, depending on the game) and
shuffle it.  Then, you'd use one of the other functions (like
<tt>stack_flip_card</tt>) to move cards from this "deck" to the other
stacks.  To restart the game, use <tt>stack_flip_stack</tt> to move
them all back to the deck, shuffle again, and start over.</p>

<dt><tt>int <b>stack_find</b>(int x, int y, Stack **stack_ret, int *n_ret)</tt>

<dd>This function is used by the <tt>click</tt> type events to
identify which card the player selected.  You pass it the <tt>x,y</tt>
of the event, and a pointer to a stack pointer and integer.  If the
player selected a card, the <tt>stack_ret</tt> and <tt>n_ret</tt>
variables are set to the stack and index into the stack they selected
(when <tt>n_ret</tt> is zero, they selected the bottom-most card) and
a non-zero value is returned.  If the player did not select a card,
<tt>stack_ret</tt> and <tt>n_ret</tt> are unchanged and a zero value
is returned.</p>

<dt><tt>int <b>stack_drag_find</b>(int x, int y, Stack **stack_ret)</tt>

<dd>When dragging a stack, this function tells you which stack you
have dragged it over.  Similar to <tt>stack_find</tt>.  Note that the
library remembers what you're dragging from <tt>stack_begin_drag</tt>
and will do the Right Thing.</p>

<dt><tt>int <b>stack_card_posn</b>(Stack *s, int n, int *x, int *y)</tt>

<dd>Given a card in a stack (when <tt>n</tt> is zero, it refers to the
bottom-most card), find its position on the table.  This takes into
account the offset the stack might have.  The size of the card is
<tt>CARD_WIDTH</tt> by <tt>CARD_HEIGHT</tt>.  If the card specified
exists, <tt>x</tt> and <tt>y</tt> are set to the coordinates of the
upper left pixel and a non-zero value is returned, else zero is
returned and <tt>x</tt> and <tt>y</tt> are unchanged.</p>

<dt><tt>void <b>stack_move_cards</b>(Stack *src, Stack *dest, int num, int flag)</tt>

<dd>Move <tt>num</tt> cards from the top of stack <tt>src</tt> to the top of
stack <tt>dest</tt>. If <tt>flag</tt> is nonzero then <tt>stack_undo</tt>
considers this an automatic move.</p>

<dt><tt>void <b>stack_move_card</b>(Stack *src, Stack *dest, int flag)</tt>

<dd>Like <tt>stack_move_cards</tt> but moves just one card.</p>

<dt><tt>void <b>stack_flip_cards</b>(Stack *src, Stack *dest, int num, int flag)</tt>

<dd>Take <tt>num</tt> cards from <tt>src</tt>, flip them over, and put
them on top of <tt>dest</tt>. If <tt>flag</tt> is nonzero then
<tt>stack_undo</tt> considers this an automatic move.</p>

<dt><tt>void <b>stack_flip_card</b>(Stack *src, Stack *dest, int flag)</tt>

<dd>Like <tt>stack_flip_cards</tt> but flips just one card.</p>

<dt><tt>void <b>stack_flip_stack</b>(Stack *src, Stack *dest, int flag)</tt>

<dd>Like <tt>stack_flip_cards</tt> but flips the entire stack.</p>

<dt><tt>void <b>stack_flip_move_stack</b>(Stack *src, Stack *dest, int flag)</tt>

<dd>Combination of <tt>stack_flip_cards</tt> and <tt>stack_move_cards</tt>;
assuming that the cards at the top of <tt>src</tt> are face up and the rest are
face down, first flip those cards that are face up, then move the rest.</p>

<dt><tt>void <b>stack_animate</b>(Stack *src, Stack *dest, int flag)</tt>

<dd>Moves one card from <tt>src</tt> to <tt>dest</tt>, but does it in
such a way that the player can <em>see</em> it moving from one to the
other. If <tt>flag</tt> is nonzero then <tt>stack_undo</tt> considers
this an automatic move. You should use this for auto-play so that the
player can see what's happening.</p>

<dt><tt>void <b>stack_undo</b>()</tt>

<dd>All operations on stacks are recorded.  Calling this function
reverses those operations.  You may continue calling this function,
and it will continue reversing the operations, until no more exist.
Calling it when no further undo is available causes no actions.</p>

<dt><tt>void <b>stack_undo_reset</b>()</tt>

<dd>This function erases all undo information.  You should call this
function after dealing the cards each time you start (or restart) a
game, so that the player cannot undo the deal itself.</p>

<dt><tt>void <b>stack_begin_drag</b>(Stack *s, int n, int x, int y)</tt>

<dd> This function is one of three that coordinate drag-and-drop
between stacks.  With this function, you identify what you are picking
up - the stack, the index of the card within the stack (when
<tt>n</tt> is zero, the whole stack is picked up), and the coordinates
of the pointer at the time you picked it up.  If you call this
function while a drag is in progress, the previous drag is
cancelled.</p>

<dt><tt>void <b>stack_continue_drag</b>(int n, int x, int y)</tt>

<dd>Called in your <tt>drag()</tt> function, this tells the library to
move the cards you've picked up to a new location to follow the
pointer.  The library maintains a constant offset relative to the
pointer to give it a "natural" feel (the card don't jump into your
hand, for example).  You also must pass the index of the card that is
allowed to be dropped at that time (use <tt>stack_drag_find</tt>).  As
you pass different values of <tt>n</tt> to this function, the window
will change to reflect carrying the right number of cards.  If you
pass <tt>n</tt> greater than the largest card index (see
<tt>stack_count_cards</tt>), a special graphic that indicates "drop
not allowed here" is used.</p>

<dt><tt>void <b>stack_drop</b>(Stack *onto, int n, int flag)</tt>

<dd>This function ends a drag-and-drop operation by specifying which
cards from the original stack are to be dropped onto <tt>onto</tt>.
If <tt>flag</tt> is nonzero then <tt>stack_undo</tt> considers this
an automatic move.
You may pass the original stack as <tt>onto</tt> or pass <tt>n</tt>
greater than the largest card index (see <tt>stack_count_cards</tt>)
to cancel a drag operation. </p>

</dl>

<h2>Adding Pictures</h2>

<p>It is to be expected that most applications will have some pictures
that are specific to that application.  For example, the splash screen
("Welcome to my game") usually has the name of the application, so it
will be specific.  Each application is allowed to create one
additional library of pictures that can be linked into your program;
the library has the other one.  To add images, paint your images in
standard PNG format (no animations, transparency is supported).  Then,
call <tt>make-imglib</tt> like this:

<pre>
gif2pack -i $(srcdir) -n appimglib - mypictures.c *.png
</pre>

Of course, replace <tt>mypictures.c</tt> and <tt>*.png</tt> with
appropriate stuff for your application.  This will create a C source
file that contains your image data.  Then, compile and link that
source with your other sources.  By calling your picture library
<tt>appimglib</tt>, the ace library functions will automatically use
it.  When you call <tt>get_picture</tt>, pass the name of the original
file (<tt>*.png</tt>) but without path info or ".png".  Run
"make-imglib -h" for a detailed list of options.</p>

</ul>

<h2>Calling X Directly</h2>

If you must call X directly (to draw lines or whatnot), look in xwin.c
for a list of non-static variables you can use <em>after</em> your
<tt>init()</tt> function is called.  These are:

<pre>
extern Display *display;
extern int screen;
extern Visual *visual;
extern Colormap cmap;
extern Window window;
extern Window rootwin;
extern GC gc;
extern XFontStruct *font;
</pre>

You'll also need to include whatever X headers you need.  Note that
during exposures, the clip mask in the gc is set as needed.  If you
must mess with the clip mask, be careful to restore it if you can, or
create your own GC to draw with.

<p>If you do this, your program will not be portable to other
windowing systems if/when that ever happens.

<h2>Online Help</h2>

To add online help to your application, you need to write the help
file in plain HTML.  There are only a few HTML constructs that are
recognized, and you <strong>must</strong> write valid HTML.  Note that
closing tags are <em>not</em> optional if you want it to work right.
Here are the supported tags.  You must use lower case, and when the
tag allows options (like <tt>img</tt>) they must be provided in the
order given with exactly the syntax shown.  The HTML parser will not
accept just any HTML file.  When a closing tag is shown, it is
mandatory.  Tags may be nested, but do not need to be properly nested
(you <em>should</em> properly nest them, but the program won't blow up
if you don't).

<dl>

<dt><tt>&lt;b&gt; . . . &lt;/b&gt;</tt>

<dd> Bold

<dt><tt>&lt;i&gt; . . . &lt;/i&gt;</tt>

<dd> Italics

<dt><tt>&lt;tt&gt; . . . &lt;/tt&gt;</tt>

<dd> Teletype (monospaced) font

<dt><tt>&lt;big&gt; . . . &lt;/big&gt;</tt>

<dd> Big font

<dt><tt>&lt;h1&gt; . . . &lt;/h1&gt;</tt>

<dd> Primary headers.  These are used to create the tabs that separate
pages, so don't use any other HTML inside an H1, avoid newlines, and
keep it short.

<dt><tt>&lt;h2&gt; . . . &lt;/h2&gt;</tt>

<dd> Secondary headers.  Same as &lt;p&gt;&lt;big&gt;&lt;b&gt;.  You
should put one of these (with more elaborate text) after each H1 so
that each page has a title banner.

<dt><tt>&lt;p&gt; . . . &lt;/p&gt;</tt>

<dd> Paragraph.  Note that both &lt;p&gt; and &lt;/p&gt; do exactly
the same thing - they cause the next "thing" (word or picture) to
start a new paragraph - but you should use them properly anyway.

<dt><tt>&lt;br&gt;</tt>

<dd>Line break.  The next "thing" will be at the left margin of the
next line.  Multiple BR act like one BR.

<dt><tt>&lt;img src=file&gt;</tt>
<dt><tt>&lt;img align=center src=file&gt;</tt>
<dt><tt>&lt;img align=left src=file&gt;</tt>
<dt><tt>&lt;img align=right src=file&gt;</tt>

<dd>An image.  No quotes around the file name, which is as you'd pass
to <tt>get_picture</tt> (since that's what it does).  The
<tt>align=center</tt> variant aligns the picture vertically centered
on the line.  If text is included in the line also, the text
centerline (not the baseline, but half the height of an "m") aligns
with the image centerline.  Left and right alignment cause the image
to float to the margins, with text wrapping around them.

</dl>

<p>While developing the HTML help, run your application such that the
filename passed to <tt>help()</tt> refers to your HTML file.  Then,
press <tt>F1</tt> to invoke the online help of your application, and
it will read the file instead of using the built-in text.  Each time
you exit help (<tt>F1</tt> again, or <tt>Esc</tt>) and re-invoke it,
it re-reads the help file (you don't need to exit your
application).</p>

When you're done, use <tt>text2c</tt> to convert the HTML file to a C
source file, which you can compile and link in to your application:

<pre>
text2c my_help < mygame-help.html > mygame-help.c
</pre>

That first argument (<tt>my_help</tt> in this example) defines the
name of a symbol which you then refer to in your program:

<pre>
extern char my_help[];
...
help("mygame-help.html", my_help);
</pre>

<hr noshade size=1> <i>Copyright &copy; 2001 <a
href="http://www.delorie.com/users/dj/">DJ Delorie</a></i>