Advanced Strategic Command
research.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  research.cpp - description
3  -------------------
4  begin : Tue Jan 23 2001
5  copyright : (C) 2001 by Martin Bickel
6  email : bickel@asc-hq.org
7  ***************************************************************************/
8 
13 /***************************************************************************
14  * *
15  * This program is free software; you can redistribute it and/or modify *
16  * it under the terms of the GNU General Public License as published by *
17  * the Free Software Foundation; either version 2 of the License, or *
18  * (at your option) any later version. *
19  * *
20  ***************************************************************************/
21 
22 #include <cmath>
23 #include <iostream>
24 #include "research.h"
25 #include "errors.h"
26 #include "typen.h"
27 #include "vehicletype.h"
28 #include "gamemap.h"
29 #include "itemrepository.h"
30 
31 const int techDependencyVersion = 2;
32 
34 {
35  int version = stream.readInt();
36  if ( version > techDependencyVersion || version < 1 )
37  throw tinvalidversion( stream.getDeviceName(), techDependencyVersion, version );
38 
39  requireAllListedTechnologies = stream.readInt();
40  readClassContainer(requiredTechnologies, stream );
41  if ( version >= 2 )
42  readClassContainer(blockingTechnologies, stream );
43 }
44 
45 void TechDependency::write ( tnstream& stream ) const
46 {
48  stream.writeInt(requireAllListedTechnologies);
49  writeClassContainer(requiredTechnologies, stream );
50  writeClassContainer(blockingTechnologies, stream );
51 }
52 
54 {
55  pc.addIntRangeArray ( "TechnologiesRequired", requiredTechnologies );
56  pc.addBool( "RequireAllListedTechnologies", requireAllListedTechnologies, true );
57  if ( pc.find( "BlockingTechnologies" ) || !pc.isReading() )
58  pc.addIntRangeArray ( "BlockingTechnologies", blockingTechnologies );
59 }
60 
61 bool TechDependency::available( const Research& research ) const
62 {
64 }
65 
67 {
68  for ( RequiredTechnologies::const_iterator j = blockingTechnologies.begin(); j != blockingTechnologies.end(); ++j )
69  for ( int k = j->from; k <= j->to; ++k )
70  if ( checkTechAvailability ( k ))
71  return NeverAvailable;
72 
73 
74  if ( requiredTechnologies.size() ) {
75  if ( requireAllListedTechnologies ) {
76  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
77  for ( int k = j->from; k <= j->to; ++k )
78  if ( !checkTechAvailability( k ))
79  return UnavailableNow;
80  return Available;
81  } else {
82  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
83  for ( int k = j->from; k <= j->to; ++k )
84  if ( checkTechAvailability ( k ))
85  return Available;
86  return UnavailableNow;
87  }
88  } else
89  return Available;
90 }
91 
92 
93 bool TechDependency::eventually_available_single( const Research& res, list<const Technology*>* dependencies, list<int>& stack, int id )
94 {
95  Technology* tech = technologyRepository.getObject_byID( id );
96  if ( !tech )
97  return false;
98  else
99  return tech->eventually_available( res, dependencies, stack );
100 }
101 
102 bool TechDependency::eventually_available( const Research& res, list<const Technology*>* dependencies, list<int>& stack ) const
103 {
104  if ( requireAllListedTechnologies ) {
105  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
106  for ( int k = j->from; k <= j->to; ++k )
107  if ( !eventually_available_single( res, dependencies, stack, k ))
108  return false;
109 
110  return true;
111  } else {
112  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
113  for ( int k = j->from; k <= j->to; ++k )
114  if ( eventually_available_single( res, dependencies, stack, k ))
115  return true;
116 
117  return false;
118  }
119  return false;
120 }
121 
122 bool TechDependency::eventually_available( const Research& res, list<const Technology*>* dependencies ) const
123 {
124  list<int> stack;
125  return eventually_available( res, dependencies, stack );
126 }
127 
128 
129 
130 int TechDependency::findInheritanceLevel( int id, vector<int>& stack, const ASCString& sourceTechName ) const
131 {
132  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
133  for ( int k = j->from; k <= j->to; ++k )
134  if ( k > 0 ) {
135  if ( find( stack.begin(), stack.end(), k ) != stack.end() ) {
136  ASCString s = "Cyclic reference for technology \n" + sourceTechName + "\n";
137  for ( vector<int>::iterator i = stack.begin(); i != stack.end(); ++i ) {
138  Technology* t = technologyRepository.getObject_byID( *i );
139  if ( t )
140  s += t->name + "\n";
141  }
142  Technology* t = technologyRepository.getObject_byID( k );
143  if ( t )
144  s += t->name + "\n";
145  warningMessage ( s );
146  return -1;
147  }
148 
149  Technology* t = technologyRepository.getObject_byID( k );
150 
151  if ( t ) {
152  // if ( requireAllListedTechnologies )
153  stack.push_back ( k );
154 
155  int i = t->techDependency.findInheritanceLevel ( id, stack, sourceTechName );
156 
157  // if ( requireAllListedTechnologies )
158  stack.pop_back();
159  if ( i > 0 )
160  return i+1;
161  }
162  }
163 
164  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
165  for ( int k = j->from; k <= j->to; ++k )
166  if ( id == k && k > 0 )
167  return 1;
168 
169  return -1;
170 }
171 
172 
173 void TechDependency::writeTreeOutput ( const ASCString& sourceTechName, tnstream& stream, bool reduce ) const
174 {
175  map<int,int> ihl;
176  vector<int> stack;
177  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
178  for ( int k = j->from; k <= j->to; ++k ) {
179  ihl[k] = findInheritanceLevel( k , stack, sourceTechName);
180  }
181 
182  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
183  for ( int k = j->from; k <= j->to; ++k ) {
184  const Technology* t = technologyRepository.getObject_byID( k );
185  if ( t && (ihl[k] == 1 || !reduce) ) {
186  ASCString s = "\"";
187  ASCString stn = sourceTechName;
188 
189  while ( stn.find ( "\"" ) != ASCString::npos )
190  stn.erase ( stn.find ( "\"" ),1 );
191 
192  s += stn;
193  s += "\" -> \"";
194 
195  ASCString stn2 = t->name;
196  while ( stn2.find ( "\"" ) != ASCString::npos )
197  stn2.erase ( stn2.find ( "\"" ),1 );
198 
199  s += stn2 + "\"";
200 
201  if ( !requireAllListedTechnologies )
202  s += "[style=dashed]";
203 
204  s += "\n";
205 
206  stream.writeString ( s, false );
207 
208  stream.writeString ( "\"" + stn + "\" [color=black] \n", false );
209  }
210  }
211 }
212 
214 {
215  ASCString s = ASCString(strrr(tech->id)) + "-";
216  ASCString stn = tech->name;
217 
218  while ( stn.find ( "\"" ) != ASCString::npos )
219  stn.erase ( stn.find ( "\"" ),1 );
220 
221  return s + stn;
222 }
223 
225 {
226  ASCString s2 = tech->name;
227  while ( s2.find ( "\"" ) != ASCString::npos )
228  s2.erase ( s2.find ( "\"" ),1 );
229 
230 
231  ASCString s = "\"" + generateTechName(tech) + "\" [color=black label=\"" + s2 + "\\n";
232 // s += "ID " + ASCString(strrr( tech->id)) + "; ";
233  s += ASCString(strrr(tech->researchpoints)) + " RP\"] \n";
234  return s;
235 }
236 
237 void TechDependency::writeInvertTreeOutput ( const Technology* tech, tnstream& stream, vector<int>& history, vector<pair<int,int> >& blockedPrintList, const vector<IntRange>* onlyWithBaseTechs ) const
238 {
239  if ( onlyWithBaseTechs && !onlyWithBaseTechs->empty() ) {
240  vector<int> inheritanceStack;
241  bool found = false;
242  for ( vector<IntRange>::const_iterator i = onlyWithBaseTechs->begin(); i != onlyWithBaseTechs->end(); ++i )
243  for ( int j = i->from; j <= i->to; ++j )
244  if ( findInheritanceLevel ( j, inheritanceStack, "" ) >= 0 )
245  found = true;
246 
247  if ( !found )
248  return;
249  }
250 
251  for ( RequiredTechnologies::const_iterator i = blockingTechnologies.begin(); i != blockingTechnologies.end(); ++i ) {
252  for ( int l = i->from; l <= i->to; ++l ) {
253  const Technology* block = technologyRepository.getObject_byID( l );
254  if ( block && find ( blockedPrintList.begin(), blockedPrintList.end(), make_pair(tech->id,l)) == blockedPrintList.end() ) {
255  ASCString b = "\"" + generateTechName( block )+ "\" -> \"" + generateTechName( tech ) + "\" [color=red label=\"blocks\" fontcolor=red fontsize=10]\n"; // arrowhead=inv
256  stream.writeString ( b, false );
257  blockedPrintList.push_back ( make_pair(tech->id,l) );
258  }
259  }
260  }
261 
262  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
263  for ( int k = j->from; k <= j->to; ++k ) {
264  const Technology* t = technologyRepository.getObject_byID( k );
265  if ( t ) {
266  ASCString s = "\"" + generateTechName( tech )+ "\" -> \"" + generateTechName( t ) + "\"";
267 
268  if ( !requireAllListedTechnologies )
269  s += "[style=dotted]";
270 
271  s += "\n";
272 
273  stream.writeString ( s, false );
274 
275 
276  stream.writeString ( generateTechLabel(tech), false );
277  stream.writeString ( generateTechLabel(t), false );
278 
279  if ( find ( history.begin(), history.end(), t->id) == history.end()) {
280  history.push_back ( t->id );
281  t->techDependency.writeInvertTreeOutput ( t, stream, history, blockedPrintList );
282  }
283  }
284  }
285 }
286 
287 void TechDependency::writeInvertTreeOutput ( const ASCString techName, tnstream& stream, vector<int>& history, vector<pair<int,int> >& blockedPrintList, const vector<IntRange>* onlyWithBaseTechs ) const
288 {
289  if ( onlyWithBaseTechs && !onlyWithBaseTechs->empty() ) {
290  vector<int> inheritanceStack;
291  bool found = false;
292  for ( vector<IntRange>::const_iterator i = onlyWithBaseTechs->begin(); i != onlyWithBaseTechs->end(); ++i )
293  for ( int j = i->from; j <= i->to; ++j )
294  if ( findInheritanceLevel ( j, inheritanceStack, "" ) >= 0 )
295  found = true;
296 
297  if ( !found )
298  return;
299  }
300 
301  for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
302  for ( int k = j->from; k <= j->to; ++k ) {
303  const Technology* t = technologyRepository.getObject_byID( k );
304  if ( t ) {
305  ASCString s = "\"";
306  ASCString stn = techName;
307 
308  s += stn;
309  s += "\" -> \"";
310 
311  ASCString stn2 = generateTechName( t );
312 
313  s += stn2 + "\"";
314 
315  if ( !requireAllListedTechnologies )
316  s += "[style=dotted]";
317 
318  s += "\n";
319 
320  stream.writeString ( s, false );
321 
322  stream.writeString ( "\"" + stn + "\" [color=black] \n", false );
323  if ( find ( history.begin(), history.end(), t->id) == history.end()) {
324  history.push_back ( t->id );
325  t->techDependency.writeInvertTreeOutput ( t, stream, history, blockedPrintList );
326  }
327  }
328  }
329 }
330 
332 {
333  ASCString s;
334  if ( requireAllListedTechnologies )
335  s += "All of the following Technologies required:\n";
336  else
337  s += "One of the following Technologies required:\n";
338 
339  s += "#indent=20,20#";
340  for ( RequiredTechnologies::const_iterator r = requiredTechnologies.begin(); r != requiredTechnologies.end(); ++r ) {
341  for ( int i = r->from; i <= r->to; ++i ) {
342  Technology* t = technologyRepository.getObject_byID(i);
343  if ( t ) {
344  s += " " + t->name + " ";
345  if ( research.techResearched( t->id ))
346  s += "#fontcolor=0x00FF00#available";
347  else
348  s += "#fontcolor=0xFF0000#missing";
349  s += "#fontcolor=default#\n";
350  }
351  }
352  }
353  s += "#indent=0,0#";
354 
355  if ( !blockingTechnologies.empty() ) {
356  s += "The following Technologies must NOT be researched:\n";
357  s += "#indent=20,20#";
358  for ( RequiredTechnologies::const_iterator r = blockingTechnologies.begin(); r != blockingTechnologies.end(); ++r ) {
359  for ( int i = r->from; i <= r->to; ++i ) {
360  Technology* t = technologyRepository.getObject_byID(i);
361  if ( t ) {
362  s += " " + t->name;
363  if ( !research.techResearched( t->id ))
364  s += "#fontcolor=0x00FF00#not available";
365  else
366  s += "#fontcolor=0xFF0000#available";
367  s += "#fontcolor=default#\n";
368  }
369  }
370  }
371  }
372 
373  return s;
374 }
375 
376 
377 
378 
379 void TechAdapter::read ( tnstream& stream )
380 {
381  int version = stream.readInt();
382  if ( version > 1 || version < 1 )
383  throw tinvalidversion( stream.getDeviceName(), 1, version );
384  name = stream.readString();
385  techDependency.read( stream );
386 }
387 
388 void TechAdapter::write ( tnstream& stream ) const
389 {
390  stream.writeInt(1);
391  stream.writeString( name );
392  techDependency.write ( stream );
393 }
394 
396 {
397  pc.addString ( "Name", name );
398  name.toLower();
399  techDependency.runTextIO ( pc );
400 }
401 
402 bool TechAdapter::available( const Research& research ) const
403 {
404  return techDependency.available ( research );
405 }
406 
407 
408 
409 
410 TechAdapterDependency::TechAdapterDependency() : requireAllListedTechAdapter ( false ) {};
411 
412 bool TechAdapterDependency::available( const Research& research ) const
413 {
414  if ( requiredTechAdapter.size() ) {
415  if ( requireAllListedTechAdapter ) {
416  for ( RequiredTechAdapter::const_iterator j = requiredTechAdapter.begin(); j != requiredTechAdapter.end(); ++j )
417  if ( !research.techAdapterAvail( *j ))
418  return false;
419  return true;
420  } else {
421  for ( RequiredTechAdapter::const_iterator j = requiredTechAdapter.begin(); j != requiredTechAdapter.end(); ++j )
422  if ( research.techAdapterAvail ( *j ))
423  return true;
424  return false;
425  }
426  }
427 
428  return true;
429 }
430 
431 
433 
435 {
436  int version = stream.readInt();
437  if ( version > 1 || version < 1 )
438  throw tinvalidversion( stream.getDeviceName(), 1, version );
439  requireAllListedTechAdapter = stream.readInt();
440  requiredTechAdapter.clear();
441  for ( int i = stream.readInt(); i >0 ; --i )
442  requiredTechAdapter.push_back ( stream.readString() );
443 }
444 
446 {
447  stream.writeInt(1);
448  stream.writeInt(requireAllListedTechAdapter);
449  stream.writeInt( requiredTechAdapter.size() );
450  for ( RequiredTechAdapter::const_iterator i = requiredTechAdapter.begin(); i != requiredTechAdapter.end(); ++i )
451  stream.writeString(*i);
452 }
453 
454 void TechAdapterDependency::runTextIO ( PropertyContainer& pc, const ASCString& defaultTechAdapter )
455 {
456  if ( pc.find( "TechAdapterRequired") || !pc.isReading() ) {
457  pc.addStringArray ( "TechAdapterRequired", requiredTechAdapter );
458  if ( pc.isReading())
459  for ( RequiredTechAdapter::iterator j = requiredTechAdapter.begin(); j != requiredTechAdapter.end(); ++j )
460  j->toLower();
461 
462  } else
463  if ( defaultTechAdapter.length() > 0 )
464  requiredTechAdapter.push_back ( defaultTechAdapter );
465 
466  pc.addBool( "RequireAllListedTechAdapter", requireAllListedTechAdapter, true );
467 }
468 
469 void TechAdapterDependency::writeInvertTreeOutput ( const ASCString& tech, tnstream& stream, const vector<IntRange>* onlyWithBaseTechs ) const
470 {
471  vector<int> history;
472  vector<pair<int,int> > blockedPrintList;
473  for ( RequiredTechAdapter::const_iterator r = requiredTechAdapter.begin(); r != requiredTechAdapter.end(); ++r )
474  for ( TechAdapterContainer::iterator i = techAdapterContainer.begin(); i != techAdapterContainer.end(); ++i )
475  if ( *r == (*i)->getName() )
476  (*i)->techDependency.writeInvertTreeOutput ( tech, stream, history, blockedPrintList, onlyWithBaseTechs );
477 }
478 
480 {
481  ASCString s;
482  if ( requireAllListedTechAdapter )
483  s += "All of the following TechAdapter required:\n";
484  else
485  s += "One of the following TechAdapter required:\n";
486 
487  for ( RequiredTechAdapter::const_iterator r = requiredTechAdapter.begin(); r != requiredTechAdapter.end(); ++r ) {
488  s += " " + *r;
489  if ( research.techAdapterAvail( *r ))
490  s += "#image=pad_symbol_ok.png#";
491  else
492  s += "#image=pad_symbol_no.png#";
493  s += "\n";
494  }
495 
496  return s;
497 }
498 
499 
501 {
502  icon = NULL;
503  id = 0;
504  researchpoints = 0;
505  requireEvent = false;
506  techlevel = 0;
507 }
508 
509 const int technologyVersion = 4;
510 
511 void Technology::read( tnstream& stream )
512 {
513  int version = stream.readInt();
514  if ( version > technologyVersion || version < 1 )
515  throw tinvalidversion( stream.getDeviceName(), technologyVersion, version );
516  id = stream.readInt();
517  researchpoints = stream.readInt();
518  requireEvent = stream.readInt();
519  techlevel = stream.readInt();
520  name = stream.readString();
521  infotext = stream.readString();
522  techDependency.read( stream );
523  if ( version >= 2 )
524  relatedUnitID = stream.readInt();
525  else
526  relatedUnitID = -1;
527 
528  if ( version >= 3 )
530 
531  if ( version >= 4 )
532  readClassContainer( secondaryIDs, stream );
533 
534 }
535 
536 void Technology::write( tnstream& stream ) const
537 {
538  stream.writeInt( technologyVersion );
539  stream.writeInt ( id );
540  stream.writeInt( researchpoints );
541  stream.writeInt( requireEvent );
542  stream.writeInt( techlevel );
543  stream.writeString( name );
544  stream.writeString( infotext );
545  techDependency.write( stream );
546  stream.writeInt ( relatedUnitID );
549 }
550 
552 {
553  pc.addString( "Name", name );
554  pc.addString( "Infotext", infotext);
555 
556  pc.addInteger( "Id", id );
557  if ( pc.find( "SecondaryIDs") || !pc.isReading())
558  pc.addIntegerArray("SecondaryIDs", secondaryIDs );
559 
560  pc.addInteger( "Researchpoints", researchpoints );
561 
562  pc.addInteger( "Techlevel", techlevel );
563  pc.addBool( "RequireEvent", requireEvent, false );
564 
566 
567  if ( pc.find ( "BlockingOtherTechnologies" ) || !pc.isReading() )
568  pc.addIntRangeArray ( "BlockingOtherTechnologies", blockingOtherTechnologies );
569 
570 
571  pc.addInteger( "RelatedUnitID", relatedUnitID, 0 );
572 }
573 
574 bool Technology::eventually_available( const Research& res, list<const Technology*>* dependencies ) const
575 {
576  if ( res.techResearched( id ))
577  return false;
578 
579  list<int> stack;
580  return eventually_available( res, dependencies, stack );
581 }
582 
583 bool Technology::eventually_available( const Research& res, list<const Technology*>* dependencies, list<int>& stack ) const
584 {
585  if ( res.techResearched( id ))
586  return true;
587 
588  if ( res.isBlocked( this ))
589  return false;
590 
591  if ( find( stack.begin(), stack.end(), id ) != stack.end() )
592  return false;
593 
594  stack.push_back( id );
595  bool result = techDependency.eventually_available( res, dependencies, stack );
596  stack.pop_back();
597 
598  if ( result ) {
599  if ( dependencies )
600  if ( find( dependencies->begin(), dependencies->end(), this) == dependencies->end() )
601  dependencies->push_back( this );
602  return true;
603  } else
604  return false;
605 
606 }
607 
608 
609 
610 Research :: Research ( ) : goal(NULL)
611 {
612  progress = 0;
613  activetechnology = 0;
614  ___loadActiveTech = 0;
615  ___oldVersionLoader = false;
616  techsAvail = true;
617  multiplier = 1;
618 }
619 
620 
621 void Research :: read ( tnstream& stream )
622 {
623  read_struct ( stream );
624  read_techs ( stream );
625  evalTechAdapter();
626 }
627 
628 
630 
631 
632 const int researchVersion = -5;
633 
634 void Research :: read_struct ( tnstream& stream, bool merge )
635 {
636  int version = stream.readInt();
637 
638  if ( version < researchVersion )
639  throw tinvalidversion( stream.getLocation(), -researchVersion, -version );
640 
641  if ( version >= 0 ) {
642  progress = version;
643  ___loadActiveTech = stream.readInt();
644 
645  for ( int i = 0; i < researchableWeaponImprovements; i++ )
646  stream.readWord(); // unitimprovement.weapons[i] =
647  stream.readWord(); // unitimprovement.armor =
648 
649  for ( int j = 0; j < 44-researchableWeaponImprovements*2; j++ )
650  stream.readUint8(); // dummy
651 
652  stream.readInt(); // techlevel =
653  stream.readInt(); // __loader_techsAvail =
654  ___oldVersionLoader = true;
655  techsAvail = true;
656  } else {
657  progress = stream.readInt();
658  activetechnology = technologyRepository.getObject_byID( stream.readInt());
659  int size = stream.readInt();
660 
661  if ( !merge )
662  developedTechnologies.clear();
663 
664  for ( int i = 0; i < size; ++i )
665  developedTechnologies.push_back ( stream.readInt());
666 
667  ___oldVersionLoader = false;
668 
669  if ( version <= -2 )
670  techsAvail = stream.readInt();
671  else
672  techsAvail = true;
673 
674  if ( version <= -3 ) {
675  if ( merge ) {
676  vector<ASCString> predefinedTechAdapter_t;
677  readClassContainer( predefinedTechAdapter_t, stream );
678  predefinedTechAdapter.insert( predefinedTechAdapter.begin(), predefinedTechAdapter_t.begin(), predefinedTechAdapter_t.end() );
679  } else {
680  readClassContainer( predefinedTechAdapter, stream );
681  }
682  }
683  if ( version <= -4 ) {
684  multiplier = stream.readInt();
685  }
686 
687  if ( version <= -5 ) {
688  int g = stream.readInt();
689  if ( g > 0 )
690  goal = technologyRepository.getObject_byID( g );
691  else
692  goal = NULL;
693  } else
694  goal = NULL;
695  }
696 }
697 
698 void Research :: write ( tnstream& stream ) {
699  stream.writeInt ( researchVersion );
700  stream.writeInt( progress );
701  stream.writeInt ( activetechnology ? activetechnology->id : 0);
702  stream.writeInt( developedTechnologies.size());
703  for ( int i = 0; i < developedTechnologies.size(); ++i )
704  stream.writeInt( developedTechnologies[i] );
705 
706  stream.writeInt ( techsAvail );
707  writeClassContainer( predefinedTechAdapter, stream );
708  stream.writeInt( multiplier );
709  if ( goal )
710  stream.writeInt( goal->id );
711  else
712  stream.writeInt( 0 );
713 
714 }
715 
716 
717 void Research :: read_techs ( tnstream& stream, bool merge )
718 {
719  if ( !___oldVersionLoader )
720  return;
721 
722  if ( !merge )
723  developedTechnologies.clear();
724 
725  int w = stream.readInt ();
726 
727  while ( w ) {
728  const Technology* tec = technologyRepository.getObject_byID( w );
729  if ( !tec )
730  throw InvalidID ( "technology", w );
731 
732  developedTechnologies.push_back(tec->id);
733 
734  w = stream.readInt();
735  } /* endwhile */
736 
737  if ( ___loadActiveTech ) {
738  w = stream.readInt ();
739 
740  activetechnology = technologyRepository.getObject_byID( w );
741 
742  if ( !activetechnology )
743  throw InvalidID ( "technology", w );
744  }
745 }
746 
748 {
749  progress = 0;
750  activetechnology = NULL;
751  goal = NULL;
752  developedTechnologies.clear();
753  predefinedTechAdapter.clear();
754  triggeredTechAdapter.clear();
755 }
756 
757 bool Research::techResearched ( int id ) const
758 {
759  for ( vector<int>::const_iterator i = developedTechnologies.begin(); i != developedTechnologies.end(); ++i )
760  if ( *i == id )
761  return true;
762  return false;
763 }
764 
765 
766 bool Research::techAdapterAvail( const ASCString& ta ) const
767 {
768  if( find ( predefinedTechAdapter.begin(), predefinedTechAdapter.end(), ta ) != predefinedTechAdapter.end() )
769  return true;
770 
771  return triggeredTechAdapter.find ( ta ) != triggeredTechAdapter.end();
772 }
773 
774 vector<ASCString> Research::evalTechAdapter()
775 {
776  vector<ASCString> newTechadapters;
777  for ( TechAdapterContainer::iterator i = techAdapterContainer.begin(); i != techAdapterContainer.end(); ++i )
778  if ( (*i)->available ( *this )) {
779  ASCString techAdap = (*i)->getName();
780  if ( find( triggeredTechAdapter.begin(), triggeredTechAdapter.end(), techAdap ) == triggeredTechAdapter.end() ) {
781  triggeredTechAdapter.insert( techAdap );
782  newTechadapters.push_back ( techAdap );
783  }
784  }
785 
786  return newTechadapters;
787 }
788 
789 
791 {
792  ASCString s;
793  for ( TriggeredTechAdapter::const_iterator i = triggeredTechAdapter.begin(); i != triggeredTechAdapter.end(); ++i ) {
794  s += "#fontsize=14# ";
795  s += *i + "\n";
796  s += "#fontsize=10#";
797  int counter = 0;
798  for ( TechAdapterContainer::iterator j = techAdapterContainer.begin(); j != techAdapterContainer.end(); ++j ) {
799  if ( (*j)->getName() == *i ) {
800  if ( counter )
801  s += " ----\n";
802  ++counter;
803 
804  s += (*j)->techDependency.showDebug( *this );
805  }
806  }
807  s += "#fontsize=14#\n";
808 
809 
810  }
811 
812  return s;
813 }
814 
815 
816 
817 
818 bool Research::isBlocked( const Technology* tech ) const
819 {
820  for ( int i = 0; i < developedTechnologies.size(); ++i ) {
821  Technology* t = technologyRepository.getObject_byID( developedTechnologies[i] );
822  if ( t && !t->techDependency.available ( *this ) ) {
823  // this is a root technology
824  for ( Technology::BlockingOtherTechnologies::iterator j = t->blockingOtherTechnologies.begin(); j != t->blockingOtherTechnologies.end(); ++j)
825  if ( j->from <= tech->id && tech->id <= j->to )
826  return true;
827  }
828  }
829  return false;
830 
831 }
832 
833 
835 {
836  if ( techResearched( tech->id ))
837  return Researched;
838 
839  if ( isBlocked( tech ))
840  return NeverAvailable;
841 
842  if ( tech->techDependency.available( *this ) ) {
843  return Available;
844  } else
845  return UnavailableNow;
846 }
847 
848 
849 vector<ASCString> Research :: addanytechnology ( const Technology* tech )
850 {
851  if ( tech ) {
852  developedTechnologies.push_back ( tech->id );
853 
854  map->player[player].queuedEvents++;
855  return evalTechAdapter();
856  } else
857  return vector<ASCString>();
858 }
859 
860 
861 void Research :: settechlevel ( int techlevel )
862 {
863  if ( techlevel > 0 ) {
864  for ( int j = 0; j < technologyRepository.getNum(); j++ ) {
865  const Technology* tech = technologyRepository.getObject_byPos ( j );
866  if ( tech )
867  if ( tech->techlevel <= techlevel )
868  if ( !techResearched ( tech->id ))
869  addanytechnology ( tech );
870  }
871  }
872  evalTechAdapter();
873 }
874 
875 
876 
877 
878 
879 /*
880 void Research::initchoosentechnology()
881 {
882  Player& player = map->player[map->actplayer];
883  player.research.progress = 0;
884 
885  Player::DissectionContainer::iterator di = player.dissections.begin();
886  while ( di != player.dissections.end() ) {
887  if ( di->tech->id == player.research.activetechnology->id ) {
888  player.research.progress += di->points;
889  di = player.dissections.erase ( di );
890  } else
891  di++;
892  }
893 }
894 */
895 
897 {
898  int rppt = 0;
899  for ( Player::BuildingList::const_iterator i = map->player[player].buildingList.begin(); i != map->player[player].buildingList.end(); i++ )
900  rppt += (*i)->researchpoints;
901 
902  for ( Player::VehicleList::const_iterator i = map->player[player].vehicleList.begin(); i != map->player[player].vehicleList.end(); i++ )
903  rppt += (*i)->researchpoints;
904 
905  return rppt * multiplier;
906 }
907 
909 {
910  if ( activetechnology ) {
911  int rpt = getResearchPerTurn();
912  if ( !rpt )
913  return 0;
914  else
915  return ( activetechnology->researchpoints - progress + rpt - 1) / rpt;
916  } else
917  return -1;
918 }
919 
920 void Research::setPredefinedTechAdapter( const set<ASCString>& adapter )
921 {
922  predefinedTechAdapter.clear();
923  predefinedTechAdapter.insert( predefinedTechAdapter.end(), adapter.begin(), adapter.end());
924 }
925 
927 {
928  predefinedTechAdapter.push_back( techAdapter );
929 }
930 
931 
932 
934 
935 
936 
938 {
939  Resources res;
941  return res;
942 
943  int num = 0;
944  /*
945  for ( Player::BuildingList::iterator i = bld->getMap()->player[bld->getOwner()].buildingList.begin(); i != bld->getMap()->player[bld->getOwner()].buildingList.end(); ++i )
946  if ( (*i)->typ->special & cgresearchb)
947  if ( (*i)->researchpoints > 0 )
948  ++num;
949  */
950  num = 1;
951 
952 
953 
954  for ( int r = 0; r < 3; ++r )
955  if ( bld->baseType->maxplus.resource(r) < 0 ) {
956  if( research > bld->baseType->nominalresearchpoints ) {
957  float a = -bld->baseType->maxplus.resource(r) / pow(double(bld->baseType->nominalresearchpoints),2);
958  res.resource(r) = int( pow(pow(double(research),2) * a, 0.98 + double(num)/50) );
959  } else
960  res.resource(r) = -bld->baseType->maxplus.resource(r) * research / bld->baseType->nominalresearchpoints;
961  }
962 
963  return res;
964 }
965 
967 {
968  return returnResourcenUseForResearch ( bld, bld->researchpoints );
969 }
970 
971 
972 #if 0
973 void returnresourcenuseforresearch ( const Building* bld, int research, int* energy, int* material )
974 {
975  /*
976  double esteigung = 55;
977  double msteigung = 40;
978  */
979 
980  double res = research;
981  double deg = res / bld->typ->maxresearchpoints;
982 
983  double m = 1 / log ( minresearchcost + maxresearchcost );
984 
985  *energy = (int)(researchenergycost * research * ( exp ( deg / m ) - ( 1 - minresearchcost ) ) / 1000 * (researchcostdouble+res)/researchcostdouble);
986  *material = (int)(researchmaterialcost * research * ( exp ( deg / m ) - ( 1 - minresearchcost ) ) / 1000 * (researchcostdouble+res)/researchcostdouble);
987 /*
988  if ( bld->typ->maxresearchpoints > 0 ) {
989  *material = researchmaterialcost * research *
990  ( exp ( res / msteigung ) - 1 ) / ( exp ( (double)bld->typ->maxresearchpoints / (msteigung*2) ) - 1 ) * (10000+res)/10000 / 1000;
991  *energy = researchenergycost * ( exp ( res / esteigung ) - 1 ) / ( exp ( (double)bld->typ->maxresearchpoints / (esteigung*2) ) - 1 ) * (10000+res)/10000 / 1000;
992  } else {
993  *material = 0;
994  *energy = 0;
995  }
996  */
997 }
998 #endif
999 
1000 
void read(tnstream &stream)
read the binary representation of this item from the given stream
Definition: research.cpp:511
int queuedEvents
if ASC should check all events for fullfilled triggers, this variable will be set to true...
Definition: player.h:193
bool techAdapterAvail(const ASCString &ta) const
Definition: research.cpp:766
The (base-) classes which are thrown as exceptions.
int relatedUnitID
Definition: research.h:139
void writeInvertTreeOutput(const Technology *tech, tnstream &stream, vector< int > &history, vector< pair< int, int > > &blockedPrintList, const vector< IntRange > *onlyWithBaseTechs=NULL) const
Definition: research.cpp:237
void write(tnstream &stream) const
write the binary representation of this item to the given stream
Definition: research.cpp:536
void addBool(const ASCString &name, bool &property)
void read_techs(tnstream &stream, bool merge=false)
Definition: research.cpp:717
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
const BuildingType * typ
Definition: buildings.h:48
ASCString & toLower()
Definition: ascstring.cpp:36
bool requireEvent
Definition: research.h:141
void clear()
Definition: research.cpp:747
vector< ASCString > evalTechAdapter()
checks for TechAdapters whose preconditions are now satisfied.
Definition: research.cpp:774
virtual ASCString getLocation()
returns the location of the stream.
Definition: basestrm.cpp:274
ASCString showDebug(const Research &research) const
Definition: research.cpp:331
int currentTechAvailableIn() const
Definition: research.cpp:908
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
virtual ASCString getDeviceName()
returns the name of the stream.
Definition: basestrm.cpp:269
void setPredefinedTechAdapter(const set< ASCString > &adapter)
Definition: research.cpp:920
bool hasFunction(ContainerFunctions function) const
bool eventually_available(const Research &res, list< const Technology * > *dependencies) const
Definition: research.cpp:574
void addIntegerArray(const ASCString &name, vector< int > &property, bool required=true)
vector< int > developedTechnologies
Definition: research.h:183
void write(tnstream &stream)
Definition: research.cpp:698
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
vector< ASCString > addanytechnology(const Technology *tech)
adds the technology to the list of available technologies
Definition: research.cpp:849
void * icon
Definition: research.h:127
void warningMessage(const ASCString &str)
The interface for all kinds of IO stream.
void write(tnstream &stream) const
write the binary representation of this item to the given stream
Definition: research.cpp:388
ItemRepositoryLoader< Technology > technologyRepository("technology")
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
ASCString generateTechName(const Technology *tech)
Definition: research.cpp:213
ResearchAvailabilityStatus
Definition: research.h:45
void runTextIO(PropertyContainer &pc, const ASCString &defaultTechAdapter="")
Definition: research.cpp:454
void addStringArray(const ASCString &name, vector< ASCString > &property)
bool available(const Research &research) const
Definition: research.cpp:61
virtual void writeString(const string &pc, bool binary=true)
writes the C++ String pc to the stream.
Definition: basestrm.cpp:545
const int researchableWeaponImprovements
Definition: research.cpp:629
TechDependency techDependency
Definition: research.h:91
bool techsAvail
is used by the chooseTechnology dialog: the first time no techs are available this variable is still ...
Definition: research.h:225
TechDependency techDependency
Definition: research.h:143
VehicleList vehicleList
a list of all units
Definition: player.h:135
void runTextIO(PropertyContainer &pc)
registers the properties of this item for loading/writing into asctxt files
Definition: research.cpp:53
char * strrr(int a)
converts a to a string.
Definition: misc.cpp:66
void read(tnstream &stream)
Definition: research.cpp:621
void log(const Vehicle *attacker, const Vehicle *attackee)
Definition: attack.cpp:417
const int technologyVersion
Definition: research.cpp:509
TechAdapterContainer techAdapterContainer
const Technology * activetechnology
the technology that is currently being researched
Definition: research.h:191
ASCString infotext
Definition: research.h:128
Definition of THE central asc class: GameMap.
const Technology * goal
the technology that is defined as long-term goal
Definition: research.h:194
void read(tnstream &stream)
read the binary representation of this item from the given stream
Definition: research.cpp:33
void write(tnstream &stream) const
write the binary representation of this item to the given stream
Definition: research.cpp:45
const int techDependencyVersion
Definition: research.cpp:31
Resources returnResourcenUseForResearch(const ContainerBase *bld, int research)
Calculates the resources that are needed to research the given number of research.
Definition: research.cpp:937
void readClassContainer(C &c, tnstream &stream)
Definition: basestrm.h:752
const int researchVersion
Definition: research.cpp:632
ResearchAvailabilityStatus techAvailable(const Technology *tech) const
Definition: research.cpp:834
Player player[9]
Definition: gamemap.h:253
void read(tnstream &stream)
read the binary representation of this item from the given stream
Definition: research.cpp:379
Loki::Functor< bool, LOKI_TYPELIST_1(int) > CheckTechAvailabilityFunctor
Definition: research.h:61
int getResearchPerTurn() const
Definition: research.cpp:896
BlockingOtherTechnologies blockingOtherTechnologies
if this Technology has been researched, it will not be possible to research the technologies given he...
Definition: research.h:148
virtual ASCString readString(bool includeCR=false)
Reads and returns a string.
Definition: basestrm.cpp:535
BuildingList buildingList
a list of all units
Definition: player.h:139
void addInteger(const ASCString &name, int &property)
vector< int > secondaryIDs
when loading a file and these IDs are encountered, this object will be used.
Definition: research.h:132
void writeInvertTreeOutput(const ASCString &tech, tnstream &stream, const vector< IntRange > *onlyWithBaseTechs=NULL) const
Definition: research.cpp:469
int nominalresearchpoints
the number of reseach points for which the plus settings apllies
int & resource(int type)
Definition: typen.h:105
bool isBlocked(const Technology *tech) const
Definition: research.cpp:818
int techlevel
Definition: research.h:138
ASCString showDebug(const Research &research) const
Definition: research.cpp:479
void runTextIO(PropertyContainer &pc)
registers the properties of this item for loading/writing into asctxt files
Definition: research.cpp:551
ASCString generateTechLabel(const Technology *tech)
Definition: research.cpp:224
void settechlevel(int techlevel)
Definition: research.cpp:861
ASCString name
Definition: research.h:137
void runTextIO(PropertyContainer &pc)
registers the properties of this item for loading/writing into asctxt files
Definition: research.cpp:395
void read_struct(tnstream &stream, bool merge=false)
Definition: research.cpp:634
const ContainerBaseType * baseType
the type descriping all non-instance specific properties of the container
Definition: containerbase.h:80
bool techResearched(int id) const
Definition: research.cpp:757
void writeClassContainer(const C &c, tnstream &stream)
Definition: basestrm.h:742
int maxresearchpoints
the maximum number of research points a research center may produce
The parent class of Vehicle and Building; The name Container originates from Battle Isle...
Definition: containerbase.h:40
int researchpoints
Definition: research.h:135
An actual building on the map, which references a BuildingType Buildings have an owner,.
Definition: buildings.h:38
void read(tnstream &stream)
Definition: research.cpp:434
Resources are basically the currency of ASC.
Definition: typen.h:97
void addString(const ASCString &name, ASCString &property)
bool available(const Research &research) const
Definition: research.cpp:412
void addPredefinedTechAdapter(const ASCString &techAdapter)
Definition: research.cpp:926
int researchpoints
the current amount of research that the building conducts every turn
void addIntRangeArray(const ASCString &name, vector< IntRange > &property, bool required=true)
void writeTreeOutput(const ASCString &sourceTechName, tnstream &stream, bool reduce) const
outputs the dependencies in text format for processing by GraphViz
Definition: research.cpp:173
bool eventually_available(const Research &res, list< const Technology * > *dependencies) const
this will recursively scan through the tech tree to check if this item will be available sometime...
Definition: research.cpp:122
bool find(const ASCString &name)
Everything related to research.
int progress
Definition: research.h:189
int findInheritanceLevel(int id, vector< int > &stack, const ASCString &sourceTechName) const
Definition: research.cpp:130
bool available(const Research &research) const
Definition: research.cpp:402
ASCString listTriggeredTechAdapter() const
Definition: research.cpp:790
void write(tnstream &stream) const
Definition: research.cpp:445