]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/aicontrol.cpp
Add control enumeration to Controller
[r2c2.git] / source / libr2c2 / aicontrol.cpp
index c2f16e38a898a0efbdc702bdfe14fabbe84d82dd..782993752ab94cd504261b5522a7211b936b92b5 100644 (file)
@@ -19,8 +19,7 @@ AIControl::AIControl(Train &t, Controller *n):
        train(t),
        next_ctrl(n),
        target_speed(Control::continuous("speed", 0, 1000)),
-       blocked(false),
-       approach(false)
+       state(NORMAL)
 {
        target_speed.set(0);
 
@@ -33,18 +32,33 @@ AIControl::~AIControl()
        delete next_ctrl;
 }
 
+const char *AIControl::enumerate_controls(unsigned index) const
+{
+       if(index==0)
+               return target_speed.name.c_str();
+       else
+       {
+               for(--index;; ++index)
+               {
+                       const char *ret = next_ctrl->enumerate_controls(index-1);
+                       if(!ret || ret!=target_speed.name)
+                               return ret;
+               }
+       }
+}
+
 void AIControl::set_control(const string &n, float v)
 {
-       if(n=="speed")
+       if(n==target_speed.name)
        {
                if(v && !train.is_active())
                        train.set_active(true);
 
                target_speed.set(v);
-               if(!blocked)
+               if(state!=BLOCKED)
                {
                        float approach_speed = 5*train.get_layout().get_catalogue().get_scale();
-                       if(approach && target_speed.value>approach_speed)
+                       if(state==APPROACH && target_speed.value>approach_speed)
                                next_ctrl->set_control("speed", approach_speed);
                        else
                                next_ctrl->set_control("speed", target_speed.value);
@@ -58,7 +72,7 @@ void AIControl::set_control(const string &n, float v)
 
 const Controller::Control &AIControl::get_control(const string &n) const
 {
-       if(n=="speed")
+       if(n==target_speed.name)
                return target_speed;
        else
                return next_ctrl->get_control(n);
@@ -88,26 +102,36 @@ void AIControl::tick(const Time::TimeDelta &dt)
        float approach_speed = 5*scale;
        float margin = 10*scale;
 
-       if(!blocked && rsv_dist<brake_dist+margin)
-       {
-               blocked = true;
-               next_ctrl->set_control("speed", 0);
-       }
-       else if((!approach && rsv_dist<brake_dist*1.3+approach_margin) || (blocked && rsv_dist>brake_dist+margin*2))
+       State old_state = state;
+
+       if(state==FOLLOW && !train.get_preceding_train())
+               state = NORMAL;
+
+       if(rsv_dist<brake_dist+margin)
+               state = BLOCKED;
+       else if(rsv_dist>brake_dist+margin*2 && rsv_dist<brake_dist*1.3+approach_margin)
+               state = APPROACH;
+       else if(rsv_dist>brake_dist*1.3+approach_margin*2)
+               state = NORMAL;
+
+       if(state==NORMAL && train.get_preceding_train())
+               state = FOLLOW;
+
+       if(state!=old_state || state==FOLLOW)
        {
-               blocked = false;
-               approach = true;
-               if(target_speed.value>approach_speed)
-                       next_ctrl->set_control("speed", approach_speed);
+               float speed_limit = -1;
+               if(state==BLOCKED)
+                       speed_limit = 0;
+               else if(state==APPROACH)
+                       speed_limit = approach_speed;
+               else if(state==FOLLOW)
+                       speed_limit = train.get_preceding_train()->get_speed();
+
+               if(speed_limit>=0 && target_speed.value>speed_limit)
+                       next_ctrl->set_control("speed", speed_limit);
                else
                        next_ctrl->set_control("speed", target_speed.value);
        }
-       else if((blocked || approach) && rsv_dist>brake_dist*1.3+approach_margin*2)
-       {
-               blocked = false;
-               approach = false;
-               next_ctrl->set_control("speed", target_speed.value);
-       }
 
        next_ctrl->tick(dt);