~ubuntu-branches/ubuntu/raring/simutrans/raring-proposed

« back to all changes in this revision

Viewing changes to .pc/0002-FIX-loading-of-savegames-with-line-with-id-0.patch/simline.cc

  • Committer: Package Import Robot
  • Author(s): Ansgar Burchardt
  • Date: 2011-11-03 19:59:02 UTC
  • mfrom: (1.2.7)
  • Revision ID: package-import@ubuntu.com-20111103195902-uopgwf488mfctb75
Tags: 111.0-1
* New upstream release.
* debian/rules: Update get-orig-source target for new upstream release.
* Use xz compression for source and binary packages.
* Use override_* targets to simplify debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include "utils/simstring.h"
2
 
#include "dataobj/translator.h"
3
 
#include "dataobj/loadsave.h"
4
 
#include "simtypes.h"
5
 
#include "simline.h"
6
 
#include "simhalt.h"
7
 
#include "player/simplay.h"
8
 
#include "vehicle/simvehikel.h"
9
 
#include "simconvoi.h"
10
 
#include "convoihandle_t.h"
11
 
#include "simworld.h"
12
 
#include "simlinemgmt.h"
13
 
 
14
 
 
15
 
uint8 simline_t::convoi_to_line_catgory[MAX_CONVOI_COST] = {
16
 
        LINE_CAPACITY, LINE_TRANSPORTED_GOODS, LINE_REVENUE, LINE_OPERATIONS, LINE_PROFIT, LINE_DISTANCE
17
 
};
18
 
 
19
 
karte_t *simline_t::welt=NULL;
20
 
 
21
 
 
22
 
simline_t::simline_t(karte_t* welt, spieler_t* sp, linetype type)
23
 
{
24
 
        self = linehandle_t(this);
25
 
        char printname[128];
26
 
        sprintf( printname, "(%i) %s", self.get_id(), translator::translate("Line",welt->get_einstellungen()->get_name_language_id()) );
27
 
        name = printname;
28
 
 
29
 
        init_financial_history();
30
 
        this->type = type;
31
 
        this->welt = welt;
32
 
        this->fpl = NULL;
33
 
        this->sp = sp;
34
 
        withdraw = false;
35
 
        state_color = COL_YELLOW;
36
 
        create_schedule();
37
 
}
38
 
 
39
 
 
40
 
simline_t::simline_t(karte_t* welt, spieler_t* sp, linetype type, loadsave_t *file)
41
 
{
42
 
        // id will be read and assigned during rdwr
43
 
        self = linehandle_t();
44
 
        this->type = type;
45
 
        this->welt = welt;
46
 
        this->fpl = NULL;
47
 
        this->sp = sp;
48
 
        create_schedule();
49
 
        rdwr(file);
50
 
        // now self has the right id but the this-pointer is not assigned to the quickstone handle yet
51
 
        // do this explicitly
52
 
        self = linehandle_t(this, self.get_id());
53
 
}
54
 
 
55
 
 
56
 
simline_t::~simline_t()
57
 
{
58
 
        DBG_DEBUG("simline_t::~simline_t()", "deleting fpl=%p", fpl);
59
 
 
60
 
        assert(count_convoys()==0);
61
 
        unregister_stops();
62
 
 
63
 
        delete fpl;
64
 
        self.detach();
65
 
        DBG_MESSAGE("simline_t::~simline_t()", "line %d (%p) destroyed", self.get_id(), this);
66
 
}
67
 
 
68
 
 
69
 
void simline_t::create_schedule()
70
 
{
71
 
        switch(type) {
72
 
                case simline_t::truckline:       set_schedule(new autofahrplan_t()); break;
73
 
                case simline_t::trainline:       set_schedule(new zugfahrplan_t()); break;
74
 
                case simline_t::shipline:        set_schedule(new schifffahrplan_t()); break;
75
 
                case simline_t::airline:         set_schedule(new airfahrplan_t()); break;
76
 
                case simline_t::monorailline:    set_schedule(new monorailfahrplan_t()); break;
77
 
                case simline_t::tramline:        set_schedule(new tramfahrplan_t()); break;
78
 
                case simline_t::maglevline:      set_schedule(new maglevfahrplan_t()); break;
79
 
                case simline_t::narrowgaugeline: set_schedule(new narrowgaugefahrplan_t()); break;
80
 
                default:
81
 
                        dbg->fatal( "simline_t::create_schedule()", "Cannot create default schedule!" );
82
 
        }
83
 
}
84
 
 
85
 
 
86
 
void simline_t::add_convoy(convoihandle_t cnv)
87
 
{
88
 
        if (line_managed_convoys.empty()) {
89
 
                // first convoi -> ok, now we can announce this connection to the stations
90
 
                register_stops(fpl);
91
 
        }
92
 
 
93
 
        // first convoi may change line type
94
 
        if (type == trainline  &&  line_managed_convoys.empty() &&  cnv.is_bound()) {
95
 
                // check, if needed to convert to tram/monorail line
96
 
                if (vehikel_t const* const v = cnv->front()) {
97
 
                        switch (v->get_besch()->get_waytype()) {
98
 
                                case tram_wt:     type = simline_t::tramline;     break;
99
 
                                // elevated monorail were saved with wrong coordinates for some versions.
100
 
                                // We try to recover here
101
 
                                case monorail_wt: type = simline_t::monorailline; break;
102
 
                                default:          break;
103
 
                        }
104
 
                }
105
 
        }
106
 
        // only add convoy if not already member of line
107
 
        line_managed_convoys.append_unique(cnv);
108
 
 
109
 
        // what goods can this line transport?
110
 
        bool update_schedules = false;
111
 
        if(  cnv->get_state()!=convoi_t::INITIAL  ) {
112
 
                const minivec_tpl<uint8> &convoys_goods = cnv->get_goods_catg_index();
113
 
                for(  uint8 i = 0;  i < convoys_goods.get_count();  i++  ) {
114
 
                        const uint8 catg_index = convoys_goods[i];
115
 
                        if(  !goods_catg_index.is_contained( catg_index )  ) {
116
 
                                goods_catg_index.append( catg_index, 1 );
117
 
                                update_schedules = true;
118
 
                        }
119
 
                }
120
 
        }
121
 
 
122
 
        // will not hurt ...
123
 
        financial_history[0][LINE_CONVOIS] = count_convoys();
124
 
        recalc_status();
125
 
 
126
 
        // do we need to tell the world about our new schedule?
127
 
        if(  update_schedules  ) {
128
 
                welt->set_schedule_counter();
129
 
        }
130
 
}
131
 
 
132
 
 
133
 
 
134
 
void simline_t::remove_convoy(convoihandle_t cnv)
135
 
{
136
 
        if(line_managed_convoys.is_contained(cnv)) {
137
 
                line_managed_convoys.remove(cnv);
138
 
                recalc_catg_index();
139
 
                financial_history[0][LINE_CONVOIS] = count_convoys();
140
 
                recalc_status();
141
 
        }
142
 
        if(line_managed_convoys.empty()) {
143
 
                unregister_stops();
144
 
        }
145
 
}
146
 
 
147
 
// invalid line id prior to 110.0
148
 
#define INVALID_LINE_ID_OLD ((uint16)(-1))
149
 
// invalid line id from 110.0 on
150
 
#define INVALID_LINE_ID ((uint16)(0))
151
 
 
152
 
void simline_t::rdwr_linehandle_t(loadsave_t *file, linehandle_t &line)
153
 
{
154
 
        uint16 id;
155
 
        if (file->is_saving()) {
156
 
                id = line.is_bound() ? line.get_id(): (file->get_version() < 110000  ? INVALID_LINE_ID_OLD : INVALID_LINE_ID);
157
 
        }
158
 
        if(file->get_version()<88003) {
159
 
                sint32 dummy=id;
160
 
                file->rdwr_long(dummy);
161
 
                id = (uint16)dummy;
162
 
        }
163
 
        else {
164
 
                file->rdwr_short(id);
165
 
        }
166
 
        if (file->is_loading()) {
167
 
                // invalid line_id's: 0 and 65535
168
 
                if (id == INVALID_LINE_ID_OLD) {
169
 
                        id = 0;
170
 
                }
171
 
                line.set_id(id);
172
 
        }
173
 
}
174
 
 
175
 
 
176
 
void simline_t::rdwr(loadsave_t *file)
177
 
{
178
 
        xml_tag_t s( file, "simline_t" );
179
 
 
180
 
        assert(fpl);
181
 
 
182
 
        if(  file->is_loading()  ) {
183
 
                char name[1024];
184
 
                file->rdwr_str(name, lengthof(name));
185
 
                this->name = name;
186
 
        }
187
 
        else {
188
 
                char name[1024];
189
 
                tstrncpy( name, this->name.c_str(), lengthof(name) );
190
 
                file->rdwr_str(name, lengthof(name));
191
 
        }
192
 
 
193
 
        rdwr_linehandle_t(file, self);
194
 
 
195
 
        fpl->rdwr(file);
196
 
 
197
 
        //financial history
198
 
        if(  file->get_version()<=102002  ) {
199
 
                for (int j = 0; j<6; j++) {
200
 
                        for (int k = MAX_MONTHS-1; k>=0; k--) {
201
 
                                file->rdwr_longlong(financial_history[k][j]);
202
 
                        }
203
 
                }
204
 
                for (int k = MAX_MONTHS-1; k>=0; k--) {
205
 
                        financial_history[k][LINE_DISTANCE] = 0;
206
 
                }
207
 
        }
208
 
        else {
209
 
                for (int j = 0; j<MAX_LINE_COST; j++) {
210
 
                        for (int k = MAX_MONTHS-1; k>=0; k--) {
211
 
                                file->rdwr_longlong(financial_history[k][j]);
212
 
                        }
213
 
                }
214
 
        }
215
 
 
216
 
        if(file->get_version()>=102002) {
217
 
                file->rdwr_bool(withdraw);
218
 
        }
219
 
 
220
 
        // otherwise inintialized to zero if loading ...
221
 
        financial_history[0][LINE_CONVOIS] = count_convoys();
222
 
}
223
 
 
224
 
 
225
 
 
226
 
void simline_t::laden_abschliessen()
227
 
{
228
 
        if(  line_managed_convoys.get_count()>0  ) {
229
 
                register_stops(fpl);
230
 
        }
231
 
        recalc_status();
232
 
}
233
 
 
234
 
 
235
 
 
236
 
void simline_t::register_stops(schedule_t * fpl)
237
 
{
238
 
DBG_DEBUG("simline_t::register_stops()", "%d fpl entries in schedule %p", fpl->get_count(),fpl);
239
 
        for (int i = 0; i<fpl->get_count(); i++) {
240
 
                const halthandle_t halt = haltestelle_t::get_halt( welt, fpl->eintrag[i].pos, sp );
241
 
                if(halt.is_bound()) {
242
 
//DBG_DEBUG("simline_t::register_stops()", "halt not null");
243
 
                        halt->add_line(self);
244
 
                }
245
 
                else {
246
 
DBG_DEBUG("simline_t::register_stops()", "halt null");
247
 
                }
248
 
        }
249
 
}
250
 
 
251
 
 
252
 
 
253
 
void simline_t::unregister_stops()
254
 
{
255
 
        unregister_stops(fpl);
256
 
}
257
 
 
258
 
 
259
 
 
260
 
void simline_t::unregister_stops(schedule_t * fpl)
261
 
{
262
 
        for (int i = 0; i<fpl->get_count(); i++) {
263
 
                halthandle_t halt = haltestelle_t::get_halt( welt, fpl->eintrag[i].pos, sp );
264
 
                if(halt.is_bound()) {
265
 
                        halt->remove_line(self);
266
 
                }
267
 
        }
268
 
}
269
 
 
270
 
 
271
 
 
272
 
void simline_t::renew_stops()
273
 
{
274
 
        if(  line_managed_convoys.get_count()>0  ) {
275
 
                register_stops( fpl );
276
 
                DBG_DEBUG("simline_t::renew_stops()", "Line id=%d, name='%s'", self.get_id(), name.c_str());
277
 
        }
278
 
}
279
 
 
280
 
 
281
 
 
282
 
void simline_t::new_month()
283
 
{
284
 
        recalc_status();
285
 
        for (int j = 0; j<MAX_LINE_COST; j++) {
286
 
                for (int k = MAX_MONTHS-1; k>0; k--) {
287
 
                        financial_history[k][j] = financial_history[k-1][j];
288
 
                }
289
 
                financial_history[0][j] = 0;
290
 
        }
291
 
        financial_history[0][LINE_CONVOIS] = count_convoys();
292
 
}
293
 
 
294
 
 
295
 
void simline_t::init_financial_history()
296
 
{
297
 
        MEMZERO(financial_history);
298
 
}
299
 
 
300
 
 
301
 
 
302
 
/*
303
 
 * the current state saved as color
304
 
 * Meanings are BLACK (ok), WHITE (no convois), YELLOW (no vehicle moved), RED (last month income minus), BLUE (at least one convoi vehicle is obsolete)
305
 
 */
306
 
void simline_t::recalc_status()
307
 
{
308
 
        if(financial_history[0][LINE_CONVOIS]==0) {
309
 
                // noconvois assigned to this line
310
 
                state_color = COL_WHITE;
311
 
                withdraw = false;
312
 
        }
313
 
        else if(financial_history[0][LINE_PROFIT]<0) {
314
 
                // ok, not performing best
315
 
                state_color = COL_RED;
316
 
        } else if((financial_history[0][LINE_OPERATIONS]|financial_history[1][LINE_OPERATIONS])==0) {
317
 
                // nothing moved
318
 
                state_color = COL_YELLOW;
319
 
        }
320
 
        else if(welt->use_timeline()) {
321
 
                // convois has obsolete vehicles?
322
 
                bool has_obsolete = false;
323
 
                for(unsigned i=0;  !has_obsolete  &&  i<line_managed_convoys.get_count();  i++ ) {
324
 
                        has_obsolete = line_managed_convoys[i]->has_obsolete_vehicles();
325
 
                }
326
 
                // now we have to set it
327
 
                state_color = has_obsolete ? COL_DARK_BLUE : COL_BLACK;
328
 
        }
329
 
        else {
330
 
                // normal state
331
 
                state_color = COL_BLACK;
332
 
        }
333
 
}
334
 
 
335
 
 
336
 
 
337
 
// recalc what good this line is moving
338
 
void simline_t::recalc_catg_index()
339
 
{
340
 
        // first copy old
341
 
        minivec_tpl<uint8> old_goods_catg_index(goods_catg_index.get_count());
342
 
        for(  uint i=0;  i<goods_catg_index.get_count();  i++  ) {
343
 
                old_goods_catg_index.append( goods_catg_index[i] );
344
 
        }
345
 
        goods_catg_index.clear();
346
 
        withdraw = line_managed_convoys.get_count()>0;
347
 
        // then recreate current
348
 
        for(unsigned i=0;  i<line_managed_convoys.get_count();  i++ ) {
349
 
                // what goods can this line transport?
350
 
                // const convoihandle_t cnv = line_managed_convoys[i];
351
 
                const convoi_t *cnv = line_managed_convoys[i].get_rep();
352
 
                withdraw &= cnv->get_withdraw();
353
 
 
354
 
                const minivec_tpl<uint8> &convoys_goods = cnv->get_goods_catg_index();
355
 
                for(  uint8 i = 0;  i < convoys_goods.get_count();  i++  ) {
356
 
                        const uint8 catg_index = convoys_goods[i];
357
 
                        goods_catg_index.append_unique( catg_index, 1 );
358
 
                }
359
 
        }
360
 
        // if different => schedule need recalculation
361
 
        if(  goods_catg_index.get_count()!=old_goods_catg_index.get_count()  ) {
362
 
                // surely changed
363
 
                welt->set_schedule_counter();
364
 
        }
365
 
        else {
366
 
                // maybe changed => must test all entries
367
 
                for(  uint i=0;  i<goods_catg_index.get_count();  i++  ) {
368
 
                        if(  !old_goods_catg_index.is_contained(goods_catg_index[i])  ) {
369
 
                                // different => recalc
370
 
                                welt->set_schedule_counter();
371
 
                                break;
372
 
                        }
373
 
                }
374
 
        }
375
 
}
376
 
 
377
 
 
378
 
 
379
 
void simline_t::set_withdraw( bool yes_no )
380
 
{
381
 
        withdraw = yes_no  &&  (line_managed_convoys.get_count()>0);
382
 
        // convois in depots will be immeadiately destroyed, thus we go backwards
383
 
        for( sint32 i=line_managed_convoys.get_count()-1;  i>=0;  i--  ) {
384
 
                line_managed_convoys[i]->set_no_load(yes_no);   // must be first, since set withdraw might destroy convoi if in depot!
385
 
                line_managed_convoys[i]->set_withdraw(yes_no);
386
 
        }
387
 
}