diplomacycommand.cpp

Go to the documentation of this file.
00001 /*
00002      This file is part of Advanced Strategic Command; http://www.asc-hq.de
00003      Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00004  
00005      This program is free software; you can redistribute it and/or modify
00006      it under the terms of the GNU General Public License as published by
00007      the Free Software Foundation; either version 2 of the License, or
00008      (at your option) any later version.
00009  
00010      This program is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013      GNU General Public License for more details.
00014  
00015      You should have received a copy of the GNU General Public License
00016      along with this program; see the file COPYING. If not, write to the 
00017      Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00018      Boston, MA  02111-1307  USA
00019 */
00020 
00021 
00022 #include "diplomacycommand.h"
00023 
00024 #include "action-registry.h"
00025 #include "../gamemap.h"
00026 #include "../itemrepository.h"
00027 #include "../cannedmessages.h"
00028 #include "../viewcalculation.h"
00029 #include "../spfst.h"
00030 
00031 #include "changediplomaticstate.h"
00032 
00033 DiplomacyCommand::DiplomacyCommand( GameMap* map )
00034    : Command( map ), actingPlayer(-1), sneak ( false), newState(WAR), towardsPlayer(-1)
00035 {
00036 }
00037 
00038 
00039 DiplomacyCommand::DiplomacyCommand( Player& player )
00040    : Command( player.getParentMap() ), actingPlayer( player.getPosition() ), sneak ( false), newState(WAR), towardsPlayer(-1)
00041 {
00042    
00043 }
00044 
00045 
00046 
00047 
00048 void DiplomacyCommand::readData ( tnstream& stream )
00049 {
00050    Command::readData( stream );
00051    stream.readInt();
00052    actingPlayer = stream.readInt();
00053    readClassContainer( generatedMessages, stream );
00054    sneak = stream.readInt();
00055    newState = (DiplomaticStates) stream.readInt();
00056    towardsPlayer = stream.readInt();
00057 }
00058 
00059 
00060 void DiplomacyCommand::writeData ( tnstream& stream ) const
00061 {
00062    Command::writeData( stream );
00063    stream.writeInt( 1 );
00064    stream.writeInt( actingPlayer );
00065    writeClassContainer( generatedMessages, stream );
00066    stream.writeInt( sneak );
00067    stream.writeInt( newState );
00068    stream.writeInt( towardsPlayer );
00069 }
00070 
00071 
00072 void DiplomacyCommand::sneakAttack( Player& enemy )
00073 {
00074    sneak = true;
00075    towardsPlayer = enemy.getPosition();
00076    newState = WAR;
00077    setState( SetUp ); 
00078 }
00079 
00080 void DiplomacyCommand::newstate( DiplomaticStates state, Player& towards )
00081 {
00082    sneak = false;
00083    towardsPlayer = towards.getPosition();
00084    newState = state;
00085    setState( SetUp );
00086 }
00087 
00088 void DiplomacyCommand::deleteMessage( int id, MessagePntrContainer& list ) 
00089 {
00090    for ( MessagePntrContainer::iterator i = list.begin(); i != list.end(); ) {
00091        if ( (*i)->id == id )
00092           i = list.erase( i );
00093        else
00094           ++i;
00095    }
00096 }
00097 
00098 void DiplomacyCommand::deleteMessage( int id )
00099 {
00100    for ( int p = 0; p < getMap()->getPlayerCount(); ++p ) {
00101       deleteMessage( id, getMap()->getPlayer(p).unreadmessage );
00102       deleteMessage( id, getMap()->getPlayer(p).oldmessage );
00103       deleteMessage( id, getMap()->getPlayer(p).sentmessage );
00104    }
00105    
00106    deleteMessage( id, getMap()->unsentmessage );
00107    
00108    for ( MessageContainer::iterator i = getMap()->messages.begin(); i != getMap()->messages.end(); ) {
00109       if ( (*i)->id == id ) {
00110          delete *i;
00111          i = getMap()->messages.erase( i );
00112       } else
00113          ++i;
00114    }
00115 }
00116 
00117 void DiplomacyCommand::sendMessage( int to, const ASCString& body )
00118 {
00119    Message* m = new Message ( body, getMap(), to );
00120    generatedMessages.push_back( m->id );
00121 }
00122 
00123 void DiplomacyCommand::immediateTwoWayChange( DiplomaticStates newState, const Context& context )
00124 {
00125    Player& acting = getMap()->getPlayer( actingPlayer );
00126    Player& towards = getMap()->getPlayer( towardsPlayer );
00127    
00128    ActionResult res = (new ChangeDiplomaticState( acting, towards, 0, newState ))->execute(context);
00129    if ( !res.successful() )
00130       throw res;
00131              
00132    res = (new ChangeDiplomaticState( towards, acting, 0, newState ))->execute(context);
00133    if ( !res.successful() )
00134       throw res;
00135 }
00136 
00137 
00138 ActionResult DiplomacyCommand::go ( const Context& context )
00139 {
00140    if ( getState() != SetUp )
00141       return ActionResult(22000);
00142    
00143    if ( actingPlayer  < 0 || actingPlayer >= getMap()->getPlayerCount() )
00144       return ActionResult( 23100 );
00145    
00146    if ( towardsPlayer  < 0 || towardsPlayer >= getMap()->getPlayerCount() )
00147       return ActionResult( 23100 );
00148    
00149    Player& acting = getMap()->getPlayer( actingPlayer );
00150    Player& towards = getMap()->getPlayer( towardsPlayer );
00151    
00152    
00153    bool oldShareView = acting.diplomacy.sharesView( towards );
00154    
00155    if ( sneak ) {
00156       
00157       immediateTwoWayChange( newState, context );
00158       
00159       int to = 0;
00160       for ( int j = 0; j < 8; j++ )
00161          if ( j != actingPlayer )
00162             if ( getMap()->getPlayer(j).exist() )
00163                to |= 1 << j;
00164 
00165       ASCString txt;
00166       txt.format ( getmessage( 10001 ), acting.getName().c_str(), getMap()->player[towardsPlayer].getName().c_str() );
00167       sendMessage( to, txt );
00168    } else {
00169       
00170       
00171       DiplomaticStateVector& targ = towards.diplomacy;
00172 
00173       DiplomaticStateVector::QueuedStateChanges::iterator i = targ.queuedStateChanges.find( acting.getPosition() );
00174          
00175       DiplomaticStates currentState = acting.diplomacy.getState( towards ) ;
00176 
00177       bool initialProposal = i == targ.queuedStateChanges.end();
00178       
00179       if ( initialProposal || (newState < currentState && i->second > currentState)) {
00180          // we only send a message if this is an initial proposal OR
00181          // if the other player proposed a more peaceful state, but we are setting a more hostile state
00182          ASCString txt;
00183          int msgid;
00184          if ( newState > acting.diplomacy.getState( towardsPlayer )) 
00185             msgid = 10003;  //  propose peace
00186          else
00187             msgid = 10002;  //  declare war
00188             
00189          txt.format( getmessage( msgid ), acting.getName().c_str(), diplomaticStateNames[newState]  ); 
00190          
00191          sendMessage(1 << towardsPlayer, txt );
00192       
00193          ActionResult res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
00194          if ( !res.successful() )
00195             return res;
00196          
00197          
00198          
00199       }  else {
00200          // we are answering a proposal by the other player
00201       
00202          if ( newState > acting.diplomacy.getState( towardsPlayer )) {
00203             // our proposal is about going to a more peaceful state 
00204 
00205             if ( newState > i->second ) {
00206                // we are proposing even more peace, but we'll only set the state he proposed and make a proposal ourself
00207                
00208                immediateTwoWayChange( i->second, context );
00209                
00210                ActionResult res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
00211                if ( !res.successful() )
00212                   return res;
00213                
00214             } else {
00215                // he proposes less or equal peace, but we'll set the lower state 
00216               
00217                immediateTwoWayChange( newState, context );
00218                
00219             }
00220             
00221             // we'll delete the other's proposal, because we have now reacted to it
00222             ActionResult res = (new ChangeDiplomaticState( towards, acting, -1, newState ))->execute(context);
00223             if ( !res.successful() )
00224                return res;
00225             
00226          } else {
00227             if ( newState < i->second ) {
00228                // we go to an even more hostile state 
00229                immediateTwoWayChange( i->second, context );
00230                
00231                
00232                ActionResult res = (new ChangeDiplomaticState( towards, acting, -1, newState ))->execute(context);
00233                if ( !res.successful() )
00234                   return res;
00235                
00236                res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
00237                if ( !res.successful() )
00238                   return res;
00239                
00240                ASCString txt;
00241                // declare war 
00242                txt.format( getmessage( 10002 ), acting.getName().c_str(), diplomaticStateNames[newState]  ); 
00243                sendMessage(1 << towardsPlayer, txt );
00244                
00245             } else {
00246               // we are going to a state that is more hostile than the current one, but less hostile then the other players declaration
00247                immediateTwoWayChange( newState, context);
00248             }
00249          }
00250       }
00251    }
00252    
00253    if ( acting.diplomacy.sharesView( towards ) != oldShareView ) {
00254       computeview( getMap(), 0, false, &context );
00255       mapChanged( getMap() );
00256       repaintMap();
00257    }
00258    
00259    setState( Finished );
00260    
00261    return ActionResult(0);
00262 }
00263 
00264 
00265 ActionResult DiplomacyCommand :: undoAction( const Context& context )
00266 {
00267    for ( vector<int>::iterator i = generatedMessages.begin(); i != generatedMessages.end(); ++i )
00268       deleteMessage( *i );
00269    
00270    return Command::undoAction(context );
00271 }
00272 
00273 
00274 ASCString DiplomacyCommand :: getCommandString() const 
00275 {
00276    ASCString c;
00277    c.format("setDiplomacy( map, %d, %d, %s, %d  )", actingPlayer, towardsPlayer, sneak?"true":"false", newState );
00278    return c;
00279 }
00280 
00281 GameActionID DiplomacyCommand::getID() const 
00282 {
00283    return ActionRegistry::DiplomacyCommand;   
00284 }
00285 
00286 ASCString DiplomacyCommand::getDescription() const
00287 {
00288    ASCString s;
00289    if ( sneak ) 
00290       s = getMap()->getPlayer( actingPlayer ).getName() + " sneak attacks " + getMap()->getPlayer( towardsPlayer ).getName() ;
00291    else {
00292       s = getMap()->getPlayer( actingPlayer ).getName() + " set diplomatic state towards " + getMap()->getPlayer( towardsPlayer ).getName() 
00293             + " to " + diplomaticStateNames[newState];
00294    }
00295    return s;
00296 }
00297 
00298 
00299 namespace {
00300    const bool r1 = registerAction<DiplomacyCommand> ( ActionRegistry::DiplomacyCommand );
00301 }
00302 

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