Advanced Strategic Command
terraintype.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  terraintype.cpp - description
3  -------------------
4  begin : Fri Jul 27 2001
5  copyright : (C) 2001 by Martin Bickel
6  email : bickel@asc-hq.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 // #include "basegfx.h"
19 #include "terraintype.h"
20 #include "gameoptions.h"
21 #include "graphicset.h"
22 #include "sgstream.h"
23 #include "textfileparser.h"
24 #include "textfiletags.h"
25 #include "textfile_evaluation.h"
26 #include "overviewmapimage.h"
27 #include "graphics/blitter.h"
28 #include "fieldimageloader.h"
29 
30 const char* terrainProperty[terrainPropertyNum+1] = {"shallow water" , // 0
31  "normal lowland",
32  "swamp",
33  "forest",
34  "high mountains", // 4
35  "road",
36  "railroad",
37  "entry of building (not to be used for terrain)" ,
38  "harbour",
39  "runway" ,
40  "pipeline", // 10
41  "buried pipeline",
42  "water",
43  "deep water",
44  "hard sand",
45  "soft sand",
46  "track possible",
47  "small rocks",
48  "mud",
49  "snow",
50  "deep snow",
51  "mountains",
52  "very shallow water",
53  "large rocks",
54  "lava",
55  "ditch",
56  "hillside",
57  "turret foundation",
58  "morass",
59  "Installation",
60  "pack ice",
61  "river",
62  "frozen water",
63  "bridge",
64  "lava barrier",
65  "spaceport",
66  "beacon",
67  "fire",
68  "concrete",
69  NULL };
70 
71 
72 
73 
74 void TerrainAccess::read ( tnstream& stream ) {
75  terrain.read ( stream );
76  terrain.reset( 7 );
77  terrainreq.read ( stream );
78  terrainnot.read ( stream );
79  terrainnot.reset( 7 );
80  terrainkill.read ( stream );
81 
82  for ( int a = 0; a < 10; a++ )
83  stream.readInt( ); //dummy
84 };
85 
86 void TerrainAccess::write ( tnstream& stream ) const {
87  terrain.write ( stream );
88  terrainreq.write ( stream );
89  terrainnot.write ( stream );
90  terrainkill.write ( stream );
91 
92  for ( int a = 0; a < 10; a++ )
93  stream.writeInt( 0 ); //dummy
94 };
95 
97 {
102 }
103 
105 {
106  for (int i = 0; i < terrainPropertyNum ; i++) {
107  TerrainBits bts;
108  bts.set ( i );
109 
110  if ( (*this & bts).any() ) {
111  text += "- " ;
112  text += terrainProperty[i];
113  text += "\n";
114  }
115  } /* endfor */
116 }
117 
118 
119 
120 
122 {
123  resize( cmovemalitypenum);
124  for ( int i = 0; i < cmovemalitypenum; i++ )
125  at(i) = 100;
126 }
127 
129 {
130  id = -1;
131  for ( int i = 0; i < cwettertypennum; i++ )
132  weather[i] = NULL;
133 
134 }
135 
136 
138 {
139  Surface* img;
140  if ( bi_pict == -1 )
141  img = &image;
142  else
143  img = &GraphicSetManager::Instance().getPic( bi_pict);
144 
149  (*img,s,pos,nullParam,nullParam,nullParam,nullParam);
150 }
151 
152 
154 {
155  if ( bi_pict >= 0 ) {
156  return GraphicSetManager::Instance().getQuickView( bi_pict );
157  } else {
158  if (!quickView ) {
159  quickView = new OverviewMapImage( image );
160  }
161  return quickView;
162  }
163 }
164 
166 {
167  delete quickView;
168 }
169 
170 
171 const int terrain_version = 6;
172 
173 
174 void TerrainType::MoveMalus::read( tnstream& stream, int defaultValue, int moveMalusCount )
175 {
176  clear();
177 
178  int version;
179  if ( moveMalusCount <= 0 ) {
180  version = stream.readInt();
181  moveMalusCount = stream.readInt();
182  } else
183  version = 0;
184 
185  #ifndef converter
186  int mmcount = moveMalusCount;
187  if (mmcount < moveMalusCount )
188  mmcount = moveMalusCount;
189  #else
190  int mmcount = moveMalusCount ;
191  #endif
192 
193  for ( int j=0; j< mmcount ; j++ ) {
194  if (j < moveMalusCount ) {
195  int i;
196  if ( version < 2 )
197  i = stream.readUint8();
198  else
199  i = stream.readInt();
200  push_back ( i );
201  } else
202  if ( j == 0 )
203  push_back ( defaultValue );
204  else
205  push_back ( at(0) );
206  }
207 }
208 
210 {
211  stream.writeInt(2);
212  stream.writeInt( size() );
213  for ( int m = 0; m < size(); m++ )
214  stream.writeInt ( at(m) );
215 }
216 
218 {
219  read( stream, terrain_version );
220 }
221 
222 
223 void TerrainType::Weather::read ( tnstream& stream, int version )
224 {
225  bool loadImage = true;
226  if (version <=2 ) {
227  loadImage = stream.readInt();
228 
229  for ( int j = 1; j < 8; j++ )
230  stream.readInt(); // pgbt->picture[j]
231 
232  for ( int j = 0; j < 8; j++ )
233  stream.readInt(); // pgbt->direcpict[j] = (void*)
234  }
235 
236  if ( version == 1 ) {
237  stream.readInt(); //dummy1
238  defensebonus = stream.readWord();
239  attackbonus = stream.readWord();
240  basicjamming = stream.readUint8();
241  } else {
242  defensebonus = stream.readInt();
243  attackbonus = stream.readInt();
244  basicjamming = stream.readInt();
245  }
246  int move_maluscount = stream.readUint8();
247  stream.readInt(); // pgbt->movemalus = (char*)
248  stream.readInt(); // pgbt->terraintype
249  stream.readInt(); // bool readQuickView
250 
251  art.read ( stream );
252 
253  bi_pict = stream.readInt();
254  for ( int j = 1; j < 6; j++ )
255  stream.readInt(); //pgbt->bi_picture[j] =
256 
257  move_malus.read( stream, minmalq, move_maluscount );
258 
259  if ( version >= 5 )
260  originalImageFilename = stream.readString();
261 
262 /*
263  for ( j=0; j<8 ;j++ )
264  if ( pgbt->picture[j] )
265  if ( pgbt->bi_picture[j] == -1 ) {
266  pgbt->picture[j] = asc_malloc ( fieldsize );
267  stream.readdata ( pgbt->picture[j], fieldsize );
268  } else
269  loadbi3pict_double ( pgbt->bi_picture[j],
270  &pgbt->picture[j],
271  CGameOptions::Instance()->bi3.interpolate.terrain );
272 
273 */
274  if ( loadImage )
275  if ( bi_pict == -1 )
276  image.read ( stream );
277 }
278 
279 void TerrainType::Weather::write ( tnstream& stream ) const
280 {
281  stream.writeInt ( defensebonus );
282  stream.writeInt ( attackbonus );
283  stream.writeInt ( basicjamming );
284  stream.writeUint8 ( 0 ); // was: movemalus count
285  stream.writeInt ( 1 );
286  stream.writeInt ( 1 );
287  stream.writeInt ( 0); // was: quickview
288  art.write ( stream );
289 
290 
291  stream.writeInt ( bi_pict );
292  for ( int m = 1; m< 6; m++ )
293  stream.writeInt ( -1 );
294 
295  move_malus.write ( stream );
296 
297  stream.writeString( originalImageFilename );
298 
299  if ( bi_pict == -1 )
300  image.write ( stream );
301 }
302 
303 
305 {
306  int version = stream.readInt();
307  if ( version > terrain_version || (version < 5 && version !=1) )
308  throw tinvalidversion ( stream.getDeviceName(), terrain_version, version );
309 
310  stream.readInt();
311  id = stream.readInt();
312 
313  bool ___loadWeather[cwettertypennum];
314  for ( int ww = 0; ww < cwettertypennum; ww++ )
315  ___loadWeather[ww] = stream.readInt();
316 
317  for ( int nf = 0; nf < 8; nf++ )
318  stream.readInt(); // neighbouringfield[nf]
319 
320  name = stream.readString();
321 
322  for ( int i=0; i<cwettertypennum ;i++ ) {
323  if ( ___loadWeather[i] ) {
324  weather[i] = new TerrainType::Weather ( this );
325  weather[i]->read( stream, version );
326  } else
327  weather[i] = NULL;
328 
329  } /* endfor */
330 
331  if ( version >= 6 )
332  readClassContainer( secondaryIDs, stream );
333 }
334 
335 
336 void TerrainType::write ( tnstream& stream ) const
337 {
338  stream.writeInt ( terrain_version );
339  stream.writeInt ( !name.empty() );
340  stream.writeInt ( id );
341  for ( int m = 0; m < cwettertypennum; m++ )
342  stream.writeInt ( weather[m] != NULL );
343 
344  for ( int m = 0; m < 8; m++ )
345  stream.writeInt ( 0 ); // bbt->neighbouringfield[nf]
346 
347  stream.writeString( name );
348  for ( int i = 0; i < cwettertypennum ; i++ )
349  if ( weather[i] )
350  weather[i]->write( stream );
351 
353 
354  /*
355  stream.writeString(filename);
356  stream.writeString(location);
357  */
358 }
359 
360 
362 {
363  int size = sizeof(*this);
364 
365  for ( int w = 0; w < cwettertypennum; ++w )
366  if ( weather[w] )
367  size += weather[w]->getMemoryFootprint();
368 
369  return size;
370 }
371 
373 {
374  int size = sizeof(*this);
375  size += image.getMemoryFootprint();
376  if ( quickView )
377  size += quickView->getMemoryFootprint();
378  return size;
379 }
380 
381 
383 {
384  for ( int i = 0; i< cwettertypennum; ++i) {
385  delete weather[i];
386  weather[i] = NULL;
387  }
388 }
389 
390 
392 {
393  terrain.flip();
394 }
395 
396 int TerrainAccess :: accessible ( const TerrainBits& bts ) const
397 {
398  if ( (terrain & bts).any()
399  && (terrainreq & bts) == terrainreq
400  && (terrainnot & bts ).none()
401  ) return 1;
402  else
403  if ( (terrainkill & bts).any() )
404  return -1;
405  else
406  return 0;
407 }
408 
409 
410 void TerrainBits::setInt ( int terrain1, int terrain2 )
411 {
412  reset();
413  for ( int i = 0; i < 32; i++ )
414  if ( terrain1 & ( 1 << i ))
415  set(i);
416 
417  for ( int i = 0; i < 32; i++ )
418  if ( terrain2 & ( 1 << i ))
419  set(32+i);
420 }
421 
422 void TerrainBits::read ( tnstream& stream )
423 {
424  int terrain1 = stream.readInt();
425  int terrain2 = stream.readInt();
426  setInt ( terrain1, terrain2 );
427  };
428 
429 void TerrainBits::write ( tnstream& stream ) const
430 {
431  int terrain1 = 0;
432  int terrain2 = 0;
433  for ( int i = 0; i < 32; i++ )
434  if ( test(i) )
435  terrain1 |= 1 << i ;
436 
437  for ( int i = 0; i < 32; i++ )
438  if ( test(32+i) )
439  terrain2 |= 1 << i ;
440 
441  stream.writeInt( terrain1 );
442  stream.writeInt( terrain2 );
443 }
444 
445 
446 
447 
449 {
450  pc.addBreakpoint();
451 
452 
453  BitSet weatherBits;
454  for ( int i = 0; i < cwettertypennum; i++ )
455  if ( weather[i] )
456  weatherBits.set(i);
457 
458  pc.addString( "Name", name );
459  pc.addInteger( "ID", id );
460 
461  if ( pc.find( "SecondaryIDs") || !pc.isReading())
462  pc.addIntegerArray("SecondaryIDs", secondaryIDs );
463 
464 
465  pc.addTagArray( "Weather", weatherBits, cwettertypennum, weatherTags );
466 
467  for ( int i = 0; i < cwettertypennum; i++ )
468  if ( weatherBits.test(i) ) {
469 
470  if ( pc.isReading() )
471  weather[i] = new TerrainType::Weather ( this );
472 
473  pc.openBracket ( weatherTags[i] );
474  weather[i]->runTextIO ( pc );
475  pc.closeBracket ( );
476  }
477 
478 }
479 
481 {
482  bool bi3pics = false;
483 
484  if ( !pc.isReading() )
485  if ( bi_pict >= 0 )
486  bi3pics = true;
487 
488  pc.addBool ( "UseGFXpics", bi3pics, false );
489  if ( !bi3pics ) {
490  bi_pict = -1;
491  int w = cwettertypennum-1;
492  for ( int i = 0; i < cwettertypennum-1; i++ )
493  if ( terraintype->weather[i] == this )
494  w = i;
495 
496  ASCString s = extractFileName_withoutSuffix ( terraintype->filename );
497  if ( s.empty() ) {
498  s = "terrain";
499  s += strrr(terraintype->id);
500  }
501  s += weatherAbbrev[w];
502  pc.addImage ( "picture", image, s, true );
503 
504  if ( pc.isReading() ) {
505  originalImageFilename = s;
506  } else {
507  pc.addString( "OriginalImageFilename", originalImageFilename );
508  }
509 
510  // applyFieldMask( image );
511 
512  if ( pc.isReading() ) {
513  int operations;
514  pc.addNamedInteger("GraphicOperations", operations, graphicOperationNum, graphicOperations, 0 );
515  if ( operations == 1 )
516  snowify( image );
517  else
518  if ( operations == 2 )
519  snowify( image, false );
520  }
521 
522  } else {
523  pc.addInteger ( "GFX_Picture", bi_pict );
524  if ( bi_pict < 0 )
525  fatalError ( "invalid BI-image " );
526  }
527 
528  pc.addInteger ( "DefenseBonus", defensebonus, 0 );
529  pc.addInteger ( "AttackBonus", attackbonus, 0 );
530  pc.addInteger ( "BasicJamming", basicjamming, 0 );
531  pc.addDFloatArray ( "MoveMalus", move_malus );
532  while ( move_malus.size() < cmovemalitypenum )
533  if ( move_malus.size() == 0 )
534  move_malus.push_back ( minmalq );
535  else
536  move_malus.push_back ( move_malus[0] );
537 
538 
539  pc.addTagArray ( "TerrainProperties", art, terrainPropertyNum, terrainProperties );
540 }
541 
542 
543 
544 
546 {
547  TerrainBits tb;
548  switch ( tbt ) {
549  case cbwater0 : tb.setInt( 1<<22 ); break;
550  case cbwater1 : tb.setInt( 1 ); break;
551  case cbwater2 : tb.setInt( 4096 ); break;
552  case cbwater3 : tb.setInt( 8192 ); break;
553  case cbwater : tb.setInt ( (1<<22) // very shallow water
554  | (1<< 0) // shallow water
555  | (1<<12) // water
556  | (1<<13) // deep water
557  | (1<<31) // river
558  ); break;
559  case cbstreet : tb.setInt ( 32, 0 ); break;
560  case cbrailroad : tb.setInt ( 64, 0 ); break;
561  case cbbuildingentry : tb.setInt ( 128, 0 ); break;
562  case cbharbour : tb.setInt ( 256, 0 ); break;
563  case cbrunway : tb.setInt ( 512, 0 ); break;
564  case cbpipeline : tb.setInt ( 1024, 0 ); break;
565  case cbpowerline : tb.setInt ( 2048, 0 ); break;
566  case cbfahrspur : tb.setInt ( 1<<16, 0 ); break;
567  case cbfestland : tb.flip(); tb ^= getTerrainBitType( cbwater ); break;
568  case cbsnow1 : tb.setInt ( 1<<19, 0 ); break;
569  case cbsnow2 : tb.setInt ( 1<<20, 0 ); break;
570  case cbhillside : tb.setInt ( 1<<26, 0 ); break;
571  case cbsmallrocks : tb.setInt ( 1<<17, 0 ); break;
572  case cblargerocks : tb.setInt ( 1<<23, 0 ); break;
573  case cbfrozenwater : tb.setInt ( 0, 1 ); break;
577  case cbriver : tb.setInt( 1 << 31, 0 ); break;
578 
579  };
580  return tb;
581 }
582 
583 
585 {
586  ASCString text;
587 
588  text += "Terrain properties of which one must be available:\n" ;
589  terrain.appendToString( text );
590 
591  if ( !( brief && terrainreq.none() )) {
592  text += "\n\nTerrain properties that must all be set:\n" ;
593  terrainreq.appendToString( text );
594  }
595 
596  if ( !( brief && terrainnot.none() )) {
597  text += "\n\nTerrain properties that must not be set:\n" ;
598  terrainnot.appendToString( text );
599  }
600 
601  if ( !( brief && terrainkill.none() )) {
602  text += "\n\nTerrain properties that are fatal:\n" ;
603  terrainkill.appendToString( text );
604  }
605 
606  return text;
607 }
void read(tnstream &stream, int defaultValue, int moveMalusCount=-1)
const char * graphicOperations[graphicOperationNum]
void addBool(const ASCString &name, bool &property)
virtual void writeInt(int i)
Writes a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is p...
Definition: basestrm.cpp:363
void write(tnstream &stream) const
write the binary representation of this item to the given stream
void snowify(Surface &s, bool adaptive)
ASCString name
Definition: terraintype.h:82
void write(tnstream &stream) const
virtual int readInt(void)
Reads a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is pe...
Definition: basestrm.cpp:284
NullParamType nullParam
Definition: blitter.cpp:30
virtual ASCString getDeviceName()
returns the name of the stream.
Definition: basestrm.cpp:269
void addImage(const ASCString &name, Surface &property, ASCString &fileName, bool applyFieldMask)
Weather * weather[cwettertypennum]
Definition: terraintype.h:140
void addIntegerArray(const ASCString &name, vector< int > &property, bool required=true)
const int terrain_version
Functions to evaluate the parsed *.asctxt files.
virtual int readWord(void)
Reads a 16 bit unsigned Integer. In the stream little-endian byte order is used and a translation is ...
Definition: basestrm.cpp:291
void appendToString(ASCString &text) const
const int graphicOperationNum
Definition: textfiletags.h:36
const char * weatherAbbrev[cwettertypennum]
A system that provides a set of images for vehicles, buildings, etc.
const char * terrainProperties[terrainPropertyNum]
The interface for all kinds of IO stream.
void read(tnstream &stream)
read the binary representation of this item from the given stream
void write(tnstream &stream) const
virtual Uint8 readUint8(void)
Reads a 8 bit unsigned Integer.
Definition: basestrm.cpp:305
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
const int terrainPropertyNum
the number of bits that specify the terrain of a field
Definition: terraintype.h:28
void read(tnstream &stream)
const OverviewMapImage * getQuickView()
ASCString extractFileName_withoutSuffix(const ASCString &filename)
Definition: basestrm.cpp:2585
virtual void writeString(const string &pc, bool binary=true)
writes the C++ String pc to the stream.
Definition: basestrm.cpp:545
void runTextIO(PropertyContainer &pc)
Definition: terraintype.cpp:96
void runTextIO(PropertyContainer &pc)
registers the properties of this item for loading/writing into asctxt files
TerrainBits getTerrainBitType(TerrainBitTypes tbt)
char * strrr(int a)
converts a to a string.
Definition: misc.cpp:66
the properties of a terrain describing which units can move onto this field and which can't ...
Definition: terraintype.h:32
ASCString toString(bool brief=true) const
TerrainBits terrainreq
ALL these bits must be set in the terrain.
Definition: terraintype.h:50
TerrainBitTypes
Definition: terraintype.h:153
const int cmovemalitypenum
The number of vehicle categories; Each category has its own move malus.
Definition: typen.h:384
virtual void writeUint8(Uint8 c)
Writes a 8 bit unsigned Integer.
Definition: basestrm.cpp:380
TerrainBits terrainnot
if one of these bits is set, the field will NOT be accessible
Definition: terraintype.h:53
int accessible(const TerrainBits &bts) const
checks whether a field with the given terrainbits is accessible.
void addDFloatArray(const ASCString &name, vector< double > &property)
The IO for many basic classes and structurs of ACS.
vector< int > secondaryIDs
when loading a file and these IDs are encountered, this object will be used.
Definition: terraintype.h:80
void readClassContainer(C &c, tnstream &stream)
Definition: basestrm.h:752
SDLmm::SPoint SPoint
Definition: surface.h:27
void paint(Surface &s, SPoint pos)
displays the image on the screen coordinates x1/y1
TerrainBits terrainkill
if a terrain is not accessible AND one of these bits is matched, the unit will be destroyed ...
Definition: terraintype.h:56
void read(tnstream &stream)
read the binary representation of this item from the given stream
virtual ASCString readString(bool includeCR=false)
Reads and returns a string.
Definition: basestrm.cpp:535
void read(tnstream &stream)
Definition: terraintype.cpp:74
void addInteger(const ASCString &name, int &property)
void setInt(int terrain1=0, int terrain2=0)
TerrainBits terrain
at least one of these bits must match on of the terrain
Definition: terraintype.h:47
void write(tnstream &stream) const
Definition: terraintype.cpp:86
virtual void closeBracket()
void addNamedInteger(const ASCString &name, int &property, int tagNum, const char **tags)
int getMemoryFootprint() const
const char * terrainProperty[terrainPropertyNum+1]
Definition: terraintype.cpp:30
const char * weatherTags[cwettertypennum]
void writeClassContainer(const C &c, tnstream &stream)
Definition: basestrm.h:742
virtual void openBracket(const ASCString &name)
the image for a TerrainType that is shown on the small map
int getMemoryFootprint() const
void megaBlitter(const Surface &src, Surface &dst, const SPoint &pos, const SourceColorTransformParameter &scmp=nullParam, const ColorMergerParameter &cmp=nullParam, const SourcePixelSelectorParameter spsp=nullParam, const TargetPixelSelectorParameter tpsp=nullParam)
Definition: blitter.h:410
void addString(const ASCString &name, ASCString &property)
bool find(const ASCString &name)
std::bitset< 64 > BitSet
Definition: basictypes.h:48
void fatalError(const ASCString &string)
void addTagArray(const ASCString &name, BitSet &property, int tagNum, const char **tags, bool inverted=false)
void runTextIO(PropertyContainer &pc)
registers the properties of this item for loading/writing into asctxt files
void write(tnstream &stream) const
write the binary representation of this item to the given stream
const int cwettertypennum
The number of different weather.
Definition: typen.h:61
#define minmalq
Definition: typen.h:430
Functions to parse the *.asctxt files.