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

« back to all changes in this revision

Viewing changes to src/tribe.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 by the 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 <iostream>
 
21
#include "editor_game_base.h"
 
22
#include "error.h"
 
23
#include "filesystem.h"
 
24
#include "game.h"
 
25
#include "profile.h"
 
26
#include "world.h"
 
27
#include "soldier.h"
 
28
#include "tribe.h"
 
29
#include "util.h"
 
30
#include "warehouse.h"
 
31
#include "wexception.h"
 
32
#include "worker.h"
 
33
 
 
34
using namespace std;
 
35
 
 
36
//
 
37
// Tribe_Descr class
 
38
//
 
39
Tribe_Descr::Tribe_Descr(const char* name)
 
40
{
 
41
        snprintf(m_name, sizeof(m_name), "%s", name);
 
42
 
 
43
        try
 
44
        {
 
45
                char directory[256];
 
46
 
 
47
                snprintf(directory, sizeof(directory), "tribes/%s", name);
 
48
 
 
49
                m_default_encdata.clear();
 
50
      parse_wares(directory);
 
51
                parse_buildings(directory);
 
52
                parse_workers(directory);
 
53
      parse_bobs(directory);
 
54
      parse_root_conf(directory);
 
55
        }
 
56
        catch(std::exception &e)
 
57
        {
 
58
                throw wexception("Error loading tribe %s: %s", name, e.what());
 
59
        }
 
60
}
 
61
 
 
62
Tribe_Descr::~Tribe_Descr(void)
 
63
{
 
64
}
 
65
 
 
66
 
 
67
/*
 
68
===============
 
69
Tribe_Descr::postload
 
70
 
 
71
Load all logic data
 
72
===============
 
73
*/
 
74
void Tribe_Descr::postload(Editor_Game_Base* g)
 
75
{
 
76
        // TODO: move more loads to postload
 
77
}
 
78
 
 
79
/*
 
80
===============
 
81
Tribe_Descr::load_graphics
 
82
 
 
83
Load tribe graphics
 
84
===============
 
85
*/
 
86
void Tribe_Descr::load_graphics()
 
87
{
 
88
        int i;
 
89
 
 
90
        for(i = 0; i < m_workers.get_nitems(); i++)
 
91
                m_workers.get(i)->load_graphics();
 
92
        
 
93
   for(i = 0; i < m_wares.get_nitems(); i++)
 
94
                m_wares.get(i)->load_graphics();
 
95
 
 
96
        for(i = 0; i < m_buildings.get_nitems(); i++)
 
97
                m_buildings.get(i)->load_graphics();
 
98
}
 
99
 
 
100
 
 
101
//
 
102
// down here: private read functions for loading
 
103
//
 
104
 
 
105
/*
 
106
===============
 
107
Tribe_Descr::parse_root_conf
 
108
 
 
109
Read and process the main conf file
 
110
===============
 
111
*/
 
112
void Tribe_Descr::parse_root_conf(const char *directory)
 
113
{
 
114
        char fname[256];
 
115
 
 
116
        snprintf(fname, sizeof(fname), "%s/conf", directory);
 
117
 
 
118
        try
 
119
        {
 
120
                Profile prof(fname);
 
121
                Section *s;
 
122
 
 
123
                // Section [tribe]
 
124
                s = prof.get_safe_section("tribe");
 
125
 
 
126
                s->get_string("author");
 
127
                s->get_string("name"); // descriptive name
 
128
                s->get_string("descr"); // long description
 
129
 
 
130
                // Section [defaults]
 
131
                s = prof.get_section("defaults");
 
132
 
 
133
                if (s)
 
134
                        m_default_encdata.parse(s);
 
135
 
 
136
                // Section [frontier]
 
137
                s = prof.get_section("frontier");
 
138
                if (!s)
 
139
                        throw wexception("Missing section [frontier]");
 
140
 
 
141
                m_anim_frontier = g_anim.get(directory, s, 0, &m_default_encdata);
 
142
 
 
143
                // Section [flag]
 
144
                s = prof.get_section("flag");
 
145
                if (!s)
 
146
                        throw wexception("Missing section [flag]");
 
147
 
 
148
                m_anim_flag = g_anim.get(directory, s, 0, &m_default_encdata);
 
149
 
 
150
      // default wares
 
151
      s = prof.get_safe_section("startwares");
 
152
           Section::Value* value;
 
153
 
 
154
      while((value=s->get_next_val(0))) {
 
155
         int idx = m_wares.get_index(value->get_name());
 
156
         if(idx == -1)
 
157
            throw wexception("In section [startwares], ware %s is not know!", value->get_name());
 
158
 
 
159
         std::string name=value->get_name();
 
160
         m_startwares[name]=value->get_int();
 
161
      }
 
162
 
 
163
      // default workers
 
164
      s = prof.get_safe_section("startworkers");
 
165
      while((value=s->get_next_val(0))) {
 
166
         if(!strcmp(value->get_name(),"soldier")) continue; // Ignore soldiers here
 
167
         int idx = m_workers.get_index(value->get_name());
 
168
         if(idx == -1)
 
169
            throw wexception("In section [startworkers], worker %s is not know!", value->get_name());
 
170
 
 
171
         std::string name=value->get_name();
 
172
         m_startworkers[name]=value->get_int();
 
173
      }
 
174
   
 
175
      // default soldiers
 
176
      s = prof.get_safe_section("startsoldiers");
 
177
      while((value=s->get_next_val(0))) {
 
178
         // NOTE: no check here, since we do not know about max levels and so on
 
179
         std::string soldier=value->get_name();
 
180
         m_startsoldiers[soldier]=value->get_int();
 
181
      }
 
182
   }
 
183
   catch(std::exception &e) {
 
184
      throw wexception("%s: %s", fname, e.what());
 
185
   }
 
186
}
 
187
 
 
188
 
 
189
/*
 
190
===============
 
191
Tribe_Descr::parse_buildings
 
192
 
 
193
Read all the building descriptions
 
194
===============
 
195
*/
 
196
void Tribe_Descr::parse_buildings(const char *rootdir)
 
197
{
 
198
        char subdir[256];
 
199
        filenameset_t dirs;
 
200
 
 
201
        snprintf(subdir, sizeof(subdir), "%s/buildings", rootdir);
 
202
 
 
203
        g_fs->FindFiles(subdir, "*", &dirs);
 
204
 
 
205
        for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
 
206
                Building_Descr *descr = 0;
 
207
 
 
208
                try {
 
209
                        descr = Building_Descr::create_from_dir(this, it->c_str(), &m_default_encdata);
 
210
                } catch(std::exception &e) {
 
211
                        log("Building %s failed: %s (garbage directory?)\n", it->c_str(), e.what());
 
212
                } catch(...) {
 
213
                        log("Building %s failed: unknown exception (garbage directory?)\n", it->c_str());
 
214
                }
 
215
 
 
216
                if (descr)
 
217
                        m_buildings.add(descr);
 
218
        }
 
219
}
 
220
 
 
221
 
 
222
/*
 
223
===============
 
224
Tribe_Descr::parse_workers
 
225
 
 
226
Read all worker descriptions
 
227
===============
 
228
*/
 
229
void Tribe_Descr::parse_workers(const char *directory)
 
230
{
 
231
        char subdir[256];
 
232
        filenameset_t dirs;
 
233
 
 
234
        snprintf(subdir, sizeof(subdir), "%s/workers", directory);
 
235
 
 
236
        g_fs->FindFiles(subdir, "*", &dirs);
 
237
 
 
238
        for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
 
239
                Worker_Descr *descr = 0;
 
240
 
 
241
                try {
 
242
                        descr = Worker_Descr::create_from_dir(this, it->c_str(), &m_default_encdata);
 
243
                } catch(std::exception &e) {
 
244
                        log("Worker %s failed: %s (garbage directory?)\n", it->c_str(), e.what());
 
245
                } catch(...) {
 
246
                        log("Worker %s failed: unknown exception (garbage directory?)\n", it->c_str());
 
247
                }
 
248
 
 
249
                if (descr)
 
250
                        m_workers.add(descr);
 
251
        }
 
252
}
 
253
 
 
254
/*
 
255
===============
 
256
Tribe_Descr::parse_wares
 
257
 
 
258
Parse the wares belonging to this tribe, adding it to the games warelist. This is delayed until the game starts,
 
259
and is called by the Game class
 
260
===============
 
261
*/
 
262
void Tribe_Descr::parse_wares(const char* directory)
 
263
{
 
264
   Descr_Maintainer<Item_Ware_Descr>* wares=&m_wares;
 
265
   char subdir[256];
 
266
        filenameset_t dirs;
 
267
 
 
268
        snprintf(subdir, sizeof(subdir), "%s/wares", directory);
 
269
 
 
270
        g_fs->FindFiles(subdir, "*", &dirs);
 
271
 
 
272
        for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
 
273
                char fname[256];
 
274
 
 
275
                snprintf(fname, sizeof(fname), "%s/conf", it->c_str());
 
276
 
 
277
                if (!g_fs->FileExists(fname))
 
278
                        continue;
 
279
 
 
280
                const char *name;
 
281
                const char *slash = strrchr(it->c_str(), '/');
 
282
                const char *backslash = strrchr(it->c_str(), '\\');
 
283
 
 
284
                if (backslash && (!slash || backslash > slash))
 
285
                        slash = backslash;
 
286
 
 
287
                if (slash)
 
288
                        name = slash+1;
 
289
                else
 
290
                        name = it->c_str();
 
291
 
 
292
                if (wares->get_index(name) >= 0)
 
293
                        log("Ware %s is already known in world init\n", it->c_str());
 
294
 
 
295
                Item_Ware_Descr* descr = 0;
 
296
 
 
297
                try
 
298
                {
 
299
                        descr = Item_Ware_Descr::create_from_dir(name, it->c_str());
 
300
                }
 
301
                catch(std::exception& e)
 
302
                {
 
303
                        cerr << it->c_str() << ": " << e.what() << " (garbage directory?)" << endl;
 
304
                }
 
305
                catch(...)
 
306
                {
 
307
                        cerr << it->c_str() << ": Unknown exception" << endl;
 
308
                }
 
309
 
 
310
                if (descr)
 
311
                        wares->add(descr);
 
312
        }
 
313
}
 
314
 
 
315
/*
 
316
 * Parse the player bobs (animations, immovables, critters)
 
317
 */
 
318
void Tribe_Descr::parse_bobs(const char* directory) {
 
319
        char subdir[256];
 
320
        filenameset_t dirs;
 
321
 
 
322
        snprintf(subdir, sizeof(subdir), "%s/bobs", directory);
 
323
 
 
324
        g_fs->FindFiles(subdir, "*", &dirs);
 
325
 
 
326
        for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
 
327
                char fname[256];
 
328
 
 
329
                snprintf(fname, sizeof(fname), "%s/conf", it->c_str());
 
330
 
 
331
                if (!g_fs->FileExists(fname))
 
332
                        continue;
 
333
 
 
334
                const char *name;
 
335
                const char *slash = strrchr(it->c_str(), '/');
 
336
                const char *backslash = strrchr(it->c_str(), '\\');
 
337
 
 
338
                if (backslash && (!slash || backslash > slash))
 
339
                        slash = backslash;
 
340
 
 
341
                if (slash)
 
342
                        name = slash+1;
 
343
                else
 
344
                        name = it->c_str();
 
345
 
 
346
                try
 
347
                {
 
348
                        Profile prof(fname, "global"); // section-less file
 
349
                        Section *s = prof.get_safe_section("global");
 
350
                        const char *type = s->get_safe_string("type");
 
351
 
 
352
                        if (!strcasecmp(type, "critter")) {
 
353
                                Bob_Descr *descr;
 
354
                                descr = Bob_Descr::create_from_dir(name, it->c_str(), &prof, this);
 
355
                                m_bobs.add(descr);
 
356
                        } else {
 
357
                                Immovable_Descr *descr = new Immovable_Descr(name, this);
 
358
                                descr->parse(it->c_str(), &prof);
 
359
                                m_immovables.add(descr);
 
360
                        }
 
361
                } catch(std::exception &e) {
 
362
                        cerr << it->c_str() << ": " << e.what() << " (garbage directory?)" << endl;
 
363
                } catch(...) {
 
364
                        cerr << it->c_str() << ": unknown exception (garbage directory?)" << endl;
 
365
                }
 
366
        }
 
367
}
 
368
 
 
369
/*
 
370
===========
 
371
void Tribe_Descr::load_warehouse_with_start_wares()
 
372
 
 
373
This loads a warehouse with the given start wares as defined in
 
374
the conf files
 
375
===========
 
376
*/
 
377
void Tribe_Descr::load_warehouse_with_start_wares(Editor_Game_Base* egbase, Warehouse* wh) {
 
378
   std::map<std::string, int>::iterator cur;
 
379
   
 
380
   for(cur=m_startwares.begin(); cur!=m_startwares.end(); cur++) {
 
381
      wh->insert_wares(get_safe_ware_index((*cur).first.c_str()), (*cur).second);
 
382
   }
 
383
   for(cur=m_startworkers.begin(); cur!=m_startworkers.end(); cur++) {
 
384
      wh->insert_workers(get_safe_worker_index((*cur).first.c_str()), (*cur).second);
 
385
   }
 
386
   for(cur=m_startsoldiers.begin(); cur!=m_startsoldiers.end(); cur++) {
 
387
      std::vector<std::string> list;
 
388
      split_string(cur->first, &list, "/");
 
389
 
 
390
      if(list.size()!=4) 
 
391
         throw wexception("Error in tribe (%s), startsoldier %s is not valid!", get_name(), cur->first.c_str());
 
392
 
 
393
      char* endp;
 
394
      int hplvl=strtol(list[0].c_str(),&endp, 0);
 
395
      if(endp && *endp)
 
396
         throw wexception("Bad hp level '%s'", list[0].c_str());
 
397
      int attacklvl=strtol(list[1].c_str(),&endp, 0);
 
398
      if(endp && *endp)
 
399
         throw wexception("Bad attack level '%s'", list[1].c_str());
 
400
      int defenselvl=strtol(list[2].c_str(),&endp, 0);
 
401
      if(endp && *endp)
 
402
         throw wexception("Bad defense level '%s'", list[2].c_str());
 
403
      int evadelvl=strtol(list[3].c_str(),&endp, 0);
 
404
      if(endp && *endp)
 
405
         throw wexception("Bad evade level '%s'", list[3].c_str());
 
406
  
 
407
      int i=0;
 
408
      for(i=0;i<cur->second; i++) {
 
409
         if(egbase->is_game()) { 
 
410
            Game* game=static_cast<Game*>(egbase);
 
411
            Soldier_Descr* soldierd=static_cast<Soldier_Descr*>(get_worker_descr(get_worker_index("soldier")));
 
412
            Soldier* soldier=static_cast<Soldier*>(soldierd->create(game, wh->get_owner(), wh, wh->get_position()));
 
413
            soldier->set_level(hplvl,attacklvl,defenselvl,evadelvl);
 
414
            wh->incorporate_worker(game, soldier);
 
415
         } 
 
416
      }
 
417
      //TODO: What to do in editor
 
418
   }
 
419
}
 
420
 
 
421
 
 
422
/*
 
423
 * does this tribe exist?
 
424
 */
 
425
bool Tribe_Descr::exists_tribe(std::string name) {
 
426
   std::string buf;
 
427
   buf="tribes/" + name + "/conf";;
 
428
 
 
429
   FileRead f;
 
430
   return f.TryOpen(g_fs, buf.c_str());
 
431
}
 
432
 
 
433
/*
 
434
 * Returns all tribes that exists
 
435
 */
 
436
void Tribe_Descr::get_all_tribes(std::vector<std::string>* retval) {
 
437
   retval->resize(0);
 
438
 
 
439
   // get all tribes
 
440
   filenameset_t m_tribes;
 
441
   g_fs->FindFiles("tribes", "*", &m_tribes);
 
442
   for(filenameset_t::iterator pname = m_tribes.begin(); pname != m_tribes.end(); pname++) {
 
443
      std::string tribe=*pname;
 
444
      tribe.erase(0,7); // remove 'tribes/'
 
445
      if(Tribe_Descr::exists_tribe(tribe.c_str()))
 
446
         retval->push_back(tribe);
 
447
   }
 
448
}
 
449
 
 
450
/*
 
451
==============
 
452
Resource_Descr::get_indicator
 
453
 
 
454
Find the best matching indicator for the given amount.
 
455
==============
 
456
*/
 
457
int Tribe_Descr::get_resource_indicator(Resource_Descr *res, uint amount)
 
458
{
 
459
   if(!res || !amount) {
 
460
      int idx=get_immovable_index("resi_none");
 
461
      if(idx==-1) 
 
462
         throw wexception("Tribe %s doesn't declare a resource indicator resi_none!\n", get_name());
 
463
      return idx;
 
464
   }
 
465
   
 
466
   char buffer[256];
 
467
 
 
468
   int i=1;
 
469
   int num_indicators=0;
 
470
   while(true) {
 
471
      sprintf(buffer, "resi_%s%i", res->get_name(), i);
 
472
      if(get_immovable_index(buffer)==-1) 
 
473
         break;
 
474
      ++i;
 
475
      ++num_indicators;
 
476
   }
 
477
  
 
478
   if(!num_indicators) {
 
479
      // Upsy, no indicators for this resource
 
480
      throw wexception("Tribe %s doesn't declar a resource indicator for resource %s!\n", get_name(), res->get_name());
 
481
   }
 
482
   
 
483
   uint bestmatch = (uint) (( static_cast<float>(amount)/res->get_max_amount() ) * num_indicators);
 
484
   if(((int)amount)<res->get_max_amount()) 
 
485
      bestmatch+=1; // Resi start with 1, not 0
 
486
 
 
487
   sprintf(buffer, "resi_%s%i", res->get_name(), bestmatch);
 
488
 
 
489
        // NoLog("Resource(%s): Indicator '%s' for amount = %u\n",
 
490
        //      res->get_name(), buffer, amount);
 
491
 
 
492
 
 
493
   
 
494
        return get_immovable_index(buffer);
 
495
}
 
496
 
 
497
/*
 
498
 * Return the given ware or die trying
 
499
 */
 
500
int Tribe_Descr::get_safe_ware_index(const char *name) {
 
501
   int retval=get_ware_index(name);
 
502
 
 
503
   if(retval==-1) 
 
504
      throw wexception("Tribe_Descr::get_safe_ware_index: Unknown ware %s!", name);
 
505
   return retval;
 
506
}
 
507
 
 
508
/*
 
509
 * Return the given worker or die trying
 
510
 */
 
511
int Tribe_Descr::get_safe_worker_index(const char *name) {
 
512
   int retval=get_worker_index(name);
 
513
 
 
514
   if(retval==-1) 
 
515
      throw wexception("Tribe_Descr::get_safe_worker_index: Unknown worker %s!", name);
 
516
   return retval;
 
517
}
 
518
 
 
519
/*
 
520
 * Return the given building or die trying
 
521
 */
 
522
int Tribe_Descr::get_safe_building_index(const char *name) {
 
523
   int retval=get_building_index(name);
 
524
 
 
525
   if(retval==-1) 
 
526
      throw wexception("Tribe_Descr::get_safe_building_index: Unknown building %s!", name);
 
527
   return retval;
 
528
}
 
529