action.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 "action.h"
00023 
00024 #include "../vehicle.h"
00025 #include "action-registry.h"
00026 #include "actioncontainer.h"
00027 
00028 GameAction::GameAction( GameMap* map )
00029  : gamemap(map)
00030 {
00031    static int counter = 0;
00032    sequenceNumber = ++counter;
00033 }
00034  
00035 
00036 void GameAction::addChild( GameAction* action )
00037 {
00038    children.push_back ( action );
00039 }
00040       
00041 ActionResult GameAction::execute( const Context& context ) 
00042 {
00043    if ( context.parentAction ) 
00044       context.parentAction->addChild( this );
00045    
00046    Context c ( context, this );
00047    
00048    try {
00049       displayLogMessage(4, "executing " + getDescription() + "\n");
00050       ActionResult result = runAction( c );
00051       Command* command = dynamic_cast<Command*>(this);
00052       if ( context.actionContainer && result.successful() && !context.parentAction && command)
00053          context.actionContainer->add( command );
00054       return result;
00055    } catch ( ActionResult res ) {
00056       return res;
00057    }
00058 }
00059 
00060 ActionResult GameAction::undoChildren( const Context& context )
00061 {
00062    ActionResult res(0);
00063    for ( Children::reverse_iterator i = children.rbegin(); i != children.rend(); ++i ) {
00064       ActionResult r = (*i)->undo( context );
00065       if ( !r.successful() && res.successful() )
00066          res =  r;
00067    }
00068    return res;
00069 }
00070 
00071 static void mergeActionFailures( ActionResult& failure, const ActionResult& res )
00072 {
00073    if ( failure.successful() && !res.successful())
00074       failure = res;  
00075 }
00076 
00077 ActionResult GameAction::undo( const Context& context ) 
00078 {
00079    // if there is one failuire, we'll preserve it
00080    ActionResult failure(0);
00081    if ( undoOrderChildFirst() )  {
00082       ActionResult r = undoChildren(context);
00083       mergeActionFailures( failure, r );
00084    }
00085    
00086    displayLogMessage(4, "undoing #" + ASCString::toString(sequenceNumber) + " " + getDescription() + "\n");
00087    ActionResult res = undoAction( context );
00088    if ( !res.successful() )
00089       warningMessage("error undoing " + getDescription() + "\n" + res.getMessage() );
00090    mergeActionFailures( failure, res );
00091    
00092    if ( !undoOrderChildFirst() ) {
00093       ActionResult r = undoChildren(context);
00094       mergeActionFailures( failure, r );
00095    }
00096    
00097    return failure;
00098 }
00099 
00100 /*
00101 GameActionID GameAction::getID() const
00102 {
00103    return ActionRegistry::Root;
00104 }
00105 */
00106 
00107 const int currentGameActionVersion = 1;
00108 const int gameActionToken = 0x12003496;
00109       
00110 void GameAction::read ( tnstream& stream )
00111 {
00112    displayLogMessage(1, "reading " + ASCString::toString(getID()) + "\n");
00113    
00114    int version = stream.readInt();
00115    if ( version > currentGameActionVersion )
00116       throw tinvalidversion ( "GameAction", currentGameActionVersion, version );
00117 
00118    readData( stream );
00119    
00120    int token = stream.readInt();
00121    if ( token != gameActionToken )
00122       throw tinvalidversion ("GameActionToken for id " + ASCString::toString( getID() ), gameActionToken, token );
00123    
00124    int childNum = stream.readInt();
00125    for ( int i = 0; i < childNum; i++ ) {
00126       GameAction* child = readFromStream( stream, getMap() );
00127       addChild( child );
00128    }
00129 }
00130 
00131 void GameAction::write ( tnstream& stream, bool persistChildren ) const
00132 {
00133    stream.writeInt( getID() );
00134    stream.writeInt( currentGameActionVersion );
00135    writeData( stream );
00136    stream.writeInt( gameActionToken );
00137    if ( persistChildren ) {
00138       stream.writeInt( children.size() );
00139       for ( int i = 0; i < children.size(); ++i ) 
00140          children[i]->write( stream );
00141    } else
00142       stream.writeInt( 0 );
00143 }
00144 
00145 void GameAction::write ( tnstream& stream ) const
00146 {
00147    write( stream, true );
00148 }
00149 
00150 GameAction* GameAction::readFromStream( tnstream& stream, GameMap* map )
00151 {
00152    GameActionID id = GameActionID( stream.readInt() );
00153    GameAction* action = gameActionFactory::Instance().createObject( id, map );
00154    action->read( stream );
00155    return action;
00156 }
00157 
00158 
00159 void GameAction::deleteChildren()
00160 {
00161    for ( Children::iterator i = children.begin(); i != children.end(); ++i )
00162       delete *i;
00163    children.clear();
00164 }

Generated on Mon May 14 01:31:39 2012 for Advanced Strategic Command by  doxygen 1.5.1