diff options
| author | Ian C <ianc@noddybox.co.uk> | 2017-05-18 14:35:15 +0000 | 
|---|---|---|
| committer | Ian C <ianc@noddybox.co.uk> | 2017-05-18 14:35:15 +0000 | 
| commit | 47d2ee2d01eb01c8234fddfd1ea895c1780d728e (patch) | |
| tree | 3c18db44b9a90a7f9382ef6d6584f58498eba993 | |
| parent | 2ace641d4457d0bbd03da2c3a079d60efd65a9d6 (diff) | |
Rolled back to previous version.  For some reason it managed to commit an
older implementation.
| -rw-r--r-- | dbox.c | 162 | 
1 files changed, 72 insertions, 90 deletions
| @@ -68,18 +68,12 @@ typedef enum {SPACE_GL=' ',  #define DIR_RIGHT	2  #define DIR_DOWN	3 -typedef struct -{ -    int		x; -    int		y; -} pos_t; - -static const pos_t g_move_dir[4]={{-1,0},{0,-1},{1,0},{0,1}}; +static int g_move_dir[4] = {-1, -1, 1, 1};  typedef struct state_t  { -    pos_t		player; -    pos_t		*box; +    int			player; +    int			*box;      int			path;      int			dir;      int			pushed; @@ -99,19 +93,19 @@ typedef struct      int			height;      int			no_targets;      int			no_boxes; -    pos_t		*target; +    int			*target;      glyph_t		*map;      state_t		*state;  } level_t;  #define AT(l,x,y)	((l)->map[(l)->width*(y)+(x)]) +#define ATP(l,p)	((l)->map[p])  /* State caches  */  typedef struct cache_t  {      const state_t	*state; -    map_t		*map;      struct cache_t	*next;  } cache_t; @@ -188,11 +182,11 @@ static void *Copy(const void *p_source, size_t p_size)  } -static const pos_t *FindPos(const pos_t *p_poslist, int p_no, int p_x, int p_y) +static const int *FindPos(const int *p_poslist, int p_no, int p_p)  {      while(p_no--)      { -	if (p_poslist->x == p_x && p_poslist->y == p_y) +	if (*p_poslist == p_p)  	{  	    return p_poslist;  	} @@ -204,11 +198,11 @@ static const pos_t *FindPos(const pos_t *p_poslist, int p_no, int p_x, int p_y)  } -static pos_t *FindPosForUpdate(pos_t *p_poslist, int p_no, int p_x, int p_y) +static int *FindPosForUpdate(int *p_poslist, int p_no, int p_p)  {      while(p_no--)      { -	if (p_poslist->x == p_x && p_poslist->y == p_y) +	if (*p_poslist == p_p)  	{  	    return p_poslist;  	} @@ -227,9 +221,7 @@ static const char *GetLine(FILE *p_fp)      static char s[1024];      size_t l; -    fgets(s, sizeof s, p_fp); - -    if (feof(p_fp)) +    if (!fgets(s, sizeof s, p_fp))      {  	return NULL;      } @@ -364,8 +356,7 @@ static level_t *Load(const char *p_path)  		case BOX_TARGET_GL:  		case TARGET_GL:  		    AT(new,x,y) = SPACE_GL; -		    new->target[tno].x = x; -		    new->target[tno].y = y; +		    new->target[tno] = x + y * new->width;  		    tno++;  		    /* NOTE: Runs into following case for BOX_TARGET_GL @@ -377,8 +368,7 @@ static level_t *Load(const char *p_path)  		case BOX_GL:  		    AT(new,x,y) = SPACE_GL; -		    new->state->box[bno].x = x; -		    new->state->box[bno].y = y; +		    new->state->box[bno] = x + y * new->width;  		    bno++;  		    break; @@ -392,8 +382,7 @@ static level_t *Load(const char *p_path)  		    }  		    AT(new,x,y) = SPACE_GL; -		    new->state->player.x = x; -		    new->state->player.y = y; +		    new->state->player = x + y * new->width;  		    break;  		default: @@ -440,24 +429,28 @@ static void Display(const level_t *p_level, const state_t *p_state)  static char GetGlyph(const level_t *p_level, const state_t *p_state,  		     int p_x, int p_y)  { +    int p; + +    p = p_x + p_y * p_level->width; +      if (AT(p_level, p_x, p_y) == WALL_GL)      {  	return WALL_GL;      } -    else if (FindPos(&p_state->player, 1, p_x, p_y)) +    else if (FindPos(&p_state->player, 1, p))      {  	return PLAYER_GL;      } -    else if (FindPos(p_state->box, p_level->no_boxes, p_x, p_y) && -		FindPos(p_level->target, p_level->no_targets, p_x, p_y)) +    else if (FindPos(p_state->box, p_level->no_boxes, p) && +		FindPos(p_level->target, p_level->no_targets, p))      {  	return BOX_TARGET_GL;      } -    else if (FindPos(p_state->box, p_level->no_boxes, p_x, p_y)) +    else if (FindPos(p_state->box, p_level->no_boxes, p))      {  	return BOX_GL;      } -    else if (FindPos(p_level->target, p_level->no_targets, p_x, p_y)) +    else if (FindPos(p_level->target, p_level->no_targets, p))      {  	return TARGET_GL;      } @@ -490,7 +483,6 @@ static void ClearStates(void)  	    cache_t *p;  	    p = g_cache[f]->next; -	    free(g_cache[f]->map);  	    free(g_cache[f]);  	    g_cache[f] = p;  	} @@ -510,11 +502,13 @@ static map_t *CreateMap(const level_t *p_level, const state_t *p_state)      	m[f] = 0;      } -    m[p_state->player.y] = 0x01llu << (p_state->player.x * 2); +    m[p_state->player / p_level->width] = +    	0x01llu << ((p_state->player % p_level->width) * 2);      for(f = 0; f < p_level->no_boxes; f++)      { -	m[p_state->box[f].y] |= 0x10llu << (p_state->box[f].x * 2); +	m[p_state->box[f] / p_level->width] |= +	    0x10llu << ((p_state->box[f] % p_level->width) * 2);      }      return m; @@ -542,7 +536,7 @@ static map_t CreateHash(const level_t *p_level, const state_t *p_state)      m = CreateMap(p_level, p_state); -    hash = p_state->player.x * p_state->player.y; +    hash = p_state->player;      for(f = 0; f < p_level->height; f++)      { @@ -585,32 +579,31 @@ static void DumpCacheDistribution(void)  static int AddNewState(const level_t *p_level, const state_t *p_state)  {      cache_t *p; -    map_t *map;      map_t hash;      hash = p_state->hash % CACHE_SIZE;      p = g_cache[hash]; -    map = CreateMap(p_level, p_state);      while(p)      { -	if (p_state->player.x == p->state->player.x && -		p_state->player.y == p->state->player.y) +	if (p_state->player == p->state->player)  	{  	    int f;  	    map_t check; -	    check = 0; +	    check = FALSE; -	    for(f = 0; f < p_level->height; f++) +	    for(f = 0; f < p_level->no_boxes && !check; f++)  	    { -		check |= (map[f] ^ p->map[f]); +	    	if (!FindPos(p->state->box, p_level->no_boxes, p_state->box[f])) +		{ +		    check = TRUE; +		}  	    } -	    if (check == 0) +	    if (!check)  	    { -		free(map);  		return FALSE;  	    }  	} @@ -621,7 +614,6 @@ static int AddNewState(const level_t *p_level, const state_t *p_state)      p = Grab(sizeof *p);      p->state = p_state; -    p->map = map;      p->next = g_cache[hash];      g_cache[hash] = p; @@ -655,13 +647,11 @@ static int CheckImpossible(const level_t *p_level, const state_t *p_state)      for(f = 0; f < p_level->no_boxes; f++)      { -	int x; -	int y; +	int p; -	x = p_state->box[f].x; -	y = p_state->box[f].y; +	p = p_state->box[f]; -	if (!FindPos(p_level->target, p_level->no_targets, x, y)) +	if (!FindPos(p_level->target, p_level->no_targets, p))  	{  	    int d;  	    int any_move; @@ -673,21 +663,17 @@ static int CheckImpossible(const level_t *p_level, const state_t *p_state)  	    for(d = 0; d < 4 && !any_move; d++)  	    { -		int nx; -		int ny; +		int np; -		nx = x + g_move_dir[d].x; -		ny = y + g_move_dir[d].y; +		np = p + g_move_dir[d]; -		if (AT(p_level, nx, ny) != WALL_GL) +		if (ATP(p_level, np) != WALL_GL)  		{ -		    int ox; -		    int oy; +		    int op; -		    ox = x + g_move_dir[(d+2)%4].x; -		    oy = y + g_move_dir[(d+2)%4].y; +		    op = p + g_move_dir[(d+2)%4]; -		    if (AT(p_level, ox, oy) != WALL_GL) +		    if (ATP(p_level, op) != WALL_GL)  		    {  		    	any_move=TRUE;  		    } @@ -696,17 +682,19 @@ static int CheckImpossible(const level_t *p_level, const state_t *p_state)  	    if (!any_move)  	    { -		NoMoveReason("Couldn't push block at %d,%d", x, y); +		NoMoveReason("Couldn't push block at %d, %d", +					p%p_level->width, p/p_level->width);  		return TRUE;  	    }  	    /* Four blocks together is impossible  	    */ -	    if (FindPos(p_state->box, p_level->no_boxes, x+1, y) && -	    	FindPos(p_state->box, p_level->no_boxes, x,   y+1) && -	    	FindPos(p_state->box, p_level->no_boxes, x+1, y+1)) +	    if (FindPos(p_state->box, p_level->no_boxes, p+1) && +	    	FindPos(p_state->box, p_level->no_boxes, p+p_level->width) && +	    	FindPos(p_state->box, p_level->no_boxes, p+p_level->width+1))  	    { -		NoMoveReason("Group of 4 boxes at %d,%d", x, y); +		NoMoveReason("Group of 4 boxes at %d, %d", +					p%p_level->width, p/p_level->width);  	    	return TRUE;  	    }  	} @@ -721,44 +709,40 @@ static state_t *CreateState(int p_dir, int p_must_push,  			    int p_check_possible)  {      state_t *new; -    const pos_t *p; -    int x,y; +    const int *p; +    int np;      int push; -    int dx,dy; - -    dx = g_move_dir[p_dir].x; -    dy = g_move_dir[p_dir].y; +    int px;      push = FALSE; -    x = p_state->player.x + dx; -    y = p_state->player.y + dy; +    px = g_move_dir[p_dir]; + +    np = p_state->player + px;      /* Check for walls      */ -    if (AT(p_level, x, y) == WALL_GL) +    if (ATP(p_level, np) == WALL_GL)      {      	return NULL;      }      /* Check for boxes      */ -    if ((p = FindPos(p_state->box, p_level->no_boxes, x, y))) +    if ((p = FindPos(p_state->box, p_level->no_boxes, np)))      { -	int bx; -	int by; +	int bp;  	/* Can the box be pushed?  	*/ -	bx = p->x+dx; -	by = p->y+dy; +	bp = *p+px; -	if (AT(p_level, bx, by) == WALL_GL) +	if (ATP(p_level, bp) == WALL_GL)  	{  	    return NULL;  	} -	if (FindPos(p_state->box, p_level->no_boxes, bx, by)) +	if (FindPos(p_state->box, p_level->no_boxes, bp))  	{  	    return NULL;  	} @@ -772,19 +756,17 @@ static state_t *CreateState(int p_dir, int p_must_push,      }      new = Grab(sizeof *new); -    new->box = Copy(p_state->box, sizeof(pos_t) * p_level->no_boxes); +    new->box = Copy(p_state->box, sizeof(int) * p_level->no_boxes); -    new->player.x = x; -    new->player.y = y; +    new->player = np;      if (push)      { -	pos_t *pd; +	int *pd; -	pd = FindPosForUpdate(new->box, p_level->no_boxes, x, y); +	pd = FindPosForUpdate(new->box, p_level->no_boxes, np); -	pd->x += dx; -	pd->y += dy; +	*pd += px;  	/* (Very) basic checks to see if the move has made the level impossible  	*/ @@ -905,10 +887,7 @@ static void SubSolve(const level_t *p_level, state_t *p_state, int p_depth,  	for(f = 0; f < p_level->no_targets && ok; f++)  	{ -	    if (!FindPos(s->box, -			 p_level->no_boxes, -	    		 p_level->target[f].x, -			 p_level->target[f].y)) +	    if (!FindPos(s->box, p_level->no_boxes, p_level->target[f]))  	    {  		ok = FALSE;  	    } @@ -1421,6 +1400,9 @@ int main(int argc, char *argv[])  	}  	else  	{ +	    g_move_dir[DIR_UP] = -level->width; +	    g_move_dir[DIR_DOWN] = level->width; +  	    if (interact)  	    {  	    	Interactive(level, play, check); | 
