bool game::opening_screen()
{
    // Play title music, whoo!
    play_music( "title" );

    world_generator->set_active_world( NULL );
    // This actually _loads_ what worlds exist.
    world_generator->get_all_worlds();

    WINDOW *w_background = newwin( TERMY, TERMX, 0, 0 );
    WINDOW_PTR w_backgroundptr( w_background );
    werase( w_background );
    wrefresh( w_background );

    // main window should also expand to use available display space.
    // expanding to evenly use up half of extra space, for now.
    int extra_w = ( ( TERMX - FULL_SCREEN_WIDTH ) / 2 ) - 1;
    int extra_h = ( ( TERMY - FULL_SCREEN_HEIGHT ) / 2 ) - 1;
    extra_w = ( extra_w > 0 ? extra_w : 0 );
    extra_h = ( extra_h > 0 ? extra_h : 0 );
    const int total_w = FULL_SCREEN_WIDTH + extra_w;
    const int total_h = FULL_SCREEN_HEIGHT + extra_h;

    // position of window within main display
    const int x0 = ( TERMX - total_w ) / 2;
    const int y0 = ( TERMY - total_h ) / 2;

    WINDOW *w_open = newwin( total_h, total_w, y0, x0 );
    WINDOW_PTR w_openptr( w_open );

    const int iMenuOffsetX = 0;
    int iMenuOffsetY = total_h - 3;
    // note: if iMenuOffset is changed,
    // please update MOTD and credits to indicate how long they can be.

    // fill menu with translated menu items
    vMenuItems.clear();
    vMenuItems.push_back( pgettext( "Main Menu", "<M|m>OTD" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<N|n>ew Game" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "Lo<a|A>d" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<W|w>orld" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<S|s>pecial" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<O|o>ptions" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "H<e|E|?>lp" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<C|c>redits" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<Q|q>uit" ) );

    // determine hotkeys from (possibly translated) menu item text
    vMenuHotkeys.clear();
    for( auto item : vMenuItems ) {
        vMenuHotkeys.push_back( get_hotkeys( item ) );
    }

    std::vector<std::string> vSubItems;
    vSubItems.push_back( pgettext( "Main Menu|New Game", "<C|c>ustom Character" ) );
    vSubItems.push_back( pgettext( "Main Menu|New Game", "<P|p>reset Character" ) );
    vSubItems.push_back( pgettext( "Main Menu|New Game", "<R|r>andom Character" ) );
    if( !MAP_SHARING::isSharing() ) { // "Play Now" function doesn't play well together with shared maps
        vSubItems.push_back( pgettext( "Main Menu|New Game", "Play <N|n>ow!" ) );
    }
    std::vector<std::vector<std::string>> vNewGameHotkeys;
    for( auto item : vSubItems ) {
        vNewGameHotkeys.push_back( get_hotkeys( item ) );
    }

    std::vector<std::string> vWorldSubItems;
    vWorldSubItems.push_back( pgettext( "Main Menu|World", "<C|c>reate World" ) );
    vWorldSubItems.push_back( pgettext( "Main Menu|World", "<D|d>elete World" ) );
    vWorldSubItems.push_back( pgettext( "Main Menu|World", "<R|r>eset World" ) );
    std::vector<std::vector<std::string>> vWorldHotkeys;
    for( auto item : vWorldSubItems ) {
        vWorldHotkeys.push_back( get_hotkeys( item ) );
    }

    mmenu_refresh_title();
    print_menu( w_open, 0, iMenuOffsetX, iMenuOffsetY );

    std::vector<std::string> savegames, templates;
    dirent *dp;
    DIR *dir;

    if( !assure_dir_exist( FILENAMES["config_dir"] ) ) {
        popup( _( "Unable to make config directory. Check permissions." ) );
        return false;
    }

    if( !assure_dir_exist( FILENAMES["savedir"] ) ) {
        popup( _( "Unable to make save directory. Check permissions." ) );
        return false;
    }

    if( !assure_dir_exist( FILENAMES["templatedir"] ) ) {
        popup( _( "Unable to make templates directory. Check permissions." ) );
        return false;
    }
    dir = opendir( FILENAMES["templatedir"].c_str() );
    while( ( dp = readdir( dir ) ) ) {
        std::string tmp = dp->d_name;
        if( tmp.find( ".template" ) != std::string::npos ) {
            templates.push_back( tmp.substr( 0, tmp.find( ".template" ) ) );
        }
    }
    closedir( dir );

    int sel1 = 1, sel2 = 1, sel3 = 1, layer = 1;
    input_context ctxt( "MAIN_MENU" );
    ctxt.register_cardinal();
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "DELETE_TEMPLATE" );
    // for the menu shortcuts
    ctxt.register_action( "ANY_INPUT" );
    bool start = false;

    // Load MOTD and Credits, load it once as it shouldn't change for the duration of the application being open
    mmenu_refresh_motd();
    mmenu_refresh_credits();

    u = player();

    while( !start ) {
        print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY, ( sel1 == 0 || sel1 == 7 ) ? false : true );

        if( layer == 1 ) {
            if( sel1 == 0 ) { // Print the MOTD.
                const int motdy = ( iMenuOffsetY - mmenu_motd.size() ) * 2 / 3;
                const int motdx = 8 + extra_w / 2;
                for( size_t i = 0; i < mmenu_motd.size(); i++ ) {
                    mvwprintz( w_open, motdy + i, motdx, c_ltred, mmenu_motd[i].c_str() );
                }

                wrefresh( w_open );
                refresh();
            } else if( sel1 == 7 ) { // Print the Credits.
                const int credy = ( iMenuOffsetY - mmenu_credits.size() ) * 2 / 3;
                const int credx = 8 + extra_w / 2;
                for( size_t i = 0; i < mmenu_credits.size(); i++ ) {
                    mvwprintz( w_open, credy + i, credx, c_ltred, mmenu_credits[i].c_str() );
                }

                wrefresh( w_open );
                refresh();
            }

            std::string action = ctxt.handle_input();
            std::string sInput = ctxt.get_raw_input().text;
            // check automatic menu shortcuts
            for( size_t i = 0; i < vMenuHotkeys.size(); ++i ) {
                for( auto hotkey : vMenuHotkeys[i] ) {
                    if( sInput == hotkey ) {
                        sel1 = i;
                        action = "CONFIRM";
                    }
                }
            }
            // also check special keys
            if( action == "QUIT" ) {
                // Quit
                sel1 = 8;
                action = "CONFIRM";
            } else if( action == "LEFT" ) {
                if( sel1 > 0 ) {
                    sel1--;
                } else {
                    sel1 = 8;
                }
                sfx::play_variant_sound( "menu_move", "default", 100 );
            } else if( action == "RIGHT" ) {
                if( sel1 < 8 ) {
                    sel1++;
                } else {
                    sel1 = 0;
                }
                sfx::play_variant_sound( "menu_move", "default", 100 );
            }
            if( ( action == "UP" || action == "CONFIRM" ) && sel1 > 0 && sel1 != 7 ) {
                if( sel1 == 5 ) {
                    get_options().show();
                } else if( sel1 == 6 ) {
                    display_help();
                } else if( sel1 == 8 ) {
                    uquit = QUIT_MENU;
                    return false;
                } else {
                    sel2 = 0;
                    layer = 2;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY, ( sel1 == 0 || sel1 == 7 ) ? false : true );
                }
            }
        } else if( layer == 2 ) {
            if( sel1 == 1 ) { // New Character
                if( MAP_SHARING::isSharing() &&
                    world_generator->all_worlds.empty() ) { //don't show anything when there are no worlds (will not work if there are special maps)
                    layer = 1;
                    sel1 = 1;
                    continue;
                }

                print_menu_items( w_open, vSubItems, sel2, iMenuOffsetY - 2, iMenuOffsetX );
                wrefresh( w_open );
                refresh();

                std::string action = ctxt.handle_input();
                std::string sInput = ctxt.get_raw_input().text;
                for( size_t i = 0; i < vNewGameHotkeys.size(); ++i ) {
                    for( auto hotkey : vNewGameHotkeys[i] ) {
                        if( sInput == hotkey ) {
                            sel2 = i;
                            action = "CONFIRM";
                        }
                    }
                }
                if( action == "LEFT" ) {
                    sel2--;
                    if( sel2 < 0 ) {
                        sel2 = vSubItems.size() - 1;
                    }
                } else if( action == "RIGHT" ) {
                    sel2++;
                    if( sel2 >= ( int )vSubItems.size() ) {
                        sel2 = 0;
                    }
                } else if( action == "DOWN" || action == "QUIT" ) {
                    layer = 1;
                    sel1 = 1;
                }
                if( action == "UP" || action == "CONFIRM" ) {
                    if( sel2 == 0 || sel2 == 2 || sel2 == 3 ) {
                        // First load the mods, this is done by
                        // loading the world.
                        // Pick a world, suppressing prompts if it's "play now" mode.
                        WORLDPTR world = world_generator->pick_world( sel2 != 3 );
                        if( world == NULL ) {
                            continue;
                        }
                        world_generator->set_active_world( world );
                        setup();
                        if( !u.create( sel2 == 0 ? PLTYPE_CUSTOM : ( sel2 == 2 ? PLTYPE_RANDOM : PLTYPE_NOW ) ) ) {
                            u = player();
                            continue;
                        }

                        werase( w_background );
                        wrefresh( w_background );

                        if( !start_game( world->world_name ) ) {
                            u = player();
                            continue;
                        }
                        start = true;
                    } else if( sel2 == 1 ) {
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if( sel1 == 2 ) { // Load Character
                if( world_generator->all_worldnames.empty() ) {
                    mvwprintz( w_open, iMenuOffsetY - 2, 15 + iMenuOffsetX + extra_w / 2,
                               c_red, _( "No Worlds found!" ) );
                } else {
                    for( int i = 0; i < ( int )world_generator->all_worldnames.size(); ++i ) {
                        int line = iMenuOffsetY - 2 - i;
                        std::string world_name = world_generator->all_worldnames[i];
                        int savegames_count = world_generator->all_worlds[world_name]->world_saves.size();
                        nc_color color1, color2;
                        if( world_name == "TUTORIAL" || world_name == "DEFENSE" ) {
                            color1 = c_ltcyan;
                            color2 = h_ltcyan;
                        } else {
                            if( world_generator->world_need_lua_build( world_name ) ) {
                                color1 = c_dkgray;
                                color2 = h_dkgray;
                            } else {
                                color1 = c_white;
                                color2 = h_white;
                            }
                        }
                        mvwprintz( w_open, line, 15 + iMenuOffsetX + extra_w / 2,
                                   ( sel2 == i ? color2 : color1 ), "%s (%d)",
                                   world_name.c_str(), savegames_count );
                    }
                }
                wrefresh( w_open );
                refresh();
                const std::string action = ctxt.handle_input();
                if( world_generator->all_worldnames.empty() && ( action == "DOWN" || action == "CONFIRM" ) ) {
                    layer = 1;
                } else if( action == "DOWN" ) {
                    if( sel2 > 0 ) {
                        sel2--;
                    } else {
                        sel2 = world_generator->all_worldnames.size() - 1;
                    }
                } else if( action == "UP" ) {
                    if( sel2 < ( int )world_generator->all_worldnames.size() - 1 ) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                } else if( action == "LEFT" || action == "QUIT" ) {
                    layer = 1;
                } else if( action == "RIGHT" || action == "CONFIRM" ) {
                    if( sel2 >= 0 && sel2 < ( int )world_generator->all_worldnames.size() ) {
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if( sel1 == 3 ) { // World Menu
                // Show options for Create, Destroy, Reset worlds.
                // Create world goes directly to Make World screen.
                // Reset and Destroy ask for world to modify.
                // Reset empties world of everything but options, then makes new world within it.
                // Destroy asks for confirmation, then destroys everything in world and then removes world folder.

                // only show reset / destroy world if there is at least one valid world existing!

                if( MAP_SHARING::isSharing() && !MAP_SHARING::isWorldmenu() && !MAP_SHARING::isAdmin() ) {
                    layer = 1;
                    popup( _( "Only the admin can change worlds." ) );
                    continue;
                }

                int world_subs_to_display = ( !world_generator->all_worldnames.empty() ) ? vWorldSubItems.size() :
                                            1;
                std::vector<std::string> world_subs;
                int xoffset = 25 + iMenuOffsetX + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for( int i = 0; i < world_subs_to_display; ++i ) {
                    world_subs.push_back( vWorldSubItems[i] );
                    xlen += vWorldSubItems[i].size() + 2; // Open and close brackets added
                }
                xlen += world_subs.size() - 1;
                if( world_subs.size() > 1 ) {
                    xoffset -= 6;
                }
                print_menu_items( w_open, world_subs, sel2, yoffset, xoffset - ( xlen / 4 ) );
                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();
                std::string sInput = ctxt.get_raw_input().text;
                for( int i = 0; i < world_subs_to_display; ++i ) {
                    for( auto hotkey : vWorldHotkeys[i] ) {
                        if( sInput == hotkey ) {
                            sel2 = i;
                            action = "CONFIRM";
                        }
                    }
                }

                if( action == "LEFT" ) {
                    if( sel2 > 0 ) {
                        --sel2;
                    } else {
                        sel2 = world_subs_to_display - 1;
                    }
                } else if( action == "RIGHT" ) {
                    if( sel2 < world_subs_to_display - 1 ) {
                        ++sel2;
                    } else {
                        sel2 = 0;
                    }
                } else if( action == "DOWN" || action == "QUIT" ) {
                    layer = 1;
                }

                if( action == "UP" || action == "CONFIRM" ) {
                    if( sel2 == 0 ) { // Create world
                        // Open up world creation screen!
                        if( world_generator->make_new_world() ) {
                            return opening_screen();
                        } else {
                            layer = 1;
                        }
                    } else if( sel2 == 1 || sel2 == 2 ) { // Delete World | Reset World
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if( sel1 == 4 ) { // Special game
                if( MAP_SHARING::isSharing() ) { // Thee can't save special games, therefore thee can't share them
                    layer = 1;
                    popup( _( "Special games don't work with shared maps." ) );
                    continue;
                }

                std::vector<std::string> special_names;
                int xoffset = 32 + iMenuOffsetX  + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for( int i = 1; i < NUM_SPECIAL_GAMES; i++ ) {
                    std::string spec_name = special_game_name( special_game_id( i ) );
                    special_names.push_back( spec_name );
                    xlen += spec_name.size() + 2;
                }
                xlen += special_names.size() - 1;
                print_menu_items( w_open, special_names, sel2, yoffset, xoffset - ( xlen / 4 ) );

                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();
                if( action == "LEFT" ) {
                    if( sel2 > 0 ) {
                        sel2--;
                    } else {
                        sel2 = NUM_SPECIAL_GAMES - 2;
                    }
                } else if( action == "RIGHT" ) {
                    if( sel2 < NUM_SPECIAL_GAMES - 2 ) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                } else if( action == "DOWN" || action == "QUIT" ) {
                    layer = 1;
                }
                if( action == "UP" || action == "CONFIRM" ) {
                    if( sel2 >= 0 && sel2 < NUM_SPECIAL_GAMES - 1 ) {
                        gamemode = get_special_game( special_game_id( sel2 + 1 ) );
                        // check world
                        WORLDPTR world = world_generator->make_new_world( special_game_id( sel2 + 1 ) );
                        if( world == NULL ) {
                            continue;
                        }
                        world_generator->set_active_world( world );
                        setup();
                        if( !gamemode->init() ) {
                            gamemode.reset();
                            u = player();
                            continue;
                        }
                        start = true;
                    }
                }
            }
        } else if( layer == 3 ) {
            bool available = false;

            if( sel1 == 2 ) { // Load Game
                savegames = world_generator->all_worlds[world_generator->all_worldnames[sel2]]->world_saves;
                std::string wn = world_generator->all_worldnames[sel2];

                //hide savegames if lua is not available for a lua-built world
                if( ( wn != "TUTORIAL" && wn != "DEFENSE" ) && world_generator->world_need_lua_build( wn ) ) {
                    savegames.clear();
                    mvwprintz( w_open, iMenuOffsetY - 2, 15 + iMenuOffsetX + extra_w / 2,
                               c_red, _( "This world requires the game to be compiled with Lua." ) );
                } else if( savegames.empty() ) {
                    mvwprintz( w_open, iMenuOffsetY - 2, 19 + 19 + iMenuOffsetX + extra_w / 2,
                               c_red, _( "No save games found!" ) );
                } else {
                    for( std::vector<std::string>::iterator it = savegames.begin();
                         it != savegames.end(); ) {
                        std::string savename = base64_decode( *it );
                        if( MAP_SHARING::isSharing() && savename != MAP_SHARING::getUsername() ) {
                            it = savegames.erase( it );
                        } else {
                            // calculates the index from distance between it and savegames.begin()
                            int i = it - savegames.begin();
                            available = true;
                            int line = iMenuOffsetY - 2 - i;
                            mvwprintz( w_open, line, 19 + 19 + iMenuOffsetX + extra_w / 2,
                                       ( sel3 == i ? h_white : c_white ),
                                       base64_decode( *it ).c_str() );
                            ++it;
                        }
                    }
                    if( !available ) {
                        mvwprintz( w_open, iMenuOffsetY - 2, 19 + 19 + iMenuOffsetX + extra_w / 2,
                                   c_red, _( "No save games found!" ) );
                    }
                }
                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();
                if( savegames.empty() && ( action == "DOWN" || action == "CONFIRM" ) ) {
                    layer = 2;
                } else if( action == "DOWN" ) {
                    if( sel3 > 0 ) {
                        sel3--;
                    } else {
                        sel3 = savegames.size() - 1;
                    }
                } else if( action == "UP" ) {
                    if( sel3 < ( int )savegames.size() - 1 ) {
                        sel3++;
                    } else {
                        sel3 = 0;
                    }
                } else if( action == "LEFT" || action == "QUIT" ) {
                    layer = 2;
                    sel3 = 0;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                }
                if( action == "RIGHT" || action == "CONFIRM" ) {
                    if( sel3 >= 0 && sel3 < ( int )savegames.size() ) {
                        werase( w_background );
                        wrefresh( w_background );
                        WORLDPTR world = world_generator->all_worlds[world_generator->all_worldnames[sel2]];
                        world_generator->set_active_world( world );
                        setup();

                        load( world->world_name, savegames[sel3] );
                        start = true;
                    }
                }
            } else if( sel1 == 3 ) { // Show world names
                int i = 0;
                for( std::vector<std::string>::iterator it = world_generator->all_worldnames.begin();
                     it != world_generator->all_worldnames.end(); ++it ) {
                    int savegames_count = world_generator->all_worlds[*it]->world_saves.size();
                    int line = iMenuOffsetY - 4 - i;
                    nc_color color1, color2;
                    if( *it == "TUTORIAL" || *it == "DEFENSE" ) {
                        color1 = c_ltcyan;
                        color2 = h_ltcyan;
                    } else {
                        color1 = c_white;
                        color2 = h_white;
                    }
                    mvwprintz( w_open, line, 26 + iMenuOffsetX + extra_w / 2,
                               ( sel3 == i ? color2 : color1 ), "%s (%d)", ( *it ).c_str(), savegames_count );
                    ++i;
                }
                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();

                if( action == "DOWN" ) {
                    if( sel3 > 0 ) {
                        --sel3;
                    } else {
                        sel3 = world_generator->all_worldnames.size() - 1;
                    }
                } else if( action == "UP" ) {
                    if( sel3 < ( int )world_generator->all_worldnames.size() - 1 ) {
                        ++sel3;
                    } else {
                        sel3 = 0;
                    }
                } else if( action == "LEFT" || action == "QUIT" ) {
                    layer = 2;

                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                }
                if( action == "RIGHT" || action == "CONFIRM" ) {
                    if( sel3 >= 0 && sel3 < ( int )world_generator->all_worldnames.size() ) {
                        bool query_yes = false;
                        bool do_delete = false;
                        if( sel2 == 1 ) { // Delete World
                            if( query_yn( _( "Delete the world and all saves?" ) ) ) {
                                query_yes = true;
                                do_delete = true;
                            }
                        } else if( sel2 == 2 ) { // Reset World
                            if( query_yn( _( "Remove all saves and regenerate world?" ) ) ) {
                                query_yes = true;
                                do_delete = false;
                            }
                        }

                        if( query_yes ) {
                            delete_world( world_generator->all_worldnames[sel3], do_delete );

                            savegames.clear();
                            MAPBUFFER.reset();
                            overmap_buffer.clear();

                            layer = 2;

                            if( do_delete ) {
                                // delete world and all contents
                                world_generator->remove_world( world_generator->all_worldnames[sel3] );
                            } else {
                                // clear out everything but worldoptions from this world
                                world_generator->all_worlds[world_generator->all_worldnames[sel3]]->world_saves.clear();
                            }
                            if( world_generator->all_worldnames.empty() ) {
                                sel2 = 0; // reset to create world selection
                            }
                        } else {
                            // hacky resolution to the issue of persisting world names on the screen
                            return opening_screen();
                        }
                    }
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                }
            } else { // Character Templates
                if( templates.empty() ) {
                    mvwprintz( w_open, iMenuOffsetY - 4, iMenuOffsetX + 20 + extra_w / 2,
                               c_red, _( "No templates found!" ) );
                } else {
                    mvwprintz( w_open, iMenuOffsetY - 2, iMenuOffsetX + 20 + extra_w / 2,
                               c_white, _( "Press 'd' to delete a preset." ) );
                    for( int i = 0; i < ( int )templates.size(); i++ ) {
                        int line = iMenuOffsetY - 4 - i;
                        mvwprintz( w_open, line, 20 + iMenuOffsetX + extra_w / 2,
                                   ( sel3 == i ? h_white : c_white ), templates[i].c_str() );
                    }
                }
                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();
                if( action == "DOWN" ) {
                    if( sel3 > 0 ) {
                        sel3--;
                    } else {
                        sel3 = templates.size() - 1;
                    }
                } else if( templates.empty() && ( action == "UP" || action == "CONFIRM" ) ) {
                    sel1 = 1;
                    layer = 2;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                } else if( action == "UP" ) {
                    if( sel3 < ( int )templates.size() - 1 ) {
                        sel3++;
                    } else {
                        sel3 = 0;
                    }
                } else if( action == "LEFT"  || action == "QUIT" || templates.empty() ) {
                    sel1 = 1;
                    layer = 2;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                } else if( !templates.empty() && action == "DELETE_TEMPLATE" ) {
                    if( query_yn( _( "Are you sure you want to delete %s?" ),
                                  templates[sel3].c_str() ) ) {
                        const auto path = FILENAMES["templatedir"] + templates[sel3] + ".template";
                        if( std::remove( path.c_str() ) != 0 ) {
                            popup( _( "Sorry, something went wrong." ) );
                        } else {
                            templates.erase( templates.begin() + sel3 );
                            if( ( size_t )sel3 > templates.size() - 1 ) {
                                sel3--;
                            }
                        }
                    }
                } else if( action == "RIGHT" || action == "CONFIRM" ) {
                    WORLDPTR world = world_generator->pick_world();
                    if( world == NULL ) {
                        u = player();
                        continue;
                    }
                    world_generator->set_active_world( world );
                    setup();
                    if( !u.create( PLTYPE_TEMPLATE, templates[sel3] ) ) {
                        u = player();
                        continue;
                    }
                    werase( w_background );
                    wrefresh( w_background );
                    if( !start_game( world_generator->active_world->world_name ) ) {
                        u = player();
                        continue;
                    }
                    start = true;
                }
            }
        }
    }
    w_openptr.reset();
    w_backgroundptr.reset();
    if( start == false ) {
        uquit = QUIT_MENU;
    } else {
        refresh_all();
        draw();
    }
    return start;
}
bool game::opening_screen()
{
    world_generator->set_active_world(NULL);
    // This actually _loads_ what worlds exist.
    world_generator->get_all_worlds();

    WINDOW *w_background = newwin(TERMY, TERMX, 0, 0);
    werase(w_background);
    wrefresh(w_background);

    // main window should also expand to use available display space.
    // expanding to evenly use up half of extra space, for now.
    int extra_w = ((TERMX - FULL_SCREEN_WIDTH) / 2) - 1;
    int extra_h = ((TERMY - FULL_SCREEN_HEIGHT) / 2) - 1;
    extra_w = (extra_w > 0 ? extra_w : 0);
    extra_h = (extra_h > 0 ? extra_h : 0);
    const int total_w = FULL_SCREEN_WIDTH + extra_w;
    const int total_h = FULL_SCREEN_HEIGHT + extra_h;

    // position of window within main display
    const int x0 = (TERMX - total_w) / 2;
    const int y0 = (TERMY - total_h) / 2;

    WINDOW *w_open = newwin(total_h, total_w, y0, x0);

    const int iMenuOffsetX = 2;
    int iMenuOffsetY = total_h - 3;

    std::vector<std::string> vSubItems;
    vSubItems.push_back(pgettext("Main Menu|New Game", "<C>ustom Character"));
    vSubItems.push_back(pgettext("Main Menu|New Game", "<P>reset Character"));
    vSubItems.push_back(pgettext("Main Menu|New Game", "<R>andom Character"));
    vSubItems.push_back(pgettext("Main Menu|New Game", "Play <N>ow!"));

    std::vector<std::string> vWorldSubItems;
    vWorldSubItems.push_back(pgettext("Main Menu|World", "<C>reate World"));
    vWorldSubItems.push_back(pgettext("Main Menu|World", "<D>elete World"));
    vWorldSubItems.push_back(pgettext("Main Menu|World", "<R>eset World"));

    print_menu(w_open, 0, iMenuOffsetX, iMenuOffsetY);

    std::vector<std::string> savegames, templates;
    dirent *dp;
    DIR *dir;

    if (!assure_dir_exist("save")) {
        popup(_("Unable to make save directory. Check permissions."));
        return false;
    }

    dir = opendir("data");
    while ((dp = readdir(dir))) {
        std::string tmp = dp->d_name;
        if (tmp.find(".template") != std::string::npos) {
            templates.push_back(tmp.substr(0, tmp.find(".template")));
        }
    }
    closedir(dir);

    int sel1 = 1, sel2 = 1, sel3 = 1, layer = 1;
    InputEvent input;
    int chInput;
    bool start = false;

    // Load MOTD and store it in a string
    // Only load it once, it shouldn't change for the duration of the application being open
    static std::vector<std::string> motd;
    if (motd.empty()) {
        std::ifstream motd_file;
        motd_file.open("data/motd");
        if (!motd_file.is_open()) {
            motd.push_back(_("No message today."));
        } else {
            while (!motd_file.eof()) {
                std::string tmp;
                getline(motd_file, tmp);
                if (!tmp.length() || tmp[0] != '#') {
                    motd.push_back(tmp);
                }
            }
        }
    }

    // Load Credits and store it in a string
    // Only load it once, it shouldn't change for the duration of the application being open
    static std::vector<std::string> credits;
    if (credits.empty()) {
        std::ifstream credits_file;
        credits_file.open("data/credits");
        if (!credits_file.is_open()) {
            credits.push_back(_("No message today."));
        } else {
            while (!credits_file.eof()) {
                std::string tmp;
                getline(credits_file, tmp);
                if (!tmp.length() || tmp[0] != '#') {
                    credits.push_back(tmp);
                }
            }
        }
    }

    u = player();

    while(!start) {
        print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY, (sel1 == 0 || sel1 == 7) ? false : true);

        if (layer == 1) {
            if (sel1 == 0) { // Print the MOTD.
                for (int i = 0; i < motd.size() && i < 16; i++) {
                    mvwprintz(w_open, i + 6, 8 + extra_w / 2, c_ltred, motd[i].c_str());
                }

                wrefresh(w_open);
                refresh();
            } else if (sel1 == 7) { // Print the Credits.
                for (int i = 0; i < credits.size() && i < 16; i++) {
                    mvwprintz(w_open, i + 6, 8 + extra_w / 2, c_ltred, credits[i].c_str());
                }

                wrefresh(w_open);
                refresh();
            }

            chInput = getch();

            if (chInput == 'm' || chInput == 'M') {
                // MOTD
                sel1 = 0;
                chInput = '\n';
            } else if (chInput == 'n' || chInput == 'N') {
                // New Game
                sel1 = 1;
                chInput = '\n';
            } else if (chInput == 'a' || chInput == 'A') {
                // Load Game
                sel1 = 2;
                chInput = '\n';
            } else if (chInput == 'w' || chInput == 'W') {
                // World
                sel1 = 3;
                chInput = '\n';
            } else if (chInput == 's' || chInput == 'S') {
                // Special Game
                sel1 = 4;
                chInput = '\n';
            } else if (chInput == 'o' || chInput == 'O') {
                // Options
                sel1 = 5;
                chInput = '\n';
            } else if (chInput == 'e' || chInput == 'E' || chInput == '?') {
                // Help
                sel1 = 6;
                chInput = '\n';
            } else if (chInput == 'c' || chInput == 'C') {
                // Credits
                sel1 = 7;
                chInput = '\n';
            } else if (chInput == 'q' || chInput == 'Q' || chInput == KEY_ESCAPE) {
                // Quit
                sel1 = 8;
                chInput = '\n';
            }

            if (chInput == KEY_LEFT || chInput == 'h') {
                if (sel1 > 0) {
                    sel1--;
                } else {
                    sel1 = 8;
                }
            } else if (chInput == KEY_RIGHT || chInput == 'l') {
                if (sel1 < 8) {
                    sel1++;
                } else {
                    sel1 = 0;
                }
            } else if ((chInput == KEY_UP || chInput == 'k' || chInput == '\n') && sel1 > 0 && sel1 != 7) {
                if (sel1 == 5) {
                    show_options();
                } else if (sel1 == 6) {
                    display_help();
                } else if (sel1 == 8) {
                    uquit = QUIT_MENU;
                    delwin(w_open);
                    delwin(w_background);
                    return false;
                } else {
                    sel2 = 0;
                    layer = 2;
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY, (sel1 == 0 || sel1 == 7) ? false : true);
                }
            }
        } else if (layer == 2) {
            if (sel1 == 1) { // New Character
                print_menu_items(w_open, vSubItems, sel2, iMenuOffsetY - 2, iMenuOffsetX);
                wrefresh(w_open);
                refresh();
                chInput = getch();

                if (chInput == 'c' || chInput == 'C') {
                    sel2 = 0;
                    chInput = '\n'  ;
                } else if (chInput == 'p' || chInput == 'P') {
                    sel2 = 1;
                    chInput = '\n';
                } else if (chInput == 'r' || chInput == 'R') {
                    sel2 = 2;
                    chInput = '\n';
                } else if (chInput == 'n' || chInput == 'N') {
                    sel2 = 3;
                    chInput = '\n';
                }

                if (chInput == KEY_LEFT || chInput == 'h') {
                    sel2--;
                    if (sel2 < 0) {
                        sel2 = vSubItems.size() - 1;
                    }
                }
                if (chInput == KEY_RIGHT || chInput == 'l') {
                    sel2++;
                    if (sel2 >= vSubItems.size()) {
                        sel2 = 0;
                    }
                } else if (chInput == KEY_DOWN || chInput == 'j' || chInput == KEY_ESCAPE) {
                    layer = 1;
                    sel1 = 1;
                }
                if (chInput == KEY_UP || chInput == 'k' || chInput == '\n') {
                    if (sel2 == 0 || sel2 == 2 || sel2 == 3) {
                        // First load the mods, this is done by
                        // loading the world.
                        // Pick a world, supressing prompts if it's "play now" mode.
                        WORLDPTR world = world_generator->pick_world( sel2 != 3 );
                        if (world == NULL) {
                            continue;
                        }
                        world_generator->set_active_world(world);
                        setup();
                        if (!u.create((sel2 == 0) ? PLTYPE_CUSTOM :
                                                    ((sel2 == 2) ? PLTYPE_RANDOM : PLTYPE_NOW))) {
                            u = player();
                            continue;
                        }
                        werase(w_background);
                        wrefresh(w_background);

                        MAPBUFFER.load(world->world_name);
                        start_game(world->world_name);
                        start = true;
                    } else if (sel2 == 1) {
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if (sel1 == 2) { // Load Character
                if (world_generator->all_worldnames.empty()) {
                    mvwprintz(w_open, iMenuOffsetY - 2, 15 + iMenuOffsetX + extra_w / 2,
                              c_red, _("No Worlds found!"));
                } else {
                    for (int i = 0; i < world_generator->all_worldnames.size(); ++i) {
                      int line = iMenuOffsetY - 2 - i;
                      std::string world_name = world_generator->all_worldnames[i];
                      int savegames_count = world_generator->all_worlds[world_name]->world_saves.size();
                      mvwprintz(w_open, line, 15 + iMenuOffsetX + extra_w / 2,
                                (sel2 == i ? h_white : c_white), "%s (%d)", world_name.c_str(), savegames_count);
                    }
                }
                wrefresh(w_open);
                refresh();
                input = get_input();
                if (world_generator->all_worldnames.empty() && (input == DirectionS || input == Confirm)) {
                    layer = 1;
                } else if (input == DirectionS) {
                    if (sel2 > 0) {
                        sel2--;
                    } else {
                        sel2 = world_generator->all_worldnames.size() - 1;
                    }
                } else if (input == DirectionN) {
                    if (sel2 < world_generator->all_worldnames.size() - 1) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                } else if (input == DirectionW || input == Cancel) {
                    layer = 1;
                }
                if (input == DirectionE || input == Confirm) {
                    if (sel2 >= 0 && sel2 < world_generator->all_worldnames.size()) {
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if (sel1 == 3) {  // World Menu
                // Show options for Create, Destroy, Reset worlds.
                // Create world goes directly to Make World screen.
                // Reset and Destroy ask for world to modify.
                // Reset empties world of everything but options, then makes new world within it.
                // Destroy asks for confirmation, then destroys everything in world and then removes world folder.

                // only show reset / destroy world if there is at least one valid world existing!

                int world_subs_to_display = (world_generator->all_worldnames.size() > 0)? vWorldSubItems.size(): 1;
                std::vector<std::string> world_subs;
                int xoffset = 25 + iMenuOffsetX + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for (int i = 0; i < world_subs_to_display; ++i) {
                    world_subs.push_back(vWorldSubItems[i]);
                    xlen += vWorldSubItems[i].size() + 2; // Open and close brackets added
                }
                xlen += world_subs.size() - 1;
                if (world_subs.size() > 1) {
                    xoffset -= 6;
                }
                print_menu_items(w_open, world_subs, sel2, yoffset, xoffset - (xlen / 4));
                wrefresh(w_open);
                refresh();
                chInput = getch();
                input = get_input(chInput);

                //shortcuts
                if (chInput == 'c' || chInput == 'C') {
                    sel2 = 0;
                    input = Confirm;
                } else if ((chInput == 'd' || chInput == 'D') && (world_subs_to_display > 1)) {
                    sel2 = 1;
                    input = Confirm;
                } else if ((chInput == 'r' || chInput == 'R') && (world_subs_to_display > 1)) {
                    sel2 = 2;
                    input = Confirm;
                }

                if (input == DirectionW) {
                    if (sel2 > 0) {
                        --sel2;
                    } else {
                        sel2 = world_subs_to_display - 1;
                    }
                } else if (input == DirectionE) {
                    if (sel2 < world_subs_to_display - 1) {
                        ++sel2;
                    } else {
                        sel2 = 0;
                    }
                } else if (input == DirectionS || input == Cancel) {
                    layer = 1;
                }

                if (input == DirectionN || input == Confirm) {
                    if (sel2 == 0) { // Create world
                        // Open up world creation screen!
                        if (world_generator->make_new_world()) {
                            return opening_screen();
                        } else {
                            layer = 1;
                        }
                    } else if (sel2 == 1 || sel2 == 2) { // Delete World | Reset World
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if (sel1 == 4) { // Special game
                std::vector<std::string> special_names;
                int xoffset = 32 + iMenuOffsetX  + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for (int i = 1; i < NUM_SPECIAL_GAMES; i++) {
                    std::string spec_name = special_game_name(special_game_id(i));
                    special_names.push_back(spec_name);
                    xlen += spec_name.size() + 2;
                }
                xlen += special_names.size() - 1;
                print_menu_items(w_open, special_names, sel2, yoffset, xoffset - (xlen / 4));

                wrefresh(w_open);
                refresh();
                input = get_input();
                if (input == DirectionW) {
                    if (sel2 > 0) {
                        sel2--;
                    } else {
                        sel2 = NUM_SPECIAL_GAMES - 2;
                    }
                } else if (input == DirectionE) {
                    if (sel2 < NUM_SPECIAL_GAMES - 2) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                } else if (input == DirectionS || input == Cancel) {
                    layer = 1;
                }
                if (input == DirectionN || input == Confirm) {
                    if (sel2 >= 0 && sel2 < NUM_SPECIAL_GAMES - 1) {
                        delete gamemode;
                        gamemode = get_special_game( special_game_id(sel2 + 1) );
                        // check world
                        WORLDPTR world = world_generator->make_new_world(special_game_id(sel2 + 1));
                        if (world == NULL) {
                            continue;
                        }
                        world_generator->set_active_world(world);
                        setup();
                        if (!gamemode->init()) {
                            delete gamemode;
                            gamemode = NULL;
                            u = player();
                            continue;
                        }
                        start = true;
                    }
                }
            }
        } else if (layer == 3) {
            if (sel1 == 2) { // Load Game
                savegames = world_generator->all_worlds[world_generator->all_worldnames[sel2]]->world_saves;
                if (savegames.empty()) {
                    mvwprintz(w_open, iMenuOffsetY - 2, 19 + 19 + iMenuOffsetX + extra_w / 2,
                              c_red, _("No save games found!"));
                } else {
                    for (int i = 0; i < savegames.size(); i++) {
                        int line = iMenuOffsetY - 2 - i;
                        mvwprintz(w_open, line, 19 + 19 + iMenuOffsetX + extra_w / 2,
                                  (sel3 == i ? h_white : c_white),
                                  base64_decode(savegames[i]).c_str());
                    }
                }
                wrefresh(w_open);
                refresh();
                input = get_input();
                if (savegames.size() == 0 && (input == DirectionS || input == Confirm)) {
                    layer = 2;
                } else if (input == DirectionS) {
                    if (sel3 > 0) {
                        sel3--;
                    } else {
                        sel3 = savegames.size() - 1;
                    }
                } else if (input == DirectionN) {
                    if (sel3 < savegames.size() - 1) {
                        sel3++;
                    } else {
                        sel3 = 0;
                    }
                } else if (input == DirectionW || input == Cancel) {
                    layer = 2;
                    sel3 = 0;
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                }
                if (input == DirectionE || input == Confirm) {
                    if (sel3 >= 0 && sel3 < savegames.size()) {
                        werase(w_background);
                        wrefresh(w_background);
                        WORLDPTR world = world_generator->all_worlds[world_generator->all_worldnames[sel2]];
                        world_generator->set_active_world(world);
                        setup();
                        MAPBUFFER.load(world->world_name);

                        load(world->world_name, savegames[sel3]);
                        start = true;
                    }
                }
            } else if (sel1 == 3) { // Show world names
                int i = 0;
                for (std::vector<std::string>::iterator it = world_generator->all_worldnames.begin();
                     it != world_generator->all_worldnames.end(); ++it) {
                    int savegames_count = world_generator->all_worlds[*it]->world_saves.size();
                    int line = iMenuOffsetY - 4 - i;
                    mvwprintz(w_open, line, 26 + iMenuOffsetX + extra_w / 2,
                              (sel3 == i ? h_white : c_white), "%s (%d)", (*it).c_str(), savegames_count);
                    ++i;
                }
                wrefresh(w_open);
                refresh();
                input = get_input();

                if (input == DirectionS) {
                    if (sel3 > 0) {
                        --sel3;
                    } else {
                        sel3 = world_generator->all_worldnames.size() - 1;
                    }
                } else if (input == DirectionN) {
                    if (sel3 < world_generator->all_worldnames.size() - 1) {
                        ++sel3;
                    } else {
                        sel3 = 0;
                    }
                } else if (input == DirectionW || input == Cancel) {
                    layer = 2;

                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                }
                if (input == DirectionE || input == Confirm) {
                    if (sel3 >= 0 && sel3 < world_generator->all_worldnames.size()) {
                        bool query_yes = false;
                        bool do_delete = false;
                        if (sel2 == 1) { // Delete World
                            if (query_yn(_("Delete the world and all saves?"))) {
                                query_yes = true;
                                do_delete = true;
                            }
                        } else if (sel2 == 2) { // Reset World
                            if (query_yn(_("Remove all saves and regenerate world?"))) {
                                query_yes = true;
                                do_delete = false;
                            }
                        }

                        if (query_yes) {
                            delete_world(world_generator->all_worldnames[sel3], do_delete);

                            savegames.clear();
                            MAPBUFFER.reset();
                            MAPBUFFER.make_volatile();
                            overmap_buffer.clear();

                            layer = 2;

                            if (do_delete) {
                                // delete world and all contents
                                world_generator->remove_world(world_generator->all_worldnames[sel3]);
                            } else {
                                // clear out everything but worldoptions from this world
                                world_generator->all_worlds[world_generator->all_worldnames[sel3]]->world_saves.clear();
                            }
                            if (world_generator->all_worldnames.size() == 0) {
                                sel2 = 0; // reset to create world selection
                            }
                        } else {
                            // hacky resolution to the issue of persisting world names on the screen
                            return opening_screen();
                        }
                    }
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                }
            } else { // Character Templates
                if (templates.size() == 0) {
                    mvwprintz(w_open, iMenuOffsetY - 4, iMenuOffsetX + 20 + extra_w / 2,
                              c_red, _("No templates found!"));
                } else {
                    for (int i = 0; i < templates.size(); i++) {
                        int line = iMenuOffsetY - 4 - i;
                        mvwprintz(w_open, line, 20 + iMenuOffsetX + extra_w / 2,
                                  (sel3 == i ? h_white : c_white), templates[i].c_str());
                    }
                }
                wrefresh(w_open);
                refresh();
                input = get_input();
                if (input == DirectionS) {
                    if (sel3 > 0) {
                        sel3--;
                    } else {
                        sel3 = templates.size() - 1;
                    }
                } else if (templates.size() == 0 && (input == DirectionN || input == Confirm)) {
                    sel1 = 1;
                    layer = 2;
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                } else if (input == DirectionN) {
                    if (sel3 < templates.size() - 1) {
                        sel3++;
                    } else {
                        sel3 = 0;
                    }
                } else if (input == DirectionW  || input == Cancel || templates.size() == 0) {
                    sel1 = 1;
                    layer = 2;
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                } else if (input == DirectionE || input == Confirm) {
                    WORLDPTR world = world_generator->pick_world();
                    if (world == NULL) {
                        u = player();
                        continue;
                    }
                    world_generator->set_active_world(world);
                    setup();
                    if (!u.create(PLTYPE_TEMPLATE, templates[sel3])) {
                        u = player();
                        continue;
                    }
                    werase(w_background);
                    wrefresh(w_background);
                    MAPBUFFER.load(world_generator->active_world->world_name);
                    start_game(world_generator->active_world->world_name);
                    start = true;
                }
            }
        }
    }
    delwin(w_open);
    delwin(w_background);
    if (start == false) {
        uquit = QUIT_MENU;
    } else {
        refresh_all();
        draw();
    }
    return start;
}