From 82a8a9aec25fd5b8b38cf3bfd8ea6dba5df2fb64 Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Fri, 7 Jul 2017 23:37:25 +0300 Subject: [PATCH 1/9] route length calculation --- simconvoi.cc | 14 ++++++++++++++ simconvoi.h | 3 +++ simline.cc | 1 + simline.h | 13 +++++++++++++ 4 files changed, 31 insertions(+) diff --git a/simconvoi.cc b/simconvoi.cc index c15454e..6f73345 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -163,6 +163,8 @@ void convoi_t::init(player_t *player) recalc_data_front = true; recalc_data = true; + + last_odometer_on_terminus = 0; } @@ -1195,6 +1197,8 @@ void convoi_t::step() // schedule window closed? if(schedule!=NULL && schedule->is_editing_finished()) { + last_odometer_on_terminus = 0; + set_schedule(schedule); schedule_target = koord3d::invalid; @@ -1565,6 +1569,14 @@ void convoi_t::ziel_erreicht() const vehicle_t* v = fahr[0]; alte_richtung = v->get_direction(); + if (line.is_bound() && schedule->get_current_stop() == 0) { + if (last_odometer_on_terminus > 0) { + sint64 new_route_length = total_distance_traveled - last_odometer_on_terminus; + line->update_route_length(new_route_length); + } + last_odometer_on_terminus = total_distance_traveled; + } + // check, what is at destination! const grund_t *gr = welt->lookup(v->get_pos()); depot_t *dp = gr->get_depot(); @@ -3435,6 +3447,8 @@ void convoi_t::check_pending_updates() wait_lock = 0; } } + + last_odometer_on_terminus = 0; } } diff --git a/simconvoi.h b/simconvoi.h index cba4c23..6a65ac3 100644 --- a/simconvoi.h +++ b/simconvoi.h @@ -292,6 +292,9 @@ private: sint32 sp_soll; // steps to go sint32 previous_delta_v; // Stores the previous delta_v value; otherwise these digits are lost during calculation and vehicle do not accelerate + // needed for vehicle unbunching. + sint64 last_odometer_on_terminus; //is resetted on line changed or when user intrudes in the shedule + uint32 next_wolke; // time to next smoke states state; diff --git a/simline.cc b/simline.cc index 235f605..244083b 100644 --- a/simline.cc +++ b/simline.cc @@ -43,6 +43,7 @@ simline_t::simline_t(player_t* player, linetype type) this->player = player; withdraw = false; state_color = SYSCOL_TEXT; + route_length = 0; create_schedule(); } diff --git a/simline.h b/simline.h index 34fc430..0c78cd8 100644 --- a/simline.h +++ b/simline.h @@ -28,6 +28,8 @@ #define LINE_WAYTOLL 8 // way toll paid by vehicles of line #define MAX_LINE_COST 9 // Total number of cost items +#define EXP_SMOOTH_COEFF 0.5 // Exponential smoothing coefficient. Used in route length estimation + class karte_ptr_t; class loadsave_t; class player_t; @@ -79,6 +81,11 @@ private: */ sint64 financial_history[MAX_MONTHS][MAX_LINE_COST]; + /* + * Estimate route length for vehicle unbunching + */ + sint64 route_length; + /** * creates empty schedule with type depending on line-type */ @@ -199,6 +206,12 @@ public: player_t *get_owner() const {return player;} + sint64 get_estimated_route_length() const { return route_length; } + + void update_route_length(sint64 new_length) { + route_length = EXP_SMOOTH_COEFF * new_length + (1 - EXP_SMOOTH_COEFF) * route_length; + } + }; #endif -- 2.7.4 From 45805f96865cc139d2e1c6f561708862c50756ab Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Mon, 10 Jul 2017 00:56:03 +0300 Subject: [PATCH 2/9] add unbunching feature. --- dataobj/schedule_entry.h | 8 ++++- gui/line_management_gui.cc | 23 +++++++++++-- gui/line_management_gui.h | 2 ++ gui/schedule_gui.cc | 7 ++++ gui/schedule_gui.h | 2 ++ simconvoi.cc | 81 ++++++++++++++++++++++++++++++++-------------- simconvoi.h | 5 ++- simline.cc | 5 ++- simline.h | 15 ++++++--- vehicle/simvehicle.cc | 17 +++++++++- vehicle/simvehicle.h | 3 ++ 11 files changed, 131 insertions(+), 37 deletions(-) diff --git a/dataobj/schedule_entry.h b/dataobj/schedule_entry.h index 8ffff04..431bcd0 100644 --- a/dataobj/schedule_entry.h +++ b/dataobj/schedule_entry.h @@ -15,7 +15,8 @@ public: schedule_entry_t(koord3d const& pos, uint const minimum_loading, sint8 const waiting_time_shift) : pos(pos), minimum_loading(minimum_loading), - waiting_time_shift(waiting_time_shift) + waiting_time_shift(waiting_time_shift), + last_departure_time(0) {} /** @@ -37,6 +38,11 @@ public: * @author prissi */ sint8 waiting_time_shift; + + /** + * unbunching: the time the last vehicle departured from here. + */ + uint32 last_departure_time; }; #endif diff --git a/gui/line_management_gui.cc b/gui/line_management_gui.cc index 9bb3430..f54d776 100644 --- a/gui/line_management_gui.cc +++ b/gui/line_management_gui.cc @@ -17,13 +17,18 @@ #include "line_management_gui.h" line_management_gui_t::line_management_gui_t(linehandle_t line, player_t* player_) : - schedule_gui_t(line->get_schedule()->copy(), player_, convoihandle_t() ) + schedule_gui_t(line->get_schedule()->copy(), player_, convoihandle_t() ) { - this->line = line; + this->line = line; // has this line a single running convoi? if( line->count_convoys() > 0 ) { reliefkarte_t::get_karte()->set_current_cnv( line->get_convoy(0) ); } + + unbunching_toggle.add_listener(this); + unbunching_toggle.pressed = line->is_unbunching(); + unbunching_toggle.set_visible(true); + show_line_selector(false); } @@ -117,5 +122,17 @@ void line_management_gui_t::rdwr(loadsave_t *file) schedule = old_schedule = NULL; line = linehandle_t(); destroy_win( this ); - } + } +} + +bool line_management_gui_t::action_triggered(gui_action_creator_t *komp, value_t p) { + if(komp == &unbunching_toggle) { + unbunching_toggle.pressed = !unbunching_toggle.pressed; + bool unbunch = unbunching_toggle.pressed; + if (line.is_bound()) { + line->set_unbunching(unbunch); + } + } + + return schedule_gui_t::action_triggered(komp, p); } diff --git a/gui/line_management_gui.h b/gui/line_management_gui.h index 37a93ac..cf79346 100644 --- a/gui/line_management_gui.h +++ b/gui/line_management_gui.h @@ -28,6 +28,8 @@ public: virtual void rdwr( loadsave_t *file ); virtual uint32 get_rdwr_id() { return magic_line_schedule_rdwr_dummy; } + bool action_triggered(gui_action_creator_t*, value_t) OVERRIDE; + private: linehandle_t line; diff --git a/gui/schedule_gui.cc b/gui/schedule_gui.cc index f6de90e..bb3bf04 100644 --- a/gui/schedule_gui.cc +++ b/gui/schedule_gui.cc @@ -346,6 +346,13 @@ schedule_gui_t::schedule_gui_t(schedule_t* schedule_, player_t* player_, convoih ypos += max(lb_waitlevel.get_size().h, bt_return.get_size().h); + unbunching_toggle.init(button_t::square_state, "Convoi unbunching on this line", scr_coord( BUTTON1_X, ypos )); + unbunching_toggle.set_tooltip("Enable/disable convoi unbunching on this line ('minimum load' and 'month wait time' will be ignored)"); + add_component(&unbunching_toggle); + unbunching_toggle.set_visible(false); + + ypos += D_BUTTON_HEIGHT+1; + bt_add.init(button_t::roundbox_state, "Add Stop", scr_coord(BUTTON1_X, ypos )); bt_add.set_tooltip("Appends stops at the end of the schedule"); bt_add.add_listener(this); diff --git a/gui/schedule_gui.h b/gui/schedule_gui.h index d96e501..d35a255 100644 --- a/gui/schedule_gui.h +++ b/gui/schedule_gui.h @@ -116,6 +116,8 @@ protected: linehandle_t new_line, old_line; + button_t unbunching_toggle; + public: static int entry_height; diff --git a/simconvoi.cc b/simconvoi.cc index 6f73345..5d6279e 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -164,7 +164,8 @@ void convoi_t::init(player_t *player) recalc_data_front = true; recalc_data = true; - last_odometer_on_terminus = 0; + last_ticks_on_terminus = 0; + end_unbunching_time = 0; } @@ -1197,7 +1198,7 @@ void convoi_t::step() // schedule window closed? if(schedule!=NULL && schedule->is_editing_finished()) { - last_odometer_on_terminus = 0; + last_ticks_on_terminus = 0; set_schedule(schedule); schedule_target = koord3d::invalid; @@ -1318,7 +1319,9 @@ void convoi_t::step() sint32 restart_speed = -1; if( fahr[0]->can_enter_tile( restart_speed, 0 ) ) { state = (steps_driven>=0) ? LEAVING_DEPOT : DRIVING; - } + } else { + fahr[0]->try_unblock_way(); + } if(restart_speed>=0) { akt_speed = restart_speed; } @@ -1570,11 +1573,13 @@ void convoi_t::ziel_erreicht() alte_richtung = v->get_direction(); if (line.is_bound() && schedule->get_current_stop() == 0) { - if (last_odometer_on_terminus > 0) { - sint64 new_route_length = total_distance_traveled - last_odometer_on_terminus; - line->update_route_length(new_route_length); + if (last_ticks_on_terminus > 0) { + uint32 new_route_time = welt->get_ticks() - last_ticks_on_terminus; + line->update_route_time(new_route_time); + fprintf(stdout, "%s: new_route_time: %d\n", get_name(), new_route_time); + fflush(stdout); } - last_odometer_on_terminus = total_distance_traveled; + last_ticks_on_terminus = welt->get_ticks(); } // check, what is at destination! @@ -1603,6 +1608,20 @@ void convoi_t::ziel_erreicht() halt->book(1, HALT_CONVOIS_ARRIVED); state = LOADING; arrived_time = welt->get_ticks(); + + //Needs unbunching? + if (line.is_bound() && line->is_unbunching()) { + uint32 last_departured_from_here = line->get_schedule()->entries[schedule->get_current_stop()].last_departure_time; + uint32 target_interval = line->get_estimated_route_time() / line->count_convoys(); + uint32 actual_interval = arrived_time - last_departured_from_here; + fprintf(stdout, "%s: curr_stop: %d; arrived_time: %d, last_arrived_here: %d; t: %d\n", get_name(), schedule->get_current_stop(), arrived_time, last_departured_from_here, target_interval); + if (actual_interval < target_interval * 0.9) { + uint32 unbunching_time = welt->get_ticks() + target_interval - actual_interval; + reset_unbunching_time(unbunching_time); + fprintf(stdout, "Unbunching (time: %d)!\n", unbunching_time); + } + fflush(stdout); + } } else { // Neither depot nor station: waypoint @@ -2982,26 +3001,38 @@ station_tile_search_ready: ; } // loading is finished => maybe drive on - if( loading_level >= loading_limit || no_load - || (schedule->get_current_entry().waiting_time_shift > 0 && welt->get_ticks() - arrived_time > (welt->ticks_per_world_month >> (16 - schedule->get_current_entry().waiting_time_shift)) ) ) { + bool proceed = false; + if ((line.is_bound() && line->is_unbunching()) ) { + proceed = end_unbunching_time < welt->get_ticks() || loading_level == 100; // Stop unbunching when full loaded + } else { + //'Wait for load' is ignored when in unbunching mode + proceed = loading_level >= loading_limit + || (schedule->get_current_entry().waiting_time_shift > 0 && welt->get_ticks() - arrived_time > (welt->ticks_per_world_month >> (16 - schedule->get_current_entry().waiting_time_shift)) ); + } + proceed |= no_load; - if( withdraw && (loading_level == 0 || goods_catg_index.empty()) ) { - // destroy when empty - self_destruct(); - return; - } + if(proceed) { + if (line.is_bound()) + line->get_schedule()->entries[schedule->get_current_stop()].last_departure_time = welt->get_ticks(); - calc_speedbonus_kmh(); + if( withdraw && (loading_level == 0 || goods_catg_index.empty()) ) { + // destroy when empty + self_destruct(); + return; + } - // add available capacity after loading(!) to statistics - for (unsigned i = 0; iget_cargo_max()-get_vehikel(i)->get_total_cargo(), CONVOI_CAPACITY); - } + calc_speedbonus_kmh(); + + // add available capacity after loading(!) to statistics + for (unsigned i = 0; iget_cargo_max()-get_vehikel(i)->get_total_cargo(), CONVOI_CAPACITY); + } + + // Advance schedule + schedule->advance(); + state = ROUTING_1; + loading_limit = 0; - // Advance schedule - schedule->advance(); - state = ROUTING_1; - loading_limit = 0; } INT_CHECK( "convoi_t::hat_gehalten" ); @@ -3448,7 +3479,7 @@ void convoi_t::check_pending_updates() } } - last_odometer_on_terminus = 0; + last_ticks_on_terminus = 0; } } @@ -3799,7 +3830,7 @@ bool convoi_t::can_overtake(overtaker_t *other_overtaker, sint32 other_speed, si set_tiles_overtaking( 1+n_tiles ); other_overtaker->set_tiles_overtaking( -1-(n_tiles*(akt_speed-diff_speed))/akt_speed ); - return true; + return true; } diff --git a/simconvoi.h b/simconvoi.h index 6a65ac3..34163e1 100644 --- a/simconvoi.h +++ b/simconvoi.h @@ -293,7 +293,8 @@ private: sint32 previous_delta_v; // Stores the previous delta_v value; otherwise these digits are lost during calculation and vehicle do not accelerate // needed for vehicle unbunching. - sint64 last_odometer_on_terminus; //is resetted on line changed or when user intrudes in the shedule + sint64 last_ticks_on_terminus; //is resetted on line changed or when user intrudes the shedule + uint32 end_unbunching_time; uint32 next_wolke; // time to next smoke @@ -887,6 +888,8 @@ public: // Overtaking for convois virtual bool can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other); + + void reset_unbunching_time(uint32 new_time = 0) { end_unbunching_time = new_time; } }; #endif diff --git a/simline.cc b/simline.cc index 244083b..6f5f9f0 100644 --- a/simline.cc +++ b/simline.cc @@ -43,7 +43,8 @@ simline_t::simline_t(player_t* player, linetype type) this->player = player; withdraw = false; state_color = SYSCOL_TEXT; - route_length = 0; + route_time = 0; + unbunching = type == truckline? true : false; create_schedule(); } @@ -58,6 +59,8 @@ simline_t::simline_t(player_t* player, linetype type, loadsave_t *file) withdraw = false; create_schedule(); rdwr(file); + route_time = 0; + unbunching = type == truckline? true : false; // now self has the right id but the this-pointer is not assigned to the quickstone handle yet // do this explicitly // some savegames have line_id=0, resolve that in finish_rd diff --git a/simline.h b/simline.h index 0c78cd8..f4638e4 100644 --- a/simline.h +++ b/simline.h @@ -82,9 +82,11 @@ private: sint64 financial_history[MAX_MONTHS][MAX_LINE_COST]; /* - * Estimate route length for vehicle unbunching + * Estimated route total time for vehicle unbunching */ - sint64 route_length; + sint64 route_time; + + bool unbunching; /** * creates empty schedule with type depending on line-type @@ -206,12 +208,15 @@ public: player_t *get_owner() const {return player;} - sint64 get_estimated_route_length() const { return route_length; } + sint64 get_estimated_route_time() const { return route_time; } - void update_route_length(sint64 new_length) { - route_length = EXP_SMOOTH_COEFF * new_length + (1 - EXP_SMOOTH_COEFF) * route_length; + void update_route_time(sint64 new_length) { + route_time = EXP_SMOOTH_COEFF * new_length + (1 - EXP_SMOOTH_COEFF) * route_time; } + bool is_unbunching() const { return unbunching; } + void set_unbunching(bool unbunch) {unbunching = unbunch; } + }; #endif diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index 0016d89..5062643 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -529,7 +529,7 @@ sint16 vehicle_base_t::get_hoff(const sint16 raster_width) const */ vehicle_base_t *vehicle_base_t::no_cars_blocking( const grund_t *gr, const convoi_t *cnv, const uint8 current_direction, const uint8 next_direction, const uint8 next_90direction ) { - // Search vehicle + // Search vehicle for( uint8 pos=1; pos<(volatile uint8)gr->get_top(); pos++ ) { if( vehicle_base_t* const v = obj_cast(gr->obj_bei(pos)) ) { if( v->get_typ()==obj_t::pedestrian ) { @@ -4290,3 +4290,18 @@ const char *air_vehicle_t::is_deletable(const player_t *player) } return NULL; } + +void vehicle_t::try_unblock_way() { + grund_t *gr = welt->lookup( pos_next ); + route_t const& r = *cnv->get_route(); + koord3d next = route_index < r.get_count() - 1u ? r.at(route_index + 1u) : pos_next; + ribi_t::ribi curr_direction = get_direction(); + ribi_t::ribi next_direction = calc_direction(get_pos(), next); + ribi_t::ribi next_90direction = calc_direction(pos_next, next); + vehicle_base_t *obj = no_cars_blocking( gr, cnv, curr_direction, next_direction, next_90direction ); + vehicle_t *v = obj_cast(obj); + + if (v && v->get_typ() == get_typ() && v->get_convoi()->get_state() == convoi_t::LOADING) { + v->get_convoi()->reset_unbunching_time(); + } +} diff --git a/vehicle/simvehicle.h b/vehicle/simvehicle.h index 66db6b5..a86aaf2 100644 --- a/vehicle/simvehicle.h +++ b/vehicle/simvehicle.h @@ -472,6 +472,9 @@ public: #else virtual void display_after(int xpos, int ypos, bool dirty) const; #endif + + //Tries to unblock way in case there are vehicle waiting for unbunching and blocking your way + void try_unblock_way(); }; -- 2.7.4 From c567af1ecd05a26a69651811005056fbcfeede76 Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Mon, 10 Jul 2017 02:04:28 +0300 Subject: [PATCH 3/9] Add read/write to savegame --- gui/line_management_gui.cc | 8 +++++--- simconvoi.cc | 2 +- simline.cc | 11 ++++++++--- simversion.h | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/gui/line_management_gui.cc b/gui/line_management_gui.cc index f54d776..00b8318 100644 --- a/gui/line_management_gui.cc +++ b/gui/line_management_gui.cc @@ -25,9 +25,11 @@ line_management_gui_t::line_management_gui_t(linehandle_t line, player_t* player reliefkarte_t::get_karte()->set_current_cnv( line->get_convoy(0) ); } - unbunching_toggle.add_listener(this); - unbunching_toggle.pressed = line->is_unbunching(); - unbunching_toggle.set_visible(true); + if (line->get_linetype() == simline_t::truckline) { + unbunching_toggle.add_listener(this); + unbunching_toggle.pressed = line->is_unbunching(); + unbunching_toggle.set_visible(true); + } show_line_selector(false); } diff --git a/simconvoi.cc b/simconvoi.cc index 5d6279e..cdc7e90 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -1615,7 +1615,7 @@ void convoi_t::ziel_erreicht() uint32 target_interval = line->get_estimated_route_time() / line->count_convoys(); uint32 actual_interval = arrived_time - last_departured_from_here; fprintf(stdout, "%s: curr_stop: %d; arrived_time: %d, last_arrived_here: %d; t: %d\n", get_name(), schedule->get_current_stop(), arrived_time, last_departured_from_here, target_interval); - if (actual_interval < target_interval * 0.9) { + if (actual_interval < target_interval * 0.8) { uint32 unbunching_time = welt->get_ticks() + target_interval - actual_interval; reset_unbunching_time(unbunching_time); fprintf(stdout, "Unbunching (time: %d)!\n", unbunching_time); diff --git a/simline.cc b/simline.cc index 6f5f9f0..c6cf874 100644 --- a/simline.cc +++ b/simline.cc @@ -44,7 +44,7 @@ simline_t::simline_t(player_t* player, linetype type) withdraw = false; state_color = SYSCOL_TEXT; route_time = 0; - unbunching = type == truckline? true : false; + unbunching = false; create_schedule(); } @@ -57,10 +57,12 @@ simline_t::simline_t(player_t* player, linetype type, loadsave_t *file) this->schedule = NULL; this->player = player; withdraw = false; + unbunching = false; + route_time = 0; + create_schedule(); rdwr(file); - route_time = 0; - unbunching = type == truckline? true : false; + // now self has the right id but the this-pointer is not assigned to the quickstone handle yet // do this explicitly // some savegames have line_id=0, resolve that in finish_rd @@ -277,6 +279,9 @@ void simline_t::rdwr(loadsave_t *file) if(file->get_version()>=102002) { file->rdwr_bool(withdraw); } + if(file->get_version()>=120006) { + file->rdwr_bool(unbunching); + } // otherwise initialized to zero if loading ... financial_history[0][LINE_CONVOIS] = count_convoys(); diff --git a/simversion.h b/simversion.h index 604790d..db7bdb6 100644 --- a/simversion.h +++ b/simversion.h @@ -17,7 +17,7 @@ // Beware: SAVEGAME minor is often ahead of version minor when there were patches. // ==> These have no direct connection at all! -#define SIM_SAVE_MINOR 5 +#define SIM_SAVE_MINOR 6 #define SIM_SERVER_MINOR 6 // NOTE: increment before next release to enable save/load of new features -- 2.7.4 From e8acb88a4e92d47ca2b8a7cc3a823bc7efefda89 Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Wed, 12 Jul 2017 00:23:06 +0300 Subject: [PATCH 4/9] add unblocking way if unbunching convoi is clogging the way --- simconvoi.cc | 21 ++++++++++++--------- simconvoi.h | 2 +- simline.cc | 4 ++-- simline.h | 10 +++++----- vehicle/simvehicle.cc | 30 ++++++++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/simconvoi.cc b/simconvoi.cc index cdc7e90..56f17df 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -164,7 +164,7 @@ void convoi_t::init(player_t *player) recalc_data_front = true; recalc_data = true; - last_ticks_on_terminus = 0; + last_length_on_terminus = 0; end_unbunching_time = 0; } @@ -1198,7 +1198,7 @@ void convoi_t::step() // schedule window closed? if(schedule!=NULL && schedule->is_editing_finished()) { - last_ticks_on_terminus = 0; + last_length_on_terminus = 0; set_schedule(schedule); schedule_target = koord3d::invalid; @@ -1573,13 +1573,13 @@ void convoi_t::ziel_erreicht() alte_richtung = v->get_direction(); if (line.is_bound() && schedule->get_current_stop() == 0) { - if (last_ticks_on_terminus > 0) { - uint32 new_route_time = welt->get_ticks() - last_ticks_on_terminus; - line->update_route_time(new_route_time); - fprintf(stdout, "%s: new_route_time: %d\n", get_name(), new_route_time); + if (last_length_on_terminus > 0) { + uint32 new_route_length = total_distance_traveled - last_length_on_terminus; + line->update_route_length(new_route_length); + fprintf(stdout, "%s: new_route_time: %d\n", get_name(), new_route_length); fflush(stdout); } - last_ticks_on_terminus = welt->get_ticks(); + last_length_on_terminus = total_distance_traveled; } // check, what is at destination! @@ -1612,7 +1612,10 @@ void convoi_t::ziel_erreicht() //Needs unbunching? if (line.is_bound() && line->is_unbunching()) { uint32 last_departured_from_here = line->get_schedule()->entries[schedule->get_current_stop()].last_departure_time; - uint32 target_interval = line->get_estimated_route_time() / line->count_convoys(); + uint64 target_interval_length = (line->get_estimated_route_length() << YARDS_PER_TILE_SHIFT) / line->count_convoys(); + uint32 target_interval = 0; + if (line->get_finance_history(1, LINE_MAXSPEED) != 0) + target_interval = target_interval_length/kmh_to_speed(line->get_finance_history(1, LINE_MAXSPEED)); uint32 actual_interval = arrived_time - last_departured_from_here; fprintf(stdout, "%s: curr_stop: %d; arrived_time: %d, last_arrived_here: %d; t: %d\n", get_name(), schedule->get_current_stop(), arrived_time, last_departured_from_here, target_interval); if (actual_interval < target_interval * 0.8) { @@ -3479,7 +3482,7 @@ void convoi_t::check_pending_updates() } } - last_ticks_on_terminus = 0; + last_length_on_terminus = 0; } } diff --git a/simconvoi.h b/simconvoi.h index 34163e1..38b0393 100644 --- a/simconvoi.h +++ b/simconvoi.h @@ -293,7 +293,7 @@ private: sint32 previous_delta_v; // Stores the previous delta_v value; otherwise these digits are lost during calculation and vehicle do not accelerate // needed for vehicle unbunching. - sint64 last_ticks_on_terminus; //is resetted on line changed or when user intrudes the shedule + sint64 last_length_on_terminus; //is resetted on line changed or when user intrudes the shedule uint32 end_unbunching_time; uint32 next_wolke; // time to next smoke diff --git a/simline.cc b/simline.cc index c6cf874..a59f5b7 100644 --- a/simline.cc +++ b/simline.cc @@ -43,7 +43,7 @@ simline_t::simline_t(player_t* player, linetype type) this->player = player; withdraw = false; state_color = SYSCOL_TEXT; - route_time = 0; + route_length = 0; unbunching = false; create_schedule(); } @@ -58,7 +58,7 @@ simline_t::simline_t(player_t* player, linetype type, loadsave_t *file) this->player = player; withdraw = false; unbunching = false; - route_time = 0; + route_length = 0; create_schedule(); rdwr(file); diff --git a/simline.h b/simline.h index f4638e4..1e09ff6 100644 --- a/simline.h +++ b/simline.h @@ -82,9 +82,9 @@ private: sint64 financial_history[MAX_MONTHS][MAX_LINE_COST]; /* - * Estimated route total time for vehicle unbunching + * Estimated route total length (in tiles) for vehicle unbunching */ - sint64 route_time; + uint64 route_length; bool unbunching; @@ -208,10 +208,10 @@ public: player_t *get_owner() const {return player;} - sint64 get_estimated_route_time() const { return route_time; } + uint64 get_estimated_route_length() const { return route_length; } - void update_route_time(sint64 new_length) { - route_time = EXP_SMOOTH_COEFF * new_length + (1 - EXP_SMOOTH_COEFF) * route_time; + void update_route_length(uint64 new_length) { + route_length = EXP_SMOOTH_COEFF * new_length + (1 - EXP_SMOOTH_COEFF) * route_length; } bool is_unbunching() const { return unbunching; } diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index 5062643..f72aae9 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -4292,16 +4292,46 @@ const char *air_vehicle_t::is_deletable(const player_t *player) } void vehicle_t::try_unblock_way() { + + uint32 test_index = route_index + 1u; + grund_t *gr = welt->lookup( pos_next ); route_t const& r = *cnv->get_route(); koord3d next = route_index < r.get_count() - 1u ? r.at(route_index + 1u) : pos_next; ribi_t::ribi curr_direction = get_direction(); + //ribi_t::ribi curr_90direction = calc_direction(get_pos(), pos_next); ribi_t::ribi next_direction = calc_direction(get_pos(), next); ribi_t::ribi next_90direction = calc_direction(pos_next, next); vehicle_base_t *obj = no_cars_blocking( gr, cnv, curr_direction, next_direction, next_90direction ); + + int ct = 0; + while (!obj && ct < 4) { + + gr = welt->lookup(r.at(test_index)); + curr_direction = next_direction; + //curr_90direction = next_90direction; + if( test_index + 1u < r.get_count() ) { + next = r.at(test_index + 1u); + next_direction = calc_direction(r.at(test_index - 1u), next); + next_90direction = calc_direction(r.at(test_index), next); + obj = no_cars_blocking( gr, cnv, curr_direction, next_direction, next_90direction ); + } else { + next = r.at(test_index); + next_90direction = calc_direction(r.at(test_index - 1u), next); + if( curr_direction == next_90direction || !gr->is_halt() ) { + // check cars but allow to enter intersection if we are turning even when a car is blocking the halt on the last tile of our route + // preserves old bus terminal behaviour + obj = no_cars_blocking( gr, cnv, curr_direction, next_90direction, ribi_t::none ); + } + } + + ct++; + } + vehicle_t *v = obj_cast(obj); if (v && v->get_typ() == get_typ() && v->get_convoi()->get_state() == convoi_t::LOADING) { v->get_convoi()->reset_unbunching_time(); } + } -- 2.7.4 From a57ef78194563e5b776c716879bce409a0d16ee4 Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Wed, 12 Jul 2017 00:55:46 +0300 Subject: [PATCH 5/9] fix crash --- vehicle/simvehicle.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index f72aae9..db8b290 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -4305,7 +4305,7 @@ void vehicle_t::try_unblock_way() { vehicle_base_t *obj = no_cars_blocking( gr, cnv, curr_direction, next_direction, next_90direction ); int ct = 0; - while (!obj && ct < 4) { + while (!obj && ct < 4 && test_index < r.get_count()) { gr = welt->lookup(r.at(test_index)); curr_direction = next_direction; @@ -4326,8 +4326,10 @@ void vehicle_t::try_unblock_way() { } ct++; + test_index++; } + vehicle_t *v = obj_cast(obj); if (v && v->get_typ() == get_typ() && v->get_convoi()->get_state() == convoi_t::LOADING) { -- 2.7.4 From 9a9a56aef1453c366e2201056479be2d332ce912 Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Wed, 12 Jul 2017 22:47:32 +0300 Subject: [PATCH 6/9] add unbunching of trains --- gui/line_management_gui.cc | 2 +- vehicle/simvehicle.cc | 24 +++++++++++++++++++++++- vehicle/simvehicle.h | 6 +++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/gui/line_management_gui.cc b/gui/line_management_gui.cc index 00b8318..9a47e60 100644 --- a/gui/line_management_gui.cc +++ b/gui/line_management_gui.cc @@ -25,7 +25,7 @@ line_management_gui_t::line_management_gui_t(linehandle_t line, player_t* player reliefkarte_t::get_karte()->set_current_cnv( line->get_convoy(0) ); } - if (line->get_linetype() == simline_t::truckline) { + if (line->get_linetype() != simline_t::shipline || line->get_linetype() != simline_t::airline) { unbunching_toggle.add_listener(this); unbunching_toggle.pressed = line->is_unbunching(); unbunching_toggle.set_visible(true); diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index db8b290..064f859 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -4291,7 +4291,7 @@ const char *air_vehicle_t::is_deletable(const player_t *player) return NULL; } -void vehicle_t::try_unblock_way() { +void road_vehicle_t::try_unblock_way() { uint32 test_index = route_index + 1u; @@ -4337,3 +4337,25 @@ void vehicle_t::try_unblock_way() { } } + +void rail_vehicle_t::try_unblock_way() { + //We're waiting at the signal for free way. So, we look at the + //reservation block and if there some train - we want it to stop unbunching and + //to proceed. + uint32 test_index = route_index; + route_t const &r = *cnv->get_route(); + for (; test_index < r.get_count(); test_index++) { + grund_t *gr = welt->lookup(r.at(test_index)); + schiene_t *sch1 = gr ? (schiene_t *)gr->get_weg(get_waytype()) : NULL; + if (!sch1) + break; + + if (sch1->is_reserved()) { + sch1->get_reserved_convoi()->reset_unbunching_time(); + break; + } + + if (sch1->has_signal()) + break; + } +} diff --git a/vehicle/simvehicle.h b/vehicle/simvehicle.h index a86aaf2..798bfce 100644 --- a/vehicle/simvehicle.h +++ b/vehicle/simvehicle.h @@ -474,7 +474,7 @@ public: #endif //Tries to unblock way in case there are vehicle waiting for unbunching and blocking your way - void try_unblock_way(); + virtual void try_unblock_way() { /* Should be implemented in sub-classes. */} }; @@ -535,6 +535,8 @@ public: schedule_t * generate_new_schedule() const; virtual overtaker_t* get_overtaker(); + + virtual void try_unblock_way() OVERRIDE; }; @@ -589,6 +591,8 @@ public: virtual void set_convoi(convoi_t *c); virtual schedule_t * generate_new_schedule() const; + + virtual void try_unblock_way() OVERRIDE; }; -- 2.7.4 From 5a8c12375de92839dce22a7e89b8e4526ab31153 Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Thu, 20 Jul 2017 20:14:15 +0300 Subject: [PATCH 7/9] Save route_length because it tooks very long time to recalc route_length on long routes --- simconvoi.cc | 2 +- simline.cc | 1 + simline.h | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/simconvoi.cc b/simconvoi.cc index 56f17df..4840006 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -1612,7 +1612,7 @@ void convoi_t::ziel_erreicht() //Needs unbunching? if (line.is_bound() && line->is_unbunching()) { uint32 last_departured_from_here = line->get_schedule()->entries[schedule->get_current_stop()].last_departure_time; - uint64 target_interval_length = (line->get_estimated_route_length() << YARDS_PER_TILE_SHIFT) / line->count_convoys(); + uint64 target_interval_length = ((uint64)line->get_estimated_route_length() << YARDS_PER_TILE_SHIFT) / line->count_convoys(); uint32 target_interval = 0; if (line->get_finance_history(1, LINE_MAXSPEED) != 0) target_interval = target_interval_length/kmh_to_speed(line->get_finance_history(1, LINE_MAXSPEED)); diff --git a/simline.cc b/simline.cc index a59f5b7..44b84e4 100644 --- a/simline.cc +++ b/simline.cc @@ -281,6 +281,7 @@ void simline_t::rdwr(loadsave_t *file) } if(file->get_version()>=120006) { file->rdwr_bool(unbunching); + file->rdwr_long(route_length); } // otherwise initialized to zero if loading ... diff --git a/simline.h b/simline.h index 1e09ff6..0fa26eb 100644 --- a/simline.h +++ b/simline.h @@ -84,7 +84,7 @@ private: /* * Estimated route total length (in tiles) for vehicle unbunching */ - uint64 route_length; + uint32 route_length; bool unbunching; @@ -208,9 +208,9 @@ public: player_t *get_owner() const {return player;} - uint64 get_estimated_route_length() const { return route_length; } + uint32 get_estimated_route_length() const { return route_length; } - void update_route_length(uint64 new_length) { + void update_route_length(uint32 new_length) { route_length = EXP_SMOOTH_COEFF * new_length + (1 - EXP_SMOOTH_COEFF) * route_length; } -- 2.7.4 From e6d1f285e701f6f4186fbf7b80d94a120925c2cb Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Sun, 23 Jul 2017 15:33:30 +0300 Subject: [PATCH 8/9] comment out debug output --- simconvoi.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/simconvoi.cc b/simconvoi.cc index 4840006..4cdff79 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -1576,8 +1576,8 @@ void convoi_t::ziel_erreicht() if (last_length_on_terminus > 0) { uint32 new_route_length = total_distance_traveled - last_length_on_terminus; line->update_route_length(new_route_length); - fprintf(stdout, "%s: new_route_time: %d\n", get_name(), new_route_length); - fflush(stdout); +// fprintf(stdout, "%s: new_route_time: %d\n", get_name(), new_route_length); +// fflush(stdout); } last_length_on_terminus = total_distance_traveled; } @@ -1617,13 +1617,13 @@ void convoi_t::ziel_erreicht() if (line->get_finance_history(1, LINE_MAXSPEED) != 0) target_interval = target_interval_length/kmh_to_speed(line->get_finance_history(1, LINE_MAXSPEED)); uint32 actual_interval = arrived_time - last_departured_from_here; - fprintf(stdout, "%s: curr_stop: %d; arrived_time: %d, last_arrived_here: %d; t: %d\n", get_name(), schedule->get_current_stop(), arrived_time, last_departured_from_here, target_interval); + //fprintf(stdout, "%s: curr_stop: %d; arrived_time: %d, last_arrived_here: %d; t: %d\n", get_name(), schedule->get_current_stop(), arrived_time, last_departured_from_here, target_interval); if (actual_interval < target_interval * 0.8) { uint32 unbunching_time = welt->get_ticks() + target_interval - actual_interval; reset_unbunching_time(unbunching_time); - fprintf(stdout, "Unbunching (time: %d)!\n", unbunching_time); + //fprintf(stdout, "Unbunching (time: %d)!\n", unbunching_time); } - fflush(stdout); + //fflush(stdout); } } else { -- 2.7.4 From 0f8256c1610f5371d734d26848f73f210d3b9b04 Mon Sep 17 00:00:00 2001 From: Denis Malkin Date: Sun, 23 Jul 2017 15:38:09 +0300 Subject: [PATCH 9/9] fix disable line unbunching for ships and air --- gui/line_management_gui.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/line_management_gui.cc b/gui/line_management_gui.cc index 9a47e60..d20fd74 100644 --- a/gui/line_management_gui.cc +++ b/gui/line_management_gui.cc @@ -25,7 +25,7 @@ line_management_gui_t::line_management_gui_t(linehandle_t line, player_t* player reliefkarte_t::get_karte()->set_current_cnv( line->get_convoy(0) ); } - if (line->get_linetype() != simline_t::shipline || line->get_linetype() != simline_t::airline) { + if (line->get_linetype() != simline_t::shipline && line->get_linetype() != simline_t::airline) { unbunching_toggle.add_listener(this); unbunching_toggle.pressed = line->is_unbunching(); unbunching_toggle.set_visible(true); -- 2.7.4