~widelands-dev/widelands/trunk

« back to all changes in this revision

Viewing changes to src/economy/road.cc

  • Committer: sigra
  • Date: 2010-01-04 03:32:50 UTC
  • Revision ID: git-v1:82d9f24adcbde7d19f90434aac5f96c7df58aa10
Fix bug #2924988 (crash when initialization removed between game preload and game start) reported by qcs - Qcumber-some.

Before the game is set up, the tribes are preloaded, which means that it is checked which tribes exist and which initializations each tribe has, so that each player can select a tribe and an initialization. The selected initialization is saved as an index. When the game is finally started, the tribes are fully read. Then a player is initialized with the initialization with the stored index.

But if for example a player has selected the initialization with index 1, then the tribe is edited so that there is no initialization with that index (such as only the initialization with index 0 remains), then the game i started, the tribe fully read, the player initialized with initialization 1, an assertion will fail in debug builds (and an out-of-range access will be done in release builds.

Now throw game_data_error when this happens. Of course it may still behave a bit unexpected if a player selects initialization a with index 0 and then initializaion a is removed and initialization b has index 0, but at least a crash is fixed.

Also make donkey breeding less broken.

git-svn-id: https://widelands.svn.sourceforge.net/svnroot/widelands/trunk@4870 37b2a8de-5219-0410-9f54-a31bc463ab9c

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2004, 2006-2009 by the Widelands Development Team
 
2
 * Copyright (C) 2004, 2006-2010 by the Widelands Development Team
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or
5
5
 * modify it under the terms of the GNU General Public License
61
61
 */
62
62
Road::~Road()
63
63
{
64
 
        for
65
 
                (SlotVector::iterator iter = m_carrier_slots.begin();
66
 
                 iter < m_carrier_slots.end(); ++iter)
67
 
        {
68
 
                 delete iter->carrier_request;
69
 
        }
 
64
        container_iterate_const(SlotVector, m_carrier_slots, i)
 
65
                delete i.current->carrier_request;
70
66
}
71
67
 
72
68
/**
208
204
        FCoords curf(m_path.get_start(), &map[m_path.get_start()]);
209
205
 
210
206
        const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
211
 
        for (Path::Step_Vector::size_type steps = 0; steps < nr_steps + 1; ++steps) {
 
207
        for (Path::Step_Vector::size_type steps = 0; steps < nr_steps + 1; ++steps)
 
208
        {
212
209
                if (steps > 0 && steps < m_path.get_nsteps())
213
210
                        unset_position(egbase, curf);
214
211
 
306
303
{
307
304
        Game & game = ref_cast<Game, Editor_Game_Base>(egbase);
308
305
 
309
 
        for
310
 
                (SlotVector::iterator iter = m_carrier_slots.begin();
311
 
                 iter < m_carrier_slots.end(); ++iter)
312
 
        {
313
 
                delete iter->carrier_request;
314
 
                iter->carrier_request = 0;
 
306
        container_iterate(SlotVector, m_carrier_slots, i) {
 
307
                delete i.current->carrier_request;
 
308
                i.current->carrier_request = 0;
315
309
 
316
310
                // carrier will be released via PlayerImmovable::cleanup
317
 
                iter->carrier = 0;
 
311
                i.current->carrier = 0;
318
312
        }
319
313
 
320
314
        // Unmark Fields
340
334
{
341
335
        PlayerImmovable::set_economy(e);
342
336
 
343
 
        for
344
 
                (SlotVector::iterator iter = m_carrier_slots.begin();
345
 
                 iter < m_carrier_slots.end(); ++iter)
346
 
        {
347
 
                if (iter->carrier_request)
348
 
                        iter->carrier_request->set_economy(e);
349
 
        }
 
337
        container_iterate_const(SlotVector, m_carrier_slots, i)
 
338
                if (i.current->carrier_request)
 
339
                        i.current->carrier_request->set_economy(e);
350
340
}
351
341
 
352
342
/**
355
345
 * Only call this if the road can handle a new carrier, and if no request has
356
346
 * been issued.
357
347
*/
358
 
void Road::_request_carrier
359
 
#ifndef NDEBUG
360
 
        (Game & game, CarrierSlot & slot)
361
 
#else
362
 
        (Game &, CarrierSlot & slot)
363
 
#endif
 
348
void Road::_request_carrier(Game &, CarrierSlot & slot)
364
349
{
365
350
 
366
351
        if (slot.carrier_type == 1 or owner().tribe().name() == "atlanteans") {
367
352
                slot.carrier_request =
368
353
                        new Request
369
354
                                (*this,
370
 
                                owner().tribe().safe_worker_index("carrier"),
371
 
                                Road::_request_carrier_callback,
372
 
                                Request::WORKER);
 
355
                                 owner().tribe().safe_worker_index("carrier"),
 
356
                                 Road::_request_carrier_callback,
 
357
                                 Request::WORKER);
373
358
        } else {
374
359
                std::string donkey_name =
375
360
                        owner().tribe().name() == "empire" ? "donkey" : "wisent";
398
383
        Road    & road    = ref_cast<Road,    PlayerImmovable>(target);
399
384
        Carrier & carrier = ref_cast<Carrier, Worker>         (*w);
400
385
 
401
 
        for
402
 
                (SlotVector::iterator iter = road.m_carrier_slots.begin();
403
 
                 iter < road.m_carrier_slots.end(); ++ iter)
404
 
        {
405
 
                if (iter->carrier_request == &rq) {
406
 
                        iter->carrier_request = 0;
407
 
                        iter->carrier = &carrier;
 
386
        container_iterate(SlotVector, road.m_carrier_slots, i)
 
387
                if (i.current->carrier_request == &rq) {
 
388
                        i.current->carrier_request = 0;
 
389
                        i.current->carrier = &carrier;
408
390
 
409
391
                        carrier.start_task_road(game);
410
392
                        delete &rq;
411
393
                        return;
412
394
                }
413
 
        }
414
395
 
415
396
        delete &rq;
416
397
        carrier.start_task_gowarehouse(game);
423
404
{
424
405
        Game & game = ref_cast<Game, Editor_Game_Base>(owner().egbase());
425
406
 
426
 
        for
427
 
                (SlotVector::iterator iter = m_carrier_slots.begin();
428
 
                 iter < m_carrier_slots.end(); ++iter)
429
 
        {
430
 
 
431
 
                Carrier * carrier = iter->carrier.get(game);
432
 
 
433
 
                if (carrier == &w)
434
 
                        iter->carrier = carrier = 0;
435
 
 
436
 
                if (not carrier and not iter->carrier_request)
437
 
                        _request_carrier(game, *iter);
 
407
        container_iterate(SlotVector, m_carrier_slots, i) {
 
408
                Carrier const * carrier = i.current->carrier.get(game);
 
409
 
 
410
                if (carrier == &w) {
 
411
                        i.current->carrier = 0;
 
412
                        carrier            = 0;
 
413
                }
 
414
 
 
415
                if (not carrier and not i.current->carrier_request)
 
416
                        _request_carrier(game, *i.current);
438
417
        }
439
418
 
440
419
        PlayerImmovable::remove_worker(w);
511
490
        //SlotVector carrierslots = m_carrier_slots;
512
491
        std::vector<Worker *> const workers = get_workers();
513
492
 
514
 
        for
515
 
                (SlotVector::iterator iter = m_carrier_slots.begin();
516
 
                 iter < m_carrier_slots.end(); ++iter)
517
 
        {
518
 
                delete iter->carrier_request;
519
 
                iter->carrier_request = 0;
 
493
        container_iterate(SlotVector, m_carrier_slots, i) {
 
494
                delete i.current->carrier_request;
 
495
                i.current->carrier_request = 0;
520
496
        }
521
497
 
522
498
 
542
518
                        }
543
519
                }
544
520
 
545
 
                if (w.serial() == 3755)
546
 
                        molog("Split: check %u -> idx %i\n", w.serial(), idx);
547
 
 
548
521
                if (idx < 0) {
549
522
                        reassigned_workers.push_back(&w);
550
523
 
552
525
                         * The current worker is not on this road. Search him
553
526
                         * in this road and remove him. Than add him to the new road
554
527
                         */
555
 
                        for
556
 
                                (SlotVector::iterator iter = m_carrier_slots.begin();
557
 
                                 iter < m_carrier_slots.end(); ++iter)
558
 
                        {
559
 
                                Carrier * carrier = iter->carrier.get(game);
 
528
                        container_iterate(SlotVector, m_carrier_slots, j) {
 
529
                                Carrier const * const carrier = j.current->carrier.get(game);
560
530
 
561
531
                                if (carrier == &w) {
562
 
                                        iter->carrier = 0;
563
 
                                        for
564
 
                                                (SlotVector::iterator iter2 =
565
 
                                                 newroad.m_carrier_slots.begin();
566
 
                                                 iter2 < newroad.m_carrier_slots.end();
567
 
                                                 ++iter2)
568
 
                                        {
 
532
                                        j.current->carrier = 0;
 
533
                                        container_iterate(SlotVector, newroad.m_carrier_slots, k)
569
534
                                                if
570
 
                                                        (not iter2->carrier.get(game) and
571
 
                                                         not iter2->carrier_request)
 
535
                                                        (not k.current->carrier.get(game) and
 
536
                                                         not k.current->carrier_request)
572
537
                                                {
573
 
                                                        iter2->carrier =
574
 
                                                                &ref_cast<Carrier, Worker> (w);
 
538
                                                        k.current->carrier = &ref_cast<Carrier, Worker> (w);
575
539
                                                        break;
576
540
                                                }
577
 
                                        }
578
541
                                }
579
542
                        }
580
543
                }
581
544
 
582
 
                if (w.serial() == 3755) {
583
 
                        molog
584
 
                                ("Split: sending signal 'road' to worker %u (at (%i, %i)):\n",
585
 
                                 w.serial(), w.get_position().x, w.get_position().y);
586
 
                        w.log_general_info(game);
587
 
                }
588
545
                // Cause a worker update in any case
589
546
                w.send_signal(game, "road");
590
547
        }