5 * Level I/O and handling
7 * (c) 2003 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of XOR.
14 * XOR is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * XOR is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with XOR; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Header files ------------------------------------------------------*/
33 /*----- Data structures ---------------------------------------------------*/
37 /*----- Main code ---------------------------------------------------------*/
39 int lev_findnext(const level
*l
, int c
, int *x
, int *y
)
44 for (i
= *y
* l
->w
+ *x
+ 1; i
< n
; i
++) {
45 if ((l
->d
[i
] & CF_CELLMASK
) == c
) {
54 int lev_findcell(const level
*l
, int c
, int *x
, int *y
)
59 for (i
= 0; i
< n
; i
++) {
60 if ((l
->d
[i
] & CF_CELLMASK
) == c
) {
69 level
*lev_read(FILE *fp
)
71 level
*l
= CREATE(level
);
72 dstr d
= DSTR_INIT
, dd
= DSTR_INIT
;
81 /* --- Basic initialization --- */
83 l
->name
= xstrdup("<untitled>");
95 /* --- Read the preamble --- */
97 while (dstr_reset(&d
), dstr_putline(&d
, fp
) != EOF
) {
100 if (!q
|| *q
== '#' || *q
== ';')
102 if (strcmp(q
, "name") == 0 && (q
= str_qword(&p
, STRF_QUOTE
)) != 0) {
104 l
->name
= xstrdup(q
);
105 } else if (strcmp(q
, "flags") == 0 && (q
= str_qword(&p
, 0)) != 0) {
108 const char *lfmap
= LF_MAP
;
109 if ((r
= strchr(lfmap
, *q
)) == 0)
111 f
|= 1 << (r
- lfmap
);
114 } else if (strcmp(q
, "masks-collected") == 0 &&
115 (q
= str_qword(&p
, 0)) != 0)
117 else if (strcmp(q
, "masks-total") == 0 &&
118 (q
= str_qword(&p
, 0)) != 0)
120 else if (strcmp(q
, "moves-made") == 0 &&
121 (q
= str_qword(&p
, 0)) != 0)
123 else if (strcmp(q
, "moves-allowed") == 0 &&
124 (q
= str_qword(&p
, 0)) != 0)
126 else if (strcmp(q
, "data") == 0) {
128 while (dstr_reset(&d
), dstr_putline(&d
, fp
) != EOF
) {
129 if (strstr("end", d
.buf
)) break;
131 while (d
.buf
[i
] == C_EMPTY
) i
++;
132 if (ind
== -1 || i
< ind
) ind
= i
;
133 while (d
.buf
[d
.len
- 1] == C_EMPTY
) d
.len
--;
134 if (d
.len
> max
) max
= d
.len
;
140 l
->d
= xmalloc(l
->h
* l
->w
* sizeof(*l
->d
));
141 for (i
= 0; i
< l
->w
* l
->h
; i
++)
144 for (i
= 0; i
< l
->h
; i
++) {
146 p
= dd
.buf
+ n
+ ind
;
148 pp
= l
->d
+ l
->w
* i
;
149 while (p
< q
) *pp
++ = *p
++;
160 while (lev_findcell(l
, C_UKMAP
, &x
, &y
)) {
161 for (i
= C_NWMAP
; lev_findcell(l
, i
, 0, 0); i
++) ;
162 CELLREF(l
, x
, y
) = i
;
164 for (i
= 0; i
< l
->w
* l
->h
; i
++) {
165 if (!cellmap
[l
->d
[i
]]) {
166 fprintf(stderr
, "warning: unknown map item: killing\n");
170 if (l
->v
> l
->vtot
) {
171 fprintf(stderr
, "warning: too many moves already: locking\n");
174 if (lev_findcell(l
, C_PLAYER
, &x
, &y
)) {
175 CELLREF(l
, x
, y
) = C_SPARE
;
176 if (lev_findcell(l
, C_PLAYER
, &xx
, &yy
)) {
177 fprintf(stderr
, "warning: multiple active players: deactivating\n");
179 CELLREF(l
, xx
, yy
) = C_SPARE
;
180 while (lev_findcell(l
, C_PLAYER
, &xx
, &yy
));
182 CELLREF(l
, x
, y
) = C_PLAYER
;
183 } else if (lev_findcell(l
, C_SPARE
, &x
, &y
)) {
184 fprintf(stderr
, "warning: no active player: activating a spare\n");
185 CELLREF(l
, x
, y
) = C_SPARE
;
187 fprintf(stderr
, "warning: no player found: hoping for the best\n");
188 for (i
= 0; i
< l
->w
* l
->h
; i
++)
189 if (cellmap
[l
->d
[i
] & CF_CELLMASK
]->f
& CF_MASK
) n
++;
199 void lev_write(const level
*l
, FILE *fp
)
201 const char *p
= LF_MAP
;
206 fprintf(fp
, "name \"%s\"\n", l
->name
);
207 fprintf(fp
, "flags ");
210 if (f
& 1) putc(*p
, fp
);
215 fprintf(fp
, "masks-collected %d\n", l
->m
);
216 fprintf(fp
, "masks-total %d\n", l
->mtot
);
217 fprintf(fp
, "size = %d x %d\n", l
->w
, l
->h
);
218 fprintf(fp
, "data\n");
219 for (i
= 0, pp
= l
->d
; i
< l
->h
; i
++) {
220 for (j
= 0; j
< l
->w
; j
++) putc(*pp
++, fp
);
223 fprintf(fp
, "end\n");
226 void lev_free(level
*l
)
233 level
*lev_copy(const level
*l
)
235 level
*ll
= CREATE(level
);
237 ll
->name
= xstrdup(l
->name
);
238 ll
->d
= xmalloc(l
->w
* l
->h
* sizeof(*l
->d
));
239 memcpy(ll
->d
, l
->d
, l
->w
* l
->h
* sizeof(*l
->d
));
243 /*----- That's all, folks -------------------------------------------------*/