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 const char* diplomaticStateNames[diplomaticStateNum+1] = 
00037 {
00038    "War",
00039    "Truce",
00040    "Peace",
00041    "Association",
00042    "Alliance",
00043    NULL
00044 };
00045 
00046 
00047 
00048 DiplomaticStateVector::DiplomaticStateVector( Player& _player ) : player( _player )
00049 {
00050 }
00051 
00052 
00053 void DiplomaticStateVector::turnBegins()
00054 {
00055    for ( QueuedStateChanges::iterator i = queuedStateChanges.begin(); i != queuedStateChanges.end(); ++i ) {
00056       if ( getState(i->first) > i->second ) {
00057          // we are changing to a more aggressive state, which doesn't need the confirmation of the counterpart
00058          setState( i->first, i->second );
00059          player.getParentMap()->player[ i->first ].diplomacy.setState( player.getPosition(), i->second);
00060       } else {
00061          // we are browsing through the queued changes of the target player to look if he accepted our proposal
00062          
00063          DiplomaticStateVector& target = player.getParentMap()->player[ i->first ].diplomacy;
00064          QueuedStateChanges::iterator t = target.queuedStateChanges.find( player.getPosition() );
00065          if ( t != target.queuedStateChanges.end() ) {
00066             // this should have been handled when the other player set his proposal 
00067          } else {
00068             // he did not answer
00069             // we are still doing nothing and deleting the request with the .clear below
00070          }
00071       }
00072    }
00073    queuedStateChanges.clear();
00074    
00075    // changes to war will be effective as soon as a new player is active,
00076    // so that the other player will get reaction fire if he approaches the war-declaring player
00077    for ( int p = 0; p < player.getParentMap()->getPlayerCount(); ++p ) {
00078       Player& pl = player.getParentMap()->getPlayer(p);
00079       if ( pl.exist() && p != player.getPosition() ) {
00080          DiplomaticStates state;
00081          if ( getProposal(p, &state ) )
00082             if ( state < getState(p)) {
00083                setState( p, state );
00084                pl.diplomacy.setState( player.getPosition(), state );
00085             }
00086       }
00087    }
00088 }
00089 
00090 
00091 
00092 DiplomaticStates DiplomaticStateVector::getState( PlayerID towardsPlayer ) const
00093 {
00094    if ( towardsPlayer.getID() < 0 )
00095       return WAR;
00096 
00097    if ( player.getPosition() == towardsPlayer.getID() )
00098       return ALLIANCE;
00099       
00100    if ( towardsPlayer.getID() < states.size() )
00101       return states[towardsPlayer.getID()];
00102    else
00103       return WAR;
00104 }
00105 
00106 void DiplomaticStateVector::resize( int size )
00107 {
00108    int oldsize  = states.size();
00109    states.resize(size);
00110    for ( int i = oldsize; i < size; ++i )
00111       states[i] = WAR;
00112 }
00113 
00114 
00115 void DiplomaticStateVector::setState( PlayerID towardsPlayer, DiplomaticStates s )
00116 {
00117    assert( towardsPlayer.getID() >= 0 );
00118 
00119    if ( towardsPlayer.getID() >= states.size() ) 
00120       resize(towardsPlayer.getID()+1);
00121       
00122    states[towardsPlayer.getID()] = s;
00123 }
00124 
00125 
00126 
00127 bool DiplomaticStateVector::getProposal( int fromPlayer, DiplomaticStates* state )
00128 {
00129    assert( fromPlayer >= 0 );
00130 
00131    DiplomaticStateVector& targ = player.getParentMap()->player[ fromPlayer ].diplomacy;
00132 
00133    QueuedStateChanges::iterator i = targ.queuedStateChanges.find( player.getPosition() );
00134          
00135    if ( i != targ.queuedStateChanges.end() ) {
00136       if ( state )
00137          *state = i->second;
00138       return true;
00139    } else
00140       return false;
00141 }
00142 
00143 
00144       
00145 void DiplomaticStateVector::read ( tnstream& stream )
00146 {
00147    stream.readInt();
00148    int size = stream.readInt();
00149    states.resize( size );
00150    for ( int i = 0; i < size; ++i )
00151       states[i] = DiplomaticStates( stream.readInt() );
00152       
00153    queuedStateChanges.clear();
00154       
00155    size = stream.readInt();
00156    for ( int i = 0; i< size; ++i ) {
00157       int p = stream.readInt();
00158       DiplomaticStates s = DiplomaticStates( stream.readInt() );
00159       queuedStateChanges[p] = s;
00160    }   
00161 }
00162 
00163 void DiplomaticStateVector::write ( tnstream& stream ) const
00164 {
00165    stream.writeInt( 1 );
00166    stream.writeInt( states.size() );
00167    for ( int i = 0; i< states.size(); ++i )
00168       stream.writeInt( int( states[i]));
00169 
00170    stream.writeInt( queuedStateChanges.size() );
00171    for ( QueuedStateChanges::const_iterator i = queuedStateChanges.begin(); i != queuedStateChanges.end(); ++i ) {
00172       stream.writeInt( i->first );
00173       stream.writeInt( int(i->second) );
00174    }   
00175 }
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 const char* Player :: playerStatusNames[6] = { "Human Player", 
00185                                                        "AI player",
00186                                                        "off",
00187                                                        "Supervisor",
00188                                                        "suspended",
00189                                                        NULL };
00190 
00191 
00192 Player :: Player() 
00193         : diplomacy( *this )
00194 {
00195    ai = NULL;
00196    parentMap = NULL;
00197    queuedEvents = 0;
00198    ASCversion = 0;
00199    color = 0;
00200    serverPlayerID = 0;
00201 }
00202 
00203 void Player :: setParentMap( GameMap* map, int pos )
00204 {
00205    parentMap = map;
00206    player = pos;
00207    parentMap->sigPlayerTurnBegins.connect( SigC::slot( *this, &Player::turnBegins ));   
00208    parentMap->sigPlayerUserInteractionBegins.connect( SigC::slot( *this, &Player::userInteractionBegins ));   
00209    parentMap->sigPlayerTurnEnds.connect( SigC::slot( *this, &Player::turnEnds ));   
00210 }
00211 
00212 
00213 void Player :: turnBegins( Player& p )
00214 {
00215    if ( &p == this ) {
00216       diplomacy.turnBegins();
00217    }   
00218    
00219    if ( stat == supervisor ) {
00220       parentMap->supervisorpasswordcrc = passwordcrc;  
00221    }
00222 }
00223 
00224 void Player :: userInteractionBegins( Player& p )
00225 {
00226    if ( &p == this ) {
00227    }
00228 }
00229 
00230 void Player :: turnEnds( Player& p )
00231 {
00232    if ( &p == this ) {
00233       sendQueuedMessages();
00234 
00235       if ( !exist() && stat != off ) {
00236          stat = off;
00237          resetView();
00238          resetResearch();
00239          resetTribute();
00240          resetPassword();
00241          email = "";
00242          name += " (removed)";
00243       }
00244    }
00245 }
00246 
00247 
00248 
00249 DI_Color Player :: getColor() const
00250 {
00251    if ( color == DI_Color(0)) {
00252       switch ( player ) {
00253          case 0: return DI_Color( 0xe0, 0, 0 );
00254          case 1: return DI_Color( 0, 0x71, 0xdb );
00255          case 2: return DI_Color( 0xbc, 0xb3, 0 );
00256          case 3: return DI_Color( 0, 0xaa, 0 );
00257          case 4: return DI_Color( 0xbc, 0, 0 );
00258          case 5: return DI_Color( 0xb2, 0, 0xb2 );
00259          case 6: return DI_Color( 0,0, 0xaa );
00260          case 7: return DI_Color( 0xbc, 0x67, 0 );
00261          case 8: return DI_Color( 0xaa, 0xaa, 0xaa );
00262       };
00263       return DI_Color(0, 0, 0);
00264    } else
00265       return color;
00266 }
00267 
00268 PlayerColor Player::getPlayerColor() const
00269 {
00270    return PlayerColor(getPosition(), getColor() );
00271 }
00272 
00273 
00274 ASCString Player :: getName( ) const
00275 {
00276    if ( name.length() ) 
00277       return name;
00278 
00279    if ( stat == off )
00280       return "off";
00281 
00282    return ASCString("Player ") + ASCString::toString(getPosition() );
00283 }
00284 
00285 int Player::getHumanPlayerNum( const GameMap* gamemap )
00286 {
00287    int h = 0;
00288    for ( int p = 0; p < gamemap->getPlayerCount(); ++p )
00289       if ( gamemap->getPlayer(p).exist() && gamemap->getPlayer(p).isHuman() )
00290          ++h;
00291    return h;
00292 }
00293 
00294 
00295 
00296 void Player :: sendQueuedMessages()
00297 {
00298    MessagePntrContainer::iterator mi = getParentMap()->unsentmessage.begin();
00299    while ( mi != getParentMap()->unsentmessage.end() ) {
00300       sentmessage.push_back ( *mi );
00301       for ( int i = 0; i < 8; i++ ) {
00302          if ( (*mi)->to & ( 1 << i ))
00303             getParentMap()->player[ i ].unreadmessage.push_back ( *mi );
00304          if ( (*mi)->cc & ( 1 << i ))
00305             getParentMap()->player[ i ].unreadmessage.push_back ( *mi );
00306       }
00307    
00308       mi = getParentMap()->unsentmessage.erase ( mi );
00309    }
00310 }
00311 
00312 
00313 bool Player::exist() const
00314 {
00315   return !(buildingList.empty() && vehicleList.empty());
00316 }
00317 
00318 
00319 const int playerVersion = 3; 
00320 
00321 void Player::read ( tnstream& stream )
00322 {
00323    int version  = stream.readInt();
00324    if ( version > playerVersion )
00325       throw tinvalidversion ( "Player", playerVersion, version );
00326    
00327    if ( version >= 3 )
00328       serverPlayerID = stream.readInt();
00329 }
00330 
00331 void Player::write ( tnstream& stream ) const
00332 {
00333    stream.writeInt( playerVersion );
00334    stream.writeInt( serverPlayerID );
00335 }
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 template <typename T> void swapData( T& t1, T& t2 )
00344 {
00345    T temp = t1;
00346    t1 = t2;
00347    t2 = temp;
00348 }
00349 
00350 void Player::swap ( Player& secondPlayer )
00351 {
00352    if ( &secondPlayer == this)
00353       return;
00354 
00355    typedef VehicleList VL;
00356    typedef VehicleList::iterator VLI;
00357 
00358    VL vl;
00359    for ( VLI i = vehicleList.begin(); i != vehicleList.end(); ) {
00360       (*i)->color = secondPlayer.player*8;
00361       vl.push_back ( *i );
00362       i = vehicleList.erase( i );
00363    }
00364 
00365    for ( VLI i = secondPlayer.vehicleList.begin(); i != secondPlayer.vehicleList.end(); ) {
00366       (*i)->color = player*8;
00367       vehicleList.push_back ( *i );
00368       i = secondPlayer.vehicleList.erase( i );
00369    }
00370 
00371    for ( VLI i = vl.begin(); i != vl.end(); ) {
00372       secondPlayer.vehicleList.push_back ( *i );
00373       i = vl.erase( i );
00374    }
00375 
00376 
00377    typedef Player::BuildingList BL;
00378    typedef Player::BuildingList::iterator BLI;
00379 
00380    BL bl;
00381    for ( BLI i = buildingList.begin(); i != buildingList.end(); ++i)
00382       bl.push_back ( *i );
00383 
00384    BL bl2 = secondPlayer.buildingList;
00385    for ( BLI i = bl2.begin(); i != bl2.end(); ++i)
00386       (*i)->convert( player, false );
00387 
00388    for ( BLI i = bl.begin(); i != bl.end(); ++i)
00389       (*i)->convert( secondPlayer.player, false );
00390 
00391    for (int i =0; i < parentMap->xsize * parentMap->ysize ;i++ ) {
00392       MapField* fld = &parentMap->field[i];
00393 
00394       VisibilityStates temp = fld->getVisibility( player );
00395       fld->setVisibility( fld->getVisibility( secondPlayer.player), player);
00396       fld->setVisibility( temp, secondPlayer.player);
00397 
00398 
00399       for ( MapField::MineContainer::iterator i = fld->mines.begin(); i != fld->mines.end(); i++ )
00400          if ( i->player == player )
00401             i->player = secondPlayer.player;
00402          else
00403             if ( i->player == secondPlayer.player  )
00404                i->player = player;
00405       if ( fld->resourceview ) {
00406          bool b = fld->resourceview->visible & (1 << player);
00407          int m = fld->resourceview->materialvisible[player];
00408          int f = fld->resourceview->fuelvisible[player];
00409 
00410          if ( fld->resourceview->visible & (1 << secondPlayer.player ) )
00411             fld->resourceview->setview( player, fld->resourceview->materialvisible[secondPlayer.player], fld->resourceview->fuelvisible[secondPlayer.player] );
00412          else
00413             fld->resourceview->resetview( player );
00414 
00415          if ( b ) 
00416             fld->resourceview->setview( secondPlayer.player, m, f );
00417          else
00418             fld->resourceview->resetview( secondPlayer.player );
00419       }
00420    } /* endfor */
00421 
00422    swapData( research, secondPlayer.research );
00423    swapData( existanceAtBeginOfTurn, secondPlayer.existanceAtBeginOfTurn );
00424 
00425    delete ai;
00426    ai = NULL;
00427 
00428    delete secondPlayer.ai;
00429    secondPlayer.ai = NULL;
00430 
00431    swapData( stat, secondPlayer.stat );
00432    swapData( passwordcrc, secondPlayer.passwordcrc );
00433    swapData( dissections, secondPlayer.dissections );
00434    swapData( unreadmessage, secondPlayer.unreadmessage );
00435    swapData( oldmessage, secondPlayer.oldmessage );
00436    swapData( sentmessage, secondPlayer.sentmessage );
00437    swapData( queuedEvents, secondPlayer.queuedEvents );
00438    swapData( ASCversion, secondPlayer.ASCversion );
00439    swapData( playTime, secondPlayer.playTime );
00440    swapData( cursorPos, secondPlayer.cursorPos );
00441    swapData( email, secondPlayer.email );
00442    swapData( name, secondPlayer.name );
00443    swapData( color, secondPlayer.color );
00444 
00445    diplomacy.swap( secondPlayer.player );
00446 
00447 
00448    int a = player;
00449    int b = secondPlayer.player;
00450    for ( int i= 0; i < parentMap->getPlayerCount(); ++i )
00451       if ( i != a ) {
00452          swapData( parentMap->tribute.paid[i][a], parentMap->tribute.paid[i][b] );
00453          swapData( parentMap->tribute.paid[a][i], parentMap->tribute.paid[b][i] );
00454          swapData( parentMap->tribute.avail[i][a], parentMap->tribute.avail[i][b] );
00455          swapData( parentMap->tribute.avail[a][i], parentMap->tribute.avail[b][i] );
00456          swapData( parentMap->tribute.payStatusLastTurn[i][a], parentMap->tribute.payStatusLastTurn[i][b] );
00457          swapData( parentMap->tribute.payStatusLastTurn[a][i], parentMap->tribute.payStatusLastTurn[b][i] );
00458       }
00459 
00460 }
00461 
00462 void DiplomaticStateVector::swap( int secondPlayer )
00463 {
00464    DiplomaticStateVector& secondDSV = player.getParentMap()->getPlayer(secondPlayer).diplomacy;
00465 
00466    swapData( states, secondDSV.states );
00467    swapData( queuedStateChanges, secondDSV.queuedStateChanges );
00468 
00469    
00470 
00471    for ( int i= 0; i < player.getParentMap()->getPlayerCount(); ++i ) {
00472       DiplomaticStates sec = player.getParentMap()->getPlayer(i).diplomacy.getState(secondPlayer);
00473       DiplomaticStates fir = player.getParentMap()->getPlayer(i).diplomacy.getState(player.getPosition());
00474 
00475       player.getParentMap()->getPlayer(i).diplomacy.setState(secondPlayer, fir );
00476       player.getParentMap()->getPlayer(i).diplomacy.setState(player.getPosition(), sec );
00477    }
00478 
00479 }
00480 
00481 
00482 void Player::merge ( Player& secondPlayer )
00483 {
00484 
00485 }
00486 
00487 
00488 void Player::resetView()
00489 {
00490    for ( int x = 0; x < getParentMap()->xsize; x++ )
00491       for ( int y = 0; y < getParentMap()->ysize; y++ ) {
00492          MapField* fld = getParentMap()->getField(x,y);
00493          fld->setVisibility( visible_not, player );
00494          if ( fld->resourceview )
00495             fld->resourceview->visible &= ~(1<<player);
00496       }
00497 
00498 }
00499 void Player::resetResearch()
00500 {
00501    research.clear();
00502 }
00503 
00504 void Player::resetTribute()
00505 {
00506    for ( int j = 0; j< getParentMap()->getPlayerCount(); ++j ) {
00507       getParentMap()->tribute.avail[player][j] = Resources();
00508       getParentMap()->tribute.avail[j][player]= Resources();
00509       getParentMap()->tribute.paid[player][j] = Resources();
00510       getParentMap()->tribute.paid[j][player]= Resources();
00511       getParentMap()->tribute.payStatusLastTurn[player][j] = Resources();
00512       getParentMap()->tribute.payStatusLastTurn[j][player]= Resources();
00513    }
00514 }
00515 
00516 void Player::resetPassword()
00517 {
00518    passwordcrc.reset();
00519 }
00520 
00521 bool Player::operator==( const Player& otherPlayer) const
00522 {
00523    return parentMap == otherPlayer.parentMap && player == otherPlayer.player;
00524 }

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