stuff
[carveJwlIkooP6JGAAIwe30JlM.git] / world_routes.h
index 4c198e1a429a23001ed299045790297353e96575..a4624dc8f579c6b7308f363c014308d2c6afd683 100644 (file)
@@ -43,15 +43,18 @@ struct subworld_routes
    {
       teleport_gate gate;
       
-      u32 route_count,
-          node_id;
+      u32 node_id;
+
+      double time_passed; /* When did we last pass this gate? */
+      u32    passed_version; /* Incremented on every reset */
    }
    *gates;
 
    u32 gate_count,
        gate_cap;
 
-   u32 active_gate;
+   u32 active_gate,
+       current_run_version;
 
    scene scene_lines;
 };
@@ -84,37 +87,12 @@ static void debug_sbpath( struct route_node *rna, struct route_node *rnb,
    }
 }
 
-static void world_routes_activate_gate( u32 id )
-{
-   struct subworld_routes *r = subworld_routes();
-   struct route_gate *ig = &r->gates[id];
-   struct route_node *pnode = &r->nodes[ig->node_id],
-                     *pdest = &r->nodes[pnode->next[0]];
-   
-   r->active_gate = id;
-
-   for( int i=0; i<r->route_count; i++ )
-   {
-      struct route *route = &r->routes[i];
-
-      route->active = 0;
-      for( int j=0; j<pdest->ref_count; j++ )
-      {
-         if( pdest->route_ids[j] == i )
-         {
-            route->active = 1;
-            break;
-         }
-      }
-   }
-}
-
-static u32 world_routes_get_path( struct route *route, u32 stack[64] )
+static u32 world_routes_get_path( u32 starter, u32 stack[64] )
 {
    struct subworld_routes *r = subworld_routes();
    u32 stack_i[64];
 
-   stack[0] = route->start;
+   stack[0] = starter;
    stack_i[0] = 0;
 
    u32 si = 1;
@@ -166,6 +144,94 @@ static u32 world_routes_get_path( struct route *route, u32 stack[64] )
    return 0;
 }
 
+static void world_routes_verify_run( u32 route, double new_pass_time )
+{
+   struct subworld_routes *r = subworld_routes();
+   if( r->current_run_version == 0 ) return;
+
+   u32 stack[64];
+   u32 si = world_routes_get_path( r->routes[route].start, stack );
+
+   /* 
+    * we only care about gates that ref gates, so shuffle down the array
+    */
+   u32 sj = 0;
+   for( u32 i=0; i<si; i++ )
+      if( r->nodes[stack[i]].is_gate && r->nodes[stack[(i+1)%si]].is_gate )
+         stack[sj ++] = r->nodes[stack[i]].gate_id;
+
+   /* 
+    * run versions & times must always ASCEND apart from exactly once, where
+    * the tail connects to the head
+    */
+
+   vg_info("Verifying run (%u)\n", route);
+
+   u32 descend_allowance = 1;
+   double lap_time = 0.0;
+
+   for( u32 i=0; i<sj; i++ )
+   {
+      struct route_gate *pa = &r->gates[stack[i]],
+                        *pb = &r->gates[stack[(i+1) % sj]];
+
+      vg_info( " pa: %u, pb: %u\n", pa->passed_version, pb->passed_version );
+      
+      int version_inorder = 0;
+      double diff = 0.0;
+
+      if( pb->passed_version == pa->passed_version+1 )
+      {
+         version_inorder = 1;
+         diff = pb->time_passed - pa->time_passed;
+      }
+      else if( pb->passed_version == pa->passed_version+1-sj &&
+               pa->passed_version+1 == r->current_run_version )
+      {
+         version_inorder = 1;
+         diff = new_pass_time - pa->time_passed;
+      }
+
+      if( !version_inorder )
+         return;
+
+      lap_time += diff;
+   }
+
+   /* We've now verified the run was completed correctly */
+   vg_success( "Lap time set. route %u: %lf\n", route, lap_time );
+}
+
+static void world_routes_activate_gate( u32 id )
+{
+   struct subworld_routes *r = subworld_routes();
+   struct route_gate *ig = &r->gates[id];
+   struct route_node *pnode = &r->nodes[ig->node_id],
+                     *pdest = &r->nodes[pnode->next[0]];
+
+   r->active_gate = id;
+
+   for( u32 i=0; i<r->route_count; i++ )
+   {
+      struct route *route = &r->routes[i];
+
+      route->active = 0;
+      for( u32 j=0; j<pdest->ref_count; j++ )
+      {
+         if( pdest->route_ids[j] == i )
+         {
+            world_routes_verify_run( i, vg_time );
+            route->active = 1;
+            break;
+         }
+      }
+   }
+   
+   ig->time_passed = vg_time;
+   ig->passed_version = r->current_run_version;
+   r->current_run_version ++;
+}
+
 static void world_routes_debug(void)
 {
    struct subworld_routes *r = subworld_routes();
@@ -181,7 +247,7 @@ static void world_routes_debug(void)
       struct route *route = &r->routes[i];
 
       u32 stack[64];
-      u32 si = world_routes_get_path( route, stack );
+      u32 si = world_routes_get_path( route->start, stack );
 
       u32 colours[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
                         0xff5442f5 };
@@ -239,7 +305,7 @@ static void world_routes_gen_meshes(void)
       struct route *route = &r->routes[i];
 
       u32 stack[64];
-      u32 si = world_routes_get_path( route, stack );
+      u32 si = world_routes_get_path( route->start, stack );
 
       u32 last_valid = 0;
 
@@ -459,6 +525,8 @@ static void world_routes_loadfrom( mdl_header *mdl )
                {
                   struct route_gate *rg = &r->gates[r->gate_count];
                   rg->node_id = r->node_count;
+                  rg->passed_version = 0;
+                  rg->time_passed = 0.0;
 
                   v3_copy( pnode->co,  rg->gate.co[0] );
                   v3_copy( pother->co, rg->gate.co[1] );
@@ -527,7 +595,7 @@ static void world_routes_loadfrom( mdl_header *mdl )
       struct route *route = &r->routes[i];
 
       u32 stack[64];
-      u32 si = world_routes_get_path( route, stack );
+      u32 si = world_routes_get_path( route->start, stack );
 
       for( int sj=0; sj<si; sj++ )
       {