~ubuntu-branches/ubuntu/precise/widelands/precise-backports

« back to all changes in this revision

Viewing changes to src/warehouse.cc

  • Committer: Bazaar Package Importer
  • Author(s): Martin Quinson
  • Date: 2005-02-14 10:41:12 UTC
  • Revision ID: james.westby@ubuntu.com-20050214104112-6v08iux9fptxpva9
Tags: upstream-build9
Import upstream version build9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2002-2004 by Widelands Development Team
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License
 
6
 * as published by the Free Software Foundation; either version 2
 
7
 * of the License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
17
 *
 
18
 */
 
19
 
 
20
#include "editor_game_base.h"
 
21
#include "error.h"
 
22
#include "game.h"
 
23
#include "player.h"
 
24
#include "profile.h"
 
25
#include "soldier.h"
 
26
#include "transport.h"
 
27
#include "warehouse.h"
 
28
#include "wexception.h"
 
29
#include "worker.h"
 
30
#include "tribe.h"
 
31
 
 
32
static const int CARRIER_SPAWN_INTERVAL = 2500;
 
33
 
 
34
 
 
35
/*
 
36
===============
 
37
WarehouseSupply::WarehouseSupply
 
38
 
 
39
Initialize the supply
 
40
===============
 
41
*/
 
42
WarehouseSupply::WarehouseSupply(Warehouse* wh)
 
43
{
 
44
        m_warehouse = wh;
 
45
        m_economy = 0;
 
46
}
 
47
 
 
48
 
 
49
/*
 
50
===============
 
51
WarehouseSupply::~WarehouseSupply
 
52
 
 
53
Destroy the supply.
 
54
===============
 
55
*/
 
56
WarehouseSupply::~WarehouseSupply()
 
57
{
 
58
        if (m_economy)
 
59
        {
 
60
                log(
 
61
                        "WarehouseSupply::~WarehouseSupply: "
 
62
                        "Warehouse %u still belongs to an economy",
 
63
                        m_warehouse->get_serial());
 
64
                set_economy(0);
 
65
        }
 
66
 
 
67
        // We're removed from the Economy. Therefore, the wares can simply
 
68
        // be cleared out. The global inventory will be okay.
 
69
        m_wares.clear();
 
70
   m_workers.clear();
 
71
}
 
72
 
 
73
/*
 
74
 * Inform this supply, how much wares
 
75
 * are to be handled
 
76
 */
 
77
void WarehouseSupply::set_nrwares( int i ) {
 
78
   assert(m_wares.get_nrwareids()==0);
 
79
 
 
80
   m_wares.set_nrwares(i);
 
81
}
 
82
void WarehouseSupply::set_nrworkers( int i ) {
 
83
   assert(m_workers.get_nrwareids()==0);
 
84
 
 
85
   m_workers.set_nrwares(i);
 
86
}
 
87
 
 
88
 
 
89
 
 
90
/*
 
91
===============
 
92
WarehouseSupply::set_economy
 
93
 
 
94
Add and remove our wares and the Supply to the economies as necessary.
 
95
===============
 
96
*/
 
97
void WarehouseSupply::set_economy(Economy* e)
 
98
{
 
99
        if (e == m_economy)
 
100
                return;
 
101
 
 
102
        if (m_economy) {
 
103
                for(int i = 0; i < m_wares.get_nrwareids(); i++) {
 
104
                        if (m_wares.stock(i)) {
 
105
                                m_economy->remove_wares(i, m_wares.stock(i));
 
106
                                m_economy->remove_ware_supply(i, this);
 
107
                        }
 
108
                }
 
109
                for(int i = 0; i < m_workers.get_nrwareids(); i++) {
 
110
                        if (m_workers.stock(i)) {
 
111
                                m_economy->remove_workers(i, m_workers.stock(i));
 
112
                                m_economy->remove_worker_supply(i, this);
 
113
                        }
 
114
                }
 
115
        }
 
116
 
 
117
        m_economy = e;
 
118
 
 
119
        if (m_economy) {
 
120
                for(int i = 0; i < m_wares.get_nrwareids(); i++) {
 
121
                        if (m_wares.stock(i)) {
 
122
                                m_economy->add_wares(i, m_wares.stock(i));
 
123
                                m_economy->add_ware_supply(i, this);
 
124
                        }
 
125
                }
 
126
                for(int i = 0; i < m_workers.get_nrwareids(); i++) {
 
127
                        if (m_workers.stock(i)) {
 
128
                                m_economy->add_workers(i, m_workers.stock(i));
 
129
                                m_economy->add_worker_supply(i, this);
 
130
                        }
 
131
                }
 
132
        }
 
133
}
 
134
 
 
135
 
 
136
/*
 
137
===============
 
138
WarehouseSupply::add_wares
 
139
 
 
140
Add wares and update the economy.
 
141
===============
 
142
*/
 
143
void WarehouseSupply::add_wares(int id, int count)
 
144
{
 
145
        if (!count)
 
146
                return;
 
147
 
 
148
        if (!m_wares.stock(id))
 
149
                m_economy->add_ware_supply(id, this);
 
150
 
 
151
        m_economy->add_wares(id, count);
 
152
        m_wares.add(id, count);
 
153
}
 
154
 
 
155
 
 
156
/*
 
157
===============
 
158
WarehouseSupply::remove_wares
 
159
 
 
160
Remove wares and update the economy.
 
161
===============
 
162
*/
 
163
void WarehouseSupply::remove_wares(int id, int count)
 
164
{
 
165
        if (!count)
 
166
                return;
 
167
 
 
168
        m_wares.remove(id, count);
 
169
        m_economy->remove_wares(id, count);
 
170
 
 
171
        if (!m_wares.stock(id))
 
172
                m_economy->remove_ware_supply(id, this);
 
173
}
 
174
 
 
175
/*
 
176
===============
 
177
WarehouseSupply::add_workers
 
178
 
 
179
Add workers and update the economy.
 
180
 
 
181
===============
 
182
*/
 
183
void WarehouseSupply::add_workers(int id, int count)
 
184
{
 
185
        if (!count)
 
186
                return;
 
187
 
 
188
        if (!m_workers.stock(id))
 
189
                m_economy->add_worker_supply(id, this);
 
190
 
 
191
   m_economy->add_workers(id, count);
 
192
        m_workers.add(id, count);
 
193
}
 
194
 
 
195
 
 
196
/*
 
197
===============
 
198
WarehouseSupply::remove_workers
 
199
 
 
200
Remove workers and update the economy.
 
201
 
 
202
Comments see add_workers
 
203
===============
 
204
*/
 
205
void WarehouseSupply::remove_workers(int id, int count)
 
206
{
 
207
        if (!count)
 
208
                return;
 
209
 
 
210
        m_workers.remove(id, count);
 
211
   m_economy->remove_workers(id, count);
 
212
 
 
213
        if (!m_workers.stock(id))
 
214
                m_economy->remove_worker_supply(id, this);
 
215
}
 
216
   
 
217
/*
 
218
===============
 
219
WarehouseSupply::get_position
 
220
 
 
221
Return the position of the Supply, i.e. the owning Warehouse.
 
222
===============
 
223
*/
 
224
PlayerImmovable* WarehouseSupply::get_position(Game* g)
 
225
{
 
226
        return m_warehouse;
 
227
}
 
228
 
 
229
 
 
230
/*
 
231
===============
 
232
WarehouseSupply::get_amount
 
233
 
 
234
Return our stock of the given ware.
 
235
===============
 
236
*/
 
237
int WarehouseSupply::get_amount(Game* g, int ware)
 
238
{
 
239
        return m_wares.stock(ware);
 
240
}
 
241
 
 
242
 
 
243
/*
 
244
===============
 
245
WarehouseSupply::is_active
 
246
 
 
247
Warehouse supplies are never active.
 
248
===============
 
249
*/
 
250
bool WarehouseSupply::is_active(Game* g)
 
251
{
 
252
        return false;
 
253
}
 
254
 
 
255
 
 
256
/*
 
257
===============
 
258
WarehouseSupply::launch_item
 
259
 
 
260
Launch a ware as item.
 
261
===============
 
262
*/
 
263
WareInstance* WarehouseSupply::launch_item(Game* g, int ware)
 
264
{
 
265
        assert(m_wares.stock(ware));
 
266
 
 
267
        return m_warehouse->launch_item(g, ware);
 
268
}
 
269
 
 
270
 
 
271
/*
 
272
===============
 
273
WarehouseSupply::launch_worker
 
274
 
 
275
Launch a ware as worker.
 
276
===============
 
277
*/
 
278
Worker* WarehouseSupply::launch_worker(Game* g, int ware)
 
279
{
 
280
        assert(m_workers.stock(ware));
 
281
 
 
282
        return m_warehouse->launch_worker(g, ware);
 
283
}
 
284
 
 
285
 
 
286
/*
 
287
===============
 
288
WarehouseSupply::launch_soldier
 
289
 
 
290
Launch a ware as soldier.
 
291
===============
 
292
*/
 
293
Soldier* WarehouseSupply::launch_soldier(Game* g, int ware, Requeriments* req)
 
294
{
 
295
        assert(m_workers.stock(ware));
 
296
 
 
297
        return m_warehouse->launch_soldier(g, ware, req);
 
298
}
 
299
 
 
300
/*
 
301
===============
 
302
WarehouseSupply::get_passing_requeriments
 
303
 
 
304
Launch a ware as soldier.
 
305
===============
 
306
*/
 
307
int WarehouseSupply::get_passing_requeriments(Game* g, int ware, Requeriments* req)
 
308
{
 
309
        assert(m_workers.stock(ware));
 
310
 
 
311
        return m_warehouse->get_soldiers_passing (g, ware, req);
 
312
}
 
313
 
 
314
/*
 
315
===============
 
316
WarehouseSupply::mark_as_used
 
317
===============
 
318
*/
 
319
void WarehouseSupply::mark_as_used (Game* g, int ware, Requeriments* r)
 
320
{
 
321
        m_warehouse->mark_as_used (g, ware, r);
 
322
}
 
323
 
 
324
 
 
325
 
 
326
/*
 
327
==============================================================================
 
328
 
 
329
Warehouse building
 
330
 
 
331
==============================================================================
 
332
*/
 
333
 
 
334
/*
 
335
===============
 
336
Warehouse_Descr::Warehouse_Descr
 
337
 
 
338
Initialize with sane defaults
 
339
===============
 
340
*/
 
341
Warehouse_Descr::Warehouse_Descr(Tribe_Descr* tribe, const char* name)
 
342
        : Building_Descr(tribe, name)
 
343
{
 
344
        m_subtype = Subtype_Normal;
 
345
        m_conquers = 0;
 
346
}
 
347
 
 
348
/*
 
349
===============
 
350
Warehouse_Descr::parse
 
351
 
 
352
Parse the additional warehouse settings from the given profile and directory
 
353
===============
 
354
*/
 
355
void Warehouse_Descr::parse(const char* directory, Profile* prof,
 
356
        const EncodeData* encdata)
 
357
{
 
358
        add_attribute(Map_Object::WAREHOUSE);
 
359
 
 
360
        Building_Descr::parse(directory, prof, encdata);
 
361
 
 
362
        Section* global = prof->get_safe_section("global");
 
363
        const char* string;
 
364
 
 
365
        string = global->get_safe_string("subtype");
 
366
        if (!strcasecmp(string, "HQ")) {
 
367
                m_subtype = Subtype_HQ;
 
368
        } else if (!strcasecmp(string, "port")) {
 
369
                m_subtype = Subtype_Port;
 
370
        } else if (!strcasecmp(string, "none")) {
 
371
                //
 
372
        } else
 
373
                throw wexception(
 
374
                        "Unsupported warehouse subtype '%s'. Possible values: none, HQ, port",
 
375
                        string);
 
376
 
 
377
        if (m_subtype == Subtype_HQ)
 
378
                m_conquers = global->get_int("conquers");
 
379
}
 
380
 
 
381
 
 
382
/*
 
383
==============================
 
384
 
 
385
IMPLEMENTATION
 
386
 
 
387
==============================
 
388
*/
 
389
 
 
390
/*
 
391
===============
 
392
Warehouse::Warehouse
 
393
 
 
394
Initialize a warehouse (zero contents, etc...)
 
395
===============
 
396
*/
 
397
Warehouse::Warehouse(Warehouse_Descr* descr)
 
398
        : Building(descr)
 
399
{
 
400
        m_supply = new WarehouseSupply(this);
 
401
        m_next_carrier_spawn = 0;
 
402
}
 
403
 
 
404
 
 
405
/*
 
406
===============
 
407
Warehouse::Warehouse
 
408
 
 
409
Cleanup
 
410
===============
 
411
*/
 
412
Warehouse::~Warehouse()
 
413
{
 
414
        delete m_supply;
 
415
}
 
416
 
 
417
 
 
418
/*
 
419
===============
 
420
Warehouse::init
 
421
 
 
422
Conquer the land around the HQ on init.
 
423
===============
 
424
*/
 
425
void Warehouse::init(Editor_Game_Base* gg)
 
426
{
 
427
        Building::init(gg);
 
428
 
 
429
        if (get_descr()->get_subtype() == Warehouse_Descr::Subtype_HQ)
 
430
                gg->conquer_area(get_owner()->get_player_number(), m_position, get_descr());
 
431
 
 
432
   m_supply->set_nrwares(get_owner()->get_tribe()->get_nrwares());
 
433
   m_supply->set_nrworkers(get_owner()->get_tribe()->get_nrworkers());
 
434
 
 
435
   if (gg->is_game()) {
 
436
      for(int i = 0; i < get_owner()->get_tribe()->get_nrwares(); i++) {
 
437
         Request* req = new Request(this, i, &Warehouse::idle_request_cb, this, Request::WARE);
 
438
 
 
439
         req->set_idle(true);
 
440
 
 
441
         m_requests.push_back(req);
 
442
      }
 
443
     for(int i = 0; i < get_owner()->get_tribe()->get_nrworkers(); i++) {
 
444
         Request* req = new Request(this, i, &Warehouse::idle_request_cb, this, Request::WORKER);
 
445
 
 
446
         req->set_idle(true);
 
447
 
 
448
         m_requests.push_back(req);
 
449
      }
 
450
 
 
451
 
 
452
      Game* g=static_cast<Game*>(gg);
 
453
 
 
454
      m_next_carrier_spawn = schedule_act(g, CARRIER_SPAWN_INTERVAL);
 
455
      m_next_military_act = schedule_act(g, 1000);
 
456
   }
 
457
}
 
458
 
 
459
 
 
460
/*
 
461
===============
 
462
Warehouse::cleanup
 
463
 
 
464
Destroy the warehouse.
 
465
===============
 
466
*/
 
467
void Warehouse::cleanup(Editor_Game_Base* gg)
 
468
{
 
469
   if(gg->is_game()) {
 
470
      Game* g=static_cast<Game*>(gg);
 
471
 
 
472
      while(m_requests.size()) {
 
473
         Request* req = m_requests[m_requests.size()-1];
 
474
 
 
475
         m_requests.pop_back();
 
476
 
 
477
         delete req;
 
478
      }
 
479
 
 
480
      // all cached workers are unbound and freed
 
481
      while(m_incorporated_workers.size()) {
 
482
         Worker* w=static_cast<Worker*>(m_incorporated_workers.begin()->get(gg));
 
483
         // If the game ends and this worker has been created before this warehouse, it might
 
484
         // already be deleted. So do not try and free him
 
485
         if(w)
 
486
            w->reset_tasks(g);
 
487
         m_incorporated_workers.erase(m_incorporated_workers.begin());
 
488
      }
 
489
   }
 
490
        // TODO: un-conquer the area?
 
491
        Building::cleanup(gg);
 
492
}
 
493
 
 
494
 
 
495
/*
 
496
===============
 
497
Warehouse::act
 
498
 
 
499
Act regularly to create carriers. According to intelligence, this is some
 
500
highly advanced technology. Not only do the settlers have no problems with
 
501
birth control, they don't even need anybody to procreate. They must have
 
502
built-in DNA samples in those warehouses. And what the hell are they doing,
 
503
killing useless tribesmen! The Borg? Or just like Soylent Green?
 
504
Or maybe I should just stop writing comments that late at night ;-)
 
505
===============
 
506
*/
 
507
void Warehouse::act(Game* g, uint data)
 
508
{
 
509
        if (g->get_gametime() - m_next_carrier_spawn >= 0)
 
510
        {
 
511
                int id = get_owner()->get_tribe()->get_safe_worker_index("carrier");
 
512
                int stock = m_supply->stock_workers(id);
 
513
                int tdelta = CARRIER_SPAWN_INTERVAL;
 
514
 
 
515
                if (stock < 100) {
 
516
                        tdelta -= 4*(100 - stock);
 
517
                        insert_workers(id, 1);
 
518
                } else if (stock > 100) {
 
519
                        tdelta -= 4*(stock - 100);
 
520
                        if (tdelta < 10)
 
521
                                tdelta = 10;
 
522
                        remove_workers(id, 1);
 
523
                }
 
524
 
 
525
                m_next_carrier_spawn = schedule_act(g, tdelta);
 
526
        }
 
527
      
 
528
      // Military stuff: Kill the soldiers that are dead
 
529
   if (g->get_gametime() - m_next_military_act >= 0)
 
530
   {
 
531
      int ware = get_owner()->get_tribe()->get_safe_worker_index("soldier");
 
532
      
 
533
      Worker_Descr* workerdescr;
 
534
      Soldier* soldier;
 
535
 
 
536
      workerdescr = get_owner()->get_tribe()->get_worker_descr(ware);
 
537
         // Look if we got one in stock of those
 
538
      std::string name=workerdescr->get_name();
 
539
      std::vector<Object_Ptr>::iterator i;
 
540
      for(i=m_incorporated_workers.begin(); i!=m_incorporated_workers.end(); i++)
 
541
      {
 
542
         if(static_cast<Worker*>(i->get(g))->get_name()==name)
 
543
         {
 
544
            soldier = static_cast<Soldier*>(i->get(g));
 
545
            
 
546
               // Soldier dead ...
 
547
            if (!soldier || (soldier->get_current_hitpoints() == 0))
 
548
            {
 
549
               m_incorporated_workers.erase(i);
 
550
               m_supply->remove_workers(ware, 1);
 
551
               continue;
 
552
            }
 
553
               // If warehouse can heal, this is the place to put it
 
554
         }
 
555
      }
 
556
      m_next_military_act = schedule_act (g, 1000);
 
557
   }
 
558
   Building::act(g, data);
 
559
}
 
560
 
 
561
 
 
562
/*
 
563
===============
 
564
Warehouse::set_economy
 
565
 
 
566
Transfer our registration to the new economy.
 
567
===============
 
568
*/
 
569
void Warehouse::set_economy(Economy* e)
 
570
{
 
571
        Economy* old = get_economy();
 
572
 
 
573
        if (old == e)
 
574
                return;
 
575
 
 
576
        if (old)
 
577
                old->remove_warehouse(this);
 
578
 
 
579
        m_supply->set_economy(e);
 
580
        Building::set_economy(e);
 
581
 
 
582
        for(uint i = 0; i < m_requests.size(); i++)
 
583
                m_requests[i]->set_economy(e);
 
584
 
 
585
        if (e)
 
586
                e->add_warehouse(this);
 
587
}
 
588
 
 
589
 
 
590
/*
 
591
===============
 
592
Warehouse::get_wares
 
593
===============
 
594
*/
 
595
const WareList& Warehouse::get_wares() const
 
596
{
 
597
        return m_supply->get_wares();
 
598
}
 
599
 
 
600
/*
 
601
===============
 
602
Warehouse::get_workers
 
603
===============
 
604
*/
 
605
const WareList& Warehouse::get_workers() const
 
606
{
 
607
        return m_supply->get_workers();
 
608
}
 
609
 
 
610
 
 
611
 
 
612
/*
 
613
===============
 
614
Warehouse::create_wares
 
615
 
 
616
Magically create wares in this warehouse. Updates the economy accordingly.
 
617
===============
 
618
*/
 
619
void Warehouse::insert_wares(int id, int count)
 
620
{
 
621
        assert(get_economy());
 
622
 
 
623
        m_supply->add_wares(id, count);
 
624
}
 
625
 
 
626
 
 
627
/*
 
628
===============
 
629
Warehouse::destroy_wares
 
630
 
 
631
Magically destroy wares.
 
632
===============
 
633
*/
 
634
void Warehouse::remove_wares(int id, int count)
 
635
{
 
636
        assert(get_economy());
 
637
 
 
638
        m_supply->remove_wares(id, count);
 
639
}
 
640
 
 
641
/*
 
642
===============
 
643
Warehouse::create_workers
 
644
 
 
645
Magically create workers in this warehouse. Updates the economy accordingly.
 
646
===============
 
647
*/
 
648
void Warehouse::insert_workers(int id, int count)
 
649
{
 
650
        assert(get_economy());
 
651
 
 
652
        m_supply->add_workers(id, count);
 
653
}
 
654
 
 
655
 
 
656
/*
 
657
===============
 
658
Warehouse::destroy_workers
 
659
 
 
660
Magically destroy workers.
 
661
===============
 
662
*/
 
663
void Warehouse::remove_workers(int id, int count)
 
664
{
 
665
        assert(get_economy());
 
666
 
 
667
        m_supply->remove_workers(id, count);
 
668
}
 
669
 
 
670
 
 
671
/*
 
672
===============
 
673
Warehouse::fetch_from_flag
 
674
 
 
675
Launch a carrier to fetch an item from our flag.
 
676
===============
 
677
*/
 
678
bool Warehouse::fetch_from_flag(Game* g)
 
679
{
 
680
        int carrierid;
 
681
        Worker* worker;
 
682
 
 
683
        carrierid = get_owner()->get_tribe()->get_safe_worker_index("carrier");
 
684
 
 
685
        if (!m_supply->stock_workers(carrierid)) // XXX yep, let's cheat
 
686
                insert_workers(carrierid, 1);
 
687
 
 
688
        worker = launch_worker(g, carrierid);
 
689
        worker->start_task_fetchfromflag(g);
 
690
 
 
691
        return true;
 
692
}
 
693
 
 
694
 
 
695
/*
 
696
===============
 
697
Warehouse::launch_worker
 
698
 
 
699
Start a worker of a given type. The worker will be assigned a job by the caller.
 
700
===============
 
701
*/
 
702
Worker* Warehouse::launch_worker(Game* g, int ware)
 
703
{
 
704
        assert(m_supply->stock_workers(ware));
 
705
 
 
706
        Worker_Descr* workerdescr;
 
707
        Worker* worker;
 
708
 
 
709
        workerdescr = get_owner()->get_tribe()->get_worker_descr(ware);
 
710
   
 
711
   // Look if we got one in stock of those
 
712
   std::string name=workerdescr->get_name();
 
713
   std::vector<Object_Ptr>::iterator i;
 
714
   for(i=m_incorporated_workers.begin();
 
715
         i!=m_incorporated_workers.end(); i++)
 
716
      if(static_cast<Worker*>(i->get(g))->get_name()==name) break;
 
717
 
 
718
   if(i==m_incorporated_workers.end()) {
 
719
      // None found, create a new one (if available)
 
720
      worker = workerdescr->create(g, get_owner(), this, m_position);
 
721
   } else {
 
722
      // one found, make him available
 
723
      worker = static_cast<Worker*>(i->get(g));
 
724
      worker->reset_tasks(g); // Forget everything you did
 
725
      worker->set_location( this ); // Back in a economy 
 
726
      m_incorporated_workers.erase(i);
 
727
   }
 
728
      
 
729
   m_supply->remove_workers(ware, 1);
 
730
   
 
731
 
 
732
        return worker;
 
733
}
 
734
 
 
735
 
 
736
/*
 
737
===============
 
738
Warehouse::launch_soldier
 
739
 
 
740
Start a soldier or certain level. The soldier will be assigned a job by the caller.
 
741
===============
 
742
*/
 
743
Soldier* Warehouse::launch_soldier(Game* g, int ware, Requeriments* r)
 
744
{
 
745
        assert(m_supply->stock_workers(ware));
 
746
 
 
747
        Worker_Descr* workerdescr;
 
748
        Soldier* soldier;
 
749
 
 
750
        workerdescr = get_owner()->get_tribe()->get_worker_descr(ware);
 
751
   // Look if we got one in stock of those
 
752
        std::string name=workerdescr->get_name();
 
753
        std::vector<Object_Ptr>::iterator i;
 
754
        for(i=m_incorporated_workers.begin(); i!=m_incorporated_workers.end(); i++)
 
755
        {
 
756
                if(static_cast<Worker*>(i->get(g))->get_name()==name)
 
757
                {
 
758
                        soldier = static_cast<Soldier*>(i->get(g));
 
759
                        if ((!r) || (r->check ( soldier->get_level(atrHP),
 
760
                                        soldier->get_level(atrAttack),
 
761
                                        soldier->get_level(atrDefense),
 
762
                                        soldier->get_level(atrEvade))
 
763
                                                        ))
 
764
                                break;
 
765
                        else
 
766
                                continue;
 
767
                }
 
768
        }
 
769
 
 
770
        soldier = 0;
 
771
        if(i==m_incorporated_workers.end()) 
 
772
        {
 
773
      // None found, create a new one (if available)
 
774
                soldier = (Soldier*)workerdescr->create(g, get_owner(), this, m_position);
 
775
        } 
 
776
        else 
 
777
        {
 
778
      // one found, make him available
 
779
                soldier = static_cast<Soldier*>(i->get(g));
 
780
                soldier->reset_tasks(g); // Forget everything you did
 
781
                soldier->mark(false);
 
782
      soldier->set_location( this );
 
783
                m_incorporated_workers.erase(i);
 
784
        }
 
785
      
 
786
   m_supply->remove_workers(ware, 1);
 
787
 
 
788
        return soldier;
 
789
}
 
790
 
 
791
 
 
792
 
 
793
/*
 
794
===============
 
795
Warehouse::mark_as_used
 
796
 
 
797
Mark a soldier as used by a request.
 
798
===============
 
799
*/
 
800
void Warehouse::mark_as_used(Game* g, int ware, Requeriments* r)
 
801
{
 
802
        assert(m_supply->stock_workers(ware));
 
803
 
 
804
        Worker_Descr* workerdescr;
 
805
        Soldier* soldier;
 
806
 
 
807
        workerdescr = get_owner()->get_tribe()->get_worker_descr(ware);
 
808
   // Look if we got one in stock of those
 
809
        std::string name=workerdescr->get_name();
 
810
        std::vector<Object_Ptr>::iterator i;
 
811
        for(i=m_incorporated_workers.begin(); i!=m_incorporated_workers.end(); i++)
 
812
        {
 
813
                if(static_cast<Worker*>(i->get(g))->get_name()==name)
 
814
                {
 
815
                        soldier = static_cast<Soldier*>(i->get(g));
 
816
                        if (!soldier->is_marked())
 
817
                        {
 
818
                                if ((!r) || (r->check ( soldier->get_level(atrHP),
 
819
                                                                                soldier->get_level(atrAttack),
 
820
                                                                                soldier->get_level(atrDefense),
 
821
                                                                                soldier->get_level(atrEvade)))
 
822
                                        )
 
823
                                        break;
 
824
                                else
 
825
                                        continue;
 
826
                        }
 
827
                }
 
828
        }
 
829
 
 
830
        soldier = 0;
 
831
        if(i==m_incorporated_workers.end())
 
832
        {
 
833
        } 
 
834
        else
 
835
        {
 
836
      // one found
 
837
                soldier = static_cast<Soldier*>(i->get(g));
 
838
                soldier->mark(true);
 
839
        }
 
840
}
 
841
 
 
842
 
 
843
/*
 
844
===============
 
845
Warehouse::incorporate_worker
 
846
 
 
847
This is the opposite of launch_worker: destroy the worker and add the
 
848
appropriate ware to our warelist
 
849
===============
 
850
*/
 
851
void Warehouse::incorporate_worker(Game* g, Worker* w)
 
852
{
 
853
        assert(w->get_owner() == get_owner());
 
854
 
 
855
        int index = get_owner()->get_tribe()->get_worker_index(w->get_name().c_str());
 
856
        WareInstance* item = w->fetch_carried_item(g); // rescue an item
 
857
 
 
858
   // We remove carrier, but we keep other workers around
 
859
   if(w->get_worker_type()==Worker_Descr::CARRIER) 
 
860
   {
 
861
      w->remove(g);
 
862
      w=0;
 
863
   }
 
864
   else
 
865
   {
 
866
         // This is to prevent having soldiers that only are used one time and become allways 'marked'
 
867
      if (w->get_worker_type() == Worker_Descr::SOLDIER)
 
868
         ((Soldier*)w)->mark(false);
 
869
 
 
870
      sort_worker_in(g, w->get_name(), w);
 
871
      w->set_location(0); // No more in a economy
 
872
      w->start_task_idle(g, 0, -1); // bind the worker into this house, hide him on the map
 
873
   }
 
874
 
 
875
   m_supply->add_workers(index, 1);
 
876
 
 
877
        if (item) 
 
878
                incorporate_item(g, item);
 
879
}
 
880
 
 
881
/*
 
882
 * Sort the worker into the right position in m_incorporated_workers
 
883
 */
 
884
void Warehouse::sort_worker_in(Editor_Game_Base* g, std::string name, Worker* w) {
 
885
      // We insert this worker, but to keep some consistency in ordering, we tell him 
 
886
      // where to insert
 
887
      
 
888
      std::vector<Object_Ptr>::iterator i=m_incorporated_workers.begin();
 
889
 
 
890
      while(i!= m_incorporated_workers.end() && name <= static_cast<Worker*>(i->get(g))->get_name()) ++i; 
 
891
      if(i==m_incorporated_workers.end()) {
 
892
         m_incorporated_workers.insert(i, w);
 
893
         return;
 
894
      }
 
895
 
 
896
      while(i!=m_incorporated_workers.end() && w->get_serial() <= static_cast<Worker*>(i->get(g))->get_serial()) ++i;
 
897
         
 
898
      m_incorporated_workers.insert(i, w);
 
899
}
 
900
 
 
901
/*
 
902
===============
 
903
Warehouse::launch_item
 
904
 
 
905
Create an instance of a ware and make sure it gets carried out of the warehouse.
 
906
===============
 
907
*/
 
908
WareInstance* Warehouse::launch_item(Game* g, int ware)
 
909
{
 
910
        WareInstance* item;
 
911
 
 
912
        // Create the item
 
913
   Item_Ware_Descr* descr=get_owner()->get_tribe()->get_ware_descr(ware);
 
914
   assert(descr);
 
915
        item = new WareInstance(ware, descr);
 
916
        item->init(g);
 
917
 
 
918
        m_supply->remove_wares(ware, 1);
 
919
 
 
920
        do_launch_item(g, item);
 
921
 
 
922
        return item;
 
923
}
 
924
 
 
925
 
 
926
/*
 
927
===============
 
928
Warehouse::do_launch_item
 
929
 
 
930
Get a carrier to actually move this item out of the warehouse.
 
931
===============
 
932
*/
 
933
void Warehouse::do_launch_item(Game* g, WareInstance* item)
 
934
{
 
935
        int carrierid;
 
936
        Worker_Descr* workerdescr;
 
937
        Worker* worker;
 
938
 
 
939
        // Create a carrier
 
940
        carrierid = get_owner()->get_tribe()->get_worker_index("carrier");
 
941
        workerdescr = get_owner()->get_tribe()->get_worker_descr(carrierid);
 
942
 
 
943
        worker = workerdescr->create(g, get_owner(), this, m_position);
 
944
 
 
945
        // Yup, this is cheating.
 
946
        if (m_supply->stock_workers(carrierid))
 
947
                m_supply->remove_workers(carrierid, 1);
 
948
 
 
949
        // Setup the carrier
 
950
        worker->start_task_dropoff(g, item);
 
951
}
 
952
 
 
953
 
 
954
/*
 
955
===============
 
956
Warehouse::incorporate_item
 
957
 
 
958
Swallow the item, adding it to out inventory.
 
959
===============
 
960
*/
 
961
void Warehouse::incorporate_item(Game* g, WareInstance* item)
 
962
{
 
963
        int ware = item->get_ware();
 
964
 
 
965
        item->destroy(g);
 
966
 
 
967
        m_supply->add_wares(ware, 1);
 
968
}
 
969
 
 
970
 
 
971
/*
 
972
===============
 
973
Warehouse::idle_request_cb [static]
 
974
 
 
975
Called when a transfer for one of the idle Requests completes.
 
976
===============
 
977
*/
 
978
void Warehouse::idle_request_cb(Game* g, Request* rq, int ware, Worker* w,
 
979
        void* data)
 
980
{
 
981
        Warehouse* wh = (Warehouse*)data;
 
982
 
 
983
        if (w)
 
984
                w->schedule_incorporate(g);
 
985
        else
 
986
                wh->m_supply->add_wares(ware, 1);
 
987
}
 
988
 
 
989
 
 
990
/*
 
991
===============
 
992
Warehouse_Descr::create_object
 
993
===============
 
994
*/
 
995
Building* Warehouse_Descr::create_object()
 
996
{
 
997
        return new Warehouse(this);
 
998
}
 
999
 
 
1000
/*
 
1001
===============
 
1002
Warehouse::get_soldiers_passing
 
1003
===============
 
1004
*/
 
1005
int Warehouse::get_soldiers_passing (Game* g, int w, Requeriments* r)
 
1006
{
 
1007
        int number = 0;
 
1008
 
 
1009
log ("Warehouse::get_soldiers_passing :");
 
1010
 
 
1011
        assert(m_supply->stock_workers(w));
 
1012
 
 
1013
        Worker_Descr* workerdescr;
 
1014
        Soldier* soldier;
 
1015
 
 
1016
        workerdescr = get_owner()->get_tribe()->get_worker_descr(w);
 
1017
   // Look if we got one in stock of those
 
1018
   std::string name=workerdescr->get_name();
 
1019
   std::vector<Object_Ptr>::iterator i;
 
1020
 
 
1021
        for(i=m_incorporated_workers.begin(); i!=m_incorporated_workers.end(); i++)
 
1022
        {
 
1023
      if(static_cast<Worker*>(i->get(g))->get_name()==name)
 
1024
                {
 
1025
                        soldier = static_cast<Soldier*>(i->get(g));
 
1026
 
 
1027
                        // Its a marked soldier, we cann't supply it !
 
1028
                        if (!soldier->is_marked())
 
1029
                        {
 
1030
                                if (r)
 
1031
                                {
 
1032
                                        if (r->check (  soldier->get_level(atrHP),
 
1033
                                                                                soldier->get_level(atrAttack),
 
1034
                                                                                soldier->get_level(atrDefense),
 
1035
                                                                                soldier->get_level(atrEvade)))
 
1036
                                        {
 
1037
                                                log ("+");
 
1038
                                                number++;
 
1039
                                        }
 
1040
                                }
 
1041
                                else
 
1042
                                {
 
1043
                                        log ("+");
 
1044
                                        number++;
 
1045
                                }
 
1046
                        }
 
1047
                        else
 
1048
                                log ("M");
 
1049
                }
 
1050
        }
 
1051
        log ("\n");
 
1052
        return number;
 
1053
}
 
1054
 
 
1055
 
 
1056
/*
 
1057
===============
 
1058
Warehouse::can_create_worker
 
1059
===============
 
1060
*/
 
1061
bool Warehouse::can_create_worker(Game *g, int worker)
 
1062
{
 
1063
        Worker_Descr *w_desc = 0;
 
1064
        
 
1065
        if (worker >= m_supply->get_workers().get_nrwareids()) {
 
1066
                throw wexception ("Worker type %d doesn't exists! (max is %d)", worker,
 
1067
            m_supply->get_workers().get_nrwareids());
 
1068
   }
 
1069
 
 
1070
   w_desc=get_owner()->get_tribe()->get_worker_descr(worker);
 
1071
 
 
1072
        if (w_desc)
 
1073
        {
 
1074
                uint i;
 
1075
                bool enought_wares;
 
1076
                const Worker_Descr::BuildCost* bc = w_desc->get_buildcost();
 
1077
                
 
1078
                // First watch if we can build it
 
1079
                if (!w_desc->get_buildable())
 
1080
                        return false;
 
1081
                enought_wares = true;
 
1082
 
 
1083
                // Now see if we have the resources
 
1084
                for(i = 0; i < bc->size(); i++) 
 
1085
                {
 
1086
                        int id_w;
 
1087
                        
 
1088
         
 
1089
                        id_w = get_owner()->get_tribe()->get_ware_index((*bc)[i].name.c_str()); 
 
1090
         if(id_w!=-1) {
 
1091
            if (m_supply->stock_wares(id_w) < (*bc)[i].amount)
 
1092
            {
 
1093
               molog (" %s: Need more %s for creation\n", w_desc->get_name(), (*bc)[i].name.c_str());
 
1094
               enought_wares = false;
 
1095
            }
 
1096
         } else {
 
1097
            id_w = get_owner()->get_tribe()->get_safe_worker_index((*bc)[i].name.c_str()); 
 
1098
            if (m_supply->stock_workers(id_w) < (*bc)[i].amount) {
 
1099
               molog (" %s: Need more %s for creation\n", w_desc->get_name(), (*bc)[i].name.c_str());
 
1100
               enought_wares = false;
 
1101
            }
 
1102
         }
 
1103
                }
 
1104
                return enought_wares;
 
1105
        }
 
1106
        else
 
1107
                throw wexception("Can not create worker of desired type : %d", worker);
 
1108
}
 
1109
 
 
1110
/*
 
1111
=============
 
1112
Warehouse::create_worker
 
1113
+=============
 
1114
*/
 
1115
void Warehouse::create_worker(Game *g, int worker)
 
1116
{
 
1117
        Worker_Descr *w_desc = 0;
 
1118
        
 
1119
        if (!can_create_worker (g, worker))
 
1120
                throw wexception ("Warehouse::create_worker WE CANN'T CREATE A %d WORKER", worker);
 
1121
 
 
1122
   w_desc=get_owner()->get_tribe()->get_worker_descr(worker);
 
1123
 
 
1124
        if (w_desc)
 
1125
        {
 
1126
                uint i;
 
1127
                const Worker_Descr::BuildCost* bc = w_desc->get_buildcost();
 
1128
                
 
1129
                for(i = 0; i < bc->size(); i++) {
 
1130
                        int id_w;
 
1131
                        id_w = get_owner()->get_tribe()->get_ware_index((*bc)[i].name.c_str());
 
1132
         if(id_w!=-1) {
 
1133
            remove_wares(id_w , (*bc)[i].amount);
 
1134
         } else {
 
1135
            id_w = get_owner()->get_tribe()->get_safe_worker_index((*bc)[i].name.c_str());
 
1136
            remove_workers(id_w , (*bc)[i].amount);
 
1137
         }
 
1138
                }
 
1139
 
 
1140
                // This is needed to have a 0 level soldiers
 
1141
                Worker* w;
 
1142
 
 
1143
                w = w_desc->create(g, get_owner(), this, m_position);
 
1144
 
 
1145
                incorporate_worker(g, w);
 
1146
 
 
1147
                molog (" We have created a(n) %s\n", w_desc->get_name ());
 
1148
 
 
1149
        }
 
1150
        else
 
1151
                throw wexception("Can not create worker of desired type : %d", worker);
 
1152
 
 
1153
        
 
1154
}
 
1155
 
 
1156
/// Down here, only military methods !! ;)
 
1157
 
 
1158
bool Warehouse::has_soldiers()
 
1159
{
 
1160
   Worker_Descr* workerdescr;
 
1161
   Soldier* soldier;
 
1162
 
 
1163
   workerdescr = get_owner()->get_tribe()->get_worker_descr (
 
1164
                     get_owner()->get_tribe()->get_safe_worker_index ("soldier"));
 
1165
   
 
1166
   // Look if we got one in stock of soldiers
 
1167
   std::string name=workerdescr->get_name();
 
1168
   std::vector<Object_Ptr>::iterator i;
 
1169
   for(i=m_incorporated_workers.begin(); i!=m_incorporated_workers.end(); i++)
 
1170
   {
 
1171
      if(static_cast<Worker*>(i->get(get_owner()->get_game()))->get_name()==name)
 
1172
      {
 
1173
         soldier = static_cast<Soldier*>(i->get(get_owner()->get_game()));
 
1174
         break;
 
1175
      }
 
1176
   }
 
1177
   return (i!=m_incorporated_workers.end());
 
1178
}
 
1179
 
 
1180
void Warehouse::defend (Game* g, Soldier* s)
 
1181
{
 
1182
   assert(s);
 
1183
   molog ("[Warehouse] We are under attack of %d!\n", s->get_serial());
 
1184
 
 
1185
   Worker_Descr* workerdescr;
 
1186
   Soldier* soldier;
 
1187
 
 
1188
   workerdescr = get_owner()->get_tribe()->get_worker_descr (
 
1189
                     get_owner()->get_tribe()->get_safe_worker_index ("soldier"));
 
1190
   
 
1191
   // Look if we got one in stock of soldiers
 
1192
   std::string name=workerdescr->get_name();
 
1193
   std::vector<Object_Ptr>::iterator i;
 
1194
   for(i=m_incorporated_workers.begin(); i!=m_incorporated_workers.end(); i++)
 
1195
   {
 
1196
      if(static_cast<Worker*>(i->get(g))->get_name()==name)
 
1197
      {
 
1198
         soldier = static_cast<Soldier*>(i->get(g));
 
1199
         break;
 
1200
      }
 
1201
   }
 
1202
 
 
1203
   if (i != m_incorporated_workers.end())
 
1204
   {
 
1205
      // TODO: Here may be extra checks
 
1206
      for(i = m_incorporated_workers.begin(); i != m_incorporated_workers.end(); i++)
 
1207
      {
 
1208
         if(static_cast<Worker*>(i->get(g))->get_name() == name)
 
1209
         {
 
1210
            soldier = static_cast<Soldier*>(i->get(g));
 
1211
            if (soldier->is_marked ())
 
1212
               continue;
 
1213
 
 
1214
            soldier->mark(true);
 
1215
            soldier->reset_tasks (g);
 
1216
            soldier->set_location (this);
 
1217
            soldier->start_task_defendbuilding (g, this, s);
 
1218
            break;
 
1219
         }
 
1220
      }
 
1221
      if (i == m_incorporated_workers.end())
 
1222
         s->send_signal(g, "fail");
 
1223
   }
 
1224
}
 
1225
 
 
1226
// A warhouse couldn't be conquered, this building is destroyed ...
 
1227
void Warehouse::conquered_by (Player* pl)
 
1228
{
 
1229
   molog ("Warehouse::conquered_by- ");
 
1230
   assert (pl);
 
1231
   molog ("destroying\n");
 
1232
   cleanup(pl->get_game());
 
1233
}
 
1234
 
 
1235