chiark / gitweb /
wip before redo segment justarrive stuff
authorian <ian>
Sun, 13 Feb 2005 18:20:29 +0000 (18:20 +0000)
committerian <ian>
Sun, 13 Feb 2005 18:20:29 +0000 (18:20 +0000)
hostside/safety.c
hostside/safety.h

index 099bad01947f8cb63a468e143211bab5512e5fa3..54b7cd8641e76065438239176c9631308feaabfe 100644 (file)
@@ -7,18 +7,66 @@
 State safety_actual;
 
 typedef struct TrackLocation TrackLocation;
-struct TrackLocation {
+struct TrackLocation { /* transparent, and manipulable by trackloc_... fns */
   SegmentNum segn; /* current segment */
   long into; /* distance from start of segment */
   unsigned backwards:1; /* if 1, into is positive and measured from end */
 };
 
-void trackloc_further(TrackLocation *tloc, long *remain_io);
+const SegmentLinkInfo *trackloc_segmentlink_near(const TrackLocation *tloc) {
+  SegmentState *seg = s->seg[tloc->segn];
+  const SegmentInfo *segi= &safety_segis[tloc->segn];
+
+  return (tloc->backwards ? &segi->forwards :
+         seg->pt_sideways ?  &segi->sideways :
+         &segi->backwards);
+}
+  
+const SegmentLinkInfo *trackloc_segmentlink_far(const TrackLocation *tloc) {
+  SegmentState *seg = s->seg[tloc->segn];
+  const SegmentInfo *segi= &safety_segis[tloc->segn];
+
+  return (tloc->backwards ? &segi->backwards :
+         seg->pt_sideways ?  &segi->sideways :
+         &segi->forwards);
+}
+  
+long trackloc_remaininseg(const TrackLocation *tloc) {
+  /* Returns dist that tloc can advance before it goes into next segment. */
+  State *s = &safety_state;
+  SegmentState *seg = s->seg[tloc->segn];
+  const SegmentInfo *segi= &safety_segis[tloc->segn];
+  const SegmentLinkInfo *lnki_near, *lnki_far;
+  long segment_len;
+  
+  lnki_near= trackloc_segmentlink_near(tloc);
+  lnki_far=  trackloc_segmentlink_far(tloc);
+  segment_len= linki_near->dist + link_far->dist;
+  assert(tloc->into <= segment_len);
+  return segment_len - tloc->info;
+}  
+
+void trackloc_further(TrackLocation *tloc, long *remain_io) {
   /* Advances tloc, decrementing *remain_io, until either
    * *remain_io becomes zero, or tloc->segn changes. */
-
-long trackloc_remaininseg(const TrackLocation *tloc);
-  /* Amount that tloc can advance before it goes into next segment. */
+  State *s = &safety_state;
+  SegmentState *seg = s->seg[tloc->segn];
+  const SegmentInfo *segi= &safety_segis[tloc->segn];
+  const SegmentLinkInfo *lnki_far;
+
+  segment_remain= trackloc_remaininseg(tloc);
+
+  if (*remain_io <= segment_remain) {
+    tloc->into += *remain_io;
+    *remain_io= 0;
+  } else {
+    lnki_far= trackloc_segmentlink_far(tloc);
+    *remain_io -= segment_remain;
+    tloc->segn= lnki_far->next;
+    tloc->into= 0;
+    tloc->backwards ^= lnki_far->next_backwards;
+  }
+}
 
 static voi seg_clear_stale(SegmentState *seg) {
   if (!seg->tr_updated) {
@@ -27,10 +75,44 @@ static voi seg_clear_stale(SegmentState *seg) {
   }
 }
 
+void lay_train_checkclash(ErrorCode *ec, SegmentLinkInfo *lnki
+                         TrainNum tran,) {
+  SegmentNum clash_segn;
+  SegmentState *clash_seg;
+  TrainNum clash_tran;
+  TrainState *clash_tra;
+
+  clash_segn= lnki->clashing;
+  if (clash_segn == NOTA(Segment)) return;
+  
+  clash_seg= &s->segs[lnki->clashing];
+  if (!clash_seg->owned) return;
+
+  clash_tran= clash->owner;
+  clash_tra= &s->tras[clash_tran];
+
+  if (clash_tra->justarrived) {
+    TrackLocation clash_loc;
+    clash_loc.segn= clash_tra->foredetect;
+    clash_loc.
+      
+
+= &s->segs[lnki->clashing];
+  if (clash->
+  
+  lay_train_checkclash2( 
+
 static void lay_train(ErrorCode *ec, TrainNum tran,
                      TrackLocation tloc, long advance,
-                     unsigned detect, unsigned clash_if_updated) {
+                     unsigned pass) {
+  /* pass 0: update actual train location, check for train clashing
+   * with itself (ie, fail if we find segment with same train and
+   * tr_updated set.
+   * pass 1: update detection only.  Clashingness checking is
+   * done where it is convenient not to avoid it, but is not
+   * necessary. */
   SegmentState *seg;
+  const SegmentInfo *segi;
   long overall, remain;
 
   if (*ec) return;
@@ -38,26 +120,44 @@ static void lay_train(ErrorCode *ec, TrainNum tran,
   remain= overall= advance + tra->speed * SPEED_CLEAR_MULT;
 
   for (;;) {
-    seg= s->segs[tloc.segn];
-    if (clash_if_updated && seg->tr_updated) {
-      *ec= safety_problem(tloc.segn, tran, tran, "collision with itself");
-      return;
-    }
-    if (seg->owned) {
-      if (seg->owner != tran) {
-       *ec= safety_problem(tloc.segn, tran, seg->owner, "collision");
+    seg= &s->segs[tloc.segn];
+    segi= &info_segment[tloc.segn];
+
+    if (pass==0) {
+      if (seg->tr_updated) {
+       *ec= safety_problem(tloc.segn, tran, tran, "collision with itself");
        return;
       }
-      seg_clear_stale(seg);
+      if (seg->owned) {
+       if (seg->owner != tran) {
+         *ec= safety_problem(tloc.segn, tran, seg->owner, "collision");
+         return;
+       }
+       seg_clear_stale(seg);
+      }
     }
+    
     seg->owned= 1;
     seg->owner_backwards= tloc.backwards;
     seg->tr_updated= 1;
     seg->tran= tran;
 
+    seg->tr_justarrived= pass==0 && remain && tra->justarrived;
+    
+      lay_train_checkclash(ec, trackloc_segmentlink_near());
+      if (!remain && tra->justarrived) {
+       
+       
+      if (tloc.into <= JUSTARRIVED_INTOMAX) {
+       seg->tr_justarrived= 1;
+      } else {
+       lay_train_checkclash(&ec, trackloc_segmentlink_far());
+      }
+
+
     dist_until= (overall - remain) - advance;
     time_until= (SPEED_FACTOR * dist_until) / tra->speed;
-    *(detect ? &seg->until_detect : &seg->until_here)= time_until;
+    *(pass==0 ? &seg->until_here : &seg->until_detect)= time_until;
 
     if (!remain) break;
     trackloc_further(&tloc, &remain);
@@ -109,17 +209,6 @@ void safety_train_changed(TrainNum tran) {
   if (ec) return ec;
 
 
-
-
-
-  segi= &safety_segis[segn];
-  lnki1= (seg->reverse ? &segi->forwards :
-         seg->sideways ?  &segi->sideways :
-         &segi->backwards);
-  lnki2= (seg->reverse ? &segi->backwards :
-         seg->sideways ?  &segi->sideways :
-         &segi->forwares);
-
   tloc.segn= segn;
   tloc.into= 
     
index 06101d45c563640b1538a276bd5cb4677a67e20f..aaedd5b66137be2c21c3c25c8ce0e34aea8cae09 100644 (file)
@@ -21,8 +21,9 @@ typedef struct {
 typedef struct {
   unsigned
     owned:1, /* this track segment is reserved for a train */
-    owner_backwards:1, /* train's motion is (would be) backwards wrt track */
+    tr_backwards:1, /* train's motion is (would be) backwards wrt track */
     pt_sideways:1, /* points are set to `alternative'. (no points?: 0) */
+    pt_moving:1, /* points have been told to change, sideways is new state */
     autostop:1, /* owning train is slow and wants to stop on detection */
     tr_updated:1; /* for use by safety_train_changed etc.; otherwise 0 */
   TimeInterval until_here, /* ) nonnegative; */  /* ) always valid but */
@@ -32,7 +33,7 @@ typedef struct {
 } SegmentState;
 
 typedef struct {
-  unsigned next_rev:1;
+  unsigned next_backwards:1;
   SegmentNum next;
   SegmentNum clashing;
   Distance dist;