Index: apps/plugins/sokoban.c
===================================================================
RCS file: /cvsroot/rockbox/apps/plugins/sokoban.c,v
retrieving revision 1.24
diff -u -r1.24 sokoban.c
--- apps/plugins/sokoban.c	9 May 2006 05:36:46 -0000	1.24
+++ apps/plugins/sokoban.c	13 May 2006 18:40:52 -0000
@@ -540,12 +540,124 @@
     update_screen();
 }
 
-static bool sokoban_loop(void)
+/* This function handles the buttons for movement.
+ * It returns true iff move was successful.
+ */
+static bool move_player(int button)
 {
+    short r = current_info.player.row;
+    short c = current_info.player.col;
+    short r_delta = 0;
+    short c_delta = 0;
     char new_spot;
+    bool moved = false;
+
+    /* r_delta and c_delta encode the relative position change
+     * of row and column for the given direction
+     */
+    switch(button)
+    {
+        case BUTTON_LEFT:
+            r_delta = 0;
+            c_delta = -1;
+            break;
+        case BUTTON_RIGHT:
+            r_delta = 0;
+            c_delta = 1;
+            break;
+        case SOKOBAN_UP:
+            r_delta = -1;
+            c_delta = 0;
+            break;
+        case SOKOBAN_DOWN:
+            r_delta = 1;
+            c_delta = 0;
+            break;
+        default:
+            /* Oops! shouldn't have called the function in this state */
+            break;
+    }
+
+    /* consider the position the player is moving to */
+    switch(current_info.board[r+r_delta][c+c_delta])
+    {
+        case ' ': /* if it is a blank spot */
+        case '.': /* if it is a home spot */
+            new_spot = current_info.board[r+r_delta][c+c_delta];
+            current_info.board[r+r_delta][c+c_delta] = '@';
+            current_info.board[r][c] = current_info.player.spot;
+            current_info.player.spot = new_spot;
+            moved = true;
+            break;
+
+        case '$': /* if it is a box */
+            switch(current_info.board[r+(2*r_delta)][c+(2*c_delta)])
+            {
+                case ' ': /* going from blank to blank */
+                    current_info.board[r+(2*r_delta)][c+(2*c_delta)] = current_info.board[r+r_delta][c+c_delta];
+                    current_info.board[r+r_delta][c+c_delta] = current_info.board[r][c];
+                    current_info.board[r][c] = current_info.player.spot;
+                    current_info.player.spot = ' ';
+                    moved = true;
+                    break;
+
+                case '.': /* going from a blank to home */
+                    current_info.board[r+(2*r_delta)][c+(2*c_delta)] = '%';
+                    current_info.board[r+r_delta][c+c_delta] = current_info.board[r][c];
+                    current_info.board[r][c] = current_info.player.spot;
+                    current_info.player.spot = ' ';
+                    current_info.level.boxes_to_go--;
+                    moved = true;
+                    break;
+
+                default:
+                    break;
+            }
+            break;
+
+        case '%': /* if it is a box on a home spot */
+            switch(current_info.board[r+(2*r_delta)][c+(2*c_delta)]) {
+                case ' ': /* we are going from a home to a blank */
+                    current_info.board[r+(2*r_delta)][c+(2*c_delta)] = '$';
+                    current_info.board[r+r_delta][c+c_delta] = current_info.board[r][c];
+                    current_info.board[r][c] = current_info.player.spot;
+                    current_info.player.spot = '.';
+                    current_info.level.boxes_to_go++;
+                    moved = true;
+                    break;
+
+                case '.': /* if we are going from a home to home */
+                    current_info.board[r+(2*r_delta)][c+(2*c_delta)] = '%';
+                    current_info.board[r+r_delta][c+c_delta] = current_info.board[r][c];
+                    current_info.board[r][c] = current_info.player.spot;
+                    current_info.player.spot = '.';
+                    moved = true;
+                    break;
+
+                default:
+                    break;
+            }
+            break;
+
+        default:
+            break;
+    }
+  
+    /* update players position */
+    if (moved)
+    {
+        current_info.player.row += r_delta;
+        current_info.player.col += c_delta;
+    }
+
+    return moved;
+}
+
+
+static bool sokoban_loop(void)
+{
     bool moved = true;
     int i = 0, button = 0, lastbutton = 0;
-    short r = 0, c = 0;
 
     current_info.level.level = 1;
 
@@ -555,9 +667,6 @@
     while (1) {
         moved = true;
 
-        r = current_info.player.row;
-        c = current_info.player.col;
-
         button = rb->button_get(true);
 
         add_undo(button);
@@ -613,265 +722,10 @@
                 break;
 
             case BUTTON_LEFT:
-                switch(current_info.board[r][c-1])
-                {
-                    case ' ': /* if it is a blank spot */
-                    case '.': /* if it is a home spot */
-                        new_spot = current_info.board[r][c-1];
-                        current_info.board[r][c-1] = '@';
-                        current_info.board[r][c] = current_info.player.spot;
-                        current_info.player.spot = new_spot;
-                        break;
-
-                    case '$':
-                        switch(current_info.board[r][c-2])
-                        {
-                            case ' ': /* going from blank to blank */
-                                current_info.board[r][c-2] = current_info.board[r][c-1];
-                                current_info.board[r][c-1] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = ' ';
-                                break;
-
-                            case '.': /* going from a blank to home */
-                                current_info.board[r][c-2] = '%';
-                                current_info.board[r][c-1] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = ' ';
-                                current_info.level.boxes_to_go--;
-                                break;
-
-                            default:
-                                moved = false;
-                                break;
-                        }
-                        break;
-
-                    case '%':
-                        switch(current_info.board[r][c-2]) {
-                            case ' ': /* we are going from a home to a blank */
-                                current_info.board[r][c-2] = '$';
-                                current_info.board[r][c-1] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = '.';
-                                current_info.level.boxes_to_go++;
-                                break;
-
-                            case '.': /* if we are going from a home to home */
-                                current_info.board[r][c-2] = '%';
-                                current_info.board[r][c-1] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = '.';
-                                break;
-
-                            default:
-                                moved = false;
-                                break;
-                        }
-                        break;
-
-                    default:
-                        moved = false;
-                        break;
-                }
-
-                if (moved)
-                    current_info.player.col--;
-                break;
-
-            case BUTTON_RIGHT: /* if it is a blank spot */
-                switch(current_info.board[r][c+1]) {
-                    case ' ':
-                    case '.': /* if it is a home spot */
-                        new_spot = current_info.board[r][c+1];
-                        current_info.board[r][c+1] = '@';
-                        current_info.board[r][c] = current_info.player.spot;
-                        current_info.player.spot = new_spot;
-                        break;
-
-                    case '$':
-                        switch(current_info.board[r][c+2]) {
-                            case ' ': /* going from blank to blank */
-                                current_info.board[r][c+2] = current_info.board[r][c+1];
-                                current_info.board[r][c+1] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = ' ';
-                                break;
-
-                            case '.': /* going from a blank to home */
-                                current_info.board[r][c+2] = '%';
-                                current_info.board[r][c+1] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = ' ';
-                                current_info.level.boxes_to_go--;
-                                break;
-
-                            default:
-                                moved = false;
-                                break;
-                        }
-                        break;
-
-                    case '%':
-                        switch(current_info.board[r][c+2]) {
-                            case ' ': /* going from a home to a blank */
-                                current_info.board[r][c+2] = '$';
-                                current_info.board[r][c+1] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = '.';
-                                current_info.level.boxes_to_go++;
-                                break;
-
-                            case '.':
-                                current_info.board[r][c+2] = '%';
-                                current_info.board[r][c+1] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = '.';
-                                break;
-
-                            default:
-                                moved = false;
-                                break;
-                        }
-                        break;
-
-                    default:
-                        moved = false;
-                        break;
-                }
-
-                if (moved)
-                    current_info.player.col++;
-                break;
-
+            case BUTTON_RIGHT:
             case SOKOBAN_UP:
-                switch(current_info.board[r-1][c]) {
-                    case ' ': /* if it is a blank spot */
-                    case '.': /* if it is a home spot */
-                        new_spot = current_info.board[r-1][c];
-                        current_info.board[r-1][c] = '@';
-                        current_info.board[r][c] = current_info.player.spot;
-                        current_info.player.spot = new_spot;
-                        break;
-
-                    case '$':
-                        switch(current_info.board[r-2][c]) {
-                            case ' ': /* going from blank to blank */
-                                current_info.board[r-2][c] = current_info.board[r-1][c];
-                                current_info.board[r-1][c] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = ' ';
-                                break;
-
-                            case '.': /* going from a blank to home */
-                                current_info.board[r-2][c] = '%';
-                                current_info.board[r-1][c] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = ' ';
-                                current_info.level.boxes_to_go--;
-                                break;
-
-                            default:
-                                moved = false;
-                                break;
-                        }
-                        break;
-
-                    case '%':
-                        switch(current_info.board[r-2][c]) {
-                            case ' ': /* we are going from a home to a blank */
-                                current_info.board[r-2][c] = '$';
-                                current_info.board[r-1][c] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = '.';
-                                current_info.level.boxes_to_go++;
-                                break;
-
-                            case '.': /* if we are going from a home to home */
-                                current_info.board[r-2][c] = '%';
-                                current_info.board[r-1][c] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = '.';
-                                break;
-
-                            default:
-                                moved = false;
-                                break;
-                        }
-                        break;
-
-                    default:
-                        moved = false;
-                        break;
-                }
-
-                if (moved)
-                    current_info.player.row--;
-                break;
-
             case SOKOBAN_DOWN:
-                switch(current_info.board[r+1][c]) {
-                    case ' ': /* if it is a blank spot */
-                    case '.': /* if it is a home spot */
-                        new_spot = current_info.board[r+1][c];
-                        current_info.board[r+1][c] = '@';
-                        current_info.board[r][c] = current_info.player.spot;
-                        current_info.player.spot = new_spot;
-                        break;
-
-                    case '$':
-                        switch(current_info.board[r+2][c]) {
-                            case ' ': /* going from blank to blank */
-                                current_info.board[r+2][c] = current_info.board[r+1][c];
-                                current_info.board[r+1][c] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = ' ';
-                                break;
-
-                            case '.': /* going from a blank to home */
-                                current_info.board[r+2][c] = '%';
-                                current_info.board[r+1][c] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = ' ';
-                                current_info.level.boxes_to_go--;
-                                break;
-
-                            default:
-                                moved = false;
-                                break;
-                        }
-                        break;
-
-                    case '%':
-                        switch(current_info.board[r+2][c]) {
-                            case ' ': /* going from a home to a blank */
-                                current_info.board[r+2][c] = '$';
-                                current_info.board[r+1][c] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = '.';
-                                current_info.level.boxes_to_go++;
-                                break;
-
-                            case '.': /* going from a home to home */
-                                current_info.board[r+2][c] = '%';
-                                current_info.board[r+1][c] = current_info.board[r][c];
-                                current_info.board[r][c] = current_info.player.spot;
-                                current_info.player.spot = '.';
-                                break;
-
-                            default:
-                                moved = false;
-                                break;
-                        }
-                        break;
-
-                    default:
-                        moved = false;
-                        break;
-                }
-
-                if (moved)
-                    current_info.player.row++;
+                moved = move_player(button);
                 break;
 
             default:
