/*

심심하기도 하고 이거 하다가 막히는 사람이 있길래 참고하라고 만들어봤음.
대충 만들어서 코드도 좀 더럽고, 버그가 있을 수 있음.
전역변수, 맵 사이즈, 지도 값등을 숫자로 직접 쓴건 간단하게 하려고 그런거고 그건 안쓰는게 좋음
여긴 게임 구현만 해놨고, 조작하는건 없음.
사용법은 ./sokoban [레벨] [명령] 이고 명령은 rlud 에서 골라서 쓰면 됨(right, left, up, down)
예: ./sokoban 1 rulurrrrllldddldrrrdruu

*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>



// 0 빈 공간
// 1 벽
// 2 별
// 3 플레이어
// 4 상자
// 5 별+상자
// 6 플레이어+상자

static const int stages[][8][8] =
        {
                {
                        {1,1,1,1,1,1,1,1},
                        {1,0,0,0,0,0,0,1},
                        {1,0,2,0,1,1,1,1},
                        {1,3,0,0,1,4,1,1},
                        {1,0,0,0,1,0,1,1},
                        {1,0,0,0,0,0,1,1},
                        {1,0,0,0,0,0,1,1},
                        {1,1,1,1,1,1,1,1}
                },
                {
                        {1,1,1,1,1,1,1,1},
                        {1,0,0,0,0,0,4,1},
                        {1,0,2,0,1,1,1,1},
                        {1,3,0,0,1,4,1,1},
                        {1,0,0,0,1,0,1,1},
                        {1,0,2,0,0,0,1,1},
                        {1,0,0,0,0,0,1,1},
                        {1,1,1,1,1,1,1,1}
                },
        };

static int current_stage, x, y;
static int stage[8][8];

int set_stage(int level)
{
        current_stage = level;
        memcpy(stage, &stages[level], sizeof(stage));
        
        for(y = 0; y < 8; y++)
        {
                for(x = 0; x < 8; x++)
                {
                        if(stage[y][x] == 3)
                        {
                                return 0;
                        }
                }
        }
        
        return -1;
}

int print_stage(void)
{
        int i, j;
        
        //for(i = 0; i < 24; i++)
                //putchar(\'\\n\');
        
        for(i = 0; i < 8; i++)
        {
                for(j = 0; j < 8; j++)
                {
                        switch(stage[i][j])
                        {
                                case 0: putchar(\' \'); break;
                                case 1: putchar(\'#\'); break;
                                case 2: putchar(\'*\'); break;
                                case 3: putchar(\'$\'); break;
                                case 4: putchar(\'=\'); break;
                                case 5: putchar(\'+\'); break;
                                case 6: putchar(\'?\'); break;
                        }
                }
                putchar(10);
        }
        
        return 0;
}

int check_stage(void)
{
        int i, j;
        
        for(i = 0; i < 8; i++)
        {
                for(j = 0; j < 8; j++)
                {
                        if(stage[i][j] == 2)
                        {
                                return 0;
                        }
                }
        }
        
        return 1;
}

int movep(int dx, int dy)
{
        int *p;
        int d;
        int *crnt, *next, *next2;
        int wplayer;

        crnt = &stage[y][x]; // 현재 위치
        wplayer = *crnt == 6?4:0; // 현재 상태가 플레이어+상자일 경우 플레이어 이동 후 채울 값
        if(dx)
        {
                p = &x; // x값을 변경
                d = dx;
                next = &stage[y][x+dx]; // 플레이어가 이동할 예정인 자리의 값
                next2 = &stage[y][x+dx+dx]; // 플레이어가 이동할 예정인 자리 다음 값 - 별을 움직일때 필요
        }
        else
        {
                p = &y;
                d = dy;
                next = &stage[y+dy][x];
                next2 = &stage[y+dy+dy][x];
        }
        
        if((d<0)?(*p > 0):(*p < 7)) // 경계 확인
        {
                switch(*next)
                {
                case 0: *p += d; *next = 3; *crnt = wplayer; break;
                case 1: break;
                case 2:
                        if((d<0)?(*p > 1):(*p < 6)) // 경계 확인
                        {
                                switch(*next2)
                                {
                                case 0: *p += d; *crnt = wplayer; *next = 3; *next2 = 2;
                                case 1: case 2: case 3: case 5: case 6: break; // 움직이지 않음
                                case 4: *p += d; *crnt = wplayer; *next = 3; *next2 = 5;
                                }
                        }
                        break;
                case 4: *p += d; *crnt = wplayer; *next = 6; break;
                case 5:
                        if((d<0)?(*p > 1):(*p < 6))
                        {
                                switch(*next2)
                                {
                                case 0: *p += d; *crnt = wplayer; *next = 6; *next2 = 2;
                                case 1: case 2: case 3: case 5: case 6: break;
                                case 4: *p += d; *crnt = wplayer; *next = 6; *next2 = 5;
                                }
                        }
                        break;
                }
        }
        
        return 0;
}

int move(char *dir)
{
        while(*dir)
        {
                switch(*dir)
                {
                case \'l\':
                        movep(-1, 0);
                        break;
                case \'r\':
                        movep(1, 0);
                        break;
                case \'u\':
                        movep(0, -1);
                        break;
                case \'d\':
                        movep(0, 1);
                        break;
                }
                dir++;
        }
        
        return 0;
}

int main(int argc, char **argv)
{
        (void)argc;
        
        set_stage(argv[1]?atoi(argv[1]):0);
        move(argv[2]?argv[2]:\"\");
        print_stage();
        if(check_stage())
        {
                printf(\"Completed\\n\");
        }
        
        return EXIT_SUCCESS;
}