Skip to content

Commit

Permalink
Add display of "Box Changes".
Browse files Browse the repository at this point in the history
  • Loading branch information
siebenstreich committed Dec 5, 2021
1 parent a1ddf5b commit 9a4eeb4
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ SOURCES=base.c settings.c sokoban.c sokoban2.c solver.c savitch.c solution.c
OBJECTS=$(SOURCES:.c=.o)

DEPS=gtk+-2.0 libpcre sqlite3
CFLAGS=`pkg-config --cflags $(DEPS)`
CFLAGS=-O2 `pkg-config --cflags $(DEPS)`
LIBS=-lz `pkg-config --libs $(DEPS)`

all: usokoban $(OBJECTS)
Expand Down
70 changes: 61 additions & 9 deletions sokoban.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,11 +453,14 @@ void sokoban_copy_all(SOKOBAN *skb1, SOKOBAN *skb2) // skb->hint is not copy yet
skb1->pj=skb2->pj;
skb1->bi=skb2->bi;
skb1->bj=skb2->bj;
skb1->box_i=skb2->box_i;
skb1->box_j=skb2->box_j;
skb1->level_len=skb2->level_len;
skb1->solution_len=skb2->solution_len;
skb1->solution_tail=skb2->solution_tail;
skb1->solution_head=skb2->solution_head;
skb1->n_push=skb2->n_push;
skb1->n_boxchange=skb2->n_boxchange;
skb1->mode=skb2->mode;

free(skb1->level);free(skb1->target); free(skb1->solution);
Expand Down Expand Up @@ -1142,7 +1145,7 @@ int sokoban_redo(SOKOBAN *skb)
/* return 1 if undo take place, 0 otherwise */
int sokoban_undo(SOKOBAN *skb)
{
int di=0,dj=0;
int di=0,dj=0,i,done;

if(skb->solution_tail==0) return 0; //already return to the begining

Expand All @@ -1151,7 +1154,7 @@ int sokoban_undo(SOKOBAN *skb)
switch(skb->solution[skb->solution_tail])
{
case SM_UP: case SM_PUSH_UP: di=-1; break;
case SM_DOWN: case SM_PUSH_DOWN: di=1; break;
case SM_DOWN: case SM_PUSH_DOWN: di=1; break;
case SM_LEFT: case SM_PUSH_LEFT: dj=-1; break;
case SM_RIGHT: case SM_PUSH_RIGHT: dj=1; break;
}
Expand All @@ -1168,14 +1171,48 @@ int sokoban_undo(SOKOBAN *skb)
default: //i.e. push
skb->level[(skb->pi)*skb->w+skb->pj]='$';
skb->level[(skb->pi+di)*skb->w+skb->pj+dj]='-';
skb->n_push--;
--skb->n_push;

// find last box which has been touched previously.
// needed for updating box_i, box_j, n_boxchange
i = skb->solution_tail;
skb->box_i = (skb->pi)-di; // start with the position of man after reverting the last move
skb->box_j = (skb->pj)-dj;
done = 0;
while (!done) {
if (i==0) {
// reverted push was the first push
skb->box_i = -1;
skb->box_j = -1;
done = 1;
} else {
--i;
switch(skb->solution[i]) {
// as long as man was moving: trace the position of the man
case SM_UP: ++skb->box_i; break;
case SM_DOWN: --skb->box_i; break;
case SM_LEFT: ++skb->box_j; break;
case SM_RIGHT: --skb->box_j; break;

// found the last push: now switch to the old box position
case SM_PUSH_UP: --skb->box_i; done = 1;break;
case SM_PUSH_DOWN: ++skb->box_i; done = 1;break;
case SM_PUSH_LEFT: --skb->box_j; done = 1;break;
case SM_PUSH_RIGHT: ++skb->box_j; done = 1;break;
}
}
}
// compare old box position with latest man position (before reverting last move),
// which is the position of the moved box before the last push which gets reverted.
if ((skb->box_i != skb->pi) || (skb->box_j != skb->pj)) {
--skb->n_boxchange;
}
break;
}

skb->pi-=di;
skb->pj-=dj;


return 1;
}

Expand All @@ -1195,6 +1232,7 @@ int sokoban_move(SOKOBAN *skb, char direction)
//g_print("invoked!");

if(skb->level[(skb->pi+di)*skb->w+skb->pj+dj]=='-'){
// move
skb->level[(skb->pi+di)*skb->w+skb->pj+dj]='@';
skb->level[(skb->pi)*skb->w+skb->pj]='-';
skb->pi+=di;
Expand All @@ -1211,6 +1249,7 @@ int sokoban_move(SOKOBAN *skb, char direction)
return 1;
}
else if(skb->level[(skb->pi+di)*skb->w+skb->pj+dj]=='$' && skb->level[(skb->pi+2*di)*skb->w+skb->pj+2*dj]=='-'){
// push
skb->level[(skb->pi+2*di)*skb->w+skb->pj+2*dj]='$';
skb->level[(skb->pi+di)*skb->w+skb->pj+dj]='@';
skb->level[(skb->pi)*skb->w+skb->pj]='-';
Expand All @@ -1223,7 +1262,12 @@ int sokoban_move(SOKOBAN *skb, char direction)
skb->solution[skb->solution_tail]=toupper(direction);
skb->solution_tail++;
skb->solution_head=skb->solution_tail;
skb->n_push++;
++skb->n_push;
if ((skb->box_i != skb->pi) || (skb->box_j != skb->pj)) {
++skb->n_boxchange;
}
skb->box_i = skb->pi+di;
skb->box_j = skb->pj+dj;
return 1;
}

Expand All @@ -1243,15 +1287,17 @@ SOKOBAN *sokoban_new_from_built_in()
skb->level=malloc(15*9);
skb->target=malloc(15*9);
memset(skb->target, ' ', sizeof(char)*15*9);
memcpy(skb->level,"###############\
memcpy(skb->level,"\
###############\
##----##------#\
##$$.-##-$***-#\
#-$.-*-##$.---#\
#--*..-*--..*-#\
#--*$.-#-$$$.-#\
##$.$*-##-.**-#\
##-@#--##--#--#\
###############", 15*9);
###############\
", 15*9);

skb->level_len=15*9;

Expand Down Expand Up @@ -1280,6 +1326,9 @@ SOKOBAN *sokoban_new_from_built_in()
skb->bi=0; skb->bj=0;

skb->n_push=0;
skb->n_boxchange=0;
skb->box_i=-1;
skb->box_j=-1;
skb->mode=SKB_UNSOLVE;

skb->key =sokoban_find_zobrist_key(skb, zob3k, 3000);
Expand Down Expand Up @@ -1464,9 +1513,9 @@ void sokoban_show_status(SOKOBAN *skb, GtkWidget *widget)


if(skb->mode==SKB_UNSOLVE)
buff = g_strdup_printf ("Moves: %d/%d Pushes: %d", skb->solution_tail,skb->solution_head,skb->n_push);
buff = g_strdup_printf ("Moves: %d/%d Pushes: %d Box changes: %d", skb->solution_tail,skb->solution_head,skb->n_push,skb->n_boxchange);
else
buff = g_strdup_printf ("Moves: %d/%d Pushes: %d (Solved)", skb->solution_tail,skb->solution_head,skb->n_push);
buff = g_strdup_printf ("Moves: %d/%d Pushes: %d Box changes: %d (Solved)", skb->solution_tail,skb->solution_head,skb->n_push,skb->n_boxchange);
gtk_statusbar_push (GTK_STATUSBAR (widget), context_id, buff);

g_free (buff);
Expand Down Expand Up @@ -1523,6 +1572,9 @@ SOKOBAN *sokoban_new()
skb->w=0; skb->h=0;

skb->n_push=0;
skb->n_boxchange=0;
skb->box_i=-1;
skb->box_j=-1;
skb->mode=SKB_UNSOLVE;
skb->bi=0; skb->bj=0;
skb->wall_click=0;
Expand Down
26 changes: 15 additions & 11 deletions sokoban.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,35 @@ enum { STATUS_NONLEVEL, STATUS_COMMENT, STATUS_TOP_BOUNDARY, STATUS_INLEVEL,

typedef struct
{
char *level;
char *target;
char *level; /* stores the level compoments @ - $ (man, empty square, box) */
char *target; /* stores the level component . (target square) */
char *hint;
int level_len;
int w;
int h;
int w; /* width of the level [squares] */
int h; /* height of the level [squares] */


int pi; /*row index of the man */
int pj;
int pi; /* row index of the pusher */
int pj; /* column index of the pusher */

int bi; /*row index for selected box*/
int bj;
int bi; /* row index for selected box */
int bj; /* column index for selected box */

char *solution;
int box_i; /* row index of last touched box */
int box_j; /* column index of last touched box */

char *solution; /* move sequence as a string of [urdlURDL] */
int solution_len;
int solution_head;
int solution_tail; // this is also the number of moves

int n_push; // number of pushes
int n_boxchange; // number of box changes

int mode; //solved? unsolve?
int wall_click;
unsigned long long key;
unsigned long long key2;
unsigned long long key; /* Zobrist key over the positions of the boxes. Pusher position, targets, walls and the general layout are ignored. */
unsigned long long key2; /* Zobrist key over the positiions of the targets. Pusher position, boxes, walls and the general layout are ignored. */

}SOKOBAN;

Expand Down

0 comments on commit 9a4eeb4

Please sign in to comment.