Logo Search packages:      
Sourcecode: lbreakout2 version File versions  Download package

chart.c

/***************************************************************************
                          chart.c  -  description
                             -------------------
    begin                : Mon Sep 24 2001
    copyright            : (C) 2001 by Michael Speck
    email                : kulkanie@gmx.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "lbreakout.h"
#include "config.h"
#include "chart.h"

#define CHART_FILE_NAME "lbreakout2.hscr"

List *charts = 0; /* list of all loaded level set charts */

char chart_path[512]; /* path charts where actually loaded/created from */
int chart_loaded = 0; /* true if highscore succesfully loaded */
SDL_Rect chart_pos; /* used to store size. x,y is set when drawing */
int chart_gap = 10;
int chart_level_offset = 0; /* level offset (name's left aligned, score's right aligned) */
char *cheader = "Name      Level Score";
extern SDL_Surface *stk_display;
extern Config config;
extern StkFont *cfont, *chfont, *ccfont; /* normal, highlight and caption font */

/*
====================================================================
Local
====================================================================
*/

/*
====================================================================
Reset charts
====================================================================
*/
void chart_reset( Set_Chart *chart )
{
    int i;
    memset( chart->entries, 0, sizeof( Chart_Entry ) * CHART_ENTRY_COUNT );
    for ( i = 0; i < CHART_ENTRY_COUNT; i++ )
        chart_add( chart, "............",  i + 1, 10000 * ( i + 1 ) );
      chart->entries[0].score = 300000;
      chart->entries[1].score = 200000;
      chart->entries[2].score = 150000;
      chart->entries[3].score = 100000;
      chart->entries[4].score =  70000;
    for ( i = 0; i < CHART_ENTRY_COUNT; i++ )
        chart->entries[i].new_entry = 0;
}

/*
====================================================================
Create/delete set chart.
====================================================================
*/
Set_Chart* chart_set_create( char *name )
{
      Set_Chart *chart = calloc( 1, sizeof( Set_Chart ) );
      chart->name = strdup( name );
      chart_reset( chart );
      return chart;
}
void chart_set_delete( void *ptr )
{
      Set_Chart *chart = (Set_Chart*)ptr;
      if ( !chart ) return;
      if ( chart->name ) free( chart->name );
      free( chart );
}

/*
====================================================================
Read entries of a chart from file position.
====================================================================
*/
void chart_read_entries( FILE *file, char *file_name, Set_Chart *chart )
{
    char buffer[128];
    int i;

    for ( i = 0; i < CHART_ENTRY_COUNT; i++ ) {
        if ( feof( file ) ) {
            fprintf( stderr, "Unexpected EOF in '%s' in entry %i... reading of highscore aborted.\n",
                     file_name, i );
            break;
        }
        fgets( buffer, 128, file ); buffer[strlen(buffer) - 1] = 0; /* remove newline */
        strcpy( chart->entries[i].name, buffer );
        fgets( buffer, 128, file ); buffer[strlen(buffer) - 1] = 0; /* remove newline */
        chart->entries[i].level = atoi( buffer );
        fgets( buffer, 128, file ); buffer[strlen(buffer) - 1] = 0; /* remove newline */
        chart->entries[i].score = atoi( buffer );
    }
}

/*
====================================================================
Load all highscores from path. If not found create chart with
one set 'Original'.
ReturnValue: True if successful
====================================================================
*/
int chart_load_from_path( char *path )
{
    FILE *file = 0;
    char file_name[512];
      char setname[1024];
      char aux[4];
      Set_Chart *chart = 0;
    /* full file name */
    sprintf( file_name, "%s/%s", path, CHART_FILE_NAME );
      /* clear chart list */
      list_clear( charts );
    /* open file */
    file = fopen( file_name, "rb" );
    if ( file ) {
            /* test if it's new format or old one. */
            fread( aux, sizeof( char ), 3, file ); aux[3] = 0;
            fseek( file, 0, SEEK_SET );
            if ( strequal( ">>>", aux ) ) {
                  /* new format: load all set charts */
                  while( !feof( file ) ) {
                        /* check if next sign is an '>' else skip reading */
                        aux[0] = 0;
                        fread( aux, sizeof( char ), 1, file );
                        fseek( file, -1, SEEK_CUR );
                        if ( aux[0] != '>' ) break;
                        chart = calloc( 1, sizeof( Set_Chart ) );
                        /* get name: >>>name */
                        fscanf( file, ">>>%s\n", setname );
                        chart->name = strdup( setname );
                        /* entries */
                        chart_read_entries( file, file_name, chart );
                        /* add */
                        list_add( charts, chart );
                  }
            }
            else {
                  /* old format: load single chart as 'Original' */
                  fprintf( stderr, "Converting highscore chart as format changed.\n" );
                  chart = chart_set_create( "LBreakout2" );
                  chart_read_entries( file, file_name, chart );
                  list_add( charts, chart );
            }
        fclose( file );
    }
    else {
        fprintf( stderr, "Highscore chart doesn't exist in '%s'... creating new one.\n", path );
            chart = chart_set_create( "LBreakout2" );
            list_add( charts, chart );
    }
    /* test if writing is allowed without changing actual contents */
    if ( ( file = fopen( file_name, "a" ) ) == 0 ) {
        fprintf( stderr, "Write permission for '%s' denied.\n", file_name );
        return 0;
    }
    else
        fclose( file );
    strcpy( chart_path, path );
    chart_loaded = 1;
    return 1;
}

/*
====================================================================
Publics
====================================================================
*/

/*
====================================================================
Load highscore. If it doesn't exist try to create it in HI_DIR if
this fails fall back to ~/.lbreakout and create highscore there.
====================================================================
*/
void chart_load()
{
      /* create list */
      if ( charts ) list_delete( charts ); charts = 0;
      charts = list_create( LIST_AUTO_DELETE, chart_set_delete );
    /* load highscore */
    if ( !chart_load_from_path( HI_DIR ) ) {
        fprintf( stderr, "Unable to access highscore chart in '%s'.\n", HI_DIR );
        fprintf( stderr, "Trying to use config directory '%s'.\n", config.dir_name );
        if ( !chart_load_from_path( config.dir_name ) ) {
            fprintf( stderr, "Unable to access highscore chart in config directory... won't be "
                             "able to save any results. Sorry.\n" );
            return;
        }
    }
    printf( "Saving highscore chart in: %s\n", chart_path );
    /* compute size and position stuff of highscore */
    chart_pos.w = stk_font_string_width( ccfont, cheader );
    chart_pos.h = ccfont->height +  chart_gap + /* title + gap */
                    cfont->height * CHART_ENTRY_COUNT + /* entries */
              chart_gap + /*gap between caption and entries */
              ccfont->height; /* caption size */
    chart_level_offset = stk_font_string_width( ccfont, "name.-----" ) + stk_font_string_width( ccfont, "Level" ) / 2; /* level offset centered */
}
/*
====================================================================
Delete resources
====================================================================
*/
void chart_delete()
{
      if ( charts ) list_delete( charts ); charts = 0;
}
/*
====================================================================
Save chart in directory it was loaded from.
====================================================================
*/
void chart_save()
{
    char file_name[512];
    int i;
      Set_Chart *chart = 0;
    FILE *file = 0;
    if ( !chart_loaded ) return;
    /* full file name */
    sprintf( file_name, "%s/%s", chart_path, CHART_FILE_NAME );
    /* open file */
    file = fopen( file_name, "w" );
    if ( !file ) {
        fprintf( stderr, "??? Highscore chart loaded properly but cannot save?\n" );
        return;
    }
      /* save all charts */
      list_reset( charts );
      while ( ( chart = list_next( charts ) ) !=  0 ) {
            fprintf( file, ">>>%s\n", chart->name );
      for ( i = 0; i < CHART_ENTRY_COUNT; i++ )
            fprintf( file, "%s\n%i\n%i\n", chart->entries[i].name, chart->entries[i].level, chart->entries[i].score );
      }           
    fclose( file );
}
/*
====================================================================
Check if this player entered the highscore chart and update it.
====================================================================
*/
void chart_add( Set_Chart *chart, char *name, int level, int score )
{
    /* add new entry at blind end of chart */
    strcpy( chart->entries[CHART_ENTRY_COUNT].name, name );
    chart->entries[CHART_ENTRY_COUNT].level = level;
    chart->entries[CHART_ENTRY_COUNT].score = score;
    chart->entries[CHART_ENTRY_COUNT].new_entry = 1;
    /* sort algorithm is stable so first sort levels then score */
    chart_sort( chart, SORT_BY_LEVEL );
    chart_sort( chart, SORT_BY_SCORE );
}
/*
====================================================================
Sort chart with stable algorithm (bubble sort's ok) by wanted
value.
====================================================================
*/
void chart_swap( Chart_Entry *entry1, Chart_Entry *entry2 )
{
    Chart_Entry dummy;
    dummy = *entry1;
    *entry1 = *entry2;
    *entry2 = dummy;
}
void chart_sort( Set_Chart *chart, int type )
{
    int j;
    int changed = 0;
    /* use entry dummy as well so count is CHART_ENTRY_COUNT + 1 */
    do {
        changed = 0;
        for ( j = 0; j < CHART_ENTRY_COUNT; j++ )
            switch ( type ) {
                case SORT_BY_LEVEL:
                    if ( chart->entries[j].level < chart->entries[j + 1].level ) {
                        chart_swap( &chart->entries[j], &chart->entries[j + 1] );
                        changed = 1;
                    }
                    break;
                case SORT_BY_SCORE:
                    if ( chart->entries[j].score < chart->entries[j + 1].score ) {
                        chart_swap( &chart->entries[j], &chart->entries[j + 1] );
                        changed = 1;
                    }
                    break;
            }
    } while ( changed );
}
/*
====================================================================
Draw highscores centered in regio x,y,w,h
====================================================================
*/
void chart_show( Set_Chart *chart, int x, int y, int w, int h )
{
    char number_buffer[24];
    int entry_offset; /* y offset of entries */
    StkFont *font;
    int i;
    /* adjust x,y so it's centered */
    chart_pos.x = x + ( w - chart_pos.w ) / 2;
    chart_pos.y = y + ( h - chart_pos.h ) / 2;
      /* title = name of levelset */
    ccfont->align = STK_FONT_ALIGN_CENTER_X | STK_FONT_ALIGN_TOP;
    stk_font_write( ccfont, stk_display, 
        chart_pos.x + ( chart_pos.w >> 1 ), chart_pos.y, -1, 
        chart->name );
      /* caption */
    ccfont->align = STK_FONT_ALIGN_LEFT | STK_FONT_ALIGN_TOP;
    stk_font_write( ccfont, stk_display, 
        chart_pos.x, chart_pos.y + ccfont->height + chart_gap, -1, 
        cheader );
    /* get entry offset */
    entry_offset = ( ccfont->height + chart_gap ) * 2 + chart_pos.y;
    /* entries */
    for ( i = 0; i < CHART_ENTRY_COUNT; i++ ) {
        font = cfont;
        if ( chart->entries[i].new_entry ) font = chfont;
        /* name */
        font->align = STK_FONT_ALIGN_LEFT | STK_FONT_ALIGN_TOP;
        stk_font_write( font, stk_display, 
            chart_pos.x, entry_offset, -1, chart->entries[i].name );
        /* level */
        font->align = STK_FONT_ALIGN_CENTER_X | STK_FONT_ALIGN_TOP;
        sprintf( number_buffer, "%i", chart->entries[i].level );
        stk_font_write( font, stk_display, 
            chart_pos.x + chart_level_offset, entry_offset, -1, number_buffer );
        /* score */
        font->align = STK_FONT_ALIGN_RIGHT | STK_FONT_ALIGN_TOP;
        sprintf( number_buffer, "%i", chart->entries[i].score );
        stk_font_write( font, stk_display, 
            chart_pos.x + chart_pos.w, entry_offset, -1, number_buffer );
        /* change offset */
        entry_offset += font->height;
    }
    stk_display_store_rect( &chart_pos );
}
/*
====================================================================
Clear all new_entry flags (done before new players are added
to chart when game over).
====================================================================
*/
void chart_clear_new_entries()
{
    int i;
    Set_Chart *chart;
    list_reset( charts );
    while ( ( chart = list_next( charts ) ) != 0 ) {
        chart->entries[CHART_ENTRY_COUNT].score = chart->entries[CHART_ENTRY_COUNT].level = 0;
        for ( i = 0; i < CHART_ENTRY_COUNT + 1; i++ ) 
            chart->entries[i].new_entry = 0;
    }
}
/*
====================================================================
Query set chart by this name or if not found create a new one
by this name.
====================================================================
*/
Set_Chart* chart_set_query( char *name )
{
      Set_Chart *chart = 0;
      list_reset( charts );
      while ( ( chart = list_next( charts ) ) != 0 )
            if ( strequal( name, chart->name ) )
                  return chart;
      /* not found so create it */
      fprintf( stderr, "First chart query for '%s'. Creating this chart.\n", name );
      chart = chart_set_create( name );
      list_add( charts, chart );
      return chart;
}
/*
====================================================================
Query chart by id. If id is invalid return 0.
====================================================================
*/
Set_Chart* chart_set_query_id( int id )
{
      if ( id >= charts->count ) {
            fprintf( stderr, "Chart index '%i' is out of range!\n", id );
            return 0;
      }
      return (Set_Chart*)list_get( charts, id );
}

Generated by  Doxygen 1.6.0   Back to index