algorithm.c
changeset 12 a2c334a71a6b
parent 10 9148590f009d
child 13 c2b272938a1f
equal deleted inserted replaced
11:dcfe4d2d4387 12:a2c334a71a6b
     1 #include <assert.h>
     1 #include <assert.h>
     2 #include <string.h>
     2 #include <string.h>
       
     3 #include <stdio.h> /**********************************PROVA */
     3 #include "general.h"
     4 #include "general.h"
     4 
     5 
     5 /* Variables related to the showing of information by os */
     6 /* Variables related to the showing of information by os */
     6 extern float percent_to_show;
     7 extern float percent_to_show;
     7 extern int depth_to_show;
     8 extern int depth_to_show;
     8 
     9 
     9 extern int max_depth;
    10 extern int max_depth;
    10 extern int min_depth_period;
    11 extern int min_depth_period;
    11 extern int max_depth_period;
    12 extern int max_depth_period;
    12 extern struct Map * actual_map;
    13 extern struct Map * actual_map;
       
    14 
       
    15 /* Prototipes */
       
    16 static Bool are_there_fixed_boxes(struct Map *m,
       
    17 	struct BoxMove movements[MAX_MOVES], int *num_movements);
       
    18 static void force_move_box(struct Map *m, const struct BoxMove move);
       
    19 static Bool search_did_found(struct Map maps[], int depth,
       
    20 	struct BoxMove movements[],
       
    21 	int num_movements, float percent, float total_percent);
       
    22 static void fill_deps(struct Map *m);
    13 
    23 
    14 #if 0 /*** THIS IS AN ERROR!!!  The box_will_be_blocked function doesn't work!*/
    24 #if 0 /*** THIS IS AN ERROR!!!  The box_will_be_blocked function doesn't work!*/
    15  Situation:
    25  Situation:
    16     
    26     
    17   ->@$ #
    27   ->@$ #
   155 	}
   165 	}
   156 	return FALSE;
   166 	return FALSE;
   157 }
   167 }
   158 #endif
   168 #endif
   159 
   169 
   160 /*
       
   161 Catch the situation where a box is moved next to a corner, where the box
       
   162 next to it will not be able to be moved.
       
   163 */
       
   164 static int is_dead1(const struct Map * m, const struct Position mov,
       
   165 	const struct Position new_pos)
       
   166 {
       
   167 	struct Position opposite1, opposite2;
       
   168 
       
   169 	/* The wall corners must exist */
       
   170 	opposite1.x = -mov.y;
       
   171 	opposite1.y = -mov.x;
       
   172 	opposite2.x = mov.y;
       
   173 	opposite2.y = mov.x;
       
   174 
       
   175 #ifdef DEBUG
       
   176 	ShowMap(m);
       
   177 #endif
       
   178 
       
   179 	/* Test the first corner */
       
   180 	if (m->Cells[new_pos.y+mov.y+opposite1.y][new_pos.x+mov.x+opposite1.x]
       
   181 		== WALL)
       
   182 	{
       
   183 		/* Test wall at opposites 1*/
       
   184 		if (m->Cells[new_pos.y+opposite1.y][new_pos.x+opposite1.x]
       
   185 			== WALL &&
       
   186 			m->man_moves[new_pos.y+mov.y][new_pos.x+mov.x] == BOX)
       
   187 		{
       
   188 				return TRUE;
       
   189 		}
       
   190 		else
       
   191 		if (m->man_moves[new_pos.y+opposite1.y][new_pos.x+opposite1.x]
       
   192 			== BOX &&
       
   193 			m->Cells[new_pos.y+mov.y][new_pos.x+mov.x] == WALL)
       
   194 		{
       
   195 				return TRUE;
       
   196 		}
       
   197 		/* Test wall at opposites 2 */
       
   198 		if (m->Cells[new_pos.y+opposite2.y][new_pos.x+opposite2.x]
       
   199 			== WALL &&
       
   200 			m->man_moves[new_pos.y+mov.y][new_pos.x+mov.x] == BOX)
       
   201 		{
       
   202 				return TRUE;
       
   203 		}
       
   204 		else
       
   205 		if (m->man_moves[new_pos.y+opposite2.y][new_pos.x+opposite2.x]
       
   206 			== BOX &&
       
   207 			m->Cells[new_pos.y+mov.y][new_pos.x+mov.x] == WALL)
       
   208 		{
       
   209 				return TRUE;
       
   210 		}
       
   211 	}
       
   212 
       
   213 	/* Test the second corner */
       
   214 	if (m->Cells[new_pos.y+mov.y+opposite2.y][new_pos.x+mov.x+opposite2.x]
       
   215 		== WALL)
       
   216 	{
       
   217 		/* Test wall at opposites 1*/
       
   218 		if (m->Cells[new_pos.y+opposite1.y][new_pos.x+opposite1.x]
       
   219 			== WALL &&
       
   220 			m->man_moves[new_pos.y+mov.y][new_pos.x+mov.x] == BOX)
       
   221 		{
       
   222 				return TRUE;
       
   223 		}
       
   224 		else
       
   225 		if (m->man_moves[new_pos.y+opposite1.y][new_pos.x+opposite1.x]
       
   226 			== BOX &&
       
   227 			m->Cells[new_pos.y+mov.y][new_pos.x+mov.x] == WALL)
       
   228 		{
       
   229 				return TRUE;
       
   230 		}
       
   231 		/* Test wall at opposites 2 */
       
   232 		if (m->Cells[new_pos.y+opposite2.y][new_pos.x+opposite2.x]
       
   233 			== WALL &&
       
   234 			m->man_moves[new_pos.y+mov.y][new_pos.x+mov.x] == BOX)
       
   235 		{
       
   236 				return TRUE;
       
   237 		}
       
   238 		else
       
   239 		if (m->man_moves[new_pos.y+opposite2.y][new_pos.x+opposite2.x]
       
   240 			== BOX &&
       
   241 			m->Cells[new_pos.y+mov.y][new_pos.x+mov.x] == WALL)
       
   242 		{
       
   243 				return TRUE;
       
   244 		}
       
   245 	}
       
   246 
       
   247 	return FALSE;
       
   248 }
       
   249 
       
   250 /*
       
   251 Catch the situation where a corner gets surrounded by boxes.
       
   252 */
       
   253 static int is_dead2(const struct Map * m, const struct Position mov,
       
   254 	const struct Position new_pos)
       
   255 {
       
   256 	struct Position next, opposite1, opposite2;
       
   257 
       
   258 	next.x = new_pos.x+mov.x;
       
   259 	next.y = new_pos.y+mov.y;
       
   260 
       
   261 	/* The corner must exist */
       
   262 	if (m->Cells[next.y][next.x] != CORNER)
       
   263 		return FALSE;
       
   264 
       
   265 
       
   266 	/* The wall corners must exist */
       
   267 	opposite1.x = next.x -mov.y;
       
   268 	opposite1.y = next.y -mov.x;
       
   269 	opposite2.x = next.x + mov.y;
       
   270 	opposite2.y = next.y + mov.x;
       
   271 
       
   272 	if (m->man_moves[opposite1.y][opposite1.x] == BOX)
       
   273 	{
       
   274 		if(m->Cells[opposite1.y+mov.y][opposite1.x+mov.x] == WALL
       
   275 		   && m->Cells[opposite1.y-mov.y][opposite1.x-mov.x] == WALL)
       
   276 		   return TRUE;
       
   277 	}
       
   278 
       
   279 	if (m->man_moves[opposite2.y][opposite2.x] == BOX)
       
   280 	{
       
   281 		if(m->Cells[opposite2.y+mov.y][opposite2.x+mov.x] == WALL
       
   282 		   && m->Cells[opposite2.y-mov.y][opposite2.x-mov.x] == WALL)
       
   283 		   return TRUE;
       
   284 	}
       
   285 	return FALSE;
       
   286 }
       
   287 
       
   288 static int is_box_movable(const struct Map * m, const struct Position mov,
       
   289 	const struct Position box_pos)
       
   290 {
       
   291 	struct Position next_pos2;
       
   292 
       
   293 	next_pos2.x = box_pos.x + mov.x;
       
   294 	next_pos2.y = box_pos.y + mov.y;
       
   295 
       
   296 	if((m->Cells[next_pos2.y][next_pos2.x] != BLANK &&
       
   297 		m->Cells[next_pos2.y][next_pos2.x] != PLATFORM) ||
       
   298 		m->man_moves[next_pos2.y][next_pos2.x] == BOX)
       
   299 	{
       
   300 		return FALSE;
       
   301 	}
       
   302 	else if (is_dead1(m, mov, next_pos2) == TRUE)
       
   303 	{
       
   304 		return FALSE;
       
   305 	}
       
   306 	else if (is_dead2(m, mov, next_pos2) == TRUE)
       
   307 	{
       
   308 		return FALSE;
       
   309 	}
       
   310 	return TRUE;
       
   311 }
       
   312 
       
   313 /* It modifies m->man_moves */
       
   314 static int get_box_movements(struct Map * m,
       
   315 	struct BoxMove movements[])
       
   316 {
       
   317 	struct Position pos[MAX_MOVES];
       
   318 	struct Position new_pos[MAX_MOVES];
       
   319 	int NumMoves, NewMoves;
       
   320 	int j, i;
       
   321 	struct Position next_pos;
       
   322 	char *next_cell;
       
   323 	int num_box_movements = 0;
       
   324 	
       
   325 	/* Let's  the map with only walls in man_moves - other, blanks */
       
   326 	for (j = 0; j<m->SizeY; j++)
       
   327 		for (i=0; i<m->SizeX; i++)
       
   328 		{
       
   329 			if (m->Cells[j][i] == WALL)
       
   330 				m->man_moves[j][i] = WALL;
       
   331 			else
       
   332 				m->man_moves[j][i] = BLANK;
       
   333 		}
       
   334 
       
   335 	/* Let's put the boxes */
       
   336 	for (i = 0; i<m->NumBoxes; i++)
       
   337 	{
       
   338 		m->man_moves[m->Box[i].y][m->Box[i].x] = BOX;
       
   339 		m->cells_boxes[m->Box[i].y][m->Box[i].x] = i;
       
   340 	}
       
   341 
       
   342 	NewMoves = 1;
       
   343 	new_pos[0].x = m->Man.x;
       
   344 	new_pos[0].y = m->Man.y;
       
   345 	m->man_moves[m->Man.y][m->Man.x] = MANCANMOVE;
       
   346 	while (NewMoves > 0)
       
   347 	{
       
   348 		/* The before named "New Moves" become the moves we have
       
   349 		   to analyze */
       
   350 		NumMoves = NewMoves;
       
   351 		for (i=0; i<NewMoves; i++)
       
   352 		{
       
   353 			pos[i] = new_pos[i];
       
   354 		}
       
   355 
       
   356 		/* Search new positions for each position */
       
   357 		NewMoves = 0;
       
   358 		for (i=0; i<NumMoves; i++)
       
   359 		{
       
   360 			/* For each direction */
       
   361 			for (j=0; j<4; j++)
       
   362 			{
       
   363 				next_pos.x = pos[i].x + move_vectors[j].x;
       
   364 				next_pos.y = pos[i].y + move_vectors[j].y;
       
   365 				next_cell = &m->man_moves[next_pos.y][next_pos.x];
       
   366 				if(*next_cell == BLANK)
       
   367 				{
       
   368 					new_pos[NewMoves] = next_pos;
       
   369 					*next_cell = MANCANMOVE;
       
   370 					NewMoves++;
       
   371 				}
       
   372 				else if (*next_cell == BOX)
       
   373 				{
       
   374 						
       
   375 					/* Check if the box is movable */
       
   376 
       
   377 					if (is_box_movable(m, move_vectors[j],
       
   378 						next_pos ))
       
   379 					{
       
   380 						{
       
   381 					movements[num_box_movements].box =
       
   382 					m->cells_boxes[next_pos.y][next_pos.x];
       
   383 					movements[num_box_movements].dir =
       
   384 					move_vectors[j];
       
   385 					num_box_movements++;
       
   386 						}
       
   387 					}
       
   388 					
       
   389 				}
       
   390 
       
   391 			}
       
   392 		}
       
   393 	}
       
   394 
       
   395 	return num_box_movements;
       
   396 }
       
   397 
   170 
   398 static void force_move_box(struct Map *m, const struct BoxMove move)
   171 static void force_move_box(struct Map *m, const struct BoxMove move)
   399 {
   172 {
   400 	struct Position newpos;
   173 	struct Position newpos;
   401 
   174 
   424 	m->Box[move.box] = newpos;
   197 	m->Box[move.box] = newpos;
   425 }
   198 }
   426 
   199 
   427 
   200 
   428 
   201 
   429 static int search_depth(struct Map maps[], int depth,
   202 static Bool search_did_found(struct Map maps[], int depth,
   430 	struct BoxMove movements[],
   203 	struct BoxMove movements[],
   431 	int num_movements, float percent, float total_percent)
   204 	int num_movements, float percent, float total_percent)
   432 {
   205 {
   433 	struct BoxMove new_movements[MAX_MOVES];
   206 	struct BoxMove new_movements[MAX_MOVES];
   434 	int num_new_movements;
   207 	int num_new_movements;
   448 
   221 
   449 	for (i=0; i < num_movements; i++)
   222 	for (i=0; i < num_movements; i++)
   450 	{
   223 	{
   451 		CopyMap(m, &maps[depth]);
   224 		CopyMap(m, &maps[depth]);
   452 		force_move_box(m, movements[i]);
   225 		force_move_box(m, movements[i]);
       
   226 		/* Let's see if we finished */
   453 		if (m->NumPlatforms == m->NumBoxesInPlatform)
   227 		if (m->NumPlatforms == m->NumBoxesInPlatform)
   454 		{
   228 		{
   455 			PrintMove(movements[i]);
   229 			PrintMove(movements[i]);
   456 			return 0;
   230 			actual_map = &maps[depth+1];
       
   231 			show_percent_and_map();
       
   232 			return TRUE;
   457 		}
   233 		}
   458 
   234 
   459 		if (is_new_map(maps, depth+1))
   235 		if (is_new_map(maps, depth+1))
   460 		{
   236 		{
   461 			num_new_movements = get_box_movements(m, new_movements);
   237 			actual_map = &maps[depth+1];
       
   238 #ifdef DEBUG		/* to be out */
       
   239 			show_percent_and_map();
       
   240 #endif
       
   241 			fill_deps(m);
       
   242 			if (are_there_fixed_boxes(m,
       
   243 				new_movements, &num_new_movements))
       
   244 			{
       
   245 				/* That means that the map is illegal */
       
   246 				/* Maybe we could update the percent here... */
       
   247 				return FALSE;
       
   248 			}
       
   249 			/* the assert should be IN the function before,
       
   250 			   before OVERfilling new_movements */
   462 			assert(num_new_movements < MAX_MOVES);
   251 			assert(num_new_movements < MAX_MOVES);
   463 		}
   252 		}
   464 		else
   253 		else
   465 			num_new_movements = 0;
   254 			num_new_movements = 0;
   466 
   255 
   467 		if (num_new_movements == 0)
   256 		if (num_new_movements == 0)
   468 		{
   257 		{
   469 			percent_to_show = total_percent + next_percent*i;
   258 			percent_to_show = total_percent + next_percent*i;
   470 			depth_to_show = depth;
   259 			depth_to_show = depth;
   471 			actual_map = &maps[depth];
   260 		}
   472 #ifdef DEBUG		/* to be out */
   261 		else
   473 			show_percent_callback(0);
   262 		{
   474 #endif
   263 			if (depth+1 < MAX_STEPS)
       
   264 			{
       
   265 				if(search_did_found(maps, depth+1, new_movements,
       
   266 					num_new_movements, next_percent,
       
   267 					total_percent + next_percent*i) == TRUE)
       
   268 				{
       
   269 					PrintMove(movements[i]);
       
   270 					actual_map = &maps[depth+1];
       
   271 					show_percent_and_map();
       
   272 					return TRUE;
       
   273 				}
       
   274 			}
       
   275 		}
       
   276 	}
       
   277 	return FALSE;
       
   278 }
       
   279 
       
   280 
       
   281 /* It only fills the m->man_moves structure */
       
   282 static void paint_mancanmove(struct Map *m)
       
   283 {
       
   284 	struct Position pos[MAX_MOVES];
       
   285 	struct Position new_pos[MAX_MOVES];
       
   286 	int NumMoves, NewMoves;
       
   287 	int j, i;
       
   288 	struct Position next_pos;
       
   289 	char *next_cell;
       
   290 
       
   291 	/* Let's  the map with only walls in man_moves - other, blanks */
       
   292 	for (j = 0; j<m->SizeY; j++)
       
   293 		for (i=0; i<m->SizeX; i++)
       
   294 		{
       
   295 			if (m->Cells[j][i] == WALL)
       
   296 				m->man_moves[j][i] = WALL;
       
   297 			else
       
   298 				m->man_moves[j][i] = BLANK;
       
   299 		}
       
   300 
       
   301 	/* Let's put the boxes */
       
   302 	for (i = 0; i<m->NumBoxes; i++)
       
   303 	{
       
   304 		m->man_moves[m->Box[i].y][m->Box[i].x] = WALL;
       
   305 	}
       
   306 
       
   307 	NewMoves = 1;
       
   308 	new_pos[0].x = m->Man.x;
       
   309 	new_pos[0].y = m->Man.y;
       
   310 	m->man_moves[m->Man.y][m->Man.x] = MANCANMOVE;
       
   311 	while (NewMoves > 0)
       
   312 	{
       
   313 		/* The before named "New Moves" become the moves we have
       
   314 		   to analyze */
       
   315 		NumMoves = NewMoves;
       
   316 		for (i=0; i<NewMoves; i++)
       
   317 		{
       
   318 			pos[i] = new_pos[i];
       
   319 		}
       
   320 
       
   321 		/* Search new positions for each position */
       
   322 		NewMoves = 0;
       
   323 		for (i=0; i<NumMoves; i++)
       
   324 		{
       
   325 			/* For each direction */
       
   326 			for (j=0; j<4; j++)
       
   327 			{
       
   328 				next_pos.x = pos[i].x + move_vectors[j].x;
       
   329 				next_pos.y = pos[i].y + move_vectors[j].y;
       
   330 				next_cell = &m->man_moves[next_pos.y][next_pos.x];
       
   331 				if(*next_cell == BLANK)
       
   332 				{
       
   333 					new_pos[NewMoves] = next_pos;
       
   334 					*next_cell = MANCANMOVE;
       
   335 					NewMoves++;
       
   336 				}
       
   337 			}
       
   338 		}
       
   339 	}
       
   340 }
       
   341 
       
   342 /* Returns TRUE if there are fixed boxes that should be moved, FALSE otherwise*/
       
   343 /* For 'm' it modifies only m->boxes[][] */
       
   344 static Bool are_there_fixed_boxes(struct Map *m,
       
   345 	struct BoxMove movements[MAX_MOVES], int *num_movements)
       
   346 {
       
   347 	int i,j;
       
   348 	enum e_direction d;
       
   349 
       
   350 	/* Box dependencies. The first depends on seconds. */
       
   351 	struct
       
   352 	{
       
   353 		Bool box[MAX_BOXES][MAX_BOXES];
       
   354 		int ndeps[MAX_BOXES];
       
   355 	} dep;
       
   356 
       
   357 	/* Free boxes' arrays */
       
   358 	struct
       
   359 	{
       
   360 		Bool box_is_free[MAX_BOXES]; /* This is only used in 'free' */
       
   361 		int box[MAX_BOXES];
       
   362 		int n;
       
   363 	} free,			/* List of all boxes free-to-move */
       
   364 		new_free,	/* List of boxes for the next loop (code) */
       
   365 		tfree;	/* List of boxes of the loop (code) */
       
   366 
       
   367 	struct Position tpos;
       
   368 
       
   369 	Bool is_not_set_free;
       
   370 
       
   371 	/* Initialize to 0 the dependency structures */
       
   372 	memset((void *) &dep, 0, sizeof(dep));
       
   373 	for(i=0; i<m->NumBoxes; i++)
       
   374 	{
       
   375 		new_free.box[i] = FALSE;
       
   376 	}
       
   377 
       
   378 	/* Let's fill the structure */
       
   379 	for(i=0; i<m->NumBoxes; i++)
       
   380 	{
       
   381 		/* See if the box is blocked. That could be
       
   382 		   done in fill_deps */
       
   383 		if (m->box_deps[i].dep_dir[0] == BLOCKED &&
       
   384 			m->box_deps[i].dep_dir[1] == BLOCKED &&
       
   385 			m->box_deps[i].dep_dir[2] == BLOCKED &&
       
   386 			m->box_deps[i].dep_dir[3] == BLOCKED )
       
   387 		{
       
   388 			if (m->Cells[m->Box[i].y][m->Box[i].x] !=
       
   389 				PLATFORM)
       
   390 				return TRUE;
       
   391 			/* This is not used actually 
       
   392 			else
       
   393 				m->boxes[m->Box[i].y][m->Box[i].x] =
       
   394 					WALL;
       
   395 			*/
       
   396 		}
       
   397 		/* Let's take note of the dependencies */
       
   398 		is_not_set_free = TRUE;
       
   399 		for(d=0; d<4; d++)
       
   400 		{
       
   401 			if(m->box_deps[i].dep_dir[d] > 0)
       
   402 			{
       
   403 				dep.box[i][m->box_deps[i].dep_dir[d]] =
       
   404 					TRUE;
       
   405 				dep.ndeps[i]++;
       
   406 			} else
       
   407 			if(m->box_deps[i].dep_dir[d] == FREE)
       
   408 			{
       
   409 				if (is_not_set_free)
       
   410 				{
       
   411 					new_free.box[new_free.n++] = i;
       
   412 					is_not_set_free = FALSE;
       
   413 				}
       
   414 			}
       
   415 		}
       
   416 	}
       
   417 
       
   418 	/* Let's analyze if the free boxes can really be moved, and
       
   419 	   set them as dependant, if they're dependant.
       
   420 	   If some can be really moved, we should know _where to_. */
       
   421 
       
   422 	/* Paint MANCANMOVE at each cell the man can reach */
       
   423 	paint_mancanmove(m);
   475 	
   424 	
   476 		}
   425 	/* For each free movable box, let's see if the man can reach them
   477 		else
   426 	   fine. If we can, add it to the possible movements. */
   478 		{
   427 	*num_movements=0;
   479 			if (depth+1 < MAX_STEPS)
   428 	for(i=0; i<new_free.n; i++)
   480 			{
   429 	{
   481 				if(search_depth(maps, depth+1, new_movements,
   430 		/* For each direction, try if the box can be moved */
   482 					num_new_movements, next_percent,
   431 		for(d=0; d<4; d++)
   483 					total_percent + next_percent*i) == 0)
   432 		{
   484 				{
   433 			if(m->box_deps[i].dep_dir[d] == FREE)
   485 					PrintMove(movements[i]);
   434 			{
   486 					return 0;
   435 				add_position3(tpos, m->Box[i], move_vectors[OPPOSITE_DIR(d)])
   487 				}
   436 				if (m->man_moves[tpos.y][tpos.x] == MANCANMOVE)
   488 			}
   437 				{
   489 		}
   438 					movements[*num_movements].box = i;
   490 	}
   439 					movements[*num_movements].dir =
   491 	return 1;
   440 						move_vectors[d];
       
   441 					(*num_movements)++;
       
   442 				}
       
   443 				/* ELSE - we should catch those cases,
       
   444 				where free boxes cannot be moved. Will they
       
   445 				ever be movable? 
       
   446 				THIS HAS TO BE IMPROVED */
       
   447 			}
       
   448 		}
       
   449 	}
       
   450 
       
   451 
       
   452 	/* ---------------- The next possible movements have been calculated --
       
   453 	We can still find that this map is illegal. We need to find
       
   454 	further more if there are boxes unmovable (due to dependencies) */
       
   455 
       
   456 	/* Let's take out all dependencies from 'free' boxes */
       
   457 	/* Prepare the 'free' list */
       
   458 	for(i=0; i<m->NumBoxes;i++)
       
   459 		free.box_is_free[i] = FALSE;
       
   460 	free.n = new_free.n;
       
   461 	for(i=0; i<new_free.n; i++)
       
   462 	{
       
   463 		free.box[i] = new_free.box[i];
       
   464 		free.box_is_free[i] = TRUE;
       
   465 	}
       
   466 
       
   467 	/* KACXO-loop  */
       
   468 	while (new_free.n > 0)
       
   469 	{
       
   470 		/* Copy new_free into free */
       
   471 		tfree.n = new_free.n;
       
   472 		for(i=0; i<new_free.n; i++)
       
   473 			tfree.box[i] = new_free.box[i];
       
   474 		new_free.n = 0;
       
   475 
       
   476 		for(i=0; i<tfree.n; i++)
       
   477 		{
       
   478 			for(j=0; j<m->NumBoxes; j++)
       
   479 			{
       
   480 				/* The box j no more depends on
       
   481 				   the box tfree[i] */
       
   482 				if(dep.box[j][tfree.box[i]])
       
   483 				{
       
   484 					dep.box[j][tfree.box[i]] = FALSE;
       
   485 					dep.ndeps[j]--;
       
   486 					assert(dep.ndeps[j] >= 0);
       
   487 					if (dep.ndeps[j] == 0 &&
       
   488 						!free.box_is_free[i])
       
   489 					{
       
   490 						new_free.box[new_free.n++]=j;
       
   491 						free.box[free.n++]=j;
       
   492 					}
       
   493 				}
       
   494 			}
       
   495 		}
       
   496 	}
       
   497 
       
   498 	/* Now are left only boxes which depend on others-non-free */
       
   499 	for(i=0; i<m->NumBoxes; i++)
       
   500 	{
       
   501 		for(j=0; j<m->NumBoxes; j++)
       
   502 		{
       
   503 			/* We only do one-level search !!! */
       
   504 			/* If the box only depends on another,
       
   505 			   which also only depends on this... */
       
   506 			if (dep.box[i][j] && dep.ndeps[i] == 1
       
   507 				&& dep.box[j][i] && dep.ndeps[j] == 1)
       
   508 			{
       
   509 				if (m->Cells[m->Box[i].y][m->Box[i].x]!=
       
   510 					PLATFORM)
       
   511 				{
       
   512 					return TRUE;
       
   513 				}
       
   514 				/* We don't set any wall here, they're not
       
   515 				   important */
       
   516 			}
       
   517 		}
       
   518 	}
       
   519 
       
   520 	return FALSE;
       
   521 }
       
   522 
       
   523 static void init_cell_boxes(struct Map *m)
       
   524 {
       
   525 	int i,j;
       
   526 
       
   527 	/* Let's  the map with only walls in man_moves - other, blanks */
       
   528 	for (j = 0; j<m->SizeY; j++)
       
   529 		for (i=0; i<m->SizeX; i++)
       
   530 			m->cells_boxes[j][i] = -1;
       
   531 
       
   532 	for(i=0; i<m->NumBoxes; i++)
       
   533 	{
       
   534 		m->cells_boxes[m->Box[i].y][m->Box[i].x] = i;
       
   535 	}
       
   536 }
       
   537 
       
   538 /* It fills only m->box_deps */
       
   539 static void fill_deps(struct Map *m)
       
   540 {
       
   541 	int i;
       
   542 	enum e_direction dir;
       
   543 	struct Position n; /* Position next to the box */
       
   544 
       
   545 	/* TO BE OPTIMIZED - get into force_move_box */
       
   546 	init_cell_boxes(m);
       
   547 
       
   548 	for(i=0; i<m->NumBoxes; i++)
       
   549 	{
       
   550 		/* Initialize the move freedom */
       
   551 		for(dir=0;dir<4; dir++)
       
   552 		{
       
   553 			m->box_deps[i].dep_dir[dir] = FREE;
       
   554 		}
       
   555 
       
   556 		/* Limit the freedom */
       
   557 		for(dir=0;dir<4; dir++)
       
   558 		{
       
   559 			add_position3(n,m->Box[i],move_vectors[dir]);
       
   560 			if(m->Cells[n.y][n.x] == WALL)
       
   561 			{
       
   562 				/* IMPROVEMENT: The fixed-box detection
       
   563 				could be done here */
       
   564 				m->box_deps[i].dep_dir[dir] = BLOCKED;
       
   565 				m->box_deps[i].dep_dir[OPPOSITE_DIR(dir)] =
       
   566 					BLOCKED;
       
   567 				continue;
       
   568 			}
       
   569 
       
   570 			/* if there is Wall limit, we don't want to set box
       
   571 			   dependency */
       
   572 			if(m->box_deps[i].dep_dir[dir] == WALL)
       
   573 				continue;
       
   574 
       
   575 			/* Put the box dependency in the list */
       
   576 			if(m->cells_boxes[n.y][n.x] >= 0)
       
   577 			{
       
   578 				m->box_deps[i].dep_dir[dir] =
       
   579 					m->cells_boxes[n.y][n.x];
       
   580 				/* If the other site is not limited by another
       
   581 				   box, we set it up too. */
       
   582 
       
   583 				/* *** MAYBE IT'S BETTER NOT TO SET IT */
       
   584 				if(m->box_deps[i].dep_dir[dir] == FREE)
       
   585 				{
       
   586 				m->box_deps[i].dep_dir[OPPOSITE_DIR(dir)] =
       
   587 					m->cells_boxes[n.y][n.x];
       
   588 				}
       
   589 				continue;
       
   590 			}
       
   591 			if(m->Cells[n.y][n.x] == CORNER)
       
   592 				m->box_deps[i].dep_dir[dir] = BLOCKED;
       
   593 				
       
   594 		}
       
   595 	}
   492 }
   596 }
   493 
   597 
   494 
   598 
   495 int solve_map(const struct Map origin)
   599 int solve_map(const struct Map origin)
   496 {
   600 {
   498 	struct BoxMove new_movements[MAX_MOVES];
   602 	struct BoxMove new_movements[MAX_MOVES];
   499 	int num_new_movements;
   603 	int num_new_movements;
   500 
   604 
   501 	CopyMap(&maps[0], &origin);
   605 	CopyMap(&maps[0], &origin);
   502 
   606 
   503 	num_new_movements = get_box_movements(&maps[0], new_movements);
   607 	fill_deps(&maps[0]);
   504 	assert(num_new_movements < MAX_MOVES);
   608 	assert(!are_there_fixed_boxes(&maps[0], new_movements,
   505 	assert(num_new_movements > 0);
   609 		&num_new_movements));
   506 
   610 	search_did_found(maps, 0, new_movements, num_new_movements, 100, 0);
   507 	init_os();
   611 
   508 
   612 	return 0;
   509 	return search_depth(maps, 0, new_movements,
   613 }
   510 		num_new_movements, 100. / num_new_movements,
       
   511 		0);
       
   512 
       
   513 }