Advanced Strategic Command
action.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Advanced Strategic Command; http://www.asc-hq.de
3  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; see the file COPYING. If not, write to the
17  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  Boston, MA 02111-1307 USA
19 */
20 
21 
22 #include "action.h"
23 
24 #include "../vehicle.h"
25 #include "action-registry.h"
26 #include "actioncontainer.h"
27 
29  : gamemap(map)
30 {
31  static int counter = 0;
32  sequenceNumber = ++counter;
33 }
34 
35 
37 {
38  children.push_back ( action );
39 }
40 
42 {
43  if ( context.parentAction )
44  context.parentAction->addChild( this );
45 
46  Context c ( context, this );
47 
48  try {
49  displayLogMessage(4, "executing " + getDescription() + "\n");
50  ActionResult result = runAction( c );
51  Command* command = dynamic_cast<Command*>(this);
52  if ( context.actionContainer && result.successful() && !context.parentAction && command)
53  context.actionContainer->add( command );
54  return result;
55  } catch ( const ActionResult& res ) {
56  return res;
57  }
58 }
59 
60 ActionResult GameAction::undoChildren( const Context& context )
61 {
62  ActionResult res(0);
63  for ( Children::reverse_iterator i = children.rbegin(); i != children.rend(); ++i ) {
64  ActionResult r = (*i)->undo( context );
65  if ( !r.successful() && res.successful() )
66  res = r;
67  }
68  return res;
69 }
70 
71 static void mergeActionFailures( ActionResult& failure, const ActionResult& res )
72 {
73  if ( failure.successful() && !res.successful())
74  failure = res;
75 }
76 
78 {
79  // if there is one failuire, we'll preserve it
80  ActionResult failure(0);
81  if ( undoOrderChildFirst() ) {
82  ActionResult r = undoChildren(context);
83  mergeActionFailures( failure, r );
84  }
85 
86  displayLogMessage(4, "undoing #" + ASCString::toString(sequenceNumber) + " " + getDescription() + "\n");
87  ActionResult res = undoAction( context );
88  if ( !res.successful() )
89  warningMessage("error undoing " + getDescription() + "\n" + res.getMessage() );
90  mergeActionFailures( failure, res );
91 
92  if ( !undoOrderChildFirst() ) {
93  ActionResult r = undoChildren(context);
94  mergeActionFailures( failure, r );
95  }
96 
97  return failure;
98 }
99 
100 /*
101 GameActionID GameAction::getID() const
102 {
103  return ActionRegistry::Root;
104 }
105 */
106 
108 const int gameActionToken = 0x12003496;
109 
110 void GameAction::read ( tnstream& stream )
111 {
112  displayLogMessage(9, "reading " + ASCString::toString(getID()) + "\n");
113 
114  int version = stream.readInt();
115  if ( version > currentGameActionVersion )
116  throw tinvalidversion ( "GameAction", currentGameActionVersion, version );
117 
118  readData( stream );
119 
120  int token = stream.readInt();
121  if ( token != gameActionToken )
122  throw tinvalidversion ("GameActionToken for id " + ASCString::toString( getID() ), gameActionToken, token );
123 
124  int childNum = stream.readInt();
125  for ( int i = 0; i < childNum; i++ ) {
126  GameAction* child = readFromStream( stream, getMap() );
127  addChild( child );
128  }
129 }
130 
131 void GameAction::write ( tnstream& stream, bool persistChildren ) const
132 {
133  stream.writeInt( getID() );
134  stream.writeInt( currentGameActionVersion );
135  writeData( stream );
136  stream.writeInt( gameActionToken );
137  if ( persistChildren ) {
138  stream.writeInt( children.size() );
139  for ( int i = 0; i < children.size(); ++i )
140  children[i]->write( stream );
141  } else
142  stream.writeInt( 0 );
143 }
144 
145 void GameAction::write ( tnstream& stream ) const
146 {
147  write( stream, true );
148 }
149 
151 {
152  GameActionID id = GameActionID( stream.readInt() );
153  GameAction* action = gameActionFactory::Instance().createObject( id, map );
154  action->read( stream );
155  return action;
156 }
157 
158 
160 {
161  for ( Children::iterator i = children.begin(); i != children.end(); ++i )
162  delete *i;
163  children.clear();
164 }
static void mergeActionFailures(ActionResult &failure, const ActionResult &res)
Definition: action.cpp:71
virtual bool undoOrderChildFirst() const
determines the order in which the child actions are undone.
Definition: action.h:85
virtual ActionResult undoAction(const Context &context)=0
virtual void writeInt(int i)
Writes a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is p...
Definition: basestrm.cpp:363
int GameActionID
Definition: action.h:35
static GameAction * readFromStream(tnstream &stream, GameMap *map)
Definition: action.cpp:150
virtual ActionResult runAction(const Context &context)=0
virtual int readInt(void)
Reads a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is pe...
Definition: basestrm.cpp:284
virtual ASCString getDescription() const =0
virtual GameActionID getID() const =0
const int currentGameActionVersion
Definition: action.cpp:107
void add(Command *action)
void warningMessage(const ASCString &str)
GameMap * getMap()
Definition: action.h:92
The interface for all kinds of IO stream.
A Command is an action that the player initiates.
Definition: command.h:114
ASCString getMessage() const
ActionResult undo(const Context &context)
Definition: action.cpp:77
static ASCString toString(int i)
converts the parameter to a String
Definition: ascstring.cpp:193
ActionResult execute(const Context &context)
Definition: action.cpp:41
void displayLogMessage(int msgVerbosity, const char *message,...)
GameAction * parentAction
Definition: context.h:38
void write(tnstream &stream) const
Definition: action.cpp:145
bool successful() const
ActionContainer * actionContainer
Definition: context.h:41
void deleteChildren()
Definition: action.cpp:159
void addChild(GameAction *action)
adds a child action. Ownership of the child action is passed to THIS
Definition: action.cpp:36
const int gameActionToken
Definition: action.cpp:108
GameAction(GameMap *map)
Definition: action.cpp:28
A GameAction is an modification of something on a map.
Definition: action.h:45
void read(tnstream &stream)
Definition: action.cpp:110
virtual void writeData(tnstream &stream) const =0
virtual void readData(tnstream &stream)=0
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182