-int main( int argc, char *argv[] )
-{
- vg_init( argc, argv, "FishLadder" );
-}
-
-#define CELL_FLAG_INPUT 0x1
-#define CELL_FLAG_OUTPUT 0x2
- #define CELL_FLAG_IO (CELL_FLAG_INPUT|CELL_FLAG_OUTPUT)
-#define CELL_FLAG_WALL 0x4
-#define CELL_FLAG_HOVER 0x8
-#define CELL_FLAG_ITER 0x10
-#define CELL_FLAG_CANAL 0x20
-#define CELL_FLAG_SPLIT 0x40 /* Does this cell split and have an incoming vertical connection? */
-#define CELL_FLAG_WALKABLE (CELL_FLAG_IO|CELL_FLAG_CANAL)
-#define CELL_FLAG_VISITED 0x80
-#define CELL_FLAG_UPLVL 0x100
-#define CELL_FLAG_MERGE 0x200
-
-// Cell data:
-// | byte 3 | byte 2 | byte 1 | byte 0 |
-// | anim | cfg | rflags | sflags |
-
-// Static flags
-// Level defined (fixed)
-#define FLAG_WALL 0x1 /* Border cells // non passable */
-#define FLAG_LEVEL_CANAL 0x2 /* Used to mark canals from IO or static sections etc */
-
-// Player defined
-#define FLAG_CANAL 0x4 /* Cell is marked as canal and can transport water */
-#define FLAG_UNUSED0 0x8
-#define FLAG_UNUSED1 0x10
-#define FLAG_UNUSED2 0x20
-#define FLAG_UNUSED3 0x40
-#define FLAG_UNUSED4 0x80
-
-// Volatile flags
-#define FLAG_WATER 0x100 /* Does this cell have water flowing through it */
-#define FLAG_UNUSED5 0x200
-#define FLAG_UNUSED6 0x400
-#define FLAG_UNUSED7 0x800
-
-#define FLAG_UNUSED8 0x1000
-#define FLAG_UNUSED9 0x2000
-#define FLAG_UNUSEDA 0x4000
-#define FLAG_UNUSEDB 0x8000
-
-// Combined
-#define CFLAG_TRANSPORT (FLAG_CANAL|FLAG_LEVEL_CANAL)
-
-static struct
-{
- u32 x,y;
-
- v2f origin;
- struct cell *selected;
- int select_valid;
- int playing;
- u32 frame;
-
- u32 *io;
-
- struct vstack
- {
- struct vframe
- {
- int x, y;
- int i;
- }
- frames[ 64 ];
-
- int level;
- u32 flags;
- }
- stack;
-
- GLuint tile_texture;
- GLuint flow_texture;
-
- GLuint tiles_vao;
- GLuint tiles_vbo;
-}
-map;
-
-static void map_free(void)
-{
- for( int i = 0; i < arrlen( map.io ); i ++ )
- {
- arrfree( map.cells[ map.io[i] ].conditions );
- }
-
- arrfree( map.cells );
- arrfree( map.io );
- map.x = 0;
- map.y = 0;
- map.cells = NULL;
- map.io = NULL;
-}
-
-static struct cell *ptile( int pos[2] )
-{
- return map.cells + pos[1]*map.x + pos[0];
-}
-
-static struct cell *gettile( int pos[2] )
-{
- if( pos[0] >= 0 && pos[0] < map.x && pos[1] >= 0 && pos[1] < map.y )
- return map.cells + pos[1]*map.x + pos[0];
- return NULL;
-}
-
-static struct cell *getiftile( int pos[2], u32 flags )
-{
- struct cell *cell = gettile( pos );
- if( cell && (cell->flags & flags) )
- return cell;
-
- return NULL;
-}
-
-static void map_tile_coords_from_index( int i, int coords[2] )
-{
- coords[0] = i % map.x;
- coords[1] = (i - coords[0])/map.x;
-}
-
-static void map_stack_refresh(void)
-{
- for( int i = 0; i < map.x*map.y; i ++ )
- map.cells[i].flags &= ~CELL_FLAG_VISITED;
-}
-
-static void map_stack_init( int coords[2] )
-{
- map.stack.level = 0;
- map.stack.frames[0].i = 0;
- map.stack.frames[0].x = coords[0];
- map.stack.frames[0].y = coords[1];
-}
-
-static struct cell *map_stack_next(void)
-{
- struct cell *tile = NULL;
-
- while( !tile )
- {
- struct vframe *frame = &map.stack.frames[ map.stack.level ];
-
- int output_dirs[][2] = { {0,1}, {-1,0}, {1,0} };
-
- if( frame->i < 3 )
- {
- int *dir = output_dirs[ frame->i ];
- tile = getiftile( (int[2]){frame->x+dir[0], frame->y+dir[1]}, CELL_FLAG_WALKABLE );
-
- if( tile && !(tile->flags & CELL_FLAG_VISITED) )
- {
- map.stack.level ++;
- frame[1].i = 0;
- frame[1].x = frame[0].x+dir[0];
- frame[1].y = frame[0].y+dir[1];
-
- tile->flags |= CELL_FLAG_VISITED;
-
- if( frame->i == 0 )
- frame->i = 400;
- }
- else
- tile = NULL;
-
- frame->i ++;
- }
- else
- {
- map.stack.level --;
- tile = NULL;
-
- if( map.stack.level < 0 )
- return NULL;
- }
- }
-
- return tile;
-}
-
-static void map_stack_current_coords( int coords[2], int offset )
-{
- coords[0] = map.stack.frames[ map.stack.level+offset ].x;
- coords[1] = map.stack.frames[ map.stack.level+offset ].y;
-}
-
-static void map_reclassify( v4i bounds )
-{
- u8 celldata[ 4096 ];
-
- for( int y = bounds[1]; y < bounds[3]; y ++ )
- {
- for( int x = bounds[0]; x < bounds[2]; x ++ )
- {
- struct cell *cur = map.cells + y*map.x + x;
- u8 *cellbytes = celldata + (y*map.x+x)*4;
-
- if( cur->flags & CELL_FLAG_WALKABLE )
- {
- struct cell *a, *b, *c, *d;
-
- a = getiftile( (int[2]){ x,y+1 }, CELL_FLAG_WALKABLE );
- b = getiftile( (int[2]){ x+1,y }, CELL_FLAG_WALKABLE );
- c = getiftile( (int[2]){ x,y-1 }, CELL_FLAG_WALKABLE );
- d = getiftile( (int[2]){ x-1,y }, CELL_FLAG_WALKABLE );
-
- u32 config = (a?0x1:0x0) | (b?0x2:0x0) | (c?0x4:0x0) | (d?0x8:0x0);
- cellbytes[ 0 ] = config;
- }
- else
- {
- // TODO: Random background tiles
- cellbytes[ 0 ] = 15;
- }
-
- cellbytes[ 1 ] = 0x00;
- cellbytes[ 2 ] = 0x00;
- cellbytes[ 3 ] = 0x00;
- }
- }
-
- glBindBuffer( GL_ARRAY_BUFFER, map.tiles_vbo );
- glBufferSubData( GL_ARRAY_BUFFER, 16*sizeof(float) + 1024*2*sizeof(float), map.x*map.y*4, celldata );
-}
-
-static int map_load( const char *str )