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