Advertisement
Guest User

sokoban.c

a guest
May 22nd, 2019
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.27 KB | None | 0 0
  1.  
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4.  
  5. #define EMPTY   0x00
  6. #define PLAYER  0x01
  7. #define BOX     0x02
  8. #define TARGET  0x04
  9. #define OUTSIDE 0xf0
  10.  
  11. #define MATCH(x, bits) ((x & bits) == bits)
  12. #define AVAILABLE(x) (!MATCH(x, OUTSIDE) && !MATCH(x, BOX))
  13.  
  14. #define MAX_WIDTH  10
  15. #define MAX_HEIGTH 10
  16.  
  17. int WIDTH, HEIGTH;
  18.  
  19. #define POS(x, y) (y * MAX_WIDTH + x)
  20. #define X(pos)    (pos % MAX_WIDTH + 1)
  21. #define Y(pos)    (pos / MAX_WIDTH + 1)
  22. #define END 987654321
  23.  
  24. int posx, posy;
  25. int board[MAX_WIDTH + 4][MAX_HEIGTH + 4];
  26.  
  27. void reset_board(int *boxes, int *targets, int *blocks) {
  28.     int i, j, pos;
  29.     for(i = 0; i < MAX_WIDTH+4; i++) {
  30.         for(j = 0; j < MAX_HEIGTH+4; j++) {
  31.             board[i][j] = OUTSIDE;
  32.             if(2 <= i && i < WIDTH+2 && 2 <= j && j < HEIGTH+2) board[i][j] = EMPTY;
  33.         }
  34.     }
  35.     for(i = 0; boxes[i] != END; i++) { int pos = boxes[i]; board[X(pos)][Y(pos)] = BOX; }
  36.     for(i = 0; targets[i] != END; i++) { int pos = targets[i]; board[X(pos)][Y(pos)] |= TARGET; }
  37.     for(i = 0; blocks[i] != END; i++) { int pos = blocks[i]; board[X(pos)][Y(pos)] |= OUTSIDE; }
  38.  
  39.     for(i = 2; i < WIDTH+2; i++) for(j = 2; j < HEIGTH+2; j++) {
  40.         if(board[i][j] == EMPTY) { posx = i; posy = j; return; }
  41.     }
  42.  
  43.     for(i = 2; i < WIDTH+2; i++) for(j = 2; j < HEIGTH+2; j++) {
  44.         if(board[i][j] == TARGET) { posx = i; posy = j; return; }
  45.     }
  46.  
  47.     fprintf(stderr, "no empty spaces!\n");
  48.     exit(1);
  49. }
  50.  
  51. int win_yet() {
  52.     int i, j, tmp;
  53.     for(j = 2; j < HEIGTH+2; j++) {
  54.         for(i = 2; i < WIDTH+2; i++) {
  55.             tmp = board[i][j];
  56.             if(MATCH(tmp, TARGET) && !MATCH(tmp, BOX)) return 0;
  57.         }
  58.     }
  59.     return 1;
  60. }
  61.  
  62.  
  63. #define OUTPUT(ch, attr) do {                             \
  64.     if(attr != a) { printf("\x1b[%dm", attr); a = attr; } \
  65.     printf("%c", ch);                                     \
  66.     } while(0)
  67.  
  68. void draw_board() {
  69.     int i, j, x;
  70.     int a = 0, a_ = 0;
  71.  
  72.     OUTPUT('\r', 0); OUTPUT('\n', 0);
  73.  
  74.     for(j = 2; j < HEIGTH+2; j++) {
  75.         OUTPUT(' ', 0);
  76.         for(i = 2; i < WIDTH+2; i++) {
  77.             x = board[i][j];
  78.             if(i == posx && j == posy) OUTPUT('@', 36);
  79.             else if(MATCH(x,OUTSIDE))  OUTPUT('=', 36);
  80.             else if(MATCH(x, BOX))     OUTPUT('#', 33);
  81.             else if(MATCH(x, TARGET))  OUTPUT('$', 35);
  82.             else if(x == EMPTY)        OUTPUT('.', 0);
  83.             else OUTPUT('?', 41);
  84.         }
  85.         OUTPUT('\r', 0);
  86.         OUTPUT('\n', 0);
  87.     }
  88.     return;
  89. }
  90.  
  91. enum { North, South, East, West, Nowhere };
  92.  
  93. void step(int x, int y, int dir) {
  94.     int nx = x, ny = y;
  95.     int nnx = x, nny = y;
  96.     int t, s;
  97.  
  98.     if(dir == North) { ny--; nny -= 2; }
  99.     if(dir == South) { ny++; nny += 2; }
  100.     if(dir == East)  { nx++; nnx += 2; }
  101.     if(dir == West)  { nx--; nnx -= 2; }
  102.  
  103.     t = board[nx][ny];
  104.     s = board[nnx][nny];
  105.  
  106.     if(AVAILABLE(t)) { posx = nx; posy = ny; return; }
  107.  
  108.     if(MATCH(t, BOX) && AVAILABLE(s)) {
  109.         t ^= BOX; board[nx][ny]   = t;
  110.         s ^= BOX; board[nnx][nny] = s;
  111.         posx = nx; posy = ny; return;
  112.     }
  113.  
  114.     return;
  115. }
  116.  
  117.  
  118. int main() {
  119.     int boxes[]   = { POS(3, 2), POS(4, 2), POS(2, 3), POS(2, 4), END };
  120.     int targets[] = { POS(3, 3), POS(4, 3), POS(3, 4), POS(4, 4), END };
  121.     int blocks[] = { END };
  122.  
  123.     WIDTH  = 5;
  124.     HEIGTH = 5;
  125.     reset_board(boxes, targets, blocks);
  126.     draw_board();
  127.  
  128.     int c = getc(stdin);
  129.     while(c != EOF) {
  130.         int dir = Nowhere;
  131.         switch(c) {
  132.             //case '\n': draw_board(); break;
  133.  
  134.             case '!': printf("goodbye\r\n"); exit(0); break;
  135.  
  136.             case 'q': printf("starting over...\r\n");
  137.                       reset_board(boxes, targets, blocks);
  138.                       break;
  139.  
  140.             default: printf("direction? [n, s, e, w]\r\n"); break;
  141.  
  142.             case 'n': case 'A': dir = North; break;
  143.             case 's': case 'B': dir = South; break;
  144.             case 'e': case 'C': dir = East; break;
  145.             case 'w': case 'D': dir = West; break;
  146.         };
  147.  
  148.         step(posx, posy, dir);
  149.         if(win_yet()) {
  150.             draw_board();
  151.             printf("you win!\r\n");
  152.             exit(0);
  153.         }
  154.         draw_board();
  155.         c = getc(stdin);
  156.     }
  157.     return 0;
  158. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement