Advanced Strategic Command
diplomacycommand.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 "diplomacycommand.h"
23 
24 #include "action-registry.h"
25 #include "../gamemap.h"
26 #include "../itemrepository.h"
27 #include "../cannedmessages.h"
28 #include "../viewcalculation.h"
29 #include "../spfst.h"
30 
31 #include "changediplomaticstate.h"
32 
33 DiplomacyCommand::DiplomacyCommand( GameMap* map )
34  : Command( map ), actingPlayer(-1), sneak ( false), newState(WAR), towardsPlayer(-1)
35 {
36 }
37 
38 
39 DiplomacyCommand::DiplomacyCommand( Player& player )
40  : Command( player.getParentMap() ), actingPlayer( player.getPosition() ), sneak ( false), newState(WAR), towardsPlayer(-1)
41 {
42 
43 }
44 
45 
46 
47 
49 {
50  Command::readData( stream );
51  stream.readInt();
52  actingPlayer = stream.readInt();
53  readClassContainer( generatedMessages, stream );
54  sneak = stream.readInt();
55  newState = (DiplomaticStates) stream.readInt();
56  towardsPlayer = stream.readInt();
57 }
58 
59 
60 void DiplomacyCommand::writeData ( tnstream& stream ) const
61 {
62  Command::writeData( stream );
63  stream.writeInt( 1 );
64  stream.writeInt( actingPlayer );
65  writeClassContainer( generatedMessages, stream );
66  stream.writeInt( sneak );
67  stream.writeInt( newState );
68  stream.writeInt( towardsPlayer );
69 }
70 
71 
73 {
74  sneak = true;
75  towardsPlayer = enemy.getPosition();
76  newState = WAR;
77  setState( SetUp );
78 }
79 
81 {
82  sneak = false;
83  towardsPlayer = towards.getPosition();
84  newState = state;
85  setState( SetUp );
86 }
87 
88 void DiplomacyCommand::deleteMessage( int id, MessagePntrContainer& list )
89 {
90  for ( MessagePntrContainer::iterator i = list.begin(); i != list.end(); ) {
91  if ( (*i)->id == id )
92  i = list.erase( i );
93  else
94  ++i;
95  }
96 }
97 
98 void DiplomacyCommand::deleteMessage( int id )
99 {
100  for ( int p = 0; p < getMap()->getPlayerCount(); ++p ) {
101  deleteMessage( id, getMap()->getPlayer(p).unreadmessage );
102  deleteMessage( id, getMap()->getPlayer(p).oldmessage );
103  deleteMessage( id, getMap()->getPlayer(p).sentmessage );
104  }
105 
106  deleteMessage( id, getMap()->unsentmessage );
107 
108  for ( MessageContainer::iterator i = getMap()->messages.begin(); i != getMap()->messages.end(); ) {
109  if ( (*i)->id == id ) {
110  delete *i;
111  i = getMap()->messages.erase( i );
112  } else
113  ++i;
114  }
115 }
116 
117 void DiplomacyCommand::sendMessage( int to, const ASCString& body )
118 {
119  Message* m = new Message ( body, getMap(), to );
120  generatedMessages.push_back( m->id );
121 }
122 
123 void DiplomacyCommand::immediateTwoWayChange( DiplomaticStates newState, const Context& context )
124 {
125  Player& acting = getMap()->getPlayer( actingPlayer );
126  Player& towards = getMap()->getPlayer( towardsPlayer );
127 
128  ActionResult res = (new ChangeDiplomaticState( acting, towards, 0, newState ))->execute(context);
129  if ( !res.successful() )
130  throw res;
131 
132  res = (new ChangeDiplomaticState( towards, acting, 0, newState ))->execute(context);
133  if ( !res.successful() )
134  throw res;
135 }
136 
137 
139 {
140  if ( getState() != SetUp )
141  return ActionResult(22000);
142 
143  if ( actingPlayer < 0 || actingPlayer >= getMap()->getPlayerCount() )
144  return ActionResult( 23100 );
145 
146  if ( towardsPlayer < 0 || towardsPlayer >= getMap()->getPlayerCount() )
147  return ActionResult( 23100 );
148 
149  Player& acting = getMap()->getPlayer( actingPlayer );
150  Player& towards = getMap()->getPlayer( towardsPlayer );
151 
152 
153  bool oldShareView = acting.diplomacy.sharesView( towards );
154 
155  if ( sneak ) {
156 
157  immediateTwoWayChange( newState, context );
158 
159  int to = 0;
160  for ( int j = 0; j < 8; j++ )
161  if ( j != actingPlayer )
162  if ( getMap()->getPlayer(j).exist() )
163  to |= 1 << j;
164 
165  ASCString txt;
166  txt.format ( getmessage( 10001 ), acting.getName().c_str(), getMap()->player[towardsPlayer].getName().c_str() );
167  sendMessage( to, txt );
168  } else {
169 
170 
171  DiplomaticStateVector& targ = towards.diplomacy;
172 
173  DiplomaticStateVector::QueuedStateChanges::iterator i = targ.queuedStateChanges.find( acting.getPosition() );
174 
175  DiplomaticStates currentState = acting.diplomacy.getState( towards ) ;
176 
177  bool initialProposal = i == targ.queuedStateChanges.end();
178 
179  if ( initialProposal || (newState < currentState && i->second > currentState)) {
180  // we only send a message if this is an initial proposal OR
181  // if the other player proposed a more peaceful state, but we are setting a more hostile state
182  ASCString txt;
183  int msgid;
184  if ( newState > acting.diplomacy.getState( towardsPlayer ))
185  msgid = 10003; // propose peace
186  else
187  msgid = 10002; // declare war
188 
189  txt.format( getmessage( msgid ), acting.getName().c_str(), diplomaticStateNames[newState] );
190 
191  sendMessage(1 << towardsPlayer, txt );
192 
193  ActionResult res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
194  if ( !res.successful() )
195  return res;
196 
197 
198 
199  } else {
200  // we are answering a proposal by the other player
201 
202  if ( newState > acting.diplomacy.getState( towardsPlayer )) {
203  // our proposal is about going to a more peaceful state
204 
205  if ( newState > i->second ) {
206  // we are proposing even more peace, but we'll only set the state he proposed and make a proposal ourself
207 
208  immediateTwoWayChange( i->second, context );
209 
210  ActionResult res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
211  if ( !res.successful() )
212  return res;
213 
214  } else {
215  // he proposes less or equal peace, but we'll set the lower state
216 
217  immediateTwoWayChange( newState, context );
218 
219  }
220 
221  // we'll delete the other's proposal, because we have now reacted to it
222  ActionResult res = (new ChangeDiplomaticState( towards, acting, -1, newState ))->execute(context);
223  if ( !res.successful() )
224  return res;
225 
226  } else {
227  if ( newState < i->second ) {
228  // we go to an even more hostile state
229  immediateTwoWayChange( i->second, context );
230 
231 
232  ActionResult res = (new ChangeDiplomaticState( towards, acting, -1, newState ))->execute(context);
233  if ( !res.successful() )
234  return res;
235 
236  res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
237  if ( !res.successful() )
238  return res;
239 
240  ASCString txt;
241  // declare war
242  txt.format( getmessage( 10002 ), acting.getName().c_str(), diplomaticStateNames[newState] );
243  sendMessage(1 << towardsPlayer, txt );
244 
245  } else {
246  // we are going to a state that is more hostile than the current one, but less hostile then the other players declaration
247  immediateTwoWayChange( newState, context);
248  }
249  }
250  }
251  }
252 
253  if ( acting.diplomacy.sharesView( towards ) != oldShareView ) {
254  computeview( getMap(), 0, false, &context );
255  mapChanged( getMap() );
256  repaintMap();
257  }
258 
259  setState( Finished );
260 
261  return ActionResult(0);
262 }
263 
264 
266 {
267  for ( vector<int>::iterator i = generatedMessages.begin(); i != generatedMessages.end(); ++i )
268  deleteMessage( *i );
269 
270  return Command::undoAction(context );
271 }
272 
273 
275 {
276  ASCString c;
277  c.format("setDiplomacy( map, %d, %d, %s, %d )", actingPlayer, towardsPlayer, sneak?"true":"false", newState );
278  return c;
279 }
280 
282 {
284 }
285 
287 {
288  ASCString s;
289  if ( sneak )
290  s = getMap()->getPlayer( actingPlayer ).getName() + " sneak attacks " + getMap()->getPlayer( towardsPlayer ).getName() ;
291  else {
292  s = getMap()->getPlayer( actingPlayer ).getName() + " set diplomatic state towards " + getMap()->getPlayer( towardsPlayer ).getName()
293  + " to " + diplomaticStateNames[newState];
294  }
295  return s;
296 }
297 
298 
299 namespace {
300  const bool r1 = registerAction<DiplomacyCommand> ( ActionRegistry::DiplomacyCommand );
301 }
302 
DiplomaticStates getState(PlayerID towardsPlayer) const
Definition: player.cpp:92
sigc::signal< void, GameMap * > mapChanged
Definition: spfst.cpp:52
Player & getPlayer(PlayerID p)
Definition: gamemap.h:257
ActionResult go(const Context &context)
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 computeview(GameMap *gamemap, int player_fieldcount_mask, bool disableShareView, const Context *context)
completely computes the view
DiplomaticStates
Definition: player.h:53
int GameActionID
Definition: action.h:35
the command is totally done
Definition: command.h:120
const char * diplomaticStateNames[diplomaticStateNum+1]
Definition: player.cpp:36
Definition: player.h:53
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
int getPosition() const
Definition: player.h:112
ASCString getName() const
returns the name of the player
Definition: player.cpp:274
void writeData(tnstream &stream) const
DiplomaticStateVector diplomacy
Definition: player.h:209
GameActionID getID() const
State getState() const
Definition: command.h:125
sigc::signal< void > repaintMap
}@
Definition: spfst.cpp:45
bool sharesView(PlayerID receivingPlayer) const
Definition: player.h:81
GameMap * getMap()
Definition: action.h:92
The interface for all kinds of IO stream.
ASCString & format(const charT *pFormat,...)
Definition: ascstring.cpp:78
A Command is an action that the player initiates.
Definition: command.h:114
void newstate(DiplomaticStates state, Player &towards)
ASCString getCommandString() const
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
const char * getmessage(int id)
returns a pointer to the message id. The messages must have been loaded with loadmessages ...
ActionResult execute(const Context &context)
Definition: action.cpp:41
MessageContainer messages
these are the messages themselfs. A MessagePntrContainer only stores pointers to message body which a...
Definition: gamemap.h:354
virtual void readData(tnstream &stream)
Definition: command.cpp:31
ActionResult(int code)
virtual ActionResult undoAction(const Context &context)
Definition: command.cpp:60
int id
an id that identifies the message. It is assigned automatically
Definition: messages.h:54
void setState(State state)
Definition: command.cpp:44
virtual void writeData(tnstream &stream) const
Definition: command.cpp:38
bool successful() const
void readClassContainer(C &c, tnstream &stream)
Definition: basestrm.h:752
Player player[9]
Definition: gamemap.h:253
list< Message * > MessagePntrContainer
Definition: messages.h:74
A Message to a player. It may either be send by another player or by the system.
Definition: messages.h:30
void readData(tnstream &stream)
ActionResult undoAction(const Context &context)
void sneakAttack(Player &enemy)
void writeClassContainer(const C &c, tnstream &stream)
Definition: basestrm.h:742
bool exist(const ASCString &s)
does a file s exist (wildcards allowed)
Definition: basestrm.cpp:2444
the different players in ASC. There may be 8 players (0..7) and neutral units (8) ...
Definition: player.h:99
int getPlayerCount() const
Definition: gamemap.h:255
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182
ASCString getDescription() const