X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Faicontrol.cpp;h=f1f16bf1850a511c25059aa247356ec4445fbcee;hb=d0881a98a6240758ac1aeceaa9443d718ab1ad5c;hp=c2f16e38a898a0efbdc702bdfe14fabbe84d82dd;hpb=1ff06c5bc46a677fa389ef86c6b26664368f1653;p=r2c2.git diff --git a/source/libr2c2/aicontrol.cpp b/source/libr2c2/aicontrol.cpp index c2f16e3..f1f16bf 100644 --- a/source/libr2c2/aicontrol.cpp +++ b/source/libr2c2/aicontrol.cpp @@ -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,115 +8,105 @@ using namespace Msp; namespace R2C2 { -AIControl::AIControl(Train &t, Controller *n): - train(t), - next_ctrl(n), - target_speed(Control::continuous("speed", 0, 1000)), - blocked(false), - approach(false) +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)); } -void AIControl::set_control(const string &n, float v) +void AIControl::set_reverse(bool r) { - if(n=="speed") + pending_reverse = r; + 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(!blocked) - { - float approach_speed = 5*train.get_layout().get_catalogue().get_scale(); - if(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 +void AIControl::message(const Message &msg) { - if(n=="speed") - return target_speed; - else - return next_ctrl->get_control(n); + if(msg.type=="set-target-speed") + set_target_speed(msg.value.value()); + else if(msg.type=="set-reverse") + set_reverse(msg.value.value()); + else if(msg.type=="toggle-reverse") + set_reverse(!reverse); } -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 -{ - return next_ctrl->get_braking_distance(); -} - -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; - if(!blocked && rsv_distset_control("speed", 0); - } - else if((!approach && rsv_distbrake_dist+margin*2)) + State old_state = state; + + if(state==FOLLOW && !train.get_preceding_train()) + state = NORMAL; + + if(rsv_distbrake_dist+margin*2 && rsv_distbrake_dist*1.3+approach_margin*2) + state = NORMAL; + + if(state==NORMAL && train.get_preceding_train()) + state = FOLLOW; + + if(state!=old_state || state==FOLLOW || need_update) { - 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 && train.get_preceding_train()->get_block_allocator().is_active()) + speed_limit = train.get_preceding_train()->get_speed(); + + 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); + + need_update = false; } - else if((blocked || approach) && rsv_dist>brake_dist*1.3+approach_margin*2) + + if(pending_reverse!=reverse && !train.get_controller().get_speed()) { - blocked = false; - approach = false; - next_ctrl->set_control("speed", target_speed.value); + reverse = pending_reverse; + train.set_control("reverse", reverse); } - - next_ctrl->tick(dt); - - if(!target_speed.value && !next_ctrl->get_speed() && train.is_active()) - train.set_active(false); } -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