 const int minutesLen = maxRadius - 13;
 const int hoursLen = maxRadius - 22;
 void clockScene(bool changed) {
-		if (changed) {
-				TV.draw_circle(WIDTH / 2, HEIGHT / 2, maxRadius, 1, 0);
-
-				currentAngle = random(60) * angleDiff;
-				hourAngle = random(60) * angleDiff;
-				minuteAngle = random(60) * angleDiff;
-		}
-
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, currentAngle, secondsLen, 0);
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, minuteAngle, minutesLen, 0);
-
-		currentAngle -= angleDiff;
-		minuteAngle -= angleDiff / 60.0;
-		// Dont bother updating hours
-
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, currentAngle, secondsLen, 1);	
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, hourAngle, hoursLen, 1);
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, minuteAngle, minutesLen, 1);
-
-		checkSceneEnded(15);
+    if (changed) {
+        TV.draw_circle(WIDTH / 2, HEIGHT / 2, maxRadius, 1, 0);
+
+        currentAngle = random(60) * angleDiff;
+        hourAngle = random(60) * angleDiff;
+        minuteAngle = random(60) * angleDiff;
+    }
+
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, currentAngle, secondsLen, 0);
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, minuteAngle, minutesLen, 0);
+
+    currentAngle -= angleDiff;
+    minuteAngle -= angleDiff / 60.0;
+    // Dont bother updating hours
+
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, currentAngle, secondsLen, 1);  
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, hourAngle, hoursLen, 1);
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, minuteAngle, minutesLen, 1);
+
+    checkSceneEnded(15);
 }
 
 double chartRayLen = 0;
 void chartScene(bool changed) {
-		const int chartRadius = (HEIGHT / 2) - 6;
-		if (changed) {
-				chartRayLen = 0;
-				TV.draw_circle(WIDTH / 2, HEIGHT / 2, chartRadius, 1, 0);
-				TV.draw_circle(WIDTH / 2, HEIGHT / 2, chartRadius - 7, 1, 0);
-				TV.draw_circle(WIDTH / 2, HEIGHT / 2, 12, 1, 0);
-
-				for (int i = 0; i < 12; i++) {
-						drawLineAngle(WIDTH / 2, HEIGHT / 2, i * (360.0 / 12), chartRadius, 1);
-				}
-
-				TV.delay(2000);
-		}
-
-		int rays = random(2, 7);
-		double offset = random(180);
-		for (int i = 0; i < rays; i++) {
-				drawLineAngle(WIDTH / 2, HEIGHT / 2, (i * (360.0 / rays)) + offset, chartRayLen + (chartRadius / 2), 1);
-		}
-
-		TV.delay(50);
-		chartRayLen += 0.2;
-
-		checkSceneEnded(20);
+    const int chartRadius = (HEIGHT / 2) - 6;
+    if (changed) {
+        chartRayLen = 0;
+        TV.draw_circle(WIDTH / 2, HEIGHT / 2, chartRadius, 1, 0);
+        TV.draw_circle(WIDTH / 2, HEIGHT / 2, chartRadius - 7, 1, 0);
+        TV.draw_circle(WIDTH / 2, HEIGHT / 2, 12, 1, 0);
+
+        for (int i = 0; i < 12; i++) {
+            drawLineAngle(WIDTH / 2, HEIGHT / 2, i * (360.0 / 12), chartRadius, 1);
+        }
+
+        TV.delay(2000);
+    }
+
+    int rays = random(2, 7);
+    double offset = random(180);
+    for (int i = 0; i < rays; i++) {
+        drawLineAngle(WIDTH / 2, HEIGHT / 2, (i * (360.0 / rays)) + offset, chartRayLen + (chartRadius / 2), 1);
+    }
+
+    TV.delay(50);
+    chartRayLen += 0.2;
+
+    checkSceneEnded(20);
 }
 
 void loop() {
-		bool changed = false;
-		if (currentScene != lastScene) {
-				TV.clear_screen();
-				TV.set_cursor(0, 0);
-
-				digitalWrite(LED_PIN, HIGH);
-				TV.delay(100);
-				digitalWrite(LED_PIN, LOW);
-
-				startTime = TV.millis();
-				changed = true;
-		}
-
-		lastScene = currentScene;
-
-		switch (currentScene) {
-				case SYMBOL_TAURUS:
-						tauroSymbolScene();
-						break;
-				case SYMBOLS_FAST:
-						fastSymbolsScene();
-						break;
-				case PLANETS_SYMBOLS_FAST:
-						planetSymbolsFastScene();
-						break;
-				case WORDS_FAST:
-						fastWordsScene();
-						break;
-				case WORDS_FAST_INLINE:
-						wordsFastInlineScene();
-						break;
-				case STARS:
-						starsScene();
-						break;
-				case NOISE:
-						noiseScene();
-						break;
-				case SYMBOL_FADE:
-						symbolFadeScene(changed);
-						break;
-				case SYMBOL_CHECKERBOARD:
-						symbolCheckerboardScene(changed);
-						break;
-				case SYMBOL_GLITCH_SIZE:
-						symbolGlitchSizeScene();
-						break;
-				case CONSTELLATIONS:
-						constellationsScene();
-						break;
-				case COMMANDS:
-						commandsScene();
-						break;
-				case SYMBOL_GLITCH_LOAD:
-						symbolGlitchLoadScene(changed);
-						break;
-				case WORD_CURSOR:
-						wordCursorScene(changed);
-						break;
-				case WORMHOLE:
-						wormholeScene(changed);
-						break;
-				case SYMBOLS_SNAKE:
-						symbolsSnakeScene(changed);
-						break;
-				case SCROLL_STARS:
-						scrollStarsScene(changed);
-						break;
-				case EYES:
-						eyesScene(changed);
-						break;
-				case CHANNEL:
-						channelScene(changed);
-						break;
-				case VHS:
-						vhsScene(changed);
-						break;
-				case SYMBOL_SHIFT:
-						symbolShiftScene(changed);
-						break;
-				case BLINDS:
-						blindsScene(changed);
-						break;
-				case FADE_IN:
-						fadeInScene(changed);
-						break;
-				// case WHITE_BEAR:
-				// 		whiteBearScene(changed);
-				// 		break;
-				case PARTY_WORDS:
-						partyWordsScene();
-						break;
-				case FILL_LINES:
-						fillLinesScene(changed);
-						break;
-				case CIRCLES:
-						circlesScene(changed);
-						break;
-				case L_SYSTEM:
-						lSystemScene();
-						break;
-				case CLOCK:
-						clockScene(changed);
-						break;
-				case CHART:
-						chartScene(changed);
-						break;
-        		case HEX_SCENE:
-            			hexScene(changed);
-            			break;
-				case PYRAMID:
-						pyramidScene(changed);
-						break;
-				default:
-						TV.print("Invalid scene. ");
-						TV.delay(1000);
-						break;
-		}
-}
+    bool changed = false;
+    if (currentScene != lastScene) {
+        TV.clear_screen();
+        TV.set_cursor(0, 0);
+
+        digitalWrite(LED_PIN, HIGH);
+        TV.delay(100);
+        digitalWrite(LED_PIN, LOW);
+
+        startTime = TV.millis();
+        changed = true;
+    }
+
+    lastScene = currentScene;
+
+    switch (currentScene) {
+        case SYMBOL_TAURUS:
+            tauroSymbolScene();
+            break;
+        case SYMBOLS_FAST:
+            fastSymbolsScene();
+            break;
+        case PLANETS_SYMBOLS_FAST:
+            planetSymbolsFastScene();
+            break;
+        case WORDS_FAST:
+            fastWordsScene();
+            break;
+        case WORDS_FAST_INLINE:
+            wordsFastInlineScene();
+            break;
+        case STARS:
+            starsScene();
+            break;
+        case NOISE:
+            noiseScene();
+            break;
+        case SYMBOL_FADE:
+            symbolFadeScene(changed);
+            break;
+        case SYMBOL_CHECKERBOARD:
+            symbolCheckerboardScene(changed);
+            break;
+        case SYMBOL_GLITCH_SIZE:
+            symbolGlitchSizeScene();
+            break;
+        case CONSTELLATIONS:
+            constellationsScene();
+            break;
+        case COMMANDS:
+            commandsScene();
+            break;
+        case SYMBOL_GLITCH_LOAD:
+            symbolGlitchLoadScene(changed);
+            break;
+        case WORD_CURSOR:
+            wordCursorScene(changed);
+            break;
+        case WORMHOLE:
+            wormholeScene(changed);
+            break;
+        case SYMBOLS_SNAKE:
+            symbolsSnakeScene(changed);
+            break;
+        case SCROLL_STARS:
+            scrollStarsScene(changed);
+            break;
+        case EYES:
+            eyesScene(changed);
+            break;
+        case CHANNEL:
+            channelScene(changed);
+            break;
+        case VHS:
+            vhsScene(changed);
+            break;
+        case SYMBOL_SHIFT:
+            symbolShiftScene(changed);
+            break;
+        case BLINDS:
+            blindsScene(changed);
+            break;
+        case FADE_IN:
+            fadeInScene(changed);
+            break;
+        case PARTY_WORDS:
+            partyWordsScene();
+            break;
+        case FILL_LINES:
+            fillLinesScene(changed);
+            break;
+        case CIRCLES:
+            circlesScene(changed);
+            break;
+        case L_SYSTEM:
+            lSystemScene();
+            break;
+        case CLOCK:
+            clockScene(changed);
+            break;
+        case CHART:
+            chartScene(changed);
+            break;
+        case HEX_SCENE:
+            hexScene(changed);
+            break;
+        case PYRAMID:
+            pyramidScene(changed);
+            break;
+        default:
+            TV.print("Invalid scene. ");
+            blinkForever();
+            break;
+    }
+}

int stepIdx = 0;
unsigned char *shiftSymbol = NULL;
void symbolShiftScene(bool changed) {
		if (changed) {
				rewinding = false;
				stepIdx = 0;

				shiftSymbol = getRandomSymbol();

				TV.bitmap(BMP_X, BMP_Y, shiftSymbol);
				TV.delay(1000);
		}

		int direction, step, col, row, orientation;

		if (!rewinding) {
				direction = random(2);
				step = random(1, 6);
				col = random(WIDTH);
				row = random(HEIGHT);
				orientation = random(2);

				steps[stepIdx][0] = orientation;
				steps[stepIdx][1] = direction;
				steps[stepIdx][2] = (orientation == 0) ? col : row;
				steps[stepIdx][3] = step;

				stepIdx++;
				if (stepIdx == STEP_COUNT) {
						rewinding = true;
				}
		} else if (stepIdx >= 0) {
				orientation = steps[stepIdx][0];
				direction = (steps[stepIdx][1] == 0) ? 1 : 0;
				col = row = steps[stepIdx][2];
				step = steps[stepIdx][3];			

				stepIdx--;
		} else {
				TV.bitmap(BMP_X, BMP_Y, shiftSymbol);
				rewinding = false;
				stepIdx = 0;
				TV.delay(200);
		}

		shiftLine(orientation, direction, (orientation == 0) ? col : row, step);

		if (checkSceneEnded(30)) {
				TV.delay(1500);
		}
}


void blindsScene(bool changed) {
		if (changed) {
				TV.bitmap(BMP_X, BMP_Y, getRandomSymbol());
				screenToBackBuffer();
				TV.clear_screen();
		}

		for (int i = 0; i < HEIGHT; i++) {
				for (int j = 0; j < WIDTH / 8; j++) {
						backBuffer[i][j] += 1;
				}
		}

		backBufferToScreen();

		checkSceneEnded(20);
}

void fadeInScene(bool changed) {
		if (changed) {
				TV.bitmap(BMP_X, BMP_Y, getRandomSymbol());
				screenToBackBuffer();
				TV.clear_screen();
		}

		int x = random(WIDTH);
		int y = random(HEIGHT);

		if (backBufferGet(x, y)) {
				TV.set_pixel(x, y, 1);
		}

		if (checkSceneEnded(20)) {
				TV.delay(1000);
		}
}

void whiteBearScene(bool changed) {
		if (changed) {
				TV.bitmap(BMP_X, BMP_Y, white_bear);
				TV.delay(3000);
				return;
		}

		TV.bitmap(BMP_X, BMP_Y, white_bear, 0, IMG_SIZE - random(1, 10), IMG_SIZE - random(1, 10));
		TV.delay(random(50, 200));
		
		TV.clear_screen();
		TV.bitmap(BMP_X, BMP_Y, white_bear);
		TV.delay(1000);

		checkSceneEnded(15);		
}

int partyIdx = 0;
void partyWordsScene() {
		TV.clear_screen();
		TV.set_cursor(0, (HEIGHT / 2) - (FONT_H / 2));
		TV.print(event_words[partyIdx % EVENT_WORDS_COUNT]);
		TV.delay(140);

		partyIdx++;

		if (checkSceneEnded(10)) {
				TV.set_cursor(0, (HEIGHT / 2) - (FONT_H / 2));
				TV.print("ORGULLO TAURINO II.");
				TV.delay(3000);					
		}
}

int fillLinesDirection = 0;
void fillLinesScene(bool changed) {
		if (changed) {
				TV.bitmap(BMP_X, BMP_Y, getRandomSymbol());
				screenToBackBuffer();
				TV.clear_screen();
				fillLinesDirection = random(4);		
		}

		int x = random(WIDTH);
		int y = random(HEIGHT);

		while (!backBufferGet(x, y)) {
				TV.set_pixel(x, y, 1);

				switch (fillLinesDirection) {
						case UP:
								y--;
								break;
						case DOWN:
								y++;
								break;
						case RIGHT:
								x++;
								break;
						case LEFT:
								x--;
								break;
				}

				if (x < 0 || x > WIDTH - 1 || y < 0 || y > HEIGHT - 1) {
						break;
				}
		}

		TV.delay_frame(1);
		
		checkSceneEnded(25);
}

unsigned int circleCounter = 0;
void circlesScene(bool changed) {
		if (changed) {

		}

		for (int i = 0; i < HEIGHT / 2; i++) {
				TV.draw_circle(WIDTH / 2, HEIGHT / 2, i, (i + circleCounter) % 2);
				TV.delay_frame(1);
		}

		circleCounter++;
		
		checkSceneEnded(15);
}

int startLen = 40;

int treeXOffset = 0;

void lSystemRecursive(int x, int y, double angle, int len) {
    if (len < 1) {
        return;
    }

    drawLineAngle(x, y, angle, len, 1);
    int endX, endY;
    toCartesian(x, y, angle, len, &endX, &endY);

    double startAngle = angle + ((branchAngle * (branches - 1)) / 2.0) + angleOffset;
    for (int i = 0; i < branches; i++) {
        double a = startAngle - (i * branchAngle);
        if (random(rouletteDenominator) != 0) {
            lSystemRecursive(endX, endY, a, len / 2);
        }
    }
}

void drawLSystem() {
    startLen = random(30, 50);
    branches = random(3, 5);
    branchAngle = random(25, 40);
    angleOffset = -10 + random(20);
    rouletteDenominator = random(3, 5);
    treeXOffset = -20 + random(40);
    lSystemRecursive(treeXOffset + (WIDTH / 2), HEIGHT - 1, 90.0 + angleOffset, startLen);
} 

void lSystemScene() {
    drawLSystem();
    TV.delay(200);
    TV.clear_screen();

    checkSceneEnded(20);
}

double currentAngle, hourAngle, minuteAngle;
