Exemple #1
0
int intro_create(scene *scene) {
    intro_local *local = malloc(sizeof(intro_local));
    local->ticks = 0;

    // Callbacks
    scene_set_userdata(scene, local);
    scene_set_dynamic_tick_cb(scene, intro_tick);
    scene_set_event_cb(scene, intro_event);
    scene_set_free_cb(scene, intro_free);
    scene_set_startup_cb(scene, intro_startup);
    scene_set_anim_prio_override_cb(scene, intro_anim_override);

    // Pick renderer
    video_select_renderer(VIDEO_RENDERER_QUIRKS);

    return 0;
}
Exemple #2
0
int scoreboard_create(scene *scene) {
    // Init local data
    scoreboard_local *local = malloc(sizeof(scoreboard_local));
    local->page = settings_get()->gameplay.rounds;

    // Load scores
    if(scores_read(&local->data) == 1) {
        scores_clear(&local->data);
        DEBUG("No score data found; using empty score array.");
    }

    // Check for pending score
    local->has_pending_data = 0;
    if(found_pending_score(scene)) {
        game_player *player = game_state_get_player(scene->gs, 0);
        unsigned int score = player->score.score;
        if(score_fits_scoreboard(local, score)) {
            local->has_pending_data = 1;
            local->pending_data.score = score;
            local->pending_data.har_id = player->har_id;
            local->pending_data.pilot_id = player->pilot_id;
            local->pending_data.name[0] = 0;
        }

        // Wipe old score data, whether it was written on scoreboard or not.
        chr_score_reset(game_player_get_score(player), 1);
    }

    // Create a surface that has an appropriate alpha for darkening the screen a bit
    surface_create(&local->black_surface, SURFACE_TYPE_RGBA, 32, 32);
    surface_fill(&local->black_surface, color_create(0,0,0,200));

    // Set callbacks
    scene_set_userdata(scene, local);
    scene_set_event_cb(scene, scoreboard_event);
    scene_set_input_poll_cb(scene, scoreboard_input_tick);
    scene_set_render_overlay_cb(scene, scoreboard_render_overlay);
    scene_set_free_cb(scene, scoreboard_free);
    video_select_renderer(VIDEO_RENDERER_HW);

    // All done
    return 0;
}
Exemple #3
0
int vs_create(scene *scene) {
    // Init local data
    vs_local *local = malloc(sizeof(vs_local));
    scene_set_userdata(scene, local);
    game_player *player1 = game_state_get_player(scene->gs, 0);
    game_player *player2 = game_state_get_player(scene->gs, 1);

    snprintf(local->vs_str, 128, "%s VS. %s", lang_get(20+player1->pilot_id), lang_get(20+player2->pilot_id));

    animation *ani;

    palette *mpal = video_get_base_palette();
    palette_set_player_color(mpal, 0, player1->colors[2], 0);
    palette_set_player_color(mpal, 0, player1->colors[1], 1);
    palette_set_player_color(mpal, 0, player1->colors[0], 2);
    palette_set_player_color(mpal, 1, player2->colors[2], 0);
    palette_set_player_color(mpal, 1, player2->colors[1], 1);
    palette_set_player_color(mpal, 1, player2->colors[0], 2);
    video_force_pal_refresh();

    // HAR
    ani = &bk_get_info(&scene->bk_data, 5)->ani;
    object_create(&local->player1_har, scene->gs, vec2i_create(160,0), vec2f_create(0, 0));
    object_set_animation(&local->player1_har, ani);
    object_select_sprite(&local->player1_har, player1->har_id);

    object_create(&local->player2_har, scene->gs, vec2i_create(160,0), vec2f_create(0, 0));
    object_set_animation(&local->player2_har, ani);
    object_select_sprite(&local->player2_har, player2->har_id);
    object_set_direction(&local->player2_har, OBJECT_FACE_LEFT);
    object_set_pal_offset(&local->player2_har, 48);

    // PLAYER
    ani = &bk_get_info(&scene->bk_data, 4)->ani;
    object_create(&local->player1_portrait, scene->gs, vec2i_create(-10,150), vec2f_create(0, 0));
    object_set_animation(&local->player1_portrait, ani);
    object_select_sprite(&local->player1_portrait, player1->pilot_id);

    object_create(&local->player2_portrait, scene->gs, vec2i_create(330,150), vec2f_create(0, 0));
    object_set_animation(&local->player2_portrait, ani);
    object_select_sprite(&local->player2_portrait, player2->pilot_id);
    object_set_direction(&local->player2_portrait, OBJECT_FACE_LEFT);

    // clone the left side of the background image
    // Note! We are touching the scene-wide background surface!
    surface_sub(&scene->bk_data.background, // DST Surface
                &scene->bk_data.background, // SRC Surface
                160, 0, // DST
                0, 0, // SRC
                160, 200, // Size
                SUB_METHOD_MIRROR); // Flip the right side horizontally

    if (player2->selectable) {
        // player1 gets to choose, start at arena 0
        local->arena = 0;
    } else {
        // pick a random arena for 1 player mode
        local->arena = rand_int(5); // srand was done in melee
    }

    // Arena
    if(player2->selectable) {
        ani = &bk_get_info(&scene->bk_data, 3)->ani;
        object_create(&local->arena_select, scene->gs, vec2i_create(59,155), vec2f_create(0, 0));
        object_set_animation(&local->arena_select, ani);
        object_select_sprite(&local->arena_select, local->arena);
    }


    // SCIENTIST
    int scientistpos = rand_int(4);
    vec2i scientistcoord = spawn_position(scientistpos, 1);
    if (scientistpos % 2) {
        scientistcoord.x += 50;
    } else {
        scientistcoord.x -= 50;
    }
    object *o_scientist = malloc(sizeof(object));
    ani = &bk_get_info(&scene->bk_data, 8)->ani;
    object_create(o_scientist, scene->gs, scientistcoord, vec2f_create(0, 0));
    object_set_animation(o_scientist, ani);
    object_select_sprite(o_scientist, 0);
    object_set_direction(o_scientist, scientistpos % 2 ? OBJECT_FACE_LEFT : OBJECT_FACE_RIGHT);
    game_state_add_object(scene->gs, o_scientist, RENDER_LAYER_MIDDLE, 0, 0);

    // WELDER
    int welderpos = rand_int(6);
    // welder can't be on the same gantry or the same *side* as the scientist
    // he also can't be on the same 'level'
    // but he has 10 possible starting positions
    while ((welderpos % 2)  == (scientistpos % 2) || (scientistpos < 2 && welderpos < 2) || (scientistpos > 1 && welderpos > 1 && welderpos < 4)) {
        welderpos = rand_int(6);
    }
    object *o_welder = malloc(sizeof(object));
    ani = &bk_get_info(&scene->bk_data, 7)->ani;
    object_create(o_welder, scene->gs, spawn_position(welderpos, 0), vec2f_create(0, 0));
    object_set_animation(o_welder, ani);
    object_select_sprite(o_welder, 0);
    object_set_spawn_cb(o_welder, cb_vs_spawn_object, (void*)scene);
    object_set_destroy_cb(o_welder, cb_vs_destroy_object, (void*)scene);
    object_set_direction(o_welder, welderpos % 2 ? OBJECT_FACE_LEFT : OBJECT_FACE_RIGHT);
    game_state_add_object(scene->gs, o_welder, RENDER_LAYER_MIDDLE, 0, 0);

    // GANTRIES
    object *o_gantry_a = malloc(sizeof(object));
    ani = &bk_get_info(&scene->bk_data, 11)->ani;
    object_create(o_gantry_a, scene->gs, vec2i_create(0,0), vec2f_create(0, 0));
    object_set_animation(o_gantry_a, ani);
    object_select_sprite(o_gantry_a, 0);
    game_state_add_object(scene->gs, o_gantry_a, RENDER_LAYER_TOP, 0, 0);

    object *o_gantry_b = malloc(sizeof(object));
    object_create(o_gantry_b, scene->gs, vec2i_create(320,0), vec2f_create(0, 0));
    object_set_animation(o_gantry_b, ani);
    object_select_sprite(o_gantry_b, 0);
    object_set_direction(o_gantry_b, OBJECT_FACE_LEFT);
    game_state_add_object(scene->gs, o_gantry_b, RENDER_LAYER_TOP, 0, 0);

    // Background tex
    menu_background2_create(&local->arena_select_bg, 211, 50);

    // Quit Dialog
    dialog_create(&local->quit_dialog, DIALOG_STYLE_YES_NO, "ARE YOU SURE YOU WANT TO QUIT THIS GAME?", 72, 60);
    local->quit_dialog.userdata = scene;
    local->quit_dialog.clicked = vs_quit_dialog_clicked;

    // Too Pathetic Dialog
    char insult[512];
    snprintf(insult, 512, lang_get(748), "Veteran", "Major Kreissack");
    dialog_create(&local->too_pathetic_dialog, DIALOG_STYLE_OK, insult, 72, 60);
    local->too_pathetic_dialog.userdata = scene;
    local->too_pathetic_dialog.clicked = vs_too_pathetic_dialog_clicked;

    if (player2->pilot_id == 10 && settings_get()->gameplay.difficulty < 2) {
        // kriessack, but not on Veteran or higher
        dialog_show(&local->too_pathetic_dialog, 1);
    }

    // Callbacks
    scene_set_render_cb(scene, vs_render);
    scene_set_render_overlay_cb(scene, vs_render_overlay);
    scene_set_input_poll_cb(scene, vs_input_tick);
    scene_set_dynamic_tick_cb(scene, vs_dynamic_tick);
    scene_set_static_tick_cb(scene, vs_static_tick);
    scene_set_free_cb(scene, vs_free);

    // Pick renderer
    video_select_renderer(VIDEO_RENDERER_HW);

    return 0;
}
Exemple #4
0
int newsroom_create(scene *scene) {
    newsroom_local *local = malloc(sizeof(newsroom_local));

    local->news_id = rand_int(24)*2;
    local->screen = 0;
    menu_background_create(&local->news_bg, 280, 50);
    str_create(&local->news_str);
    str_create(&local->pilot1);
    str_create(&local->pilot2);
    str_create(&local->har1);
    str_create(&local->har2);

    game_player *p1 = game_state_get_player(scene->gs, 0);
    game_player *p2 = game_state_get_player(scene->gs, 1);

    int health = 0;
    if (p2->sp_wins > 0) {
        // AI won, player lost
        local->won = 0;
        health = game_player_get_score(p2)->health;
    } else {
        local->won = 1;
        health = game_player_get_score(p1)->health;
    }

    DEBUG("health is %d", health);

    if (health > 40 && local->won == 1) {
        local->news_id = rand_int(6)*2;
    } else if (local->won == 1) {
        local->news_id = 12+rand_int(6)*2;
    } else if (health < 40 && local->won == 0) {
        local->news_id = 38+rand_int(5)*2;
    } else {
        local->news_id = 24+rand_int(7)*2;
    }

    // XXX TODO get the real sex of pilot
    // XXX TODO strip spaces from the end of the pilots name
    // XXX TODO set winner/loser names properly
    newsroom_set_names(local, lang_get(20+p1->pilot_id),
                              lang_get(20+p2->pilot_id),
                              har_get_name(p1->har_id),
                              har_get_name(p2->har_id),
                              pilot_sex(p1->pilot_id),
                              pilot_sex(p2->pilot_id));
    newsroom_fixup_str(local);

    // Continue Dialog
    dialog_create(&local->continue_dialog, DIALOG_STYLE_YES_NO, "DO YOU WISH TO CONTINUE?", 72, 60);
    local->continue_dialog.userdata = scene;
    local->continue_dialog.clicked = newsroom_continue_dialog_clicked;

    // Set callbacks
    scene_set_userdata(scene, local);
    scene_set_input_poll_cb(scene, newsroom_input_tick);
    scene_set_render_overlay_cb(scene, newsroom_overlay_render);
    scene_set_free_cb(scene, newsroom_free);
    scene_set_static_tick_cb(scene, newsroom_static_tick);
    scene_set_startup_cb(scene, newsroom_startup);

    // Start correct music
    music_play(PSM_MENU);

    // Pick renderer
    video_select_renderer(VIDEO_RENDERER_HW);

    return 0;
}
Exemple #5
0
// Init mechlab
int mechlab_create(scene *scene) {
    // Alloc
    mechlab_local *local = malloc(sizeof(mechlab_local));
    memset(local, 0, sizeof(mechlab_local));

    animation *bg_ani[3];

    // Init the background
    for(int i = 0; i < sizeof(bg_ani)/sizeof(animation*); i++) {
        sprite *spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 14)->ani, i));
        bg_ani[i] = create_animation_from_single(spr, spr->pos);
        object_create(&local->bg_obj[i], scene->gs, vec2i_create(0,0), vec2f_create(0,0));
        object_set_animation(&local->bg_obj[i], bg_ani[i]);
        object_select_sprite(&local->bg_obj[i], 0);
        object_set_repeat(&local->bg_obj[i], 1);
        object_set_animation_owner(&local->bg_obj[i], OWNER_OBJECT);
    }

    // Find last saved game ...
    game_player *p1 = game_state_get_player(scene->gs, 0);
    const char* last_name = settings_get()->tournament.last_name;
    if(last_name == NULL || strlen(last_name) == 0) {
        last_name = NULL;
    }

    // ... and attempt to load it, if one was found.
    if(last_name != NULL) {
        int ret = sg_load(&p1->pilot, last_name);
        if(ret != SD_SUCCESS) {
            PERROR("Could not load saved game for playername '%s': %s!", last_name, sd_get_error(ret));
            last_name = NULL;
        } else {
            DEBUG("Loaded savegame for playername '%s'.", last_name);
        }
    }

    // Either initialize a new tournament if no savegame is found,
    // or just show old savegame stats directly if it was.
    local->dashtype = DASHBOARD_NONE;
    if(last_name == NULL) {
        DEBUG("No previous savegame found");
    } else {
        DEBUG("Previous savegame found; loading as default.");
    }
    mechlab_select_dashboard(scene, local, DASHBOARD_STATS);

    // Create main menu
    local->frame = guiframe_create(0, 0, 320, 200);
    guiframe_set_root(local->frame, lab_menu_main_create(scene));
    guiframe_layout(local->frame);

    // Load HAR
    animation *initial_har_ani = &bk_get_info(&scene->bk_data, 15 + p1->pilot.har_id)->ani;
    local->mech = malloc(sizeof(object));
    object_create(local->mech, scene->gs, vec2i_create(0,0), vec2f_create(0,0));
    object_set_animation(local->mech, initial_har_ani);
    object_set_repeat(local->mech, 1);
    object_dynamic_tick(local->mech);

    // Set callbacks
    scene_set_userdata(scene, local);
    scene_set_input_poll_cb(scene, mechlab_input_tick);
    scene_set_event_cb(scene, mechlab_event);
    scene_set_render_cb(scene, mechlab_render);
    scene_set_free_cb(scene, mechlab_free);
    scene_set_dynamic_tick_cb(scene, mechlab_tick);

    // Pick renderer
    video_select_renderer(VIDEO_RENDERER_HW);

    return 0;
}
Exemple #6
0
int cutscene_create(scene *scene) {
    cutscene_local *local = malloc(sizeof(cutscene_local));

    game_player *p1 = game_state_get_player(scene->gs, 0);

    const char *text = "";
    switch (scene->id) {
      case SCENE_END:
        cutscene_music(PSM_END);
        text = lang_get(END_TEXT);
        local->text_x = 10;
        local->text_y = 5;
        local->text_width = 300;
        local->color = COLOR_YELLOW;
        break;

      case SCENE_END1:
        text = lang_get(END1_TEXT+p1->pilot_id);
        local->text_x = 10;
        local->text_y = 160;
        local->text_width = 300;
        local->color = COLOR_RED;

        // Pilot face
        animation *ani = &bk_get_info(&scene->bk_data, 3)->ani;
        object *obj = malloc(sizeof(object));
        object_create(obj, scene->gs, vec2i_create(0,0), vec2f_create(0, 0));
        object_set_animation(obj, ani);
        object_select_sprite(obj, p1->pilot_id);
        obj->halt=1;
        game_state_add_object(scene->gs, obj, RENDER_LAYER_TOP);

        // Face effects
        ani = &bk_get_info(&scene->bk_data, 10+p1->pilot_id)->ani;
        obj = malloc(sizeof(object));
        object_create(obj, scene->gs, vec2i_create(0,0), vec2f_create(0, 0));
        object_set_animation(obj, ani);
        game_state_add_object(scene->gs, obj, RENDER_LAYER_TOP);
        break;

      case SCENE_END2:
        text = lang_get(END2_TEXT+p1->pilot_id);
        local->text_x = 10;
        local->text_y = 160;
        local->text_width = 300;
        local->color = COLOR_GREEN;
        break;
    }

    local->len = strlen(text)-1;
    local->pos = 0;
    local->text = malloc(strlen(text)+1);
    strcpy(local->text, text);
    local->current = local->text;
    char *p;

    if ((p = strchr(local->text, '\n'))) {
      // null out the byte
      *p = '\0';
    }

    // Callbacks
    scene_set_userdata(scene, local);
    scene_set_free_cb(scene, cutscene_free);
    scene_set_event_cb(scene, cutscene_event);
    scene_set_startup_cb(scene, cutscene_startup);
    scene_set_render_overlay_cb(scene, cutscene_render_overlay);

    // Pick renderer
    video_select_renderer(VIDEO_RENDERER_HW);

    return 0;
}
Exemple #7
0
int melee_create(scene *scene) {
    char bitmap[51*36*4];

    // Init local data
    melee_local *local = malloc(sizeof(melee_local));
    memset(local, 0, sizeof(melee_local));
    scene_set_userdata(scene, local);

    game_player *player1 = game_state_get_player(scene->gs, 0);
    game_player *player2 = game_state_get_player(scene->gs, 1);

    controller *player1_ctrl = game_player_get_ctrl(player1);
    controller *player2_ctrl = game_player_get_ctrl(player2);

    palette *mpal = video_get_base_palette();
    palette_set_player_color(mpal, 0, 8, 0);
    palette_set_player_color(mpal, 0, 8, 1);
    palette_set_player_color(mpal, 0, 8, 2);
    video_force_pal_refresh();

    memset(&bitmap, 255, 51*36*4);
    local->ticks = 0;
    local->pulsedir = 0;
    local->selection = 0;
    local->row_a = 0;
    local->column_a = 0;
    local->row_b = 0;
    local->column_b = 4;
    local->done_a = 0;
    local->done_b = 0;

    menu_background2_create(&local->feh, 90, 61);
    menu_background2_create(&local->bleh, 160, 43);
    surface_create_from_data(&local->select_hilight, SURFACE_TYPE_RGBA, 51, 36, bitmap);

    // set up the magic controller hooks
    if(player1_ctrl && player2_ctrl) {
        if(player1_ctrl->type == CTRL_TYPE_NETWORK) {
            controller_add_hook(player2_ctrl, player1_ctrl, player1_ctrl->controller_hook);
        }

        if (player2_ctrl->type == CTRL_TYPE_NETWORK) {
            controller_add_hook(player1_ctrl, player2_ctrl, player2_ctrl->controller_hook);
        }
    }

    animation *ani;
    sprite *spr;
    for(int i = 0; i < 10; i++) {
        ani = &bk_get_info(&scene->bk_data, 3)->ani;
        object_create(&local->pilots[i], scene->gs, vec2i_create(0,0), vec2f_create(0, 0));
        object_set_animation(&local->pilots[i], ani);
        object_select_sprite(&local->pilots[i], i);

        ani = &bk_get_info(&scene->bk_data, 18+i)->ani;
        object_create(&local->har_player1[i], scene->gs, vec2i_create(110,95), vec2f_create(0, 0));
        object_set_animation(&local->har_player1[i], ani);
        object_select_sprite(&local->har_player1[i], 0);
        object_set_repeat(&local->har_player1[i], 1);

        int row = i / 5;
        int col = i % 5;
        spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0));
        mask_sprite(spr->data, 62*col, 42*row, 51, 36);
        ani = create_animation_from_single(spr, spr->pos);
        object_create(&local->harportraits_player1[i], scene->gs, vec2i_create(0, 0), vec2f_create(0, 0));
        object_set_animation(&local->harportraits_player1[i], ani);
        object_select_sprite(&local->harportraits_player1[i], 0);
        object_set_animation_owner(&local->harportraits_player1[i], OWNER_OBJECT);
        if (player2->selectable) {
            spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0));
            mask_sprite(spr->data, 62*col, 42*row, 51, 36);
            ani = create_animation_from_single(spr, spr->pos);
            object_create(&local->harportraits_player2[i], scene->gs, vec2i_create(0, 0), vec2f_create(0, 0));
            object_set_animation(&local->harportraits_player2[i], ani);
            object_select_sprite(&local->harportraits_player2[i], 0);
            object_set_animation_owner(&local->harportraits_player2[i], OWNER_OBJECT);
            object_set_pal_offset(&local->harportraits_player2[i], 48);

            ani = &bk_get_info(&scene->bk_data, 18+i)->ani;
            object_create(&local->har_player2[i], scene->gs, vec2i_create(210,95), vec2f_create(0, 0));
            object_set_animation(&local->har_player2[i], ani);
            object_select_sprite(&local->har_player2[i], 0);
            object_set_repeat(&local->har_player2[i], 1);
            object_set_direction(&local->har_player2[i], OBJECT_FACE_LEFT);
            object_set_pal_offset(&local->har_player2[i], 48);
        }
    }

    ani = &bk_get_info(&scene->bk_data, 4)->ani;
    object_create(&local->bigportrait1, scene->gs, vec2i_create(0,0), vec2f_create(0, 0));
    object_set_animation(&local->bigportrait1, ani);
    object_select_sprite(&local->bigportrait1, 0);

    if (player2->selectable) {
        object_create(&local->bigportrait2, scene->gs, vec2i_create(320,0), vec2f_create(0, 0));
        object_set_animation(&local->bigportrait2, ani);
        object_select_sprite(&local->bigportrait2, 4);
        object_set_direction(&local->bigportrait2, OBJECT_FACE_LEFT);
    }

    ani = &bk_get_info(&scene->bk_data, 5)->ani;
    object_create(&local->player2_placeholder, scene->gs, vec2i_create(0,0), vec2f_create(0, 0));
    object_set_animation(&local->player2_placeholder, ani);
    if (player2->selectable) {
        object_select_sprite(&local->player2_placeholder, 0);
    } else {
        object_select_sprite(&local->player2_placeholder, 1);
    }

    spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0));
    surface_convert_to_rgba(spr->data, video_get_pal_ref(), 0);
    ani = create_animation_from_single(spr, spr->pos);
    object_create(&local->unselected_har_portraits, scene->gs, vec2i_create(0,0), vec2f_create(0, 0));
    object_set_animation(&local->unselected_har_portraits, ani);
    object_select_sprite(&local->unselected_har_portraits, 0);
    object_set_animation_owner(&local->unselected_har_portraits, OWNER_OBJECT);

    for(int i = 0; i < 2; i++) {
        local->bar_power[i] = progressbar_create(PROGRESSBAR_THEME_MELEE, PROGRESSBAR_LEFT, 50);
        local->bar_agility[i] = progressbar_create(PROGRESSBAR_THEME_MELEE, PROGRESSBAR_LEFT, 50);
        local->bar_endurance[i] = progressbar_create(PROGRESSBAR_THEME_MELEE, PROGRESSBAR_LEFT, 50);
    }
    component_layout(local->bar_power[0], 74, 12, 20*4, 8);
    component_layout(local->bar_agility[0], 74, 30, 20*4, 8);
    component_layout(local->bar_endurance[0], 74, 48, 20*4, 8);
    component_layout(local->bar_power[1], 320-66-local->feh.w, 12, 20*4, 8);
    component_layout(local->bar_agility[1], 320-66-local->feh.w, 30, 20*4, 8);
    component_layout(local->bar_endurance[1], 320-66-local->feh.w, 48, 20*4, 8);

    refresh_pilot_stats(local);

    // initialize nova selection cheat
    memset(local->har_selected, 0, sizeof(local->har_selected));
    memset(local->katana_down_count, 0, sizeof(local->katana_down_count));

    // Set callbacks
    scene_set_input_poll_cb(scene, melee_input_tick);
    scene_set_render_cb(scene, melee_render);
    scene_set_free_cb(scene, melee_free);
    scene_set_dynamic_tick_cb(scene, melee_tick);

    // Play correct music
    music_play(PSM_MENU);

    // Pick renderer
    video_select_renderer(VIDEO_RENDERER_HW);

    // All done
    return 0;
}