1
/* The Ace of Penguins - freecell.c
2
Copyright (C) 1998, 2001 DJ Delorie
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2, or (at your option)
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
24
//#include "imagelib.h"
29
#define F CARD_FAN_DOWN
31
static Picture *splash, *youwin, *youlose, *arrow, *no_arrow;
34
static Stack *outcells[8];
35
static Stack *maincells[10];
37
static int suit_mask = 0; // 0 = one suit, 2 = two suit, 3 = four suit
39
static void auto_move();
40
static void check_for_end_of_game();
41
static void set_arrows();
42
static void clear_arrows();
43
static int ax, adx, ay, ady;
53
stack_flip_stack(outcells[i], deck);
55
stack_flip_stack(maincells[i], deck);
57
while(stack_take_card(deck) != -1);
60
for (v=ACE; v<=KING; v++)
61
stack_add_card(deck, MAKE_CARD(s & suit_mask, v, FACEDOWN));
67
stack_move_cards(deck, stack_count_cards(deck)-1, maincells[i%10]);
69
stack_move_cards(deck, stack_count_cards(deck)-1, maincells[i*3]);
71
stack_flip_card(deck, maincells[i]);
84
stack_load_standard_deck();
85
empty = get_picture("empty");
87
set_centered_pic(splash);
90
outcells[s] = stack_create((2+s)*(W+M), M);
91
stack_set_empty_picture(outcells[s], empty);
94
for (s=0; s<10; s++) {
95
maincells[s] = stack_create(M+s*(M+W), H+M);
96
stack_set_offset(maincells[s], STACK_OFFSET_DOWN);
99
deck = stack_create(M, M);
107
int margin, offset, cw, ch, s, fd, fr, tfd, tfr;
111
stack_set_card_size (w/11, w/11*4/3);
112
stack_get_card_size (&cw, &ch);
114
empty = (Picture *)get_image("empty", cw, ch, 0);
116
margin = (w - 10*cw) / 11;
117
offset = (w - margin*11 - cw*10) / 2 + margin;
119
for (s=0; s<8; s++) {
120
stack_move(outcells[s], (s+2)*(cw+margin)+offset, margin);
121
stack_set_empty_picture(outcells[s], empty);
124
stack_move(maincells[s], offset + s*(cw+margin), ch + (offset<0?0:offset));
125
stack_move(deck, margin+offset, margin);
127
stack_get_fans(&fd, &fr, &tfd, &tfr);
131
ay = offset + ch*2 + 2;
138
static int no_arrows = 0;
139
static int supress_arrows = 0;
140
static int arrowsx[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
141
static int arrowsy[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
144
set_arrow(int column, int on)
146
int x = ax + adx*column;
147
if (supress_arrows || no_arrows) return;
149
put_picture(no_arrow, arrowsx[column]-no_arrow->w/2, arrowsy[column],
150
0, 0, no_arrow->w, no_arrow->h);
155
arrowsy[column] = ay+ady*(stack_count_cards(maincells[column])-1);
156
put_picture(arrow, arrowsx[column]-arrow->w/2, arrowsy[column],
157
0, 0, arrow->w, arrow->h);
167
if(no_arrows) return;
171
put_picture(arrow, arrowsx[i]-arrow->w/2, arrowsy[i],
172
0, 0, arrow->w, arrow->h);
187
int i, j, k, src_next;
190
Stack *dest = maincells[i];
191
int dest_count = stack_count_cards(dest);
192
int dest_top = stack_get_card(dest, dest_count-1);
197
if (dest_count == 0) { set_arrow(i,1); add=1; };
199
for (j=0; j<10 && add==0; j++) {
200
Stack *src = maincells[j];
201
int src_count = stack_count_cards(src);
206
if ((i == j) || (src_count == 0)) n = 0;
208
src_top = stack_get_card(src, n);
209
src_next = stack_get_card(src, n-1);
210
if (VALUE(src_top) == VALUE(dest_top)-1) {
212
//possible let's see if better
213
if(n == 0) better = 1;
215
if (VALUE(src_top) != VALUE(src_next)-1) better = 1;
218
if (SUIT(src_top) != SUIT(src_next)) better = 1;
222
if (n == 0 || VALUE(src_top) != VALUE(src_next)-1 ||
223
SUIT(src_top) != SUIT(src_next) ||
224
FACEDOWNP(src_next) == FACEDOWN ) n = 0;
228
if (add) set_arrow(i,1);
240
extern char spider_help[];
243
key(int k, int x, int y)
245
Picture *p = get_centered_pic();
248
if (p == splash) return;
251
case 3: case 27: case 'q': case 'Q':
254
case KEY_F(1): case 'h': case 'H':
255
help("bj.html", spider_help);
257
case KEY_F(2): case 'r':
260
case 8: case 127: case KEY_DELETE:
289
static Stack *src_stack = 0;
290
static int src_n = 0;
292
static Stack *dest_stack;
293
static int last_n=-1;
296
n_droppable_s(Stack *dest_stack)
298
int src_top, dest_top, src_count, dest_count, i, src_next;
300
src_count = stack_count_cards(src_stack);
301
dest_count = stack_count_cards(dest_stack);
302
dest_top = stack_get_card(dest_stack, dest_count-1);
304
for (i=0; i<10; i++) {
305
if (dest_stack == maincells[i]) {
310
src_top = stack_get_card(src_stack, n);
311
if ((VALUE(src_top) == VALUE(dest_top)-1)
312
|| (n == src_n && dest_count == 0)) return n;
314
src_next = stack_get_card(src_stack, n-1);
315
if (n == 0 || VALUE(src_top) != VALUE(src_next)-1 ||
316
SUIT(src_top) != SUIT(src_next) ||
317
FACEDOWNP(src_next) == FACEDOWN ) {
318
if ((dest_count == 0) || (dest_stack == src_stack))return n;
319
else return src_count;
329
n_droppable(int x, int y)
333
if (!stack_drag_find(x, y, &dest_stack))
335
dest_stack = src_stack;
336
return last_n != -1 ? last_n : src_n;
338
return n_droppable_s(dest_stack);
345
int i, c, s, v, f, n;
347
for (i=0; i<10; i++) {
348
n = stack_count_cards(maincells[i]);
349
c = stack_get_card(maincells[i],n-1);
350
if (FACEDOWNP(c)) stack_flip_card(maincells[i], maincells[i]);
351
if ((VALUE(c) == ACE) && n >= 13) {
356
while((n>=0)&&(stack_get_card(maincells[i],n) == MAKE_CARD(s,v,f))) {
360
//Full suit to move, first find empty outcell
362
while(stack_count_cards(outcells[c++]) != 0);
364
for(v=ACE; v<=KING; v++) stack_animate(maincells[i],outcells[c]);
365
i--; // to flip any cards in this column
372
check_for_end_of_game()
375
if (stack_count_cards(outcells[7]) == 13) set_centered_pic(youwin);
376
if (stack_count_cards(deck) == 0) {
380
for (i=0; i<10; i++) {
381
if (arrowsy[i] != 0) end = 0;
383
// if (end) set_centered_pic(youlose);
388
click(int x, int y, int b)
391
Picture *cp = get_centered_pic();
410
f = stack_find(x, y, &src_stack, &src_n);
415
stack_peek_card(src_stack, src_n, 1);
421
if (src_stack == outcells[c])
424
if (src_stack == deck) {
426
for (c=0; c<10; c++) {
427
if (stack_count_cards(maincells[c]) == 0) empty_stack = 1;
430
if (empty_stack == 0) {
431
for (c=0; c<10; c++) {
432
stack_flip_card(deck, maincells[c]);
437
if (stack_count_cards(src_stack) > 0)
438
stack_begin_drag(src_stack, src_n, x, y);
444
drag(int x, int y, int b)
447
last_n = n_droppable(x, y);
448
stack_continue_drag(last_n, x, y);
452
drop(int x, int y, int b)
454
last_n = n_droppable(x, y); /* also sets dest_stack */
459
stack_peek_card(src_stack, src_n, 0);
463
stack_drop(dest_stack, last_n);
464
check_for_end_of_game();
468
static FunctionMapping fmap[] = {
469
{ "click", (void *)click },
470
{ "drag", (void *)drag },
471
{ "drop", (void *)drop },
472
{ "init", (void *)init },
473
{ "key", (void *)key },
474
{ "redraw", (void *)redraw },
475
{ "resize", (void *)resize },
480
main(int argc, char **argv)
482
register_imagelib(appimglib_imagelib);
483
init_ace(argc, argv, fmap);
484
splash = get_picture("spider");
485
youwin = get_picture("youwin");
486
youlose = get_picture("youlose");
487
arrow = get_picture("golf-arrow");
488
no_arrow = get_picture("golf-noarrow");
489
if (table_width == 0 || table_height == 0)
491
table_width = 10*(W+M) + M;
494
init_table(table_width, table_height);