Stop the analysis pass in Loopy's redraw routine from being
[sgt/puzzles] / undead.c
1 /*
2 * undead: Implementation of Haunted Mirror Mazes
3 *
4 * http://www.janko.at/Raetsel/Spukschloss/index.htm
5 *
6 * Puzzle definition is the total number of each monster type, the
7 * grid definition, and the list of sightings (clockwise, starting
8 * from top left corner)
9 *
10 * Example: (Janko puzzle No. 1,
11 * http://www.janko.at/Raetsel/Spukschloss/001.a.htm )
12 *
13 * Ghosts: 0 Vampires: 2 Zombies: 6
14 *
15 * 2 1 1 1
16 * 1 \ \ . / 2
17 * 0 \ . / . 2
18 * 0 / . / . 2
19 * 3 . . . \ 2
20 * 3 3 2 2
21 *
22 * would be encoded into:
23 * 4x4:0,2,6,LLaRLaRaRaRdL,2,1,1,1,2,2,2,2,2,2,3,3,3,0,0,1
24 *
25 * Additionally, the game description can contain monsters fixed at a
26 * certain grid position. The internal generator does not (yet) use
27 * this feature, but this is needed to enter puzzles like Janko No.
28 * 14, which is encoded as:
29 * 8x5:12,12,0,LaRbLaRaLaRLbRaVaVaGRaRaRaLbLaRbRLb,0,2,0,2,2,1,2,1,3,1,0,1,8,4,3,0,0,2,3,2,7,2,1,6,2,1
30 *
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <assert.h>
37 #include <ctype.h>
38 #include <math.h>
39
40 #include "puzzles.h"
41
42 enum {
43 COL_BACKGROUND,
44 COL_GRID,
45 COL_TEXT,
46 COL_ERROR,
47 COL_HIGHLIGHT,
48 COL_FLASH,
49 COL_GHOST,
50 COL_ZOMBIE,
51 COL_VAMPIRE,
52 NCOLOURS
53 };
54
55 #define DIFFLIST(A) \
56 A(EASY,Easy,e) \
57 A(NORMAL,Normal,n) \
58 A(TRICKY,Tricky,t)
59 #define ENUM(upper,title,lower) DIFF_ ## upper,
60 #define TITLE(upper,title,lower) #title,
61 #define ENCODE(upper,title,lower) #lower
62 #define CONFIG(upper,title,lower) ":" #title
63 enum { DIFFLIST(ENUM) DIFFCOUNT };
64 static char const *const undead_diffnames[] = { DIFFLIST(TITLE) "(count)" };
65 static char const undead_diffchars[] = DIFFLIST(ENCODE);
66 #define DIFFCONFIG DIFFLIST(CONFIG)
67
68 struct game_params {
69 int w; /* Grid width */
70 int h; /* Grid height */
71 int diff; /* Puzzle difficulty */
72 };
73
74 static const struct game_params undead_presets[] = {
75 { 4, 4, DIFF_EASY },
76 { 4, 4, DIFF_NORMAL },
77 { 4, 4, DIFF_TRICKY },
78 { 5, 5, DIFF_EASY },
79 { 5, 5, DIFF_NORMAL },
80 { 5, 5, DIFF_TRICKY },
81 { 7, 7, DIFF_EASY },
82 { 7, 7, DIFF_NORMAL }
83 };
84
85 #define DEFAULT_PRESET 1
86
87 static game_params *default_params(void) {
88 game_params *ret = snew(game_params);
89
90 *ret = undead_presets[DEFAULT_PRESET];
91 return ret;
92 }
93
94 static int game_fetch_preset(int i, char **name, game_params **params) {
95 game_params *ret;
96 char buf[64];
97
98 if (i < 0 || i >= lenof(undead_presets)) return FALSE;
99
100 ret = default_params();
101 *ret = undead_presets[i]; /* struct copy */
102 *params = ret;
103
104 sprintf(buf, "%dx%d %s",
105 undead_presets[i].w, undead_presets[i].h,
106 undead_diffnames[undead_presets[i].diff]);
107 *name = dupstr(buf);
108
109 return TRUE;
110 }
111
112 static void free_params(game_params *params) {
113 sfree(params);
114 }
115
116 static game_params *dup_params(game_params *params) {
117 game_params *ret = snew(game_params);
118 *ret = *params; /* structure copy */
119 return ret;
120 }
121
122 static void decode_params(game_params *params, char const *string) {
123 params->w = params->h = atoi(string);
124
125 while (*string && isdigit((unsigned char) *string)) ++string;
126 if (*string == 'x') {
127 string++;
128 params->h = atoi(string);
129 while (*string && isdigit((unsigned char)*string)) string++;
130 }
131
132 params->diff = DIFF_NORMAL;
133 if (*string == 'd') {
134 int i;
135 string++;
136 for (i = 0; i < DIFFCOUNT; i++)
137 if (*string == undead_diffchars[i])
138 params->diff = i;
139 if (*string) string++;
140 }
141
142 return;
143 }
144
145 static char *encode_params(game_params *params, int full) {
146 char buf[256];
147 sprintf(buf, "%dx%d", params->w, params->h);
148 if (full)
149 sprintf(buf + strlen(buf), "d%c", undead_diffchars[params->diff]);
150 return dupstr(buf);
151 }
152
153 static config_item *game_configure(game_params *params) {
154 config_item *ret;
155 char buf[64];
156
157 ret = snewn(4, config_item);
158
159 ret[0].name = "Width";
160 ret[0].type = C_STRING;
161 sprintf(buf, "%d", params->w);
162 ret[0].sval = dupstr(buf);
163 ret[0].ival = 0;
164
165 ret[1].name = "Height";
166 ret[1].type = C_STRING;
167 sprintf(buf, "%d", params->h);
168 ret[1].sval = dupstr(buf);
169 ret[1].ival = 0;
170
171 ret[2].name = "Difficulty";
172 ret[2].type = C_CHOICES;
173 ret[2].sval = DIFFCONFIG;
174 ret[2].ival = params->diff;
175
176 ret[3].name = NULL;
177 ret[3].type = C_END;
178 ret[3].sval = NULL;
179 ret[3].ival = 0;
180
181 return ret;
182 }
183
184 static game_params *custom_params(config_item *cfg) {
185 game_params *ret = snew(game_params);
186
187 ret->w = atoi(cfg[0].sval);
188 ret->h = atoi(cfg[1].sval);
189 ret->diff = cfg[2].ival;
190 return ret;
191 }
192
193 static char *validate_params(game_params *params, int full) {
194 if ((params->w * params->h ) > 54) return "Grid is too big";
195 if (params->w < 3) return "Width must be at least 3";
196 if (params->h < 3) return "Height must be at least 3";
197 if (params->diff >= DIFFCOUNT) return "Unknown difficulty rating";
198 return NULL;
199 }
200
201 /* --------------------------------------------------------------- */
202 /* Game state allocation, deallocation. */
203
204 struct path {
205 int length;
206 int *p;
207 int grid_start;
208 int grid_end;
209 int num_monsters;
210 int *mapping;
211 int sightings_start;
212 int sightings_end;
213 int *xy;
214 };
215
216 struct game_common {
217 int refcount;
218 struct game_params params;
219 int wh;
220 int num_ghosts,num_vampires,num_zombies,num_total;
221 int num_paths;
222 struct path *paths;
223 int *grid;
224 int *xinfo;
225 int *fixed;
226 int solved;
227 };
228
229 struct game_state {
230 struct game_common *common;
231 int *guess;
232 unsigned char *pencils;
233 unsigned char *cell_errors;
234 unsigned char *hint_errors;
235 unsigned char count_errors[3];
236 int solved;
237 int cheated;
238 };
239
240 static game_state *new_state(game_params *params) {
241 int i;
242 game_state *state = snew(game_state);
243 state->common = snew(struct game_common);
244
245 state->common->refcount = 1;
246 state->common->params.w = params->w;
247 state->common->params.h = params->h;
248 state->common->params.diff = params->diff;
249
250 state->common->wh = (state->common->params.w +2) * (state->common->params.h +2);
251
252 state->common->num_ghosts = 0;
253 state->common->num_vampires = 0;
254 state->common->num_zombies = 0;
255 state->common->num_total = 0;
256
257 state->common->grid = snewn(state->common->wh, int);
258 state->common->xinfo = snewn(state->common->wh, int);
259 state->common->fixed = NULL;
260 state->common->solved = FALSE;
261
262 state->common->num_paths =
263 state->common->params.w + state->common->params.h;
264 state->common->paths = snewn(state->common->num_paths, struct path);
265
266 for (i=0;i<state->common->num_paths;i++) {
267 state->common->paths[i].length = 0;
268 state->common->paths[i].grid_start = -1;
269 state->common->paths[i].grid_end = -1;
270 state->common->paths[i].num_monsters = 0;
271 state->common->paths[i].sightings_start = 0;
272 state->common->paths[i].sightings_end = 0;
273 state->common->paths[i].p = snewn(state->common->wh,int);
274 state->common->paths[i].xy = snewn(state->common->wh,int);
275 state->common->paths[i].mapping = snewn(state->common->wh,int);
276 }
277
278 state->guess = NULL;
279 state->pencils = NULL;
280
281 state->cell_errors = snewn(state->common->wh, unsigned char);
282 for (i=0;i<state->common->wh;i++)
283 state->cell_errors[i] = FALSE;
284 state->hint_errors = snewn(2*state->common->num_paths, unsigned char);
285 for (i=0;i<2*state->common->num_paths;i++)
286 state->hint_errors[i] = FALSE;
287 for (i=0;i<3;i++)
288 state->count_errors[i] = FALSE;
289
290 state->solved = FALSE;
291 state->cheated = FALSE;
292
293 return state;
294 }
295
296 static game_state *dup_game(game_state *state) {
297 game_state *ret = snew(game_state);
298
299 ret->common = state->common;
300 ret->common->refcount++;
301
302 if (state->guess != NULL) {
303 ret->guess = snewn(ret->common->num_total,int);
304 memcpy(ret->guess, state->guess, ret->common->num_total*sizeof(int));
305 }
306 else ret->guess = NULL;
307
308 if (state->pencils != NULL) {
309 ret->pencils = snewn(ret->common->num_total,unsigned char);
310 memcpy(ret->pencils, state->pencils,
311 ret->common->num_total*sizeof(unsigned char));
312 }
313 else ret->pencils = NULL;
314
315 if (state->cell_errors != NULL) {
316 ret->cell_errors = snewn(ret->common->wh,unsigned char);
317 memcpy(ret->cell_errors, state->cell_errors,
318 ret->common->wh*sizeof(unsigned char));
319 }
320 else ret->cell_errors = NULL;
321
322 if (state->hint_errors != NULL) {
323 ret->hint_errors = snewn(2*ret->common->num_paths,unsigned char);
324 memcpy(ret->hint_errors, state->hint_errors,
325 2*ret->common->num_paths*sizeof(unsigned char));
326 }
327 else ret->hint_errors = NULL;
328
329 ret->count_errors[0] = state->count_errors[0];
330 ret->count_errors[1] = state->count_errors[1];
331 ret->count_errors[2] = state->count_errors[2];
332
333 ret->solved = state->solved;
334 ret->cheated = state->cheated;
335
336 return ret;
337 }
338
339 static void free_game(game_state *state) {
340 int i;
341
342 state->common->refcount--;
343 if (state->common->refcount == 0) {
344 for (i=0;i<state->common->num_paths;i++) {
345 sfree(state->common->paths[i].mapping);
346 sfree(state->common->paths[i].xy);
347 sfree(state->common->paths[i].p);
348 }
349 sfree(state->common->paths);
350 sfree(state->common->xinfo);
351 sfree(state->common->grid);
352 if (state->common->fixed != NULL) sfree(state->common->fixed);
353 sfree(state->common);
354 }
355 if (state->hint_errors != NULL) sfree(state->hint_errors);
356 if (state->cell_errors != NULL) sfree(state->cell_errors);
357 if (state->pencils != NULL) sfree(state->pencils);
358 if (state->guess != NULL) sfree(state->guess);
359 sfree(state);
360
361 return;
362 }
363
364 /* --------------------------------------------------------------- */
365 /* Puzzle generator */
366
367 /* cell states */
368 enum {
369 CELL_EMPTY,
370 CELL_MIRROR_L,
371 CELL_MIRROR_R,
372 CELL_GHOST,
373 CELL_VAMPIRE,
374 CELL_ZOMBIE,
375 CELL_UNDEF
376 };
377
378 /* grid walk directions */
379 enum {
380 DIRECTION_NONE,
381 DIRECTION_UP,
382 DIRECTION_RIGHT,
383 DIRECTION_LEFT,
384 DIRECTION_DOWN
385 };
386
387 int range2grid(int rangeno, int width, int height, int *x, int *y) {
388
389 if (rangeno < 0) {
390 *x = 0; *y = 0; return DIRECTION_NONE;
391 }
392 if (rangeno < width) {
393 *x = rangeno+1; *y = 0; return DIRECTION_DOWN;
394 }
395 rangeno = rangeno - width;
396 if (rangeno < height) {
397 *x = width+1; *y = rangeno+1; return DIRECTION_LEFT;
398 }
399 rangeno = rangeno - height;
400 if (rangeno < width) {
401 *x = width-rangeno; *y = height+1; return DIRECTION_UP;
402 }
403 rangeno = rangeno - width;
404 if (rangeno < height) {
405 *x = 0; *y = height-rangeno; return DIRECTION_RIGHT;
406 }
407 *x = 0; *y = 0;
408 return DIRECTION_NONE;
409 }
410
411 int grid2range(int x, int y, int w, int h) {
412 if (x>0 && x<w+1 && y>0 && y<h+1) return -1;
413 if (x<0 || x>w+1 || y<0 || y>h+1) return -1;
414 if ((x == 0 || x==w+1) && (y==0 || y==h+1)) return -1;
415 if (y==0) return x-1;
416 if (x==(w+1)) return y-1+w;
417 if (y==(h+1)) return 2*w + h - x;
418 return 2*(w+h) - y;
419 }
420
421 void make_paths(game_state *state) {
422 int i;
423 int count = 0;
424
425 for (i=0;i<2*(state->common->params.w + state->common->params.h);i++) {
426 int x,y,dir;
427 int j,k,num_monsters;
428 int found;
429 int c,p;
430 found = FALSE;
431 /* Check whether inverse path is already in list */
432 for (j=0;j<count;j++) {
433 if (i == state->common->paths[j].grid_end) {
434 found = TRUE;
435 break;
436 }
437 }
438 if (found) continue;
439
440 /* We found a new path through the mirror maze */
441 state->common->paths[count].grid_start = i;
442 dir = range2grid(i, state->common->params.w,
443 state->common->params.h,&x,&y);
444 state->common->paths[count].sightings_start =
445 state->common->grid[x+y*(state->common->params.w +2)];
446 while (TRUE) {
447 int c,r;
448
449 if (dir == DIRECTION_DOWN) y++;
450 else if (dir == DIRECTION_LEFT) x--;
451 else if (dir == DIRECTION_UP) y--;
452 else if (dir == DIRECTION_RIGHT) x++;
453
454 r = grid2range(x, y, state->common->params.w,
455 state->common->params.h);
456 if (r != -1) {
457 state->common->paths[count].grid_end = r;
458 state->common->paths[count].sightings_end =
459 state->common->grid[x+y*(state->common->params.w +2)];
460 break;
461 }
462
463 c = state->common->grid[x+y*(state->common->params.w+2)];
464 state->common->paths[count].xy[state->common->paths[count].length] =
465 x+y*(state->common->params.w+2);
466 if (c == CELL_MIRROR_L) {
467 state->common->paths[count].p[state->common->paths[count].length] = -1;
468 if (dir == DIRECTION_DOWN) dir = DIRECTION_RIGHT;
469 else if (dir == DIRECTION_LEFT) dir = DIRECTION_UP;
470 else if (dir == DIRECTION_UP) dir = DIRECTION_LEFT;
471 else if (dir == DIRECTION_RIGHT) dir = DIRECTION_DOWN;
472 }
473 else if (c == CELL_MIRROR_R) {
474 state->common->paths[count].p[state->common->paths[count].length] = -1;
475 if (dir == DIRECTION_DOWN) dir = DIRECTION_LEFT;
476 else if (dir == DIRECTION_LEFT) dir = DIRECTION_DOWN;
477 else if (dir == DIRECTION_UP) dir = DIRECTION_RIGHT;
478 else if (dir == DIRECTION_RIGHT) dir = DIRECTION_UP;
479 }
480 else {
481 state->common->paths[count].p[state->common->paths[count].length] =
482 state->common->xinfo[x+y*(state->common->params.w+2)];
483 }
484 state->common->paths[count].length++;
485 }
486 /* Count unique monster entries in each path */
487 state->common->paths[count].num_monsters = 0;
488 for (j=0;j<state->common->num_total;j++) {
489 num_monsters = 0;
490 for (k=0;k<state->common->paths[count].length;k++)
491 if (state->common->paths[count].p[k] == j)
492 num_monsters++;
493 if (num_monsters > 0)
494 state->common->paths[count].num_monsters++;
495 }
496
497 /* Generate mapping vector */
498 c = 0;
499 for (p=0;p<state->common->paths[count].length;p++) {
500 int m;
501 m = state->common->paths[count].p[p];
502 if (m == -1) continue;
503 found = FALSE;
504 for (j=0; j<c; j++)
505 if (state->common->paths[count].mapping[j] == m) found = TRUE;
506 if (!found) state->common->paths[count].mapping[c++] = m;
507 }
508 count++;
509 }
510 return;
511 }
512
513 struct guess {
514 int length;
515 int *guess;
516 int *possible;
517 };
518
519 int next_list(struct guess *g, int pos) {
520
521 if (pos == 0) {
522 if ((g->guess[pos] == 1 && g->possible[pos] == 1) ||
523 (g->guess[pos] == 2 && (g->possible[pos] == 3 ||
524 g->possible[pos] == 2)) ||
525 g->guess[pos] == 4)
526 return FALSE;
527 if (g->guess[pos] == 1 && (g->possible[pos] == 3 ||
528 g->possible[pos] == 7)) {
529 g->guess[pos] = 2; return TRUE;
530 }
531 if (g->guess[pos] == 1 && g->possible[pos] == 5) {
532 g->guess[pos] = 4; return TRUE;
533 }
534 if (g->guess[pos] == 2 && (g->possible[pos] == 6 || g->possible[pos] == 7)) {
535 g->guess[pos] = 4; return TRUE;
536 }
537 }
538
539 if (g->guess[pos] == 1) {
540 if (g->possible[pos] == 1) {
541 return next_list(g,pos-1);
542 }
543 if (g->possible[pos] == 3 || g->possible[pos] == 7) {
544 g->guess[pos] = 2; return TRUE;
545 }
546 if (g->possible[pos] == 5) {
547 g->guess[pos] = 4; return TRUE;
548 }
549 }
550
551 if (g->guess[pos] == 2) {
552 if (g->possible[pos] == 2) {
553 return next_list(g,pos-1);
554 }
555 if (g->possible[pos] == 3) {
556 g->guess[pos] = 1; return next_list(g,pos-1);
557 }
558 if (g->possible[pos] == 6 || g->possible[pos] == 7) {
559 g->guess[pos] = 4; return TRUE;
560 }
561 }
562
563 if (g->guess[pos] == 4) {
564 if (g->possible[pos] == 5 || g->possible[pos] == 7) {
565 g->guess[pos] = 1; return next_list(g,pos-1);
566 }
567 if (g->possible[pos] == 6) {
568 g->guess[pos] = 2; return next_list(g,pos-1);
569 }
570 if (g->possible[pos] == 4) {
571 return next_list(g,pos-1);
572 }
573 }
574 return FALSE;
575 }
576
577 void get_unique(game_state *state, int counter, random_state *rs) {
578
579 int p,i,c,count_uniques;
580 struct guess path_guess;
581
582 struct entry {
583 struct entry *link;
584 int *guess;
585 int start_view;
586 int end_view;
587 };
588
589 struct {
590 struct entry *head;
591 struct entry *node;
592 } views, single_views, loop_views, test_views;
593
594 struct entry test_entry;
595
596 path_guess.length = state->common->paths[counter].num_monsters;
597 path_guess.guess = snewn(path_guess.length,int);
598 path_guess.possible = snewn(path_guess.length,int);
599 for (i=0;i<path_guess.length;i++)
600 path_guess.guess[i] = path_guess.possible[i] = 0;
601
602 for (p=0;p<path_guess.length;p++) {
603 path_guess.possible[p] =
604 state->guess[state->common->paths[counter].mapping[p]];
605 switch (path_guess.possible[p]) {
606 case 1: path_guess.guess[p] = 1; break;
607 case 2: path_guess.guess[p] = 2; break;
608 case 3: path_guess.guess[p] = 1; break;
609 case 4: path_guess.guess[p] = 4; break;
610 case 5: path_guess.guess[p] = 1; break;
611 case 6: path_guess.guess[p] = 2; break;
612 case 7: path_guess.guess[p] = 1; break;
613 }
614 }
615
616 views.head = NULL;
617 views.node = NULL;
618
619 do {
620 int mirror;
621
622 views.node = snewn(1,struct entry);
623 views.node->link = views.head;
624 views.node->guess = snewn(path_guess.length,int);
625 views.head = views.node;
626 views.node->start_view = 0;
627 views.node->end_view = 0;
628 memcpy(views.node->guess, path_guess.guess,
629 path_guess.length*sizeof(int));
630
631 mirror = FALSE;
632 for (p=0;p<state->common->paths[counter].length;p++) {
633 if (state->common->paths[counter].p[p] == -1) mirror = TRUE;
634 else {
635 for (i=0;i<path_guess.length;i++) {
636 if (state->common->paths[counter].p[p] ==
637 state->common->paths[counter].mapping[i]) {
638 if (path_guess.guess[i] == 1 && mirror == TRUE)
639 views.node->start_view++;
640 if (path_guess.guess[i] == 2 && mirror == FALSE)
641 views.node->start_view++;
642 if (path_guess.guess[i] == 4)
643 views.node->start_view++;
644 break;
645 }
646 }
647 }
648 }
649 mirror = FALSE;
650 for (p=state->common->paths[counter].length-1;p>=0;p--) {
651 if (state->common->paths[counter].p[p] == -1) mirror = TRUE;
652 else {
653 for (i=0;i<path_guess.length;i++) {
654 if (state->common->paths[counter].p[p] ==
655 state->common->paths[counter].mapping[i]) {
656 if (path_guess.guess[i] == 1 && mirror == TRUE)
657 views.node->end_view++;
658 if (path_guess.guess[i] == 2 && mirror == FALSE)
659 views.node->end_view++;
660 if (path_guess.guess[i] == 4)
661 views.node->end_view++;
662 break;
663 }
664 }
665 }
666 }
667 } while (next_list(&path_guess, path_guess.length-1));
668
669 /* extract single entries from view list */
670
671 test_views.head = views.head;
672 test_views.node = views.node;
673
674 test_entry.guess = snewn(path_guess.length,int);
675
676 single_views.head = NULL;
677 single_views.node = NULL;
678
679 count_uniques = 0;
680 while (test_views.head != NULL) {
681 test_views.node = test_views.head;
682 test_views.head = test_views.head->link;
683 c = 0;
684 loop_views.head = views.head;
685 loop_views.node = views.node;
686 while (loop_views.head != NULL) {
687 loop_views.node = loop_views.head;
688 loop_views.head = loop_views.head->link;
689 if (test_views.node->start_view == loop_views.node->start_view &&
690 test_views.node->end_view == loop_views.node->end_view)
691 c++;
692 }
693 if (c == 1) {
694 single_views.node = snewn(1,struct entry);
695 single_views.node->link = single_views.head;
696 single_views.node->guess = snewn(path_guess.length,int);
697 single_views.head = single_views.node;
698 single_views.node->start_view = test_views.node->start_view;
699 single_views.node->end_view = test_views.node->end_view;
700 memcpy(single_views.node->guess, test_views.node->guess,
701 path_guess.length*sizeof(int));
702 count_uniques++;
703 }
704 }
705
706 if (count_uniques > 0) {
707 test_entry.start_view = 0;
708 test_entry.end_view = 0;
709 /* Choose one unique guess per random */
710 /* While we are busy with looping through single_views, we
711 * conveniently free the linked list single_view */
712 c = random_upto(rs,count_uniques);
713 while(single_views.head != NULL) {
714 single_views.node = single_views.head;
715 single_views.head = single_views.head->link;
716 if (c-- == 0) {
717 memcpy(test_entry.guess, single_views.node->guess,
718 path_guess.length*sizeof(int));
719 test_entry.start_view = single_views.node->start_view;
720 test_entry.end_view = single_views.node->end_view;
721 }
722 sfree(single_views.node->guess);
723 sfree(single_views.node);
724 }
725
726 /* Modify state_guess according to path_guess.mapping */
727 for (i=0;i<path_guess.length;i++)
728 state->guess[state->common->paths[counter].mapping[i]] =
729 test_entry.guess[i];
730 }
731
732 sfree(test_entry.guess);
733
734 while (views.head != NULL) {
735 views.node = views.head;
736 views.head = views.head->link;
737 sfree(views.node->guess);
738 sfree(views.node);
739 }
740
741 sfree(path_guess.possible);
742 sfree(path_guess.guess);
743
744 return;
745 }
746
747 int count_monsters(game_state *state,
748 int *cGhost, int *cVampire, int *cZombie) {
749 int cNone;
750 int i;
751
752 *cGhost = *cVampire = *cZombie = cNone = 0;
753
754 for (i=0;i<state->common->num_total;i++) {
755 if (state->guess[i] == 1) (*cGhost)++;
756 else if (state->guess[i] == 2) (*cVampire)++;
757 else if (state->guess[i] == 4) (*cZombie)++;
758 else cNone++;
759 }
760
761 return cNone;
762 }
763
764 int check_numbers(game_state *state, int *guess) {
765 int valid;
766 int i;
767 int count_ghosts, count_vampires, count_zombies;
768
769 count_ghosts = count_vampires = count_zombies = 0;
770 for (i=0;i<state->common->num_total;i++) {
771 if (guess[i] == 1) count_ghosts++;
772 if (guess[i] == 2) count_vampires++;
773 if (guess[i] == 4) count_zombies++;
774 }
775
776 valid = TRUE;
777
778 if (count_ghosts > state->common->num_ghosts) valid = FALSE;
779 if (count_vampires > state->common->num_vampires) valid = FALSE;
780 if (count_zombies > state->common->num_zombies) valid = FALSE;
781
782 return valid;
783 }
784
785 int check_solution(int *g, struct path path) {
786 int i;
787 int mirror;
788 int count;
789
790 count = 0;
791 mirror = FALSE;
792 for (i=0;i<path.length;i++) {
793 if (path.p[i] == -1) mirror = TRUE;
794 else {
795 if (g[path.p[i]] == 1 && mirror) count++;
796 else if (g[path.p[i]] == 2 && !mirror) count++;
797 else if (g[path.p[i]] == 4) count++;
798 }
799 }
800 if (count != path.sightings_start) return FALSE;
801
802 count = 0;
803 mirror = FALSE;
804 for (i=path.length-1;i>=0;i--) {
805 if (path.p[i] == -1) mirror = TRUE;
806 else {
807 if (g[path.p[i]] == 1 && mirror) count++;
808 else if (g[path.p[i]] == 2 && !mirror) count++;
809 else if (g[path.p[i]] == 4) count++;
810 }
811 }
812 if (count != path.sightings_end) return FALSE;
813
814 return TRUE;
815 }
816
817 int solve_iterative(game_state *state, struct path *paths) {
818 int solved;
819 int p,i,j,count;
820
821 int *guess;
822 int *possible;
823
824 struct guess loop;
825
826 solved = TRUE;
827 loop.length = state->common->num_total;
828 guess = snewn(state->common->num_total,int);
829 possible = snewn(state->common->num_total,int);
830
831 for (i=0;i<state->common->num_total;i++) {
832 guess[i] = state->guess[i];
833 possible[i] = 0;
834 }
835
836 for (p=0;p<state->common->num_paths;p++) {
837 if (paths[p].num_monsters > 0) {
838 loop.length = paths[p].num_monsters;
839 loop.guess = snewn(paths[p].num_monsters,int);
840 loop.possible = snewn(paths[p].num_monsters,int);
841
842 for (i=0;i<paths[p].num_monsters;i++) {
843 switch (state->guess[paths[p].mapping[i]]) {
844 case 1: loop.guess[i] = 1; break;
845 case 2: loop.guess[i] = 2; break;
846 case 3: loop.guess[i] = 1; break;
847 case 4: loop.guess[i] = 4; break;
848 case 5: loop.guess[i] = 1; break;
849 case 6: loop.guess[i] = 2; break;
850 case 7: loop.guess[i] = 1; break;
851 }
852 loop.possible[i] = state->guess[paths[p].mapping[i]];
853 possible[paths[p].mapping[i]] = 0;
854 }
855
856 while(TRUE) {
857 for (i=0;i<state->common->num_total;i++) {
858 guess[i] = state->guess[i];
859 }
860 count = 0;
861 for (i=0;i<paths[p].num_monsters;i++)
862 guess[paths[p].mapping[i]] = loop.guess[count++];
863 if (check_numbers(state,guess) &&
864 check_solution(guess,paths[p]))
865 for (j=0;j<paths[p].num_monsters;j++)
866 possible[paths[p].mapping[j]] |= loop.guess[j];
867 if (!next_list(&loop,loop.length-1)) break;
868 }
869 for (i=0;i<paths[p].num_monsters;i++)
870 state->guess[paths[p].mapping[i]] &=
871 possible[paths[p].mapping[i]];
872 sfree(loop.possible);
873 sfree(loop.guess);
874 }
875 }
876
877 for (i=0;i<state->common->num_total;i++) {
878 if (state->guess[i] == 3 || state->guess[i] == 5 ||
879 state->guess[i] == 6 || state->guess[i] == 7) {
880 solved = FALSE; break;
881 }
882 }
883
884 sfree(possible);
885 sfree(guess);
886
887 return solved;
888 }
889
890 int solve_bruteforce(game_state *state, struct path *paths) {
891 int solved, correct;
892 int number_solutions;
893 int p,i;
894
895 struct guess loop;
896
897 loop.guess = snewn(state->common->num_total,int);
898 loop.possible = snewn(state->common->num_total,int);
899
900 for (i=0;i<state->common->num_total;i++) {
901 loop.possible[i] = state->guess[i];
902 switch (state->guess[i]) {
903 case 1: loop.guess[i] = 1; break;
904 case 2: loop.guess[i] = 2; break;
905 case 3: loop.guess[i] = 1; break;
906 case 4: loop.guess[i] = 4; break;
907 case 5: loop.guess[i] = 1; break;
908 case 6: loop.guess[i] = 2; break;
909 case 7: loop.guess[i] = 1; break;
910 }
911 }
912
913 solved = FALSE;
914 number_solutions = 0;
915
916 while (TRUE) {
917
918 correct = TRUE;
919 if (!check_numbers(state,loop.guess)) correct = FALSE;
920 else
921 for (p=0;p<state->common->num_paths;p++)
922 if (!check_solution(loop.guess,paths[p])) {
923 correct = FALSE; break;
924 }
925 if (correct) {
926 number_solutions++;
927 solved = TRUE;
928 if(number_solutions > 1) {
929 solved = FALSE;
930 break;
931 }
932 for (i=0;i<state->common->num_total;i++)
933 state->guess[i] = loop.guess[i];
934 }
935 if (!next_list(&loop,state->common->num_total -1)) {
936 break;
937 }
938 }
939
940 sfree(loop.possible);
941 sfree(loop.guess);
942
943 return solved;
944 }
945
946 int path_cmp(const void *a, const void *b) {
947 const struct path *pa = (const struct path *)a;
948 const struct path *pb = (const struct path *)b;
949 return pa->num_monsters - pb->num_monsters;
950 }
951
952 static char *new_game_desc(game_params *params, random_state *rs,
953 char **aux, int interactive) {
954 int i,count,c,w,h,r,p,g;
955 game_state *new;
956
957 /* Variables for puzzle generation algorithm */
958 int filling;
959 int max_length;
960 int count_ghosts, count_vampires, count_zombies;
961 int abort;
962 float ratio;
963
964 /* Variables for solver algorithm */
965 int solved_iterative, solved_bruteforce, contains_inconsistency,
966 count_ambiguous;
967 int iterative_depth;
968 int *old_guess;
969
970 /* Variables for game description generation */
971 int x,y;
972 char *e;
973 char *desc;
974
975 i = 0;
976 while (TRUE) {
977 new = new_state(params);
978 abort = FALSE;
979
980 /* Fill grid with random mirrors and (later to be populated)
981 * empty monster cells */
982 count = 0;
983 for (h=1;h<new->common->params.h+1;h++)
984 for (w=1;w<new->common->params.w+1;w++) {
985 c = random_upto(rs,5);
986 if (c >= 2) {
987 new->common->grid[w+h*(new->common->params.w+2)] = CELL_EMPTY;
988 new->common->xinfo[w+h*(new->common->params.w+2)] = count++;
989 }
990 else if (c == 0) {
991 new->common->grid[w+h*(new->common->params.w+2)] =
992 CELL_MIRROR_L;
993 new->common->xinfo[w+h*(new->common->params.w+2)] = -1;
994 }
995 else {
996 new->common->grid[w+h*(new->common->params.w+2)] =
997 CELL_MIRROR_R;
998 new->common->xinfo[w+h*(new->common->params.w+2)] = -1;
999 }
1000 }
1001 new->common->num_total = count; /* Total number of monsters in maze */
1002
1003 /* Puzzle is boring if it has too few monster cells. Discard
1004 * grid, make new grid */
1005 if (new->common->num_total <= 4) {
1006 free_game(new);
1007 continue;
1008 }
1009
1010 /* Monsters / Mirrors ratio should be balanced */
1011 ratio = (float)new->common->num_total /
1012 (float)(new->common->params.w * new->common->params.h);
1013 if (ratio < 0.48 || ratio > 0.78) {
1014 free_game(new);
1015 continue;
1016 }
1017
1018 /* Assign clue identifiers */
1019 for (r=0;r<2*(new->common->params.w+new->common->params.h);r++) {
1020 int x,y,gridno;
1021 gridno = range2grid(r,new->common->params.w,new->common->params.h,
1022 &x,&y);
1023 new->common->grid[x+y*(new->common->params.w +2)] = gridno;
1024 new->common->xinfo[x+y*(new->common->params.w +2)] = 0;
1025 }
1026 /* The four corners don't matter at all for the game. Set them
1027 * all to zero, just to have a nice data structure */
1028 new->common->grid[0] = 0;
1029 new->common->xinfo[0] = 0;
1030 new->common->grid[new->common->params.w+1] = 0;
1031 new->common->xinfo[new->common->params.w+1] = 0;
1032 new->common->grid[new->common->params.w+1 + (new->common->params.h+1)*(new->common->params.w+2)] = 0;
1033 new->common->xinfo[new->common->params.w+1 + (new->common->params.h+1)*(new->common->params.w+2)] = 0;
1034 new->common->grid[(new->common->params.h+1)*(new->common->params.w+2)] = 0;
1035 new->common->xinfo[(new->common->params.h+1)*(new->common->params.w+2)] = 0;
1036
1037 /* Initialize solution vector */
1038 new->guess = snewn(new->common->num_total,int);
1039 for (g=0;g<new->common->num_total;g++) new->guess[g] = 7;
1040
1041 /* Initialize fixed flag from common. Not needed for the
1042 * puzzle generator; initialize it for having clean code */
1043 new->common->fixed = snewn(new->common->num_total,int);
1044 for (g=0;g<new->common->num_total;g++)
1045 new->common->fixed[g] = FALSE;
1046
1047 /* paths generation */
1048 make_paths(new);
1049
1050 /* Grid is invalid if max. path length > threshold. Discard
1051 * grid, make new one */
1052 switch (new->common->params.diff) {
1053 case DIFF_EASY: max_length = min(new->common->params.w,new->common->params.h) + 1; break;
1054 case DIFF_NORMAL: max_length = (max(new->common->params.w,new->common->params.h) * 3) / 2; break;
1055 case DIFF_TRICKY: max_length = 9; break;
1056 default: max_length = 9; break;
1057 }
1058
1059 for (p=0;p<new->common->num_paths;p++) {
1060 if (new->common->paths[p].num_monsters > max_length) {
1061 abort = TRUE;
1062 }
1063 }
1064 if (abort) {
1065 free_game(new);
1066 continue;
1067 }
1068
1069 qsort(new->common->paths, new->common->num_paths,
1070 sizeof(struct path), path_cmp);
1071
1072 /* Grid monster initialization */
1073 /* For easy puzzles, we try to fill nearly the whole grid
1074 with unique solution paths (up to 2) For more difficult
1075 puzzles, we fill only roughly half the grid, and choose
1076 random monsters for the rest For hard puzzles, we fill
1077 even less paths with unique solutions */
1078
1079 switch (new->common->params.diff) {
1080 case DIFF_EASY: filling = 2; break;
1081 case DIFF_NORMAL: filling = min( (new->common->params.w+new->common->params.h) , (new->common->num_total)/2 ); break;
1082 case DIFF_TRICKY: filling = max( (new->common->params.w+new->common->params.h) , (new->common->num_total)/2 ); break;
1083 default: filling = 0; break;
1084 }
1085
1086 count = 0;
1087 while ( (count_monsters(new, &count_ghosts, &count_vampires,
1088 &count_zombies)) > filling) {
1089 if ((count) >= new->common->num_paths) break;
1090 if (new->common->paths[count].num_monsters == 0) {
1091 count++;
1092 continue;
1093 }
1094 get_unique(new,count,rs);
1095 count++;
1096 }
1097
1098 /* Fill any remaining ambiguous entries with random monsters */
1099 for(g=0;g<new->common->num_total;g++) {
1100 if (new->guess[g] == 7) {
1101 r = random_upto(rs,3);
1102 new->guess[g] = (r == 0) ? 1 : ( (r == 1) ? 2 : 4 );
1103 }
1104 }
1105
1106 /* Determine all hints */
1107 count_monsters(new, &new->common->num_ghosts,
1108 &new->common->num_vampires, &new->common->num_zombies);
1109
1110 /* Puzzle is trivial if it has only one type of monster. Discard. */
1111 if ((new->common->num_ghosts == 0 && new->common->num_vampires == 0) ||
1112 (new->common->num_ghosts == 0 && new->common->num_zombies == 0) ||
1113 (new->common->num_vampires == 0 && new->common->num_zombies == 0)) {
1114 free_game(new);
1115 continue;
1116 }
1117
1118 /* Discard puzzle if difficulty Tricky, and it has only 1
1119 * member of any monster type */
1120 if (new->common->params.diff == DIFF_TRICKY &&
1121 (new->common->num_ghosts <= 1 ||
1122 new->common->num_vampires <= 1 || new->common->num_zombies <= 1)) {
1123 free_game(new);
1124 continue;
1125 }
1126
1127 for (w=1;w<new->common->params.w+1;w++)
1128 for (h=1;h<new->common->params.h+1;h++) {
1129 c = new->common->xinfo[w+h*(new->common->params.w+2)];
1130 if (c >= 0) {
1131 if (new->guess[c] == 1) new->common->grid[w+h*(new->common->params.w+2)] = CELL_GHOST;
1132 if (new->guess[c] == 2) new->common->grid[w+h*(new->common->params.w+2)] = CELL_VAMPIRE;
1133 if (new->guess[c] == 4) new->common->grid[w+h*(new->common->params.w+2)] = CELL_ZOMBIE;
1134 }
1135 }
1136
1137 /* Prepare path information needed by the solver (containing all hints) */
1138 for (p=0;p<new->common->num_paths;p++) {
1139 int mirror,x,y;
1140
1141 new->common->paths[p].sightings_start = 0;
1142 new->common->paths[p].sightings_end = 0;
1143
1144 mirror = FALSE;
1145 for (g=0;g<new->common->paths[p].length;g++) {
1146
1147 if (new->common->paths[p].p[g] == -1) mirror = TRUE;
1148 else {
1149 if (new->guess[new->common->paths[p].p[g]] == 1 && mirror == TRUE) (new->common->paths[p].sightings_start)++;
1150 else if (new->guess[new->common->paths[p].p[g]] == 2 && mirror == FALSE) (new->common->paths[p].sightings_start)++;
1151 else if (new->guess[new->common->paths[p].p[g]] == 4) (new->common->paths[p].sightings_start)++;
1152 }
1153 }
1154
1155 mirror = FALSE;
1156 for (g=new->common->paths[p].length-1;g>=0;g--) {
1157 if (new->common->paths[p].p[g] == -1) mirror = TRUE;
1158 else {
1159 if (new->guess[new->common->paths[p].p[g]] == 1 && mirror == TRUE) (new->common->paths[p].sightings_end)++;
1160 else if (new->guess[new->common->paths[p].p[g]] == 2 && mirror == FALSE) (new->common->paths[p].sightings_end)++;
1161 else if (new->guess[new->common->paths[p].p[g]] == 4) (new->common->paths[p].sightings_end)++;
1162 }
1163 }
1164
1165 range2grid(new->common->paths[p].grid_start,
1166 new->common->params.w,new->common->params.h,&x,&y);
1167 new->common->grid[x+y*(new->common->params.w +2)] =
1168 new->common->paths[p].sightings_start;
1169 range2grid(new->common->paths[p].grid_end,
1170 new->common->params.w,new->common->params.h,&x,&y);
1171 new->common->grid[x+y*(new->common->params.w +2)] =
1172 new->common->paths[p].sightings_end;
1173 }
1174
1175 /* Try to solve the puzzle with the iterative solver */
1176 old_guess = snewn(new->common->num_total,int);
1177 for (p=0;p<new->common->num_total;p++) {
1178 new->guess[p] = 7;
1179 old_guess[p] = 7;
1180 }
1181 iterative_depth = 0;
1182 solved_iterative = FALSE;
1183 contains_inconsistency = FALSE;
1184 count_ambiguous = 0;
1185
1186 while (TRUE) {
1187 int no_change;
1188 no_change = TRUE;
1189 solved_iterative = solve_iterative(new,new->common->paths);
1190 iterative_depth++;
1191 for (p=0;p<new->common->num_total;p++) {
1192 if (new->guess[p] != old_guess[p]) no_change = FALSE;
1193 old_guess[p] = new->guess[p];
1194 if (new->guess[p] == 0) contains_inconsistency = TRUE;
1195 }
1196 if (solved_iterative || no_change) break;
1197 }
1198
1199 /* If necessary, try to solve the puzzle with the brute-force solver */
1200 solved_bruteforce = FALSE;
1201 if (new->common->params.diff != DIFF_EASY &&
1202 !solved_iterative && !contains_inconsistency) {
1203 for (p=0;p<new->common->num_total;p++)
1204 if (new->guess[p] != 1 && new->guess[p] != 2 &&
1205 new->guess[p] != 4) count_ambiguous++;
1206
1207 solved_bruteforce = solve_bruteforce(new, new->common->paths);
1208 }
1209
1210 /* Determine puzzle difficulty level */
1211 if (new->common->params.diff == DIFF_EASY && solved_iterative &&
1212 iterative_depth <= 3 && !contains_inconsistency) {
1213 /* printf("Puzzle level: EASY Level %d Ratio %f Ambiguous %d (Found after %i tries)\n",iterative_depth, ratio, count_ambiguous, i); */
1214 break;
1215 }
1216
1217 if (new->common->params.diff == DIFF_NORMAL &&
1218 ((solved_iterative && iterative_depth > 3) ||
1219 (solved_bruteforce && count_ambiguous < 4)) &&
1220 !contains_inconsistency) {
1221 /* printf("Puzzle level: NORMAL Level %d Ratio %f Ambiguous %d (Found after %d tries)\n", iterative_depth, ratio, count_ambiguous, i); */
1222 break;
1223 }
1224 if (new->common->params.diff == DIFF_TRICKY &&
1225 solved_bruteforce && iterative_depth > 0 &&
1226 count_ambiguous >= 4 && !contains_inconsistency) {
1227 /* printf("Puzzle level: TRICKY Level %d Ratio %f Ambiguous %d (Found after %d tries)\n", iterative_depth, ratio, count_ambiguous, i); */
1228 break;
1229 }
1230
1231 /* If puzzle is not solvable or does not satisfy the desired
1232 * difficulty level, free memory and start from scratch */
1233 sfree(old_guess);
1234 free_game(new);
1235 i++;
1236 }
1237
1238 /* We have a valid puzzle! */
1239
1240 desc = snewn(10 + new->common->wh +
1241 6*(new->common->params.w + new->common->params.h), char);
1242 e = desc;
1243
1244 /* Encode monster counts */
1245 e += sprintf(e, "%d,", new->common->num_ghosts);
1246 e += sprintf(e, "%d,", new->common->num_vampires);
1247 e += sprintf(e, "%d,", new->common->num_zombies);
1248
1249 /* Encode grid */
1250 count = 0;
1251 for (y=1;y<new->common->params.h+1;y++)
1252 for (x=1;x<new->common->params.w+1;x++) {
1253 c = new->common->grid[x+y*(new->common->params.w+2)];
1254 if (count > 25) {
1255 *e++ = 'z';
1256 count -= 26;
1257 }
1258 if (c != CELL_MIRROR_L && c != CELL_MIRROR_R) {
1259 count++;
1260 }
1261 else if (c == CELL_MIRROR_L) {
1262 if (count > 0) *e++ = (count-1 + 'a');
1263 *e++ = 'L';
1264 count = 0;
1265 }
1266 else {
1267 if (count > 0) *e++ = (count-1 + 'a');
1268 *e++ = 'R';
1269 count = 0;
1270 }
1271 }
1272 if (count > 0) *e++ = (count-1 + 'a');
1273
1274 /* Encode hints */
1275 for (p=0;p<2*(new->common->params.w + new->common->params.h);p++) {
1276 range2grid(p,new->common->params.w,new->common->params.h,&x,&y);
1277 e += sprintf(e, ",%d", new->common->grid[x+y*(new->common->params.w+2)]);
1278 }
1279
1280 *e++ = '\0';
1281 desc = sresize(desc, e - desc, char);
1282
1283 sfree(old_guess);
1284 free_game(new);
1285
1286 return desc;
1287 }
1288
1289 void num2grid(int num, int width, int height, int *x, int *y) {
1290 *x = 1+(num%width);
1291 *y = 1+(num/width);
1292 return;
1293 }
1294
1295 static game_state *new_game(midend *me, game_params *params, char *desc) {
1296 int i;
1297 int n;
1298 int count;
1299
1300 game_state *state = new_state(params);
1301
1302 state->common->num_ghosts = atoi(desc);
1303 while (*desc && isdigit((unsigned char)*desc)) desc++;
1304 desc++;
1305 state->common->num_vampires = atoi(desc);
1306 while (*desc && isdigit((unsigned char)*desc)) desc++;
1307 desc++;
1308 state->common->num_zombies = atoi(desc);
1309 while (*desc && isdigit((unsigned char)*desc)) desc++;
1310 desc++;
1311
1312 state->common->num_total = state->common->num_ghosts + state->common->num_vampires + state->common->num_zombies;
1313
1314 state->guess = snewn(state->common->num_total,int);
1315 state->pencils = snewn(state->common->num_total,unsigned char);
1316 state->common->fixed = snewn(state->common->num_total,int);
1317 for (i=0;i<state->common->num_total;i++) {
1318 state->guess[i] = 7;
1319 state->pencils[i] = 0;
1320 state->common->fixed[i] = FALSE;
1321 }
1322 for (i=0;i<state->common->wh;i++)
1323 state->cell_errors[i] = FALSE;
1324 for (i=0;i<2*state->common->num_paths;i++)
1325 state->hint_errors[i] = FALSE;
1326 for (i=0;i<3;i++)
1327 state->count_errors[i] = FALSE;
1328
1329 count = 0;
1330 n = 0;
1331 while (*desc != ',') {
1332 int c;
1333 int x,y;
1334
1335 if (*desc == 'L') {
1336 num2grid(n,state->common->params.w,state->common->params.h,&x,&y);
1337 state->common->grid[x+y*(state->common->params.w +2)] = CELL_MIRROR_L;
1338 state->common->xinfo[x+y*(state->common->params.w+2)] = -1;
1339 n++;
1340 }
1341 else if (*desc == 'R') {
1342 num2grid(n,state->common->params.w,state->common->params.h,&x,&y);
1343 state->common->grid[x+y*(state->common->params.w +2)] = CELL_MIRROR_R;
1344 state->common->xinfo[x+y*(state->common->params.w+2)] = -1;
1345 n++;
1346 }
1347 else if (*desc == 'G') {
1348 num2grid(n,state->common->params.w,state->common->params.h,&x,&y);
1349 state->common->grid[x+y*(state->common->params.w +2)] = CELL_GHOST;
1350 state->common->xinfo[x+y*(state->common->params.w+2)] = count;
1351 state->guess[count] = 1;
1352 state->common->fixed[count++] = TRUE;
1353 n++;
1354 }
1355 else if (*desc == 'V') {
1356 num2grid(n,state->common->params.w,state->common->params.h,&x,&y);
1357 state->common->grid[x+y*(state->common->params.w +2)] = CELL_VAMPIRE;
1358 state->common->xinfo[x+y*(state->common->params.w+2)] = count;
1359 state->guess[count] = 2;
1360 state->common->fixed[count++] = TRUE;
1361 n++;
1362 }
1363 else if (*desc == 'Z') {
1364 num2grid(n,state->common->params.w,state->common->params.h,&x,&y);
1365 state->common->grid[x+y*(state->common->params.w +2)] = CELL_ZOMBIE;
1366 state->common->xinfo[x+y*(state->common->params.w+2)] = count;
1367 state->guess[count] = 4;
1368 state->common->fixed[count++] = TRUE;
1369 n++;
1370 }
1371 else {
1372 c = *desc - ('a' -1);
1373 while (c-- > 0) {
1374 num2grid(n,state->common->params.w,state->common->params.h,&x,&y);
1375 state->common->grid[x+y*(state->common->params.w +2)] = CELL_EMPTY;
1376 state->common->xinfo[x+y*(state->common->params.w+2)] = count;
1377 state->guess[count] = 7;
1378 state->common->fixed[count++] = FALSE;
1379 n++;
1380 }
1381 }
1382 desc++;
1383 }
1384 desc++;
1385
1386 for (i=0;i<2*(state->common->params.w + state->common->params.h);i++) {
1387 int x,y;
1388 int sights;
1389
1390 sights = atoi(desc);
1391 while (*desc && isdigit((unsigned char)*desc)) desc++;
1392 desc++;
1393
1394
1395 range2grid(i,state->common->params.w,state->common->params.h,&x,&y);
1396 state->common->grid[x+y*(state->common->params.w +2)] = sights;
1397 state->common->xinfo[x+y*(state->common->params.w +2)] = -2;
1398 }
1399
1400 state->common->grid[0] = 0;
1401 state->common->xinfo[0] = -2;
1402 state->common->grid[state->common->params.w+1] = 0;
1403 state->common->xinfo[state->common->params.w+1] = -2;
1404 state->common->grid[state->common->params.w+1 + (state->common->params.h+1)*(state->common->params.w+2)] = 0;
1405 state->common->xinfo[state->common->params.w+1 + (state->common->params.h+1)*(state->common->params.w+2)] = -2;
1406 state->common->grid[(state->common->params.h+1)*(state->common->params.w+2)] = 0;
1407 state->common->xinfo[(state->common->params.h+1)*(state->common->params.w+2)] = -2;
1408
1409 make_paths(state);
1410 qsort(state->common->paths, state->common->num_paths, sizeof(struct path), path_cmp);
1411
1412 return state;
1413 }
1414
1415 static char *validate_desc(game_params *params, char *desc) {
1416 int i;
1417 int w = params->w, h = params->h;
1418 int wh = w*h;
1419 int area;
1420 int monsters;
1421 int monster_count;
1422 char *desc_s = desc;
1423
1424 for (i=0;i<3;i++) {
1425 if (!*desc) return "Faulty game description";
1426 while (*desc && isdigit((unsigned char)*desc)) { desc++; }
1427 if (*desc != ',') return "Invalid character in number list";
1428 desc++;
1429 }
1430 desc = desc_s;
1431
1432 area = monsters = monster_count = 0;
1433 for (i=0;i<3;i++) {
1434 monster_count += atoi(desc);
1435 while (*desc && isdigit((unsigned char)*desc)) desc++;
1436 desc++;
1437 }
1438 while (*desc && *desc != ',') {
1439 if (*desc >= 'a' && *desc <= 'z') {
1440 area += *desc - 'a' +1; monsters += *desc - 'a' +1;
1441 } else if (*desc == 'G' || *desc == 'V' || *desc == 'Z') {
1442 area++; monsters++;
1443 } else if (*desc == 'L' || *desc == 'R') {
1444 area++;
1445 } else
1446 return "Invalid character in grid specification";
1447 desc++;
1448 }
1449 if (area < wh) return "Not enough data to fill grid";
1450 else if (area > wh) return "Too much data to fill grid";
1451 if (monsters != monster_count)
1452 return "Monster numbers do not match grid spaces";
1453
1454 for (i = 0; i < 2*(w+h); i++) {
1455 if (!*desc) return "Not enough numbers given after grid specification";
1456 else if (*desc != ',') return "Invalid character in number list";
1457 desc++;
1458 while (*desc && isdigit((unsigned char)*desc)) { desc++; }
1459 }
1460
1461 if (*desc) return "Unexpected additional data at end of game description";
1462
1463 return NULL;
1464 }
1465
1466 static char *solve_game(game_state *state_start, game_state *currstate, char *aux, char **error) {
1467 int p;
1468 int *old_guess;
1469 int iterative_depth;
1470 int solved_iterative, solved_bruteforce, contains_inconsistency,
1471 count_ambiguous;
1472
1473 int i;
1474 char *move, *c;
1475
1476 game_state *solve_state = dup_game(currstate);
1477
1478 old_guess = snewn(solve_state->common->num_total,int);
1479 for (p=0;p<solve_state->common->num_total;p++) {
1480 if (solve_state->common->fixed[p]) {
1481 old_guess[p] = solve_state->guess[p] = state_start->guess[p];
1482 }
1483 else {
1484 old_guess[p] = solve_state->guess[p] = 7;
1485 }
1486 }
1487 iterative_depth = 0;
1488 solved_iterative = FALSE;
1489 contains_inconsistency = FALSE;
1490 count_ambiguous = 0;
1491
1492 /* Try to solve the puzzle with the iterative solver */
1493 while (TRUE) {
1494 int no_change;
1495 no_change = TRUE;
1496 solved_iterative =
1497 solve_iterative(solve_state,solve_state->common->paths);
1498 iterative_depth++;
1499 for (p=0;p<solve_state->common->num_total;p++) {
1500 if (solve_state->guess[p] != old_guess[p]) no_change = FALSE;
1501 old_guess[p] = solve_state->guess[p];
1502 if (solve_state->guess[p] == 0) contains_inconsistency = TRUE;
1503 }
1504 if (solved_iterative || no_change || contains_inconsistency) break;
1505 }
1506
1507 if (contains_inconsistency) {
1508 *error = "Puzzle is inconsistent";
1509 sfree(old_guess);
1510 free_game(solve_state);
1511 return NULL;
1512 }
1513
1514 /* If necessary, try to solve the puzzle with the brute-force solver */
1515 solved_bruteforce = FALSE;
1516 if (!solved_iterative) {
1517 for (p=0;p<solve_state->common->num_total;p++)
1518 if (solve_state->guess[p] != 1 && solve_state->guess[p] != 2 &&
1519 solve_state->guess[p] != 4) count_ambiguous++;
1520 solved_bruteforce =
1521 solve_bruteforce(solve_state, solve_state->common->paths);
1522 }
1523
1524 if (!solved_iterative && !solved_bruteforce) {
1525 *error = "Puzzle is unsolvable";
1526 sfree(old_guess);
1527 free_game(solve_state);
1528 return NULL;
1529 }
1530
1531 /* printf("Puzzle solved at level %s, iterations %d, ambiguous %d\n", (solved_bruteforce ? "TRICKY" : "NORMAL"), iterative_depth, count_ambiguous); */
1532
1533 move = snewn(solve_state->common->num_total * 4 +2, char);
1534 c = move;
1535 *c++='S';
1536 for (i = 0; i < solve_state->common->num_total; i++) {
1537 if (solve_state->guess[i] == 1) c += sprintf(c, ";G%d", i);
1538 if (solve_state->guess[i] == 2) c += sprintf(c, ";V%d", i);
1539 if (solve_state->guess[i] == 4) c += sprintf(c, ";Z%d", i);
1540 }
1541 *c++ = '\0';
1542 move = sresize(move, c - move, char);
1543
1544 sfree(old_guess);
1545 free_game(solve_state);
1546 return move;
1547 }
1548
1549 static int game_can_format_as_text_now(game_params *params) {
1550 return TRUE;
1551 }
1552
1553 static char *game_text_format(game_state *state) {
1554 int w,h,c,r,xi,g;
1555 char *ret;
1556 char buf[120];
1557
1558 ret = snewn(50 + 6*(state->common->params.w +2) +
1559 6*(state->common->params.h+2) +
1560 3*(state->common->params.w * state->common->params.h), char);
1561
1562 sprintf(ret,"G: %d V: %d Z: %d\n\n",state->common->num_ghosts,
1563 state->common->num_vampires, state->common->num_zombies);
1564
1565 for (h=0;h<state->common->params.h+2;h++) {
1566 for (w=0;w<state->common->params.w+2;w++) {
1567 c = state->common->grid[w+h*(state->common->params.w+2)];
1568 xi = state->common->xinfo[w+h*(state->common->params.w+2)];
1569 r = grid2range(w,h,state->common->params.w,state->common->params.h);
1570 if (r != -1) {
1571 sprintf(buf,"%2d", c); strcat(ret,buf);
1572 } else if (c == CELL_MIRROR_L) {
1573 sprintf(buf," \\"); strcat(ret,buf);
1574 } else if (c == CELL_MIRROR_R) {
1575 sprintf(buf," /"); strcat(ret,buf);
1576 } else if (xi >= 0) {
1577 g = state->guess[xi];
1578 if (g == 1) { sprintf(buf," G"); strcat(ret,buf); }
1579 else if (g == 2) { sprintf(buf," V"); strcat(ret,buf); }
1580 else if (g == 4) { sprintf(buf," Z"); strcat(ret,buf); }
1581 else { sprintf(buf," ."); strcat(ret,buf); }
1582 } else {
1583 sprintf(buf," "); strcat(ret,buf);
1584 }
1585 }
1586 sprintf(buf,"\n"); strcat(ret,buf);
1587 }
1588
1589 return ret;
1590 }
1591
1592 struct game_ui {
1593 int hx, hy; /* as for solo.c, highlight pos */
1594 int hshow, hpencil, hcursor; /* show state, type, and ?cursor. */
1595 int ascii;
1596 };
1597
1598 static game_ui *new_ui(game_state *state) {
1599 game_ui *ui = snew(game_ui);
1600 ui->hx = ui->hy = 0;
1601 ui->hpencil = ui->hshow = ui->hcursor = 0;
1602 ui->ascii = FALSE;
1603 return ui;
1604 }
1605
1606 static void free_ui(game_ui *ui) {
1607 sfree(ui);
1608 return;
1609 }
1610
1611 static char *encode_ui(game_ui *ui) {
1612 return NULL;
1613 }
1614
1615 static void decode_ui(game_ui *ui, char *encoding) {
1616 return;
1617 }
1618
1619 static void game_changed_state(game_ui *ui, game_state *oldstate, game_state *newstate) {
1620 /* See solo.c; if we were pencil-mode highlighting and
1621 * somehow a square has just been properly filled, cancel
1622 * pencil mode. */
1623 if (ui->hshow && ui->hpencil && !ui->hcursor) {
1624 int g = newstate->guess[newstate->common->xinfo[ui->hx + ui->hy*(newstate->common->params.w+2)]];
1625 if (g == 1 || g == 2 || g == 4)
1626 ui->hshow = 0;
1627 }
1628 }
1629
1630 struct game_drawstate {
1631 int tilesize, started, solved;
1632 int w, h;
1633
1634 int *monsters;
1635 unsigned char *pencils;
1636
1637 unsigned char count_errors[3];
1638 unsigned char *cell_errors;
1639 unsigned char *hint_errors;
1640
1641 int hx, hy, hshow, hpencil; /* as for game_ui. */
1642 int hflash;
1643 int ascii;
1644 };
1645
1646 #define TILESIZE (ds->tilesize)
1647 #define BORDER (TILESIZE/2)
1648
1649 static char *interpret_move(game_state *state, game_ui *ui,
1650 const game_drawstate *ds, int x, int y, int button)
1651 {
1652 int gx,gy;
1653 int g,xi;
1654 char buf[80];
1655
1656 gx = ((x-BORDER-1) / TILESIZE );
1657 gy = ((y-BORDER-2) / TILESIZE ) - 1;
1658
1659 if (button == 'a' || button == 'A') {
1660 ui->ascii = !ui->ascii;
1661 return "";
1662 }
1663
1664 if (ui->hshow == 1 && ui->hpencil == 0) {
1665 xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)];
1666 if (xi >= 0 && !state->common->fixed[xi]) {
1667 if (button == 'g' || button == 'G' || button == '1') {
1668 if (!ui->hcursor) ui->hshow = 0;
1669 sprintf(buf,"G%d",xi);
1670 return dupstr(buf);
1671 }
1672 if (button == 'v' || button == 'V' || button == '2') {
1673 if (!ui->hcursor) ui->hshow = 0;
1674 sprintf(buf,"V%d",xi);
1675 return dupstr(buf);
1676 }
1677 if (button == 'z' || button == 'Z' || button == '3') {
1678 if (!ui->hcursor) ui->hshow = 0;
1679 sprintf(buf,"Z%d",xi);
1680 return dupstr(buf);
1681 }
1682 if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 ||
1683 button == '0' || button == '\b' ) {
1684 if (!ui->hcursor) ui->hshow = 0;
1685 sprintf(buf,"E%d",xi);
1686 return dupstr(buf);
1687 }
1688 }
1689 }
1690
1691 if (IS_CURSOR_MOVE(button)) {
1692 if (ui->hx == 0 && ui->hy == 0) {
1693 ui->hx = 1;
1694 ui->hy = 1;
1695 }
1696 else switch (button) {
1697 case CURSOR_UP: ui->hy -= (ui->hy > 1) ? 1 : 0; break;
1698 case CURSOR_DOWN: ui->hy += (ui->hy < ds->h) ? 1 : 0; break;
1699 case CURSOR_RIGHT: ui->hx += (ui->hx < ds->w) ? 1 : 0; break;
1700 case CURSOR_LEFT: ui->hx -= (ui->hx > 1) ? 1 : 0; break;
1701 }
1702 ui->hshow = ui->hcursor = 1;
1703 return "";
1704 }
1705 if (ui->hshow && button == CURSOR_SELECT) {
1706 ui->hpencil = 1 - ui->hpencil;
1707 ui->hcursor = 1;
1708 return "";
1709 }
1710
1711 if (ui->hshow == 1 && ui->hpencil == 1) {
1712 xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)];
1713 if (xi >= 0 && !state->common->fixed[xi]) {
1714 if (button == 'g' || button == 'G' || button == '1') {
1715 sprintf(buf,"g%d",xi);
1716 ui->hpencil = ui->hshow = 0;
1717 return dupstr(buf);
1718 }
1719 if (button == 'v' || button == 'V' || button == '2') {
1720 sprintf(buf,"v%d",xi);
1721 ui->hpencil = ui->hshow = 0;
1722 return dupstr(buf);
1723 }
1724 if (button == 'z' || button == 'Z' || button == '3') {
1725 sprintf(buf,"z%d",xi);
1726 ui->hpencil = ui->hshow = 0;
1727 return dupstr(buf);
1728 }
1729 if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 ||
1730 button == '0' || button == '\b') {
1731 if (!ui->hcursor) ui->hshow = 0;
1732 sprintf(buf,"E%d",xi);
1733 ui->hpencil = ui->hshow = 0;
1734 return dupstr(buf);
1735 }
1736 }
1737 }
1738
1739 if (gx > 0 && gx < ds->w+1 && gy > 0 && gy < ds->h+1) {
1740 xi = state->common->xinfo[gx+gy*(state->common->params.w+2)];
1741 if (xi >= 0 && !state->common->fixed[xi]) {
1742 g = state->guess[xi];
1743 if (ui->hshow == 0) {
1744 if (button == LEFT_BUTTON) {
1745 ui->hshow = 1; ui->hpencil = 0; ui->hcursor = 0;
1746 ui->hx = gx; ui->hy = gy;
1747 return "";
1748 }
1749 else if (button == RIGHT_BUTTON && g == 7) {
1750 ui->hshow = 1; ui->hpencil = 1; ui->hcursor = 0;
1751 ui->hx = gx; ui->hy = gy;
1752 return "";
1753 }
1754 }
1755 else if (ui->hshow == 1) {
1756 if (button == LEFT_BUTTON) {
1757 if (ui->hpencil == 0) {
1758 if (gx == ui->hx && gy == ui->hy) {
1759 ui->hshow = 0; ui->hpencil = 0; ui->hcursor = 0;
1760 ui->hx = 0; ui->hy = 0;
1761 return "";
1762 }
1763 else {
1764 ui->hshow = 1; ui->hpencil = 0; ui->hcursor = 0;
1765 ui->hx = gx; ui->hy = gy;
1766 return "";
1767 }
1768 }
1769 else {
1770 ui->hshow = 1; ui->hpencil = 0; ui->hcursor = 0;
1771 ui->hx = gx; ui->hy = gy;
1772 return "";
1773 }
1774 }
1775 else if (button == RIGHT_BUTTON) {
1776 if (ui->hpencil == 0 && g == 7) {
1777 ui->hshow = 1; ui->hpencil = 1; ui->hcursor = 0;
1778 ui->hx = gx; ui->hy = gy;
1779 return "";
1780 }
1781 else {
1782 if (gx == ui->hx && gy == ui->hy) {
1783 ui->hshow = 0; ui->hpencil = 0; ui->hcursor = 0;
1784 ui->hx = 0; ui->hy = 0;
1785 return "";
1786 }
1787 else if (g == 7) {
1788 ui->hshow = 1; ui->hpencil = 1; ui->hcursor = 0;
1789 ui->hx = gx; ui->hy = gy;
1790 return "";
1791 }
1792 }
1793 }
1794 }
1795 }
1796 }
1797
1798 return NULL;
1799 }
1800
1801 int check_numbers_draw(game_state *state, int *guess) {
1802 int valid, filled;
1803 int i,x,y,xy;
1804 int count_ghosts, count_vampires, count_zombies;
1805
1806 count_ghosts = count_vampires = count_zombies = 0;
1807 for (i=0;i<state->common->num_total;i++) {
1808 if (guess[i] == 1) count_ghosts++;
1809 if (guess[i] == 2) count_vampires++;
1810 if (guess[i] == 4) count_zombies++;
1811 }
1812
1813 valid = TRUE;
1814 filled = (count_ghosts + count_vampires + count_zombies >=
1815 state->common->num_total);
1816
1817 if (count_ghosts > state->common->num_ghosts ||
1818 (filled && count_ghosts != state->common->num_ghosts) ) {
1819 valid = FALSE;
1820 state->count_errors[0] = TRUE;
1821 for (x=1;x<state->common->params.w+1;x++)
1822 for (y=1;y<state->common->params.h+1;y++) {
1823 xy = x+y*(state->common->params.w+2);
1824 if (state->common->xinfo[xy] >= 0 &&
1825 guess[state->common->xinfo[xy]] == 1)
1826 state->cell_errors[xy] = TRUE;
1827 }
1828 }
1829 if (count_vampires > state->common->num_vampires ||
1830 (filled && count_vampires != state->common->num_vampires) ) {
1831 valid = FALSE;
1832 state->count_errors[1] = TRUE;
1833 for (x=1;x<state->common->params.w+1;x++)
1834 for (y=1;y<state->common->params.h+1;y++) {
1835 xy = x+y*(state->common->params.w+2);
1836 if (state->common->xinfo[xy] >= 0 &&
1837 guess[state->common->xinfo[xy]] == 2)
1838 state->cell_errors[xy] = TRUE;
1839 }
1840 }
1841 if (count_zombies > state->common->num_zombies ||
1842 (filled && count_zombies != state->common->num_zombies) ) {
1843 valid = FALSE;
1844 state->count_errors[2] = TRUE;
1845 for (x=1;x<state->common->params.w+1;x++)
1846 for (y=1;y<state->common->params.h+1;y++) {
1847 xy = x+y*(state->common->params.w+2);
1848 if (state->common->xinfo[xy] >= 0 &&
1849 guess[state->common->xinfo[xy]] == 4)
1850 state->cell_errors[xy] = TRUE;
1851 }
1852 }
1853
1854 return valid;
1855 }
1856
1857 int check_path_solution(game_state *state, int p) {
1858 int i;
1859 int mirror;
1860 int count;
1861 int correct;
1862 int unfilled;
1863
1864 count = 0;
1865 mirror = FALSE;
1866 correct = TRUE;
1867
1868 unfilled = 0;
1869 for (i=0;i<state->common->paths[p].length;i++) {
1870 if (state->common->paths[p].p[i] == -1) mirror = TRUE;
1871 else {
1872 if (state->guess[state->common->paths[p].p[i]] == 1 && mirror)
1873 count++;
1874 else if (state->guess[state->common->paths[p].p[i]] == 2 && !mirror)
1875 count++;
1876 else if (state->guess[state->common->paths[p].p[i]] == 4)
1877 count++;
1878 else if (state->guess[state->common->paths[p].p[i]] == 7)
1879 unfilled++;
1880 }
1881 }
1882
1883 if (unfilled == 0 && count != state->common->paths[p].sightings_start) {
1884 correct = FALSE;
1885 state->hint_errors[state->common->paths[p].grid_start] = TRUE;
1886 }
1887
1888 count = 0;
1889 mirror = FALSE;
1890 unfilled = 0;
1891 for (i=state->common->paths[p].length-1;i>=0;i--) {
1892 if (state->common->paths[p].p[i] == -1) mirror = TRUE;
1893 else {
1894 if (state->guess[state->common->paths[p].p[i]] == 1 && mirror)
1895 count++;
1896 else if (state->guess[state->common->paths[p].p[i]] == 2 && !mirror)
1897 count++;
1898 else if (state->guess[state->common->paths[p].p[i]] == 4)
1899 count++;
1900 else if (state->guess[state->common->paths[p].p[i]] == 7)
1901 unfilled++;
1902 }
1903 }
1904
1905 if (unfilled == 0 && count != state->common->paths[p].sightings_end) {
1906 correct = FALSE;
1907 state->hint_errors[state->common->paths[p].grid_end] = TRUE;
1908 }
1909
1910 if (!correct) {
1911 for (i=0;i<state->common->paths[p].length;i++)
1912 state->cell_errors[state->common->paths[p].xy[i]] = TRUE;
1913 }
1914
1915 return correct;
1916 }
1917
1918 static game_state *execute_move(game_state *state, char *move) {
1919 int x,n,p,i;
1920 char c;
1921 int correct;
1922 int solver;
1923
1924 game_state *ret = dup_game(state);
1925 solver = FALSE;
1926
1927 while (*move) {
1928 c = *move;
1929 if (c == 'S') {
1930 move++;
1931 solver = TRUE;
1932 }
1933 if (c == 'G' || c == 'V' || c == 'Z' || c == 'E' ||
1934 c == 'g' || c == 'v' || c == 'z') {
1935 move++;
1936 sscanf(move, "%d%n", &x, &n);
1937 if (c == 'G') ret->guess[x] = 1;
1938 if (c == 'V') ret->guess[x] = 2;
1939 if (c == 'Z') ret->guess[x] = 4;
1940 if (c == 'E') { ret->guess[x] = 7; ret->pencils[x] = 0; }
1941 if (c == 'g') ret->pencils[x] ^= 1;
1942 if (c == 'v') ret->pencils[x] ^= 2;
1943 if (c == 'z') ret->pencils[x] ^= 4;
1944 move += n;
1945 }
1946 if (*move == ';') move++;
1947 }
1948
1949 correct = TRUE;
1950
1951 for (i=0;i<ret->common->wh;i++) ret->cell_errors[i] = FALSE;
1952 for (i=0;i<2*ret->common->num_paths;i++) ret->hint_errors[i] = FALSE;
1953 for (i=0;i<3;i++) ret->count_errors[i] = FALSE;
1954
1955 if (!check_numbers_draw(ret,ret->guess)) correct = FALSE;
1956
1957 for (p=0;p<state->common->num_paths;p++)
1958 if (!check_path_solution(ret,p)) correct = FALSE;
1959
1960 for (i=0;i<state->common->num_total;i++)
1961 if (!(ret->guess[i] == 1 || ret->guess[i] == 2 ||
1962 ret->guess[i] == 4)) correct = FALSE;
1963
1964 if (correct && !solver) ret->solved = TRUE;
1965 if (solver) ret->cheated = TRUE;
1966
1967 return ret;
1968 }
1969
1970 /* ----------------------------------------------------------------------
1971 * Drawing routines.
1972 */
1973
1974 #define PREFERRED_TILE_SIZE 64
1975
1976 static void game_compute_size(game_params *params, int tilesize,
1977 int *x, int *y) {
1978 *x = tilesize + (2 + params->w) * tilesize;
1979 *y = tilesize + (3 + params->h) * tilesize;
1980 return;
1981 }
1982
1983 static void game_set_size(drawing *dr, game_drawstate *ds,
1984 game_params *params, int tilesize) {
1985 ds->tilesize = tilesize;
1986 return;
1987 }
1988
1989 #define COLOUR(ret, i, r, g, b) ((ret[3*(i)+0] = (r)), (ret[3*(i)+1] = (g)), (ret[3*(i)+2] = (b)))
1990
1991 static float *game_colours(frontend *fe, int *ncolours) {
1992 float *ret = snewn(3 * NCOLOURS, float);
1993
1994 frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
1995
1996 ret[COL_GRID * 3 + 0] = 0.0F;
1997 ret[COL_GRID * 3 + 1] = 0.0F;
1998 ret[COL_GRID * 3 + 2] = 0.0F;
1999
2000 ret[COL_TEXT * 3 + 0] = 0.0F;
2001 ret[COL_TEXT * 3 + 1] = 0.0F;
2002 ret[COL_TEXT * 3 + 2] = 0.0F;
2003
2004 ret[COL_ERROR * 3 + 0] = 1.0F;
2005 ret[COL_ERROR * 3 + 1] = 0.0F;
2006 ret[COL_ERROR * 3 + 2] = 0.0F;
2007
2008 ret[COL_HIGHLIGHT * 3 + 0] = 0.78F * ret[COL_BACKGROUND * 3 + 0];
2009 ret[COL_HIGHLIGHT * 3 + 1] = 0.78F * ret[COL_BACKGROUND * 3 + 1];
2010 ret[COL_HIGHLIGHT * 3 + 2] = 0.78F * ret[COL_BACKGROUND * 3 + 2];
2011
2012 ret[COL_FLASH * 3 + 0] = 1.0F;
2013 ret[COL_FLASH * 3 + 1] = 1.0F;
2014 ret[COL_FLASH * 3 + 2] = 1.0F;
2015
2016 ret[COL_GHOST * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] * 0.5F;
2017 ret[COL_GHOST * 3 + 1] = ret[COL_BACKGROUND * 3 + 0];
2018 ret[COL_GHOST * 3 + 2] = ret[COL_BACKGROUND * 3 + 0];
2019
2020 ret[COL_ZOMBIE * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] * 0.5F;
2021 ret[COL_ZOMBIE * 3 + 1] = ret[COL_BACKGROUND * 3 + 0];
2022 ret[COL_ZOMBIE * 3 + 2] = ret[COL_BACKGROUND * 3 + 0] * 0.5F;
2023
2024 ret[COL_VAMPIRE * 3 + 0] = ret[COL_BACKGROUND * 3 + 0];
2025 ret[COL_VAMPIRE * 3 + 1] = ret[COL_BACKGROUND * 3 + 0] * 0.9F;
2026 ret[COL_VAMPIRE * 3 + 2] = ret[COL_BACKGROUND * 3 + 0] * 0.9F;
2027
2028 *ncolours = NCOLOURS;
2029 return ret;
2030 }
2031
2032 static game_drawstate *game_new_drawstate(drawing *dr, game_state *state) {
2033 int i;
2034 struct game_drawstate *ds = snew(struct game_drawstate);
2035
2036 ds->tilesize = 0;
2037 ds->started = ds->solved = FALSE;
2038 ds->w = state->common->params.w;
2039 ds->h = state->common->params.h;
2040 ds->ascii = FALSE;
2041
2042 ds->count_errors[0] = FALSE;
2043 ds->count_errors[1] = FALSE;
2044 ds->count_errors[2] = FALSE;
2045
2046 ds->monsters = snewn(state->common->num_total,int);
2047 for (i=0;i<(state->common->num_total);i++)
2048 ds->monsters[i] = 7;
2049 ds->pencils = snewn(state->common->num_total,unsigned char);
2050 for (i=0;i<state->common->num_total;i++)
2051 ds->pencils[i] = 0;
2052
2053 ds->cell_errors = snewn(state->common->wh,unsigned char);
2054 for (i=0;i<state->common->wh;i++)
2055 ds->cell_errors[i] = FALSE;
2056 ds->hint_errors = snewn(2*state->common->num_paths,unsigned char);
2057 for (i=0;i<2*state->common->num_paths;i++)
2058 ds->hint_errors[i] = FALSE;
2059
2060 ds->hshow = ds->hpencil = ds->hflash = 0;
2061 ds->hx = ds->hy = 0;
2062 return ds;
2063 }
2064
2065 static void game_free_drawstate(drawing *dr, game_drawstate *ds) {
2066 sfree(ds->hint_errors);
2067 sfree(ds->cell_errors);
2068 sfree(ds->pencils);
2069 sfree(ds->monsters);
2070 sfree(ds);
2071 return;
2072 }
2073
2074 static void draw_cell_background(drawing *dr, game_drawstate *ds,
2075 game_state *state, game_ui *ui, int x, int y) {
2076
2077 int hon;
2078 int dx,dy;
2079 dx = BORDER+(x* ds->tilesize)+(TILESIZE/2);
2080 dy = BORDER+(y* ds->tilesize)+(TILESIZE/2)+TILESIZE;
2081
2082 hon = (ui->hshow && x == ui->hx && y == ui->hy);
2083 draw_rect(dr,dx-(TILESIZE/2)+1,dy-(TILESIZE/2)+1,TILESIZE-1,TILESIZE-1,(hon && !ui->hpencil) ? COL_HIGHLIGHT : COL_BACKGROUND);
2084
2085 if (hon && ui->hpencil) {
2086 int coords[6];
2087 coords[0] = dx-(TILESIZE/2)+1;
2088 coords[1] = dy-(TILESIZE/2)+1;
2089 coords[2] = coords[0] + TILESIZE/2;
2090 coords[3] = coords[1];
2091 coords[4] = coords[0];
2092 coords[5] = coords[1] + TILESIZE/2;
2093 draw_polygon(dr, coords, 3, COL_HIGHLIGHT, COL_HIGHLIGHT);
2094 }
2095
2096 draw_update(dr,dx-(TILESIZE/2)+1,dy-(TILESIZE/2)+1,TILESIZE-1,TILESIZE-1);
2097
2098 return;
2099 }
2100
2101 static void draw_circle_or_point(drawing *dr, int cx, int cy, int radius,
2102 int colour)
2103 {
2104 if (radius > 0)
2105 draw_circle(dr, cx, cy, radius, colour, colour);
2106 else
2107 draw_rect(dr, cx, cy, 1, 1, colour);
2108 }
2109
2110 static void draw_monster(drawing *dr, game_drawstate *ds, int x, int y,
2111 int tilesize, int hflash, int monster)
2112 {
2113 int black = (hflash ? COL_FLASH : COL_TEXT);
2114
2115 if (monster == 1) { /* ghost */
2116 int poly[80], i, j;
2117
2118 clip(dr,x-(tilesize/2)+2,y-(tilesize/2)+2,tilesize-3,tilesize/2+1);
2119 draw_circle(dr,x,y,2*tilesize/5, COL_GHOST,black);
2120 unclip(dr);
2121
2122 i = 0;
2123 poly[i++] = x - 2*tilesize/5;
2124 poly[i++] = y-2;
2125 poly[i++] = x - 2*tilesize/5;
2126 poly[i++] = y + 2*tilesize/5;
2127
2128 for (j = 0; j < 3; j++) {
2129 int total = (2*tilesize/5) * 2;
2130 int before = total * j / 3;
2131 int after = total * (j+1) / 3;
2132 int mid = (before + after) / 2;
2133 poly[i++] = x - 2*tilesize/5 + mid;
2134 poly[i++] = y + 2*tilesize/5 - (total / 6);
2135 poly[i++] = x - 2*tilesize/5 + after;
2136 poly[i++] = y + 2*tilesize/5;
2137 }
2138
2139 poly[i++] = x + 2*tilesize/5;
2140 poly[i++] = y-2;
2141
2142 clip(dr,x-(tilesize/2)+2,y,tilesize-3,tilesize-(tilesize/2)-1);
2143 draw_polygon(dr, poly, i/2, COL_GHOST, black);
2144 unclip(dr);
2145
2146 draw_circle(dr,x-tilesize/6,y-tilesize/12,tilesize/10,
2147 COL_BACKGROUND,black);
2148 draw_circle(dr,x+tilesize/6,y-tilesize/12,tilesize/10,
2149 COL_BACKGROUND,black);
2150
2151 draw_circle_or_point(dr,x-tilesize/6+1+tilesize/48,y-tilesize/12,
2152 tilesize/48,black);
2153 draw_circle_or_point(dr,x+tilesize/6+1+tilesize/48,y-tilesize/12,
2154 tilesize/48,black);
2155
2156 } else if (monster == 2) { /* vampire */
2157 int poly[80], i;
2158
2159 clip(dr,x-(tilesize/2)+2,y-(tilesize/2)+2,tilesize-3,tilesize/2);
2160 draw_circle(dr,x,y,2*tilesize/5,black,black);
2161 unclip(dr);
2162
2163 clip(dr,x-(tilesize/2)+2,y-(tilesize/2)+2,tilesize/2+1,tilesize/2);
2164 draw_circle(dr,x-tilesize/7,y,2*tilesize/5-tilesize/7,
2165 COL_VAMPIRE,black);
2166 unclip(dr);
2167 clip(dr,x,y-(tilesize/2)+2,tilesize/2+1,tilesize/2);
2168 draw_circle(dr,x+tilesize/7,y,2*tilesize/5-tilesize/7,
2169 COL_VAMPIRE,black);
2170 unclip(dr);
2171
2172 clip(dr,x-(tilesize/2)+2,y,tilesize-3,tilesize/2);
2173 draw_circle(dr,x,y,2*tilesize/5, COL_VAMPIRE,black);
2174 unclip(dr);
2175
2176 draw_circle(dr, x-tilesize/7, y-tilesize/16, tilesize/16,
2177 COL_BACKGROUND, black);
2178 draw_circle(dr, x+tilesize/7, y-tilesize/16, tilesize/16,
2179 COL_BACKGROUND, black);
2180 draw_circle_or_point(dr, x-tilesize/7, y-tilesize/16, tilesize/48,
2181 black);
2182 draw_circle_or_point(dr, x+tilesize/7, y-tilesize/16, tilesize/48,
2183 black);
2184
2185 clip(dr, x-(tilesize/2)+2, y+tilesize/8, tilesize-3, tilesize/4);
2186
2187 i = 0;
2188 poly[i++] = x-3*tilesize/16;
2189 poly[i++] = y+1*tilesize/8;
2190 poly[i++] = x-2*tilesize/16;
2191 poly[i++] = y+7*tilesize/24;
2192 poly[i++] = x-1*tilesize/16;
2193 poly[i++] = y+1*tilesize/8;
2194 draw_polygon(dr, poly, i/2, COL_BACKGROUND, black);
2195 i = 0;
2196 poly[i++] = x+3*tilesize/16;
2197 poly[i++] = y+1*tilesize/8;
2198 poly[i++] = x+2*tilesize/16;
2199 poly[i++] = y+7*tilesize/24;
2200 poly[i++] = x+1*tilesize/16;
2201 poly[i++] = y+1*tilesize/8;
2202 draw_polygon(dr, poly, i/2, COL_BACKGROUND, black);
2203
2204 draw_circle(dr, x, y-tilesize/5, 2*tilesize/5, COL_VAMPIRE, black);
2205 unclip(dr);
2206
2207 } else if (monster == 4) { /* zombie */
2208 draw_circle(dr,x,y,2*tilesize/5, COL_ZOMBIE,black);
2209
2210 draw_line(dr,
2211 x-tilesize/7-tilesize/16, y-tilesize/12-tilesize/16,
2212 x-tilesize/7+tilesize/16, y-tilesize/12+tilesize/16,
2213 black);
2214 draw_line(dr,
2215 x-tilesize/7+tilesize/16, y-tilesize/12-tilesize/16,
2216 x-tilesize/7-tilesize/16, y-tilesize/12+tilesize/16,
2217 black);
2218 draw_line(dr,
2219 x+tilesize/7-tilesize/16, y-tilesize/12-tilesize/16,
2220 x+tilesize/7+tilesize/16, y-tilesize/12+tilesize/16,
2221 black);
2222 draw_line(dr,
2223 x+tilesize/7+tilesize/16, y-tilesize/12-tilesize/16,
2224 x+tilesize/7-tilesize/16, y-tilesize/12+tilesize/16,
2225 black);
2226
2227 clip(dr, x-tilesize/5, y+tilesize/6, 2*tilesize/5+1, tilesize/2);
2228 draw_circle(dr, x-tilesize/15, y+tilesize/6, tilesize/12,
2229 COL_BACKGROUND, black);
2230 unclip(dr);
2231
2232 draw_line(dr, x-tilesize/5, y+tilesize/6, x+tilesize/5, y+tilesize/6,
2233 black);
2234 }
2235
2236 draw_update(dr,x-(tilesize/2)+2,y-(tilesize/2)+2,tilesize-3,tilesize-3);
2237 }
2238
2239 static void draw_monster_count(drawing *dr, game_drawstate *ds,
2240 game_state *state, int c, int hflash) {
2241 int dx,dy,dh;
2242 char buf[8];
2243 char bufm[8];
2244
2245 dy = TILESIZE/2;
2246 dh = TILESIZE;
2247 dx = BORDER+(ds->w+2)*TILESIZE/2+TILESIZE/4;
2248 switch (c) {
2249 case 0:
2250 sprintf(buf,"%d",state->common->num_ghosts);
2251 sprintf(bufm,"G");
2252 dx -= 3*TILESIZE/2;
2253 break;
2254 case 1:
2255 sprintf(buf,"%d",state->common->num_vampires);
2256 sprintf(bufm,"V");
2257 break;
2258 case 2:
2259 sprintf(buf,"%d",state->common->num_zombies);
2260 sprintf(bufm,"Z");
2261 dx += 3*TILESIZE/2;
2262 break;
2263 }
2264
2265 if (!ds->ascii) {
2266 draw_rect(dr,dx-2*TILESIZE/3,dy,3*TILESIZE/2,dh,COL_BACKGROUND);
2267 draw_monster(dr,ds,dx-TILESIZE/3,dh,2*TILESIZE/3,hflash,1<<c);
2268 draw_text(dr,dx,dh,FONT_VARIABLE,dy-1,ALIGN_HLEFT|ALIGN_VCENTRE,
2269 (state->count_errors[c] ? COL_ERROR : hflash ? COL_FLASH : COL_TEXT), buf);
2270 draw_update(dr,dx-2*TILESIZE/3,dy,3*TILESIZE/2,dh);
2271 }
2272 else {
2273 draw_rect(dr,dx-2*TILESIZE/3,dy,3*TILESIZE/2,dh,COL_BACKGROUND);
2274 draw_text(dr,dx-TILESIZE/3,dh,FONT_VARIABLE,dy-1,
2275 ALIGN_HCENTRE|ALIGN_VCENTRE,
2276 hflash ? COL_FLASH : COL_TEXT, bufm);
2277 draw_text(dr,dx,dh,FONT_VARIABLE,dy-1,ALIGN_HLEFT|ALIGN_VCENTRE,
2278 (state->count_errors[c] ? COL_ERROR : hflash ? COL_FLASH : COL_TEXT), buf);
2279 draw_update(dr,dx-2*TILESIZE/3,dy,3*TILESIZE/2,dh);
2280 }
2281
2282 return;
2283 }
2284
2285 static void draw_path_hint(drawing *dr, game_drawstate *ds, game_state *state,
2286 int i, int hflash, int start) {
2287 int dx,dy,x,y;
2288 int p,error;
2289 char buf[80];
2290
2291 p = start ? state->common->paths[i].grid_start : state->common->paths[i].grid_end;
2292 range2grid(p,state->common->params.w,state->common->params.h,&x,&y);
2293 error = ds->hint_errors[p];
2294
2295 dx = BORDER+(x* ds->tilesize)+(TILESIZE/2);
2296 dy = BORDER+(y* ds->tilesize)+(TILESIZE/2)+TILESIZE;
2297 sprintf(buf,"%d", start ? state->common->paths[i].sightings_start : state->common->paths[i].sightings_end);
2298 draw_rect(dr,dx-(TILESIZE/2)+2,dy-(TILESIZE/2)+2,TILESIZE-3,TILESIZE-3,COL_BACKGROUND);
2299 draw_text(dr,dx,dy,FONT_FIXED,TILESIZE/2,ALIGN_HCENTRE|ALIGN_VCENTRE, error ? COL_ERROR : hflash ? COL_FLASH : COL_TEXT,buf);
2300 draw_update(dr,dx-(TILESIZE/2)+2,dy-(TILESIZE/2)+2,TILESIZE-3,TILESIZE-3);
2301
2302 return;
2303 }
2304
2305 static void draw_mirror(drawing *dr, game_drawstate *ds, game_state *state,
2306 int x, int y, int hflash, int mirror) {
2307 int dx,dy,mx1,my1,mx2,my2;
2308 dx = BORDER+(x* ds->tilesize)+(TILESIZE/2);
2309 dy = BORDER+(y* ds->tilesize)+(TILESIZE/2)+TILESIZE;
2310
2311 if (mirror == CELL_MIRROR_L) {
2312 mx1 = dx-(TILESIZE/4);
2313 my1 = dy-(TILESIZE/4);
2314 mx2 = dx+(TILESIZE/4);
2315 my2 = dy+(TILESIZE/4);
2316 }
2317 else {
2318 mx1 = dx-(TILESIZE/4);
2319 my1 = dy+(TILESIZE/4);
2320 mx2 = dx+(TILESIZE/4);
2321 my2 = dy-(TILESIZE/4);
2322 }
2323 draw_thick_line(dr,(float)(TILESIZE/16),mx1,my1,mx2,my2,
2324 hflash ? COL_FLASH : COL_TEXT);
2325 draw_update(dr,dx-(TILESIZE/2)+1,dy-(TILESIZE/2)+1,TILESIZE-1,TILESIZE-1);
2326
2327 return;
2328 }
2329
2330 static void draw_big_monster(drawing *dr, game_drawstate *ds, game_state *state,
2331 int x, int y, int hflash, int monster)
2332 {
2333 int dx,dy;
2334 char buf[10];
2335 dx = BORDER+(x* ds->tilesize)+(TILESIZE/2);
2336 dy = BORDER+(y* ds->tilesize)+(TILESIZE/2)+TILESIZE;
2337 if (ds->ascii) {
2338 if (monster == 1) sprintf(buf,"G");
2339 else if (monster == 2) sprintf(buf,"V");
2340 else if (monster == 4) sprintf(buf,"Z");
2341 else sprintf(buf," ");
2342 draw_text(dr,dx,dy,FONT_FIXED,TILESIZE/2,ALIGN_HCENTRE|ALIGN_VCENTRE,
2343 hflash ? COL_FLASH : COL_TEXT,buf);
2344 draw_update(dr,dx-(TILESIZE/2)+2,dy-(TILESIZE/2)+2,TILESIZE-3,
2345 TILESIZE-3);
2346 }
2347 else {
2348 draw_monster(dr, ds, dx, dy, 3*TILESIZE/4, hflash, monster);
2349 }
2350 return;
2351 }
2352
2353 static void draw_pencils(drawing *dr, game_drawstate *ds, game_state *state,
2354 int x, int y, int pencil) {
2355 int dx, dy;
2356 int monsters[4];
2357 int i, j, px, py;
2358 char buf[10];
2359 dx = BORDER+(x* ds->tilesize)+(TILESIZE/4);
2360 dy = BORDER+(y* ds->tilesize)+(TILESIZE/4)+TILESIZE;
2361
2362 for (i = 0, j = 1; j < 8; j *= 2)
2363 if (pencil & j)
2364 monsters[i++] = j;
2365 while (i < 4)
2366 monsters[i++] = 0;
2367
2368 for (py = 0; py < 2; py++)
2369 for (px = 0; px < 2; px++)
2370 if (monsters[py*2+px]) {
2371 if (!ds->ascii) {
2372 draw_monster(dr, ds,
2373 dx + TILESIZE/2 * px, dy + TILESIZE/2 * py,
2374 TILESIZE/2, 0, monsters[py*2+px]);
2375 }
2376 else {
2377 switch (monsters[py*2+px]) {
2378 case 1: sprintf(buf,"G"); break;
2379 case 2: sprintf(buf,"V"); break;
2380 case 4: sprintf(buf,"Z"); break;
2381 }
2382 draw_text(dr,dx + TILESIZE/2 * px,dy + TILESIZE/2 * py,
2383 FONT_FIXED,TILESIZE/4,ALIGN_HCENTRE|ALIGN_VCENTRE,
2384 COL_TEXT,buf);
2385 }
2386 }
2387 draw_update(dr,dx-(TILESIZE/4)+2,dy-(TILESIZE/4)+2,
2388 (TILESIZE/2)-3,(TILESIZE/2)-3);
2389
2390 return;
2391 }
2392
2393 #define FLASH_TIME 0.7F
2394
2395 static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
2396 game_state *state, int dir, game_ui *ui,
2397 float animtime, float flashtime) {
2398 int i,j,x,y,xy;
2399 int stale, xi, c, hflash, hchanged, changed_ascii;
2400
2401 hflash = (int)(flashtime * 5 / FLASH_TIME) % 2;
2402
2403 /* Draw static grid components at startup */
2404 if (!ds->started) {
2405 draw_rect(dr, 0, 0, 2*BORDER+(ds->w+2)*TILESIZE,
2406 2*BORDER+(ds->h+3)*TILESIZE, COL_BACKGROUND);
2407 draw_rect(dr, BORDER+TILESIZE-1, BORDER+2*TILESIZE-1,
2408 (ds->w)*TILESIZE +3, (ds->h)*TILESIZE +3, COL_GRID);
2409 for (i=0;i<ds->w;i++)
2410 for (j=0;j<ds->h;j++)
2411 draw_rect(dr, BORDER+(ds->tilesize*(i+1))+1,
2412 BORDER+(ds->tilesize*(j+2))+1, ds->tilesize-1,
2413 ds->tilesize-1, COL_BACKGROUND);
2414 draw_update(dr,BORDER+TILESIZE-1,BORDER+2*TILESIZE-1,
2415 (ds->w)*TILESIZE+3, (ds->h)*TILESIZE+3);
2416 }
2417
2418 hchanged = FALSE;
2419 if (ds->hx != ui->hx || ds->hy != ui->hy ||
2420 ds->hshow != ui->hshow || ds->hpencil != ui->hpencil)
2421 hchanged = TRUE;
2422
2423 if (ds->ascii != ui->ascii) {
2424 ds->ascii = ui->ascii;
2425 changed_ascii = TRUE;
2426 } else
2427 changed_ascii = FALSE;
2428
2429 /* Draw monster count hints */
2430
2431 for (i=0;i<3;i++) {
2432 stale = FALSE;
2433 if (!ds->started) stale = TRUE;
2434 if (ds->hflash != hflash) stale = TRUE;
2435 if (changed_ascii) stale = TRUE;
2436 if (ds->count_errors[i] != state->count_errors[i]) {
2437 stale = TRUE;
2438 ds->count_errors[i] = state->count_errors[i];
2439 }
2440
2441 if (stale) {
2442 draw_monster_count(dr, ds, state, i, hflash);
2443 }
2444 }
2445
2446 /* Draw path count hints */
2447 for (i=0;i<state->common->num_paths;i++) {
2448 int p;
2449 stale = FALSE;
2450
2451 if (!ds->started) stale = TRUE;
2452 if (ds->hflash != hflash) stale = TRUE;
2453
2454 p = state->common->paths[i].grid_start;
2455 if (ds->hint_errors[p] != state->hint_errors[p]) {
2456 stale = TRUE;
2457 ds->hint_errors[p] = state->hint_errors[p];
2458 }
2459
2460 if (stale) {
2461 draw_path_hint(dr, ds, state, i, hflash, TRUE);
2462 }
2463
2464 stale = FALSE;
2465
2466 if (!ds->started) stale = TRUE;
2467 if (ds->hflash != hflash) stale = TRUE;
2468
2469 p = state->common->paths[i].grid_end;
2470 if (ds->hint_errors[p] != state->hint_errors[p]) {
2471 stale = TRUE;
2472 ds->hint_errors[p] = state->hint_errors[p];
2473 }
2474
2475 if (stale) {
2476 draw_path_hint(dr, ds, state, i, hflash, FALSE);
2477 }
2478
2479 }
2480
2481 /* Draw puzzle grid contents */
2482 for (x = 1; x < ds->w+1; x++)
2483 for (y = 1; y < ds->h+1; y++) {
2484 stale = FALSE;
2485 xy = x+y*(state->common->params.w+2);
2486 xi = state->common->xinfo[xy];
2487 c = state->common->grid[xy];
2488
2489 if (!ds->started) stale = TRUE;
2490 if (ds->hflash != hflash) stale = TRUE;
2491 if (changed_ascii) stale = TRUE;
2492
2493 if (hchanged) {
2494 if ((x == ui->hx && y == ui->hy) ||
2495 (x == ds->hx && y == ds->hy))
2496 stale = TRUE;
2497 }
2498
2499 if (xi >= 0 && (state->guess[xi] != ds->monsters[xi]) ) {
2500 stale = TRUE;
2501 ds->monsters[xi] = state->guess[xi];
2502 }
2503
2504 if (xi >= 0 && (state->pencils[xi] != ds->pencils[xi]) ) {
2505 stale = TRUE;
2506 ds->pencils[xi] = state->pencils[xi];
2507 }
2508
2509 if (state->cell_errors[xy] != ds->cell_errors[xy]) {
2510 stale = TRUE;
2511 ds->cell_errors[xy] = state->cell_errors[xy];
2512 }
2513
2514 if (stale) {
2515 draw_cell_background(dr, ds, state, ui, x, y);
2516 if (xi < 0)
2517 draw_mirror(dr, ds, state, x, y, hflash, c);
2518 else if (state->guess[xi] == 1 || state->guess[xi] == 2 ||
2519 state->guess[xi] == 4)
2520 draw_big_monster(dr, ds, state, x, y, hflash, state->guess[xi]);
2521 else
2522 draw_pencils(dr, ds, state, x, y, state->pencils[xi]);
2523 }
2524 }
2525
2526 ds->hx = ui->hx; ds->hy = ui->hy;
2527 ds->hshow = ui->hshow;
2528 ds->hpencil = ui->hpencil;
2529 ds->hflash = hflash;
2530 ds->started = TRUE;
2531 return;
2532 }
2533
2534 static float game_anim_length(game_state *oldstate, game_state *newstate,
2535 int dir, game_ui *ui) {
2536 return 0.0F;
2537 }
2538
2539 static float game_flash_length(game_state *oldstate, game_state *newstate,
2540 int dir, game_ui *ui) {
2541 return (!oldstate->solved && newstate->solved && !oldstate->cheated &&
2542 !newstate->cheated) ? FLASH_TIME : 0.0F;
2543 }
2544
2545 static int game_status(game_state *state) {
2546 return state->solved;
2547 }
2548
2549 static int game_timing_state(game_state *state, game_ui *ui) {
2550 return TRUE;
2551 }
2552
2553 static void game_print_size(game_params *params, float *x, float *y) {
2554 }
2555
2556 static void game_print(drawing *dr, game_state *state, int tilesize) {
2557 }
2558
2559 #ifdef COMBINED
2560 #define thegame undead
2561 #endif
2562
2563 const struct game thegame = {
2564 "Undead", "games.undead", "undead",
2565 default_params,
2566 game_fetch_preset,
2567 decode_params,
2568 encode_params,
2569 free_params,
2570 dup_params,
2571 TRUE, game_configure, custom_params,
2572 validate_params,
2573 new_game_desc,
2574 validate_desc,
2575 new_game,
2576 dup_game,
2577 free_game,
2578 TRUE, solve_game,
2579 TRUE, game_can_format_as_text_now, game_text_format,
2580 new_ui,
2581 free_ui,
2582 encode_ui,
2583 decode_ui,
2584 game_changed_state,
2585 interpret_move,
2586 execute_move,
2587 PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
2588 game_colours,
2589 game_new_drawstate,
2590 game_free_drawstate,
2591 game_redraw,
2592 game_anim_length,
2593 game_flash_length,
2594 game_status,
2595 FALSE, FALSE, game_print_size, game_print,
2596 FALSE, /* wants_statusbar */
2597 FALSE, game_timing_state,
2598 0, /* flags */
2599 };
2600