int snake_game::start_game()
{
    std::vector<std::pair<int, int> > vSnakeBody;
    std::map<int, std::map<int, bool> > mSnakeBody;

    int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    WINDOW *w_snake = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    print_header(w_snake);

    //Snake start position
    vSnakeBody.push_back(std::make_pair(FULL_SCREEN_HEIGHT / 2, FULL_SCREEN_WIDTH / 2));
    mSnakeBody[FULL_SCREEN_HEIGHT / 2][FULL_SCREEN_WIDTH / 2] = true;
    mvwputch(w_snake, vSnakeBody[vSnakeBody.size() - 1].first, vSnakeBody.back().second, c_white, '#');

    //Snake start direction
    int iDirY = 0;
    int iDirX = 1;

    //Snake start length
    size_t iSnakeBody = 10;

    //GameSpeed aka inputdelay/timeout
    int iGameSpeed = 100;

    //Score
    int iScore = 0;
    int iFruitPosY = 0;
    int iFruitPosX = 0;

    //Draw Score
    print_score(w_snake, iScore);

    long ch;
    InputEvent input;

    do {
        //Check if we hit a border
        if (vSnakeBody[vSnakeBody.size() - 1].first + iDirY == 0) {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first +
                                                iDirY + FULL_SCREEN_HEIGHT - 2,
                                                vSnakeBody[vSnakeBody.size() - 1].second + iDirX));

        } else if (vSnakeBody[vSnakeBody.size() - 1].first + iDirY == FULL_SCREEN_HEIGHT - 1) {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first +
                                                iDirY - FULL_SCREEN_HEIGHT + 2,
                                                vSnakeBody[vSnakeBody.size() - 1].second + iDirX));

        } else if (vSnakeBody[vSnakeBody.size() - 1].second + iDirX == 0) {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first + iDirY,
                                                vSnakeBody[vSnakeBody.size() - 1].second +
                                                iDirX + FULL_SCREEN_WIDTH - 2));

        } else if (vSnakeBody[vSnakeBody.size() - 1].second + iDirX == FULL_SCREEN_WIDTH - 1) {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first + iDirY,
                                                vSnakeBody[vSnakeBody.size() - 1].second +
                                                iDirX - FULL_SCREEN_WIDTH + 2));

        } else {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first + iDirY,
                                                vSnakeBody[vSnakeBody.size() - 1].second + iDirX));
        }

        //Check if we hit ourself
        if (mSnakeBody[vSnakeBody[vSnakeBody.size() - 1].first][vSnakeBody[vSnakeBody.size() - 1].second]) {
            //We are dead :(
            break;
        } else {
            //Add new position to map
            mSnakeBody[vSnakeBody[vSnakeBody.size() - 1].first][vSnakeBody[vSnakeBody.size() - 1].second] = true;
        }

        //Have we eaten the forbidden fruit?
        if (vSnakeBody[vSnakeBody.size() - 1].first == iFruitPosY &&
            vSnakeBody[vSnakeBody.size() - 1].second == iFruitPosX) {
            iScore += 500;
            iSnakeBody += 10;
            iGameSpeed -= 3;

            print_score(w_snake, iScore);

            iFruitPosY = 0;
            iFruitPosX = 0;
        }

        //Check if we are longer than our max size
        if (vSnakeBody.size() > iSnakeBody) {
            mSnakeBody[vSnakeBody[0].first][vSnakeBody[0].second] = false;
            mvwputch(w_snake, vSnakeBody[0].first, vSnakeBody[0].second, c_black, ' ');
            vSnakeBody.erase(vSnakeBody.begin(), vSnakeBody.begin() + 1);
        }

        //Draw Snake
        mvwputch(w_snake, vSnakeBody[vSnakeBody.size() - 1].first,
                 vSnakeBody[vSnakeBody.size() - 1].second, c_white, '#');
        mvwputch(w_snake, vSnakeBody[vSnakeBody.size() - 2].first,
                 vSnakeBody[vSnakeBody.size() - 2].second, c_ltgray, '#');

        //On full length add a fruit
        if (iFruitPosY == 0 && iFruitPosY == 0) {
            do {
                iFruitPosY = rng(1, FULL_SCREEN_HEIGHT - 2);
                iFruitPosX = rng(1, FULL_SCREEN_WIDTH - 2);
            } while (mSnakeBody[iFruitPosY][iFruitPosX]);

            mvwputch(w_snake, iFruitPosY, iFruitPosX, c_ltred, '*');
        }

        wrefresh(w_snake);

        //Check input
        timeout(iGameSpeed);
        ch = getch();
        input = get_input(ch);
        timeout(-1);

        switch (input) {
        case DirectionN: /* up */
            if (iDirY != 1) {
                iDirY = -1;
                iDirX = 0;
            }
            break;
        case DirectionS: /* down */
            if (iDirY != -1) {
                iDirY = 1;
                iDirX = 0;
            }
            break;
        case DirectionW: /* left */
            if (iDirX != 1) {
                iDirY = 0;
                iDirX = -1;
            }
            break;
        case DirectionE: /* right */
            if (iDirX != -1) {
                iDirY = 0;
                iDirX = 1;
            }
            break;
        case Cancel:
            return iScore;
            break;
        default:
            break;
        }

    } while (true);

    snake_over(w_snake, iScore);
    return iScore;
}
int snake_game::start_game()
{
    std::vector<std::pair<int, int> > vSnakeBody;
    std::map<int, std::map<int, bool> > mSnakeBody;

    int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    WINDOW *w_snake = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    print_header(w_snake);

    //Snake start position
    vSnakeBody.push_back(std::make_pair(FULL_SCREEN_HEIGHT / 2, FULL_SCREEN_WIDTH / 2));
    mSnakeBody[FULL_SCREEN_HEIGHT / 2][FULL_SCREEN_WIDTH / 2] = true;
    mvwputch(w_snake, vSnakeBody[vSnakeBody.size() - 1].first, vSnakeBody.back().second, c_white, '#');

    //Snake start direction
    int iDirY = 0;
    int iDirX = 1;

    //Snake start length
    size_t iSnakeBody = 10;

    //GameSpeed aka inputdelay/timeout
    int iGameSpeed = 100;

    //Score
    int iScore = 0;
    int iFruitPosY = 0;
    int iFruitPosX = 0;

    //Draw Score
    print_score(w_snake, iScore);

    input_context ctxt("SNAKE");
    ctxt.register_cardinal();
    ctxt.register_action("CONFIRM");
    ctxt.register_action("QUIT");
    ctxt.register_action("HELP_KEYBINDINGS");
    ctxt.register_action("ANY_INPUT");

    do {
        //Check if we hit a border
        if (vSnakeBody[vSnakeBody.size() - 1].first + iDirY == 0) {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first +
                                                iDirY + FULL_SCREEN_HEIGHT - 2,
                                                vSnakeBody[vSnakeBody.size() - 1].second + iDirX));

        } else if (vSnakeBody[vSnakeBody.size() - 1].first + iDirY == FULL_SCREEN_HEIGHT - 1) {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first +
                                                iDirY - FULL_SCREEN_HEIGHT + 2,
                                                vSnakeBody[vSnakeBody.size() - 1].second + iDirX));

        } else if (vSnakeBody[vSnakeBody.size() - 1].second + iDirX == 0) {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first + iDirY,
                                                vSnakeBody[vSnakeBody.size() - 1].second +
                                                iDirX + FULL_SCREEN_WIDTH - 2));

        } else if (vSnakeBody[vSnakeBody.size() - 1].second + iDirX == FULL_SCREEN_WIDTH - 1) {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first + iDirY,
                                                vSnakeBody[vSnakeBody.size() - 1].second +
                                                iDirX - FULL_SCREEN_WIDTH + 2));

        } else {
            vSnakeBody.push_back(std::make_pair(vSnakeBody[vSnakeBody.size() - 1].first + iDirY,
                                                vSnakeBody[vSnakeBody.size() - 1].second + iDirX));
        }

        //Check if we hit ourself
        if (mSnakeBody[vSnakeBody[vSnakeBody.size() - 1].first][vSnakeBody[vSnakeBody.size() - 1].second]) {
            //We are dead :(
            break;
        } else {
            //Add new position to map
            mSnakeBody[vSnakeBody[vSnakeBody.size() - 1].first][vSnakeBody[vSnakeBody.size() - 1].second] =
                true;
        }

        //Have we eaten the forbidden fruit?
        if (vSnakeBody[vSnakeBody.size() - 1].first == iFruitPosY &&
                vSnakeBody[vSnakeBody.size() - 1].second == iFruitPosX) {
            iScore += 500;
            iSnakeBody += 10;
            iGameSpeed -= 3;

            print_score(w_snake, iScore);

            iFruitPosY = 0;
            iFruitPosX = 0;
        }

        //Check if we are longer than our max size
        if (vSnakeBody.size() > iSnakeBody) {
            mSnakeBody[vSnakeBody[0].first][vSnakeBody[0].second] = false;
            mvwputch(w_snake, vSnakeBody[0].first, vSnakeBody[0].second, c_black, ' ');
            vSnakeBody.erase(vSnakeBody.begin(), vSnakeBody.begin() + 1);
        }

        //Draw Snake
        mvwputch(w_snake, vSnakeBody[vSnakeBody.size() - 1].first,
                 vSnakeBody[vSnakeBody.size() - 1].second, c_white, '#');
        mvwputch(w_snake, vSnakeBody[vSnakeBody.size() - 2].first,
                 vSnakeBody[vSnakeBody.size() - 2].second, c_ltgray, '#');

        //On full length add a fruit
        if (iFruitPosY == 0 && iFruitPosY == 0) {
            do {
                iFruitPosY = rng(1, FULL_SCREEN_HEIGHT - 2);
                iFruitPosX = rng(1, FULL_SCREEN_WIDTH - 2);
            } while (mSnakeBody[iFruitPosY][iFruitPosX]);

            mvwputch(w_snake, iFruitPosY, iFruitPosX, c_ltred, '*');
        }

        wrefresh(w_snake);

        //Check input
        timeout(iGameSpeed);
        const std::string action = ctxt.handle_input();
        timeout(-1);

        if (action == "UP") {
            if (iDirY != 1) {
                iDirY = -1;
                iDirX = 0;
            }
        } else if (action == "DOWN") {
            if (iDirY != -1) {
                iDirY = 1;
                iDirX = 0;
            }
        } else if (action == "LEFT") {
            if (iDirX != 1) {
                iDirY = 0;
                iDirX = -1;
            }
        } else if (action == "RIGHT") {
            if (iDirX != -1) {
                iDirY = 0;
                iDirX = 1;
            }
        } else if (action == "QUIT") {
            return iScore;
        }

    } while (true);

    snake_over(w_snake, iScore);
    while(ctxt.handle_input() != "QUIT") {
        // try again
    }

    return iScore;
}