Pol  Revision:4b29d2b
multidef.cpp
Go to the documentation of this file.
1 
9 #include "multidef.h"
10 
11 #include <cstdio>
12 #include <sstream>
13 #include <string>
14 
15 #include "../../bscript/bstruct.h"
16 #include "../../clib/cfgelem.h"
17 #include "../../clib/cfgfile.h"
18 #include "../../clib/passert.h"
19 #include "../../clib/strutil.h"
20 #include "../globals/multidefs.h"
21 
22 namespace Pol
23 {
24 namespace Multi
25 {
26 bool BoatShapeExists( u16 graphic );
27 
29  : multiid( multiid ),
30  type( UNKNOWN ),
31  elems(),
32 
33  xbase( 0 ),
34  xsize( 0 ),
35  ybase( 0 ),
36  ysize( 0 ),
37 
38  minrx( 0 ),
39  minry( 0 ),
40  minrz( 0 ),
41  maxrx( 0 ),
42  maxry( 0 ),
43  maxrz( 0 )
44 {
45  if ( elem.type_is( "BOAT" ) )
46  {
47  if ( !BoatShapeExists( multiid ) )
48  elem.throw_error( "Entry for Boat (multiid " + Clib::hexint( multiid ) +
49  ") not found in boats.cfg" );
50  type = BOAT;
51  }
52  else if ( elem.type_is( "HOUSE" ) )
53  {
54  type = HOUSE;
55  }
56  else if ( elem.type_is( "STAIRS" ) )
57  {
58  type = STAIRS;
59  }
60 
61  std::string tmp;
62  while ( elem.remove_prop( "static", &tmp ) )
63  {
64  std::istringstream is( tmp );
65  MULTI_ELEM multielem;
66  multielem.is_static = true;
67  if ( is >> std::hex >> multielem.objtype >> std::dec >> multielem.x >> multielem.y >>
68  multielem.z )
69  {
70  elems.push_back( multielem );
71  }
72  else
73  {
74  std::string message = "Badly formed static directive: '" + tmp + "'";
75  elem.throw_error( message );
76  }
77  }
78  while ( elem.remove_prop( "dynamic", &tmp ) )
79  {
80  std::istringstream is( tmp );
81  MULTI_ELEM multielem;
82  multielem.is_static = false;
83  if ( is >> std::hex >> multielem.objtype >> std::dec >> multielem.x >> multielem.y >>
84  multielem.z )
85  {
86  elems.push_back( multielem );
87  }
88  else
89  {
90  std::string message = "Badly formed dynamic directive: '" + tmp + "'";
91  elem.throw_error( message );
92  }
93  }
94 }
95 
97 
98 bool MultiDef::findcomponents( Components::const_iterator& beg, Components::const_iterator& end,
99  short rx, short ry ) const
100 {
101  ItrPair pr = components.equal_range( getkey( rx, ry ) );
102  if ( pr.first == components.end() )
103  {
104  return false;
105  }
106  else
107  {
108  beg = pr.first;
109  end = pr.second;
110  return true;
111  }
112 }
113 
114 bool MultiDef::body_contains( short rx, short ry ) const
115 {
116  return ( components.count( getkey( rx, ry ) ) != 0 );
117 }
118 const MULTI_ELEM* MultiDef::find_component( short rx, short ry ) const
119 {
120  if ( body_contains( rx, ry ) )
121  return ( *components.find( getkey( rx, ry ) ) ).second;
122  else
123  return nullptr;
124 }
125 
127 {
128  unsigned short k = getkey( elem->x, elem->y );
129 
130  if ( !hull2.count( k ) )
131  {
132  hull.push_back( elem );
133  hull2.insert( k );
134  }
135 
136 
137  if ( type == BOAT )
138  {
139  short int_rx = elem->x, int_ry = elem->y;
140  if ( ( multiid & 1 ) == 0 ) // N/S hull, so squeeze X
141  {
142  if ( elem->x == minrx )
143  int_rx = minrx + 1;
144  else if ( elem->x == maxrx )
145  int_rx = maxrx - 1;
146  }
147  else
148  {
149  if ( elem->y == minry )
150  int_ry = minry + 1;
151  else if ( elem->y > 0 )
152  int_ry = maxry - 1;
153  }
154  elem = find_component( int_rx, int_ry );
155  if ( elem )
156  add_to_internal_hull( elem );
157  }
158 }
159 
161 {
162  unsigned short k = getkey( elem->x, elem->y );
163 
164  if ( !internal_hull2.count( k ) )
165  {
166  internal_hull.push_back( elem );
167  internal_hull2.insert( k );
168  }
169 }
170 
172 {
173  short rx, ry;
174  for ( ry = minry; ry <= maxry; ++ry )
175  {
176  for ( rx = minrx; rx <= maxrx; ++rx )
177  {
178  const MULTI_ELEM* elem = find_component( rx, ry );
179  if ( elem != nullptr )
180  {
181  add_to_hull( elem );
182 
183  break;
184  }
185  }
186  for ( rx = maxrx; rx >= minrx; --rx )
187  {
188  const MULTI_ELEM* elem = find_component( rx, ry );
189  if ( elem != nullptr )
190  {
191  add_to_hull( elem );
192 
193  break;
194  }
195  }
196  }
197 
198 
199  for ( rx = minrx; rx <= maxrx; ++rx )
200  {
201  for ( ry = minry; ry <= maxry; ++ry )
202  {
203  const MULTI_ELEM* elem = find_component( rx, ry );
204  if ( elem != nullptr )
205  {
206  add_to_hull( elem );
207  break;
208  }
209  }
210  for ( ry = maxry; ry >= minry; --ry )
211  {
212  const MULTI_ELEM* elem = find_component( rx, ry );
213  if ( elem != nullptr )
214  {
215  add_to_hull( elem );
216  break;
217  }
218  }
219  }
220 }
221 
222 
224 {
225  add_body_tohull();
226 }
227 
228 void MultiDef::addrec( const MULTI_ELEM* elem )
229 {
230  if ( elem->x < minrx )
231  minrx = elem->x;
232  if ( elem->y < minry )
233  minry = elem->y;
234  if ( elem->z < minrz )
235  minrz = elem->z;
236 
237  if ( elem->x > maxrx )
238  maxrx = elem->x;
239  if ( elem->y > maxry )
240  maxry = elem->y;
241  if ( elem->z > maxrz )
242  maxrz = elem->z;
243 
244  if ( elem->x < global_minrx )
245  global_minrx = elem->x;
246  if ( elem->y < global_minry )
247  global_minry = elem->y;
248  if ( elem->z < global_minrz )
249  global_minrz = elem->z;
250 
251  if ( elem->x > global_maxrx )
252  global_maxrx = elem->x;
253  if ( elem->y > global_maxry )
254  global_maxry = elem->y;
255  if ( elem->z > global_maxrz )
256  global_maxrz = elem->z;
257 
258  components.insert( Components::value_type( getkey( elem->x, elem->y ), elem ) );
259 }
260 
262 {
263  for ( unsigned i = 0; i < elems.size(); i++ )
264  {
265  addrec( &elems[i] );
266  }
267  computehull();
268 }
269 
271 {
272  size_t size = sizeof( MultiDef );
273  size += 3 * sizeof( MULTI_ELEM* ) + elems.capacity() * sizeof( MULTI_ELEM );
274  size += 3 * sizeof( MULTI_ELEM** ) + hull.capacity() * sizeof( MULTI_ELEM* );
275  size += 3 * sizeof( MULTI_ELEM** ) + internal_hull.capacity() * sizeof( MULTI_ELEM* );
276 
277  size += 3 * sizeof( void* ) + hull2.size() * ( sizeof( unsigned short ) + 3 * sizeof( void* ) );
278  size += 3 * sizeof( void* ) +
279  internal_hull2.size() * ( sizeof( unsigned short ) + 3 * sizeof( void* ) );
280 
281  size += ( sizeof( unsigned short ) + sizeof( MULTI_ELEM* ) + ( sizeof( void* ) * 3 + 1 ) / 2 ) *
282  components.size();
283  return size;
284 }
285 
292 
294 {
295  return multidef_buffer.multidefs_by_multiid.count( multiid ) != 0;
296 }
298 {
299  passert( multidef_buffer.multidefs_by_multiid.count( multiid ) != 0 );
300 
301  MultiDefs::const_iterator citr = multidef_buffer.multidefs_by_multiid.find( multiid );
302  if ( citr != multidef_buffer.multidefs_by_multiid.end() )
303  return ( *citr ).second;
304  else
305  return nullptr;
306 }
307 
308 
310 {
311  Clib::ConfigFile cf( "config/multis.cfg", "BOAT HOUSE STAIRS" );
312  Clib::ConfigElem elem;
313  while ( cf.read( elem ) )
314  {
315  u16 multiid = static_cast<u16>( strtoul( elem.rest(), nullptr, 0 ) );
316 
317  MultiDef* mdef = new MultiDef( elem, multiid );
318  mdef->init();
319 
321  }
322 }
323 }
324 }
MultiDefs multidefs_by_multiid
Definition: multidefs.h:35
void add_to_internal_hull(const MULTI_ELEM *elem)
Definition: multidef.cpp:160
static short global_maxry
Definition: multidef.h:93
size_t estimateSize() const
Definition: multidef.cpp:270
void add_to_hull(const MULTI_ELEM *elem)
Definition: multidef.cpp:126
bool BoatShapeExists(u16 multiid)
Definition: boat.cpp:276
ItrPair findcomponents(short rx, short ry)
const MULTI_ELEM * find_component(short rx, short ry) const
Definition: multidef.cpp:118
HullList2 internal_hull2
Definition: multidef.h:80
Components components
Definition: multidef.h:87
static short global_maxrx
Definition: multidef.h:92
static unsigned short getkey(short rx, short ry)
Definition: multidef.h:128
void addrec(const MULTI_ELEM *elem)
Definition: multidef.cpp:228
std::string hexint(unsigned short v)
Definition: strutil.cpp:23
unsigned short u16
Definition: rawtypes.h:26
const char * rest() const
Definition: cfgfile.cpp:71
static short global_maxrz
Definition: multidef.h:94
POL_NORETURN void throw_error(const std::string &errmsg) const
Definition: cfgfile.cpp:285
std::pair< Components::const_iterator, Components::const_iterator > ItrPair
Definition: multidef.h:83
std::vector< MULTI_ELEM > elems
Definition: multidef.h:68
static short global_minrz
Definition: multidef.h:91
HullList2 hull2
Definition: multidef.h:79
#define passert(exp)
Definition: passert.h:62
bool remove_prop(const char *propname, std::string *value)
Definition: cfgfile.cpp:128
MultiDef(Clib::ConfigElem &elem, u16 multiid)
Definition: multidef.cpp:28
bool MultiDefByMultiIDExists(u16 multiid)
Definition: multidef.cpp:293
bool type_is(const char *name) const
Definition: cfgfile.cpp:95
static short global_minrx
Definition: multidef.h:89
static short global_minry
Definition: multidef.h:90
void read_multidefs()
Definition: multidef.cpp:309
bool read(ConfigElem &elem)
Definition: cfgfile.cpp:1015
enum Pol::Multi::MultiDef::HOUSETYPE type
Definition: berror.cpp:12
MultiDefBuffer multidef_buffer
Definition: multidefs.cpp:19
HullList internal_hull
Definition: multidef.h:77
const MultiDef * MultiDefByMultiID(u16 multiid)
Definition: multidef.cpp:297
unsigned short objtype
Definition: multidef.h:46
bool body_contains(short rx, short ry) const
Definition: multidef.cpp:114