]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/aicontrol.cpp
Export AI control parameters over the network
[r2c2.git] / source / libr2c2 / aicontrol.cpp
index 782993752ab94cd504261b5522a7211b936b92b5..e3ab1e47bf2886615c9cf7051be4b4e81a24395c 100644 (file)
@@ -1,10 +1,3 @@
-/* $Id$
-
-This file is part of R²C²
-Copyright © 2010  Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
 #include "aicontrol.h"
 #include "catalogue.h"
 #include "layout.h"
@@ -15,92 +8,58 @@ using namespace Msp;
 
 namespace R2C2 {
 
-AIControl::AIControl(Train &t, Controller *n):
-       train(t),
-       next_ctrl(n),
-       target_speed(Control::continuous("speed", 0, 1000)),
-       state(NORMAL)
+AIControl::AIControl(Train &t):
+       TrainAI(t),
+       target_speed(0),
+       reverse(false),
+       pending_reverse(false),
+       state(NORMAL),
+       need_update(false)
 {
-       target_speed.set(0);
-
-       train.signal_arrived.connect(sigc::mem_fun(this, &AIControl::arrived));
-       next_ctrl->signal_control_changed.connect(sigc::mem_fun(this, &AIControl::control_changed));
+       train.signal_ai_event.connect(sigc::mem_fun(this, &AIControl::event));
 }
 
-AIControl::~AIControl()
+void AIControl::set_target_speed(float s)
 {
-       delete next_ctrl;
+       target_speed = s;
+       need_update = true;
+       signal_event.emit(Message("target-speed-changed", target_speed));
 }
 
-const char *AIControl::enumerate_controls(unsigned index) const
+void AIControl::set_reverse(bool r)
 {
-       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;
-               }
-       }
-}
+       pending_reverse = r;
+       if(r==reverse)
+               return;
 
-void AIControl::set_control(const string &n, float v)
-{
-       if(n==target_speed.name)
+       if(train.get_controller().get_speed())
+               set_target_speed(0);
+       else
        {
-               if(v && !train.is_active())
-                       train.set_active(true);
-
-               target_speed.set(v);
-               if(state!=BLOCKED)
-               {
-                       float approach_speed = 5*train.get_layout().get_catalogue().get_scale();
-                       if(state==APPROACH && target_speed.value>approach_speed)
-                               next_ctrl->set_control("speed", approach_speed);
-                       else
-                               next_ctrl->set_control("speed", target_speed.value);
-               }
-
-               signal_control_changed.emit(target_speed);
+               reverse = r;
+               train.set_control("reverse", reverse);
+               signal_event.emit(Message("reverse-changed", reverse));
        }
-       else
-               next_ctrl->set_control(n, v);
-}
-
-const Controller::Control &AIControl::get_control(const string &n) const
-{
-       if(n==target_speed.name)
-               return target_speed;
-       else
-               return next_ctrl->get_control(n);
-}
-
-float AIControl::get_speed() const
-{
-       return next_ctrl->get_speed();
-}
-
-bool AIControl::get_reverse() const
-{
-       return next_ctrl->get_reverse();
 }
 
-float AIControl::get_braking_distance() const
+void AIControl::message(const Message &msg)
 {
-       return next_ctrl->get_braking_distance();
+       if(msg.type=="set-target-speed")
+               set_target_speed(msg.value.value<float>());
+       else if(msg.type=="set-reverse")
+               set_reverse(msg.value.value<bool>());
+       else if(msg.type=="toggle-reverse")
+               set_reverse(!reverse);
 }
 
-void AIControl::tick(const Time::TimeDelta &dt)
+void AIControl::tick(const Time::TimeDelta &)
 {
        float scale = train.get_layout().get_catalogue().get_scale();
        float rsv_dist = train.get_reserved_distance();
-       float brake_dist = next_ctrl->get_braking_distance();
+       float brake_dist = train.get_controller().get_braking_distance();
        float approach_margin = 50*scale;
        float approach_speed = 5*scale;
-       float margin = 10*scale;
+       float margin = 1*scale;
 
        State old_state = state;
 
@@ -117,37 +76,40 @@ void AIControl::tick(const Time::TimeDelta &dt)
        if(state==NORMAL && train.get_preceding_train())
                state = FOLLOW;
 
-       if(state!=old_state || state==FOLLOW)
+       if(state!=old_state || state==FOLLOW || need_update)
        {
                float speed_limit = -1;
                if(state==BLOCKED)
                        speed_limit = 0;
                else if(state==APPROACH)
                        speed_limit = approach_speed;
-               else if(state==FOLLOW)
+               else if(state==FOLLOW && train.get_preceding_train()->get_block_allocator().is_active())
                        speed_limit = train.get_preceding_train()->get_speed();
 
-               if(speed_limit>=0 && target_speed.value>speed_limit)
-                       next_ctrl->set_control("speed", speed_limit);
+               if(speed_limit>=0 && target_speed>speed_limit)
+                       train.set_control("speed", speed_limit);
                else
-                       next_ctrl->set_control("speed", target_speed.value);
-       }
+                       train.set_control("speed", target_speed);
 
-       next_ctrl->tick(dt);
+               need_update = false;
+       }
 
-       if(!target_speed.value && !next_ctrl->get_speed() && train.is_active())
-               train.set_active(false);
+       if(pending_reverse!=reverse && !train.get_controller().get_speed())
+       {
+               reverse = pending_reverse;
+               train.set_control("reverse", reverse);
+       }
 }
 
-void AIControl::control_changed(const Control &ctrl)
+bool AIControl::has_intent_to_move() const
 {
-       if(ctrl.name!="speed")
-               signal_control_changed.emit(ctrl);
+       return target_speed;
 }
 
-void AIControl::arrived()
+void AIControl::event(TrainAI &, const Message &ev)
 {
-       set_control("speed", 0);
+       if(ev.type=="arrived")
+               set_target_speed(0);
 }
 
 } // namespace R2C2