1 /* $Id: pile.c,v 1.3 2002/03/02 21:02:21 sverrehu Exp $ */
2 /**************************************************************************
3  *
4  *  FILE            pile.c
5  *  MODULE OF       Card game.
6  *
7  *  WRITTEN BY      Sverre H. Huseby <shh@thathost.com>
8  *
9  **************************************************************************/
10 
11 #include <stdlib.h>
12 #include <stdio.h>
13 
14 #include <shhmsg.h>
15 #include <xalloc.h>
16 #include <shhcards.h>
17 
18 #include "pile.h"
19 
20 /**************************************************************************
21  *                                                                        *
22  *                    P U B L I C    F U N C T I O N S                    *
23  *                                                                        *
24  **************************************************************************/
25 
26 Pile *
pileNew(void)27 pileNew(void)
28 {
29     Pile *p;
30 
31     p = xmalloc(sizeof(Pile));
32     p->x = p->y = 0;
33     p->maxWidth = CARD_WIDTH;
34     p->maxHeight = CARD_HEIGHT;
35     p->dx = p->dy = 0;
36     p->deltaEach = 1;
37     p->outline = -1;
38     p->numCards = 0;
39     p->bottom = p->top = NULL;
40     return p;
41 }
42 
43 void
pileDelete(Pile * p)44 pileDelete(Pile *p)
45 {
46     pileRemoveAllCards(p);
47     free(p);
48 }
49 
50 /* before==NULL, insert at top. */
51 void
pileInsertCardBefore(Pile * p,Card * c,Card * before)52 pileInsertCardBefore(Pile *p, Card *c, Card *before)
53 {
54     Card *target;
55 
56     if (c->pile)
57 	pileRemoveCard(c->pile, c);
58     c->pile = p;
59     if (!before) {
60 	c->next = NULL;
61 	c->prev = p->top;
62 	if (p->top)
63 	    p->top->next = c;
64 	else
65 	    p->bottom = c;
66 	p->top = c;
67     } else {
68 	target = p->top;
69 	while (target && target != before)
70 	    target = target->prev;
71 	if (target != before)
72 	    msgFatal("internal error in pileInsertCardBefore\n");
73 	c->prev = target->prev;
74 	if (c->prev == NULL)
75 	    p->bottom = c;
76 	else
77 	    c->prev->next = c;
78 	target->prev = c;
79 	c->next = target;
80     }
81     ++(p->numCards);
82 }
83 
84 void
pileAddCardBottom(Pile * p,Card * c)85 pileAddCardBottom(Pile *p, Card *c)
86 {
87     pileInsertCardBefore(p, c, p->bottom);
88 }
89 
90 void
pileAddCardTop(Pile * p,Card * c)91 pileAddCardTop(Pile *p, Card *c)
92 {
93     pileInsertCardBefore(p, c, NULL);
94 }
95 
96 void
pileInsertPileBefore(Pile * p,Pile * ip,Card * before)97 pileInsertPileBefore(Pile *p, Pile *ip, Card *before)
98 {
99     msgFatal("pileInsertPileBefore() isn't implemented\n");
100 }
101 
102 void
pileAddPileBottom(Pile * p,Pile * ap)103 pileAddPileBottom(Pile *p, Pile *ap)
104 {
105     msgFatal("pileAddPileBottom() isn't implemented\n");
106 }
107 
108 void
pileAddPileTop(Pile * p,Pile * ap)109 pileAddPileTop(Pile *p, Pile *ap)
110 {
111     Card *c;
112 
113     while ((c = ap->bottom) != NULL) {
114 	pileRemoveCard(ap, c);
115 	pileAddCardTop(p, c);
116     }
117 }
118 
119 void
pileRemoveCard(Pile * p,Card * c)120 pileRemoveCard(Pile *p, Card *c)
121 {
122     if (p != c->pile)
123 	msgFatal("internal error in pileRemoveCard\n");
124     c->pile = NULL;
125     if (c->prev)
126 	c->prev->next = c->next;
127     else
128 	p->bottom = c->next;
129     if (c->next)
130 	c->next->prev = c->prev;
131     else
132 	p->top = c->prev;
133     --(p->numCards);
134     c->prev = c->next = NULL;
135 }
136 
137 void
pileRemoveAllCards(Pile * p)138 pileRemoveAllCards(Pile *p)
139 {
140     while (p->numCards)
141 	pileRemoveCard(p, p->bottom);
142 }
143 
144 Pile *
pileMoveToNewPileFromCard(Pile * p,Card * c)145 pileMoveToNewPileFromCard(Pile *p, Card *c)
146 {
147     Pile *ret;
148     Card *cc;
149 
150     if (p != c->pile)
151 	msgFatal("internal error in pileMoveToNewPileFromCard\n");
152     ret = pileNew();
153     cc = p->top;
154     for (;;) {
155 	pileRemoveCard(p, cc);
156 	pileAddCardBottom(ret, cc);
157 	if (cc == c)
158 	    break;
159 	cc = p->top;
160     }
161     ret->x = p->x;
162     ret->y = p->y;
163     ret->maxWidth = p->maxWidth;
164     ret->maxHeight = p->maxHeight;
165     ret->dx = p->dx;
166     ret->dy = p->dy;
167     ret->deltaEach = p->deltaEach;
168     ret->outline = p->outline;
169     return ret;
170 }
171