Game entry for the Game Programming Contest sponsored by OutrageousCircuits.com (RETRO Game Console)

Dependencies:   mbed

Fork of Official_RETRO by GHI Electronics

Files at this revision

API Documentation at this revision

Comitter:
Rogerup
Date:
Sun Mar 01 09:34:29 2015 +0000
Parent:
3:7680307a02d7
Commit message:
Game Entry

Changed in this revision

DisplayN18.cpp Show annotated file Show diff for this revision Revisions of this file
DisplayN18.h Show annotated file Show diff for this revision Revisions of this file
Game.cpp Show annotated file Show diff for this revision Revisions of this file
Game.h Show annotated file Show diff for this revision Revisions of this file
Level.cpp Show annotated file Show diff for this revision Revisions of this file
Main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 7680307a02d7 -r 2d41b942a823 DisplayN18.cpp
--- a/DisplayN18.cpp	Sat Feb 14 11:40:55 2015 +0000
+++ b/DisplayN18.cpp	Sun Mar 01 09:34:29 2015 +0000
@@ -189,10 +189,10 @@
 }
 
 void DisplayN18::drawRect(int x, int y, int width, int height, unsigned short foreColor) {
-    this->drawLine(x, y, x + width, y, foreColor);
-    this->drawLine(x, y + height, x + width, y + height, foreColor);
-    this->drawLine(x, y, x, y + height, foreColor);
-    this->drawLine(x + width, y, x + width, y + height, foreColor);
+    //this->drawLine(x, y, x + width, y, foreColor);
+    //this->drawLine(x, y + height, x + width, y + height, foreColor);
+    //this->drawLine(x, y, x, y + height, foreColor);
+    //this->drawLine(x + width, y, x + width, y + height, foreColor);
 }
 
 void DisplayN18::fillCircle(int x, int y, int radius, unsigned short foreColor) {
@@ -263,6 +263,7 @@
     }
 }
 
+/*
 void DisplayN18::drawLine(int x0, int y0, int x1, int y1, unsigned short foreColor) {
     if (x0 == x1) {
         if (y1 < y0) {
@@ -349,10 +350,11 @@
         }
     }
 }
+*/
 
-unsigned char characters[95 * 5] = {
+unsigned char characters[59 * 5] = {
     0x00, 0x00, 0x00, 0x00, 0x00, /* Space  0x20 */
-    0x00, 0x00, 0x4f, 0x00, 0x00, /* ! */
+    0x00, 0x4f, 0x4f, 0x00, 0x00, /* ! */
     0x00, 0x07, 0x00, 0x07, 0x00, /* " */
     0x14, 0x7f, 0x14, 0x7f, 0x14, /* # */
     0x24, 0x2a, 0x7f, 0x2a, 0x12, /* $ */
@@ -367,87 +369,70 @@
     0x08, 0x08, 0x08, 0x08, 0x08, /* - */
     0x00, 0x60, 0x60, 0x00, 0x00, /* . */
     0x20, 0x10, 0x08, 0x04, 0x02, /* / */
-    0x3e, 0x51, 0x49, 0x45, 0x3e, /* 0      0x30 */
-    0x00, 0x42, 0x7f, 0x40, 0x00, /* 1 */
-    0x42, 0x61, 0x51, 0x49, 0x46, /* 2 */
-    0x21, 0x41, 0x45, 0x4b, 0x31, /* 3 */
-    0x18, 0x14, 0x12, 0x7f, 0x10, /* 4 */
-    0x27, 0x45, 0x45, 0x45, 0x39, /* 5 */
-    0x3c, 0x4a, 0x49, 0x49, 0x30, /* 6 */
-    0x01, 0x71, 0x09, 0x05, 0x03, /* 7 */
-    0x36, 0x49, 0x49, 0x49, 0x36, /* 8 */
-    0x06, 0x49, 0x49, 0x29, 0x1e, /* 9 */
+    0x3e, 0x41, 0x41, 0x7f, 0x3e, /* 0      0x30 */
+    0x00, 0x42, 0x7f, 0x7f, 0x40, /* 1 */
+    0x72, 0x59, 0x49, 0x4f, 0x46, /* 2 */
+    0x49, 0x49, 0x49, 0x7f, 0x36, /* 3 */
+    0x1f, 0x10, 0x10, 0x7f, 0x7f, /* 4 */
+    0x4f, 0x4f, 0x49, 0x79, 0x31, /* 5 */
+    0x3e, 0x7f, 0x49, 0x49, 0x32, /* 6 */
+    0x01, 0x61, 0x79, 0x1f, 0x07, /* 7 */
+    0x36, 0x49, 0x49, 0x7f, 0x36, /* 8 */
+    0x26, 0x49, 0x49, 0x7f, 0x3e, /* 9 */
     0x00, 0x36, 0x36, 0x00, 0x00, /* : */
     0x00, 0x56, 0x36, 0x00, 0x00, /* ; */
     0x08, 0x14, 0x22, 0x41, 0x00, /* < */
     0x14, 0x14, 0x14, 0x14, 0x14, /* = */
-    0x00, 0x41, 0x22, 0x14, 0x08, /* > */
+    0x08, 0x08, 0x08, 0x1C, 0x08, /* > */
     0x02, 0x01, 0x51, 0x09, 0x06, /* ? */
     0x3e, 0x41, 0x5d, 0x55, 0x1e, /* @      0x40 */
-    0x7e, 0x11, 0x11, 0x11, 0x7e, /* A */
-    0x7f, 0x49, 0x49, 0x49, 0x36, /* B */
-    0x3e, 0x41, 0x41, 0x41, 0x22, /* C */
-    0x7f, 0x41, 0x41, 0x22, 0x1c, /* D */
-    0x7f, 0x49, 0x49, 0x49, 0x41, /* E */
-    0x7f, 0x09, 0x09, 0x09, 0x01, /* F */
+    0x7e, 0x7f, 0x11, 0x11, 0x7e, /* A */
+    0x7f, 0x7f, 0x49, 0x49, 0x36, /* B */
+    0x3e, 0x7f, 0x41, 0x41, 0x22, /* C */
+    0x7f, 0x7f, 0x41, 0x22, 0x1c, /* D */
+    0x7f, 0x7f, 0x49, 0x49, 0x49, /* E */
+    0x7f, 0x7f, 0x09, 0x09, 0x01, /* F */
     0x3e, 0x41, 0x49, 0x49, 0x7a, /* G */
-    0x7f, 0x08, 0x08, 0x08, 0x7f, /* H */
-    0x00, 0x41, 0x7f, 0x41, 0x00, /* I */
+    0x7f, 0x7f, 0x08, 0x08, 0x7f, /* H */
+    0x41, 0x7f, 0x7f, 0x41, 0x00, /* I */
     0x20, 0x40, 0x41, 0x3f, 0x01, /* J */
-    0x7f, 0x08, 0x14, 0x22, 0x41, /* K */
-    0x7f, 0x40, 0x40, 0x40, 0x40, /* L */
-    0x7f, 0x02, 0x0c, 0x02, 0x7f, /* M */
-    0x7f, 0x04, 0x08, 0x10, 0x7f, /* N */
-    0x3e, 0x41, 0x41, 0x41, 0x3e, /* O */
-    0x7f, 0x09, 0x09, 0x09, 0x06, /* P      0x50 */
-    0x3e, 0x41, 0x51, 0x21, 0x5e, /* Q */
-    0x7f, 0x09, 0x19, 0x29, 0x46, /* R */
-    0x26, 0x49, 0x49, 0x49, 0x32, /* S */
-    0x01, 0x01, 0x7f, 0x01, 0x01, /* T */
-    0x3f, 0x40, 0x40, 0x40, 0x3f, /* U */
-    0x1f, 0x20, 0x40, 0x20, 0x1f, /* V */
-    0x3f, 0x40, 0x38, 0x40, 0x3f, /* W */
+    0x7f, 0x7f, 0x14, 0x22, 0x41, /* K */
+    0x7f, 0x7f, 0x40, 0x40, 0x40, /* L */
+    0x7f, 0x7e, 0x0c, 0x06, 0x7f, /* M */ //02->06
+    0x7f, 0x7e, 0x08, 0x10, 0x7f, /* N */
+    0x3e, 0x7f, 0x41, 0x41, 0x3e, /* O */
+    0x7f, 0x7f, 0x09, 0x09, 0x06, /* P      0x50 */
+    0x3e, 0x7f, 0x51, 0x21, 0x5e, /* Q */
+    0x7f, 0x7f, 0x19, 0x29, 0x46, /* R */
+    0x26, 0x4f, 0x49, 0x79, 0x32, /* S */
+    0x01, 0x7f, 0x7f, 0x01, 0x01, /* T */
+    0x3f, 0x7f, 0x40, 0x40, 0x3f, /* U */
+    0x1f, 0x3f, 0x40, 0x20, 0x1f, /* V */
+    //0x3f, 0x40, 0x38, 0x40, 0x3f, /* W */
+    0x7f, 0x3f, 0x18, 0x20, 0x7f, /* W */
     0x63, 0x14, 0x08, 0x14, 0x63, /* X */
-    0x07, 0x08, 0x70, 0x08, 0x07, /* Y */
+    0x07, 0x0f, 0x78, 0x08, 0x07, /* Y */
     0x61, 0x51, 0x49, 0x45, 0x43, /* Z */
-    0x00, 0x7f, 0x41, 0x41, 0x00, /* [ */
-    0x02, 0x04, 0x08, 0x10, 0x20, /* \ */
-    0x00, 0x41, 0x41, 0x7f, 0x00, /* ] */
-    0x04, 0x02, 0x01, 0x02, 0x04, /* ^ */
-    0x40, 0x40, 0x40, 0x40, 0x40, /* _ */
-    0x00, 0x00, 0x03, 0x05, 0x00, /* `      0x60 */
-    0x20, 0x54, 0x54, 0x54, 0x78, /* a */
-    0x7F, 0x44, 0x44, 0x44, 0x38, /* b */
-    0x38, 0x44, 0x44, 0x44, 0x44, /* c */
-    0x38, 0x44, 0x44, 0x44, 0x7f, /* d */
-    0x38, 0x54, 0x54, 0x54, 0x18, /* e */
-    0x04, 0x04, 0x7e, 0x05, 0x05, /* f */
-    0x08, 0x54, 0x54, 0x54, 0x3c, /* g */
-    0x7f, 0x08, 0x04, 0x04, 0x78, /* h */
-    0x00, 0x44, 0x7d, 0x40, 0x00, /* i */
-    0x20, 0x40, 0x44, 0x3d, 0x00, /* j */
-    0x7f, 0x10, 0x28, 0x44, 0x00, /* k */
-    0x00, 0x41, 0x7f, 0x40, 0x00, /* l */
-    0x7c, 0x04, 0x7c, 0x04, 0x78, /* m */
-    0x7c, 0x08, 0x04, 0x04, 0x78, /* n */
-    0x38, 0x44, 0x44, 0x44, 0x38, /* o */
-    0x7c, 0x14, 0x14, 0x14, 0x08, /* p      0x70 */
-    0x08, 0x14, 0x14, 0x14, 0x7c, /* q */
-    0x7c, 0x08, 0x04, 0x04, 0x00, /* r */
-    0x48, 0x54, 0x54, 0x54, 0x24, /* s */
-    0x04, 0x04, 0x3f, 0x44, 0x44, /* t */
-    0x3c, 0x40, 0x40, 0x20, 0x7c, /* u */
-    0x1c, 0x20, 0x40, 0x20, 0x1c, /* v */
-    0x3c, 0x40, 0x30, 0x40, 0x3c, /* w */
-    0x44, 0x28, 0x10, 0x28, 0x44, /* x */
-    0x0c, 0x50, 0x50, 0x50, 0x3c, /* y */
-    0x44, 0x64, 0x54, 0x4c, 0x44, /* z */
-    0x08, 0x36, 0x41, 0x41, 0x00, /* { */
-    0x00, 0x00, 0x77, 0x00, 0x00, /* | */
-    0x00, 0x41, 0x41, 0x36, 0x08, /* } */
-    0x08, 0x08, 0x2a, 0x1c, 0x08  /* ~ */
 };
 
+unsigned short numbers[10] = { 0xF6BE, 0x592E, 0xE7CE, 0xE79E, 0xB792, 0xF39E, 0xF3DE, 0xE492, 0xF7DE, 0xF79E };
+
+void DisplayN18::drawNumber(int x, int y, const char character, unsigned short foreColor, unsigned short backColor)
+{
+    unsigned short mask = 0x8000; 
+    
+    for (int i = 0; i < 5; i++) {
+        for (int j = 0; j < 3; j++) {
+            if( numbers[character] & mask )
+                draw(&foreColor, x+j, y+i, 1, 1);
+            else
+                draw(&backColor, x+j, y+i, 1, 1);
+            
+            mask >>= 1;
+        }
+    }
+}
+
 void DisplayN18::drawCharacter(int x, int y, const char character, unsigned short foreColor, unsigned short backColor, unsigned char fontSize) {
     if (character > 126 || character < 32)
         return;
diff -r 7680307a02d7 -r 2d41b942a823 DisplayN18.h
--- a/DisplayN18.h	Sat Feb 14 11:40:55 2015 +0000
+++ b/DisplayN18.h	Sun Mar 01 09:34:29 2015 +0000
@@ -21,13 +21,19 @@
 
     public:
         DisplayN18();
-        
+        /*
         static const unsigned short BLUE = 0x00F8;
         static const unsigned short GREEN = 0xE007;
         static const unsigned short RED = 0x1F00;
+        static const unsigned short CYAN = 0xE0FF;
+        static const unsigned short MAGENT = 0x1FF8;
+        static const unsigned short YELLOW = 0xFF07;
         static const unsigned short WHITE = 0xFFFF;
+        static const unsigned short LGRAY = 0x18C6;
+        static const unsigned short GRAY = 0x1084;
+        static const unsigned short DGRAY = 0x0842;
         static const unsigned short BLACK = 0x0000;
-
+        */
         static const unsigned int WIDTH = 160;
         static const unsigned int HEIGHT = 128;
         static const unsigned char CHAR_WIDTH = 5;
@@ -46,8 +52,9 @@
         void fillCircle(int x, int y, int radius, unsigned short foreColor);
         void drawCircle(int x, int y, int radius, unsigned short foreColor);
 
-        void drawLine(int x0, int y0, int x1, int y1, unsigned short foreColor);
+        //void drawLine(int x0, int y0, int x1, int y1, unsigned short foreColor);
 
+        void drawNumber(int x, int y, const char character, unsigned short foreColor, unsigned short backColor);
         void drawCharacter(int x, int y, const char character, unsigned short foreColor, unsigned short backColor, unsigned char fontSize = 1);
         void drawString(int x, int y, const char* str, unsigned short foreColor, unsigned short backColor, unsigned char fontSize = 1);
 };
\ No newline at end of file
diff -r 7680307a02d7 -r 2d41b942a823 Game.cpp
--- a/Game.cpp	Sat Feb 14 11:40:55 2015 +0000
+++ b/Game.cpp	Sun Mar 01 09:34:29 2015 +0000
@@ -1,288 +1,332 @@
 #include "Game.h"
+#include <cstdarg>
+
+#define SOUNDWIN    1
 
-const char* Game::LOSE_1 = "You lose.";
-const char* Game::LOSE_2 = "Press ship to restart.";
-const char* Game::SPLASH_1 = "Press ship to start.";
-const char* Game::SPLASH_2 = "Press robot to switch.";
-    
-Game::Game() : left(P0_14, PullUp), right(P0_11, PullUp), down(P0_12, PullUp), up(P0_13, PullUp), square(P0_16, PullUp), circle(P0_1, PullUp), led1(P0_9), led2(P0_8), pwm(P0_18), ain(P0_15), i2c(P0_5, P0_4) {
-    srand(this->ain.read_u16());
-    
-    this->lastUp = false;
-    this->lastDown = false;
-    this->mode = true;
-    
-    this->i2c.frequency(400);
-    this->writeRegister(0x2A, 0x01); 
-    
-    this->colors[0] = DisplayN18::RED;
-    this->colors[1] = DisplayN18::GREEN;
-    this->colors[2] = DisplayN18::BLUE;
-    
+unsigned short piececolor[5] = { 0, LGRAY, WHITE, WHITE, DGRAY };
+
+Game::Game() : left(P0_14, PullUp), right(P0_11, PullUp), down(P0_12, PullUp), up(P0_13, PullUp), square(P0_16, PullUp), circle(P0_1, PullUp), led1(P0_9), led2(P0_8), pwm(P0_18), ain(P0_15), i2c(P0_5, P0_4)
+{
     this->initialize();
 }
 
-void Game::readRegisters(char address, char* buffer, int len) {
-    this->i2c.write(Game::I2C_ADDR, &address, 1, true);
-    this->i2c.read(Game::I2C_ADDR | 1, buffer, len);
+void Game::showNumber(int y, int val)
+{
+    char buf[8];
+    int len = sprintf(buf, "%d", val);
+    
+    disp.fillRect( 128, y+9, 32, 8, BLACK );
+    
+    if( val < 1000 )
+        disp.drawString(145-len*3, y+9, buf, CYAN, BLACK);
+    else
+        disp.drawString(145-3*3, y+9, "...", CYAN, BLACK);
 }
 
-int Game::writeRegister(char address, char value) {    
-    char buffer[2] = { address, value };
-    
-    return this->i2c.write(Game::I2C_ADDR, buffer, 2);
+void Game::initialize() 
+{
+    disp.clear();
+    led1 = 0; led2 = 0;
+    pwm = 0; pwm.period_ms(1);
+
+    tickCounter = 1000;
+    tickWin = 0;
+    bamTicksLeft = 0;
+
+    level = 0; oldLevel = -1;
+    for( int lev=0; lev<L_LAST; lev++ )
+        your[lev] = 10000;
+        
+    initTable();
 }
 
-double Game::convert(char* buffer) {
-    double val = ((buffer[0] << 2) | (buffer[1] >> 6));
-            
-    if (val > 511.0) 
-        val -= 1024.0;
+void Game::tick()
+{
+    tickCounter++;
+    
+    playSound();
     
-    return val / 512.0;
+    if( levelCompleted ) {
+        if( (tickCounter % 40) ==  0 ) { led1 = 1; led2 = 0; }
+        if( (tickCounter % 40) == 20 ) { led1 = 0; led2 = 1; }
+    }
+    
+    checkButtons();
+    if( level != L_INTRO)
+        showTable();
+        
+    playBam();
+    
+    wait_ms(25);
 }
 
-void Game::getXYZ(double& x, double& y, double& z) {
-    char buffer[6];
+void Game::checkButtons()
+{
+    bool kSquare = false, kCircle = false, kUp = false, kDown = false, kLeft = false, kRight = false;
     
-    this->readRegisters(0x01, buffer, 6);
+    //
+    // Repeat key after 16*25ms = 400ms
+    //
+    char noKey = 0;
+    if( !square.read() ) kSquare = !lastKey; else noKey++;
+    if( !circle.read() ) kCircle = !lastKey; else noKey++;
+    if( !up.read()     ) kUp     = !lastKey; else noKey++;
+    if( !down.read()   ) kDown   = !lastKey; else noKey++;
+    if( !left.read()   ) kLeft   = !lastKey; else noKey++;
+    if( !right.read()  ) kRight  = !lastKey; else noKey++;
+    if( noKey < 6 ) {
+        if( lastKey == 0 ) lastKey = 16; else lastKey--;
+    } else
+        lastKey = 0;
     
-    x = this->convert(buffer);
-    y = this->convert(buffer + 2);
-    z = this->convert(buffer + 4);
+    //
+    // Select level
+    //
+    if( kSquare ) if( ++level > L_LAST  ) level = L_INTRO;
+    if( kCircle ) if( --level < L_INTRO ) level = L_INTRO + 1; //L_LAST;
+    if( kSquare || kCircle || (!up.read() && !left.read()) )
+        initTable();
+    
+    //
+    // Arrow keys to move
+    //
+    if( kUp    ) moveTable( -1,  0,      1, TABH,      0, TABW );
+    if( kDown  ) moveTable(  1,  0, TABH-2,   -1,      0, TABW );
+    if( kLeft  ) moveTable(  0, -1,      0, TABH,      1, TABW );
+    if( kRight ) moveTable(  0,  1,      0, TABH, TABW-2,   -1 );
 }
 
-void Game::printDouble(double value, int x, int y) {
-    char buffer[10];
-    int len = sprintf(buffer, "%.1f", value);
-    
-    this->disp.drawString(x, y, buffer, DisplayN18::WHITE, DisplayN18::BLACK);
+void Game::fillTable(char i0, char j0, char h, char w, unsigned char v)
+{
+    unsigned char nh = v & 0xF0;
+    unsigned char nl = v & 0x0F;   
+
+    for( int i=i0; i<i0+h; i++ )
+        for( int j=j0; j<j0+w; j++ ) {
+            if( v <= BONG ) {
+                table[i][j] = v;
+            } else {
+                if( nh && table[i][j] <= BONG ) table[i][j] = FREE;
+                if( nh ) table[i][j] = (table[i][j] & 0x0F) | nh;
+                if( nl ) table[i][j] = (table[i][j] & 0xF0) | nl;
+            }
+
+            if( nl > MARK ) nl += 0x01;
+            if( nh > BALL ) nh += 0x10;
+            
+            change[i] |= 1 << j;
+        }
 }
 
-void Game::drawAxes() {
-    for (int i = 0; i < 3; i++) {
-        this->disp.drawLine(0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING), 0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT, DisplayN18::WHITE);
-        this->disp.drawLine(0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT / 2, DisplayN18::WIDTH, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT / 2, DisplayN18::WHITE);
+void Game::fillTableV( unsigned char v, ...)
+{
+    unsigned short pos;
+
+    va_list arguments; 
+        
+    va_start ( arguments, v );
+    
+    while( (pos = (unsigned short)va_arg ( arguments, int)) != 0 ) {
+        unsigned char h = (pos & 0x00F0) >> 4;
+        unsigned char w = (pos & 0x000F) >> 0;
+        if( w == 0 ) w = 16;
+        
+        fillTable((pos&0xF000)>>12, (pos&0x0F00)>>8, h, w, v);
+        if( (v&0x0F) > MARK ) v += h*w;
+        if( v > BALL ) v += ((h*w) << 4);
     }
+    
+    va_end ( arguments ); 
 }
 
-void Game::drawPoint(int axis, double value) {
-    if (value < -1.0)
-        value = -1.0;
+void Game::moveTable(int di, int dj, int i0, int i2, int j0, int j2 )
+{
+    if( level == L_INTRO || levelCompleted ) return;
+  
+    int ai = 1, aj = 1, mov = 0;
+    
+    if( i2 < i0 ) ai = -1;
+    if( j2 < j0 ) aj = -1;
 
-    if (value > 1.0)
-        value = 1.0;
+    //
+    // Check BONG (RED) - If any ball hits BONG, no ball can move.
+    //
+    for( int i=i0; i!=i2; i+=ai )
+        for( int j=j0; j!=j2; j+=aj )
+            if( table[i][j] & 0xF0 )
+                if( (table[i+di][j+dj] & 0x0F) == BONG ) {
+                    showNumber( MOVY, ++moves );
+                    bamX = (j+dj)*8; bamY = (i+di)*8;
+                    fillPieceV( BLACK,  0x0077, 0 );
+                    fillPieceV( YELLOW, 0x1111, 0x5111, 0x1511, 0x5511, 0x3115, 0x1351, 0x2233, 0 );
+                    disp.draw((unsigned short *)piece, bamX, bamY, 7, 7);
+                    bamTicksLeft = 5;
+                    return;
+                }
 
-    value += 1.0;
-    value /= 2.0;
-    value = 1.0 - value;
-    value *= Game::GRAPH_HEIGHT;
+    //
+    // Move Balls
+    //
+    for( int i=i0; i!=i2; i+=ai )
+    {
+        for( int j=j0; j!=j2; j+=aj )
+        {
+            unsigned char ball = table[i][j] & 0xF0;
+            
+            if( !ball ) continue;
+            if( table[i+di][j+dj] & 0xF0 ) continue;
+            if( (table[i+di][j+dj] & 0x0F) == WALL ) continue;
 
-    this->disp.setPixel(this->graphX, axis * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + (int)value, this->colors[axis]);
-}
-
-void Game::checkGraphReset() {
-    if (this->graphX > DisplayN18::WIDTH) {
-        this->graphX = 0;
-        this->disp.clear();
-        this->drawAxes();
+            table[i+di][j+dj] |= ball;
+            table[i][j] &= 0x0F;
+            
+            change[i+di] |= 1 << (j+dj);
+            change[i] |= 1 << j;
+            
+            mov = 1;
+        }
+    }
+    moves += mov;
+    showNumber( MOVY, moves );
+       
+    //
+    // Check if Level is Completed
+    //
+    int balls = 0, marks = 0;
+    for( int i=0; i<TABH; i++ ) {
+        for( int j=0; j<TABW; j++ )
+            if( table[i][j] & 0xF0 ) {
+                balls++;
+                if( ((table[i][j] & 0x0F) - MARK + 1) == ((table[i][j] & 0xF0) >> 4) )
+                    marks++;
+            }
+    }
+    if( marks == balls ) {
+        levelCompleted = true;
+        if( moves < your[level] ) your[level] = moves;
+        showNumber( YOUY, your[level] );
+        disp.drawString(8, 117, "  LEVEL COMPLETED!       ", RED, BLACK);
+        led1 = 1; led2 = 1;
+#ifdef SOUNDWIN
+        tickWin = tickCounter;
+#endif
     }
 }
 
-void Game::initialize() {    
-    this->initializeBall();
-        
-    this->paddleX = DisplayN18::WIDTH / 2 - Game::PADDLE_WIDTH / 2;
-    this->pwmTicksLeft = 0;
-    this->lives = 10;//4;
-    
-    this->pwm.period_ms(1);
-    this->pwm.write(0.00);
-    
-    this->disp.clear();
-}
-    
-void Game::initializeBall() {
-    this->ballX = DisplayN18::WIDTH / 2 - Game::BALL_RADIUS;
-    this->ballY = DisplayN18::HEIGHT / 4 - Game::BALL_RADIUS;
-    
-    this->ballSpeedX = rand() % 2 ? 1 : -1;
-    this->ballSpeedY = rand() % 2 ? 1 : -1;
+void Game::showTable()
+{
+    for( int i=0; i<TABH; i++ )
+        for( int j=0; j<TABW; j++ )
+            showPiece(i,j);
 }
 
-void Game::tick() {  
-    this->checkButtons();
+void Game::showPiece(int i, int j)
+{
+    if( !(change[i] & (1 << j)) ) return;
+
+    change[i] &= ~(1 << j);
+    
+    unsigned char ball = table[i][j] >> 4;
+    unsigned char base = table[i][j] & 0x0F;
+    
+    unsigned char basec = base;
+    if( basec > MARK ) basec = MARK;
+    
+    fillPiece( 0, 0, 7, 7, piececolor[basec] );
     
-    if (this->mode) {
-        this->clearPaddle();
-        this->clearBall();
-        
-        this->updatePaddle();
-        this->updateBall();
+    if( base == WALL ) {
+        fillPiece( 1, 1, 1, 1, 0 );
+        fillPiece( 1, 5, 1, 1, 0 );
+        fillPiece( 5, 1, 1, 1, 0 );
+        fillPiece( 5, 5, 1, 1, 0 );
+    }
     
-        this->checkCollision();
-        
-        this->drawPaddle();        
-        this->drawBall();
+    if( base == BONG ) {
+        fillPiece( 1, 1, 5, 5, RED );
+        //fillPieceV( RED, 0x1111, 0x5111, 0x1511, 0x5511, 0x3115, 0x1351, 0x2233, 0 );
+    }
+    
+    if( base == MARK ) {
+        fillPiece( 3, 3, 1, 1, WHITE );
+    }
+    
+    if( ball ) {
+        fillPieceV( BLUE, 0x1051,0x0175, 0x1651, 0 );
+        //fillPieceV( WHITE 0x3311, 0 );
+    }
         
-        this->checkPwm();
-        this->checkLives(); 
-        
-        wait_ms(25);
-    }
-    else {    
-        double x, y, z;
+    disp.draw((unsigned short *)piece, j*8, i*8, 7, 7);
+    
+    if( base > MARK && !ball )
+        disp.drawNumber( j*8+2, i*8+1, base-MARK, WHITE, piececolor[MARK] );
         
-        this->getXYZ(x, y, z);
-        
-        this->checkGraphReset();
-        this->drawPoint(0, x);
-        this->drawPoint(1, y);
-        this->drawPoint(2, z);
-        this->graphX++;
-    } 
+    if( ball > 1 )
+        disp.drawNumber( j*8+2, i*8+1, ball-1, WHITE, BLUE );
 }
 
-void Game::checkButtons() {
-    if (!this->square.read()) {
-        this->mode = !this->mode;
-        
-        this->disp.clear();
-        
-        if (!this->mode) {
-            this->graphX = 0;
-            
-            this->drawAxes();
-        }
-        
-        this->led1.write(this->mode);
-        this->led2.write(!this->mode);
-    }  
-    
-    bool xDir = this->ballSpeedX > 0;
-    bool yDir = this->ballSpeedY > 0;
-    bool isUp = !this->up.read();
-    bool isDown = !this->down.read();
-    
-    if (isUp && isDown) goto end;
-    if (!isUp && !isDown) goto end;
-    
-    if (isUp && this->lastUp) goto end;
-    if (isDown && this->lastDown) goto end;
-    
-    if (!xDir) this->ballSpeedX *= -1;
-    if (!yDir) this->ballSpeedY *= -1;
-    
-    if (isUp) {
-        if (++this->ballSpeedX > 5) this->ballSpeedX = 5;
-        if (++this->ballSpeedY > 5) this->ballSpeedY = 5;
-    }
-    else if (isDown) {
-        if (--this->ballSpeedX == 0) this->ballSpeedX = 1;
-        if (--this->ballSpeedY == 0) this->ballSpeedY = 1;
-    }
-    
-    if (!xDir) this->ballSpeedX *= -1;
-    if (!yDir) this->ballSpeedY *= -1;
-    
-end:
-    this->lastUp = isUp;
-    this->lastDown = isDown;    
+void Game::fillPiece(int x0, int y0, int w, int h, unsigned short v)
+{
+    for( int y=y0; y<y0+h; y++ )
+        for( int x=x0; x<x0+w; x++ )
+            piece[y][x] = v;
 }
 
-void Game::drawString(const char* str, int y) {
-    this->disp.drawString(DisplayN18::WIDTH / 2 - (DisplayN18::CHAR_WIDTH + DisplayN18::CHAR_SPACING) * strlen(str) / 2, y, str, DisplayN18::WHITE, DisplayN18::BLACK);         
+void Game::fillPieceV(unsigned short color, ...)
+{
+    va_list arguments; 
+    va_start( arguments, color );
+    
+    int pos;
+    while( (pos = va_arg ( arguments, int)) != 0 )
+        fillPiece( (pos&0xF000)>>12, (pos&0x0F00)>>8, (pos & 0x00F0) >> 4, (pos & 0x000F) >> 0, color );
+    
+    va_end( arguments );
 }
 
-void Game::showSplashScreen() {
-    this->drawString(Game::SPLASH_1, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT / 2);  
-    this->drawString(Game::SPLASH_2, DisplayN18::HEIGHT / 2 + DisplayN18::CHAR_HEIGHT / 2); 
-       
-    while (this->circle.read())
-        wait_ms(1);
-        
-    this->disp.clear();
-}
-
-void Game::clearPaddle() {
-    this->disp.fillRect(this->paddleX, DisplayN18::HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT, DisplayN18::BLACK);    
-}
-
-void Game::drawPaddle() {
-    this->disp.fillRect(this->paddleX, DisplayN18::HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT, DisplayN18::BLUE);    
-}
-
-void Game::updatePaddle() {
-    if (this->left.read())
-        this->paddleX += Game::PADDLE_SPEED;
-        
-    if (this->right.read())
-        this->paddleX -= Game::PADDLE_SPEED;
-}
-
-void Game::clearBall() {   
-    this->disp.fillRect(this->ballX - Game::BALL_RADIUS, ballY - Game::BALL_RADIUS, Game::BALL_RADIUS * 2, Game::BALL_RADIUS * 2, DisplayN18::BLACK); 
+void Game::showImage( unsigned char x, unsigned char y, unsigned short back, unsigned short front, ... )
+{
+    fillPieceV( back, 0x0077, 0 );
+    
+    va_list args;
+    va_start( args, front );
+    
+    int pos;
+    while( (pos = va_arg ( args, int)) != 0 )
+        fillPiece( (pos&0xF000)>>12, (pos&0x0F00)>>8, (pos & 0x00F0) >> 4, (pos & 0x000F) >> 0, front );
+    
+    va_end( args );
+    
+    disp.draw( (unsigned short *)piece, x, y, 7, 7 );
 }
 
-void Game::drawBall() {
-    this->disp.fillRect(this->ballX - Game::BALL_RADIUS, ballY - Game::BALL_RADIUS, Game::BALL_RADIUS * 2, Game::BALL_RADIUS * 2, DisplayN18::RED); 
-}
-
-void Game::updateBall() {
-    this->ballX += this->ballSpeedX;
-    this->ballY += this->ballSpeedY;
-}
-
-void Game::checkCollision() {    
-    if (this->paddleX < 0)
-        this->paddleX = 0;
-        
-    if (this->paddleX + Game::PADDLE_WIDTH > DisplayN18::WIDTH)
-        this->paddleX = DisplayN18::WIDTH - Game::PADDLE_WIDTH;
+void Game::playBam()
+{
+    if( bamTicksLeft == 0 )
+        return;
         
-    if ((this->ballX - Game::BALL_RADIUS < 0 && this->ballSpeedX < 0) || (this->ballX + Game::BALL_RADIUS >= DisplayN18::WIDTH && this->ballSpeedX > 0))
-        this->ballSpeedX *= -1;
-        
-    if (this->ballY - Game::BALL_RADIUS < 0 && this->ballSpeedY < 0)
-        this->ballSpeedY *= -1;
-        
-    if (this->ballY + Game::BALL_RADIUS >= DisplayN18::HEIGHT - Game::PADDLE_HEIGHT && this->ballSpeedY > 0) {
-        if (this->ballY + Game::BALL_RADIUS >= DisplayN18::HEIGHT) {
-            this->initializeBall();
-            
-            this->lives--;
-        }
-        else if (this->ballX > this->paddleX && this->ballX < this->paddleX + Game::PADDLE_WIDTH) {
-            this->ballSpeedY *= -1;
-            
-            this->pwmTicksLeft = Game::BOUNCE_SOUND_TICKS;                       
-        }
+    if( --bamTicksLeft % 2 ) {
+        led1 = 1;
+        led2 = 1;
+    } else {
+        led1 = 0;
+        led2 = 0;
+    }
+    
+    //pwm.write(0.5);
+    pwm.period_us(50);
+    pwm.pulsewidth_us(50);
+    
+    if (bamTicksLeft == 0) {
+        pwm.write(0.0);
+        fillPieceV( WHITE, 0x0077, 0 );
+        fillPieceV( RED,   0x1111, 0x5111, 0x1511, 0x5511, 0x3115, 0x1351, 0x2233, 0 );
+        disp.draw((unsigned short *)piece, bamX, bamY, 7, 7);
     }
 }
 
-void Game::checkPwm() {
-    if (this->pwmTicksLeft == 0) {
-        this->pwm.write(0.0);
-    }
-    else {
-        this->pwmTicksLeft--;
-        this->pwm.write(0.5); 
-    }
-}
-
-void Game::checkLives() {
-    if (this->lives == 0) {
-        this->disp.clear();
-        
-        this->drawString(Game::LOSE_1, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT); 
-        this->drawString(Game::LOSE_2, DisplayN18::HEIGHT / 2);  
-        
-        while (this->circle.read())
-            wait_ms(1);
-            
-        this->initialize();
-    }
-    else {
-        this->disp.drawCharacter(0, 0, static_cast<char>(this->lives + '0'), DisplayN18::WHITE, DisplayN18::BLACK);   
-    }
+void Game::playSound()
+{
+    if( tickCounter == tickWin +  1 ) { pwm = 0.02; pwm.period( 1.0 / 330.0 ); }
+    if( tickCounter == tickWin +  9 ) { pwm = 0.02; pwm.period( 1.0 / 440.0 ); }
+    if( tickCounter == tickWin + 25 ) { pwm = 0; pwm.period_ms(1); }
 }
\ No newline at end of file
diff -r 7680307a02d7 -r 2d41b942a823 Game.h
--- a/Game.h	Sat Feb 14 11:40:55 2015 +0000
+++ b/Game.h	Sun Mar 01 09:34:29 2015 +0000
@@ -4,78 +4,116 @@
 
 #pragma once
 
-class Game {    
-    static const char* LOSE_1;
-    static const char* LOSE_2;
-    static const char* SPLASH_1;
-    static const char* SPLASH_2;
-    
-    static const int BALL_RADIUS = 3;
-    static const int PADDLE_WIDTH = 38;
-    static const int PADDLE_HEIGHT = 4;
-    static const int PADDLE_SPEED = 4;
-    static const int BOUNCE_SOUND_TICKS = 2;
-    static const int GRAPH_HEIGHT = 40;
-    static const int GRAPH_SPACING = 2;
+#define RED     0x1F00
+#define GREEN   0xE007
+#define BLUE    0x00F8
+
+#define YELLOW  0xFF07
+#define CYAN    0xE0FF
+#define MAGENT  0x1FF8
+
+#define WHITE   0xFFFF
+#define LGRAY   0x18C6
+#define GRAY    0x1084
+#define DGRAY   0x0842
+#define BLACK   0x0000
+
+#define TABW 16
+#define TABH 14
+
+#define WALL 0x01
+#define BONG 0x02
+#define FREE 0x03
+#define MARK 0x04
+#define MAR1 0x05
+#define BALL 0x10
+#define BAL1 0x20
+
+#define TITY 0
+#define LEVY 24
+#define BESY 48
+#define YOUY 72
+#define MOVY 96
+
+#define L_INTRO     0
+#define L_START     (L_INTRO     + 1)   //   1 1.0   9
+#define L_FIRSTBAM  (L_START     + 1)   //   2 1.0   9
+#define L_ZIGZAG    (L_FIRSTBAM  + 1)   //   3 1.0  11
+#define L_FIRSTPOS  (L_ZIGZAG    + 1)   //   4 1.0  13
+#define L_MANYBOX   (L_FIRSTPOS  + 1)   //  41 1.0   9
+//#define L_NOBACK    (L_MANYBOX   + 1)   // 470 1.8  26
+#define L_FEWMOVES  (L_MANYBOX   + 1)   //  44 2.1  18
+#define L_BAMPOS    (L_FEWMOVES  + 1)   //   6 5.7  15
+#define L_LABYRINTH (L_BAMPOS    + 1)   //  59 2.5  98
+#define L_FACEFOUR  (L_LABYRINTH + 1)   //  69 3.1  50
+#define L_MANYBAM   (L_FACEFOUR  + 1)   // 101 3.2  28
+#define L_CHANGEPOS (L_MANYBAM   + 1)   //   8 3.7  22
+#define L_ONLYTWO   (L_CHANGEPOS + 1)   //  73 3.9  50
+#define L_NUMBLOCKS (L_ONLYTWO   + 1)   //  94 4.0  54
+#define L_SEPARATED (L_NUMBLOCKS + 1)   //  10 4.6  17
+#define L_NUMBERMIX (L_SEPARATED + 1)   //  79 4.7  47
+#define L_STEPS     (L_NUMBERMIX + 1)   // 381 5.0  48
+#define L_CHESS     (L_STEPS     + 1)   //  25 5.7  46
+#define L_HAMMER    (L_CHESS     + 1)   // 464 6.3  50
+#define L_CAREMOVES (L_HAMMER    + 1)   // 128 6.5 248
+#define L_FLUTE     (L_CAREMOVES + 1)   // 126 6.9 118
+#define L_CROSS     (L_FLUTE     + 1)   // 136 7.0  70
+#define L_DIAGONAL  (L_CROSS     + 1)   // 445 7.1  78
+#define L_LASTSIX   (L_DIAGONAL  + 1)   // 239 7.2 119
+#define L_FORTYTWO  (L_LASTSIX   + 1)   // 106 4.9  42
+#define L_ALEXAND   (L_FORTYTWO  + 1)   //   7 7.4  23
+#define L_CALCULATE (L_ALEXAND   + 1)   // 123 7.5  76
+#define L_MANYBALLS (L_CALCULATE + 1)   //   9 8.0  26
+#define L_SPIDERBAM (L_MANYBALLS + 1)   // 110 8.1  65
+#define L_CONFUSE   (L_SPIDERBAM + 1)   // 135 8.5  37
+#define L_PRECISE   (L_CONFUSE   + 1)   // 142 8.8  61 (nao verificado)
+#define L_ORDER     (L_PRECISE   + 1)   // 113 9.8  50
+#define L_GRANDMAST (L_ORDER     + 1)   // 143  10 299
+#define L_LAST      (L_GRANDMAST + 0)   // LAST LEVEL
+
+class Game
+{    
     static const char I2C_ADDR = 0x1C << 1;
+
+    int tickCounter, tickWin, bamTicksLeft;
+    char lastKey;
     
-    int ballX;
-    int ballY;
-    int ballSpeedX;
-    int ballSpeedY;
-    int paddleX;
-    int pwmTicksLeft;
-    int lives;
-    int graphX;    
-    bool mode;
-    bool lastUp;
-    bool lastDown;
-    unsigned short colors[3];
+    unsigned char table[14][16];
+    unsigned short change[14];
+    unsigned short piece[7][7];
+    int best, moves;
+    short your[32];
+    int level, oldLevel;
+    bool levelCompleted;
+    unsigned char bamX, bamY;
 
-    DigitalIn left;
-    DigitalIn right;
-    DigitalIn down;
-    DigitalIn up;
-    DigitalIn square;
-    DigitalIn circle; 
-    DigitalOut led1;
-    DigitalOut led2;
+    DigitalIn left, right, down, up, square, circle; 
+    DigitalOut led1, led2;
     PwmOut pwm;
     AnalogIn ain;
     I2C i2c;
     DisplayN18 disp;
     
-    void readRegisters(char address, char* buffer, int len);
-    int writeRegister(char address, char value);
-    void getXYZ(double& x, double& y, double& z);
-    double convert(char* buffer);
-    void printDouble(double value, int x, int y);
-    
-    void drawAxes();
-    void drawPoint(int axis, double value);
-    void checkGraphReset();
+    void showNumber(int y, int val);
     
     void initialize();
-    void initializeBall();
-    
-    void drawString(const char* str, int y);
-    
-    void clearPaddle();
-    void drawPaddle();
-    void updatePaddle();
-    
-    void clearBall();
-    void drawBall();
-    void updateBall();
-    
+
     void checkButtons();
-    void checkCollision();
-    void checkPwm();
-    void checkLives();
+
+    void playBam();
+    void playSound();
+   
+    void initTable();
+    void fillTable(char i0, char j0, char h, char w, unsigned char v);
+    void fillTableV(unsigned char v, ...);
+    void showTable();
+    void moveTable(int di, int dj, int i0, int i2, int j0, int j2); 
+    void showPiece(int i, int j);
+    void fillPiece(int x0, int y0, int w, int h, unsigned short v);
+    void fillPieceV(unsigned short color, ...);
+    void showImage( unsigned char x, unsigned char y, unsigned short back, unsigned short front, ... );
     
     public:
         Game();
-        
-        void showSplashScreen();
         void tick();
 };
\ No newline at end of file
diff -r 7680307a02d7 -r 2d41b942a823 Level.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Level.cpp	Sun Mar 01 09:34:29 2015 +0000
@@ -0,0 +1,359 @@
+#include "Game.h"
+
+void Game::initTable()
+{
+    if( oldLevel == L_INTRO ) {
+        if( level == L_INTRO ) return;
+
+        disp.clear();
+        disp.drawString(133, TITY, "NOKO", MAGENT, BLACK);
+        disp.drawString(134, TITY+10, "BAM!", RED, BLACK);
+        disp.drawString(130, LEVY, "LEVEL", YELLOW, BLACK);
+        disp.drawString(133, BESY, "BEST",  YELLOW, BLACK);
+        disp.drawString(136, YOUY, "YOU",  YELLOW, BLACK);
+        disp.drawString(130, MOVY, "MOVES", YELLOW, BLACK);
+    }
+    oldLevel = level;
+    
+    levelCompleted = false;
+    moves = 0;
+
+    disp.fillRect( 0, 112, 160, 16, 0 );
+    fillTable( 0, 0, TABH, TABW, WALL );
+
+    switch( level ) {
+        case L_INTRO:
+            disp.clear();
+            
+            disp.drawString( 28,  9, "NOKO", MAGENT, BLACK, 2 );
+            disp.drawString( 88,  9, "BAM!", RED, BLACK, 2 );
+            
+            disp.drawString( 24, 32, "MOVE  THE BALLS >", YELLOW, BLACK );
+            disp.drawString( 24, 42, "TO THEIR PLACES >", YELLOW, BLACK );
+            
+            disp.drawString( 36, 58, "TRY LESS MOVES", GREEN, BLACK );
+            
+            //disp.drawString( 30, 61, "ARROWS = MOVE", YELLOW, BLACK );
+            disp.drawString( 30, 74, "SQUARE = LEVEL ++", YELLOW, BLACK );
+            disp.drawString( 30, 84, "CIRCLE = LEVEL --", YELLOW, BLACK );
+            disp.drawString( 30, 94, "LEFT + UP = CLEAR", YELLOW, BLACK );
+            
+            disp.drawString( 30, 111, "HAVE A GOOD TIME!", RED, BLACK );
+
+            showImage( 132, 32, BLACK, BLUE, 0x1051,0x0175, 0x1651, 0 );
+            showImage( 132, 42, GRAY, WHITE, 0x3311, 0 );
+            break;
+            
+        case L_START: // 1 (1.0)
+            fillTableV( FREE, 0x4566, 0 );
+            fillTableV( MARK, 0x4912, 0 );
+            fillTableV( BALL, 0x9511, 0x9811, 0 );
+            best = 9;
+            break;
+
+        case L_FIRSTBAM:    // 2 (1.0)
+            fillTableV( BONG, 0x4468, 0 );
+            fillTableV( FREE, 0x4566, 0 );
+            fillTableV( WALL, 0x6411, 0 );
+            fillTableV( MARK, 0x9512, 0 );
+            fillTableV( BALL, 0x4811, 0x4A11,0 );
+            best = 9;
+            break;
+            
+        case L_ZIGZAG:      // 3 (1.0)
+            fillTableV( FREE, 0x4631, 0x4741, 0x5841, 0x6941, 0x7A41, 0x8B41, 0x9C31, 0 );
+            fillTableV( MARK, 0x9C11, 0xBC11, 0 );
+            fillTableV( BALL, 0x4611, 0x6611,0 );
+            best = 11;
+            break;
+            
+        case L_FIRSTPOS:    // 4 (1.0)
+            fillTableV( FREE, 0x4566, 0 );
+            fillTableV( WALL, 0x9711, 0 );
+            fillTableV( MAR1, 0x5A11, 0x4A11, 0 );
+            fillTableV( BAL1, 0x9911, 0x9A11, 0 );
+            best = 13;
+            break;
+            
+        case L_MANYBOX:     // 41 (1.0)
+            fillTableV( FREE, 0x1133, 0x1513, 0x1931, 0x1B31, 0x2611, 0x2913, 0x3513, 0 );
+            fillTableV( FREE, 0x5232, 0x5532, 0x6923, 0 );
+            fillTableV( FREE, 0x9133, 0x9533, 0x9933, 0 );
+            fillTableV( WALL, 0x9711, 0xA211, 0xA611, 0xAA11, 0xB911, 0 );
+            fillTableV( MARK, 0x3311, 0x3711, 0x3B11, 0x7311, 0x7711, 0x7B11, 0xB311, 0xB711, 0xBB11, 0 );
+            fillTableV( BALL, 0x1111, 0x1511, 0x1911, 0x5211, 0x5511, 0x6911, 0x9111, 0x9511, 0x9911, 0 );
+            best = 9;
+            break;
+            
+        /*
+        case L_NOBACK:      // 470 (1.8)
+            fillTableV( FREE, 0x03DD, 0 );
+            fillTableV( WALL, 0x0321, 0xA411, 0xAE11, 0xB511, 0xCD11, 0 );
+            fillTableV( BONG, 0x0111, 0x041C, 0x152B, 0x3011, 0x366A, 0xB617, 0 );
+            fillTableV( MARK, 0x1111, 0x3111, 0 );
+            fillTableV( BALL, 0x1111, 0x3111, 0 );
+            fillTableV( MAR1, 0xCF11, 0xBF11, 0xCC11, 0 );
+            fillTableV( BAL1, 0x1411, 0x3511, 0x2311, 0 );
+            best = 26;
+            break;
+        */
+            
+        case L_FEWMOVES:    //  44 2.1
+            fillTableV( FREE, 0x23AA, 0 );
+            fillTableV( WALL, 0x3712, 0x6518, 0x8831, 0 );
+            fillTableV( MARK, 0x9611, 0x9A11, 0 );
+            fillTableV( BALL, 0x5611, 0x5A11, 0 );
+            best = 18;
+            break;
+            
+        case L_LABYRINTH:   // 59 2.5
+            fillTableV( FREE, 0x0511, 0x1016, 0x1A16, 0x2311, 0x2F11, 0x3014, 0x3917, 0x4011, 0x4614, 0 );
+            fillTableV( FREE, 0x5012, 0x5611, 0x5B15, 0x6111, 0x6612, 0x6913, 0x6F41, 0x7012, 0x7313, 0 );
+            fillTableV( FREE, 0x7731, 0x7931, 0x7D13, 0x8011, 0x8311, 0x8541, 0x8B41, 0x8D11, 0x9014, 0 );
+            fillTableV( FREE, 0x9713, 0x9B13, 0xB016, 0xB723, 0xBB15, 0xC011, 0xCF11, 0xD010, 0 );
+            fillTableV( MAR1, 0x0011, 0x0B11, 0x0F11, 0x411, 0 );
+            fillTableV( BAL1, 0xD614, 0 );
+            best = 98;
+            break;
+            
+        case L_FACEFOUR:    //  69 3.1
+            fillTableV( FREE, 0x23AA, 0 );
+            fillTableV( WALL, 0x4511, 0x4A11, 0x9712, 0 );
+            fillTableV( MAR1, 0x5611, 0x5911, 0x8712, 0 );
+            fillTableV( BAL1, 0x9A11, 0x9511, 0x5811, 0x5711, 0 );
+            best = 50;
+            break;
+            
+        case L_MANYBAM:     // 101 (3.2)
+            fillTableV( FREE, 0x23AA, 0 );
+            fillTableV( WALL, 0x6611, 0x6911, 0xB411, 0 );
+            fillTableV( BONG, 0x2516, 0x2CA1, 0x3391, 0x4611, 0x4813, 0x6511, 0x7641, 0x7941, 0 );
+            fillTableV( BONG, 0x8431, 0x8B41, 0 );
+            fillTableV( MAR1, 0x6712, 0 );
+            fillTableV( BAL1, 0x5911, 0x5511, 0 );
+            best = 28;
+            break;
+            
+        case L_CHANGEPOS:   // 8 (3.7)
+            fillTableV( FREE, 0x2691, 0x2891, 0 );
+            fillTableV( MAR1, 0x3711, 0x5711, 0x7711, 0x9711, 0 );
+            fillTableV( BAL1, 0x9711, 0x7711, 0x5711, 0x3711, 0 );
+            best = 22;
+            break;
+            
+        case L_ONLYTWO:     // 73 (3.9)
+            fillTableV( FREE, 0x117E, 0x831B, 0x913F, 0xC11C, 0xCE12, 0 );
+            fillTableV( BONG, 0x9F11, 0xA111, 0 );
+            fillTableV( MARK, 0x8011, 0 );
+            fillTableV( BALL, 0x8F11, 0 );
+            fillTableV( MAR1, 0x1111, 0x8E11, 0 );
+            fillTableV( BAL1, 0x9011, 0x8011, 0 );
+            best = 50;
+            break;
+            
+        case L_NUMBLOCKS:   // 94 (4.0)
+            fillTableV( FREE, 0x0211, 0x03E4, 0x09E4, 0x2F11, 0x3083, 0x3D83, 0xB011, 0xDD11, 0 );
+            fillTableV( MAR1, 0x1E11, 0xCE11, 0x1F11, 0xDE11, 0x2522, 0 );
+            fillTableV( BAL1, 0xA922, 0x1111, 0x0111, 0xC012, 0 );
+            best = 54;
+            break;
+            
+        case L_SEPARATED:   // 14 10 (4.6)
+            fillTableV( FREE, 0x4166, 0x4966, 0 );
+            fillTableV( WALL, 0x5311, 0 );
+            fillTableV( BONG, 0x4211, 0x4A11, 0x5611, 0x5E11, 0x6411, 0x7911, 0x7B11, 0x8111, 0x8E11, 0x9611, 0 );
+            fillTableV( MARK, 0x7511, 0x8A11, 0 );
+            fillTableV( BALL, 0x8311, 0x8B11, 0 );
+            best = 17;
+            break;
+            
+        case L_NUMBERMIX:   // 15 79 (4.7)
+            fillTableV( FREE, 0x11CE, 0 );
+            fillTableV( WALL, 0x5321, 0x5C21, 0 );
+            fillTableV( MAR1, 0x8D11, 0x7D11, 0x2D11, 0x5D11, 0x4D11, 0x1D11, 0x6D11, 0x3D11, 0 );
+            fillTableV( BAL1, 0xCE11, 0xCD11, 0xCC11, 0xCB11, 0xCA11, 0xC911, 0xC811, 0xC711, 0 );
+            best = 47;
+            break;
+            
+        case L_STEPS:       // 16 381 (5.0)
+            fillTableV( FREE, 0x2361, 0x2561, 0x2761, 0x2961, 0x2B61, 0x834A, 0 );
+            fillTableV( WALL, 0x541C, 0 );
+            fillTableV( MAR1, 0x2411, 0x2611, 0x2811, 0x2A11, 0x2C11, 0 );
+            fillTableV( BAL1, 0x6311, 0x6511, 0x6711, 0x6911, 0x6B11, 0 );
+            best = 48;
+            break;
+
+        case L_BAMPOS:      // 17 6 (5.7)
+            fillTableV( BONG, 0x3488, 0 );
+            fillTableV( FREE, 0x4566, 0 );
+            fillTableV( WALL, 0x5911, 0 );
+            fillTableV( MAR1, 0x6811, 0x4A11, 0 );
+            fillTableV( BAL1, 0x4A11, 0x6811, 0 );
+            best = 15;
+            break;
+            
+        case L_CHESS:       // 18 25 (5.7)
+            fillTableV( FREE, 0x24A1, 0x26A1, 0x28A1, 0x2AA1, 0x2CA1, 0 );
+            fillTableV( FREE, 0x3711, 0x3B11, 0x4511, 0x4911, 0x5711, 0x5B11, 0 );
+            fillTableV( FREE, 0x8511, 0x8911, 0x9711, 0x9B11, 0xA511, 0xA911, 0 );
+            fillTableV( BONG, 0x2511, 0x2911, 0x6511, 0x6911, 0x7711, 0x7B11, 0xB711, 0xBB11, 0 );
+            fillTableV( MAR1, 0x2D11, 0x4D11, 0x6D11, 0x8D11, 0xAD11, 0 );
+            fillTableV( BAL1, 0xB311, 0x9311, 0x7311, 0x5311, 0x3311, 0 );
+            best = 46;
+            break;
+            
+        case L_HAMMER:      // 19 464 (6.3)
+            fillTableV( FREE, 0x0015, 0x0913, 0x0D13, 0x1041, 0x1616, 0x1F31, 0x222C, 0x422B, 0 );
+            fillTableV( FREE, 0x612E, 0x824C, 0x9051, 0x9F51, 0xC612, 0xD015, 0xD917, 0 );
+            fillTableV( MARK, 0x4F11, 0x5623, 0x7721, 0 );
+            fillTableV( BALL, 0x0612, 0x4F11, 0x6021, 0x6F21, 0xD612, 0 );
+            best = 50; // (Possible 37)
+            break;
+            
+        case L_CAREMOVES:   // 20 128 (6.5)
+            fillTableV( FREE, 0x11CE, 0xB031, 0 );
+            fillTableV( WALL, 0x1A51, 0x3521, 0x3B12, 0x711A, 0x8631, 0x9841, 0xA231, 0xC711, 0 );
+            fillTableV( BONG, 0x1911, 0x1B24, 0x3411, 0x4611, 0x5911, 0x5B11, 0x6111, 0x7B11, 0 );
+            fillTableV( BONG, 0x8441, 0x9211, 0x9B11, 0xBD22, 0xC611, 0xC911, 0 );
+            fillTableV( MAR1, 0x1122, 0 );
+            fillTableV( BAL1, 0xC021, 0xD111, 0xC111, 0 );
+            best = 248;
+            break;
+            
+        case L_FLUTE:       // 21 126 (6.9)
+            fillTableV( FREE, 0x00E0, 0 );
+            fillTableV( WALL, 0x0021, 0x0231, 0x0441, 0x0651, 0x0861, 0x0A71, 0x0C81, 0x0E91, 0xA311, 0 );
+            fillTableV( BONG, 0x3111, 0x4311, 0x5511, 0x6711, 0x7911, 0x8B11, 0x9D11, 0 );
+            fillTableV( MAR1, 0x0F71, 0 );
+            fillTableV( BAL1, 0x0111, 0x0311, 0x0511, 0x0711, 0x0911, 0x0B11, 0x0D11, 0 );
+            best = 118;
+            break;
+
+        case L_CROSS:       // 22 136 (7.0)
+            fillTableV( FREE, 0x12CC, 0 );
+            fillTableV( WALL, 0x1712, 0x6221, 0x6D21, 0xC712, 0 );
+            fillTableV( BONG, 0x6722, 0 );
+            fillTableV( MAR1, 0x5611, 0x5911, 0x8911, 0x8611, 0 );
+            fillTableV( BAL1, 0x9A11, 0x9511, 0x4511, 0x4A11, 0 );
+            best = 70;
+            break;
+            
+        case L_DIAGONAL:    // 23 445 (7.1)
+            fillTableV( FREE, 0x00E0, 0 );
+            fillTableV( WALL, 0x0111, 0x2113, 0x4313, 0x6513, 0x8713, 0xA913, 0xCB13, 0x2A21, 0 );
+            fillTableV( BONG, 0x2411, 0x5711, 0x8A11, 0xBD11, 0 );
+            fillTableV( MARK, 0x0B25, 0x2E22, 0 );
+            fillTableV( BALL, 0x0011, 0x1111, 0x2211, 0x3311, 0x4411, 0x5511, 0x6611, 0 );
+            fillTableV( BALL, 0x7711, 0x8811, 0x9911, 0xAA11, 0xBB11, 0xCC11, 0xDD11, 0 );
+            best = 78;
+            break;
+            
+        case L_LASTSIX:     // 24 239 (7.2)
+            fillTableV( FREE, 0x00E0, 0 );
+            fillTableV( WALL, 0x501D, 0 );
+            fillTableV( MARK, 0x0020, 0 );
+            fillTableV( BALL, 0x6012, 0x6813, 0x7211, 0x7711, 0x8311, 0x8611, 0x9412, 0 );
+            fillTableV( BALL, 0x8F11, 0x9E12, 0xAD13, 0xBC14, 0xCB15, 0xDA16, 0 );
+            best = 119;
+            break;
+            
+        case L_FORTYTWO:    // 24 106 (4.2)
+            fillTableV( BONG, 0x00E0, 0 );
+            fillTableV( FREE, 0x11CE, 0 );
+            fillTableV( WALL, 0x2234, 0x5521, 0x2914, 0x3C11, 0x4914, 0x5911, 0x6914, 0 );
+            fillTableV( MARK, 0xA323, 0xC312, 0 );
+            fillTableV( BALL, 0x2322, 0x3A12, 0x5A12, 0 );
+            best = 42;
+            break;
+            
+        case L_ALEXAND:     // 25 7 (7.4)
+            fillTableV( FREE, 0x23AA, 0 );
+            fillTableV( WALL, 0x3411, 0x6611, 0xAB11, 0 );
+            fillTableV( MAR1, 0x2311, 0x4511, 0x4811, 0x8611, 0 );
+            fillTableV( BAL1, 0x5911, 0x8711, 0x2C11, 0x7311, 0 );
+            best = 23;
+            break;
+            
+        case L_CALCULATE:   // 26 123 (7.5)
+            fillTableV( FREE, 0x3574, 0x6114, 0x7311, 0 );
+            fillTableV( WALL, 0x3711, 0x9611, 0 );
+            fillTableV( MAR1, 0x5633, 0 );
+            fillTableV( BAL1, 0x8111, 0x4211, 0x5111, 0x9111, 0x8311, 0x9211, 0x4311, 0x9311, 0x4111, 0 );
+            best = 76;
+            break;
+            
+        case L_MANYBALLS:   // 27 9 (8.0)
+            fillTable( 0, 0, TABH, TABW, FREE );
+            fillTable( 0, 0, 2, TABW, MARK );
+            fillTable( TABH-2, 0, 2, TABW, BALL );
+            fillTable( TABH/2-1, TABW/2-1, 2, 2, WALL );
+            best = 26;
+            break;
+            
+        case L_SPIDERBAM:   // 28 110 8.1
+            fillTableV( FREE, 0x00E8, 0x0841, 0x0931, 0x0A21, 0x0B11, 0x0D21, 0x1C21, 0x2B21, 0 );
+            fillTableV( FREE, 0x3A21, 0x4921, 0x5841, 0x8921, 0x9A21, 0xAB21, 0xBC21, 0xCD21, 0 );
+            fillTableV( FREE, 0xA841, 0xB931, 0xCA21, 0xDB11, 0 );
+            fillTableV( BONG, 0x0821, 0x1511, 0x2611, 0x3122, 0x3711, 0x6111, 0x6311, 0x6511, 0x6711, 0 );
+            fillTableV( BONG, 0x0821, 0x1511, 0x2611, 0x3122, 0x3711, 0x6111, 0x6311, 0x6511, 0x6711, 0 );
+            fillTableV( BONG, 0x7011, 0x7211, 0x7411, 0x7611, 0x7811, 0x9122, 0xA711, 0xB611, 0xC511, 0xC821, 0 );
+            fillTableV( MARK, 0x1011, 0xC011, 0 );
+            fillTableV( BALL, 0x0E11, 0xDE11, 0 );
+            best = 65;
+            break;
+            
+        case L_CONFUSE:     // 29 135 (8.5)
+            fillTableV( FREE, 0x11CE, 0 );
+            fillTableV( WALL, 0x2212, 0x4B11, 0x5C11, 0x6D11, 0xA611, 0xCB11, 0 );
+            fillTableV( BONG, 0x1511, 0x1A11, 0x3311, 0x4711, 0x5211, 0x5911, 0x7121, 0x7A21, 0 );
+            fillTableV( BONG, 0x8611, 0x9C11, 0xA121, 0xC611, 0xC911, 0xCD11, 0 );
+            fillTableV( MARK, 0xBE11, 0 );
+            fillTableV( MAR1, 0xCE11, 0xBD11, 0xAC11, 0 );
+            fillTableV( BALL, 0x1611, 0 );
+            fillTableV( BAL1, 0x4411, 0x6611, 0x5511, 0 );
+            best = 37;
+            break;
+            
+        case L_PRECISE:     // 30 142 (8.8)
+            fillTableV( FREE, 0x0614, 0x1631, 0x4687, 0 );
+            fillTableV( WALL, 0x8842, 0 );
+            fillTableV( BONG, 0x1812 ,0x4581, 0x4714, 0x5C71, 0x7811, 0x9731, 0x9A31, 0 );
+            fillTableV( MAR1, 0xB611, 0xBB11, 0 );
+            fillTableV( BAL1, 0x5911, 0x5811, 0 );
+            best = 61;
+            break;
+            
+        case L_ORDER:       // 31 113 (9.8)
+            fillTableV( FREE, 0x4715, 0x5711, 0x5B41, 0x8A11, 0 );
+            fillTableV( BONG, 0x5A11, 0 );
+            fillTableV( MAR1, 0x6713, 0x7713, 0x8713, 0 );
+            fillTableV( BAL1, 0x8911, 0x8711, 0x7711, 0x6711, 0x6911, 0x7811, 0x7911, 0x6811, 0x8811, 0 );
+            best = 50;
+            break;
+            
+        case L_GRANDMAST:   // 32 143 (10.0)
+            fillTableV( FREE, 0x00E0, 0 );
+            fillTableV( WALL, 0x0541, 0x1742, 0x2043, 0x3D33, 0x5314, 0x5814, 0x6911, 0x6C11, 0 );
+            fillTableV( WALL, 0x7211, 0x7611, 0x7A11, 0x8411, 0x8811, 0x8E11, 0x9713, 0 );
+            fillTableV( WALL, 0xA013, 0xA41C, 0xB313, 0xC611, 0xC814, 0xD014, 0xD914, 0 );
+            fillTableV( BONG, 0x1911, 0x1B11, 0x1D11, 0x1F11, 0x2831, 0x3231, 0x3B21, 0 );
+            fillTableV( BONG, 0x4111, 0x5C11, 0x6611, 0x9A11, 0xA714, 0xB411, 0xB611, 0 );
+            fillTableV( BONG, 0xC511, 0xCC11, 0 );
+            fillTableV( MARK, 0xDB11, 0 );
+            fillTableV( MAR1, 0xDD11, 0xDF11, 0xDE11, 0x2021, 0x2111, 0x8C11, 0x9611, 0x9E11, 0 );
+            fillTableV( BALL, 0xDA11, 0 );
+            fillTableV( BAL1, 0xC211, 0xC012, 0x4E12, 0x3F11, 0x5011, 0x8311, 0x6B11, 0 );
+            best = 299;
+            break;
+    }
+    
+    if( level != L_INTRO ) {
+        showNumber( LEVY, level );
+        showNumber( BESY, best );
+        showNumber( YOUY, your[level] );
+        showNumber( MOVY, moves );
+    }
+    
+    led1 = 0; led2 = 0;
+    pwm = 0; pwm.period_ms(1);
+}
\ No newline at end of file
diff -r 7680307a02d7 -r 2d41b942a823 Main.cpp
--- a/Main.cpp	Sat Feb 14 11:40:55 2015 +0000
+++ b/Main.cpp	Sun Mar 01 09:34:29 2015 +0000
@@ -2,11 +2,10 @@
 
 #include "Game.h"
 
-int main() {
+int main()
+{
     Game game;
-        
-    game.showSplashScreen();
-    
+
     while (true)
         game.tick();
 }
\ No newline at end of file