added minimum boxamount, check for crappy file
[mc1516pa.git] / modelchecker / sokoban.c
index d5e967f..e5dfd9c 100644 (file)
@@ -1,6 +1,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "uthash.h"
 #include "sokoban.h"
 
 sokoban_screen *add_coord(int x, int y, sokoban_tile tile, sokoban_screen *screen)
@@ -50,7 +49,24 @@ void sokoban_print(sokoban_screen *screen)
        }
 }
 
-void sokoban_clear(sokoban_screen *screen)
+sokoban_screen *sokoban_shrink(int x, int y, sokoban_screen *screen, sokoban_screen *newscreen)
+{
+       sokoban_screen *c, *nc = NULL;
+       c = get_coord(x, y, screen);
+       if (c) {
+               nc = get_coord(c->coord.x, c->coord.y, newscreen);
+               if (c->tile != WALL && nc == NULL) {
+                       newscreen = add_coord(x, y, c->tile, newscreen);
+                       newscreen = sokoban_shrink(x-1, y, screen, newscreen);
+                       newscreen = sokoban_shrink(x+1, y, screen, newscreen);
+                       newscreen = sokoban_shrink(x, y-1, screen, newscreen);
+                       newscreen = sokoban_shrink(x, y+1, screen, newscreen);
+               }
+       }
+       return newscreen;
+}
+
+void sokoban_free(sokoban_screen *screen)
 {
        sokoban_screen *r, *tmp = NULL;
        HASH_ITER(hh, screen, r, tmp) {
@@ -59,11 +75,16 @@ void sokoban_clear(sokoban_screen *screen)
        }
 }
 
-sokoban_screen *parse_screen(FILE *stream)
+sokoban_screen *parse_screen(FILE *stream, bool safe)
 {
-       int buffer, x, y;
+       int buffer, x, y, agent_x, agent_y, boxes, targets, agents;
        x = 0;
        y = 0;
+       agent_x = 0;
+       agent_y = 0;
+       boxes = 0;
+       targets = 0;
+       agents = 0;
        sokoban_screen *screen = NULL;
        while((buffer = fgetc(stream)) != EOF){
                if (buffer == '\n'){
@@ -73,19 +94,57 @@ sokoban_screen *parse_screen(FILE *stream)
                else {
                        switch(buffer) {
                        case ' ': screen = add_coord(x, y, FREE, screen); break;
-                       case '@': screen = add_coord(x, y, AGENT, screen); break;
-                       case '.': screen = add_coord(x, y, TARGET, screen); break;
+                       case '@':
+                               screen = add_coord(x, y, AGENT, screen);
+                               agent_x = x;
+                               agent_y = y;
+                               agents++;
+                               break;
+                       case '.':
+                               screen = add_coord(x, y, TARGET, screen);
+                               targets++;
+                               break;
                        case '#': screen = add_coord(x, y, WALL, screen); break;
-                       case '$': screen = add_coord(x, y, BOX, screen); break;
-                       case '*': screen = add_coord(x, y, TARGBOX, screen); break;
-                       case '+': screen = add_coord(x, y, TARGAGENT, screen); break;
+                       case '$':
+                               screen = add_coord(x, y, BOX, screen);
+                               boxes++;
+                               break;
+                       case '*': 
+                               screen = add_coord(x, y, TARGBOX, screen);
+                               boxes++;
+                               targets++;
+                               break;
+                       case '+': 
+                               screen = add_coord(x, y, TARGAGENT, screen);
+                               agent_x = x;
+                               agent_y = y;
+                               agents++;
+                               targets++;
+                               break;
                        default: return NULL;
                        }
                        x++;
                }
        }
-       sokoban_screen *test = NULL;
-       test = get_coord(0,0,screen);
-       if(test->tile == TARGAGENT) printf("Yuppi\n");
-       return screen;
+       if(safe == true && boxes == 0){
+               fprintf(stderr, 
+                       "Invalid screen. You need at least 1 box\n");
+               exit(1);
+       }
+       if(safe == true && boxes != targets){
+               fprintf(stderr, 
+                       "Invalid screen. Boxes: %d, Targets: %d\n", boxes, targets);
+               exit(1);
+       }
+       if(safe == true && agents != 1){
+               fprintf(stderr, 
+                       "Invalid screen. There has to be exactly one agent. Found: %d\n", 
+                       agents);
+               exit(1);
+       }
+
+       sokoban_screen *newscreen = NULL;
+       newscreen = sokoban_shrink(agent_x, agent_y, screen, newscreen);
+       sokoban_free(screen);
+       return newscreen;
 }