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

« back to all changes in this revision

Viewing changes to src/world.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 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 <sstream>
 
22
#include "constants.h"
 
23
#include "filesystem.h"
 
24
#include "graphic.h"
 
25
#include "profile.h"
 
26
#include "wexception.h"
 
27
#include "world.h"
 
28
#include "worlddata.h"
 
29
#include "util.h"
 
30
#include "error.h"
 
31
 
 
32
using std::cerr;
 
33
using std::endl;
 
34
 
 
35
/*
 
36
=============================================================================
 
37
 
 
38
Resource_Descr
 
39
 
 
40
=============================================================================
 
41
*/
 
42
 
 
43
/*
 
44
==============
 
45
Resource_Descr::parse
 
46
 
 
47
Parse a resource description section.
 
48
==============
 
49
*/
 
50
void Resource_Descr::parse(Section *s, std::string basedir)
 
51
{
 
52
   const char* string;
 
53
 
 
54
 
 
55
   m_name=s->get_name();
 
56
   m_descrname = s->get_string("name", s->get_name());
 
57
   m_is_detectable=s->get_bool("detectable", true);
 
58
 
 
59
   m_max_amount = s->get_safe_int("max_amount");
 
60
   while(s->get_next_string("editor_pic", &string))
 
61
   {
 
62
      std::vector<std::string> args;
 
63
      Editor_Pic i;
 
64
 
 
65
      split_string(string, &args, " \t");
 
66
 
 
67
      if (args.size() != 1 && args.size() != 2)
 
68
      {
 
69
         log("Resource '%s' has bad editor_pic=%s\n", m_name.c_str(), string);
 
70
         continue;
 
71
      }
 
72
 
 
73
      i.picname = basedir + "/pics/";
 
74
      i.picname += args[0];
 
75
      i.upperlimit = -1;
 
76
 
 
77
      if (args.size() >= 2)
 
78
      {
 
79
         char* endp;
 
80
 
 
81
         i.upperlimit = strtol(args[1].c_str(), &endp, 0);
 
82
 
 
83
         if (endp && *endp)
 
84
         {
 
85
            log("Resource '%s' has bad editor_pic=%s\n", m_name.c_str(), string);
 
86
            continue;
 
87
         }
 
88
      }
 
89
 
 
90
      m_editor_pics.push_back(i);
 
91
   }
 
92
   if(!m_editor_pics.size())
 
93
      throw wexception("Resource '%s' has no editor_pic", m_name.c_str());
 
94
}
 
95
 
 
96
 
 
97
/*
 
98
 * Get the correct editor pic for this amount of this resource
 
99
 */
 
100
std::string Resource_Descr::get_editor_pic(uint amount) {
 
101
        uint bestmatch = 0;
 
102
 
 
103
        assert(m_editor_pics.size());
 
104
 
 
105
        for(uint i = 1; i < m_editor_pics.size(); ++i)
 
106
        {
 
107
                int diff1 = m_editor_pics[bestmatch].upperlimit - (int)amount;
 
108
                int diff2 = m_editor_pics[i].upperlimit - (int)amount;
 
109
 
 
110
                // This is a catch-all for high amounts
 
111
                if (m_editor_pics[i].upperlimit < 0)
 
112
                {
 
113
                        if (diff1 < 0) {
 
114
                                bestmatch = i;
 
115
                                continue;
 
116
                        }
 
117
 
 
118
                        continue;
 
119
                }
 
120
 
 
121
                // This is lower than the actual amount
 
122
                if (diff2 < 0)
 
123
                {
 
124
                        if (m_editor_pics[bestmatch].upperlimit < 0)
 
125
                                continue;
 
126
 
 
127
                        if (diff1 < diff2) {
 
128
                                bestmatch = i; // still better than previous best match
 
129
                                continue;
 
130
                        }
 
131
 
 
132
                        continue;
 
133
                }
 
134
 
 
135
                // This is higher than the actual amount
 
136
                if (m_editor_pics[bestmatch].upperlimit < 0 || diff1 > diff2 || diff1 < 0) {
 
137
                        bestmatch = i;
 
138
                        continue;
 
139
                }
 
140
        }
 
141
 
 
142
//      noLog("Resource(%s): Editor_Pic '%s' for amount = %u\n",
 
143
//              m_name.c_str(), m_editor_pics[bestmatch].picname.c_str(), amount);
 
144
 
 
145
        return m_editor_pics[bestmatch].picname;
 
146
}
 
147
 
 
148
 
 
149
/*
 
150
=============================================================================
 
151
 
 
152
World
 
153
 
 
154
=============================================================================
 
155
*/
 
156
 
 
157
World::World(const char* name)
 
158
{
 
159
        char directory[256];
 
160
 
 
161
        try
 
162
        {
 
163
                snprintf(directory, sizeof(directory), "worlds/%s", name);
 
164
                m_basedir = directory;
 
165
 
 
166
                parse_root_conf(name);
 
167
                parse_resources();
 
168
                parse_terrains();
 
169
                parse_bobs();
 
170
        }
 
171
        catch(std::exception &e)
 
172
        {
 
173
                // tag with world name
 
174
                throw wexception("Error loading world %s: %s", name, e.what());
 
175
        }
 
176
}
 
177
 
 
178
World::~World(void)
 
179
{
 
180
 
 
181
}
 
182
 
 
183
 
 
184
/*
 
185
===============
 
186
World::postload
 
187
 
 
188
Load all logic game data now
 
189
===============
 
190
*/
 
191
void World::postload(Editor_Game_Base* g)
 
192
{
 
193
        // TODO: move more loads to postload
 
194
}
 
195
 
 
196
 
 
197
/*
 
198
===============
 
199
World::load_graphics
 
200
 
 
201
Load graphics data here
 
202
===============
 
203
*/
 
204
void World::load_graphics()
 
205
{
 
206
        int i;
 
207
 
 
208
        // Load terrain graphics
 
209
        for(i = 0; i < ters.get_nitems(); i++)
 
210
                ters.get(i)->load_graphics();
 
211
 
 
212
        // TODO: load more graphics
 
213
}
 
214
 
 
215
 
 
216
//
 
217
// down here: Private functions for loading
 
218
//
 
219
 
 
220
//
 
221
// read the <world-directory>/conf
 
222
//
 
223
void World::parse_root_conf(const char *name)
 
224
{
 
225
        char fname[256];
 
226
 
 
227
        snprintf(fname, sizeof(fname), "%s/conf", m_basedir.c_str());
 
228
 
 
229
        try
 
230
        {
 
231
                Profile prof(fname);
 
232
                Section* s;
 
233
 
 
234
                s = prof.get_safe_section("world");
 
235
 
 
236
                const char* str;
 
237
 
 
238
                str = s->get_string("name", name);
 
239
                snprintf(hd.name, sizeof(hd.name), "%s", str);
 
240
 
 
241
                str = s->get_safe_string("author");
 
242
                snprintf(hd.author, sizeof(hd.author), "%s", str);
 
243
 
 
244
                str = s->get_safe_string("descr");
 
245
                snprintf(hd.descr, sizeof(hd.descr), "%s", str);
 
246
 
 
247
                prof.check_used();
 
248
        }
 
249
        catch(std::exception &e) {
 
250
                throw wexception("%s: %s", fname, e.what());
 
251
        }
 
252
}
 
253
 
 
254
void World::parse_resources()
 
255
{
 
256
        char fname[256];
 
257
 
 
258
        snprintf(fname, sizeof(fname), "%s/resconf", m_basedir.c_str());
 
259
 
 
260
        try
 
261
        {
 
262
                Profile prof(fname);
 
263
      Section* section;
 
264
 
 
265
      Resource_Descr* descr;
 
266
      while((section=prof.get_next_section(0))) {
 
267
         descr=new Resource_Descr();
 
268
         descr->parse(section,m_basedir);
 
269
         m_resources.add(descr);
 
270
      }
 
271
        }
 
272
        catch(std::exception &e) {
 
273
                throw wexception("%s: %s", fname, e.what());
 
274
        }
 
275
}
 
276
 
 
277
void World::parse_terrains()
 
278
{
 
279
        char fname[256];
 
280
 
 
281
        snprintf(fname, sizeof(fname), "%s/terrainconf", m_basedir.c_str());
 
282
 
 
283
        try
 
284
        {
 
285
                Profile prof(fname);
 
286
                Section* s;
 
287
 
 
288
                while((s = prof.get_next_section(0)))
 
289
                {
 
290
                        Terrain_Descr *ter = new Terrain_Descr(m_basedir.c_str(), s, &m_resources);
 
291
                        ters.add(ter);
 
292
                }
 
293
 
 
294
                prof.check_used();
 
295
        }
 
296
        catch(std::exception &e) {
 
297
                throw wexception("%s: %s", fname, e.what());
 
298
        }
 
299
}
 
300
 
 
301
void World::parse_bobs()
 
302
{
 
303
        char subdir[256];
 
304
        filenameset_t dirs;
 
305
 
 
306
        snprintf(subdir, sizeof(subdir), "%s/bobs", m_basedir.c_str());
 
307
 
 
308
        g_fs->FindFiles(subdir, "*", &dirs);
 
309
 
 
310
        for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
 
311
                char fname[256];
 
312
 
 
313
                snprintf(fname, sizeof(fname), "%s/conf", it->c_str());
 
314
 
 
315
                if (!g_fs->FileExists(fname))
 
316
                        continue;
 
317
 
 
318
                const char *name;
 
319
                const char *slash = strrchr(it->c_str(), '/');
 
320
                const char *backslash = strrchr(it->c_str(), '\\');
 
321
 
 
322
                if (backslash && (!slash || backslash > slash))
 
323
                        slash = backslash;
 
324
 
 
325
                if (slash)
 
326
                        name = slash+1;
 
327
                else
 
328
                        name = it->c_str();
 
329
 
 
330
                try
 
331
                {
 
332
                        Profile prof(fname, "global"); // section-less file
 
333
                        Section *s = prof.get_safe_section("global");
 
334
                        const char *type = s->get_safe_string("type");
 
335
 
 
336
                        if (!strcasecmp(type, "critter")) {
 
337
                                Bob_Descr *descr;
 
338
                                descr = Bob_Descr::create_from_dir(name, it->c_str(), &prof, 0);
 
339
                                bobs.add(descr);
 
340
                        } else {
 
341
                                Immovable_Descr *descr = new Immovable_Descr(name, 0);
 
342
                                descr->parse(it->c_str(), &prof);
 
343
                                immovables.add(descr);
 
344
                        }
 
345
                } catch(std::exception &e) {
 
346
                        cerr << it->c_str() << ": " << e.what() << " (garbage directory?)" << endl;
 
347
                } catch(...) {
 
348
                        cerr << it->c_str() << ": unknown exception (garbage directory?)" << endl;
 
349
                }
 
350
        }
 
351
}
 
352
 
 
353
/*
 
354
 * World::exists_world()
 
355
 */
 
356
bool World::exists_world(std::string worldname) {
 
357
   std::string buf;
 
358
   buf="worlds/" + worldname + "/conf";;
 
359
 
 
360
   FileRead f;
 
361
   return f.TryOpen(g_fs, buf.c_str());
 
362
}
 
363
 
 
364
/*
 
365
 * World::get_all_worlds()
 
366
 */
 
367
void World::get_all_worlds(std::vector<std::string>* retval) {
 
368
   retval->resize(0);
 
369
 
 
370
   // get all worlds
 
371
   filenameset_t m_worlds;
 
372
   g_fs->FindFiles("worlds", "*", &m_worlds);
 
373
   for(filenameset_t::iterator pname = m_worlds.begin(); pname != m_worlds.end(); pname++) {
 
374
      std::string world=*pname;
 
375
      world.erase(0,7); // remove worlds/
 
376
      if(World::exists_world(world.c_str()))
 
377
         retval->push_back(world);
 
378
   }
 
379
}
 
380
 
 
381
 
 
382
/*
 
383
==============================================================================
 
384
 
 
385
Terrain_Descr
 
386
 
 
387
==============================================================================
 
388
*/
 
389
 
 
390
Terrain_Descr::Terrain_Descr(const char* directory, Section* s, Descr_Maintainer<Resource_Descr>* resources)
 
391
{
 
392
        const char *str;
 
393
 
 
394
        // Set some defaults
 
395
        m_texture = 0;
 
396
        m_frametime = FRAME_LENGTH;
 
397
        m_picnametempl = 0;
 
398
   m_valid_resources = 0;
 
399
   m_nr_valid_resources = 0;
 
400
   m_default_resources=-1;
 
401
   m_default_amount=0;
 
402
 
 
403
        // Read configuration
 
404
        snprintf(m_name, sizeof(m_name), "%s", s->get_name());
 
405
 
 
406
        // Parse the default resource
 
407
   str = s->get_string("def_resources", 0);
 
408
        if (str) {
 
409
      std::istringstream str1(str);
 
410
      std::string resource;
 
411
      int amount;
 
412
           str1 >> resource >> amount;
 
413
      int res=resources->get_index(resource.c_str());;
 
414
      if(res==-1)
 
415
         throw wexception("Terrain %s has valid resource %s which doesn't exist in world!\n", s->get_name(), resource.c_str());
 
416
      m_default_resources=res;
 
417
      m_default_amount=amount;
 
418
   }
 
419
 
 
420
   // Parse valid resources
 
421
   std::string str1=s->get_string("resources", "");
 
422
   if(str1!="") {
 
423
      int nres=1;
 
424
      uint i=0;
 
425
      while(i < str1.size()) { if(str1[i]==',') { nres++; }  i++; }
 
426
 
 
427
      m_nr_valid_resources=nres;
 
428
      if(nres==1)
 
429
         m_valid_resources=new uchar;
 
430
      else
 
431
         m_valid_resources=new uchar[nres];
 
432
      std::string curres;
 
433
      i=0;
 
434
      int cur_res=0;
 
435
      while(i<=str1.size()) {
 
436
         if(str1[i] == ' ' || str1[i] == ' ' || str1[i]=='\t') { ++i; continue; }
 
437
         if(str1[i]==',' || i==str1.size()) {
 
438
            int res=resources->get_index(curres.c_str());;
 
439
            if(res==-1)
 
440
               throw wexception("Terrain %s has valid resource %s which doesn't exist in world!\n", s->get_name(), curres.c_str());
 
441
            m_valid_resources[cur_res++]=res;
 
442
            curres="";
 
443
         } else {
 
444
            curres.append(1, str1[i]);
 
445
         }
 
446
         i++;
 
447
      }
 
448
   }
 
449
 
 
450
        int fps = s->get_int("fps");
 
451
        if (fps > 0)
 
452
                m_frametime = 1000 / fps;
 
453
 
 
454
        // switch is
 
455
        str = s->get_safe_string("is");
 
456
 
 
457
        if(!strcasecmp(str, "dry")) {
 
458
                m_is = TERRAIN_DRY;
 
459
        } else if(!strcasecmp(str, "green")) {
 
460
                m_is = 0;
 
461
        } else if(!strcasecmp(str, "water")) {
 
462
                m_is = TERRAIN_WATER|TERRAIN_DRY|TERRAIN_UNPASSABLE;
 
463
        } else if(!strcasecmp(str, "acid")) {
 
464
                m_is = TERRAIN_ACID|TERRAIN_DRY|TERRAIN_UNPASSABLE;
 
465
        } else if(!strcasecmp(str, "mountain")) {
 
466
                m_is = TERRAIN_DRY|TERRAIN_MOUNTAIN;
 
467
        } else if(!strcasecmp(str, "dead")) {
 
468
                m_is = TERRAIN_DRY|TERRAIN_UNPASSABLE|TERRAIN_ACID;
 
469
        } else if(!strcasecmp(str, "unpassable")) {
 
470
                m_is = TERRAIN_DRY|TERRAIN_UNPASSABLE;
 
471
        } else
 
472
                throw wexception("%s: invalid type '%s'", m_name, str);
 
473
 
 
474
        // Determine template of the texture animation pictures
 
475
        char fnametmpl[256];
 
476
 
 
477
        str = s->get_string("texture", 0);
 
478
        if (str)
 
479
                snprintf(fnametmpl, sizeof(fnametmpl), "%s/%s", directory, str);
 
480
        else
 
481
                snprintf(fnametmpl, sizeof(fnametmpl), "%s/pics/%s_??.png", directory, m_name);
 
482
 
 
483
        m_picnametempl = strdup(fnametmpl);
 
484
}
 
485
 
 
486
Terrain_Descr::~Terrain_Descr()
 
487
{
 
488
        if (m_picnametempl)
 
489
                free(m_picnametempl);
 
490
   if(m_nr_valid_resources==1) {
 
491
      delete m_valid_resources;
 
492
   }
 
493
   if(m_nr_valid_resources>1) {
 
494
      delete[] m_valid_resources;
 
495
   }
 
496
   m_nr_valid_resources=0;
 
497
   m_valid_resources=0;
 
498
}
 
499
 
 
500
 
 
501
/*
 
502
===============
 
503
Terrain_Descr::load_graphics
 
504
 
 
505
Trigger load of the actual animation frames.
 
506
===============
 
507
*/
 
508
void Terrain_Descr::load_graphics()
 
509
{
 
510
        if (m_picnametempl)
 
511
                m_texture = g_gr->get_maptexture(m_picnametempl, m_frametime);
 
512
}