Labyrinth of the Minotaur A simple roguelike/RPG using a nokia 5110 screen

Dependencies:   N5110 PowerControl mbed

Game.cpp

Committer:
ThomasBGill
Date:
2015-05-11
Revision:
37:a0ea57af9279
Parent:
35:2c290fa78f1d

File content as of revision 37:a0ea57af9279:

#include "Game.h"

int main()
{
    calibrateJoystick();  // get centred values of joystick
    pollJoystick.attach(&updateJoystick,1.0/10.0);  // read joystick 10 times per second

    //Power Saving
    PHY_PowerDown();
    int result = semihost_powerdown();

    //Initilize switches
    Start.mode(PullDown);
    Act.mode(PullDown);
    Start.fall(&StartPressed);
    Act.fall(&ActPressed);

    //Generate random seed
    srand(Noise * 1000000);

    //Initilize screen
    lcd.init();

    //Display game title screen
    Intro();

    //Start game
    MainMenu();
}

//Power Saving
int semihost_powerdown()
{
    uint32_t arg;
    return __semihost(USR_POWERDOWN, &arg);
}

//ISR
void ActPressed()
{
    ActFlag = 1;
}
void StartPressed()
{
    StartFlag = 1;
}

//Joystick functions
// read default positions of the joystick to calibrate later readings
void calibrateJoystick()
{
    //button.mode(PullDown);
    // must not move during calibration
    joystick.x0 = xPot;  // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly)
    joystick.y0 = yPot;
}
void updateJoystick()
{
    // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred)
    joystick.x = xPot - joystick.x0;
    joystick.y = yPot - joystick.y0;
    // read button state

    // calculate direction depending on x,y values
    // tolerance allows a little lee-way in case joystick not exactly in the stated direction
    if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = Centre;
    } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = Down;
    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = Up;
    } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = Right;
    } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = Left;
    } else {
        joystick.direction = Unknown;
    }
}


//High score system
void writeDataToFile()
{
    FILE *fp = fopen("/local/highscore.txt", "w"); // open 'highscore.txt' for writing
    fprintf(fp,"%d\r\n",HScore1); // print score to file
    fprintf(fp,"%d\r\n",HScore2); // print score to file
    fprintf(fp,"%d\r\n",HScore3); // print score to file
    fprintf(fp,"%d\r\n",HScore4); // print score to file
    fclose(fp); // close file
}

void readDataFromFile()
{
    FILE *fp = fopen("/local/highscore.txt", "r"); // open 'highscore.txt' for writing
    fscanf(fp,"%d", &HScore1); // read score from file and save to int
    fscanf(fp,"%d", &HScore2); // read score from file and save to int
    fscanf(fp,"%d", &HScore3); // read score from file and save to int
    fscanf(fp,"%d", &HScore4); // read score from file and save to int
    fclose(fp); // close file
}

void HighScoreCheck()
{
    readDataFromFile();

    if(score >= HScore1) {
        HScore4 = HScore3;
        HScore3 = HScore2;
        HScore2 = HScore1;
        HScore1 = score;
    } else if(score >= HScore2) {
        HScore4 = HScore3;
        HScore3 = HScore2;
        HScore2 = score;
    } else if(score >= HScore3) {
        HScore4 = HScore3;
        HScore3 = score;
    } else if(score > HScore4) {
        HScore4 = score;
    }

    writeDataToFile();
}

//Graphic functions
void DrawGraphic(int p, int y, int x)
{

    for(int i = 0; i < 38; i++) {
        for(int j = 0; j < 38; j++) {

            if(p == 0 ) {
                if(HugeRat[i][j] == 1) {
                    lcd.setPixel(y+i, x+j);
                }
            } else if(p == 1 ) {
                if(Goblin[i][j] == 1) {
                    lcd.setPixel(y+i, x+j);
                }
            } else if(p == 2 ) {
                if(Skeleton[i][j] == 1) {
                    lcd.setPixel(y+i, x+j);
                }
            } else if(p == 3 ) {
                if(Wraith[i][j] == 1) {
                    lcd.setPixel(y+i, x+j);
                }
                if(rand()%4 == 1) {
                    lcd.setPixel(y+i, x+j);
                }
            } else if(p == 4 ) {
                if(Ogre[i][j] == 1) {
                    lcd.setPixel(y+i, x+j);
                }
            } else if(p == 5 ) {
                if(Minotaur[i][j] == 1) {
                    lcd.setPixel(y+i, x+j);
                }
            }
        }
    }
}

void FlashScreen(int n)
{
    for (int i = 0; i<n; i++) {
        lcd.inverseMode();
        lcd.refresh();
        wait(0.2);
        lcd.normalMode();
        lcd.refresh();
        wait(0.2);
    }
}

//Game functions

void Intro()
{

    lcd.clear();
    lcd.printString("Labyrinth", 15, 1);
    lcd.printString("of the", 24, 2);
    lcd.printString("Minotaur", 18, 3);
    lcd.refresh();
    wait(1.0);
}

void Initilize()
{

    score = -100;

    level = 0;

    //Player Health
    ph = PH_MAX;

    //Player weapon
    pw = 0; //0 to 4

    //Player armour
    pa = 5; //5 to 9

}

void MainMenu()
{
    Initilize();

    int menu = 0;

    while (1) {

        ActFlag = 0;

        lcd.clear();
        if (menu == 0) {
            lcd.printString("New Game <", 6, 1);
            lcd.printString("High Scores", 6, 2);
            lcd.printString("Options", 6, 3);
            lcd.refresh();
        } else if (menu == 1) {
            lcd.printString("New Game", 6, 1);
            lcd.printString("High Scores <", 6, 2);
            lcd.printString("Options", 6, 3);
            lcd.refresh();
        } else {
            lcd.printString("New Game", 6, 1);
            lcd.printString("High Scores", 6, 2);
            lcd.printString("Options <", 6, 3);
            lcd.refresh();
        }

        Sleep();

        if (joystick.direction == Up) {
            if(menu > 0) {
                menu--;
            }
        }
        if(joystick.direction == Down) {
            if(menu < 3) {
                menu++;
            }
        }
        if (ActFlag) {

            ActFlag = 0;

            if (menu == 0) {
                GameLoop();
            } else if (menu == 1) {
                HighScoreScreen();
            } else {
                Options();
            }
        }
    }
}

void Options()
{

    bool bright = 1;

    lcd.clear();
    while(1) {
        if(bright == 1) {
            lcd.printString("Backlight ON", 6, 2);
        } else {
            lcd.printString("Backlight OFF", 6, 2);
        }

        lcd.refresh();

        if (joystick.direction != Centre) {

            bright = !bright;
            lcd.setBrightness(bright);
            lcd.clear();
        }
        if (ActFlag) {
            ActFlag = 0;

            bright = !bright;
            lcd.setBrightness(bright);
            lcd.clear();
        }
        if(StartFlag) {

            StartFlag = 0;

            MainMenu();

        }
    }
}

void LevelScreen()
{
    char buffer[14];

    int write = sprintf(buffer, "Level %d", level); // print formatted data to buffer

    lcd.clear();
    lcd.printString(buffer, 20, 2);
    lcd.refresh();
    wait(1.0);
}

void NextLevel()
{

    level++;

    score = score + 100;

    World();

    LevelScreen();

    //RevealMap(); //Uncomment for debugging to view map

    srand(Noise * 1000000);

}

void GameLoop()
{
    while (1) {

        NextLevel();

        PlayerCamera();

        while (1) {

            ActFlag = 0;
            StartFlag = 0;

            if (map[px][py] == CHEST) { //If player's current tile is a chest, call the chest function
                Chest();
            }

            if (px == exx && py == exy) { //If plyer's current tile is the exit

                if(level%5 == 0) { //If the current level number is a multiple of 5 start a boss fight
                    BossFight = true;
                    Fight();
                }

                break;

            }

            Sleep();


            if (joystick.direction != Centre) {

                PlayerMove();

                if (rand() % 40 == 0) { //Random chance to heal player as they move
                    if (ph < PH_MAX) {
                        ph++;
                    }

                }

                if (rand() % 50 == 0) { //Random chance for fight to start when player moves
                    Fight();
                }

                PlayerCamera();

            }
            if (StartFlag) {

                StartFlag = 0;

                StartMenu();

                PlayerCamera();
            }
            if (ActFlag) {

                ActFlag = 0;
            }
        }
    }
}

void PlayerCamera()
{
    lcd.clear();

    int tile;

    for (int i = 0; i < 14; i++) {
        for (int j = 0; j < 6; j++) {

            if (i == 6 && j == 2) {
                lcd.printString("@", (6 * i) + 1, j); //Make player's location a '@' symbol
            } else {
                int diffx = i - 6;
                int diffy = j - 2;

                if (px + diffx < 84 && px + diffx > 0 && py + diffy < 48 && py + diffy > 0) {
                    tile = map[px + diffx][py + diffy];
                } else {
                    tile = WALL;
                }
                lcd.printChar(TileList[tile].Symbol, (6 * i) + 1, j);

                if (map[px + diffx][py + diffy] == FLOOR) {
                    map[px + diffx][py + diffy] = FLOOR_SEEN; //Set the floor that has been in view of the player camera to seen to be displayed on the map
                }

            }
        }
    }
    lcd.refresh();
}

void PlayerMove()
{
    //If direction analogue stick is moved is passable then update the player position

    if (joystick.direction == Up) {
        int tile = map[px][py - 1];
        if (TileList[tile].Passable) {
            py--;
        }
    }
    if (joystick.direction == Down) {
        int tile = map[px][py + 1];
        if (TileList[tile].Passable) {
            py++;
        }
    }
    if (joystick.direction == Right) {
        int tile = map[px + 1][py];
        if (TileList[tile].Passable) {
            px++;
        }
    }
    if (joystick.direction == Left) {
        int tile = map[px - 1][py];
        if (TileList[tile].Passable) {
            px--;
        }
    }
}

void Fight()
{
    int m;

    lcd.clear();

    if(BossFight) {
        BossFight = false; //Reset BossFight to false

        m = 5; //Monster is a minotaur

        lcd.printString("BOSS!", 30, 2);
    } else { //If not a boss fight randomly choose a monster to fight

        //Lvl 1- Huge Rat + Goblin, Lvl 2 +Skeleton, Lvl 3 +Wraith, Lvl 4 +Ogre
        int mr = level + 1;

        if (mr > 5) {
            mr = 5;
        }

        lcd.printString("FIGHT!", 24, 2);

        m = rand() % mr;
    }

    mh = EnemyList[m].EHealth;

    FlashScreen(5);

    char buffer1[14];
    int write = sprintf(buffer1, "%d/%d", mh, EnemyList[m].EHealth); // print formatted data to buffer

    lcd.clear();
    lcd.printString(EnemyList[m].EName, 0, 0); 
    lcd.printString(buffer1, 54, 0); //Current enemy health/max enemy health
    DrawGraphic(m, 23, 7); //Image of monster
    lcd.refresh();
    wait(2.0);

    bool menu = 1;

    while (1) {
        ActFlag = 0;
        StartFlag = 0;

        lcd.clear();

        lcd.printString(EnemyList[m].EName, 0, 0);
        write = sprintf(buffer1, "%d/%d", mh, EnemyList[m].EHealth); // print formatted data to buffer
        lcd.printString(buffer1, 54, 0); //Current enemy health/max enemy health

        lcd.printString("You", 0, 2);
        char buffer2[14];
        int phm = PH_MAX;
        write = sprintf(buffer2, "%d/%d", ph, phm); // print formatted data to buffer
        lcd.printString(buffer2, 54, 2); //Current player health/max player health

        if (menu) {
            lcd.printString("Fight <", 0, 4);
            lcd.printString("Run", 0, 5);
        } else {
            lcd.printString("Fight", 0, 4);
            lcd.printString("Run <", 0, 5);
        }
        lcd.refresh();
        Sleep();

        if (joystick.direction != Centre) {
            menu = !menu;
        }
        if (ActFlag) {
            ActFlag = 0;
            if (menu) { //Fight

                PlayerAttack(m);

                if (mh <= 0) { //Check if monster is dead
                    score = score + EnemyList[m].EPoints;
                    lcd.clear();
                    lcd.printString("You win!", 18, 2);
                    lcd.refresh();
                    wait(1.0);
                    Sleep();
                    break;
                }

                MonsterAttack(m);


            } else { //Run away

                score = score - 2;

                int b = rand() % 5;

                if (b == 0) { //Monster blocks the path

                    lcd.clear();
                    lcd.printString("You try to run", 0, 0);
                    lcd.printString("away but the", 0, 1);
                    lcd.printString("monster blocks", 0, 2);
                    lcd.printString("the path", 0, 3);
                    lcd.refresh();
                    wait(1.0);
                    Sleep();

                    MonsterAttack(m);

                } else { //Monster doesn't block the path

                    int s = rand() % 100 + 1;

                    if (s > EnemyList[m].ESpd) { //If you outspeed monster

                        lcd.clear();
                        lcd.printString("You run away", 6, 2);
                        lcd.refresh();
                        wait(1.0);
                        Sleep();
                        break;

                    } else { //You don't outspeed the monster and it attacks you

                        lcd.clear();
                        lcd.printString("You try to run", 0, 0);
                        lcd.printString("away but the", 0, 1);
                        lcd.printString("monster", 0, 2);
                        lcd.printString("catches up to", 0, 3);
                        lcd.printString("you", 0, 4);
                        lcd.refresh();
                        wait(1.0);
                        Sleep();

                        MonsterAttack(m);

                    }


                }
            }
        }
    }
}

void PlayerAttack(int m)
{

    //Hit monster
    if (rand() % 100 + 1 > EnemyList[m].EDodge) { //If monster doesn't dodge

        int damage = ItemList[pw].ItemValue - EnemyList[m].EArmour + rand() % 3 - rand() % 3; //Calculate damage
        if (damage < 0) {
            damage = 0;
        }
        mh = mh - damage; //Apply damage and calculate the monster's health

        char damBuffer[14];
        int write = sprintf(damBuffer,"-%d", damage);

        //Flash image of monster on the screen with the amount of damage it recieved
        lcd.clear();
        DrawGraphic(m, 23, 7);
        lcd.printString(damBuffer, 62, 2);
        FlashScreen(3);


        char buffer3[14];
        write = sprintf(buffer3, "for %d damage", damage); // print formatted data to buffer

        lcd.clear();
        lcd.printString("You hit the", 0, 1);
        lcd.printString(EnemyList[m].EName, 0, 2);
        lcd.printString(buffer3, 0, 3);
        lcd.refresh();
        wait(1.0);
        Sleep();

    } else { //Monster dodges
        lcd.clear();
        lcd.printString(EnemyList[m].EName, 0, 1);
        lcd.printString("dodges your", 0, 2);
        lcd.printString("attack", 0, 3);
        lcd.refresh();
        wait(1.0);
        Sleep();
    }
}

void MonsterAttack(int m)
{
    if (rand() % 100 + 1 < EnemyList[m].EHit) { //If monster hits and isn't dead

        int damage = EnemyList[m].EDamage - ItemList[pa].ItemValue + rand() % 3 - rand() % 3; //Calculate damage
        if (damage < 0) {
            damage = 0;
        }
        ph = ph - damage; //Apply damage and calculate the monster's health

        char buffer[14];
        int write = sprintf(buffer, "%d damage", damage); // print formatted data to buffer

        lcd.clear();
        lcd.printString(EnemyList[m].EName, 0, 1);
        lcd.printString("hits you for", 0, 2);
        lcd.printString(buffer, 0, 3);
        lcd.refresh();
        wait(1.0);
        Sleep();

    } else { //You dodge
        lcd.clear();
        lcd.printString("You dodge the", 0, 1);
        lcd.printString("monster's", 0, 2);
        lcd.printString("attack", 0, 3);
        lcd.refresh();
        wait(1.0);
        Sleep();
    }
    if (ph <= 0) { //Check if player is dead
        GameOver();
    }

}

void StartMenu()
{
    int menu = 0;

    char buffer[14];
    int phm = PH_MAX;
    int write = sprintf(buffer, "Health  %d/%d", ph, phm); // print formatted data to buffer


    while (1) {
        if (menu == 0) {
            lcd.clear();
            lcd.printString(buffer, 0, 0); //Player current/max health
            lcd.printString("Map <", 0, 2);
            lcd.printString("Map Legend", 0, 3);
            lcd.printString("Inventory", 0, 4);
            lcd.printString("Continue", 0, 5);
            lcd.refresh();
            Sleep();
        } else if (menu == 1) {
            lcd.clear();
            lcd.printString(buffer, 0, 0); //Player current/max health
            lcd.printString("Map", 0, 2); 
            lcd.printString("Map Legend <", 0, 3);
            lcd.printString("Inventory", 0, 4);
            lcd.printString("Continue", 0, 5);
            lcd.refresh();
            Sleep();
        } else if (menu == 2) {
            lcd.clear();
            lcd.printString(buffer, 0, 0); //Player current/max health
            lcd.printString("Map", 0, 2);
            lcd.printString("Map Legend", 0, 3);
            lcd.printString("Inventory <", 0, 4);
            lcd.printString("Continue", 0, 5);
            lcd.refresh();
            Sleep();
        } else if (menu == 3) {
            lcd.clear();
            lcd.printString(buffer, 0, 0); //Player current/max health
            lcd.printString("Map", 0, 2);
            lcd.printString("Map Legend", 0, 3);
            lcd.printString("Inventory", 0, 4);
            lcd.printString("Continue <", 0, 5);
            lcd.refresh();
            Sleep();
        }

        if (joystick.direction != Centre) {

            if ((joystick.direction == Down || joystick.direction == Right) && menu < 3) {
                menu++;
            } else if ((joystick.direction == Up || joystick.direction == Left) && menu > 0)
                menu--;
        }
        if (ActFlag) {
            ActFlag = 0;
            if (menu == 0) {
                Map();
            } else if (menu == 1) {
                MapLegend();
            } else if (menu == 2) {
                Inventory();
            } else {
                break;
            }
        }
        if (StartFlag) {
            StartFlag = 0;
        }
    }
}

void Map()
{
    lcd.clear();
    DrawMap();
    while (!StartFlag) {
        FlashPlayerLocation();
    }
    StartFlag = 0;
    ActFlag = 0;
}

void DrawMap()
{
    //Draw map on screen
    for (int i = 0; i<84; i++) {
        for (int j = 0; j<48; j++) {
            if (map[i][j] == FLOOR_SEEN || map[i][j] == CHEST_OPENED) {
                lcd.clearPixel(i, j);
            } else {
                lcd.setPixel(i, j);
            }
        }
    }
    lcd.refresh();
}

void FlashPlayerLocation()
{
    lcd.setPixel(px, py);
    lcd.refresh();
    wait(0.5);
    lcd.clearPixel(px, py);
    lcd.refresh();
    wait(0.5);
}

void MapLegend()
{
    lcd.clear();
    lcd.printString("@ Player", 0, 0);
    lcd.printString("# Wall", 0, 1);
    lcd.printString(". Floor", 0, 2);
    lcd.printString("= Chest", 0, 3);
    lcd.printString("/ Open Chest", 0, 4);


    while (1) {
        Sleep();

        if (ActFlag) {
            ActFlag = 0;
        }
        if (StartFlag) {
            StartFlag = 0;
            break;
        }
    }
}

void Inventory()
{
    lcd.clear();
    lcd.printString("Armour:", 0, 0);
    lcd.printString(ItemList[pa].ItemName, 0, 1); //Current armour
    char buffer1[14];
    int write = sprintf(buffer1, "+%d Armour", ItemList[pa].ItemValue); // print formatted data to buffer
    lcd.printString(buffer1, 0, 2); //Current armour value

    lcd.printString("Weapon:", 0, 3);
    lcd.printString(ItemList[pw].ItemName, 0, 4); //Current weapon
    char buffer2[14];
    write = sprintf(buffer2, "+%d Damage", ItemList[pw].ItemValue); // print formatted data to buffer
    lcd.printString(buffer2, 0, 5); //Current weapon value
    lcd.refresh();

    while (1) {
        Sleep();

        if (ActFlag) {
            ActFlag = 0;
        }
        if (StartFlag) {
            StartFlag = 0;
            break;
        }
    }
}

void Chest()
{
    score = score + 10;

    //Generate what is in the chest
    int c = rand() % 4; //0- Item, 1- Booby trap, 2- Map, Else- Potion

    if (c == 0) {
        getItem();
    } else if (c == 1) {
        BoobyTrap();
    } else if (c == 2) {
        RevealMap();
    } else {
        Potion();
    }

    map[px][py] = CHEST_OPENED; //Change the current tile to CHEST_OPENED

}

void getItem()
{
    //Generate item from ItemList
    int r = rand() % 10;

    lcd.clear();
    lcd.printString("Do you want to", 0, 1);
    lcd.printString("take the", 0, 2);
    lcd.printString(ItemList[r].ItemName, 0, 3);
    lcd.printString("-Yes (Action)", 0, 4);
    lcd.printString("-No (Start)", 0, 5);
    lcd.refresh();
    wait(1.0);

    while(1) {
        Sleep();

        if (ActFlag) { //Take item

            ActFlag = 0;

            if (r > 5) {
                pa = r;
            } else {
                pw = r;
            }

            lcd.clear();
            lcd.printString("You take the", 0, 1);
            lcd.printString(ItemList[r].ItemName, 0, 2);
            lcd.refresh();
            wait(1.0);
            Sleep();

        }
        if(StartFlag) { //Leave item

            StartFlag = 0;

            lcd.clear();
            lcd.printString("You leave the", 0, 1);
            lcd.printString(ItemList[r].ItemName, 0, 2);
            lcd.refresh();
            wait(1.0);
            Sleep();
        }
    }
}

void BoobyTrap()
{
    //Generate damage
    int damage = rand() % 5;

    if (damage != 0) {

        ph = ph - damage;

        char buffer[15];
        int write = sprintf(buffer, "You recive %d", damage);

        lcd.clear();
        lcd.printString("The chest is", 0, 0);
        lcd.printString("booby trapped!", 0, 1);
        lcd.printString(buffer, 0, 3);
        lcd.printString("damage", 0, 4);
        lcd.refresh();
        wait(1.0);
        Sleep();

        //Check if player is dead
        if (ph < 0) {
            GameOver();
        }
    } else {

        lcd.clear();
        lcd.printString("The chest is", 0, 0);
        lcd.printString("booby trapped", 0, 1);
        lcd.printString("but the trap", 0, 2);
        lcd.printString("fails", 0, 3);
        lcd.refresh();
        wait(1.0);
        Sleep();

    }
}

void RevealMap()
{
    //Iterates through each cell in the array, changing any unseen floor tiles to seen ones
    for (int i = 0; i < 84; i++) {
        for (int j = 0; j < 48; j++) {

            if (map[i][j] == FLOOR) {
                map[i][j] = FLOOR_SEEN;
            }
        }
    }

    lcd.clear();
    lcd.printString("You find a map", 0, 0);
    lcd.printString("of the current", 0, 1);
    lcd.printString("level inside", 0, 2);
    lcd.printString("the chest", 0, 3);
    lcd.refresh();
    wait(1.0);
    Sleep();
}

void Potion()
{
    //Generates what the potion is
    int p = rand() % 5; //0- Poison, 1- Teleport, Else- Full heal

    lcd.clear();
    lcd.printString("You find a", 0, 0);
    lcd.printString("potion inside", 0, 1);
    lcd.printString("the chest", 0, 2);
    lcd.printString("Drink (Action)", 0, 4);
    lcd.printString("Leave (Start)", 0, 5);
    lcd.refresh();
    wait(1.0);
    Sleep();

    if (ActFlag) { //Potion drunk
        ActFlag = 0;

        if (p == 0) { //Poison

            int damage = rand() % 4 + 1;

            ph = ph - damage;

            char buffer[15];
            int write = sprintf(buffer, "%d damage", damage);

            lcd.clear();
            lcd.printString("You drink the", 0, 0);
            lcd.printString("potion and", 0, 1);
            lcd.printString("suddenly feel", 0, 2);
            lcd.printString("ill.", 0, 3);
            lcd.printString("You take", 0, 4);
            lcd.printString(buffer, 0, 5);
            lcd.refresh();
            wait(1.0);
            Sleep();

            //Check if player is dead
            if (ph < 0) {
                GameOver();
            }
        } else if (p == 1) { //Teleport

            lcd.clear();
            lcd.printString("You drink the", 0, 0);
            lcd.printString("potion and", 0, 1);
            lcd.printString("suddenly feel", 0, 2);
            lcd.printString("your body", 0, 3);
            lcd.printString("being", 0, 4);
            lcd.printString("transported", 0, 5);
            lcd.refresh();
            wait(1.0);
            Sleep();

            GameLoop();

        } else { //Full heal

            ph = PH_MAX;

            lcd.clear();
            lcd.printString("You drink the", 0, 0);
            lcd.printString("potion and", 0, 1);
            lcd.printString("suddenly feel", 0, 2);
            lcd.printString("all your", 0, 3);
            lcd.printString("wounds heal", 0, 4);
            lcd.refresh();
            wait(1.0);
            Sleep();
        }
    }
    if(StartFlag) { //Leave the potion
        StartFlag = 0;
        lcd.clear();
        lcd.printString("You walk away", 0, 0);
        lcd.printString("and leave the", 0, 1);
        lcd.printString("potion", 0, 2);
        lcd.refresh();
        wait(1.0);
        Sleep();
    }
}

void GameOver()
{
    lcd.inverseMode();
    lcd.clear();
    lcd.printString("GAME OVER", 12, 2);
    lcd.refresh();
    wait(1.0);
    Sleep();
    lcd.normalMode();
    ScoreScreen();
}

void ScoreScreen()
{
    char buffer[14];

    int write = sprintf(buffer, "%d points", score);

    lcd.clear();
    lcd.printString("You scored", 6, 1);
    lcd.printString(buffer, 6, 2); //Player's final score
    lcd.refresh();
    wait(1.0);
    Sleep();

    HighScoreScreen();
}

void HighScoreScreen()
{
    HighScoreCheck();

    char buffer1[14];
    int write = sprintf(buffer1, "1. %d", HScore1);

    char buffer2[14];
    write = sprintf(buffer2, "2. %d", HScore2);

    char buffer3[14];
    write = sprintf(buffer3, "3. %d", HScore3);

    char buffer4[14];
    write = sprintf(buffer4, "4. %d", HScore4);

    lcd.clear();
    lcd.printString("High Scores", 6, 0);
    lcd.printString(buffer1, 6, 2); //High score 1
    lcd.printString(buffer2, 6, 3); //High score 2
    lcd.printString(buffer3, 6, 4); //High score 3
    lcd.printString(buffer4, 6, 5); //High score 4
    lcd.refresh();
    wait(1.0);

    while(1) {
        Sleep();

        if(StartFlag) {
            StartFlag = 0;
            MainMenu();
        }
        if(ActFlag) {
            ActFlag = 0;
        }
    }
}