add element's move feature
authorLaurent Mazet <mazet@softndesign.org>
Tue, 17 Dec 2024 22:56:00 +0000 (23:56 +0100)
committerLaurent Mazet <mazet@softndesign.org>
Tue, 17 Dec 2024 22:56:00 +0000 (23:56 +0100)
function.c
function.h
sokoban.c

index 446e0c1ac8c4bdceb6605d2dc3969e7973838a03..f628035d1705978830f7315ef4dabd2045483ebc 100644 (file)
@@ -7,6 +7,11 @@
 
 #include "function.h"
 
+typedef struct {
+    int x;
+    int y;
+} point;
+
 int strmaxlen (char *str, char ch)
 {
     int len = 0;
@@ -216,4 +221,110 @@ char getvalue (board_t *board, int x, int y)
     return (x >= 0) && (x < board->width) && (y >= 0) && (y < board->height) ? *getcell (board, x, y) : 0;
 }
 
+int _moveelements (board_t *board, point *pt, int dir)
+{
+    /* define direction */
+    point _move = {0, 0};
+    point *move = &_move;
+    switch (dir) {
+    case 0:
+        move->y--;
+        break;
+    case 1:
+        move->x++;
+        break;
+    case 2:
+        move->y++;
+        break;
+    case 3:
+        move->x--;
+        break;
+    }
+
+    /* check 2 next positions in line */
+    int rc = 1;
+    char next = getvalue (board, pt->x + move->x, pt->y + move->y);
+    char next2 = getvalue (board, pt->x + 2 * move->x, pt->y + 2 * move->y);
+    switch (next) {
+    case '$':
+    case '*':
+        switch (next2) {
+        case ' ':
+            *getcell (board, pt->x + 2 * move->x, pt->y + 2 * move->y) = '$';
+            break;
+        case '.':
+            *getcell (board, pt->x + 2 * move->x, pt->y + 2 * move->y) = '*';
+            break;
+        default:
+            rc = 0;
+        }
+    }
+
+    /* push box */
+    if (rc == 1) {
+        switch (next) {
+        case '$':
+            *getcell (board, pt->x + move->x, pt->y + move->y) = ' ';
+            break;
+        case '*':
+            *getcell (board, pt->x + move->x, pt->y + move->y) = '.';
+            break;
+        }
+    }
+
+    /* move sokoban */
+    switch (next) {
+    case ' ':
+        *getcell (board, pt->x + move->x, pt->y + move->y) = '@';
+        rc = 1;
+        break;
+    case '.':
+        *getcell (board, pt->x + move->x, pt->y + move->y) = '+';
+        rc = 1;
+        break;
+    default:
+        rc = 0;
+    }
+
+    /* clean old sokoban position */
+    if (rc == 1) {
+        char sokoban = getvalue (board, pt->x, pt->y);
+        switch (sokoban) {
+        case '@':
+            *getcell (board, pt->x, pt->y) = ' ';
+            break;
+        case '+':
+            *getcell (board, pt->x, pt->y) = '.';
+            break;
+        }
+    }
+
+    return rc;
+}
+
+void _findsokoban (board_t *board, point *pt)
+{
+    int x, y;
+    for (x = 0; x < board->width; x++) {
+        for (y = 0; y < board->height; y++) {
+            switch (getvalue (board, x, y)) {
+            case '@':
+            case '+':
+                pt->x = x;
+                pt->y = y;
+                break;
+            }
+        }
+    }
+}
+
+void movesokoban (board_t *board, int dir)
+{
+    point sokoban = {-1, -1};
+    _findsokoban (board, &sokoban);
+    if (sokoban.x != -1) {
+        _moveelements (board, &sokoban, dir);
+    }
+}
+
 /* vim: set ts=4 sw=4 et: */
index 34f87600ae61c95dce1a67694f71de32e5d63615..f0fa0ef3d87dca545c8961bf1c9ea46e2bdadf7d 100644 (file)
@@ -37,6 +37,8 @@ char *getcell (board_t *board, int x, int y);
 
 char getvalue (board_t *board, int x, int y);
 
+void movesokoban (board_t *board, int dir);
+
 #endif /* __FUNCTION_H__ */
 
 /* vim: set ts=4 sw=4 et: */
index 49557f16d121948218866754e73716cfeccf9a3f..eeb17f4f12ff51bff91659564b26e969b90f8daa 100644 (file)
--- a/sokoban.c
+++ b/sokoban.c
@@ -134,7 +134,7 @@ int main (int argc, char *argv[])
         }
     }
     if (board == NULL) {
-        VERBOSE (ERROR, fprintf (stderr, "no board defined"));
+        VERBOSE (ERROR, fprintf (stderr, "no board defined\n"));
         return 1;
     }
     setscale (board, scale);
@@ -170,9 +170,14 @@ int main (int argc, char *argv[])
     /* event loop */
     int mode = 0;
     int stop = 0;
+    int dir = -1;
     while (!stop) {
         char *ptr = NULL;
 
+        if (dir >= 0) {
+            movesokoban (board, dir);
+            dir = -1;
+        }
         boardwindow (board);
 
         int ch = getch ();
@@ -187,15 +192,19 @@ int main (int argc, char *argv[])
             break;
         case KEY_UP:
         case 'i':
+            dir = 0;
             break;
         case KEY_LEFT:
         case 'j':
+            dir = 3;
             break;
         case KEY_DOWN:
         case 'k':
+            dir = 2;
             break;
         case KEY_RIGHT:
         case 'l':
+            dir = 1;
             break;
         case KEY_ESC:
         case 'q':