3 This file is part of R²C²
4 Copyright © 2010-2011 Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
18 AIControl::AIControl(Train &t, Controller *n):
21 target_speed(Control::continuous("speed", 0, 1000)),
26 train.signal_arrived.connect(sigc::mem_fun(this, &AIControl::arrived));
27 next_ctrl->signal_control_changed.connect(sigc::mem_fun(this, &AIControl::control_changed));
30 AIControl::~AIControl()
35 const char *AIControl::enumerate_controls(unsigned index) const
38 return target_speed.name.c_str();
41 for(--index;; ++index)
43 const char *ret = next_ctrl->enumerate_controls(index-1);
44 if(!ret || ret!=target_speed.name)
50 void AIControl::set_control(const string &n, float v)
52 if(n==target_speed.name)
54 if(v && !train.is_active())
55 train.set_active(true);
60 float approach_speed = 5*train.get_layout().get_catalogue().get_scale();
61 if(state==APPROACH && target_speed.value>approach_speed)
62 next_ctrl->set_control("speed", approach_speed);
64 next_ctrl->set_control("speed", target_speed.value);
67 signal_control_changed.emit(target_speed);
70 next_ctrl->set_control(n, v);
73 const Controller::Control &AIControl::get_control(const string &n) const
75 if(n==target_speed.name)
78 return next_ctrl->get_control(n);
81 float AIControl::get_speed() const
83 return next_ctrl->get_speed();
86 bool AIControl::get_reverse() const
88 return next_ctrl->get_reverse();
91 float AIControl::get_braking_distance() const
93 return next_ctrl->get_braking_distance();
96 void AIControl::tick(const Time::TimeDelta &dt)
98 float scale = train.get_layout().get_catalogue().get_scale();
99 float rsv_dist = train.get_reserved_distance();
100 float brake_dist = next_ctrl->get_braking_distance();
101 float approach_margin = 50*scale;
102 float approach_speed = 5*scale;
103 float margin = 1*scale;
105 State old_state = state;
107 if(state==FOLLOW && !train.get_preceding_train())
110 if(rsv_dist<brake_dist+margin)
112 else if(rsv_dist>brake_dist+margin*2 && rsv_dist<brake_dist*1.3+approach_margin)
114 else if(rsv_dist>brake_dist*1.3+approach_margin*2)
117 if(state==NORMAL && train.get_preceding_train())
120 if(state!=old_state || state==FOLLOW)
122 float speed_limit = -1;
125 else if(state==APPROACH)
126 speed_limit = approach_speed;
127 else if(state==FOLLOW && train.get_preceding_train()->is_active())
128 speed_limit = train.get_preceding_train()->get_speed();
130 if(speed_limit>=0 && target_speed.value>speed_limit)
131 next_ctrl->set_control("speed", speed_limit);
133 next_ctrl->set_control("speed", target_speed.value);
138 if(!target_speed.value && !next_ctrl->get_speed() && train.is_active())
139 train.set_active(false);
142 void AIControl::control_changed(const Control &ctrl)
144 if(ctrl.name!="speed")
145 signal_control_changed.emit(ctrl);
148 void AIControl::arrived()
150 set_control("speed", 0);