From: hgn Date: Wed, 24 Nov 2021 17:46:26 +0000 (+0000) Subject: trigger link serialize/load X-Git-Url: https://harrygodden.com/git/?p=fishladder.git;a=commitdiff_plain;h=f41ad9a5cd33c68bab59f2818416b8b6e8b632ae trigger link serialize/load --- diff --git a/fishladder.c b/fishladder.c index 3a3d53c..bcb5547 100644 --- a/fishladder.c +++ b/fishladder.c @@ -199,10 +199,12 @@ struct world u32 frame; + int initialzed; + u32 sim_frame; float sim_start; int simulating; - u32 sim_run; + u32 sim_run, max_runs; float frame_lerp; @@ -271,11 +273,15 @@ static void map_free(void) world.score = 0; world.time = 0; world.completed = 0; + world.max_runs = 0; + world.initialzed = 0; } static void map_reclassify( v2i start, v2i end, int update_texbuffer ); static int map_load( const char *str, const char *name ) { + //TODO: It may be worthwhile, at this point, to switch to binary encoding for save data + map_free(); char const *c = str; @@ -296,6 +302,12 @@ static int map_load( const char *str, const char *name ) int cx = 0; int reg_start = 0, reg_end = 0; + u32 *links_to_make = NULL; + int links_satisfied = 0; + + char link_id_buffer[32]; + int link_id_n = 0; + for(;;) { if( !*c ) @@ -332,47 +344,93 @@ static int map_load( const char *str, const char *name ) { terminal->runs[ terminal->run_count ].condition_count = 0; terminal->run_count ++; + world.max_runs = vg_max( world.max_runs, terminal->run_count ); } else { vg_error( "Unkown attribute '%c' (row: %u)\n", *c, world.h ); - return 0; + goto IL_REG_ERROR; } } } else { - vg_error( "Too many values to assign (row: %u)\n", world.h ); - return 0; + if( links_satisfied < arrlen( links_to_make ) ) + { + struct cell *target = &world.data[ links_to_make[ links_satisfied ] ]; + + if( (((u32)*c >= (u32)'0') && ((u32)*c <= (u32)'9')) || *c == '-' ) + { + if( link_id_n >= vg_list_size( link_id_buffer )-1 ) + { + vg_error( "Number was way too long to be parsed (row: %u)\n", world.h ); + goto IL_REG_ERROR; + } + + link_id_buffer[ link_id_n ++ ] = *c; + } + else if( *c == ',' || *c == '\n' ) + { + link_id_buffer[ link_id_n ] = 0x00; + int value = atoi( link_id_buffer ); + + target->links[value >= 0? 1:0] = abs(value); + links_satisfied ++; + link_id_n = 0; + + if( *c == '\n' ) + break; + } + else + { + vg_error( "Invalid character '%c' (row: %u)\n", *c, world.h ); + goto IL_REG_ERROR; + } + } + else + { + vg_error( "Too many values to assign (row: %u)\n", world.h ); + goto IL_REG_ERROR; + } } c ++; } } + // Registry length-error checks if( reg_start != reg_end ) { - vg_error( "Not enough values assigned (row: %u, %u of %u)\n", world.h, reg_start, reg_end ); - return 0; + vg_error( "Not enough spawn values assigned (row: %u, %u of %u)\n", world.h, reg_start, reg_end ); + goto IL_REG_ERROR; + } + + if( links_satisfied != arrlen( links_to_make ) ) + { + vg_error( "Not enough link values assigned (row: %u, %u of %u)\n", world.h, links_satisfied, arrlen( links_to_make ) ); + goto IL_REG_ERROR; } if( cx != world.w ) { vg_error( "Not enough cells to match previous row definition (row: %u, %u<%u)\n", world.h, cx, world.w ); - return 0; + goto IL_REG_ERROR; } row = arraddnptr( world.data, world.w ); cx = 0; world.h ++; reg_end = reg_start = arrlen( world.io ); + + arrsetlen( links_to_make, 0 ); + links_satisfied = 0; } else { if( cx == world.w ) { vg_error( "Too many cells to match previous row definition (row: %u, %u>%u)\n", world.h, cx, world.w ); - return 0; + goto IL_REG_ERROR; } // Tile initialization @@ -398,8 +456,12 @@ static int map_load( const char *str, const char *name ) // 2: Reserved // 3: Reserved - cell->state = ((u32)*c - (u32)'A') & FLAG_CANAL; // Only canal supported currently - cell->links[0] = 0; // TODO: Link these somewhere else + cell->state = ((u32)*c - (u32)'A') & (FLAG_CANAL|FLAG_IS_TRIGGER); + + if( cell->state & FLAG_IS_TRIGGER ) + arrpush( links_to_make, cx + world.h*world.w ); + + cell->links[0] = 0; cell->links[1] = 0; world.score ++; } @@ -410,7 +472,7 @@ static int map_load( const char *str, const char *name ) c ++; } - + // Update data texture to fill out the background { u8 info_buffer[64*64*4]; @@ -427,11 +489,58 @@ static int map_load( const char *str, const char *name ) glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 64, 64, GL_RGBA, GL_UNSIGNED_BYTE, info_buffer ); } + arrfree( links_to_make ); + map_reclassify( NULL, NULL, 1 ); + + // Validate links + for( int i = 0; i < world.h*world.w; i ++ ) + { + struct cell *src = &world.data[i]; + if( src->state & FLAG_IS_TRIGGER ) + { + int link_id = src->links[0]?0:1; + if( src->links[link_id] <= world.h*world.w ) + { + struct cell *target = &world.data[ src->links[link_id] ]; + if( (target->state & FLAG_CANAL) && (target->config == k_cell_type_split) ) + { + if( target->links[ link_id ] ) + { + vg_error( "Link target was already targeted\n" ); + goto IL_REG_ERROR; + } + else + { + // Valid link + target->links[ link_id ] = i; + target->state |= FLAG_TARGETED; + } + } + else + { + vg_error( "Link target was invalid\n" ); + goto IL_REG_ERROR; + } + } + else + { + vg_error( "Link target out of bounds\n" ); + goto IL_REG_ERROR; + } + } + } + vg_success( "Map '%s' loaded! (%u:%u)\n", name, world.w, world.h ); strncpy( world.map_name, name, vg_list_size( world.map_name )-1 ); + world.initialzed = 1; return 1; + +IL_REG_ERROR: + arrfree( links_to_make ); + map_free(); + return 0; } static struct cell *pcell( v2i pos ) @@ -486,6 +595,19 @@ static void map_serialize( FILE *stream ) } } + for( int x = 0; x < world.w; x ++ ) + { + struct cell *cell = pcell( (v2i){ x,y } ); + if( cell->state & FLAG_IS_TRIGGER ) + { + if( terminal_write_count ) + fputc( ',', stream ); + terminal_write_count ++; + + fprintf( stream, "%d", cell->links[0]? -cell->links[0]: cell->links[1] ); + } + } + fputc( '\n', stream ); } } @@ -497,6 +619,12 @@ int main( int argc, char *argv[] ) static int console_save_map( int argc, char const *argv[] ) { + if( !world.initialzed ) + { + vg_error( "Tried to save uninitialized map!\n" ); + return 0; + } + char map_path[ 256 ]; strcpy( map_path, "sav/" ); @@ -506,6 +634,7 @@ static int console_save_map( int argc, char const *argv[] ) FILE *test_writer = fopen( map_path, "wb" ); if( test_writer ) { + vg_info( "Saving map to '%s'\n", map_path ); map_serialize( test_writer ); fclose( test_writer ); @@ -542,14 +671,17 @@ static int console_load_map( int argc, char const *argv[] ) if( text_source ) { + vg_info( "Loading map: '%s'\n", map_path ); + world.ptr_career_level = NULL; + if( !map_load( text_source, argv[0] ) ) - map_free(); + { + free( text_source ); + return 0; + } free( text_source ); - // Update career link - world.ptr_career_level = NULL; - for( int i = 0; i < vg_list_size( level_pack_1 ); i ++ ) { if( !strcmp( level_pack_1[i], argv[0] ) ) @@ -1080,6 +1212,7 @@ void vg_update(void) world.num_fishes = 0; world.sim_frame = 0; world.sim_start = vg_time; + world.sim_run = 0; for( int i = 0; i < world.w*world.h; i ++ ) world.data[ i ].state &= ~FLAG_FLIP_FLOP; @@ -1163,7 +1296,7 @@ void vg_update(void) { // Try other directions for valid, so down, left, right.. v2i dirs[] = {{1,0},{-1,0},{0,-1}}; - vg_info( "Trying some other directions...\n" ); + //vg_info( "Trying some other directions...\n" ); for( int j = 0; j < vg_list_size(dirs); j ++ ) { @@ -1324,15 +1457,26 @@ void vg_update(void) if( world.completed ) { - vg_success( "Level passed!\n" ); - - u32 score = 0; - for( int i = 0; i < world.w*world.h; i ++ ) - if( world.data[ i ].state & FLAG_CANAL ) - score ++; - - world.score = score; - world.time = world.sim_frame; + if( world.sim_run < world.max_runs-1 ) + { + vg_success( "Run passed, starting next\n" ); + world.sim_run ++; + world.sim_frame = 0; + world.sim_start = vg_time; + continue; + } + else + { + vg_success( "Level passed!\n" ); + + u32 score = 0; + for( int i = 0; i < world.w*world.h; i ++ ) + if( world.data[ i ].state & FLAG_CANAL ) + score ++; + + world.score = score; + world.time = world.sim_frame; + } } else { @@ -1714,38 +1858,42 @@ void vg_render(void) v4f dot_colour = { 0.0f, 0.0f, 0.0f, 1.0f }; - // TODO: Iterate runs - for( int j = 0; j < term->runs[0].condition_count; j ++ ) + for( int k = 0; k < term->run_count; k ++ ) { - float y_offset = is_input? 1.2f: -0.2f; - glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)posx + 0.2f + 0.2f * (float)j, (float)posy + y_offset, 0.1f ); - - if( is_input ) + for( int j = 0; j < term->runs[k].condition_count; j ++ ) { - colour_code_v3( term->runs[0].conditions[j], dot_colour ); - glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour ); - - // Draw filled if tick not passed, draw empty if empty - if( world.sim_frame > j ) - draw_mesh( empty_start, empty_count ); + float y_offset = is_input? 1.2f: -0.2f; + y_offset += (is_input? 0.2f: -0.2f) * (float)k; + + glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)posx + 0.2f + 0.2f * (float)j, (float)posy + y_offset, 0.1f ); + + if( is_input ) + { + colour_code_v3( term->runs[k].conditions[j], dot_colour ); + glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour ); + + // Draw filled if tick not passed, draw empty if empty + if( world.sim_frame > j && world.sim_run >= k ) + draw_mesh( empty_start, empty_count ); + else + draw_mesh( filled_start, filled_count ); + } else - draw_mesh( filled_start, filled_count ); - } - else - { - if( term->runs[0].recv_count > j ) { - colour_code_v3( term->runs[0].recieved[j], dot_colour ); - v3_muls( dot_colour, 0.8f, dot_colour ); + if( term->runs[k].recv_count > j ) + { + colour_code_v3( term->runs[k].recieved[j], dot_colour ); + v3_muls( dot_colour, 0.8f, dot_colour ); + glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour ); + + draw_mesh( filled_start, filled_count ); + } + + colour_code_v3( term->runs[k].conditions[j], dot_colour ); glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour ); - draw_mesh( filled_start, filled_count ); + draw_mesh( empty_start, empty_count ); } - - colour_code_v3( term->runs[0].conditions[j], dot_colour ); - glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour ); - - draw_mesh( empty_start, empty_count ); } } } diff --git a/maps/xor.map b/maps/xor.map index ca66c87..4d05382 100644 --- a/maps/xor.map +++ b/maps/xor.map @@ -11,5 +11,5 @@ ## ##; ## ##; ## ##; -#####+##+#####+##;:a:,a::a,c:c:c +#####+##+#####+##;:a:a,a::a,c:c:c #################;