khoa phan test

Dependencies:   4DGL-uLCD-SE MMA8452 mbed wave_player

Fork of rpg_game_shell by ECE 2035 TA

Files at this revision

API Documentation at this revision

Comitter:
kphan9
Date:
Sun Apr 22 02:27:42 2018 +0000
Parent:
1:399033d39feb
Commit message:
test

Changed in this revision

graphics.cpp Show annotated file Show diff for this revision Revisions of this file
graphics.h Show annotated file Show diff for this revision Revisions of this file
hardware.cpp Show annotated file Show diff for this revision Revisions of this file
hash_table.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
map.cpp Show annotated file Show diff for this revision Revisions of this file
map.h Show annotated file Show diff for this revision Revisions of this file
speech.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/graphics.cpp	Wed Apr 04 21:11:07 2018 +0000
+++ b/graphics.cpp	Sun Apr 22 02:27:42 2018 +0000
@@ -1,17 +1,13 @@
 #include "graphics.h"
-
 #include "globals.h"
-
-
-
-void draw_player(int u, int v, int key)
-{
-    uLCD.filled_rectangle(u, v, u+11, v+11, RED);
-}
-
 #define YELLOW 0xFFFF00
 #define BROWN  0xD2691E
 #define DIRT   BROWN
+#define RED    0xFF0000
+#define ORANGE 0xFFA500
+#define BLACK  0x000000
+#define WHITE  0xffffff
+#define SKIN   0xDCB847
 void draw_img(int u, int v, const char* img)
 {
     int colors[11*11];
@@ -23,12 +19,115 @@
         else if (img[i] == 'D') colors[i] = DIRT;
         else if (img[i] == '5') colors[i] = LGREY;
         else if (img[i] == '3') colors[i] = DGREY;
+        else if (img[i] == 'R') colors[i] = RED;
+        else if (img[i] == 'B') colors[i] = BLACK;
+        else if (img[i] == 'W') colors[i] = WHITE;
+        else if (img[i] == 'S') colors[i] = SKIN;
         else colors[i] = BLACK;
     }
     uLCD.BLIT(u, v, 11, 11, colors);
     wait_us(250); // Recovery time!
 }
 
+const char duck[121] = {
+    'B','B','B','B','B','B','Y','Y','Y','B','B',
+    'B','B','B','B','B','Y','Y','Y','Y','Y','B',    
+    'B','B','B','B','B','Y','Y','Y','B','Y','B',
+    'B','B','B','B','B','Y','Y','Y','Y','O','R',
+    'Y','B','Y','Y','Y','Y','Y','Y','Y','B','B',
+    'Y','5','Y','Y','5','Y','Y','Y','Y','Y','B',
+    'Y','Y','5','5','Y','Y','Y','Y','Y','Y','B',
+    'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
+    'B','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
+    'B','Y','Y','Y','Y','Y','Y','Y','Y','Y','B',
+    'B','Y','Y','Y','Y','Y','Y','Y','Y','Y','B',
+    };
+const char apple[121] = {
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','G','G','B','D','B','B','B','B',
+    'B','B','B','B','G','D','B','B','B','B','B',
+    'B','B','R','B','B','R','R','R','B','B','B',
+    'B','R','W','W','R','R','R','R','R','R','B',
+    'B','R','W','R','R','R','R','R','R','R','B',
+    'B','R','R','R','R','R','R','R','R','R','B',
+    'B','R','R','R','R','R','R','R','R','R','B',
+    'B','B','R','R','R','R','R','R','R','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    };
+    
+const char poisonapple[121] = {
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','G','G','B','D','B','B','B','B',
+    'B','B','B','B','G','D','B','B','B','B','B',
+    'B','B','R','B','B','R','R','R','G','B','B',
+    'B','G','W','W','R','R','R','R','R','R','B',
+    'B','R','W','R','G','R','R','R','R','R','B',
+    'B','R','R','R','R','R','R','R','G','R','B',
+    'B','R','R','G','R','R','R','R','R','R','B',
+    'B','B','R','R','R','R','R','R','R','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    };
+    
+const char oldMan[121] = {
+    'B','B','B','B','S','S','S','S','B','B','B',
+    'B','B','B','S','S','S','S','S','S','B','B',
+    'B','B','3','W','S','S','S','S','S','B','B',
+    'B','B','3','B','W','W','S','W','W','B','B',
+    'B','B','3','S','B','S','S','S','B','B','B',
+    'B','B','3','3','S','R','R','R','S','B','B',
+    'B','D','D','D','3','3','3','3','B','B','B',
+    'B','D','S','D','D','3','3','3','B','B','B',
+    'B','D','S','D','D','D','3','S','B','B','B',
+    'B','B','B','D','D','D','3','D','B','B','B',
+    'B','B','B','S','B','S','B','D','B','B','B',
+    };
+    
+const char goldkey [121] = {
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','Y','Y','Y','Y','B',
+    'B','Y','Y','Y','Y','Y','Y','W','W','Y','B',
+    'B','Y','Y','Y','Y','Y','Y','W','W','Y','B',
+    'B','Y','B','Y','B','B','Y','Y','Y','Y','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    };
+const char door [121] = {
+    'D','D','D','D','D','D','D','D','D','D','D',
+    'D','D','D','D','D','D','D','D','D','D','D',
+    'D','D','D','D','D','D','D','D','D','D','D',
+    'D','D','D','D','D','D','D','D','D','B','D',
+    'D','D','D','D','D','D','D','D','D','B','D',
+    'D','D','D','D','D','D','D','D','D','B','D',
+    'D','D','D','D','D','D','D','D','D','B','D',
+    'D','D','D','D','D','D','D','D','D','B','D',
+    'D','D','D','D','D','D','D','D','D','D','D',
+    'D','D','D','D','D','D','D','D','D','D','D',
+    'D','D','D','D','D','D','D','D','D','D','D',
+    };
+
+const char plant [121] = {
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','B','B','B','B','B','B','B','B',
+    'B','B','B','G','B','G','B','G','G','B','B',
+    'B','B','G','G','G','G','G','G','G','G','B',
+    'B','G','G','G','G','G','G','G','G','G','B',
+    'G','G','G','G','G','G','G','G','G','B','B',
+    'B','G','G','G','G','G','G','G','G','G','B',
+    'G','G','G','G','G','G','G','G','G','G','B',
+    'G','G','G','G','G','G','G','G','G','G','G',
+    };
+
+void draw_player(int u, int v, int key)
+{
+   draw_img(u, v, duck);
+}
+
 void draw_nothing(int u, int v)
 {
     // Fill a tile with blackness
@@ -38,11 +137,11 @@
 void draw_wall(int u, int v)
 {
     uLCD.filled_rectangle(u, v, u+10, v+10, BROWN);
-}
+}    
 
 void draw_plant(int u, int v)
 {
-    uLCD.filled_rectangle(u, v, u+10, v+10, GREEN);
+    draw_img(u, v, plant);
 }
 
 void draw_upper_status()
@@ -69,4 +168,41 @@
     uLCD.filled_rectangle(124,  14, 127, 117, WHITE); // Right
 }
 
+void draw_startScreen()
+{   
+    uLCD.text_bold(ON);
+    uLCD.text_string("Homebound Duck", 3, 1, FONT_7X8, WHITE);
+    uLCD.text_string("HELP THIS DUCK", 2, 7,FONT_7X8, WHITE);
+    uLCD.text_string("RETURN HOME", 5, 9,FONT_7X8, WHITE);
+    uLCD.text_string("Press any button", 1, 14, FONT_7X8, WHITE);
+    uLCD.text_string("to start", 1, 15, FONT_7X8, WHITE);
+}
 
+void draw_gameend()
+{   
+    uLCD.filled_rectangle(0,0, 127,  127, BLACK); // Top
+    uLCD.text_bold(ON);
+    uLCD.text_string("Game Over", 4, 1, FONT_7X8, WHITE);
+}
+void draw_NPC(int u, int v)
+{
+    draw_img(u, v, oldMan);
+}
+void draw_apple(int u, int v)
+{
+    draw_img(u,v,apple);
+}
+void draw_poiapple(int u, int v)
+{
+    draw_img(u,v,poisonapple);
+}
+void draw_door(int u, int v)
+{
+    draw_img(u,v,door);
+}
+void draw_key(int u, int v)
+{
+    draw_img(u,v,goldkey);    
+}
+
+
--- a/graphics.h	Wed Apr 04 21:11:07 2018 +0000
+++ b/graphics.h	Sun Apr 22 02:27:42 2018 +0000
@@ -29,6 +29,7 @@
 void draw_nothing(int u, int v);
 void draw_wall(int u, int v);
 void draw_plant(int u, int v);
+void draw_door(int u, int v);
 
 /**
  * Draw the upper status bar.
@@ -45,4 +46,9 @@
  */
 void draw_border();
 
+void draw_NPC(int u, int v);
+void draw_apple(int u, int v);
+void draw_poiapple(int u, int v);
+void draw_key(int u, int v);
+void draw_gameend();
 #endif // GRAPHICS_H
\ No newline at end of file
--- a/hardware.cpp	Wed Apr 04 21:11:07 2018 +0000
+++ b/hardware.cpp	Sun Apr 22 02:27:42 2018 +0000
@@ -32,12 +32,18 @@
     button1.mode(PullUp); 
     button2.mode(PullUp);
     button3.mode(PullUp);
+    acc.activate();
     
     return ERROR_NONE;
 }
 
 GameInputs read_inputs() 
 {
-    GameInputs in;
+    GameInputs in = {0};
+    in.b1 = button1.read();
+    in.b2 = button2.read();
+    in.b3 = button3.read();
+    
+    acc.readXYZGravity(&(in.ax),&(in.ay),&(in.az));
     return in;
 }
--- a/hash_table.cpp	Wed Apr 04 21:11:07 2018 +0000
+++ b/hash_table.cpp	Sun Apr 22 02:27:42 2018 +0000
@@ -127,6 +127,14 @@
 */
 static HashTableEntry* createHashTableEntry(unsigned int key, void* value) {
 
+HashTableEntry* spointer = (HashTableEntry*)malloc(sizeof(HashTableEntry));
+
+spointer -> key = key;
+spointer -> value = value;
+spointer -> next = NULL;
+
+return spointer;
+
 }
 
 /**
@@ -141,6 +149,26 @@
 */
 static HashTableEntry* findItem(HashTable* hashTable, unsigned int key) {
 
+unsigned int hashIndex = hashTable -> hash(key);
+HashTableEntry* hashEntry = hashTable -> buckets[hashIndex];
+if(hashEntry == NULL)
+{
+    return NULL;
+}
+
+while(1){
+    if (hashEntry == NULL){
+        return NULL;
+    }
+    else if(hashEntry -> key == key)
+    {
+        return hashEntry;
+    }
+    else{
+        hashEntry = hashEntry -> next;
+    }
+}
+
 }
 
 /****************************************************************************
@@ -178,21 +206,153 @@
 }
 
 void destroyHashTable(HashTable* hashTable) {
-
+void* value;
+HashTableEntry* temp;
+for(int i = 0; i<hashTable->num_buckets; i++){
+    HashTableEntry* hashEntry = hashTable->buckets[i];
+    while(hashEntry)
+    {
+        temp = hashEntry ->next;
+        free(hashEntry);
+        hashEntry = temp;
+    }
+}
 }
 
 void* insertItem(HashTable* hashTable, unsigned int key, void* value) {
+unsigned int hashIndex = hashTable->hash(key);
+HashTableEntry* hashEntry = hashTable -> buckets[hashIndex];
+void* temp;
+
+
+if(hashEntry == NULL){
+    hashTable -> buckets[hashIndex] = createHashTableEntry(key, value);
+    return NULL;
+
+}
+while(1){
+    if(hashEntry -> key == key){
+        temp = hashEntry -> value;
+        hashEntry -> value = value;
+        return temp;
+    }
+    if(hashEntry -> next == NULL){
+        hashEntry -> next = createHashTableEntry(key, value);
+        return NULL;
+    }
+    hashEntry = hashEntry -> next;
+}
 
 }
 
+
 void* getItem(HashTable* hashTable, unsigned int key) {
+    unsigned int hashIndex = hashTable->hash(key);
+    HashTableEntry* hashEntry = hashTable -> buckets[hashIndex];
+    void* value;
 
+    if(hashEntry == NULL){
+        return NULL;
+    }
+    while(1){
+        if(hashEntry ->key == key){
+            value = hashEntry -> value;
+            return value;
+        }
+        if(hashEntry -> next == NULL)
+        {
+            return NULL;
+        }
+        hashEntry = hashEntry -> next;
+    }
+    findItem(hashTable,key);
 }
 
 void* removeItem(HashTable* hashTable, unsigned int key) {
+    unsigned int hashIndex = hashTable->hash(key);
+    HashTableEntry* hashEntry = hashTable -> buckets[hashIndex];
+    HashTableEntry* temp;
+    void* value;
 
+    if(hashEntry == NULL){
+        return NULL;
+    }
+    if(hashEntry ->key == key)
+    {
+        temp = hashEntry -> next;
+        value = hashEntry -> value;
+
+        free(hashEntry);
+        hashTable -> buckets[hashIndex] = temp;
+        return value;
+    }
+    if (hashEntry -> next == NULL){
+        return NULL;
+    }
+
+    HashTableEntry* prev = hashEntry;
+    hashEntry = hashEntry-> next;
+
+    while(1){
+        if(hashEntry -> key == key){
+            temp = hashEntry -> next;
+            value = hashEntry -> value;
+            free(hashEntry);
+            prev -> next = temp;
+            return value;
+        }
+        else if (hashEntry -> next == NULL){
+
+            return NULL;
+        }
+        else{
+            prev = hashEntry;
+        }
+        hashEntry = hashEntry -> next;
+    }
 }
 
 void deleteItem(HashTable* hashTable, unsigned int key) {
+    unsigned int hashIndex = hashTable->hash(key);
+    HashTableEntry* hashEntry = hashTable -> buckets[hashIndex];
+    HashTableEntry* temp;
+    void* value;
 
-}
\ No newline at end of file
+    if(hashEntry == NULL){
+        return;
+    }
+    if(hashEntry ->key == key)
+    {
+        temp = hashEntry -> next;
+        value = hashEntry -> value;
+
+        free(value);
+        free(hashEntry);
+        hashTable -> buckets[hashIndex] = temp;
+        return;
+    }
+    if (hashEntry -> next == NULL){
+        return;
+    }
+
+    HashTableEntry* prev = hashEntry;
+    hashEntry = hashEntry-> next;
+
+    while(1){
+        if(hashEntry -> key == key){
+            temp = hashEntry -> next;
+            value = hashEntry -> value;
+            free(hashEntry);
+            prev -> next = temp;
+            return;
+        }
+        else if (hashEntry -> next == NULL){
+
+            return;
+        }
+        else{
+            prev = hashEntry;
+        }
+        hashEntry = hashEntry -> next;
+    }
+}
--- a/main.cpp	Wed Apr 04 21:11:07 2018 +0000
+++ b/main.cpp	Sun Apr 22 02:27:42 2018 +0000
@@ -7,10 +7,15 @@
 
 // Functions in this file
 int get_action (GameInputs inputs);
+int check_button(GameInputs inputs);
 int update_game (int action);
 void draw_game (int init);
+void draw_startScreen();
 void init_main_map ();
 int main ();
+int buttonPressed1 = 0;
+int buttonPressed2 = 0;
+int buttonPressed3 = 0;
 
 /**
  * The main game state. Must include Player locations and previous locations for
@@ -20,6 +25,10 @@
     int x,y;    // Current locations
     int px, py; // Previous locations
     int has_key;
+    int health;
+    int omni;
+    int apples;
+    int end;
 } Player;
 
 /**
@@ -33,11 +42,102 @@
 #define GO_RIGHT 4
 #define GO_UP 5
 #define GO_DOWN 6
+#define TALK 7
+#define DOORFOUND 8
+
 int get_action(GameInputs inputs)
 {
-    return NO_ACTION;
+    MapItem* itemNorth = get_north(Player.x,Player.y);
+    MapItem* itemSouth = get_south(Player.x,Player.y);
+    MapItem* itemEast = get_east(Player.x,Player.y);
+    MapItem* itemWest = get_west(Player.x,Player.y);
+    MapItem* itemHere = get_here(Player.x,Player.y);
+
+    //pc.printf("%d " , itemEast);
+    //pc.printf("%d " , itemEast -> walkable);
+    //pc.printf("%f, %f ", inputs.ax, inputs.ay);
+    
+    if((itemEast->type == NPC || itemWest->type == NPC || itemNorth->type == NPC || itemSouth->type == NPC) && inputs.b2 == 0)
+    {
+        return TALK;    
+    }
+    if((itemEast->type == DOOR || itemWest->type == DOOR || itemNorth->type == DOOR || itemSouth->type == DOOR) && inputs.b2 == 0)
+    {
+        return DOORFOUND;    
+    }
+    else if((inputs.ay <= -0.2) && (itemNorth->walkable || Player.omni == 1))
+    {
+        return GO_UP;
+    }
+    else if((inputs.ay >= 0.2) && (itemSouth->walkable || Player.omni == 1))
+    {
+        return GO_DOWN;
+    }
+    else if((inputs.ax <= -0.2) && (itemWest->walkable || Player.omni == 1))
+    {
+        return GO_LEFT;
+    }
+    else if((inputs.ax >= 0.2) && (itemEast->walkable || Player.omni == 1))
+    {
+        return GO_RIGHT;
+    }
+    else
+        return NO_ACTION;
 }
 
+int check_Button(GameInputs inputs)
+{
+    if(inputs.b1 == 0 && buttonPressed1 == 0)
+    {
+        buttonPressed1 = 1;
+    }
+    if(inputs.b1 == 1 && buttonPressed1 == 1)
+    {
+        Player.omni = !Player.omni;
+        buttonPressed1 = 0;
+        return 1;
+    }
+    if(inputs.b2 == 0 && buttonPressed2 == 0)
+    {
+        buttonPressed2 = 1;
+    }
+    if(inputs.b2 == 1 && buttonPressed2 == 1)
+    {
+        buttonPressed2 = 0;
+        return 1;
+    }
+    if(inputs.b3 == 0 && buttonPressed3 == 0)
+    {
+        buttonPressed3 = 1;
+    }
+    if(inputs.b3 == 1 && buttonPressed3 == 1)
+    {
+        buttonPressed3 = 0;
+        return 1;
+    }          
+}
+
+void check_stuff()
+{
+    MapItem* itemHere = get_here(Player.x,Player.y);
+    if(itemHere->type == APPLE)
+    {
+        deleteHere(Player.x,Player.y);
+        Player.apples ++;   
+    }
+    else if(itemHere->type == POIAPPLE)
+    {
+        deleteHere(Player.x,Player.y);
+        Player.health --;   
+    }
+    else if(itemHere->type == KEY)
+    {
+        deleteHere(Player.x,Player.y);
+        Player.has_key = 1;   
+    }
+}
+
+
 /**
  * Update the game state based on the user action. For example, if the user
  * requests GO_UP, then this function should determine if that is possible by
@@ -60,11 +160,64 @@
     // You can define functions like "go_up()" that get called for each case.
     switch(action)
     {
-        case GO_UP:     break;
-        case GO_LEFT:   break;            
-        case GO_DOWN:   break;
-        case GO_RIGHT:  break;
-        case ACTION_BUTTON: break;
+        case GO_UP:
+            Player.y = Player.y + 1; 
+            break;
+        case GO_LEFT:   
+            Player.x = Player.x - 1; 
+            break;            
+        case GO_DOWN:   
+            Player.y = Player.y - 1; 
+            break;
+        case GO_RIGHT:
+            Player.x = Player.x + 1; 
+            break;            
+        case TALK:
+            if(Player.apples == 0)
+            {
+                //talk to NPC
+                speech("Hello there my","Young duck");
+                speech("I can see you","are able to walk");
+                speech("You see I have","a problem!");
+                speech("My legs aren't","what they used to be");
+                speech("Give me 5 apples","and I will grant");
+                speech("You the key", "out of here");
+                speech("Careful of",  "Poison apples!");
+                add_apple(41,6);
+                add_apple(41,7);
+                add_apple(41,8);
+                add_apple(41,9);
+                add_apple(41,10);
+                add_poiapple(45,5);
+                add_poiapple(43,2);
+                add_poiapple(47,8);
+                add_poiapple(47,9);
+                add_poiapple(48,9);
+                add_poiapple(46,9);
+                add_poiapple(41,5);
+            }
+            else if (Player.apples >= 5)
+            {
+                speech("Thank you little", "Duckling!");
+                speech("Here is the key", "to the door!");
+                add_key(46,1);
+            }
+            else
+                speech("Where are the", "apples sir?");
+            break;
+        case DOORFOUND:
+            {
+                //open door
+                if(Player.has_key == 0)
+                {
+                    speech("You don't have the key!","");    
+                }
+                else
+                {
+                    speech("You open the door", "and return safely home");
+                    Player.end = 0;    
+                }    
+            }
         case MENU_BUTTON: break;
         default:        break;
     }
@@ -80,7 +233,11 @@
 void draw_game(int init)
 {
     // Draw game border first
-    if(init) draw_border();
+    if(init)
+    {
+        draw_border();
+    }
+    
     
     // Iterate over all visible map tiles
     for (int i = -5; i <= 5; i++) // Iterate over columns of tiles
@@ -103,7 +260,7 @@
             
             // Figure out what to draw
             DrawFunc draw = NULL;
-            if (init && i == 0 && j == 0) // Only draw the player on init
+            if (i == 0 && j == 0) // Only draw the player on init
             {
                 draw_player(u, v, Player.has_key);
                 continue;
@@ -146,12 +303,32 @@
  */
 void init_main_map()
 {
+    uLCD.filled_rectangle(0,0,127,127, BLACK);
     // "Random" plants
     Map* map = set_active_map(0);
-    for(int i = map_width() + 3; i < map_area(); i += 39)
+    for(int i = 15; i < 20; i ++)
+    {
+        add_plant(i,1,VERTICAL,25);
+    }
+    for(int i = 41; i < 45; i ++)
+    {
+        add_plant(i,1,VERTICAL,25);
+    }
+    for(int i = 19; i < 26; i++)
     {
-        add_plant(i % map_width(), i / map_width());
+       add_plant(i,21,VERTICAL,5); 
+    }
+    for(int i = 35; i < 45; i++)
+    {
+        add_plant(i,21,VERTICAL,5);
     }
+    add_wall(20,1,VERTICAL,20);
+    add_wall(40,1,VERTICAL,20);
+    add_wall(20,20,HORIZONTAL,5);
+    add_wall(35,20,HORIZONTAL,5);
+    add_door(30,1);
+    add_NPC(48,1);
+    
     pc.printf("plants\r\n");
         
     pc.printf("Adding walls!\r\n");
@@ -174,7 +351,15 @@
 {
     // First things first: initialize hardware
     ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!");
-
+    
+    int startScreen = 1;
+    //Start screen
+    while(startScreen)
+    {
+        draw_startScreen();
+        startScreen = !check_Button(read_inputs());
+    }
+    
     // Initialize the maps
     maps_init();
     init_main_map();
@@ -182,26 +367,51 @@
     // Initialize game state
     set_active_map(0);
     Player.x = Player.y = 5;
-
+    Player.health = 5;
+    Player.omni = 0;
+    Player.apples = 0;
+    Player.end = 1;
     // Initial drawing
     draw_game(true);
-
+    
     // Main game loop
-    while(1)
+    while(Player.end)
     {
         // Timer to measure game update speed
         Timer t; t.start();
-        
+        draw_game(false);
+        update_game(get_action(read_inputs()));
+        draw_game(false);
         // Actuall do the game update:
         // 1. Read inputs        
         // 2. Determine action (get_action)        
         // 3. Update game (update_game)
         // 3b. Check for game over
         // 4. Draw frame (draw_game)
-        
         // 5. Frame delay
+        uLCD.locate(1,15);
+        uLCD.printf("Health %d",Player.health);
+        uLCD.locate(1,0);
+        if(Player.x < 10)
+            uLCD.printf("X 0%d",Player.x);    
+        else
+            uLCD.printf("X %d",Player.x);
+        uLCD.locate(7,0);
+        if (Player.y < 10)
+            uLCD.printf("Y 0%d",Player.y);
+        else
+            uLCD.printf("Y %d",Player.y);
+        uLCD.locate(9,15);
+        uLCD.printf("Apples: %d",Player.apples);
+        check_stuff();
+        check_Button(read_inputs());
+        if(Player.health <=0)
+        {
+            Player.end = 0;    
+        }
         t.stop();
         int dt = t.read_ms();
         if (dt < 100) wait_ms(100 - dt);
     }
+    draw_gameend();
 }
--- a/map.cpp	Wed Apr 04 21:11:07 2018 +0000
+++ b/map.cpp	Sun Apr 22 02:27:42 2018 +0000
@@ -26,6 +26,7 @@
  * This function should uniquely map (x,y) onto the space of unsigned integers.
  */
 static unsigned XY_KEY(int X, int Y) {
+    return (X * map_width())+ Y;
     // TODO: Fix me!
 }
 
@@ -36,11 +37,16 @@
  */
 unsigned map_hash(unsigned key)
 {
+    return key % 50;
     // TODO: Fix me!
 }
 
 void maps_init()
 {
+    HashTable* hashpointer  = createHashTable(&map_hash,50);
+    map.items = hashpointer;
+    map.w = map_width();
+    map.h = map_height();
     // TODO: Implement!    
     // Initialize hash table
     // Set width & height
@@ -76,34 +82,42 @@
 
 int map_width()
 {
+    return 50;
 }
 
 int map_height()
 {
+    return 50;
 }
 
 int map_area()
 {
+    return map_width() * map_height();
 }
 
 MapItem* get_north(int x, int y)
 {
+    return ((MapItem*)getItem(map.items, XY_KEY(x,y+1)));
 }
 
 MapItem* get_south(int x, int y)
 {
+    return ((MapItem*)getItem(map.items, XY_KEY(x,y-1)));
 }
 
 MapItem* get_east(int x, int y)
 {
+    return ((MapItem*)getItem(map.items, XY_KEY(x+1,y)));
 }
 
 MapItem* get_west(int x, int y)
 {
+    return ((MapItem*)getItem(map.items, XY_KEY(x-1,y+1)));
 }
 
 MapItem* get_here(int x, int y)
 {
+    return ((MapItem*)getItem(map.items, XY_KEY(x,y)));
 }
 
 
@@ -126,13 +140,77 @@
     }
 }
 
-void add_plant(int x, int y)
+void add_plant(int x, int y, int dir, int len)
+{
+    for(int i = 0; i < len; i++)
+    {
+        MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
+        w1->type = PLANT;
+        w1->draw = draw_plant;
+        w1->walkable = true;
+        w1->data = NULL;
+        unsigned key = (dir == HORIZONTAL) ? XY_KEY(x+i, y) : XY_KEY(x, y+i);
+        void* val = insertItem(get_active_map()->items, key, w1);
+        if (val) free(val); // If something is already there, free it
+    }
+}
+
+void add_NPC(int x, int y)
 {
     MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
-    w1->type = PLANT;
-    w1->draw = draw_plant;
+    w1->type = NPC;
+    w1->draw = draw_NPC;
+    w1->walkable = false;
+    w1->data = NULL;
+    void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1);
+    if (val) free(val); // If something is already there, free it
+}
+
+void add_apple(int x, int y)
+{
+    MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
+    w1->type = APPLE;
+    w1->draw = draw_apple;
     w1->walkable = true;
     w1->data = NULL;
     void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1);
     if (val) free(val); // If something is already there, free it
+}
+
+void add_poiapple(int x, int y)
+{
+    MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
+    w1->type = POIAPPLE;
+    w1->draw = draw_poiapple;
+    w1->walkable = true;
+    w1->data = NULL;
+    void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1);
+    if (val) free(val); // If something is already there, free it
+}
+void add_door(int x, int y)
+{
+    MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
+    w1->type = DOOR;
+    w1->draw = draw_door;
+    w1->walkable = false;
+    w1->data = NULL;
+    void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1);
+    if (val) free(val); // If something is already there, free it
+}
+void add_key(int x, int y)
+{
+    MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
+    w1->type = KEY;
+    w1->draw = draw_key;
+    w1->walkable = true;
+    w1->data = NULL;
+    void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1);
+    if (val) free(val); // If something is already there, free it
+}
+void deleteHere(int x, int y)
+{
+    MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
+    w1->draw = draw_nothing;
+    void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1);
+    if (val) free(val); // If something is already there, free it
 }
\ No newline at end of file
--- a/map.h	Wed Apr 04 21:11:07 2018 +0000
+++ b/map.h	Sun Apr 22 02:27:42 2018 +0000
@@ -55,6 +55,11 @@
 // Define more of these!
 #define WALL    0
 #define PLANT   1
+#define NPC     2
+#define APPLE   3
+#define POIAPPLE 4
+#define DOOR 5
+#define KEY 6
 
 /**
  * Initializes the internal structures for all maps. This does not populate
@@ -149,6 +154,17 @@
  * Add a PLANT item at (x,y). If there is already a MapItem at (x,y), erase it
  * before adding the plant.
  */
-void add_plant(int x, int y);
+void add_plant(int x, int y, int dir, int len);
+
+void add_NPC(int x, int y);
+
+void add_apple(int x, int y);
 
+void add_poiapple(int x, int y);
+
+void add_door(int x, int y);
+
+void add_key(int x, int y);
+
+void deleteHere(int x, int y);
 #endif //MAP_H
\ No newline at end of file
--- a/speech.cpp	Wed Apr 04 21:11:07 2018 +0000
+++ b/speech.cpp	Sun Apr 22 02:27:42 2018 +0000
@@ -2,7 +2,7 @@
 
 #include "globals.h"
 #include "hardware.h"
-
+int buttonPressed5 = 0;
 /**
  * Draw the speech bubble background.
  */
@@ -29,26 +29,64 @@
 
 void draw_speech_bubble()
 {
+    uLCD.filled_rectangle(0,100,127,127, WHITE);
 }
 
 void erase_speech_bubble()
 {
+    uLCD.filled_rectangle(0,100,127,127, BLACK);
+    uLCD.filled_rectangle(0,     9, 127,  14, WHITE); // Top
+    uLCD.filled_rectangle(0,    13,   2, 114, WHITE); // Left
+    uLCD.filled_rectangle(0,   114, 127, 117, WHITE); // Bottom
+    uLCD.filled_rectangle(124,  14, 127, 117, WHITE); // Right
+    uLCD.line(0, 9, 127, 9, GREEN);
 }
 
 void draw_speech_line(const char* line, int which)
 {
+    if(which == TOP)
+    {
+        uLCD.locate(1,13);
+        uLCD.printf(line);
+    }
+    else if(which == BOTTOM)
+    {
+        uLCD.locate(1,14);
+        uLCD.printf(line);
+    }
 }
 
-void speech_bubble_wait()
+int speech_bubble_wait(GameInputs inputs)
 {
+    if(inputs.b2 == 0 && buttonPressed5 == 0)
+    {
+        buttonPressed5 = 1;
+        return 0;
+    }
+    else if(inputs.b2 == 1 && buttonPressed5 == 1)
+    {
+        buttonPressed5 = 0;
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }    
 }
 
 void speech(const char* line1, const char* line2)
 {
+    int waiting = 1;
     draw_speech_bubble();
     draw_speech_line(line1, TOP);
     draw_speech_line(line2, BOTTOM);
-    speech_bubble_wait();
+    while(waiting == 1)
+    {
+        if(speech_bubble_wait(read_inputs()))
+        {
+            waiting = 0;
+        }
+    }
     erase_speech_bubble();
 }