Pol  Revision:cb584c9
resource.cpp
Go to the documentation of this file.
1 
8 #include "resource.h"
9 
10 #include "../bscript/berror.h"
11 #include "../clib/cfgelem.h"
12 #include "../clib/cfgfile.h"
13 #include "../clib/fileutil.h"
14 #include "../clib/logfacility.h"
15 #include "../clib/passert.h"
16 #include "../clib/random.h"
17 #include "../clib/streamsaver.h"
18 #include "../plib/maptile.h"
19 #include "../plib/systemstate.h"
20 #include "globals/state.h"
21 #include "globals/uvars.h"
22 #include "item/itemdesc.h"
23 #include "polcfg.h"
24 #include "polclock.h"
25 #include "polsig.h"
26 #include "realms/realm.h"
27 
28 namespace Pol
29 {
30 namespace Core
31 {
34  : Region( elem, id ),
35  tilecount_( 0 ),
36 
37  units_per_area_( elem.remove_ulong( "UnitsPerArea" ) ),
38  seconds_per_regrow_( elem.remove_ulong( "SecondsPerRegrow" ) ),
39  last_regen_( poltime() ),
40 
41  capacity_( elem.remove_ulong( "Capacity" ) ),
42  units_( 0 )
43 
44 {
45 }
46 
47 
49 {
50  units_ = elem.remove_ulong( "Units" );
51 }
52 
53 
57  Realms::Realm* realm )
58 {
59  (void)realm;
60  unsigned int xy = ( x << 16 ) | y;
61  Depletions::iterator itr = depletions_.find( xy );
62  int units = units_per_area_;
63  if ( itr != depletions_.end() )
64  {
65  units -= ( *itr ).second;
66  }
67  passert( units >= 0 );
68 
69  if ( units == 0 )
70  {
71  return new Bscript::BError( "Resource is depleted" );
72  }
73 
74  unsigned int base_difficulty = 90 - ( units * 80 / units_per_area_ );
75  unsigned int this_difficulty = Clib::random_int( ( base_difficulty * 2 ) - 1 );
76  return new Bscript::BLong( this_difficulty );
77 }
78 
80 {
81  unsigned int xy = ( x << 16 ) | y;
82  Depletions::iterator itr = depletions_.find( xy );
83  int avail_units = units_per_area_;
84  if ( itr != depletions_.end() )
85  {
86  avail_units -= ( *itr ).second;
87  }
88  passert( avail_units >= 0 );
89  int a = avail_units / n;
90  if ( a > m )
91  a = m;
92  short na = static_cast<short>( n * a );
93  if ( itr != depletions_.end() )
94  {
95  ( *itr ).second += na;
96  }
97  else
98  {
99  depletions_[xy] = na;
100  }
101  return new Bscript::BLong( na );
102 }
103 
104 void ResourceRegion::regenerate( time_t now )
105 {
106  unsigned int diff = static_cast<unsigned int>( now - last_regen_ );
107  unsigned int n_regrow;
108  if ( seconds_per_regrow_ )
109  {
110  n_regrow = diff / seconds_per_regrow_;
111  }
112  else
113  {
114  n_regrow = units_per_area_;
115  }
116  last_regen_ = now;
117  //
118  // a simple optimization. If we'd regenerate everything,
119  // just delete all depletions.
120  //
121  if ( n_regrow >= units_per_area_ )
122  {
123  depletions_.clear();
124  }
125  else
126  {
127  Depletions::iterator itr = depletions_.begin(), end = depletions_.end();
128  while ( itr != end )
129  {
130  Depletions::iterator cur = itr;
131  ++itr;
132  if ( n_regrow >= ( *cur ).second )
133  depletions_.erase( cur );
134  else
135  ( *cur ).second -= static_cast<unsigned short>( n_regrow );
136  }
137  }
138 }
139 
140 
142  : RegionGroup<ResourceRegion>( name ), initial_units_( 0 ), current_units_( 0 )
143 {
144 }
145 
147 {
148  initial_units_ = elem.remove_ulong( "InitialUnits" );
149 
150  // start current_units at initial_units in case there's no entry in
151  // RESOURCE.DAT
153 
154  unsigned short tmp;
155  while ( elem.remove_prop( "LandTile", &tmp ) )
156  {
157  landtiles_.insert( tmp );
158  }
159  while ( elem.remove_prop( "ObjType", &tmp ) )
160  {
161  tiles_.insert( tmp );
162  }
163 }
164 
166 {
167  current_units_ = static_cast<int>( elem.remove_ulong( "Units" ) );
168 }
169 
170 bool ResourceDef::findmarker( xcoord x, ycoord y, Realms::Realm* realm, unsigned int objtype )
171 {
172  if ( !landtiles_.count( Items::getgraphic( objtype ) ) &&
173  !tiles_.count( Items::getgraphic( objtype ) ) )
174  return false;
175  if ( realm->findstatic( static_cast<unsigned short>( x ), static_cast<unsigned short>( y ),
176  static_cast<unsigned short>( objtype ) ) )
177  {
178  return true;
179  }
180 
181  // FIXME range can be bad
182  Plib::MAPTILE_CELL cell =
183  realm->getmaptile( static_cast<unsigned short>( x ), static_cast<unsigned short>( y ) );
184  return ( cell.landtile == objtype ); // FIXME blech! objtype == landtile? eh? well broken anyway.
185 }
186 
187 
189 {
190  unsigned int tilecount = 0;
191 
192  std::vector<Realms::Realm*>::iterator itr;
193  for ( itr = gamestate.Realms.begin(); itr != gamestate.Realms.end(); ++itr )
194  {
195  for ( unsigned short x = 0; x < ( *itr )->width(); ++x )
196  {
197  for ( unsigned short y = 0; y < ( *itr )->height(); ++y )
198  {
199  Plib::MAPTILE_CELL cell = ( *itr )->getmaptile( x, y );
200 
201  if ( landtiles_.count( cell.landtile ) )
202  {
203  ++tilecount;
204  ResourceRegion* rgn = getregion( x, y, *itr );
205  if ( rgn )
206  ++rgn->tilecount_;
207  }
208  }
209  }
210  }
211  POLLOG_INFO << "Resource " << name() << ": " << tilecount << "\n";
212  for ( unsigned i = 0; i < regions_.size(); ++i )
213  {
214  ResourceRegion* rrgn = static_cast<ResourceRegion*>( regions_[i] );
215  POLLOG_INFO << "Region " << regions_[i]->name() << ": " << rrgn->tilecount_ << "\n";
216  }
217 }
218 
219 void ResourceDef::regenerate( time_t now )
220 {
221  for ( unsigned i = 0; i < regions_.size(); ++i )
222  {
223  ResourceRegion* rrgn = static_cast<ResourceRegion*>( regions_[i] );
224  rrgn->regenerate( now );
225  }
226 }
227 
228 void ResourceDef::consume( unsigned amount )
229 {
230  current_units_ -= amount;
231 }
232 
233 void ResourceDef::produce( unsigned amount )
234 {
235  current_units_ += amount;
236 }
237 
239 {
240  THREAD_CHECKPOINT( tasks, 700 );
241  time_t now = poltime();
242  for ( ResourceDefs::iterator itr = gamestate.resourcedefs.begin(),
243  end = gamestate.resourcedefs.end();
244  itr != end; ++itr )
245  {
246  ( *itr ).second->regenerate( now );
247  }
248  THREAD_CHECKPOINT( tasks, 799 );
249 }
251 {
252  for ( ResourceDefs::iterator itr = gamestate.resourcedefs.begin(),
253  end = gamestate.resourcedefs.end();
254  itr != end; ++itr )
255  {
256  ( *itr ).second->counttiles();
257  }
258 }
259 
261  Realms::Realm* realm, unsigned short marker )
262 {
263  ResourceDefs::iterator itr = gamestate.resourcedefs.find( resource );
264  if ( itr == gamestate.resourcedefs.end() )
265  return new Bscript::BError( "No resource by that name" );
266 
267  ResourceDef* rd = ( *itr ).second;
268  if ( !rd->findmarker( x, y, realm, marker ) )
269  return new Bscript::BError( "No resource-bearing landmark there" );
270 
271  ResourceRegion* rgn = rd->getregion( x, y, realm );
272  if ( rgn == nullptr )
273  return new Bscript::BError( "No resource region at that location" );
274 
275  return rgn->get_harvest_difficulty( x, y, realm );
276 }
277 
278 Bscript::BObjectImp* harvest_resource( const char* resource, xcoord x, ycoord y,
279  Realms::Realm* realm, int b, int n )
280 {
281  ResourceDefs::iterator itr = gamestate.resourcedefs.find( resource );
282  if ( itr == gamestate.resourcedefs.end() )
283  return new Bscript::BError( "No resource by that name" );
284 
285  ResourceDef* rd = ( *itr ).second;
286 
287  /* assume GetHarvestDifficulty was already checked
288  if (!rd->findmarker(x,y,marker))
289  return new BError( "No resource-bearing landmark there" );
290  */
291  ResourceRegion* rgn = rd->getregion( x, y, realm );
292  if ( rgn == nullptr )
293  return new Bscript::BError( "No resource region at that location" );
294 
295  return rgn->harvest_resource( x, y, b, n );
296 }
297 
298 Bscript::BObjectImp* get_region_string( const char* resource, xcoord x, ycoord y,
299  Realms::Realm* realm, const std::string& propname )
300 {
301  ResourceDefs::iterator itr = gamestate.resourcedefs.find( resource );
302  if ( itr == gamestate.resourcedefs.end() )
303  return new Bscript::BError( "No resource by that name" );
304 
305  ResourceDef* rd = ( *itr ).second;
306 
307  ResourceRegion* rgn = rd->getregion( x, y, realm );
308  if ( rgn == nullptr )
309  return new Bscript::BError( "No resource region at that location" );
310 
311  return rgn->get_region_string( propname );
312 }
313 
314 
315 ResourceDef* find_resource_def( const std::string& rname )
316 {
317  ResourceDefs::iterator itr = gamestate.resourcedefs.find( rname );
318  if ( itr == gamestate.resourcedefs.end() )
319  {
320  return nullptr;
321  }
322  else
323  {
324  return ( *itr ).second;
325  }
326 }
327 
328 
329 void read_resource_cfg( const char* resource )
330 {
331  std::string filename = std::string( "regions/" ) + resource + std::string( ".cfg" );
332  Clib::ConfigFile cf( filename.c_str(), "GLOBAL REGION" );
333  Clib::ConfigElem elem;
334 
335  std::unique_ptr<ResourceDef> rd( new ResourceDef( resource ) );
336 
337  while ( cf.read( elem ) )
338  {
339  if ( elem.type_is( "global" ) )
340  {
341  rd->read_config( elem );
342  }
343  else
344  {
345  rd->read_region( elem );
346  }
347  }
348 
349  gamestate.resourcedefs[resource] = rd.release();
350 }
351 
353 {
354  if ( !Clib::FileExists( "regions/resource.cfg" ) )
355  {
356  if ( Plib::systemstate.config.loglevel > 1 )
357  INFO_PRINT << "File regions/resource.cfg not found, skipping.\n";
358  return;
359  }
360 
361  Clib::ConfigFile cf( "regions/resource.cfg", "ResourceSystem" );
362  Clib::ConfigElem elem;
363  while ( cf.read( elem ) )
364  {
365  std::string resourcename;
366  while ( elem.remove_prop( "ResourceType", &resourcename ) )
367  {
368  read_resource_cfg( resourcename.c_str() );
369  }
370  }
371  if ( Plib::systemstate.config.count_resource_tiles )
373 }
374 
375 
377 {
378  ResourceDef* rd = find_resource_def( elem.rest() );
379  if ( rd == nullptr )
380  {
381  ERROR_PRINT << "Error reading RESOURCE.DAT: Unable to find resource type " << elem.rest()
382  << "\n";
383  throw std::runtime_error( "Data file error" );
384  }
385 
386  rd->read_data( elem );
387 }
389 {
390  ResourceDef* rd = find_resource_def( elem.rest() );
391  if ( rd == nullptr )
392  {
393  ERROR_PRINT << "Error reading RESOURCE.DAT: Unable to find resource type " << elem.rest()
394  << "\n";
395  throw std::runtime_error( "Data file error" );
396  }
397  std::string regionname = elem.remove_string( "Name" );
398  ResourceRegion* rgn = rd->getregion( regionname );
399  if ( rgn == nullptr )
400  {
401  ERROR_PRINT << "Error reading RESOURCE.DAT: Unable to find region " << regionname
402  << " in resource " << elem.rest() << "\n";
403  throw std::runtime_error( "Data file error" );
404  }
405  rgn->read_data( elem );
406 }
407 
409 {
410  std::string resourcefile = Plib::systemstate.config.world_data_path + "resource.dat";
411 
412  if ( Clib::FileExists( resourcefile ) )
413  {
414  Clib::ConfigFile cf( resourcefile, "GLOBALRESOURCEPOOL REGIONALRESOURCEPOOL" );
415  Clib::ConfigElem elem;
416  while ( cf.read( elem ) )
417  {
418  if ( elem.type_is( "GlobalResourcePool" ) )
419  {
420  read_global_data( elem );
421  }
422  else
423  {
424  read_region_data( elem );
425  }
426  }
427  }
428 }
429 
431 {
432  sw() << "GlobalResourcePool " << name() << '\n'
433  << "{" << '\n'
434  << "\tUnits\t" << current_units_ << '\n'
435  << "}" << '\n'
436  << '\n';
437 
438  for ( unsigned i = 0; i < regions_.size(); ++i )
439  {
440  ResourceRegion* rrgn = static_cast<ResourceRegion*>( regions_[i] );
441  rrgn->write( sw, name() );
442  }
443 }
444 
446 {
447  size_t size =
448  RegionGroup<ResourceRegion>::estimateSize() + sizeof( unsigned int ) /*initial_units_*/
449  + sizeof( int ) /*current_units_*/
450  + 3 * sizeof( void* ) +
451  landtiles_.size() * ( sizeof( unsigned short ) + 3 * sizeof( void* ) ) + 3 * sizeof( void* ) +
452  tiles_.size() * ( sizeof( unsigned short ) + 3 * sizeof( void* ) );
453  return size;
454 }
455 
456 
457 void ResourceRegion::write( Clib::StreamWriter& sw, const std::string& resource_name ) const
458 {
459  sw() << "RegionalResourcePool " << resource_name << '\n'
460  << "{" << '\n'
461  << "\tName\t" << name_ << '\n'
462  << "\tUnits\t" << units_ << '\n'
463  << "#\t(regions/" << resource_name << ".cfg: Capacity is " << capacity_ << ")" << '\n'
464  << "}" << '\n'
465  << '\n';
466  // sw.flush();
467 }
468 
470 {
471  size_t size =
473  5 * sizeof( unsigned int ) /*tilecount_ units_per_area_ seconds_per_regrow_ capacity_ units_*/
474  + sizeof( time_t ) /*last_regen_*/
475  + ( sizeof( unsigned int ) + sizeof( unsigned short ) + ( sizeof( void* ) * 3 + 1 ) / 2 ) *
476  depletions_.size();
477  return size;
478 }
479 
481 {
482  for ( const auto& resdef : gamestate.resourcedefs )
483  {
484  resdef.second->write( sw_resource );
485  }
486 }
487 
489 {
490  for ( const auto& resdef : gamestate.resourcedefs )
491  {
492  delete resdef.second;
493  }
494  gamestate.resourcedefs.clear();
495 }
496 }
497 }
unsigned short landtile
Definition: maptile.h:21
void read_global_data(Clib::ConfigElem &elem)
Definition: resource.cpp:376
void read_region_data(RegionGroupBase &grp, const char *preferred_filename, const char *other_filename, const char *tags_expected)
Definition: region.cpp:225
void write(Clib::StreamWriter &sw, const std::string &resource_name) const
Definition: resource.cpp:457
void produce(unsigned amount)
Definition: resource.cpp:233
std::string remove_string(const char *propname)
Definition: cfgfile.cpp:381
Bscript::BObjectImp * get_region_string(const std::string &propname)
Definition: region.cpp:48
Depletions depletions_
Definition: resource.h:88
void read_resource_cfg(const char *resource)
Definition: resource.cpp:329
SystemState systemstate
Definition: systemstate.cpp:12
Bscript::BObjectImp * harvest_resource(const char *resource, xcoord x, ycoord y, Realms::Realm *realm, int b, int n)
Definition: resource.cpp:278
Core::PolConfig config
Definition: systemstate.h:43
std::string world_data_path
Definition: polcfg.h:28
unsigned short ycoord
Definition: poltype.h:20
std::vector< Region * > regions_
Definition: region.h:86
void load_resource_cfg()
Definition: resource.cpp:352
#define POLLOG_INFO
Definition: logfacility.h:213
void regenerate(time_t now)
Definition: resource.cpp:104
unsigned int remove_ulong(const char *propname)
Definition: cfgfile.cpp:461
ResourceDefs resourcedefs
Definition: uvars.h:211
#define THREAD_CHECKPOINT(thread, check)
Definition: polsig.h:48
void consume(unsigned amount)
Definition: resource.cpp:228
Bscript::BObjectImp * get_harvest_difficulty(xcoord x, ycoord y, Realms::Realm *realm)
[1] Harvest Difficulty
Definition: resource.cpp:56
bool findstatic(unsigned short x, unsigned short y, unsigned short objtype) const
Definition: realmfunc.cpp:744
virtual ResourceRegion * getregion(xcoord x, ycoord y, Realms::Realm *realm)
ResourceDef(const char *name)
Definition: resource.cpp:141
const unsigned int units_per_area_
Definition: resource.h:85
unsigned int initial_units_
Definition: resource.h:118
void read_data(Clib::ConfigElem &elem)
Definition: resource.cpp:48
void read_data(Clib::ConfigElem &elem)
Definition: resource.cpp:165
unsigned short getgraphic(u32 objtype)
Definition: itemdesc.cpp:906
void write_resources_dat(Clib::StreamWriter &sw_resource)
Definition: resource.cpp:480
const char * rest() const
Definition: cfgfile.cpp:71
unsigned int units_
Definition: resource.h:96
virtual size_t estimateSize() const
Definition: region.cpp:201
void read_config(Clib::ConfigElem &elem)
Definition: resource.cpp:146
unsigned int tilecount_
Definition: resource.h:78
void read_resources_dat()
Definition: resource.cpp:408
void write(Clib::StreamWriter &sw) const
Definition: resource.cpp:430
virtual size_t estimateSize() const POL_OVERRIDE
Definition: resource.cpp:469
Bscript::BObjectImp * harvest_resource(xcoord x, ycoord y, int b, int n)
Definition: resource.cpp:79
std::vector< Realms::Realm * > Realms
Definition: uvars.h:163
virtual size_t estimateSize() const
Definition: region.cpp:38
int random_int(int i)
Definition: random.cpp:34
void regenerate(time_t now)
Definition: resource.cpp:219
const std::string & name() const
Definition: region.h:101
ResourceDef * find_resource_def(const std::string &rname)
Definition: resource.cpp:315
#define passert(exp)
Definition: passert.h:62
std::set< unsigned short > landtiles_
Definition: resource.h:120
GameState gamestate
Definition: uvars.cpp:74
time_t poltime()
Definition: polclock.cpp:102
std::set< unsigned short > tiles_
Definition: resource.h:121
const unsigned int seconds_per_regrow_
Definition: resource.h:86
bool remove_prop(const char *propname, std::string *value)
Definition: cfgfile.cpp:128
void count_resource_tiles()
Definition: resource.cpp:250
bool type_is(const char *name) const
Definition: cfgfile.cpp:95
unsigned short RegionId
Definition: zone.h:23
Bscript::BObjectImp * get_region_string(const char *resource, xcoord x, ycoord y, Realms::Realm *realm, const std::string &propname)
Definition: resource.cpp:298
ResourceRegion(Clib::ConfigElem &elem, RegionId id)
Resource Management.
Definition: resource.cpp:33
const std::string & name() const
Definition: region.h:60
#define ERROR_PRINT
Definition: logfacility.h:230
void clean_resources()
Definition: resource.cpp:488
virtual size_t estimateSize() const POL_OVERRIDE
Definition: resource.cpp:445
bool FileExists(const char *filename)
Definition: fileutil.cpp:118
bool read(ConfigElem &elem)
Definition: cfgfile.cpp:1015
Bscript::BObjectImp * get_harvest_difficulty(const char *resource, xcoord x, ycoord y, Realms::Realm *realm, unsigned short marker)
Definition: resource.cpp:260
#define INFO_PRINT
Definition: logfacility.h:223
void regen_resources()
Definition: resource.cpp:238
Plib::MAPTILE_CELL getmaptile(unsigned short x, unsigned short y) const
Definition: realmfunc.cpp:772
Definition: berror.cpp:12
unsigned short xcoord
Definition: poltype.h:19
bool findmarker(xcoord x, ycoord y, Realms::Realm *realm, unsigned int objtype)
Definition: resource.cpp:170