#include <stdio.h>
-
+#include <stdlib.h>
#include "sokoban.h"
-struct sokoban_screen *parse_screen(FILE *stream){
- int buffer;
+sokoban_screen *add_coord(int x, int y, sokoban_tile tile, sokoban_screen *screen)
+{
+ sokoban_screen *r = NULL;
+
+ r = (sokoban_screen *)malloc(sizeof(sokoban_screen));
+ memset(r, 0, sizeof(sokoban_screen));
+ r->coord.x = x;
+ r->coord.y = y;
+ r->tile = tile;
+ HASH_ADD(hh, screen, coord, sizeof(record_key), r);
+ return screen;
+}
+
+sokoban_screen *get_coord(int x, int y, sokoban_screen *screen)
+{
+ sokoban_screen k, *r = NULL;
+ memset(&k, 0, sizeof(sokoban_screen));
+ k.coord.x = x;
+ k.coord.y = y;
+ HASH_FIND(hh, screen, &k.coord, sizeof(record_key), r);
+ return r;
+}
+
+sokoban_screen *delete_coord(int x, int y, sokoban_screen *screen)
+{
+ sokoban_screen *r = NULL;
+ r = get_coord(x, y, screen);
+ if (r) HASH_DEL(screen, r);
+ return screen;
+}
+
+void sokoban_print(sokoban_screen *screen)
+{
+ sokoban_screen *r;
+ for(r=screen; r != NULL; r = (sokoban_screen *)(r->hh.next)){
+ switch(r->tile){
+ case FREE: printf("x = %d y = %d FREE\n", r->coord.x, r->coord.y); break;
+ case WALL: printf("x = %d y = %d WALL\n", r->coord.x, r->coord.y); break;
+ case BOX: printf("x = %d y = %d BOX\n", r->coord.x, r->coord.y); break;
+ case TARGET: printf("x = %d y = %d TARGET\n", r->coord.x, r->coord.y); break;
+ case AGENT: printf("x = %d y = %d AGENT\n", r->coord.x, r->coord.y); break;
+ case TARGAGENT: printf("x = %d y = %d TARGAGENT\n", r->coord.x, r->coord.y); break;
+ case TARGBOX: printf("x = %d y = %d TARGBOX\n", r->coord.x, r->coord.y); break;
+ }
+ }
+}
+
+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) {
+ HASH_DEL(screen, r);
+ free(r);
+ }
+}
+
+sokoban_screen *parse_screen(FILE *stream, bool safe)
+{
+ 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){
- printf("%c", buffer);
+ if (buffer == '\n'){
+ x = 0;
+ y++;
+ }
+ else {
+ switch(buffer) {
+ case ' ': screen = add_coord(x, y, FREE, 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);
+ 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++;
+ }
+ }
+ if(safe == true && boxes != targets){
+ fprintf(stderr,
+ "Invalid screen. Boxes: %d, Targets: %d\n", boxes, targets);
+ exit(1);
}
- // Alex:
- // Screen reading
- // - Removing outside walls
- // - Bucket fill
- // - [tile]
- // - tile = structure {int, int, enumtile}
- return NULL;
+ 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;
}