3 * $Id: level.c,v 1.1 2003/12/12 10:55:30 mdw Exp $
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 /*----- Revision history --------------------------------------------------*
32 * Revision 1.1 2003/12/12 10:55:30 mdw
33 * Initial checkin. Not there yet.
37 /*----- Header files ------------------------------------------------------*/
41 /*----- Data structures ---------------------------------------------------*/
45 /*----- Main code ---------------------------------------------------------*/
47 int lev_findnext(const level *l, int c, int *x, int *y)
52 for (i= *y * l->w + *x + 1; i < n; i++) {
53 if ((l->d[i] & CF_CELLMASK) == c) {
62 int lev_findcell(const level *l, int c, int *x, int *y)
67 for (i = 0; i < n; i++) {
68 if ((l->d[i] & CF_CELLMASK) == c) {
77 level *lev_read(FILE *fp)
79 level *l = CREATE(level);
80 dstr d = DSTR_INIT, dd = DSTR_INIT;
89 /* --- Basic initialization --- */
91 l->name = xstrdup("<untitled>");
103 /* --- Read the preamble --- */
105 while (dstr_reset(&d), dstr_putline(&d, fp) != EOF) {
107 q = str_qword(&p, 0);
108 if (!q || *q == '#' || *q == ';')
110 if (strcmp(q, "name") == 0 && (q = str_qword(&p, STRF_QUOTE)) != 0) {
112 l->name = xstrdup(q);
113 } else if (strcmp(q, "flags") == 0 && (q = str_qword(&p, 0)) != 0) {
116 const char *lfmap = LF_MAP;
117 if ((r = strchr(lfmap, *q)) == 0)
119 f |= 1 << (r - lfmap);
122 } else if (strcmp(q, "masks-collected") == 0 &&
123 (q = str_qword(&p, 0)) != 0)
125 else if (strcmp(q, "masks-total") == 0 &&
126 (q = str_qword(&p, 0)) != 0)
128 else if (strcmp(q, "moves-made") == 0 &&
129 (q = str_qword(&p, 0)) != 0)
131 else if (strcmp(q, "moves-allowed") == 0 &&
132 (q = str_qword(&p, 0)) != 0)
134 else if (strcmp(q, "data") == 0) {
136 while (dstr_reset(&d), dstr_putline(&d, fp) != EOF) {
137 if (strstr("end", d.buf)) break;
139 while (d.buf[i] == C_EMPTY) i++;
140 if (ind == -1 || i < ind) ind = i;
141 while (d.buf[d.len - 1] == C_EMPTY) d.len--;
142 if (d.len > max) max = d.len;
148 l->d = xmalloc(l->h * l->w * sizeof(*l->d));
149 for (i = 0; i < l->w * l->h; i++)
152 for (i = 0; i < l->h; i++) {
154 p = dd.buf + n + ind;
156 pp = l->d + l->w * i;
157 while (p < q) *pp++ = *p++;
168 while (lev_findcell(l, C_UKMAP, &x, &y)) {
169 for (i = C_NWMAP; lev_findcell(l, i, 0, 0); i++) ;
170 CELLREF(l, x, y) = i;
172 for (i = 0; i < l->w * l->h; i++) {
173 if (!cellmap[l->d[i]]) {
174 fprintf(stderr, "warning: unknown map item: killing\n");
178 if (l->v > l->vtot) {
179 fprintf(stderr, "warning: too many moves already: locking\n");
182 if (lev_findcell(l, C_PLAYER, &x, &y)) {
183 CELLREF(l, x, y) = C_SPARE;
184 if (lev_findcell(l, C_PLAYER, &xx, &yy)) {
185 fprintf(stderr, "warning: multiple active players: deactivating\n");
187 CELLREF(l, xx, yy) = C_SPARE;
188 while (lev_findcell(l, C_PLAYER, &xx, &yy));
190 CELLREF(l, x, y) = C_PLAYER;
191 } else if (lev_findcell(l, C_SPARE, &x, &y)) {
192 fprintf(stderr, "warning: no active player: activating a spare\n");
193 CELLREF(l, x, y) = C_SPARE;
195 fprintf(stderr, "warning: no player found: hoping for the best\n");
196 for (i = 0; i < l->w * l->h; i++)
197 if (cellmap[l->d[i] & CF_CELLMASK]->f & CF_MASK) n++;
207 void lev_write(const level *l, FILE *fp)
209 const char *p = LF_MAP;
214 fprintf(fp, "name \"%s\"\n", l->name);
215 fprintf(fp, "flags ");
218 if (f & 1) putc(*p, fp);
223 fprintf(fp, "masks-collected %d\n", l->m);
224 fprintf(fp, "masks-total %d\n", l->mtot);
225 fprintf(fp, "size = %d x %d\n", l->w, l->h);
226 fprintf(fp, "data\n");
227 for (i = 0, pp = l->d; i < l->h; i++) {
228 for (j = 0; j < l->w; j++) putc(*pp++, fp);
231 fprintf(fp, "end\n");
234 void lev_free(level *l)
241 level *lev_copy(const level *l)
243 level *ll = CREATE(level);
245 ll->name = xstrdup(l->name);
246 ll->d = xmalloc(l->w * l->h * sizeof(*l->d));
247 memcpy(ll->d, l->d, l->w * l->h * sizeof(*l->d));
251 /*----- That's all, folks -------------------------------------------------*/