         break;
 
         case LEFT:
-            // TODO
-        break;
-    }
-
-    // Update display
-    renderBoard();
-}
-
-void endGame() {
+            for (int i = 0; i < 4; i++) {
+                for (int j = 0; j < 4; j++) {
+                    if (j == 0) {
+                        continue;
+                    }
+
+                    movedAnythingYet = attemptTileMove(i, j, i, j - 1) || movedAnythingYet;
+                }
+            }
+        break;
+    }
+
+    // If no tiles moved, this was an invalid move
+    if (!movedAnythingYet) {
+        return false;
+    }
+
+    // Otherwise, it was valid, so add a new tile
+    // TODO
+
+    return true;
+}
+
+/* Checks whether the game is still winnable. Calls lostGame() if not. */
+void checkLost() {
+    for (int i = 0; i < 4; i++) {
+        if (attemptMove(i)) {
+            return;
+        }
+    }
+
+    // Whoops, we lost the game
+    lostGame();
+}
+
+void lostGame() {
     // Update game state
     gameInProgress = false;
+
+    // TODO ~ Do something to show they lost (womp womp)
+}
+
+void wonGame() {
+    // Update game state
+    gameInProgress = false;
+
+    // TODO ~ Do something to show they won (woohooo!)
 }
 
 /****************************************

        return;
    }

    int upVal = digitalRead(UP_PIN);
    int rightVal = digitalRead(RIGHT_PIN);
    int downVal = digitalRead(DOWN_PIN);

    }

    // Update game state
    gameInProgress = true;

    // Update display
    renderBoard();
