Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           base.cpp  -  description
00003                              -------------------
00004     begin                : Fri Mar 30 2001
00005     copyright            : (C) 2001 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "ai_common.h"
00019 
00020 #include "../replaymapdisplay.h"
00021 #include "../turncontrol.h"
00022 #include "../widgets/textrenderer.h"
00023 #include "../mapdisplay.h"
00024 #include "../asc-mainscreen.h"
00025 #include "../gameeventsystem.h"
00026 
00027 AI :: AI ( GameMap* _map, int _player ) : activemap ( _map ) , sections ( this )
00028 {
00029    strictChecks = false;
00030    benchMark = false;
00031 
00032    player = _player;
00033 
00034    _isRunning = false;
00035    fieldInformation = NULL;
00036 
00037    reset();
00038    ReplayMapDisplay* r = new ReplayMapDisplay ( &getDefaultMapDisplay() );
00039    r->setCursorDelay (CGameOptions::Instance()->replayspeed + 30 );
00040    rmd = r;
00041    mapDisplay = rmd;
00042 }
00043 
00044 void AI :: reset ( void )
00045 {
00046    maxTrooperMove = 0;
00047    maxTransportMove = 0;
00048    maxUnitMove = 0;
00049 
00050    for ( int i= 0; i < 8; i++ )
00051       maxWeapDist[i] = -1;
00052    baseThreatsCalculated = 0;
00053 
00054    if ( fieldInformation )
00055       delete[] fieldInformation;
00056 
00057    fieldInformation = NULL;
00058    fieldNum = 0;
00059 
00060    config.wholeMapVisible = 1;
00061    config.lookIntoTransports = 1;
00062    config.lookIntoBuildings = 1;
00063    config.aggressiveness  = 3;
00064    config.damageLimit = 70;
00065    config.resourceLimit = Resources ( 0, 5, 20 );
00066    config.ammoLimit= 10;
00067    config.maxCaptureTime = 15;
00068    config.maxTactTime = 10*100;
00069    config.waitForResourcePlus = 2;
00070 
00071    sections.reset();
00072 }
00073 
00074 
00075 
00076 void    AI :: setup (void)
00077 {
00078    displaymessage2("calculating all threats ... ");
00079    calculateAllThreats ();
00080 
00081    displaymessage2("calculating field threats ... ");
00082    calculateFieldInformation();
00083 
00084    displaymessage2("calculating sections ... ");
00085    sections.calculate();
00086 
00087 /*
00088    for ( i = 0; i <= 8; i++) {
00089       Building* building = actmap->player[i].firstbuilding;
00090       while (building != NULL) {
00091          generatethreatvaluebuilding(building);
00092          building = building->next;
00093       }
00094       if (i == actmap->actplayer) {
00095          building = actmap->player[i].firstbuilding;
00096          while (building != NULL) {
00097             tcmpcheckreconquerbuilding ccrcb;
00098             ccrcb.init(3);
00099             ccrcb.initsuche(building->xpos,building->ypos,(maxfusstruppenmove + maxtransportmove) / 8 + 1,0);
00100             ccrcb.startsuche();
00101             int j;
00102             ccrcb.returnresult( &j );
00103             ccrcb.done();
00104             building = building->next;
00105          }
00106       }
00107    }
00108    */
00109 
00110    /*
00111     punits units = new tunits;
00112     tjugdesituationspfd jugdesituationspfd;
00113     jugdesituationspfd.init(units,1);
00114     jugdesituationspfd.startsuche();
00115     jugdesituationspfd.done();
00116     delete units;
00117    */
00118 
00119    for ( int p = 0; p < 8; p++ )
00120       actmap->player[p].existanceAtBeginOfTurn = actmap->player[p].exist();
00121 
00122 
00123    for ( Player::VehicleList::iterator i = getPlayer().vehicleList.begin(); i != getPlayer().vehicleList.end(); ++i)
00124       if ( (*i)->typ->hasFunction( ContainerBaseType::MoveWithReactionFire ) )
00125           if ( (*i)->reactionfire.getStatus() == Vehicle::ReactionFire::off )
00126              (*i)->reactionfire.enable();
00127 
00128 
00129 
00130 
00131    // showthreats("init: threatvals generated");
00132    displaymessage2("setup completed ... ");
00133 }
00134 
00135 
00136 void AI::checkKeys ( void )
00137 {
00138    for ( int i = 0; i < 5; ++i )
00139       getPGApplication().processEvent();
00140 }
00141 
00142 void AI::removeDisplay()
00143 {
00144    mapDisplay = NULL;
00145 }
00146 
00147 
00148 typedef Loki::Functor<void> CloseScreenCallback;
00149 
00150 
00151 class AI_KeyboardWatcher : public SigC::Object {
00152       CloseScreenCallback callback;
00153       MapDisplayPG::LockDisplay* lock;
00154       PG_Widget* w;
00155       MainScreenWidget::StandardActionLocker menuLocker;
00156 
00157       bool keyPressed( const SDL_KeyboardEvent* key )
00158       {
00159          if ( key->keysym.sym == SDLK_ESCAPE  ) {
00160             callback();
00161 
00162             if ( !lock )
00163                lock = new MapDisplayPG::LockDisplay;
00164 
00165             return true;
00166          } else
00167             return false;
00168       }
00169 
00170    public:   
00171       AI_KeyboardWatcher( CloseScreenCallback callback ) : lock(NULL), w(NULL), menuLocker( mainScreenWidget, MainScreenWidget::LockOptions::Menu + MainScreenWidget::LockOptions::MapActions + MainScreenWidget::LockOptions::MapControl)
00172       {
00173          
00174          // w = new PG_Widget(NULL);
00175          // w->SetCapture();
00176          this->callback = callback;
00177          // w->sigKeyDown.connect( SigC::slot( *this, &AI_KeyboardWatcher::keyPressed ));
00178          PG_Application::GetApp()->sigKeyDown.connect( SigC::slot( *this, &AI_KeyboardWatcher::keyPressed ));
00179          
00180       };
00181 
00182       void release()
00183       {
00184          delete w;
00185          w = NULL;
00186          delete lock;
00187          lock = NULL;
00188       }
00189 
00190       ~AI_KeyboardWatcher() 
00191       {
00192          release();
00193       }
00194 };
00195 
00196 void AI :: checkGameEvents()
00197 {
00198    while ( getMap()->player[ actmap->actplayer ].queuedEvents )
00199       if ( !checkevents( mapDisplay ))
00200          return ;
00201 
00202    checktimedevents( mapDisplay );
00203 }
00204 
00205 void AI:: run ( bool benchMark )
00206 {
00207    AI_KeyboardWatcher kw ( CloseScreenCallback( this, &AI::removeDisplay )); 
00208 
00209    this->benchMark = benchMark;
00210 
00211    if ( getMap()->getPlayerView() >= 0 && !benchMark)
00212       mapDisplay = rmd;
00213    else
00214       mapDisplay = NULL;
00215 
00216    int startTime = ticker;
00217    AiResult res;
00218 
00219    unitCounter = 0;
00220    _isRunning = true;
00221    _vision = visible_ago;
00222 
00223    int setupTime = ticker;
00224    if ( mapDisplay ) 
00225       mapDisplay->setTempView( false );
00226    
00227    setup();
00228 
00229 //   GameMap::Weather weatherBackup = getMap()->weather;
00230 //   for ( int i = 0; i < 3; i++ )
00231 //      getMap()->weather.wind[i].speed = 0;
00232 
00233    diplomacy();
00234 
00235    if ( !originalUnitDistribution.calculated )
00236       originalUnitDistribution = calcUnitDistribution();
00237 
00238    calcReconPositions();
00239 
00240    if ( mapDisplay )
00241       mapDisplay->setTempView( true );
00242    
00243    setupTime = ticker-setupTime;
00244 
00245    int serviceTime = ticker;
00246    issueServices( );
00247    executeServices();
00248 
00249    checkGameEvents();
00250 
00251    serviceTime = ticker-serviceTime;
00252 
00253    int conquerTime = ticker;
00254    checkConquer();
00255    conquerTime = ticker - conquerTime;
00256 
00257    runReconUnits ( );
00258 
00259    int containerTime = ticker;
00260    buildings( 3 );
00261    transports ( 3 );
00262    containerTime = ticker-containerTime;
00263 
00264    int tacticsTime = ticker;
00265    do {
00266       res = tactics();
00267       checkGameEvents();
00268    } while ( res.unitsMoved );
00269    tacticsTime = ticker - tacticsTime;
00270 
00271    int strategyTime = ticker;
00272    strategy();
00273    checkGameEvents();
00274 
00275    strategyTime = ticker - strategyTime;
00276 
00277    buildings( 1 );
00278    transports ( 3 );
00279 
00280    production();
00281 
00282    checkGameEvents();
00283 
00284    _isRunning = false;
00285    if ( !mapDisplay )
00286       repaintMap();
00287    int duration = ticker-startTime;
00288 
00289 
00290    if ( getMap()->replayinfo )
00291       getMap()->replayinfo->closeLogging();
00292 
00293 //   getMap()->weather = weatherBackup;
00294 
00295    if ( benchMark ) // (CGameOptions::Instance()->runAI == 2 && duration > 100*60) ||
00296       displaymessage ("The AI took %.2f seconds to run\n"
00297                       " setup: %d \n"
00298                       " service: %d \n"
00299                       " conquer: %d \n"
00300                       " container: %d \n"
00301                       " tactics: %d \n"
00302                       " strategy: %d \n",
00303         3, float(duration)/100,
00304            setupTime / 100,
00305            serviceTime/100,
00306            conquerTime /100,
00307            containerTime/100,
00308            tacticsTime/100,
00309            strategyTime/100 );
00310 
00311    displaymessage2("AI completed in %d second", duration/100);
00312 
00313    checkforvictory( false );
00314 }
00315 
00316 
00317 void AI :: diplomacy ()
00318 {
00319    for ( int i = 0; i < getMap()->getPlayerCount(); ++i ) {
00320       if ( i != getPlayerNum() ) {
00321          DiplomaticStates proposal;
00322          if ( getPlayer().diplomacy.getProposal( i, &proposal )) {
00323             if ( proposal > getPlayer().diplomacy.getState( i ))
00324                new Message( "Your diplomatic proposal is declined", getMap(), 1 << i, 1 << getPlayerNum() );
00325             else
00326                getPlayer().diplomacy.propose( i, proposal );
00327          }
00328       }
00329    }
00330 }
00331 
00332 
00333 bool AI :: isRunning ( void )
00334 {
00335    return _isRunning;
00336 }
00337 
00338 
00339 VisibilityStates AI:: getVision ( void )
00340 {
00341    return _vision;
00342 }
00343 
00344 void AI :: showFieldInformation ( int x, int y )
00345 {
00346    if ( !fieldInformation )
00347       calculateFieldInformation();
00348 
00349    const char* fieldinfo = "#font02#Field Information (%d,%d)#font01##aeinzug20##eeinzug10##crtp10#"
00350                            "threat orbit: %d\n"
00351                            "threat high-level flight: %d\n"
00352                            "threat flight: %d\n"
00353                            "threat low-level flight: %d\n"
00354                            "threat ground level: %d\n"
00355                            "threat floating: %d\n"
00356                            "threat submerged: %d\n"
00357                            "threat deep submerged: %d\n"
00358                            "controlled by %d\n";
00359 
00360    char text[10000];
00361    AiThreat& threat = getFieldThreat ( x, y );
00362    sprintf(text, fieldinfo, x,y,threat.threat[7], threat.threat[6], threat.threat[5],
00363                                 threat.threat[4], threat.threat[3], threat.threat[2],
00364                                 threat.threat[1], threat.threat[0], getFieldInformation(x,y).control );
00365 
00366    tfield* fld = getfield (x, y );
00367    if ( fld->vehicle && fieldvisiblenow ( fld ) && fld->vehicle->aiparam[getPlayerNum()] ) {
00368       char text2[1000];
00369       sprintf(text2, "\nunit nwid: %d ; typeid: %d", fld->vehicle->networkid, fld->vehicle->typ->id );
00370       strcat ( text, text2 );
00371       AiParameter& aip = *fld->vehicle->aiparam[getPlayerNum()];
00372 
00373       if ( fld->vehicle->aiparam ) {
00374 
00375          sprintf(text2, "\nunit value: %d; xtogo: %d, ytogo: %d; ztogo: %d;\njob %s ; task %s \n", aip.getValue(), aip.dest.x, aip.dest.y, aip.dest.getBitmappedHeight(), AIjobs[aip.getJob()], AItasks[aip.getTask()] );
00376          strcat ( text, text2 );
00377       }
00378 
00379       if ( aip.dest.x >= 0 && aip.dest.y >= 0 ) {
00380          getMap()->cleartemps ( 1 );
00381          getfield ( aip.dest.x, aip.dest.y )->a.temp = 1;
00382       }
00383 
00384 
00385    }
00386 
00387    for ( ReconPositions::iterator i = reconPositions.begin(); i != reconPositions.end(); i++ )
00388       getMap()->getField( i->first )->a.temp2 = 1;
00389 
00390    repaintMap();
00391 
00392 
00393    strcat ( text, "\n#font02#Section Information#font01##aeinzug20##eeinzug10##crtp10#");
00394    string s;
00395 
00396    Section& sec = sections.getForCoordinate ( x, y );
00397 
00398    s += "xp = ";
00399    s += strrr ( sec.xp );
00400    s += " ; yp = ";
00401    s += strrr ( sec.yp );
00402    s += "\n";
00403    const char* threattypes[4] = { "absUnitThreat", "avgUnitThreat", "absFieldThreat", "avgFieldThreat" };
00404 
00405    for ( int i = 0; i < 4; i++ ) {
00406       for ( int h = 0; h < 8; h++ ) {
00407          s += threattypes[i];
00408          s += " ";
00409          s += choehenstufen [h];
00410          s += " ";
00411          switch ( i ) {
00412             case 0: s += strrr ( sec.absUnitThreat.threat[h] );
00413                     break;
00414             case 1: s += strrr ( sec.avgUnitThreat.threat[h] );
00415                     break;
00416             case 2: s += strrr ( sec.absFieldThreat.threat[h] );
00417                     break;
00418             case 3: s += strrr ( sec.avgFieldThreat.threat[h] );
00419                     break;
00420          }
00421          s += "\n";
00422       }
00423       s += "\n";
00424    }
00425 
00426    for ( int j = 0; j < aiValueTypeNum; j++ ) {
00427       s+= "\nvalue ";
00428       s+= strrr ( j );
00429       s+= " = ";
00430       s+= strrr ( sec.value[j] );
00431    }
00432 
00433    strcat ( text, s.c_str() );
00434 
00435    ViewFormattedText vft( "AI information", text, PG_Rect( -1, -1, 500, 550 ) );
00436    vft.Show();
00437    vft.RunModal();
00438 }
00439 
00440 
00441 const int currentAiStreamVersion = 104;
00442 
00443 void AI :: read ( tnstream& stream )
00444 {
00445    int version = stream.readInt ( );
00446    if ( version > currentServiceOrderVersion )
00447       throw tinvalidversion ( "AI :: read", currentServiceOrderVersion, version );
00448    _isRunning = stream.readInt ();
00449    _vision = VisibilityStates(stream.readInt ( ));
00450    unitCounter = stream.readInt ( );
00451 
00452    int i = stream.readInt();
00453    while ( i ) {
00454       ServiceOrder so ( this, stream );
00455       serviceOrders.push_back ( so );
00456       i = stream.readInt();
00457    }
00458 
00459    for_each ( serviceOrders.begin(), serviceOrders.end(), ServiceOrder::activate );
00460 
00461    i = stream.readInt();
00462    while ( i ) {
00463       MapCoordinate mc;
00464       mc.read ( stream );
00465 
00466       AI::BuildingCapture bc;
00467       bc.read ( stream );
00468 
00469       buildingCapture[mc] = bc;
00470 
00471       i = stream.readInt();
00472    }
00473 
00474    config.lookIntoTransports = stream.readInt();
00475    config.lookIntoBuildings = stream.readInt( );
00476    config.wholeMapVisible = stream.readInt( );
00477    config.aggressiveness = stream.readFloat( );
00478    config.damageLimit = stream.readInt();
00479    config.resourceLimit.read( stream );
00480    config.ammoLimit = stream.readInt();
00481    config.maxCaptureTime = stream.readInt();
00482    if ( version >= 102 )
00483       config.waitForResourcePlus = stream.readInt();
00484 
00485    if ( version >= 101 )
00486       config.maxTactTime = stream.readInt();
00487 
00488    if ( version >= 102 )
00489       originalUnitDistribution.read ( stream );
00490 
00491    if ( version >= 103 ) {
00492       int id = stream.readInt();
00493       while ( id >= 0 ) {
00494          float enemyValue = stream.readFloat();
00495          float ownValue = stream.readFloat();
00496          unitTypeSuccess[id] = make_pair ( enemyValue, ownValue );
00497          id = stream.readInt();
00498       }
00499    }
00500 
00501    if ( version >= 104 ) {
00502       int id = stream.readInt();
00503       while ( id >= 0 ) {
00504          stream.readFloat(); // enemyValue
00505          stream.readFloat(); // ownValue
00506          id = stream.readInt();
00507       }
00508    }
00509 
00510    int version2 = stream.readInt();
00511    if ( version != version2 )
00512       throw tinvalidversion ( "AI :: read", version, version2 );
00513 
00514 
00515 }
00516 
00517 void AI :: write ( tnstream& stream ) const
00518 {
00519    const int version = currentAiStreamVersion;
00520    stream.writeInt ( version );
00521    stream.writeInt ( _isRunning );
00522    stream.writeInt ( _vision );
00523    stream.writeInt ( unitCounter );
00524 
00525    for ( ServiceOrderContainer::const_iterator i = serviceOrders.begin(); i != serviceOrders.end(); i++) {
00526       stream.writeInt ( 1 );
00527       i->write ( stream );
00528    }
00529 
00530    stream.writeInt ( 0 );
00531 
00532    for ( map<MapCoordinate,BuildingCapture>::const_iterator i = buildingCapture.begin(); i != buildingCapture.end(); i++ ) {
00533       stream.writeInt ( 1 );
00534       i->first.write ( stream );
00535       i->second.write ( stream );
00536    }
00537    stream.writeInt ( 0 );
00538 
00539    stream.writeInt( config.lookIntoTransports );   /*  gegnerische transporter einsehen  */
00540    stream.writeInt( config.lookIntoBuildings );
00541    stream.writeInt( config.wholeMapVisible );
00542    stream.writeFloat( config.aggressiveness );   // 1: units are equally worth ; 2
00543    stream.writeInt( config.damageLimit );
00544    config.resourceLimit.write( stream );
00545    stream.writeInt( config.ammoLimit );
00546    stream.writeInt( config.maxCaptureTime );
00547    stream.writeInt( config.maxTactTime );
00548    stream.writeInt( config.waitForResourcePlus );
00549 
00550    originalUnitDistribution.write( stream );
00551 
00552    for ( UnitTypeSuccess::const_iterator i = unitTypeSuccess.begin(); i != unitTypeSuccess.end(); ++i ) {
00553      stream.writeInt( i->first );
00554      stream.writeFloat( i->second.first );
00555      stream.writeFloat( i->second.second );
00556    }
00557    stream.writeInt( -1 );
00558    stream.writeInt( -1 );
00559 
00560    stream.writeInt ( version );
00561 }
00562 
00563 
00564 AI :: ~AI ( )
00565 {
00566    if ( fieldInformation ) {
00567       delete[] fieldInformation;
00568       fieldInformation = NULL;
00569       fieldNum = 0;
00570    }
00571    if ( rmd ) {
00572       delete rmd;
00573       rmd = NULL;
00574    }
00575 }
00576 
00577 

Generated on Tue Jun 24 01:27:35 2008 for Advanced Strategic Command by  doxygen 1.4.2