sokosol.c
changeset 6 bfbca2c0fc70
parent 4 d9259a605dec
child 26 95fccfcbd04c
equal deleted inserted replaced
5:9d1e320acbb0 6:bfbca2c0fc70
       
     1 #include <assert.h>
     1 #include <stdio.h>
     2 #include <stdio.h>
     2 #include <string.h>
     3 #include <string.h>
     3 #include <assert.h>
       
     4 #include <stdlib.h>
     4 #include <stdlib.h>
     5 #include <unistd.h>
       
     6 #include <signal.h>
       
     7 #include "general.h"
     5 #include "general.h"
     8 
     6 
     9 #define NBOX(n) ((n)<<2)
     7 #define NBOX(n) ((n)<<2)
    10 
     8 
    11 /* SOKOBAN Solution Finder
     9 /* SOKOBAN Solution Finder
    24  * 	marked as is: WALLS.
    22  * 	marked as is: WALLS.
    25  * 	All lines must be of the same length.
    23  * 	All lines must be of the same length.
    26  */
    24  */
    27 
    25 
    28 
    26 
    29 float percent_to_show = 0;
       
    30 int depth_to_show = 0;
       
    31 
       
    32 int max_depth = 0;
       
    33 int min_depth_period = 0;
       
    34 int max_depth_period = 0;
       
    35 struct Map * actual_map;
       
    36 
    27 
    37 
    28 
    38 
    29 
    39 
    30 
    40 int InverseMove(char Dir1, char Dir2)
       
    41 {
       
    42 	if ((Dir1 + Dir2 == DIR_LEFT + DIR_RIGHT) ||
       
    43 		(Dir1 + Dir2 == DIR_UP + DIR_DOWN))
       
    44 		return 1;
       
    45 	return 0;
       
    46 }
       
    47 
       
    48 
       
    49 void PrintCombination(int Moves[], int NumMoves)
       
    50 {
       
    51 	int i;
       
    52 
       
    53 	for (i=0; i < NumMoves; i++)
       
    54 	{
       
    55 		printf("%i", Moves[i] >> 2);
       
    56 		if ((Moves[i] & 0x03) == DIR_LEFT)
       
    57 			printf("L");
       
    58 		else if ((Moves[i] & 0x03) == DIR_RIGHT)
       
    59 			printf("R");
       
    60 		else if ((Moves[i] & 0x03) == DIR_UP)
       
    61 			printf("U");
       
    62 		else
       
    63 			printf("D");
       
    64 		printf(",");
       
    65 	}
       
    66 	printf("\n");
       
    67 }
       
    68 
       
    69 #if 0 /*** THIS IS AN ERROR!!!  The box_will_be_blocked function doesn't work!*/
       
    70  Situation:
       
    71     
       
    72   ->@$ #
       
    73       $
       
    74 */
       
    75 int box_will_be_blocked(const struct Map * m, const struct Position mov,
       
    76 	const struct Position box_pos)
       
    77 {
       
    78 	struct Position next_pos2, tmp, tmp2[2];
       
    79 	int i;
       
    80 
       
    81 	next_pos2.x = box_pos.x + mov.x;
       
    82 	next_pos2.y = box_pos.y + mov.y;
       
    83 
       
    84 	tmp.x = next_pos2.x + mov.x;
       
    85 	tmp.y = next_pos2.y + mov.y;
       
    86 	tmp2[0].x = next_pos2.x + mov.y;
       
    87 	tmp2[0].y = next_pos2.y + mov.x;
       
    88 	tmp2[1].x = next_pos2.x - mov.y;
       
    89 	tmp2[1].y = next_pos2.y - mov.x;
       
    90 	for (i=0; i < 2; i++)
       
    91 	{
       
    92 		if (m->man_moves[tmp.y][tmp.x] == WALL &&
       
    93 			m->man_moves[tmp2[i].y][tmp2[i].x] == BOX)
       
    94 		{
       
    95 			return TRUE;
       
    96 		}
       
    97 		else if (m->man_moves[tmp.y][tmp.x] == BOX &&
       
    98 			m->man_moves[tmp2[i].y][tmp2[i].x] == WALL)
       
    99 		{
       
   100 			return TRUE;
       
   101 		}
       
   102 		else if (m->man_moves[tmp.y][tmp.x] == BOX &&
       
   103 			m->man_moves[tmp2[i].y][tmp2[i].x] == BOX)
       
   104 		{
       
   105 			return TRUE;
       
   106 		}
       
   107 	}
       
   108 
       
   109 	return FALSE;
       
   110 }
       
   111 
       
   112 int is_corner_area(const struct Map * m, const struct Position p,
       
   113 	const struct Position box, const struct Position new_box)
       
   114 {
       
   115 	int NumMoves, NewMoves;
       
   116 	struct Position pos[MAX_MOVES];
       
   117 	struct Position new_pos[MAX_MOVES];
       
   118 	char corners[MAX_Y][MAX_X];
       
   119 	int i,j;
       
   120 	struct Position next_pos;
       
   121 	char *next_cell;
       
   122 
       
   123 
       
   124 	/* Blank the garden */
       
   125 	for (j = 0; j<m->SizeY; j++)
       
   126 		for (i=0; i<m->SizeX; i++)
       
   127 			corners[j][i] = m->Cells[j][i];
       
   128 
       
   129 	/* Let's put the boxes */
       
   130 	for (i = 0; i<m->NumBoxes; i++)
       
   131 		corners[m->Box[i].y][m->Box[i].x] = BOX;
       
   132 
       
   133 	/* Let's put our box - it can be simply added */
       
   134 	corners[new_box.y][new_box.x] = BOX;
       
   135 	/* Let's remove the original box. */
       
   136 	corners[box.y][box.x] = BLANK;
       
   137 
       
   138 	NewMoves = 1;
       
   139 	new_pos[0] = p;
       
   140 	while (NewMoves > 0)
       
   141 	{
       
   142 		/* The before named "New Moves" become the moves we have
       
   143 		   to analyze */
       
   144 		NumMoves = NewMoves;
       
   145 		for (i=0; i<NewMoves; i++)
       
   146 		{
       
   147 			pos[i] = new_pos[i];
       
   148 		}
       
   149 
       
   150 		/* Search new positions for each position */
       
   151 		NewMoves = 0;
       
   152 		for (i=0; i<NumMoves; i++)
       
   153 		{
       
   154 			/* For each direction */
       
   155 			for (j=0; j<4; j++)
       
   156 			{
       
   157 				next_pos.x = pos[i].x + move_vectors[j].x;
       
   158 				next_pos.y = pos[i].y + move_vectors[j].y;
       
   159 				next_cell = &corners[next_pos.y][next_pos.x];
       
   160 				if(*next_cell == BLANK ||
       
   161 					*next_cell == PLATFORM)
       
   162 				{
       
   163 					return FALSE;
       
   164 				}
       
   165 				else if(*next_cell == CORNER)
       
   166 				{
       
   167 					new_pos[NewMoves] = next_pos;
       
   168 					*next_cell = MANCANMOVE;
       
   169 					NewMoves++;
       
   170 				}
       
   171 			}
       
   172 		}
       
   173 	}
       
   174 
       
   175 	return TRUE;
       
   176 }
       
   177 
       
   178 int does_box_close_corners(const struct Map * m, const struct Position mov,
       
   179 	const struct Position box_pos)
       
   180 {
       
   181 	struct Position p, p2;
       
   182 
       
   183 	p.x = box_pos.x + mov.x;
       
   184 	p.y = box_pos.y + mov.y;
       
   185 	
       
   186 	/* Let's plan the checks */
       
   187 	/* The point will be marked with a MANCANMOVE */
       
   188 	p2.x = p.x + mov.x;
       
   189 	p2.y = p.y + mov.y;
       
   190 	if (m->Cells[p2.y][p2.x] == CORNER)
       
   191 	{
       
   192 		if (is_corner_area(m, p2, box_pos, p))
       
   193 			return TRUE;
       
   194 	}
       
   195 
       
   196 	p2.x = p.x + mov.y;
       
   197 	p2.y = p.y + mov.x;
       
   198 	if (m->Cells[p2.y][p2.x] == CORNER)
       
   199 	{
       
   200 		if (is_corner_area(m, p2, box_pos, p))
       
   201 			return TRUE;
       
   202 	}
       
   203 
       
   204 	p2.x = p.x - mov.y;
       
   205 	p2.y = p.y - mov.x;
       
   206 	if (m->Cells[p2.y][p2.x] == CORNER)
       
   207 	{
       
   208 		if (is_corner_area(m, p2, box_pos, p))
       
   209 			return TRUE;
       
   210 	}
       
   211 	return FALSE;
       
   212 }
       
   213 #endif
       
   214 
       
   215 /*
       
   216 Catch the situation where a box is moved next to a corner, where the box
       
   217 next to it will not be able to be moved.
       
   218 */
       
   219 int is_dead1(const struct Map * m, const struct Position mov,
       
   220 	const struct Position new_pos)
       
   221 {
       
   222 	struct Position opposite1, opposite2;
       
   223 
       
   224 	/* The wall corners must exist */
       
   225 	opposite1.x = -mov.y;
       
   226 	opposite1.y = -mov.x;
       
   227 	opposite2.x = mov.y;
       
   228 	opposite2.y = mov.x;
       
   229 
       
   230 #ifdef DEBUG
       
   231 	ShowMap(m);
       
   232 #endif
       
   233 
       
   234 	/* Test the first corner */
       
   235 	if (m->Cells[new_pos.y+mov.y+opposite1.y][new_pos.x+mov.x+opposite1.x]
       
   236 		== WALL)
       
   237 	{
       
   238 		/* Test wall at opposites 1*/
       
   239 		if (m->Cells[new_pos.y+opposite1.y][new_pos.x+opposite1.x]
       
   240 			== WALL &&
       
   241 			m->man_moves[new_pos.y+mov.y][new_pos.x+mov.x] == BOX)
       
   242 		{
       
   243 				return TRUE;
       
   244 		}
       
   245 		else
       
   246 		if (m->man_moves[new_pos.y+opposite1.y][new_pos.x+opposite1.x]
       
   247 			== BOX &&
       
   248 			m->Cells[new_pos.y+mov.y][new_pos.x+mov.x] == WALL)
       
   249 		{
       
   250 				return TRUE;
       
   251 		}
       
   252 		/* Test wall at opposites 2 */
       
   253 		if (m->Cells[new_pos.y+opposite2.y][new_pos.x+opposite2.x]
       
   254 			== WALL &&
       
   255 			m->man_moves[new_pos.y+mov.y][new_pos.x+mov.x] == BOX)
       
   256 		{
       
   257 				return TRUE;
       
   258 		}
       
   259 		else
       
   260 		if (m->man_moves[new_pos.y+opposite2.y][new_pos.x+opposite2.x]
       
   261 			== BOX &&
       
   262 			m->Cells[new_pos.y+mov.y][new_pos.x+mov.x] == WALL)
       
   263 		{
       
   264 				return TRUE;
       
   265 		}
       
   266 	}
       
   267 
       
   268 	/* Test the second corner */
       
   269 	if (m->Cells[new_pos.y+mov.y+opposite2.y][new_pos.x+mov.x+opposite2.x]
       
   270 		== WALL)
       
   271 	{
       
   272 		/* Test wall at opposites 1*/
       
   273 		if (m->Cells[new_pos.y+opposite1.y][new_pos.x+opposite1.x]
       
   274 			== WALL &&
       
   275 			m->man_moves[new_pos.y+mov.y][new_pos.x+mov.x] == BOX)
       
   276 		{
       
   277 				return TRUE;
       
   278 		}
       
   279 		else
       
   280 		if (m->man_moves[new_pos.y+opposite1.y][new_pos.x+opposite1.x]
       
   281 			== BOX &&
       
   282 			m->Cells[new_pos.y+mov.y][new_pos.x+mov.x] == WALL)
       
   283 		{
       
   284 				return TRUE;
       
   285 		}
       
   286 		/* Test wall at opposites 2 */
       
   287 		if (m->Cells[new_pos.y+opposite2.y][new_pos.x+opposite2.x]
       
   288 			== WALL &&
       
   289 			m->man_moves[new_pos.y+mov.y][new_pos.x+mov.x] == BOX)
       
   290 		{
       
   291 				return TRUE;
       
   292 		}
       
   293 		else
       
   294 		if (m->man_moves[new_pos.y+opposite2.y][new_pos.x+opposite2.x]
       
   295 			== BOX &&
       
   296 			m->Cells[new_pos.y+mov.y][new_pos.x+mov.x] == WALL)
       
   297 		{
       
   298 				return TRUE;
       
   299 		}
       
   300 	}
       
   301 
       
   302 	return FALSE;
       
   303 }
       
   304 
       
   305 /*
       
   306 Catch the situation where a corner gets surrounded by boxes.
       
   307 */
       
   308 int is_dead2(const struct Map * m, const struct Position mov,
       
   309 	const struct Position new_pos)
       
   310 {
       
   311 	struct Position next, next2, opposite1, opposite2;
       
   312 
       
   313 	next.x = new_pos.x+mov.x;
       
   314 	next.y = new_pos.y+mov.y;
       
   315 
       
   316 	/* The corner must exist */
       
   317 	if (m->Cells[next.y][next.x] != CORNER)
       
   318 		return FALSE;
       
   319 
       
   320 
       
   321 	/* The wall corners must exist */
       
   322 	opposite1.x = next.x -mov.y;
       
   323 	opposite1.y = next.y -mov.x;
       
   324 	opposite2.x = next.x + mov.y;
       
   325 	opposite2.y = next.y + mov.x;
       
   326 
       
   327 	if (m->man_moves[opposite1.y][opposite1.x] == BOX)
       
   328 	{
       
   329 		if(m->Cells[opposite1.y+mov.y][opposite1.x+mov.x] == WALL
       
   330 		   && m->Cells[opposite1.y-mov.y][opposite1.x-mov.x] == WALL)
       
   331 		   return TRUE;
       
   332 	}
       
   333 
       
   334 	if (m->man_moves[opposite2.y][opposite2.x] == BOX)
       
   335 	{
       
   336 		if(m->Cells[opposite2.y+mov.y][opposite2.x+mov.x] == WALL
       
   337 		   && m->Cells[opposite2.y-mov.y][opposite2.x-mov.x] == WALL)
       
   338 		   return TRUE;
       
   339 	}
       
   340 	return FALSE;
       
   341 }
       
   342 
       
   343 int is_box_movable(const struct Map * m, const struct Position mov,
       
   344 	const struct Position box_pos)
       
   345 {
       
   346 	struct Position next_pos2;
       
   347 
       
   348 	next_pos2.x = box_pos.x + mov.x;
       
   349 	next_pos2.y = box_pos.y + mov.y;
       
   350 
       
   351 	if((m->Cells[next_pos2.y][next_pos2.x] != BLANK &&
       
   352 		m->Cells[next_pos2.y][next_pos2.x] != PLATFORM) ||
       
   353 		m->man_moves[next_pos2.y][next_pos2.x] == BOX)
       
   354 	{
       
   355 		return FALSE;
       
   356 	}
       
   357 	else if (is_dead1(m, mov, next_pos2) == TRUE)
       
   358 	{
       
   359 		return FALSE;
       
   360 	}
       
   361 	else if (is_dead2(m, mov, next_pos2) == TRUE)
       
   362 	{
       
   363 		return FALSE;
       
   364 	}
       
   365 	return TRUE;
       
   366 }
       
   367 
       
   368 /* It modifies m->man_moves */
       
   369 int get_box_movements(struct Map * m,
       
   370 	struct BoxMove movements[])
       
   371 {
       
   372 	struct Position pos[MAX_MOVES];
       
   373 	struct Position new_pos[MAX_MOVES];
       
   374 	int NumMoves, NewMoves;
       
   375 	int j, i;
       
   376 	struct Position next_pos;
       
   377 	char *next_cell;
       
   378 	int num_box_movements = 0;
       
   379 	
       
   380 	/* Let's  the map with only walls in man_moves - other, blanks */
       
   381 	for (j = 0; j<m->SizeY; j++)
       
   382 		for (i=0; i<m->SizeX; i++)
       
   383 		{
       
   384 			if (m->Cells[j][i] == WALL)
       
   385 				m->man_moves[j][i] = WALL;
       
   386 			else
       
   387 				m->man_moves[j][i] = BLANK;
       
   388 		}
       
   389 
       
   390 	/* Let's put the boxes */
       
   391 	for (i = 0; i<m->NumBoxes; i++)
       
   392 	{
       
   393 		m->man_moves[m->Box[i].y][m->Box[i].x] = BOX;
       
   394 		m->cells_boxes[m->Box[i].y][m->Box[i].x] = i;
       
   395 	}
       
   396 
       
   397 	NewMoves = 1;
       
   398 	new_pos[0].x = m->Man.x;
       
   399 	new_pos[0].y = m->Man.y;
       
   400 	m->man_moves[m->Man.y][m->Man.x] = MANCANMOVE;
       
   401 	while (NewMoves > 0)
       
   402 	{
       
   403 		/* The before named "New Moves" become the moves we have
       
   404 		   to analyze */
       
   405 		NumMoves = NewMoves;
       
   406 		for (i=0; i<NewMoves; i++)
       
   407 		{
       
   408 			pos[i] = new_pos[i];
       
   409 		}
       
   410 
       
   411 		/* Search new positions for each position */
       
   412 		NewMoves = 0;
       
   413 		for (i=0; i<NumMoves; i++)
       
   414 		{
       
   415 			/* For each direction */
       
   416 			for (j=0; j<4; j++)
       
   417 			{
       
   418 				next_pos.x = pos[i].x + move_vectors[j].x;
       
   419 				next_pos.y = pos[i].y + move_vectors[j].y;
       
   420 				next_cell = &m->man_moves[next_pos.y][next_pos.x];
       
   421 				if(*next_cell == BLANK)
       
   422 				{
       
   423 					new_pos[NewMoves] = next_pos;
       
   424 					*next_cell = MANCANMOVE;
       
   425 					NewMoves++;
       
   426 				}
       
   427 				else if (*next_cell == BOX)
       
   428 				{
       
   429 						
       
   430 					/* Check if the box is movable */
       
   431 
       
   432 					if (is_box_movable(m, move_vectors[j],
       
   433 						next_pos ))
       
   434 					{
       
   435 						{
       
   436 					movements[num_box_movements].box =
       
   437 					m->cells_boxes[next_pos.y][next_pos.x];
       
   438 					movements[num_box_movements].dir =
       
   439 					move_vectors[j];
       
   440 					num_box_movements++;
       
   441 						}
       
   442 					}
       
   443 					
       
   444 				}
       
   445 
       
   446 			}
       
   447 		}
       
   448 	}
       
   449 
       
   450 	return num_box_movements;
       
   451 }
       
   452 
       
   453 void force_move_box(struct Map *m, struct BoxMove move)
       
   454 {
       
   455 	struct Position newpos;
       
   456 
       
   457 
       
   458 	/* Add coords */
       
   459 	newpos.x = m->Box[move.box].x + move.dir.x;
       
   460 	newpos.y = m->Box[move.box].y + move.dir.y;
       
   461 
       
   462 	/* Be certain the move can be done */
       
   463 	assert(m->Cells[newpos.y][newpos.x] != BOX);
       
   464 	assert(m->Cells[newpos.y][newpos.x] != WALL);
       
   465 
       
   466 	/* Control if we moved the box to a platform */
       
   467 	if(m->Cells[newpos.y][newpos.x] == PLATFORM)
       
   468 	{
       
   469 		m->NumBoxesInPlatform++;
       
   470 	}
       
   471 
       
   472 	/* Control if we moved the box from a platform */
       
   473 	if (m->Cells[m->Box[move.box].y][m->Box[move.box].x] == PLATFORM)
       
   474 	{
       
   475 		m->NumBoxesInPlatform--;
       
   476 	}
       
   477 	m->Man = m->Box[move.box];
       
   478 
       
   479 	m->Box[move.box] = newpos;
       
   480 }
       
   481 
       
   482 int are_boxes_equal(const struct Position b1[], const struct Position b2[],
       
   483 	int n)
       
   484 {
       
   485 	int i;
       
   486 	char tmp[MAX_Y][MAX_X]; /* !!!argh */
       
   487 
       
   488 	memset(tmp, 0, sizeof(tmp));
       
   489 
       
   490 	for (i=0; i < n; i++)
       
   491 	{
       
   492 		tmp[b1[i].y][b1[i].x] = 1;
       
   493 	}
       
   494 	for (i=0; i < n; i++)
       
   495 	{
       
   496 		if (tmp[b2[i].y][b2[i].x] != 1)
       
   497 			return FALSE;
       
   498 	}
       
   499 	return TRUE;
       
   500 }
       
   501 
       
   502 int is_new_map(struct Map maps[], int depth)
       
   503 {
       
   504 	struct Map *m;
       
   505 	int i;
       
   506 
       
   507 	m = &maps[depth];
       
   508 
       
   509 	for(i=0; i<max_depth; i++)
       
   510 	{
       
   511 		/* No l'hem de comparar amb ell mateix */
       
   512 		if (i == depth)
       
   513 			continue;
       
   514 
       
   515 		if (m->NumBoxesInPlatform != maps[i].NumBoxesInPlatform)
       
   516 			continue;
       
   517 		else
       
   518 		{
       
   519 			if (!are_boxes_equal(m->Box, maps[i].Box, m->NumBoxes))
       
   520 				continue;
       
   521 		}
       
   522 		return FALSE;
       
   523 	}
       
   524 	return TRUE;
       
   525 }
       
   526 
       
   527 void PrintMove(struct BoxMove b)
       
   528 {
       
   529 	printf("Box: %i, Direction: {%i,%i}\n", b.box, b.dir.x, b.dir.y);
       
   530 }
       
   531 
       
   532 void show_percent_callback(int parameter)
       
   533 {
       
   534 	fprintf(stderr, "Percent: %2.12f, depth: %i-%i\n", percent_to_show,
       
   535 		min_depth_period, max_depth_period);
       
   536 	ShowMap(actual_map);
       
   537 	fflush(stderr);
       
   538 	min_depth_period = MAX_STEPS;
       
   539 	max_depth_period = 0;
       
   540 #ifndef DEBUG
       
   541 	alarm(ALARM_SECONDS);
       
   542 #endif
       
   543 }
       
   544 
       
   545 int search_depth(struct Map maps[], int depth,
       
   546 	struct BoxMove movements[],
       
   547 	int num_movements, float percent, float total_percent)
       
   548 {
       
   549 	struct BoxMove new_movements[MAX_MOVES];
       
   550 	int num_new_movements;
       
   551 	struct Map *m; 
       
   552 	int i;
       
   553 	float next_percent;
       
   554 
       
   555 	next_percent = percent / num_movements;
       
   556 
       
   557 	m = &maps[depth+1];
       
   558 	if (depth > max_depth)
       
   559 		max_depth = depth;
       
   560 	if (depth > max_depth_period)
       
   561 		max_depth_period = depth;
       
   562 	if (depth < min_depth_period)
       
   563 		min_depth_period = depth;
       
   564 
       
   565 	for (i=0; i < num_movements; i++)
       
   566 	{
       
   567 		CopyMap(m, &maps[depth]);
       
   568 		force_move_box(m, movements[i]);
       
   569 		if (m->NumPlatforms == m->NumBoxesInPlatform)
       
   570 		{
       
   571 			printf("\nSolved!\n");
       
   572 			PrintMove(movements[i]);
       
   573 			return 0;
       
   574 		}
       
   575 
       
   576 		if (is_new_map(maps, depth+1))
       
   577 		{
       
   578 			num_new_movements = get_box_movements(m, new_movements);
       
   579 			assert(num_new_movements < MAX_MOVES);
       
   580 		}
       
   581 		else
       
   582 			num_new_movements = 0;
       
   583 
       
   584 		if (num_new_movements == 0)
       
   585 		{
       
   586 			percent_to_show = total_percent + next_percent*i;
       
   587 			depth_to_show = depth;
       
   588 			actual_map = &maps[depth];
       
   589 #ifdef DEBUG		/* to be out */
       
   590 			show_percent_callback(0);
       
   591 #endif
       
   592 	
       
   593 		}
       
   594 		else
       
   595 		{
       
   596 			if (depth+1 < MAX_STEPS)
       
   597 			{
       
   598 				if(search_depth(maps, depth+1, new_movements,
       
   599 					num_new_movements, next_percent,
       
   600 					total_percent + next_percent*i) == 0)
       
   601 				{
       
   602 					PrintMove(movements[i]);
       
   603 					return 0;
       
   604 				}
       
   605 			}
       
   606 		}
       
   607 	}
       
   608 	return 1;
       
   609 }
       
   610 
       
   611 
       
   612 
       
   613 
       
   614 void program_alarm()
       
   615 {
       
   616         struct sigaction my_action;
       
   617         int result;
       
   618 
       
   619         my_action.sa_handler = show_percent_callback;
       
   620         my_action.sa_flags = 0;
       
   621         memset(&my_action.sa_mask, 0, sizeof(my_action.sa_mask));
       
   622 
       
   623         result = sigaction(SIGALRM, &my_action, NULL);
       
   624         assert(result == 0);
       
   625 
       
   626 	alarm(1);
       
   627 }
       
   628 
    31 
   629 int main(int argn, char **argv)
    32 int main(int argn, char **argv)
   630 {
    33 {
   631 	struct Map Morigin;
    34 	struct Map Morigin;
   632 	struct Map maps[MAX_STEPS+1];
       
   633 	struct BoxMove new_movements[MAX_MOVES];
       
   634 	int num_new_movements;
       
   635 
       
   636 
    35 
   637 	if (argn != 2)
    36 	if (argn != 2)
   638 	{
    37 	{
   639 		printf("Usage: %s <mapfile>\n", argv[0]);
    38 		printf("Usage: %s <mapfile>\n", argv[0]);
   640 		exit(3);
    39 		exit(3);
   641 	}
    40 	}
   642 	ReadMap(&Morigin, argv[1]);
    41 	ReadMap(&Morigin, argv[1]);
       
    42 	assert(Morigin.NumPlatforms > Morigin.NumBoxesInPlatform);
   643 
    43 
   644 	// Reget the original map
    44 	init_os();
   645 	CopyMap(&maps[0], &Morigin);
       
   646 
    45 
   647 	assert(maps[0].NumPlatforms > maps[0].NumBoxesInPlatform);
    46 	return solve_map(Morigin);
   648 
       
   649 	num_new_movements = get_box_movements(&maps[0], new_movements);
       
   650 	assert(num_new_movements < MAX_MOVES);
       
   651 	assert(num_new_movements > 0);
       
   652 
       
   653 #ifndef DEBUG
       
   654 	program_alarm();
       
   655 #endif
       
   656 	search_depth(maps, 0, new_movements,
       
   657 		num_new_movements, 100. / num_new_movements,
       
   658 		0);
       
   659 
       
   660 	return 0;
       
   661 
       
   662 }
    47 }