Advanced Strategic Command
actioncontainer.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 "actioncontainer.h"
23 #include "../gamemap.h"
24 
25 #include "../util/messaginghub.h"
26 #include "../basestrm.h"
27 #include "../util/messaginghub.h"
28 
29 sigc::signal<void,GameMap*,const Command&> ActionContainer::postActionExecution;
30 sigc::signal<void,GameMap*,Command&> ActionContainer::commitCommand;
31 sigc::signal<void,GameMap*> ActionContainer::actionListChanged;
32 
33 
35  : map ( gamemap )
36 {
37  currentPos = actions.begin();
38 
39 }
40 
42 {
43  for ( Actions::iterator i = currentPos; i != actions.end(); ++i )
44  delete *i;
45  actions.erase( currentPos, actions.end() );
46 
47  actions.push_back( action );
48  currentPos = actions.end();
49 
50  commandState_map[action] = true;
51 
52  postActionExecution( map, *action );
53  actionListChanged(map);
54 }
55 
57 {
58  ActionResult res(0);
59  if ( currentPos == actions.begin() )
60  return ActionResult(23400);
61 
62  try {
63  Actions::iterator a = currentPos;
64  --a;
65  if( isActive_map( *a ) ) {
66  res = (*a)->undo ( context );
67  commandState_map[*a] = false;
68  }
69  currentPos = a;
70  } catch ( ActionResult result ) {
71  errorMessage(result.getMessage());
72  return result;
73  }
74  actionListChanged(map);
75  return res;
76 }
77 
78 
80 {
81  ActionResult res(0);
82  if ( currentPos == actions.end() )
83  return res;
84 
85  try {
86  res = (*currentPos)->redo( context );
87  commandState_map[*currentPos] = true;
88  ++currentPos;
89  } catch ( ActionResult result ) {
90  errorMessage(result.getMessage());
91  }
92  actionListChanged(map);
93  return res;
94 }
95 
97 {
98  for ( Actions::iterator i = actions.begin(); i != currentPos; ++i ) {
99  if( isActive_map( *i ) )
100  commitCommand( map, **i );
101  delete *i;
102  }
103  actions.clear();
104  currentPos=actions.end();
105 
106  actionListChanged(map);
107 }
108 
110 
112 {
113  int version = stream.readInt();
114  if ( version > actionContainerversion )
115  throw tinvalidversion ( "ActionContainer", actionContainerversion, version );
116 
117  int actionCount = stream.readInt();
118  for ( int i = 0; i < actionCount; ++i ) {
119  Command* a = dynamic_cast<Command*>( GameAction::readFromStream( stream, map ));
120  actions.push_back ( a );
121 
122  if ( version >= 2 ) {
123  commandState_map[a] = stream.readInt();
124 
125  int b = stream.readInt();
126  if ( b >= 0 )
127  commandState_map[a] = b;
128  }
129  }
130 
131  int pos = stream.readInt();
132  currentPos = actions.begin();
133  while ( pos-- )
134  currentPos++;
135 
136  if ( version <= 1 )
137  initCommandState( commandState_map );
138 
139 }
140 
141 
143 {
145 
146  stream.writeInt( actions.size() );
147  for ( Actions::iterator i = actions.begin(); i != actions.end(); ++i ) {
148  (*i)->write(stream );
149 
150  if ( commandState_map.find( *i ) != commandState_map.end() )
151  stream.writeInt( commandState_map[*i] );
152  else
153  stream.writeInt( 1 );
154 
155  if ( commandState_request.find( *i ) != commandState_request.end() )
156  stream.writeInt( commandState_request[*i] );
157  else
158  stream.writeInt( -1 );
159 
160  }
161 
162  int counter = 0;
163  Actions::iterator i = actions.begin();
164  while ( i != currentPos ) {
165  ++counter;
166  ++i;
167  }
168  stream.writeInt( counter );
169 
170 }
171 
172 void ActionContainer::getActionDescriptions( vector<ASCString>& list )
173 {
174  list.clear();
175  for ( Actions::iterator i = actions.begin(); i != currentPos; ++i )
176  list.push_back( (*i)->getDescription() );
177 
178 }
179 
180 void ActionContainer::initCommandState( CommandState& commandState )
181 {
182  commandState.clear();
183  for ( Actions::iterator i = actions.begin(); i != currentPos; ++i )
184  commandState[*i] = true;
185  for ( Actions::iterator i = currentPos; i != actions.end(); ++i )
186  commandState[*i] = false;
187 }
188 
189 
190 bool ActionContainer::isActive_map( const Command* action ) const
191 {
192  if ( commandState_map.find( action ) != commandState_map.end() )
193  return commandState_map.find(action)->second;
194  else {
195  warningMessage("ActionContainer::isActive_map - invalid parameter");
196  return false;
197  }
198 }
199 
201 {
202  if ( commandState_request.find( action ) != commandState_request.end() )
203  return commandState_request[action];
204  else {
205  commandState_request = commandState_map;
206  if ( commandState_request.find( action ) != commandState_request.end() )
207  return commandState_request[action];
208  else
209  return false;
210  }
211 }
212 
213 
215 {
216 
217  Actions::iterator firstDelta = currentPos;
218  Actions::iterator i = currentPos;
219  while ( i != actions.begin() ) {
220  --i;
221  if ( commandState_map.find( *i ) == commandState_map.end() )
222  fatalError( "ActionContainer::rerun - inconsistent commandState_map ");
223 
224  if ( commandState_request.find( *i ) != commandState_request.end() ) {
225  if ( commandState_request[*i] != commandState_map[*i] )
226  firstDelta = i;
227  }
228  }
229 
230  while ( currentPos > firstDelta ) {
231  --currentPos;
232  if( isActive_map( *currentPos ) ) {
233  ActionResult res = (*currentPos)->undo ( context );
234  if ( !res.successful())
235  return res;
236  }
237  }
238 
239  for ( CommandState::iterator j = commandState_request.begin(); j != commandState_request.end(); ++j )
240  commandState_map[j->first] = j->second;
241 
242  commandState_request.clear();
243 
244  while ( currentPos < actions.end() ) {
245  if( isActive_map( *currentPos ) ) {
246  ActionResult res = (*currentPos)->redo ( context );
247  if ( !res.successful())
248  return res;
249  }
250  ++currentPos;
251  }
252 
253 
254 
255  return ActionResult(0);
256 }
257 
258 
259 void ActionContainer::setActive( const Command* action, bool active )
260 {
261  if ( commandState_request.empty() )
262  commandState_request = commandState_map;
263 
264  commandState_request[action] = active;
265 }
266 
267 
269 {
270  for ( Actions::iterator i = actions.begin(); i != actions.end(); ++i ) {
271  if ( isActive_map( *i )) {
272  ASCString command = (*i)->getCommandString();
273  if ( !command.empty()) {
274  writer.printComment( (*i)->getDescription() );
275  writer.printCommand( command );
276  }
277  }
278  }
279 }
280 
281 
283 {
284  for ( Actions::iterator i = actions.begin(); i != actions.end(); ++i ) {
285  delete *i;
286  }
287 }
288 
virtual void printCommand(const ASCString &command)=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
static GameAction * readFromStream(tnstream &stream, GameMap *map)
Definition: action.cpp:150
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
bool isActive_map(const Command *action) const
returns if the command is active in the current map's state
const int actionContainerversion
void add(Command *action)
void warningMessage(const ASCString &str)
The interface for all kinds of IO stream.
A Command is an action that the player initiates.
Definition: command.h:114
void setActive(const Command *action, bool active)
static sigc::signal< void, GameMap *, const Command & > postActionExecution
signales an executed Command. The command can still be undone after postActionExecution ...
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
ASCString getMessage() const
ActionResult undo(const Context &context)
does a single undo step
bool isActive_req(const Command *action)
returns if the command is active in the queued command list
virtual void printComment(const ASCString &comment)=0
static sigc::signal< void, GameMap * > actionListChanged
void getActionDescriptions(vector< ASCString > &list)
void breakUndo()
to be called when some modification to the map is taking place that is not recorded by undo ...
ActionResult redo(const Context &context)
does a single redo step
void read(tnstream &stream)
bool successful() const
void errorMessage(const ASCString &string)
static sigc::signal< void, GameMap *, Command & > commitCommand
The command, which has already been executed, is finally commited and will not be undone any more Thi...
ActionContainer(GameMap *gamemap)
void getCommands(AbstractCommandWriter &writer)
ActionResult rerun(const Context &context)
reruns the necessary commands to propage take the changes done by setActive to the map ...
void write(tnstream &stream)
void fatalError(const ASCString &string)
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182