1 #ifndef schedule_h
2 #define schedule_h
3 
4 #include "schedule_entry.h"
5 
6 #include "../halthandle_t.h"
7 
8 #include "../tpl/minivec_tpl.h"
9 
10 
11 class cbuffer_t;
12 class grund_t;
13 class player_t;
14 class karte_t;
15 
16 
17 /**
18  * Class to hold schedule of vehicles in Simutrans.
19  *
20  * @author Hj. Malthaner
21  */
22 class schedule_t
23 {
24 	bool  editing_finished;
25 	uint8 current_stop;
26 
27 	static schedule_entry_t dummy_entry;
28 
29 	/**
30 	 * Fix up current_stop value, which we may have made out of range
31 	 * @author neroden
32 	 */
make_current_stop_valid()33 	void make_current_stop_valid() {
34 		uint8 count = entries.get_count();
35 		if(  count == 0  ) {
36 			current_stop = 0;
37 		}
38 		else if(  current_stop >= count  ) {
39 			current_stop = count-1;
40 		}
41 	}
42 
43 protected:
schedule_t()44 	schedule_t() : editing_finished(false), current_stop(0) {}
45 
46 public:
47 	enum schedule_type {
48 		schedule = 0, truck_schedule = 1, train_schedule = 2, ship_schedule = 3, airplane_schedule = 4, monorail_schedule = 5, tram_schedule = 6, maglev_schedule = 7, narrowgauge_schedule = 8,
49 	};
50 
51 	minivec_tpl<schedule_entry_t> entries;
52 
53 	/**
54 	 * Returns error message if stops are not allowed
55 	 * @author Hj. Malthaner
56 	 */
57 	virtual char const* get_error_msg() const = 0;
58 
59 	/**
60 	 * Returns true if this schedule allows stop at the
61 	 * given tile.
62 	 * @author Hj. Malthaner
63 	 */
64 	bool is_stop_allowed(const grund_t *gr) const;
65 
empty()66 	bool empty() const { return entries.empty(); }
67 
get_count()68 	uint8 get_count() const { return entries.get_count(); }
69 
70 	virtual schedule_type get_type() const = 0;
71 
72 	virtual waytype_t get_waytype() const = 0;
73 
74 	/**
75 	 * Get current stop of the schedule.
76 	 * @author hsiegeln
77 	 */
get_current_stop()78 	uint8 get_current_stop() const { return current_stop; }
79 
80 	/// returns the current stop, always a valid entry
get_current_entry()81 	schedule_entry_t const& get_current_entry() const { return current_stop >= entries.get_count() ? dummy_entry : entries[current_stop]; }
82 
83 	/**
84 	 * Set the current stop of the schedule .
85 	 * If new value is bigger than stops available, the max stop will be used.
86 	 * @author hsiegeln
87 	 */
set_current_stop(uint8 new_current_stop)88 	void set_current_stop(uint8 new_current_stop) {
89 		current_stop = new_current_stop;
90 		make_current_stop_valid();
91 	}
92 
93 	/// advance current_stop by one
advance()94 	void advance() {
95 		if(  !entries.empty()  ) {
96 			current_stop = (current_stop+1)%entries.get_count();
97 		}
98 	}
99 
is_editing_finished()100 	inline bool is_editing_finished() const { return editing_finished; }
finish_editing()101 	void finish_editing() { editing_finished = true; }
start_editing()102 	void start_editing() { editing_finished = false; }
103 
~schedule_t()104 	virtual ~schedule_t() {}
105 
106 	/**
107 	 * returns a halthandle for the next halt in the schedule (or unbound)
108 	 */
109 	halthandle_t get_next_halt( player_t *player, halthandle_t halt ) const;
110 
111 	/**
112 	 * returns a halthandle for the previous halt in the schedule (or unbound)
113 	 */
114 	halthandle_t get_prev_halt( player_t *player ) const;
115 
116 	/**
117 	 * Inserts a coordinate at current_stop into the schedule.
118 	 */
119 	bool insert(const grund_t* gr, uint8 minimum_loading = 0, uint8 waiting_time_shift = 0);
120 
121 	/**
122 	 * Appends a coordinate to the schedule.
123 	 */
124 	bool append(const grund_t* gr, uint8 minimum_loading = 0, uint8 waiting_time_shift = 0);
125 
126 	/**
127 	 * Cleanup a schedule, removes double entries.
128 	 */
129 	void cleanup();
130 
131 	/**
132 	 * Remove current_stop entry from the schedule.
133 	 */
134 	bool remove();
135 
136 	void rdwr(loadsave_t *file);
137 
138 	void rotate90( sint16 y_size );
139 
140 	/**
141 	 * if the passed in schedule matches "this", then return true
142 	 * @author hsiegeln
143 	 */
144 	bool matches(karte_t *welt, const schedule_t *schedule);
145 
146 	/**
147 	 * Compare this schedule with another, ignoring order and exact positions and waypoints.
148 	 * @author prissi
149 	 */
150 	bool similar( const schedule_t *schedule, const player_t *player );
151 
152 	/**
153 	 * Calculates a return way for this schedule.
154 	 * Will add elements 1 to end in reverse order to schedule.
155 	 * @author hsiegeln
156 	 */
157 	void add_return_way();
158 
159 	virtual schedule_t* copy() = 0;//{ return new schedule_t(this); }
160 
161 	// copy all entries from schedule src to this and adjusts current_stop
162 	void copy_from(const schedule_t *src);
163 
164 	// fills the given buffer with a schedule
165 	void sprintf_schedule( cbuffer_t &buf ) const;
166 
167 	// converts this string into a schedule
168 	bool sscanf_schedule( const char * );
169 
170 	/**
171 	 * Append description of entry to buf.
172 	 * If @p max_chars > 0 then append short version, without loading level and position.
173 	 */
174 	static void gimme_stop_name(cbuffer_t& buf, karte_t* welt, player_t const* player_, schedule_entry_t const& entry, int max_chars);
175 };
176 
177 
178 /**
179  * Schedules with stops on tracks.
180  *
181  * @author Hj. Malthaner
182  */
183 class train_schedule_t : public schedule_t
184 {
185 public:
train_schedule_t()186 	train_schedule_t() {}
copy()187 	schedule_t* copy() OVERRIDE { schedule_t *s = new train_schedule_t(); s->copy_from(this); return s; }
get_error_msg()188 	const char *get_error_msg() const OVERRIDE { return "Zughalt muss auf\nSchiene liegen!\n"; }
189 
get_type()190 	schedule_type get_type() const OVERRIDE { return train_schedule; }
191 
get_waytype()192 	waytype_t get_waytype() const OVERRIDE { return track_wt; }
193 };
194 
195 /**
196  * Schedules with stops on tram tracks.
197  * @author Hj. Malthaner
198  */
199 class tram_schedule_t : public train_schedule_t
200 {
201 public:
tram_schedule_t()202 	tram_schedule_t() {}
copy()203 	schedule_t* copy() OVERRIDE { schedule_t *s = new tram_schedule_t(); s->copy_from(this); return s; }
204 
get_type()205 	schedule_type get_type() const OVERRIDE { return tram_schedule; }
206 
get_waytype()207 	waytype_t get_waytype() const OVERRIDE { return tram_wt; }
208 };
209 
210 
211 /**
212  * Schedules with stops on roads.
213  *
214  * @author Hj. Malthaner
215  */
216 class truck_schedule_t : public schedule_t
217 {
218 public:
truck_schedule_t()219 	truck_schedule_t() {}
copy()220 	schedule_t* copy() OVERRIDE { schedule_t *s = new truck_schedule_t(); s->copy_from(this); return s; }
get_error_msg()221 	const char *get_error_msg() const OVERRIDE { return "Autohalt muss auf\nStrasse liegen!\n"; }
222 
get_type()223 	schedule_type get_type() const OVERRIDE { return truck_schedule; }
224 
get_waytype()225 	waytype_t get_waytype() const OVERRIDE { return road_wt; }
226 };
227 
228 
229 /**
230  * Schedules with stops on water.
231  *
232  * @author Hj. Malthaner
233  */
234 class ship_schedule_t : public schedule_t
235 {
236 public:
ship_schedule_t()237 	ship_schedule_t() {}
copy()238 	schedule_t* copy() OVERRIDE { schedule_t *s = new ship_schedule_t(); s->copy_from(this); return s; }
get_error_msg()239 	const char *get_error_msg() const OVERRIDE { return "Schiffhalt muss im\nWasser liegen!\n"; }
240 
get_type()241 	schedule_type get_type() const OVERRIDE { return ship_schedule; }
242 
get_waytype()243 	waytype_t get_waytype() const OVERRIDE { return water_wt; }
244 };
245 
246 
247 /**
248  * Schedules for airplanes.
249  *
250  * @author Hj. Malthaner
251  */
252 class airplane_schedule_t : public schedule_t
253 {
254 public:
airplane_schedule_t()255 	airplane_schedule_t() {}
copy()256 	schedule_t* copy() OVERRIDE { schedule_t *s = new airplane_schedule_t(); s->copy_from(this); return s; }
get_error_msg()257 	const char *get_error_msg() const OVERRIDE { return "Flugzeughalt muss auf\nRunway liegen!\n"; }
258 
get_type()259 	schedule_type get_type() const OVERRIDE { return airplane_schedule; }
260 
get_waytype()261 	waytype_t get_waytype() const OVERRIDE { return air_wt; }
262 };
263 
264 /**
265  * Schedules with stops on mono-rails.
266  * @author Hj. Malthaner
267  */
268 class monorail_schedule_t : public schedule_t
269 {
270 public:
monorail_schedule_t()271 	monorail_schedule_t() {}
copy()272 	schedule_t* copy() OVERRIDE { schedule_t *s = new monorail_schedule_t(); s->copy_from(this); return s; }
get_error_msg()273 	const char *get_error_msg() const OVERRIDE { return "Monorailhalt muss auf\nMonorail liegen!\n"; }
274 
get_type()275 	schedule_type get_type() const OVERRIDE { return monorail_schedule; }
276 
get_waytype()277 	waytype_t get_waytype() const OVERRIDE { return monorail_wt; }
278 };
279 
280 /**
281  * Schedules with stops on maglev tracks.
282  * @author Hj. Malthaner
283  */
284 class maglev_schedule_t : public schedule_t
285 {
286 public:
maglev_schedule_t()287 	maglev_schedule_t() {}
copy()288 	schedule_t* copy() OVERRIDE { schedule_t *s = new maglev_schedule_t(); s->copy_from(this); return s; }
get_error_msg()289 	const char *get_error_msg() const OVERRIDE { return "Maglevhalt muss auf\nMaglevschiene liegen!\n"; }
290 
get_type()291 	schedule_type get_type() const OVERRIDE { return maglev_schedule; }
292 
get_waytype()293 	waytype_t get_waytype() const OVERRIDE { return maglev_wt; }
294 };
295 
296 /**
297  * Schedules with stops on narrowgauge tracks.
298  *
299  * @author Hj. Malthaner
300  */
301 class narrowgauge_schedule_t : public schedule_t
302 {
303 public:
narrowgauge_schedule_t()304 	narrowgauge_schedule_t() {}
copy()305 	schedule_t* copy() OVERRIDE { schedule_t *s = new narrowgauge_schedule_t(); s->copy_from(this); return s; }
get_error_msg()306 	const char *get_error_msg() const OVERRIDE { return "On narrowgauge track only!\n"; }
307 
get_type()308 	schedule_type get_type() const OVERRIDE { return narrowgauge_schedule; }
309 
get_waytype()310 	waytype_t get_waytype() const OVERRIDE { return narrowgauge_wt; }
311 };
312 
313 
314 #endif
315