Advanced Strategic Command
alliancesetup.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 <sstream>
23 #include <pgimage.h>
24 #include <pglistboxbaseitem.h>
25 #include <pgtooltiphelp.h>
26 
27 #include "../iconrepository.h"
28 #include "../gamemap.h"
29 #include "../paradialog.h"
30 #include "playersetup.h"
31 #include "alliancesetup.h"
32 #include "../actions/diplomacycommand.h"
33 #include "../dialog.h"
34 
35 const int diplomaticStateIconSize = 20;
37 
38 
39 template<typename SelectionType>
40 int getItemNum() { return 0; };
41 
42 template<typename SelectionType>
43 const char* getStateName(int s) { return NULL; };
44 
45 
46 template<>
48 
49 template<>
50 const char* getStateName<DiplomaticStates>(int s) { return diplomaticStateNames[s]; };
51 
52 
53 template<>
54 int getItemNum<AllianceSetupWidget::DiplomaticTransitions>() { return diplomaticStateNum+1; };
55 
56 template<>
57 const char* getStateName<AllianceSetupWidget::DiplomaticTransitions>(int s)
58 {
59  if ( s == 0 )
60  return "Sneak Attack";
61  else
62  return diplomaticStateNames[s-1];
63 };
64 
65 
67 {
68  ASCString filename = "diplo-" + ASCString::toString(s) + ".png";
69  return filename;
70 };
71 
73 {
75  ASCString filename = "diplo-sneak.png";
76  return filename;
77  } else
79 };
80 
81 
82 template <typename SelectionType>
83 class ListBoxImageItem : public PG_ListBoxBaseItem {
84  SelectionType state;
85  public:
86  ListBoxImageItem( PG_ListBox *parent, PG_Point pos, SelectionType s ) : PG_ListBoxBaseItem( parent, diplomaticStateIconSize + 2*diplomaticStateIconSpace ), state(s)
87  {
88  new PG_Image( this, PG_Point(diplomaticStateIconSpace,diplomaticStateIconSpace), IconRepository::getIcon( getDiplomaticStateImage(s)).getBaseSurface() , false );
89  new PG_Label( this, PG_Rect(diplomaticStateIconSize + 5, diplomaticStateIconSpace, 200,diplomaticStateIconSize), getStateName<SelectionType>(s));
90  }
91 
92  sigc::signal<void,SelectionType> sigSet;
93 
94  bool eventMouseButtonUp(const SDL_MouseButtonEvent* button)
95  {
96  if(button->button != 1) {
97  return false;
98  }
99 
100  PG_ListBox* listbox = dynamic_cast<PG_ListBox*>(GetParent());
101 
102  if(listbox == NULL || !listbox->IsVisible()) {
103  return true;
104  }
105 
106  listbox->SelectItem(this);
107  listbox->QuitModal();
108  sigSet(state);
109 
110  return true;
111  }
112 };
113 
114 
115 
116 
117 
118 template <typename SelectionType>
119 class DiplomaticModeChooser : public PG_Widget {
120  SelectionType& mode;
121  bool writePossible;
122 
123  protected:
124 
125  void selectMode()
126  {
127  PG_ListBox listBox( NULL, PG_Rect( x, y + Height(), 250, getItemNum<SelectionType>() * ( diplomaticStateIconSpace * 2 + diplomaticStateIconSize ) + 4 ));
128  for ( int i = 0; i < getItemNum<SelectionType>(); ++i) {
129  ListBoxImageItem<SelectionType>* item = new ListBoxImageItem<SelectionType>( NULL, PG_Point(0,0), SelectionType(i));
130  item->sigSet.connect( sigc::mem_fun( *this, &DiplomaticModeChooser::SetState));
131  listBox.AddChild( item );
132  }
133  listBox.Show();
134  listBox.RunModal();
135  }
136 
137  public:
138  DiplomaticModeChooser ( PG_Widget *parent, const PG_Rect& pos, SelectionType& dm, bool writeable ) : PG_Widget( parent, pos, true ), mode(dm), writePossible( writeable )
139  {
140  };
141 
142  sigc::signal<void,SelectionType> sigStateChange;
143 
144  void eventDraw (SDL_Surface *surface, const PG_Rect &rect)
145  {
146  Surface s = Surface::Wrap( surface );
148  }
149 
150  void SetState( SelectionType state )
151  {
152  mode = state;
153  Redraw();
154  Update(true);
155  sigStateChange(state);
156  }
157 
158  bool eventMouseButtonUp(const SDL_MouseButtonEvent* button)
159  {
160  if (button->button != 1) {
161  return false;
162  }
163 
164  if ( writePossible )
165  selectMode();
166  return true;
167  }
168 };
169 
170 
171 AllianceSetupWidget::AllianceSetupWidget( GameMap* gamemap, ApplyStrategy* applyStrategy, bool allEditable, PG_Widget *parent, const PG_Rect &r, const std::string &style )
172  : PG_ScrollWidget( parent, r, style ) , actmap ( gamemap ), strategy( applyStrategy )
173 
174 {
175  this->allEditable = allEditable;
176  int playerNum = 0;
177 
178  for ( int i = 0; i < actmap->getPlayerCount(); ++i ) {
179  vector<DiplomaticTransitions> t;
180  vector< DiplomaticStates > s;
181 
182  const DiplomaticStateVector& diplo = actmap->player[i].diplomacy;
183 
184  for ( int j = 0; j < actmap->getPlayerCount(); ++j ) {
185  DiplomaticStateVector::QueuedStateChanges::const_iterator change = diplo.queuedStateChanges.find(j);
186  if ( change != diplo.queuedStateChanges.end() )
187  t.push_back( DiplomaticTransitions( change->second + 1 ));
188  else
189  t.push_back( DiplomaticTransitions( diplo.getState(j) + 1 ));
190  s.push_back( diplo.getState(j));
191  }
192 
193  stateChanges.push_back ( t );
194  states.push_back ( s );
195 
196  if ( actmap->player[i].exist() )
197  ++playerNum;
198  }
199 
200 
201  const int colWidth = 40;
202  const int lineHeight = 30;
203  const int barSpace = 5;
204  const int spacing = 10;
205  const int nameLength = 200;
206  const int barOverhang = 20;
207  const int sqaureWidth = lineHeight;
208  const int lineLength = sqaureWidth + nameLength + playerNum * (colWidth + spacing) + barOverhang;
209  const int colHeight = barOverhang + playerNum * (lineHeight + spacing) - spacing + barOverhang;
210 
211  #define calcx(counter) (sqaureWidth + nameLength + spacing + counter * (colWidth + spacing) )
212  #define calcy(counter) (barOverhang + counter * (lineHeight + spacing))
213 
214  int counter = 0;
215  for ( int i = 0; i < actmap->getPlayerCount(); ++i )
216  if ( actmap->player[i].exist() ) {
217  int x = calcx(counter);
218 
219  ColoredBar* verticalBar = new ColoredBar( actmap->player[i].getColor(), this, PG_Rect( x, 0, colWidth, colHeight ));
220  verticalBar->SetTransparency( 128 );
221 
222  ++counter;
223  }
224 
225 
226  counter = 0;
227  for ( int i = 0; i < actmap->getPlayerCount(); ++i ) // rows
228  if ( actmap->player[i].exist() ) {
229 
230  PlayerWidgets pw;
231  pw.pos = i;
232 
233  int y = calcy(counter);
234 
235  ColoredBar* horizontalBar = new ColoredBar( actmap->player[i].getColor(), this, PG_Rect( 0, y, lineLength, lineHeight ));
236  horizontalBar->SetTransparency( 128 );
237 
238  pw.name = new PG_LineEdit( horizontalBar, PG_Rect( sqaureWidth, barSpace, nameLength, lineHeight-2*barSpace ));
239  pw.name->SetText( actmap->player[i].getName());
240  pw.name->SetEditable( false );
241 
242  new PG_ToolTipHelp( pw.name, "Position: " + ASCString::toString(i) );
243 
244  PG_ThemeWidget* col = new PG_ThemeWidget( horizontalBar, PG_Rect( barSpace, barSpace, sqaureWidth - 2*barSpace, lineHeight - 2*barSpace ));
245  col->SetSimpleBackground(true);
246  col->SetBackgroundColor ( actmap->player[i].getColor());
247  col->SetBorderSize(0);
248 
249  int cnt2 = 0;
250  for ( int j = 0; j < actmap->getPlayerCount(); ++j ) // columns
251  if ( actmap->player[j].exist() ) {
252  if ( i != j ) {
253  int x = calcx(cnt2) - barSpace;
254  PG_Rect rect ( x + (colWidth - diplomaticStateIconSize)/2 , (lineHeight - diplomaticStateIconSize)/2,diplomaticStateIconSize,diplomaticStateIconSize);
255  if ( allEditable ) {
257  dmc->sigStateChange.connect( sigc::bind( sigc::mem_fun( *this, &AllianceSetupWidget::setState ), j, i));
258  diplomaticWidgets[ linearize( i,j) ] = dmc;
259  } else {
262  // dmc->sigStateChange.connect( sigc::bind( sigc::mem_fun( *this, &AllianceSetupWidget::setState ), j, i));
263  diplomaticWidgets[ linearize( i,j) ] = dmc;
264  }
265 
266  }
267  ++cnt2;
268  }
269 
270  playerWidgets.push_back( pw );
271 
272  ++counter;
273  }
274 
275  SetTransparency(255);
276 };
277 
278 
279 void AllianceSetupWidget::setState( DiplomaticStates s, int actingPlayer, int secondPlayer )
280 {
281  getState( actingPlayer, secondPlayer) = s;
282 
283  DiplomaticWidgets::iterator i = diplomaticWidgets.find( linearize( actingPlayer, secondPlayer) );
284  if ( i != diplomaticWidgets.end() )
285  i->second->Redraw(true);
286 }
287 
288 DiplomaticStates& AllianceSetupWidget::getState( int actingPlayer, int secondPlayer )
289 {
290  return states.at(actingPlayer).at(secondPlayer);
291 }
292 
293 int AllianceSetupWidget::linearize( int actingPlayer, int secondPlayer )
294 {
295  return actingPlayer * actmap->getPlayerCount() + secondPlayer;
296 }
297 
298 
300 {
301  for ( int acting = 0; acting < actmap->getPlayerCount(); ++acting )
302  for ( int second = 0; second < actmap->getPlayerCount(); ++second ) {
303 
304  if ( allEditable ) {
305  if ( getState( acting, second ) != actmap->player[acting].diplomacy.getState( second ))
306  actmap->player[acting].diplomacy.setState( second, getState( acting, second ));
307  } else {
308  if ( acting == actmap->actplayer ) {
309  if ( stateChanges[acting][second] == SNEAK_ATTACK ) {
310  strategy->sneakAttack( actmap, acting, second );
311  } else {
312  DiplomaticStates s = DiplomaticStates( stateChanges[acting][second] - 1);
314  DiplomaticStateVector::QueuedStateChanges::iterator q = actmap->player[acting].diplomacy.queuedStateChanges.find( second );
315  if ( q == actmap->player[acting].diplomacy.queuedStateChanges.end() )
316  t = getState( acting, second );
317  else
318  t = q->second;
319 
320  if ( t != s ) {
321  strategy->setState( actmap, acting, second, s );
322  }
323  }
324  }
325  }
326  }
327 };
328 
329 
331 {
332 }
333 
334 
335 
336 
337 
338 
339 
340 
341 
342 
344  AllianceSetupWidget* asw;
345  bool changed;
346  public:
347  AllianceSetupWindow( GameMap* actmap, AllianceSetupWidget::ApplyStrategy* strategy, bool allEditable, PG_Widget *parent, const PG_Rect &r ) : ASC_PG_Dialog( parent, r, "Diplomacy" ), changed(false)
348  {
349  asw = new AllianceSetupWidget( actmap, strategy, allEditable, this, PG_Rect( 5, 30, r.Width() - 10, r.Height() - 60 ));
350  PG_Button* ok = new PG_Button( this, PG_Rect( Width() - 200, Height() - 30, 90, 20 ), "OK" );
351  ok->sigClick.connect( sigc::hide( sigc::mem_fun( *this, &AllianceSetupWindow::Apply )));
352  PG_Button* cancel = new PG_Button( this, PG_Rect( Width() - 100, Height() - 30, 90, 20 ), "Cancel" );
353  cancel->sigClick.connect( sigc::hide( sigc::mem_fun( *this, &AllianceSetupWindow::QuitModal )));
354  }
355 
356  bool Apply()
357  {
358  asw->Apply();
359  QuitModal();
360  changed = true;
361  return true;
362  }
363 
364  bool isSomethingChanged() { return changed; };
365 
366 };
367 
369 {
370  AllianceSetupWindow asw ( actmap, strategy, supervisor, NULL, PG_Rect( 100, 100, 700, 500 ));
371  asw.Show();
372  asw.RunModal();
373  return asw.isSomethingChanged();
374 }
375 
376 void DirectAllianceSetupStrategy::sneakAttack ( GameMap* map, int actingPlayer, int towardsPlayer )
377 {
378  map->getPlayer( actingPlayer ).diplomacy.setState( towardsPlayer, WAR );
379 }
380 
381 
382 void DirectAllianceSetupStrategy::setState ( GameMap* map, int actingPlayer, int towardsPlayer, DiplomaticStates newState )
383 {
384  map->getPlayer( actingPlayer ).diplomacy.setState( towardsPlayer, newState );
385 }
DiplomaticStates getState(PlayerID towardsPlayer) const
Definition: player.cpp:92
sigc::signal< void, SelectionType > sigSet
const int diplomaticStateIconSpace
void setState(DiplomaticStates s, int actingPlayer, int secondPlayer)
Player & getPlayer(PlayerID p)
Definition: gamemap.h:257
DiplomaticStates
Definition: player.h:53
const char * diplomaticStateNames[diplomaticStateNum+1]
Definition: player.cpp:36
void eventDraw(SDL_Surface *surface, const PG_Rect &rect)
Definition: player.h:53
AllianceSetupWindow(GameMap *actmap, AllianceSetupWidget::ApplyStrategy *strategy, bool allEditable, PG_Widget *parent, const PG_Rect &r)
const char * getStateName< DiplomaticStates >(int s)
sigc::signal< void, SelectionType > sigStateChange
DiplomaticModeChooser(PG_Widget *parent, const PG_Rect &pos, SelectionType &dm, bool writeable)
int linearize(int actingPlayer, int secondPlayer)
ASCString getName() const
returns the name of the player
Definition: player.cpp:274
DiplomaticStateVector diplomacy
Definition: player.h:209
int getItemNum()
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
const char * getStateName(int s)
bool eventMouseButtonUp(const SDL_MouseButtonEvent *button)
const int diplomaticStateNum
Definition: player.h:52
const int diplomaticStateIconSize
#define calcy(counter)
void SetState(SelectionType state)
static ASCString toString(int i)
converts the parameter to a String
Definition: ascstring.cpp:193
#define calcx(counter)
AllianceSetupWidget(GameMap *gamemap, ApplyStrategy *applyStrategy, bool allEditable, PG_Widget *parent, const PG_Rect &r, const std::string &style="ScrollWidget")
ASCString getDiplomaticStateImage(DiplomaticStates s)
void setState(PlayerID towardsPlayer, DiplomaticStates s)
Definition: player.cpp:115
virtual void setState(GameMap *map, int actingPlayer, int towardsPlayer, DiplomaticStates newState)=0
virtual void sneakAttack(GameMap *map, int actingPlayer, int towardsPlayer)=0
Adapter class for using Paragui Dialogs in ASC. This class transfers the event control from ASC to Pa...
Definition: paradialog.h:127
int getItemNum< DiplomaticStates >()
DI_Color getColor() const
Definition: player.cpp:249
signed char actplayer
the player who is currently making his moves (may be human or AI)
Definition: gamemap.h:232
DiplomaticWidgets diplomaticWidgets
Definition: alliancesetup.h:48
vector< PlayerWidgets > playerWidgets
Definition: alliancesetup.h:50
Player player[9]
Definition: gamemap.h:253
bool eventMouseButtonUp(const SDL_MouseButtonEvent *button)
DiplomaticStates & getState(int actingPlayer, int secondPlayer)
vector< vector< DiplomaticStates > > states
Definition: alliancesetup.h:45
static Surface & getIcon(const ASCString &name)
GameMap * actmap
Definition: spfst.cpp:64
static Surface Wrap(SDL_Surface *surface)
Definition: surface.h:76
ListBoxImageItem(PG_ListBox *parent, PG_Point pos, SelectionType s)
const int playerNum
the maximum number of players that ASC can manage.
Definition: typen.h:54
vector< vector< DiplomaticTransitions > > stateChanges
Definition: alliancesetup.h:44
int getPlayerCount() const
Definition: gamemap.h:255
bool exist() const
does the player exist at all
Definition: player.cpp:313
bool setupalliances(GameMap *actmap, AllianceSetupWidget::ApplyStrategy *strategy, bool supervisor)
runs the Alliance-Setup dialog.
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182