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

Generated on Mon May 21 01:26:28 2012 for Advanced Strategic Command by  doxygen 1.5.1