1 /*
2     XorGramana Copyright 2009 James W. Morris, james@jwm-art.net
3 
4     This file is part of XorGramana.
5 
6     XorGramana is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10 
11     XorGramana is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with XorGramana.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "movelist.h"
20 
21 #include "map.h"
22 
23 #include <stdlib.h>
24 
25 struct xmv_list* xmvlist=0;
26 
xmvlist_create()27 struct xmv_list* xmvlist_create()
28 {
29     if(xmvlist)
30         xmvlist_destroy();
31     if(!(xmvlist=malloc(sizeof(struct xmv_list))))
32         return 0;
33     xmvlist->first=xmvlist->last=xmvlist->current=0;
34     #ifdef MOVE_DEBUG
35     printf("created xmvlist=%lx\n",(unsigned long)xmvlist);
36     #endif
37     return xmvlist;
38 }
39 
xmvlist_destroy()40 void xmvlist_destroy()
41 {
42     struct xmv_link* tmp=0;
43     xmvlist->current=xmvlist->first;
44     while(xmvlist->current){
45         tmp=xmvlist->current;
46         xmvlist->current=tmp->next;
47         #ifdef MOVE_DEBUG
48         printf("destroyed xmv_link %lx\n",(unsigned long)tmp);
49         #endif
50         free(tmp);
51     }
52     #ifdef MOVE_DEBUG
53     printf("destroyed xmvlist %lx\n",(unsigned long)xmvlist);
54     #endif
55     free(xmvlist);
56     xmvlist=0;
57 }
58 
xmvlist_first()59 struct xmv_link* xmvlist_first()
60 {
61     return xmvlist->current=xmvlist->first;
62 }
63 
xmvlist_last()64 struct xmv_link* xmvlist_last()
65 {
66     return xmvlist->current=xmvlist->first;
67 }
68 
xmvlist_prev()69 struct xmv_link* xmvlist_prev()
70 {
71     if(xmvlist->current)
72         if(xmvlist->current->prev)
73             return (xmvlist->current=xmvlist->current->prev);
74     return xmvlist->current=0;
75 }
76 
xmvlist_next()77 struct xmv_link* xmvlist_next()
78 {
79     if(xmvlist->current)
80         if(xmvlist->current->next)
81             return (xmvlist->current=xmvlist->current->next);
82     return xmvlist->current=0;
83 }
84 
xmvlist_cycle_prev()85 struct xmv_link* xmvlist_cycle_prev()
86 {
87     if(xmvlist->current){
88         if(xmvlist->current==xmvlist->first)
89             return (xmvlist->current=xmvlist->last);
90         else
91             return (xmvlist->current=xmvlist->current->prev);
92     }
93     return 0;
94 }
95 
xmvlist_cycle_next()96 struct xmv_link* xmvlist_cycle_next()
97 {
98     if(xmvlist->current){
99         if(xmvlist->current==xmvlist->last)
100             return (xmvlist->current=xmvlist->first);
101         else
102             return (xmvlist->current=xmvlist->current->next);
103     }
104     return 0;
105 }
106 
xmvlist_current()107 struct xmv_link* xmvlist_current()
108 {
109     return xmvlist->current;
110 }
111 
xmvlist_append_xor_move(struct xor_move * xmv)112 struct xmv_link* xmvlist_append_xor_move(struct xor_move* xmv)
113 {
114     struct xmv_link* lnk=0;
115     if(!(lnk=malloc(sizeof(struct xmv_link))))
116         return 0;
117     lnk->xmv=xmv;
118     lnk->next=0;
119     if(!xmvlist->first){
120         xmvlist->first=xmvlist->last=xmvlist->current=lnk;
121         lnk->prev=0;
122         #ifdef MOVE_DEBUG
123         printf("created xmv_link %lx for xor_move %lx\n",
124             (unsigned long)lnk, (unsigned long)xmv);
125         #endif
126         return lnk;
127     }
128     xmvlist->last->next=lnk;
129     lnk->prev=xmvlist->last;
130     xmvlist->last=lnk;
131     #ifdef MOVE_DEBUG
132     printf("created xmv_link %lx for xor_move %lx\n",
133         (unsigned long)lnk, (unsigned long)xmv);
134     #endif
135     return lnk;
136 }
137 
xmvlist_unlink_xor_move(struct xmv_link * lnk)138 struct xor_move* xmvlist_unlink_xor_move(struct xmv_link* lnk)
139 {
140     struct xmv_link* tmp=0;
141     struct xor_move* xmv=lnk->xmv;
142     #ifdef MOVE_DEBUG
143     printf("xor_move* xmvlist_unlink_xor_move(xmv_link* lnk=%lx)\n",
144         (unsigned long)lnk);
145     if(lnk==xmvlist->current)
146         printf("\tunlinking xmvlist->current\n");
147     #endif
148     if(lnk==xmvlist->first){
149         if(xmvlist->first==xmvlist->last){
150             xmvlist->first=xmvlist->last=xmvlist->current=0;
151             #ifdef MOVE_DEBUG
152             printf("destroyed xmv_link (first/last) %lx for xor_move %lx\n",
153                 (unsigned long)lnk, (unsigned long)xmv);
154             #endif
155             free(lnk);
156             return xmv;
157         }
158         if(xmvlist->current==lnk)
159             xmvlist->current=lnk->next;
160         xmvlist->first=lnk->next;
161         xmvlist->first->prev=0;
162         #ifdef MOVE_DEBUG
163         printf("destroyed xmv_link (first) %lx for xor_move %lx\n",
164             (unsigned long)lnk, (unsigned long)xmv);
165         #endif
166         free(lnk);
167         return xmv;
168     }
169     if(lnk==xmvlist->last){
170         if(xmvlist->current==lnk)
171             xmvlist->current=xmvlist->first;
172         xmvlist->last=lnk->prev;
173         xmvlist->last->next=0;
174         #ifdef MOVE_DEBUG
175         printf("destroyed xmv_link (last) %lx for xor_move %lx\n",
176             (unsigned long)lnk, (unsigned long)xmv);
177         #endif
178         free(lnk);
179         return xmv;
180     }
181     tmp=lnk->next;
182     if(xmvlist->current==lnk)
183         xmvlist->current=tmp;
184     tmp->prev=lnk->prev;
185     tmp=lnk->prev;
186     tmp->next=lnk->next;
187     #ifdef MOVE_DEBUG
188     printf("destroyed xmv_link %lx for xor_move %lx\n",
189         (unsigned long)lnk, (unsigned long)xmv);
190     #endif
191     free(lnk);
192     return xmv;
193 }
194 
xmvlist_contains_coord(xy_t x,xy_t y,struct xmv_link * stop_at,struct xor_move ** res_prev)195 struct xmv_link* xmvlist_contains_coord
196 (
197     xy_t x,
198     xy_t y,
199     struct xmv_link* stop_at,
200     struct xor_move** res_prev
201 )
202 {
203     struct xmv_link* tmp=xmvlist->current;
204     struct xmv_link* result=0;
205     struct xor_move* xmv;
206     struct xor_move* rpxmv;
207     xmvlist_first();
208     while((result=xmvlist->current)&&xmvlist->current!=stop_at){
209         rpxmv=0;
210         xmv=xmvlist->current->xmv;
211         switch(xmv->dir){
212             case MV_LEFT:
213                 if(xmv->from_y==y&&xmv->from_x<=x){
214                     while(xmv){
215                         if(xmv->from_x==x){
216                             xmvlist->current=tmp;
217                             if(res_prev)
218                                 *res_prev=rpxmv;
219                             return result;
220                         }
221                         rpxmv=xmv;
222                         xmv=xmv->right;
223                     }
224                 }
225                 break;
226             case MV_RIGHT:
227                 if(xmv->from_y==y&&xmv->from_x>=x){
228                     while(xmv){
229                         if(xmv->from_x==x){
230                             xmvlist->current=tmp;
231                             if(res_prev)
232                                 *res_prev=rpxmv;
233                             return result;
234                         }
235                         rpxmv=xmv;
236                         xmv=xmv->left;
237                     }
238                 }
239                 break;
240             case MV_DOWN:
241                 if(xmv->from_x==x&&xmv->from_y<=y){
242                     while(xmv){
243                         if(xmv->from_y==y){
244                             xmvlist->current=tmp;
245                             if(res_prev)
246                                 *res_prev=rpxmv;
247                             return result;
248                         }
249                         rpxmv=xmv;
250                         xmv=xmv->up;
251                     }
252                 }
253                 break;
254             case MV_UP:
255                 if(xmv->from_x==x&&xmv->from_y>=y){
256                     while(xmv){
257                         if(xmv->from_y==y){
258                             xmvlist->current=tmp;
259                             if(res_prev)
260                                 *res_prev=rpxmv;
261                             return result;
262                         }
263                         rpxmv=xmv;
264                         xmv=xmv->down;
265                     }
266                 }
267                 break;
268             default:
269                 break;
270         }
271         xmvlist_next();
272     }
273     if(res_prev)
274         res_prev=0;
275     xmvlist->current=tmp;
276     return 0;
277 }
278