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

player.cpp

Go to the documentation of this file.
00001 
00002 /***************************************************************************
00003                           gamemap.cpp  -  description
00004                              -------------------
00005     begin                : Tue Oct 24 2000
00006     copyright            : (C) 2000 by Martin Bickel
00007     email                : bickel@asc-hq.org
00008  ***************************************************************************/
00009 
00010 /***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   (at your option) any later version.                                   *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 #include <algorithm>
00020 #include <ctime>
00021 #include <cmath>
00022 
00023 #include "global.h"
00024 #include "misc.h"
00025 #include "typen.h"
00026 #include "vehicletype.h"
00027 #include "buildingtype.h"
00028 #include "player.h"
00029 #include "gamemap.h"
00030 #include "cannedmessages.h"
00031 
00032 
00033 PlayerID::PlayerID( const Player& p ) : num( p.getPosition() ) {};
00034 
00035 
00036 SigC::Signal4<void,GameMap*,int,int,DiplomaticStates> DiplomaticStateVector::anyStateChanged;
00037 SigC::Signal3<void,GameMap*,int,int> DiplomaticStateVector::shareViewChanged;
00038 
00039 
00040 const char* diplomaticStateNames[diplomaticStateNum+1] = 
00041 {
00042    "War",
00043    "Truce",
00044    "Peace",
00045    "Association",
00046    "Alliance",
00047    NULL
00048 };
00049 
00050 
00051 
00052 DiplomaticStateVector::DiplomaticStateVector( Player& _player ) : player( _player )
00053 {
00054 }
00055 
00056 
00057 void DiplomaticStateVector::turnBegins()
00058 {
00059    for ( QueuedStateChanges::iterator i = queuedStateChanges.begin(); i != queuedStateChanges.end(); ++i ) {
00060       if ( getState(i->first) > i->second ) {
00061          // we are changing to a more aggressive state, which doesn't need the confirmation of the counterpart
00062          setState( i->first, i->second );
00063          player.getParentMap()->player[ i->first ].diplomacy.setState( player.getPosition(), i->second);
00064       } else {
00065          // we are browsing through the queued changes of the target player to look if he accepted our proposal
00066          
00067          DiplomaticStateVector& target = player.getParentMap()->player[ i->first ].diplomacy;
00068          QueuedStateChanges::iterator t = target.queuedStateChanges.find( player.getPosition() );
00069          if ( t != target.queuedStateChanges.end() ) {
00070             // this should have been handled when the other player set his proposal 
00071          } else {
00072             // he did not answer
00073          }
00074       }
00075    }
00076    queuedStateChanges.clear();
00077 }
00078 
00079 
00080 
00081 DiplomaticStates DiplomaticStateVector::getState( int towardsPlayer ) const
00082 {
00083    if ( towardsPlayer < 0 )
00084       return WAR;
00085 
00086    if ( player.getPosition() == towardsPlayer )
00087       return ALLIANCE;
00088       
00089    if ( towardsPlayer < states.size() )
00090       return states[towardsPlayer];
00091    else
00092       return WAR;
00093 }
00094 
00095 void DiplomaticStateVector::resize( int size )
00096 {
00097    int oldsize  = states.size();
00098    states.resize(size);
00099    for ( int i = oldsize; i < size; ++i )
00100       states[i] = WAR;
00101 }
00102 
00103 
00104 void DiplomaticStateVector::setState( int towardsPlayer, DiplomaticStates s, bool fireSignal )
00105 {
00106    assert( towardsPlayer >= 0 );
00107 
00108    if ( towardsPlayer >= states.size() ) 
00109       resize(towardsPlayer+1);
00110       
00111    states[towardsPlayer] = s;
00112    
00113    if ( fireSignal )
00114       anyStateChanged( player.getParentMap(), player.getPosition(), towardsPlayer,s);
00115 }
00116 
00117 void DiplomaticStateVector::sneakAttack( int towardsPlayer )
00118 {
00119    assert( towardsPlayer >= 0 );
00120 
00121    setState( towardsPlayer, WAR );         
00122    player.getParentMap()->player[ towardsPlayer ].diplomacy.setState( player.getPosition(), WAR );
00123    
00124    int to = 0;
00125    for ( int j = 0; j < 8; j++ )
00126       if ( j != player.getPosition() )
00127          to |= 1 << j;
00128 
00129    ASCString txt;
00130    txt.format ( getmessage( 10001 ), player.getName().c_str(), player.getParentMap()->player[towardsPlayer].getName().c_str() );
00131    new Message ( txt, player.getParentMap(), to );
00132 }
00133 
00134 
00135 void DiplomaticStateVector::changeToState( int towardsPlayer, DiplomaticStates s, bool mail )
00136 {
00137    assert( towardsPlayer >= 0 );
00138 
00139    int msgid;
00140    if ( s > getState( towardsPlayer ))
00141       msgid = 10003;  //  propose peace
00142    else
00143       msgid = 10002;  // declare war
00144 
00145 
00146    bool oldShareView = sharesView(towardsPlayer);
00147 
00148    setState( towardsPlayer, s );
00149    
00150    DiplomaticStateVector& targ = player.getParentMap()->player[ towardsPlayer ].diplomacy;
00151    targ.setState( player.getPosition(), s );
00152 
00153    if( sharesView(towardsPlayer) != oldShareView )
00154       shareViewChanged( player.getParentMap(), player.getPosition(), towardsPlayer );
00155 
00156    if ( mail ) {
00157       ASCString txt;
00158       txt.format( getmessage( msgid ), player.getName().c_str(), diplomaticStateNames[s]  );
00159       new Message ( txt, player.getParentMap(), 1 << towardsPlayer );
00160    }
00161 /*
00162    for ( int p = 0; p < player.getParentMap()->getPlayerCount(); ++p )
00163       if ( p != player.getPosition() ) {
00164          if ( getState( p ) == ALLIANCE ) {
00165             // we have an allied player which must now react
00166             DiplomaticStateVector& ally = player.getParentMap()->getPlayer( p ).diplomacy;
00167             if ( ally.getState( towardsPlayer ) != s )
00168                ally.changeToState( towardsPlayer, s );
00169       
00170          }
00171          
00172          if ( targ.getState( p ) == ALLIANCE ) {
00173             // the opponent has an ally which must now react
00174             if ( getState( p ) != s )
00175                changeToState( p, s );
00176       
00177          }
00178       }
00179       */
00180 }
00181 
00182 
00183 void DiplomaticStateVector::propose( int towardsPlayer, DiplomaticStates s )
00184 {
00185    assert( towardsPlayer >= 0 );
00186 
00187    DiplomaticStateVector& targ = player.getParentMap()->player[ towardsPlayer ].diplomacy;
00188 
00189    QueuedStateChanges::iterator i = targ.queuedStateChanges.find( player.getPosition() );
00190          
00191    DiplomaticStates currentState = getState( towardsPlayer ) ;
00192 
00193    if ( i == targ.queuedStateChanges.end() || (s < currentState && i->second > currentState)) {
00194       // we only send a message if this is an initial proposal OR
00195       // if the other player proposed a more peaceful state, but we are setting a more hostile state
00196       ASCString txt;
00197       int msgid;
00198       if ( s > getState( towardsPlayer )) 
00199          msgid = 10003;  //  propose peace
00200       else
00201          msgid = 10002;  //  declare war
00202             
00203       txt.format( getmessage( msgid ), player.getName().c_str(), diplomaticStateNames[s]  ); 
00204       new Message ( txt, player.getParentMap(), 1 << towardsPlayer );
00205       
00206       queuedStateChanges[towardsPlayer] = s;
00207    }  else {
00208       // we are answering a proposal by the other player
00209       
00210       if ( s > getState( towardsPlayer )) {
00211          // our proposal is about going to a more peaceful state 
00212 
00213          if ( s > i->second ) {
00214             // we are proposing even more peace, but we'll only set the state he proposed and keep our proposal
00215             changeToState( towardsPlayer, i->second );
00216          } else {
00217             // he proposes less or equal peace, but we'll set the state he proposed and delete his proposal, because it's fulfilled
00218             changeToState( towardsPlayer, s, true );  // s < i->second would only send mail if the proposal differs
00219             targ.queuedStateChanges.erase( i );
00220          }
00221       } else {
00222          if ( s < i->second ) {
00223             // we go to an even more hostile state 
00224             changeToState( towardsPlayer, i->second );
00225             targ.queuedStateChanges.erase( i );
00226          } else {
00227             // we are going to a state that is more hostile than the current one, but less hostile then the other players declaration
00228             changeToState( towardsPlayer, s, false );
00229          }
00230 
00231       }
00232    }
00233    
00234 }
00235 
00236 bool DiplomaticStateVector::getProposal( int fromPlayer, DiplomaticStates* state )
00237 {
00238    assert( fromPlayer >= 0 );
00239 
00240    DiplomaticStateVector& targ = player.getParentMap()->player[ fromPlayer ].diplomacy;
00241 
00242    QueuedStateChanges::iterator i = targ.queuedStateChanges.find( player.getPosition() );
00243          
00244    if ( i != targ.queuedStateChanges.end() ) {
00245       if ( state )
00246          *state = i->second;
00247       return true;
00248    } else
00249       return false;
00250 }
00251 
00252 
00253       
00254 void DiplomaticStateVector::read ( tnstream& stream )
00255 {
00256    stream.readInt();
00257    int size = stream.readInt();
00258    states.resize( size );
00259    for ( int i = 0; i < size; ++i )
00260       states[i] = DiplomaticStates( stream.readInt() );
00261       
00262    queuedStateChanges.clear();
00263       
00264    size = stream.readInt();
00265    for ( int i = 0; i< size; ++i ) {
00266       int p = stream.readInt();
00267       DiplomaticStates s = DiplomaticStates( stream.readInt() );
00268       queuedStateChanges[p] = s;
00269    }   
00270 }
00271 
00272 void DiplomaticStateVector::write ( tnstream& stream ) const
00273 {
00274    stream.writeInt( 1 );
00275    stream.writeInt( states.size() );
00276    for ( int i = 0; i< states.size(); ++i )
00277       stream.writeInt( int( states[i]));
00278 
00279    stream.writeInt( queuedStateChanges.size() );
00280    for ( QueuedStateChanges::const_iterator i = queuedStateChanges.begin(); i != queuedStateChanges.end(); ++i ) {
00281       stream.writeInt( i->first );
00282       stream.writeInt( int(i->second) );
00283    }   
00284 }
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 const char* Player :: playerStatusNames[6] = { "Human Player", 
00294                                                        "AI player",
00295                                                        "off",
00296                                                        "Supervisor",
00297                                                        "suspended",
00298                                                        NULL };
00299 
00300 
00301 Player :: Player() 
00302         : diplomacy( *this )
00303 {
00304    ai = NULL;
00305    parentMap = NULL;
00306    queuedEvents = 0;
00307    ASCversion = 0;
00308    color = 0;
00309 }
00310 
00311 void Player :: setParentMap( GameMap* map, int pos )
00312 {
00313    parentMap = map;
00314    player = pos;
00315    parentMap->sigPlayerTurnBegins.connect( SigC::slot( *this, &Player::turnBegins ));   
00316    parentMap->sigPlayerUserInteractionBegins.connect( SigC::slot( *this, &Player::userInteractionBegins ));   
00317    parentMap->sigPlayerTurnEnds.connect( SigC::slot( *this, &Player::turnEnds ));   
00318 }
00319 
00320 
00321 void Player :: turnBegins( Player& p )
00322 {
00323    if ( &p == this ) {
00324       diplomacy.turnBegins();
00325    }   
00326 }
00327 
00328 void Player :: userInteractionBegins( Player& p )
00329 {
00330    if ( &p == this ) {
00331    }
00332 }
00333 
00334 void Player :: turnEnds( Player& p )
00335 {
00336    if ( &p == this ) {
00337       sendQueuedMessages();
00338 
00339       if ( !exist() && stat != off ) {
00340          stat = off;
00341          resetView();
00342          resetResearch();
00343          resetTribute();
00344          resetPassword();
00345          email = "";
00346          name += " (removed)";
00347       }
00348    }
00349 }
00350 
00351 
00352 
00353 DI_Color Player :: getColor() const
00354 {
00355    if ( color == DI_Color(0)) {
00356       switch ( player ) {
00357          case 0: return DI_Color( 0xe0, 0, 0 );
00358          case 1: return DI_Color( 0, 0x71, 0xdb );
00359          case 2: return DI_Color( 0xbc, 0xb3, 0 );
00360          case 3: return DI_Color( 0, 0xaa, 0 );
00361          case 4: return DI_Color( 0xbc, 0, 0 );
00362          case 5: return DI_Color( 0xb2, 0, 0xb2 );
00363          case 6: return DI_Color( 0,0, 0xaa );
00364          case 7: return DI_Color( 0xbc, 0x67, 0 );
00365          case 8: return DI_Color( 0xaa, 0xaa, 0xaa );
00366       };
00367       return DI_Color(0, 0, 0);
00368    } else
00369       return color;
00370 }
00371 
00372 PlayerColor Player::getPlayerColor() const
00373 {
00374    return PlayerColor(getPosition(), getColor() );
00375 }
00376 
00377 
00378 ASCString Player :: getName( ) const
00379 {
00380    if ( name.length() ) 
00381       return name;
00382 
00383    if ( stat == off )
00384       return "off";
00385 
00386    return ASCString("Player ") + ASCString::toString(getPosition() );
00387 }
00388 
00389 int Player::getHumanPlayerNum( const GameMap* gamemap )
00390 {
00391    int h = 0;
00392    for ( int p = 0; p < gamemap->getPlayerCount(); ++p )
00393       if ( gamemap->getPlayer(p).exist() && gamemap->getPlayer(p).isHuman() )
00394          ++h;
00395    return h;
00396 }
00397 
00398 
00399 
00400 void Player :: sendQueuedMessages()
00401 {
00402    MessagePntrContainer::iterator mi = getParentMap()->unsentmessage.begin();
00403    while ( mi != getParentMap()->unsentmessage.end() ) {
00404       sentmessage.push_back ( *mi );
00405       for ( int i = 0; i < 8; i++ ) {
00406          if ( (*mi)->to & ( 1 << i ))
00407             getParentMap()->player[ i ].unreadmessage.push_back ( *mi );
00408          if ( (*mi)->cc & ( 1 << i ))
00409             getParentMap()->player[ i ].unreadmessage.push_back ( *mi );
00410       }
00411    
00412       mi = getParentMap()->unsentmessage.erase ( mi );
00413    }
00414 }
00415 
00416 
00417 bool Player::exist() const
00418 {
00419   return !(buildingList.empty() && vehicleList.empty());
00420 }
00421 
00422 
00423 const int playerVersion = 2; 
00424 
00425 void Player::read ( tnstream& stream )
00426 {
00427    int version  = stream.readInt();
00428    if ( version > playerVersion )
00429       throw tinvalidversion ( "Player", playerVersion, version );
00430    
00431    // to be filled with future attributes
00432 }
00433 
00434 void Player::write ( tnstream& stream ) const
00435 {
00436    stream.writeInt( playerVersion );
00437    // to be filled with future attributes
00438 }
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 template <typename T> void swapData( T& t1, T& t2 )
00447 {
00448    T temp = t1;
00449    t1 = t2;
00450    t2 = temp;
00451 }
00452 
00453 void Player::swap ( Player& secondPlayer )
00454 {
00455    if ( &secondPlayer == this)
00456       return;
00457 
00458    typedef VehicleList VL;
00459    typedef VehicleList::iterator VLI;
00460 
00461    VL vl;
00462    for ( VLI i = vehicleList.begin(); i != vehicleList.end(); ) {
00463       (*i)->color = secondPlayer.player*8;
00464       vl.push_back ( *i );
00465       i = vehicleList.erase( i );
00466    }
00467 
00468    for ( VLI i = secondPlayer.vehicleList.begin(); i != secondPlayer.vehicleList.end(); ) {
00469       (*i)->color = player*8;
00470       vehicleList.push_back ( *i );
00471       i = secondPlayer.vehicleList.erase( i );
00472    }
00473 
00474    for ( VLI i = vl.begin(); i != vl.end(); ) {
00475       secondPlayer.vehicleList.push_back ( *i );
00476       i = vl.erase( i );
00477    }
00478 
00479 
00480    typedef Player::BuildingList BL;
00481    typedef Player::BuildingList::iterator BLI;
00482 
00483    BL bl;
00484    for ( BLI i = buildingList.begin(); i != buildingList.end(); ++i)
00485       bl.push_back ( *i );
00486 
00487    BL bl2 = secondPlayer.buildingList;
00488    for ( BLI i = bl2.begin(); i != bl2.end(); ++i)
00489       (*i)->convert( player );
00490 
00491    for ( BLI i = bl.begin(); i != bl.end(); ++i)
00492       (*i)->convert( secondPlayer.player );
00493 
00494    for (int i =0; i < parentMap->xsize * parentMap->ysize ;i++ ) {
00495       tfield* fld = &parentMap->field[i];
00496 
00497       VisibilityStates temp = fld->getVisibility( player );
00498       fld->setVisibility( fld->getVisibility( secondPlayer.player), player);
00499       fld->setVisibility( temp, secondPlayer.player);
00500 
00501 
00502       for ( tfield::MineContainer::iterator i = fld->mines.begin(); i != fld->mines.end(); i++ )
00503          if ( i->player == player )
00504             i->player = secondPlayer.player;
00505          else
00506             if ( i->player == secondPlayer.player  )
00507                i->player = player;
00508       if ( fld->resourceview ) {
00509          bool b = fld->resourceview->visible & (1 << player);
00510          int m = fld->resourceview->materialvisible[player];
00511          int f = fld->resourceview->fuelvisible[player];
00512 
00513          if ( fld->resourceview->visible & (1 << secondPlayer.player ) )
00514             fld->resourceview->setview( player, fld->resourceview->materialvisible[secondPlayer.player], fld->resourceview->fuelvisible[secondPlayer.player] );
00515          else
00516             fld->resourceview->resetview( player );
00517 
00518          if ( b ) 
00519             fld->resourceview->setview( secondPlayer.player, m, f );
00520          else
00521             fld->resourceview->resetview( secondPlayer.player );
00522       }
00523    } /* endfor */
00524 
00525    swapData( research, secondPlayer.research );
00526    swapData( existanceAtBeginOfTurn, secondPlayer.existanceAtBeginOfTurn );
00527 
00528    delete ai;
00529    ai = NULL;
00530 
00531    delete secondPlayer.ai;
00532    secondPlayer.ai = NULL;
00533 
00534    swapData( stat, secondPlayer.stat );
00535    swapData( passwordcrc, secondPlayer.passwordcrc );
00536    swapData( dissections, secondPlayer.dissections );
00537    swapData( unreadmessage, secondPlayer.unreadmessage );
00538    swapData( oldmessage, secondPlayer.oldmessage );
00539    swapData( sentmessage, secondPlayer.sentmessage );
00540    swapData( queuedEvents, secondPlayer.queuedEvents );
00541    swapData( ASCversion, secondPlayer.ASCversion );
00542    swapData( playTime, secondPlayer.playTime );
00543    swapData( cursorPos, secondPlayer.cursorPos );
00544    swapData( email, secondPlayer.email );
00545    swapData( name, secondPlayer.name );
00546    swapData( color, secondPlayer.color );
00547 
00548    diplomacy.swap( secondPlayer.player );
00549 
00550 
00551    int a = player;
00552    int b = secondPlayer.player;
00553    for ( int i= 0; i < parentMap->getPlayerCount(); ++i )
00554       if ( i != a ) {
00555          swapData( parentMap->tribute.paid[i][a], parentMap->tribute.paid[i][b] );
00556          swapData( parentMap->tribute.paid[a][i], parentMap->tribute.paid[b][i] );
00557          swapData( parentMap->tribute.avail[i][a], parentMap->tribute.avail[i][b] );
00558          swapData( parentMap->tribute.avail[a][i], parentMap->tribute.avail[b][i] );
00559          swapData( parentMap->tribute.payStatusLastTurn[i][a], parentMap->tribute.payStatusLastTurn[i][b] );
00560          swapData( parentMap->tribute.payStatusLastTurn[a][i], parentMap->tribute.payStatusLastTurn[b][i] );
00561       }
00562 
00563 }
00564 
00565 void DiplomaticStateVector::swap( int secondPlayer )
00566 {
00567    DiplomaticStateVector& secondDSV = player.getParentMap()->getPlayer(secondPlayer).diplomacy;
00568 
00569    swapData( states, secondDSV.states );
00570    swapData( queuedStateChanges, secondDSV.queuedStateChanges );
00571 
00572    resize( max(player.getPosition(), secondPlayer));
00573 
00574    for ( int i= 0; i < player.getParentMap()->getPlayerCount(); ++i )
00575       swapData( player.getParentMap()->getPlayer(i).diplomacy.states[secondPlayer],  player.getParentMap()->getPlayer(i).diplomacy.states[player.getPosition()] );
00576 
00577 }
00578 
00579 
00580 void Player::merge ( Player& secondPlayer )
00581 {
00582 
00583 }
00584 
00585 
00586 void Player::resetView()
00587 {
00588    for ( int x = 0; x < getParentMap()->xsize; x++ )
00589       for ( int y = 0; y < getParentMap()->ysize; y++ ) {
00590          tfield* fld = getParentMap()->getField(x,y);
00591          fld->setVisibility( visible_not, player );
00592          if ( fld->resourceview )
00593             fld->resourceview->visible &= ~(1<<player);
00594       }
00595 
00596 }
00597 void Player::resetResearch()
00598 {
00599    research.clear();
00600 }
00601 
00602 void Player::resetTribute()
00603 {
00604    for ( int j = 0; j< getParentMap()->getPlayerCount(); ++j ) {
00605       getParentMap()->tribute.avail[player][j] = Resources();
00606       getParentMap()->tribute.avail[j][player]= Resources();
00607       getParentMap()->tribute.paid[player][j] = Resources();
00608       getParentMap()->tribute.paid[j][player]= Resources();
00609       getParentMap()->tribute.payStatusLastTurn[player][j] = Resources();
00610       getParentMap()->tribute.payStatusLastTurn[j][player]= Resources();
00611    }
00612 }
00613 
00614 void Player::resetPassword()
00615 {
00616    passwordcrc.reset();
00617 }

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