If you have comments or questions concerning this source file, discuss them in the forum.
/*
Copyright (c) 2002 Nicolai Haehnle

See the license.txt for details. If that file was not included in the
source distributions, please email <prefect@rtts.org>
*/
// ge_main.c

#include "game.h"

#include "rttspanels.h"

class StatsScreen : public GLabel {
public:
    StatsScreen(EEngine *eng, ELevel *level);

    virtual bool Key(int code, char c, bool down);
    virtual bool MouseButton(int btn, int x, int y, bool down);
};

StatsScreen::StatsScreen(EEngine *eng, ELevel *level)
    : GLabel(0, "splash", pic_normal, 0, 0, 0, 640, 480)
{
    char buf[256];
    GLabel *pLabel;

    SetCanFocus(true);

    snprintf(buf, sizeof(buf), "Level %04i", eng->m_iLevel+1);
    pLabel = new GLabel(this, 320, 40, 0, 30, buf, halign_center);
    pLabel->AdjustSize();

    pLabel = new GLabel(this, 50, 100, 0, 25, "You played:");
    pLabel->SetColor(255, 255, 0);
    pLabel->AdjustSize();

    snprintf(buf, sizeof(buf), "%04i - %s", level->m_iBaseLevel+1, level->m_szName);
    pLabel = new GLabel(this, 590, 100, 0, 25, buf, halign_right);
    pLabel->AdjustSize();

    pLabel = new GLabel(this, 50, 125, 0, 25, "Made by:");
    pLabel->SetColor(255, 255, 0);
    pLabel->AdjustSize();

    pLabel = new GLabel(this, 590, 125, 0, 25, level->m_szAuthor, halign_right);
    pLabel->AdjustSize();

    pLabel = new GLabel(this, 50, 200, 0, 25, "Money earned:");
    pLabel->SetColor(255, 255, 0);
    pLabel->AdjustSize();

    snprintf(buf, sizeof(buf), "%i\x80 / %i\x80",
            eng->m_player.stats.money, eng->m_player.stats.moneymax);
    pLabel = new GLabel(this, 590, 200, 0, 25, buf, halign_right);
    pLabel->AdjustSize();

    pLabel = new GLabel(this, 50, 225, 0, 25, "Shields lost:");
    pLabel->SetColor(255, 255, 0);
    pLabel->AdjustSize();

    snprintf(buf, sizeof(buf), "%i", (int)eng->m_player.stats.shieldslost);
    pLabel = new GLabel(this, 590, 225, 0, 25, buf, halign_right);
    pLabel->AdjustSize();

    pLabel = new GLabel(this, 320, 420, 0, 25, "Press any key to continue", halign_center);
    pLabel->SetColor(255, 192, 0);
    pLabel->AdjustSize();
}

bool StatsScreen::Key(int code, char c, bool down)
{
    if (down)
        EndModal(0);
    return true;
}

bool StatsScreen::MouseButton(int btn, int x, int y, bool down)
{
    if (down)
        EndModal(0);
    return true;
}

/*
==============
G_LoadLevel

Load a matching level for the given difficulty
==============
*/
int G_LoadLevel(ELevel *level, int lvl)
{
    char **names;
    int count, match, i, tlvl;
    int num, tries;
    bool playable, picky;

    playable = false;
    count = L_FindFiles("levels", "*.lvl", &names);

    try {
        // count the number of matching levels
        picky = true;
        for(;;) {
            match = 0;
            for(i = 0; i < count; i++) {
                tlvl = atoi(names[i]);
                if (tlvl < 1 || tlvl > lvl+1)
                    continue;

                if (picky && ((tlvl-1) % 10) != (lvl % 10))
                    continue;

                match++;
            }

            if (match)
                break;

            if (!picky)
                throw LError("no levels found");
            picky = false;
        }

        // try to load one
        tries = match;
        while(tries--) {
            num = rand() % match;

            for(i = 0; i < count; i++) {
                tlvl = atoi(names[i]);
                if (tlvl < 1 || tlvl > lvl+1)
                    continue;

                if (picky && ((tlvl-1) % 10) != (lvl % 10))
                    continue;

                if (!num--)
                    break;
            }

            lassert(i < count);

            try {
                char buf[MAX_OSPATH];

                snprintf(buf, sizeof(buf), "levels/%s", names[i]);
                playable = level->Load(buf);
            } catch(LError &err) {
                L_Printf("Failed to load %s: %s\n", names[i], err.Get());
                playable = false;
            }

            if (playable) {
                L_FreeFindFiles(names);
                return (lvl - level->m_iBaseLevel) / 10;
            }
        }

        throw LError("Failed to load a matching level");
    } catch(...) {
        L_FreeFindFiles(names);
        throw;
    }
}

/*
==============
G_Run

Run one level of the game
==============
*/
int G_Run()
{
    EEngine eng;
    ETileTypes tts;
    ELevel level(&tts);
    int lvl, adjust;
    int code;

    eng.PokePlayer(&game.player, config->GetItem("controls"));

    lvl = game.player.level;

    adjust = G_LoadLevel(&level, lvl);

    eng.SetLevel(&level, false);
    eng.SetLevelAdjust(lvl, adjust);

    code = eng.Run();

    if (code == ENGINE_WIN) {
        StatsScreen scr(&eng, &level);
        scr.Run();

        eng.PeekPlayer(&game.player);
        game.player.level++;
        return GAME_HANGAR;
    } else if (code == ENGINE_LOOSE) {
        game.running = false;
        return GAME_LOOSE;
    } else {
        player_t plr;

        eng.PeekPlayer(&plr);

        if (plr.health < game.player.health)
            game.player.health = plr.health;
        return GAME_HANGAR;
    }
}