1 /* $Id: wopsettings.cpp,v 1.81.2.3 2006/01/24 10:08:10 chfreund Exp $ */
2
3 #include "global.hpp"
4 #include "constants.hpp"
5 #include "wopsettings.hpp"
6 #include "spriteset.hpp"
7 #include "string.hpp"
8
9 #include <cstdlib>
10 #include <cstdio>
11
12 #ifdef WIN32
13 #define NO_HOME_PATH_EXPANSION
14 #endif
15
16 #ifndef NO_HOME_PATH_EXPANSION
17 #include <pwd.h>
18 #endif
19
20 /**********************************************************/
21 // definition of some standard attributes
22
23 // STD_ATTR : standard setting
24 // - explicit assignment by "="
25 // - comma separation of parameters possible
26 #define STD_ATTR (Setting::EXPLICIT_ASSIGNMENT | \
27 Setting::COMMA_SEPARATED)
28 // STD_ATTR_MAND : standard setting, but mandatory
29 #define STD_ATTR_MAND (STD_ATTR | Setting::MANDATORY)
30 // STD_ATTR_CLO : standard settings, command line only
31 #define STD_ATTR_CLO (STD_ATTR | Setting::COMMAND_LINE_ONLY)
32 // STD_ATTR_CFO : standard settings, config file only
33 #define STD_ATTR_CFO (STD_ATTR | Setting::CONFIG_FILE_ONLY)
34
35 /**********************************************************
36 * definition of settings and string maps
37 **********************************************************/
38
39 // the default configuration file is defined as a macro,
40 // since it is also used in the help string of the setting
41
42 // commented out on 15.Jan 2005 (uwe)
43 //// #if defined(__APPLE__) || defined(WIN32)
44 //// #define DEFAULT_WOP_CONFIG_FILE "woprc.txt"
45 //// #else
46 //// #define DEFAULT_WOP_CONFIG_FILE ".woprc"
47 //// #endif
48
49 // Here the standard search paths for the config file are set,
50 // INCLUDING their names.
51 // This list also defines the hierarchy of the settings' usage.
52 // First the command line is parsed and the specified settings are
53 // accepted. Then one by one config file from the list defined in
54 // m_configPaths is read, and the settings are AUGMENTED with the
55 // ones in that file, NOT OVERWRITTEN. This alows for example the
56 // definition of a standard system-wide configuration file and a
57 // userspecific configuration file by setting:
58 //
59 // const char* WopSettings::m_configPaths[] = {
60 // "~/.woprc", "/usr/local/config/sys_woprc", NULL };
61 //
62 // The list must be terminated by a 0x0 pointer as last entry.
63 //
64 // So the settings are read in the following hierarchy:
65 //
66 // HIGHEST PRIORITY
67 // -> command line options
68 // -> options in configuration file, that has been
69 // specified optionally in the commandline using
70 // the setting "config=<path/filename>"
71 // -> m_configPaths[0]
72 // :
73 // :
74 // LOWEST PRIORITY
75 //
76 const char* WopSettings::m_configPaths[] = {
77 #ifdef __APPLE__
78 "~/woprc.txt",
79 #else
80 "~/.woprc", // home directory
81 "/usr/local/etc/woprc", // system wide
82 #endif
83 0x0
84 };
85
86 /**********************************************************/
87
88 // definition of the basic settings
89 SettingDef WopSettings::m_basicSettings[] = {
90 // the members are:
91 // (1) ID string of the setting
92 // (2) alternative ID string (optional, can also be set to NULL)
93 // (3) parameter type of the setting (Setting::[INT,BOOL,FLOAT,STRING])
94 // (4) minimal number of parameters for the setting
95 // (5) maximal number of parameters for the setting (-1 means unlimited)
96 // (6) attributes for the setting (as default use STD_ATTR, for more
97 // details read documentation of class SettingDef in settings.hpp
98 // (7) if the new setting is a server setting, that should be sent to
99 // the clients, add its IDstring to m_serverSettingsIDs
100 //
101 // try to limit line length of the help to maximal 60 characters |<------ 60 characters, including built in indent ------>|
102 // mode -> SettingStringMap<int> WopSettings::m_mode_StringMap[]
103 SettingDef( "mode", "m", Setting::STRING, 1, 1, STD_ATTR_MAND, "program mode [server,client,replay]", 0 ),
104 SettingDef( "gamemode","gm", Setting::STRING, 1, 1, STD_ATTR, "game mode (server only) [deathmatch,teamplay]", 0 ),
105 SettingDef( "data", "d", Setting::STRING, 1, 1, STD_ATTR, "path of data directory\n "
106 "default: \"data\", then /usr/local/games/wop/data", 0 ),
107 SettingDef( "server", "s", Setting::STRING, 1, 1, STD_ATTR, "server address. default: localhost", 0 ),
108 SettingDef( "width", "w", Setting::INT, 1, 1, STD_ATTR, "width of the game map: > 0 (server only)", 0 ),
109 SettingDef( "height", "h", Setting::INT, 1, 1, STD_ATTR, "height of the game map: > 0 (server only)", 0 ),
110 SettingDef( "theme", 0x0, Setting::STRING, 1, 1, STD_ATTR, "name of the map theme (effect on server only)\n "
111 "possible theme names are specified in file "THEME_CONFIG"\n "
112 "in the data directory (default: \"standard\").\n "
113 "To get a list of the available themes simply specify a\n "
114 "non-valid theme, e.g. theme=?", 0 ),
115 // view -> SettingStringMap<int> WopSettings::m_view_StringMap[]
116 SettingDef( "view", "v", Setting::STRING, 1, 1, STD_ATTR, "view mode: [fullscreen,window], default: window", 0 ),
117 SettingDef( "quiet", "q", Setting::BOOL , 0, 1, STD_ATTR, "no sound output: [yes,no], default: no", 0 ),
118 SettingDef( "config", "c", Setting::STRING, 1, 1, STD_ATTR_CLO, "path of the configuration file", 0 ),
119 SettingDef( "name", "n", Setting::STRING, 1, 1, STD_ATTR, "the name of the player", 0 ),
120 SettingDef( "color", "c", Setting::INT, 3, 3, STD_ATTR, "the color of the player's avatar, specified in the\n "
121 "three color components RED, GREEN, BLUE in this order.\n "
122 "The RGB values must be in range [0,255]" ),
123 SettingDef( "team", "t", Setting::INT, 1, 1, STD_ATTR, "the team number (0 <= team <= 19, only considered in \n "
124 "team mode)", 0 ),
125 SettingDef( "keyboard","kb", Setting::STRING, 1, 1, STD_ATTR, "Keyboard layout (de/us)" ),
126 SettingDef( "nballs", "nb", Setting::INT, 1, 1, STD_ATTR, "number of balls in the game", 0 ),
127 SettingDef( "ngoals", "ng", Setting::INT, 1, 1, STD_ATTR, "number of goals in the game", 0 ),
128 SettingDef( "szprob", 0x0, Setting::REAL, 1, 1, STD_ATTR, "probability for the creation of SkwoermZones [0.0, 1.0]", 0 ),
129 SettingDef( "debug", "db", Setting::BOOL, 0, 1, STD_ATTR, "debug mode: [yes,no], default: no", 0 ),
130 SettingDef( "musicdir", 0x0, Setting::STRING, 1, 1, STD_ATTR, "path of a directory containing sound files of type\n "
131 "*.wav, *.mp3, *.ogg, that are played randomly during\n "
132 "the game.", 0 ),
133 SettingDef( "bots", 0x0, Setting::STRING, 1,-1, STD_ATTR, "list of bot names" ),
134 SettingDef( "replaylog",0x0, Setting::STRING, 1, 1, STD_ATTR, "name of replay log file. This setting also activates\n "
135 "the replay logging (server only). To view the replay\n "
136 "in the specified file choose \"mode=replay\"", 0 ),
137 SettingDef( "keyhelp", 0x0, Setting::BOOL, 1, -1, STD_ATTR_CLO, "prints the long list of possible key configurations on\n "
138 "the terminal.", 0 ),
139 // settings for keyboard configuration
140 SettingDef( "key_left", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "left key (configuration file only)", 10 ),
141 SettingDef( "key_right", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "right key (configuration file only)", 10 ),
142 SettingDef( "key_down", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "down key (configuration file only)", 10 ),
143 SettingDef( "key_up", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "up key (configuration file only)", 10 ),
144 SettingDef( "key_shoot", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "shoot key (configuration file only)", 10 ),
145 SettingDef( "key_jump", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "jump key (configuration file only)", 10 ),
146 SettingDef( "key_dig", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "dig key (configuration file only)", 10 ),
147 SettingDef( "key_jet", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "jet key (configuration file only)", 10 ),
148 SettingDef( "key_rope_on", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "rope on key (configuration file only)", 10 ),
149 SettingDef( "key_rope_off", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "rope off key (configuration file only)", 10 ),
150 SettingDef( "key_rope_in", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "rope in key (configuration file only)", 10 ),
151 SettingDef( "key_rope_out", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "rope out key (configuration file only)", 10 ),
152 SettingDef( "key_rope_rel", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "rope rel key (configuration file only)", 10 ),
153 SettingDef( "key_screenshot", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "screenshot key (configuration file only)", 10 ),
154 SettingDef( "key_debug", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "debug key (configuration file only)", 10 ),
155 SettingDef( "key_dec_vol", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "decrease volume key (configuration file only)", 10 ),
156 SettingDef( "key_inc_vol", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "increase volume key (configuration file only)", 10 ),
157 SettingDef( "key_toggle_jukebox", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "toggle jukebox key (configuration file only)", 10 ),
158 SettingDef( "key_weapon_1", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 1 key (configuration file only)", 10 ),
159 SettingDef( "key_weapon_2", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 2 key (configuration file only)", 10 ),
160 SettingDef( "key_weapon_3", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 3 key (configuration file only)", 10 ),
161 SettingDef( "key_weapon_4", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 4 key (configuration file only)", 10 ),
162 SettingDef( "key_weapon_5", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 5 key (configuration file only)", 10 ),
163 SettingDef( "key_weapon_6", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 6 key (configuration file only)", 10 ),
164 SettingDef( "key_weapon_7", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 7 key (configuration file only)", 10 ),
165 SettingDef( "key_weapon_8", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 8 key (configuration file only)", 10 ),
166 SettingDef( "key_weapon_9", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 9 key (configuration file only)", 10 ),
167 SettingDef( "key_weapon_0", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "weapon 0 key (configuration file only)", 10 ),
168 SettingDef( "key_spawn", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "spawn key (configuration file only)", 10 ),
169 SettingDef( "key_next_weapon", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "next weapon key (configuration file only)", 10 ),
170 SettingDef( "key_prev_weapon", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "previous weapon key (configuration file only)", 10 ),
171 SettingDef( "key_insert_replay_bookmark",
172 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "insert replay bookmark key (configuration file only)", 10 ),
173 SettingDef( "key_change_focus", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "change focus key (configuration file only)", 10 ),
174 SettingDef( "key_toggle_fullscreen",
175 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "toggle fullscreen key (configuration file only)", 10 ),
176 SettingDef( "key_show_fps", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "show frames per second key (configuration file only)", 10 ),
177 SettingDef( "key_limit_fps", 0x0, Setting::STRING, 1, 1, STD_ATTR_CFO, "limit frames per second key (configuration file only)", 10 ),
178 // empty SettingDef() for termination, do not remove
179 SettingDef()
180 };
181
182 // map for the setting "mode"
183 SettingStringMap<int> WopSettings::
184 m_mode_StringMap[NUMBER_OF_PROGRAM_MODES+1] = {
185 SettingStringMap<int>( "server", SERVER ),
186 SettingStringMap<int>( "client", CLIENT ),
187 SettingStringMap<int>( "replay", REPLAY ),
188 SettingStringMap<int>()
189 };
190
191 // map for the setting "view"
192 SettingStringMap<int> WopSettings::
193 m_view_StringMap[NUMBER_OF_VIEW_MODES+1] = {
194 SettingStringMap<int>( "fullscreen", FULLSCREEN ),
195 SettingStringMap<int>( "window", WINDOW ),
196 SettingStringMap<int>()
197 };
198
199 // map for the setting "view"
200 SettingStringMap<int> WopSettings::
201 m_gamemode_StringMap[NUMBER_OF_GAME_MODES+1] = {
202 SettingStringMap<int>( "deathmatch", DEATHMATCH ),
203 SettingStringMap<int>( "teamplay", TEAMPLAY ),
204 SettingStringMap<int>()
205 };
206
207 // primary IDs of the settings, that are fixed on server side only
208 // and sent to all clients.
209 // IMPORTANT: All server settings must be present as objects on the
210 // server, since we have this Client-Server-Join-or--Start-Game-Feature.
211 // This creation of not explicitly set setting objects is done by
212 // method WopSettings::enforcePresenceOfServerSettings and is not
213 // adapted automatically to new entries in array m_serverSettingsIDs.
214 // Therefore, whenever you add a new server setting, also add its
215 // "instantiation" in WopSettings::enforcePresenceOfServerSettings.
216 const char* WopSettings::m_serverSettingsIDs[] = {
217 "gamemode",
218 "width", "height",
219 "nballs", "ngoals",
220 "theme",
221 NULL
222 };
223
224
225 /**********************************************************
226 * default values
227 **********************************************************/
228
229 // IMPORTANT: Do not use paths containing '~' for HOME as
230 // default paths. '~' is only expanded, if specified
231 // in command line or configuration file.
232 const int WopSettings::m_DefaultMode = CLIENT;
233 const int WopSettings::m_DefaultGameMode = DEATHMATCH;
234 const char WopSettings::m_DefaultData[] = "data";
235 const char WopSettings::m_DefaultServer[] = "localhost";
236 const int WopSettings::m_DefaultWidth = 1000;
237 const int WopSettings::m_DefaultHeight = 1000;
238 // RANDOM_CIRCLES_WOP_MAP_THEME defined in constants.hpp
239 const char WopSettings::m_DefaultTheme[] = "standard"; // RANDOM_CIRCLES_WOP_MAP_THEME;
240 const int WopSettings::m_DefaultView = WINDOW;
241 const bool WopSettings::m_DefaultQuiet = false;
242 #if defined(__APPLE__) || defined(WIN32)
243 const char WopSettings::m_DefaultConfig[] = "woprc.txt";
244 #else
245 const char WopSettings::m_DefaultConfig[] = ".woprc";
246 #endif
247 const char WopSettings::m_DefaultName[] = "The Dude";
248 const Uint32 WopSettings::m_DefaultPlayerColor = 0x00ffffff;
249 const int WopSettings::m_DefaultTeamID = 0;
250 const char WopSettings::m_DefaultKeyboard[] = "us";
251 const int WopSettings::m_DefaultNumBalls = 2;
252 const int WopSettings::m_DefaultNumGoals = 2;
253 const real WopSettings::m_DefaultSZProb = 0.01;
254 const bool WopSettings::m_DefaultDebug = false;
255
256 // some additional definitions, e.g. for range control
257 #define MIN_MAP_WIDTH 100
258 #define MAX_MAP_WIDTH 2000
259 #define MIN_MAP_HEIGHT 100
260 #define MAX_MAP_HEIGHT 2000
261 //#define MIN_GAME_ID 0
262
263 /**********************************************************/
264
265 #ifndef FUNCTION_ERROR
266 #define FUNCTION_ERROR(fns) "\033[31m" << fns << ":\033[0m\n >> "
267 #endif // FUNCTION_ERROR
268 #ifndef CALLED_FROM
269 #define CALLED_FROM(fns) " called from \033[36m" << fns << "\033[0m\n"
270 #endif // CALLED_FROM
271
272 /**********************************************************/
273
274 WopSettings* WopSettings::m_settings = 0;
275
276 /**********************************************************/
277
WopSettings(const bool verbose)278 WopSettings::WopSettings( const bool verbose )
279 : SettingDataBase( verbose ),
280 m_writeConfigFile( false ),
281 m_pickySuccess( false )
282 {}
283
284 /**********************************************************/
285
getInstance()286 WopSettings* WopSettings::getInstance()
287 {
288 if( NULL == m_settings &&
289 NULL == (m_settings = NEW WopSettings()) ) {
290 cerr << FUNCTION_ERROR("WopSettings::getInstance")
291 << "could not create setting object\n";
292 }
293 return m_settings;
294 }
295
296 /**********************************************************/
297
deleteInstance()298 void WopSettings::deleteInstance()
299 {
300 delete m_settings;
301 m_settings = NULL;
302 }
303
304 /**********************************************************/
305
~WopSettings()306 WopSettings::~WopSettings()
307 {
308 /* Deactivated writing of config file in the destructor,
309 * since this will be triggered in the settings GUI from
310 * now on (19.01.2005, uwe)
311 *
312 if( m_writeConfigFile ) {
313 Setting *setting = getSetting( "config" );
314 String path( setting ? setting->getString() : NULL );
315 writeConfigFile( path );
316 }
317 *
318 */
319 }
320
321 /**********************************************************/
322
getMode(const bool exitOnError) const323 int WopSettings::getMode( const bool exitOnError ) const
324 {
325 int mode = m_DefaultMode;
326 // note that "mode" is a mandatory setting, and that we
327 // have passed already SettingDataBase::finalCheck
328 // ==> setting "mode" is present
329 if( false == mapStringParameter("mode", m_mode_StringMap, mode) ) {
330 Setting *setting = getSetting( "mode" );
331 if( setting ) {
332 cerr << FUNCTION_ERROR("WopSettings::getMode")
333 << "\"" << setting->getString()
334 << "\" is not a valid program mode\n the list of "
335 "options follows\n\n";
336 // print help strings only of level 0
337 printHelp( 0, 0 );
338 }
339 if( exitOnError ) exit( 1 );
340 }
341
342 return mode;
343 }
344
345 /**********************************************************/
346
getGameMode() const347 int WopSettings::getGameMode() const
348 {
349 int gamemode = m_DefaultGameMode;
350 Setting *setting = getSetting( "gamemode" );
351 if( setting != NULL ) {
352 ASSERT( mapStringParameter("gamemode",
353 m_gamemode_StringMap,
354 gamemode),
355 "WopSettings::getGameMode: \"%s\" is not a valid "
356 "game mode.\n", setting->getString() );
357 }
358
359 return gamemode;
360 }
361
362 /**********************************************************/
363
getData() const364 const char* WopSettings::getData() const
365 {
366 const char *data = m_DefaultData;
367 Setting *setting = getSetting( "data" );
368 if( setting ) {
369 ASSERT( true == setting->expandPathString(), "could not expand "
370 "data path \"%s\"\n", setting->getString() );
371 data = setting->getString();
372 }
373 return (const char*)data;
374 }
375
376 /**********************************************************/
377
getServer() const378 const char* WopSettings::getServer() const
379 {
380 const char *server = m_DefaultServer;
381 Setting *setting = getSetting( "server" );
382 if( setting ) server = setting->getString();
383 return (const char*)server;
384 }
385
386 /**********************************************************/
387
getWidth() const388 int WopSettings::getWidth() const
389 {
390 int width = m_DefaultWidth;
391 Setting *setting = getSetting( "width" );
392 if( setting ) {
393 width = setting->getInt();
394 if( width < MIN_MAP_WIDTH || width > MAX_MAP_WIDTH ) {
395 cerr << FUNCTION_ERROR("WopSettings::getWidth")
396 << "width (given as " << width << ") must be in "
397 "range [" << MIN_MAP_WIDTH << ", " << MAX_MAP_WIDTH
398 << "]\n";
399 exit( 1 );
400 }
401 }
402 return width;
403 }
404
405 /**********************************************************/
406
getHeight() const407 int WopSettings::getHeight() const
408 {
409 int height = m_DefaultHeight;
410 Setting *setting = getSetting( "height" );
411 if( setting ) {
412 height = setting->getInt();
413 if( height < MIN_MAP_HEIGHT || height > MAX_MAP_HEIGHT ) {
414 cerr << FUNCTION_ERROR("WopSettings::getHeight")
415 << "heigth (given as " << height << ") must be in "
416 "range [" << MIN_MAP_HEIGHT << ", " << MAX_MAP_HEIGHT
417 << "]\n";
418 exit( 1 );
419 }
420 }
421 return height;
422 }
423
424 /**********************************************************/
425
getTheme() const426 const char* WopSettings::getTheme() const
427 {
428 const Setting* setting = getSetting( "theme" );
429 if( setting ) return setting->getString();
430
431 return m_DefaultTheme;
432 }
433
434 /**********************************************************/
435
getView() const436 int WopSettings::getView() const
437 {
438 int view = m_DefaultView;
439 if( NULL != getSetting("view") &&
440 false == mapStringParameter("view", m_view_StringMap, view) ) {
441 cerr << FUNCTION_ERROR("WopSettings::getView")
442 << "\"" << getSetting("view")->getString()
443 << "\" is not a valid view\n the list of options"
444 " follows\n\n";
445 // print help strings only of level 0
446 printHelp( 0, 0 );
447 exit( 1 );
448 }
449 return view;
450 }
451
452 /**********************************************************/
453
getQuiet() const454 bool WopSettings::getQuiet() const
455 {
456 bool quiet = m_DefaultQuiet;
457 Setting *setting = getSetting( "quiet" );
458 if( setting ) {
459 // quiet should be also usable as a simple flag
460 // -> no parameter is interpreted as "true"
461 quiet = setting->getNumParameters() > 0
462 ? setting->getBool()
463 : true;
464 // if the setting "quiet" is not specified explicitly,
465 // the server runs in quiet mode explicitely
466 } else {
467 if( SERVER == getMode() ) quiet = true;
468 }
469 return quiet;
470 }
471
472 /**********************************************************/
473
getName() const474 const char* WopSettings::getName() const
475 {
476 const char *name = m_DefaultName;
477 Setting *setting = getSetting( "name" );
478 if( setting ) name = setting->getString();
479 return (const char*) name;
480 }
481
482 /**********************************************************/
483
getPlayerColor() const484 Uint32 WopSettings::getPlayerColor() const
485 {
486 Uint32 color = m_DefaultPlayerColor;
487 Setting* setting = getSetting( "color" );
488 if( setting ) {
489 color = (Uint32)(TPLCOL_RGB(setting->getInt(0),
490 setting->getInt(1),
491 setting->getInt(2)));
492 }
493 return color;
494 }
495
496 /**********************************************************/
497
getTeamID() const498 int WopSettings::getTeamID() const
499 {
500 Setting *setting = getSetting( "team" );
501 if( setting ) {
502 ASSERT( setting->getInt() >= 0
503 && setting->getInt() < MAX_NUMBER_OF_PLAYERS,
504 "invalid team number (%i): 0 <= team < %i\n",
505 setting->getInt(), MAX_NUMBER_OF_PLAYERS );
506 return setting->getInt();
507 } else {
508 return m_DefaultTeamID;
509 }
510 }
511
512 /**********************************************************/
513
getKeyboard() const514 const char* WopSettings::getKeyboard() const
515 {
516 const char *keyboard = m_DefaultKeyboard;
517 Setting *setting = getSetting( "keyboard" );
518 if( setting ) keyboard = setting->getString();
519 return (const char*) keyboard;
520 }
521
522 /**********************************************************/
523
getNumBalls() const524 int WopSettings::getNumBalls() const
525 {
526 Setting *setting = getSetting( "nballs" );
527 if( setting ) {
528 ASSERT( setting->getInt() >= 0,
529 "the number of balls must be >= 0, using "
530 "default %d\n",m_DefaultNumBalls );
531 return setting->getInt();
532 } else {
533 return m_DefaultNumBalls;
534 }
535 }
536
537 /**********************************************************/
538
getNumGoals() const539 int WopSettings::getNumGoals() const
540 {
541 Setting *setting = getSetting( "ngoals" );
542 if( setting ) {
543 ASSERT( setting->getInt() >= 0,
544 "the number of goals must be >= 0, using "
545 "default %d\n",m_DefaultNumGoals );
546 return setting->getInt();
547 } else {
548 return m_DefaultNumGoals;
549 }
550 }
551
552 /**********************************************************/
553
getSZProb() const554 real WopSettings::getSZProb() const
555 {
556 Setting *setting = getSetting( "szprob" );
557 if( setting ) {
558 ASSERT( setting->getReal() >= 0.0 && setting->getReal() <= 1.0,
559 "the skwoerm zone probability must be between "
560 "0 and 1, using default %f\n", m_DefaultSZProb );
561 return setting->getReal();
562 } else {
563 return m_DefaultSZProb;
564 }
565 }
566
567 /**********************************************************/
568
getDebug() const569 bool WopSettings::getDebug() const
570 {
571 bool debug = m_DefaultDebug;
572 Setting *setting = getSetting( "debug" );
573 if( setting ) {
574 // debug should be also usable as a simple flag
575 // -> no parameter is interpreted as "true"
576 debug = setting->getNumParameters() > 0
577 ? setting->getBool()
578 : true;
579 }
580 return debug;
581 }
582
583 /**********************************************************/
584
getBots(const Sint32 i) const585 const char* WopSettings::getBots( const Sint32 i ) const
586 {
587 Setting *setting = getSetting( "bots" );
588 return (setting && i >= 0 && i < setting->getNumParameters())
589 ? setting->getString( i ) : 0x0;
590 }
591
592 /**********************************************************/
593
getReplayFileName(String & path) const594 bool WopSettings::getReplayFileName( String& path ) const
595 {
596 Setting *setting = getSetting( "replaylog" );
597 if( setting ) {
598 path = setting->getString();
599 return expandPath( path );
600 }
601
602 return false;
603 }
604
605 /**********************************************************/
606
getMinWidth() const607 int WopSettings::getMinWidth() const { return MIN_MAP_WIDTH; }
getMaxWidth() const608 int WopSettings::getMaxWidth() const { return MAX_MAP_WIDTH; }
getMinHeight() const609 int WopSettings::getMinHeight() const { return MIN_MAP_HEIGHT; }
getMaxHeight() const610 int WopSettings::getMaxHeight() const { return MIN_MAP_HEIGHT; }
611
612 /**********************************************************/
613
getMusicDir(String & path) const614 bool WopSettings::getMusicDir( String& path ) const
615 {
616 Setting *setting = getSetting( "musicdir" );
617 if( setting ) {
618 path = setting->getString();
619 return expandPath( path );
620 }
621
622 return false;
623 }
624
625 /**********************************************************/
626
setGameMode(const int mode)627 bool WopSettings::setGameMode( const int mode )
628 {
629 int i = 0;
630 while( m_gamemode_StringMap[i].m_String ) {
631 if( m_gamemode_StringMap[i].m_Value == mode ) {
632 if( !CHECK(setValue(m_basicSettings, "gamemode",
633 &m_gamemode_StringMap[i].m_String),
634 "WopSettings::setGameMode: failed setting "
635 "the game mode to \"%s\"\n",
636 m_gamemode_StringMap[i].m_String) ) {
637 return false;
638 }
639 return true;
640 }
641 }
642 return CHECK( false, "WopSettings::setGameMode: %d is not"
643 "a valid game mode\n", mode );
644 }
645
646 /**********************************************************/
647
setData(const char * const path)648 bool WopSettings::setData( const char* const path )
649 {
650 return
651 CHECK( setValue(m_basicSettings, "data", (char**)&path),
652 "WopSettings::setData: could not set data path "
653 "to %s\n", path );
654 }
655
656 /**********************************************************/
657
setServer(const char * const server)658 bool WopSettings::setServer( const char* const server )
659 {
660 return
661 CHECK( setValue(m_basicSettings, "server", (char**)&server),
662 "WopSettings::setServer: could not set server address "
663 "to \"%s\"", server );
664 }
665
666 /**********************************************************/
667
setWidth(const int width)668 bool WopSettings::setWidth( const int width )
669 {
670 return
671 CHECK( setValue(m_basicSettings, "width", &width),
672 "WopSettings::setTeam: could not set map width to %d",
673 width );
674 }
675
676 /**********************************************************/
677
setHeight(const int height)678 bool WopSettings::setHeight( const int height )
679 {
680 return
681 CHECK( setValue(m_basicSettings, "height", &height),
682 "WopSettings::setTeam: could not set map height to %d",
683 height );
684 }
685
686 /**********************************************************/
687
setName(const char * const name)688 bool WopSettings::setName( const char* const name )
689 {
690 return
691 CHECK( setValue(m_basicSettings, "name", (char**)&name),
692 "WopSettings::setName: could not set player name "
693 "to \"%s\"", name );
694 }
695
696 /**********************************************************/
697
setPlayerColor(const Uint32 color)698 bool WopSettings::setPlayerColor( const Uint32 color )
699 {
700 int rgb[3] = { TPLCOL_RED( color ),
701 TPLCOL_GREEN( color ),
702 TPLCOL_BLUE( color ) };
703 return
704 CHECK( setValue(m_basicSettings, "color", (int*)rgb, -1, 3),
705 "WopSettings::setColor: could not set player color "
706 "to (%d,%d,%d)", rgb[0], rgb[1], rgb[2] );
707 }
708
709 /**********************************************************/
710
setTeamID(const int teamID)711 bool WopSettings::setTeamID( const int teamID )
712 {
713 return
714 CHECK( setValue(m_basicSettings, "team", &teamID),
715 "WopSettings::setTeam: could not set team ID to %d",
716 teamID );
717 }
718
719 /**********************************************************/
720
setKey(const char * name,const char * value)721 bool WopSettings::setKey( const char* name, const char* value ) {
722 return
723 CHECK( setValue(m_basicSettings, name, (char**)&value),
724 "WopSettings::setKey: could not set key %s "
725 "to value \"%s\"", name, value );
726 }
727
728 /**********************************************************/
729
730 #define NUM_KEYBOARD_LAYOUTS 2
731
setKeyboard(const char * const layout)732 bool WopSettings::setKeyboard( const char* const layout )
733 {
734 const char *layouts[NUM_KEYBOARD_LAYOUTS] = {"us", "de"};
735
736 for( int i = 0; i < NUM_KEYBOARD_LAYOUTS; i++ ) {
737 if( !strcmp(layouts[i], layout) ) {
738 return
739 CHECK( setValue(m_basicSettings, "keyboard", (char**)&layout),
740 "WopSettings::setKeyboard: could not set keyboard "
741 "layout to \"%s\"", layout );
742 }
743 }
744 return
745 CHECK( false, "WopSettings::setKeyboard: \"%s\" is not "
746 "a valid keyboard layout", layout );
747 }
748
749 #undef NUM_KEYBOARD_LAYOUTS
750
751 /**********************************************************/
752
setNumBalls(const int nballs)753 bool WopSettings::setNumBalls( const int nballs )
754 {
755 return
756 CHECK( setValue(m_basicSettings, "nballs", &nballs),
757 "WopSettings::setNumBalls: could not set number "
758 "of balls to %d", nballs );
759 }
760
761 /**********************************************************/
762
setNumGoals(const int ngoals)763 bool WopSettings::setNumGoals( const int ngoals )
764 {
765 return
766 CHECK( setValue(m_basicSettings, "nballs", &ngoals),
767 "WopSettings::setNumGoals: could not set number "
768 "of goals to %d", ngoals );
769 }
770
771 /**********************************************************/
772
isAvailableTheme(const String & name) const773 bool WopSettings::isAvailableTheme( const String& name ) const
774 {
775 const char fn[] = "WopSettings::isAvailableTheme:";
776 PointerVector<String> themes;
777
778 ASSERT( getAvailableThemes(themes),
779 "%s could not build list of theme names\n", fn );
780
781 for( int i = 0; i < themes.getSize(); i++ ) {
782 if( *themes[i] == name ) return true;
783 }
784
785 return false;
786 }
787
788 /**********************************************************/
789
790 bool WopSettings::
getAvailableThemes(PointerVector<String> & themes) const791 getAvailableThemes( PointerVector<String>& themes ) const
792 {
793 const char fn[] = "WopSettings::getAvailableThemes:";
794
795 themes.reset();
796
797 String themePath( getData() );
798 themePath += '/';
799 themePath += THEME_CONFIG_PATH;
800 themePath += '/';
801 themePath += THEME_CONFIG;
802
803 FILE* file = fopen( themePath, "rt" );
804 ASSERT( file, "%s could not open theme file \"%s\"\n",
805 themePath.getString() );
806
807 char character = EOF ^ 0x1;
808 const char *const key = SETTING_DB_DIRECTIVE_SECTION_IN;
809 const int keyLength = strlen(key);
810 int lineIndex = 1;
811
812 while( character != EOF ) {
813 // start scanning of line
814 bool section_enter = true;
815 for( int i = 0; i < keyLength; i++ ) {
816 character = fgetc( file );
817 if( EOF == character || character != key[i] ) {
818 section_enter = false;
819 break;
820 }
821 }
822 // We found the complete string "key" at top of the current
823 // line. The position of "file" is the first character after
824 // the directive "key".
825 if( section_enter ) {
826 // search start of theme string
827 // NOTE: Due to the for-loop above we did not yet read
828 // the first character after SETTING_DB_DIRECTIVE_SECTION_IN
829 while( EOF != (character = fgetc(file)) ) {
830 if( ! CHECK(character != '\n',
831 "%s no section identifier in file \"%s\","
832 " line %d\n", fn, themePath.getString(),
833 lineIndex) ) {
834 fclose( file );
835 return false;
836 }
837 if( character != ' ' && character != '\t' ) break;
838 }
839 // build the theme name string
840 String *name = NEW String;
841 while( character != EOF && character != ' ' &&
842 character != '\t' && character != '\n' ) {
843 *name += character;
844 character = fgetc( file );
845 }
846 // add theme name to list
847 themes.append( name );
848 }
849
850 // search the next line start
851 if( character != '\n' ) {
852 while( EOF != (character = fgetc(file))
853 && character != '\n' );
854 }
855
856 lineIndex++;
857 }
858
859 // add the circle theme by hand
860 themes.append( NEW String(RANDOM_CIRCLES_WOP_MAP_THEME) );
861
862 fclose( file );
863
864 return true;
865 }
866
867 /**********************************************************/
868
869 void WopSettings::
printAvailableThemes(ostream & out,const char * const head,const char * const tail) const870 printAvailableThemes( ostream& out,
871 const char *const head,
872 const char *const tail ) const
873 {
874 const char fn[] = "WopSettings::printAvailableThemes:";
875
876 PointerVector<String> themes;
877
878 ASSERT( getAvailableThemes(themes),
879 "%s could not build list of theme names\n", fn );
880
881 for( int i = 0; i < themes.getSize(); i++ ) {
882 if( head ) out << head;
883 out << *themes[i];
884 if( tail ) out << tail;
885 }
886 }
887
888 /**********************************************************/
889
890 void WopSettings::
serializeServerSettings(Uint8 * & bufferPointer)891 serializeServerSettings( Uint8*& bufferPointer )
892 {
893 const Setting* setting = NULL;
894
895 LOG(2) INFO( "WopSettings::serializeServerSettings\n" );
896
897 for( int i = 0; m_serverSettingsIDs[i]; i++ ) {
898 if( NULL != (setting = getSetting(m_serverSettingsIDs[i])) ) {
899 LOG(3) INFO( "\"%s\": -> present\n", m_serverSettingsIDs[i] );
900 // write a 1 to signalize, that a setting follows
901 Serialize<Uint8>::serialize( (Uint8)1, bufferPointer );
902 // serialize the setting
903 setting->serialize( bufferPointer );
904 } else {
905 LOG(3) INFO( "\"%s\": -> absent\n", m_serverSettingsIDs[i] );
906 }
907 }
908 // terminate the serialization with a 0
909 Serialize<Uint8>::serialize( (Uint8)0, bufferPointer );
910 }
911
912 /**********************************************************/
913
914 void WopSettings::
deserializeServerSettings(Uint8 * & bufferPointer)915 deserializeServerSettings( Uint8*& bufferPointer )
916 {
917 const char fn[] = "WopSettings::deserializeServerSettings";
918 Setting* setting = NULL;
919 Uint8 flag = 0;
920
921 LOG(2) INFO( "%s\n", fn );
922
923 Serialize<Uint8>::deserialize( bufferPointer, flag );
924 while( flag ) {
925 // create new setting object, if necessary
926 ASSERT( !setting && NULL != (setting = new Setting(m_verbose)),
927 "%s: could not create new Setting object\n", fn );
928 // deserialize the setting
929 ASSERT( setting->deserialize(bufferPointer, m_basicSettings),
930 "%s: server setting \"%s\" could not be deserialized "
931 "properly\n", fn, setting->getIDString() );
932 // integrate the deserialized setting
933 // Return value "false" means that the local setting
934 // object has not been used and inserted in the list
935 // of settings and can be reused
936 if( integrateSetting(setting, true, NULL) ) {
937 setting = NULL;
938 }
939 Serialize<Uint8>::deserialize( bufferPointer, flag );
940 }
941
942 // if the last auxiliary setting has not been integrated
943 // in the list of settings, delete it
944 delete setting;
945 }
946
947 /**********************************************************/
948
serialize(Uint8 * & bufferPointer) const949 void WopSettings::serialize( Uint8*& bufferPointer ) const
950 {
951 ASSERT( false, "WopSettings::serialize not implemented.\n"
952 " Did you want to call WopSettings::"
953 "serializeServerSettings instead?\n" );
954 }
955
956 /**********************************************************/
957
deserialize(Uint8 * & bufferPointer)958 void WopSettings::deserialize( Uint8*& bufferPointer )
959 {
960 ASSERT( false, "WopSettings::deserialize not implemented.\n"
961 " Did you want to call WopSettings::"
962 "deserializeServerSettings instead?\n" );
963 }
964
965 /**********************************************************/
966
getSerializeBufferSize() const967 Uint32 WopSettings::getSerializeBufferSize() const
968 {
969 Uint32 size = sizeof(Uint8);
970 const Setting* setting = NULL;
971
972 for( int i = 0; m_serverSettingsIDs[i]; i++ ) {
973 if( NULL != (setting = getSetting(m_serverSettingsIDs[i])) ) {
974 size += setting->getSerializeBufferSize();
975 size += sizeof(Uint8);
976 }
977 }
978
979 return size;
980 }
981
982 /**********************************************************/
983
enforcePresenceOfServerSettings()984 bool WopSettings::enforcePresenceOfServerSettings()
985 {
986 bool result = true;
987
988 if( !getSetting("gamemode") ) {
989 result = result && setGameMode( getGameMode() ); }
990 if( !getSetting("width") ) {
991 result = result && setWidth( getWidth() ); }
992 if( !getSetting("height") ) {
993 result = result && setHeight( getHeight() ); }
994 if( !getSetting("nballs") ) {
995 result = result && setNumBalls( getNumBalls() ); }
996 if( !getSetting("ngoals") ) {
997 result = result && setNumGoals( getNumGoals() ); }
998
999 return result;
1000 }
1001
1002 /**********************************************************
1003 * read settings form command line AND configuration file
1004 **********************************************************/
1005
readSettings(const char ** const CommandLine,const int nargs)1006 bool WopSettings::readSettings( const char** const CommandLine,
1007 const int nargs )
1008 {
1009 const char fn[] = "WopSettings::readSettings";
1010 bool pickySuccess = true;
1011
1012 // read command line (SettingDataBase::readSettings)
1013 LOG(1) INFO( "%s: reading command line options\n", fn );
1014 // read settings from command line
1015 if( false == SettingDataBase::readSettings(
1016 m_basicSettings, // class internal setting definitions
1017 CommandLine, nargs, // command line and # argumentes
1018 true, // overwrite == true
1019 false, // expectDashesInCommandLine == false
1020 &pickySuccess) || // get more details about the success
1021 // stop also, if there happened only small errors
1022 false == pickySuccess )
1023 {
1024 return false;
1025 }
1026
1027 String configfile;
1028 int rank = 0;
1029 // read the configuration files in the ranking order
1030 while( getConfigFilePath(configfile, rank) ) {
1031 LOG(1) INFO( "%s: checking presence of \"%s\"\n",
1032 fn, configfile.getString() );
1033 // check, whether the configuration file is available
1034 FILE* configFile = fopen( (char*)configfile, "r" );
1035 if( configFile == NULL ) {
1036 // If the file, that was specified in the command
1037 // line cannot be opened, abort.
1038 if( !CHECK( rank > 0, "%s: cannot open \"%s\"\n",
1039 fn, configfile.getString() ) ) return false;
1040 // otherwise only print out a warning
1041 LOG(1) INFO( "%s: \"%s\" not available\n",
1042 fn, configfile.getString() );
1043 continue;
1044 }
1045 fclose( configFile );
1046 // now we are sure that we can open the configuration file
1047 LOG(1) INFO( "%s: reading options in \"%s\"\n",
1048 fn, configfile.getString() );
1049 // read configuration file, DO NOT overwrite settings, since
1050 // the command line has got a higher priority ( 3rd param == false)
1051 if( ! SettingDataBase::
1052 readSettings(m_basicSettings, configfile,
1053 false, &pickySuccess) ||
1054 // stop also, if there happened only small errors
1055 ! pickySuccess )
1056 {
1057 return false;
1058 }
1059 }
1060
1061 // check, if every mandatory setting is present
1062 if( false == finalCheck(m_basicSettings) ) return false;
1063
1064 // check if data directory is present by opening the theme path
1065 String themesConfPath( getData() );
1066 themesConfPath += '/';
1067 themesConfPath += THEME_CONFIG_PATH;
1068 themesConfPath += '/';
1069 themesConfPath += THEME_CONFIG;
1070 FILE* themesConfFile = fopen( themesConfPath, "r" );
1071 ASSERT ( themesConfFile,
1072 "Could not open data directory (%s).\n"
1073 "Make sure that you:\n"
1074 " - downloaded the data package\n"
1075 " - set the \"data\" option in the command line "
1076 "or the configuration file\n", getData() );
1077 fclose( themesConfFile );
1078
1079 // remove pure server settings from a client
1080 // if( getMode() == CLIENT ) {
1081 // for( int i = 0; m_serverSettingsIDs[i]; i++ ) {
1082 // Setting *setting = getSetting( m_serverSettingsIDs[i] );
1083 // if( setting ) {
1084 // LOG(1) INFO( "%s: setting \"%s\" ignored on client\n",
1085 // fn, m_serverSettingsIDs[i] );
1086 // delSetting( m_serverSettingsIDs[i] );
1087 // }
1088 // }
1089 // }
1090
1091 // check the validity of the theme right here
1092 // In fact it is checked later per default in World::createFromTheme,
1093 // but after a lot of output. To check it right at the program start
1094 // after reading the settings is more user friendly.
1095 if( getTheme() ) {
1096 if( ! CHECK(isAvailableTheme(getTheme()),
1097 "%s \"%s\" is not a valid theme name.\n"
1098 " =======================\n"
1099 " Available Themes:\n",
1100 fn, getTheme()) ) {
1101 // if theme name is not valid, print list of available themes
1102 printAvailableThemes( std::cerr,
1103 " \033[0;1m- ",
1104 "\033[0m\n" );
1105 std::cout <<" ======================="<<std::endl;
1106 return false;
1107 }
1108 }
1109
1110 return pickySuccess;
1111 }
1112
1113 /**********************************************************/
1114
getConfigFilePath(String & path,int & rank)1115 bool WopSettings::getConfigFilePath( String& path, int &rank )
1116 {
1117 DBG(1) {
1118 int maxrank = 0;
1119 while( m_configPaths[maxrank++] );
1120 ASSERT( 0 <= rank && rank <= maxrank,
1121 "WopSettings::getConfigFilePath: parameter rank is "
1122 "out of valid range [0,%d]. This is a code bug.\n",
1123 maxrank );
1124 }
1125
1126 // rank 0 means "check the command line"
1127 if( rank == 0 ) {
1128 Setting *setting = getSetting( "config" );
1129 // if the command line contains a path to the config file
1130 if( setting ) {
1131 // take this path and expand it
1132 path = setting->getString();
1133 rank++;
1134 return expandPath( path );
1135 // otherwise get the first path in the hierarchy
1136 } else {
1137 return getConfigFilePath( path, ++rank );
1138 }
1139 // otherwise take the next path in the hierarchy
1140 } else {
1141 if( m_configPaths[rank-1] == NULL ) return false;
1142 path = m_configPaths[(rank++)-1];
1143 }
1144
1145 return expandPath( path );
1146 }
1147
1148 /**********************************************************/
1149
expandPath(String & path) const1150 bool WopSettings::expandPath( String& path ) const
1151 {
1152 const char fn[] = "WopSettings::expandPath:";
1153
1154 // check, if there is something to expand: a path must
1155 // contain at least '~' and a following character to be
1156 // sensibly expanded
1157 if( path.getLength() < 2 || path[0] != '~' ) return true;
1158
1159 #ifdef NO_HOME_PATH_EXPANSION
1160
1161 return CHECK( false,
1162 "%s path expansion is disabled. Cannot expand "
1163 "path \"%s\"\n", fn, path.getString() );
1164
1165 #else
1166
1167 // '~/' means "home of current user
1168 String expansion;
1169 int iNull = 1;
1170 if( path[1] == '/' ) {
1171 expansion = getenv( "HOME" );
1172 if( !CHECK( expansion.getLength(),
1173 "%s could not get content of environment "
1174 "variable \"HOME\"", fn ) ) {
1175 return false;
1176 }
1177 // '~' is not followed by a '/', so we need the full path
1178 // of a different user's home directory
1179 } else {
1180 // temporarily crop the user's name
1181 while( path[iNull] != '/' && path[iNull] != 0 ) iNull++;
1182 // remember, whether you have cropped the string
1183 const bool cropped = (path[iNull] == '/');
1184 path[iNull] = 0;
1185 // get the user's full home path from /etc/pwd
1186 struct passwd *pwdentry = getpwnam( path.getString()+1 );
1187 if( !CHECK( pwdentry != NULL,
1188 "%s could not read passwd entry of user \"%s\"",
1189 fn, path.getString()+1 ) ) {
1190 // restore path
1191 if( cropped ) path[iNull] = '/';
1192 return false;
1193 }
1194 expansion = pwdentry->pw_dir;
1195 if( !CHECK( expansion.getLength(),
1196 "%s could not expand home path of user \"%s\"",
1197 fn, path.getString()+1 ) ) {
1198 // restore path
1199 if( cropped ) path[iNull] = '/';
1200 return false;
1201 }
1202 if( cropped ) path[iNull] = '/';
1203 }
1204
1205 // concatenate expansion and string
1206 String extention( path.getString() + iNull );
1207 path = expansion;
1208 path += extention;
1209
1210 #endif
1211
1212 return true;
1213 }
1214
1215 /**********************************************************/
1216
writeConfigFile(String & path)1217 bool WopSettings::writeConfigFile( String& path )
1218 {
1219 const char fn[] = "WopSettings::writeConfigFile";
1220
1221 // get default path, if "path" is empty
1222 if( !path.getLength() ) {
1223 // if config file is given write to that location else try to
1224 // write in the current directory
1225 if ( !WopSettings::getInstance()->getSetting( "config" ) ) {
1226 int rank = 0;
1227 WopSettings::getInstance()->getConfigFilePath( path, rank );
1228 }
1229 else {
1230 path = getenv( "HOME" );
1231 if( path.getLength() ) {
1232 path += '/';
1233 path += m_DefaultConfig;
1234 }
1235 else
1236 path = "woprc.txt";
1237 }
1238 }
1239
1240 INFO( "WopSettings::writeConfigFile: writing configuration "
1241 "file to %s\n",
1242 path.getLength() ? path.getString() : "woprc.txt" );
1243
1244 // open file
1245 FILE *file = fopen( path, "wt" );
1246 if( file == NULL ) {
1247 cerr << FUNCTION_ERROR(fn)
1248 << "cannot open \"" << path << "\"\n";
1249 return false;
1250 }
1251
1252 // write file
1253 fprintf( file,
1254 "## This is a skeleton file for the configuration of\n"
1255 "## \"Woerms of Prey\", www.wormsofprey.org\n"
1256 "##\n"
1257 "## - All settings, used here, can also be specified\n"
1258 "## using the command line. For example\n"
1259 "## \"wop mode=client view=window\" (no spaces between\n"
1260 "## the setting's name and its values)\n"
1261 "## Command line settings OVERWRITE settings read from\n"
1262 "## configuration files.\n"
1263 "## - For a quick overview of the possible settings\n"
1264 "## invoke \"wop -help\"\n"
1265 "## - On UNIX based systems the shortcuts using \"~\"\n"
1266 "## are expanded correctly.\n"
1267 "## - If you want to use the default value of a setting,\n"
1268 "## you can leave it undefined. The default is taken\n"
1269 "## automatically.\n"
1270 "## - On the command line you can specify the path of\n"
1271 "## this configuration file using the setting \"config\"\n"
1272 "\n" );
1273 fprintf( file,
1274 "## program mode [server,client,replay]\n"
1275 "## - required\n"
1276 "mode = client\n"
1277 "\n" );
1278 fprintf( file,
1279 "## game mode [deathmatch,teamplay]\n"
1280 "## - optional, default \"deathmatch\"\n"
1281 "## - has effect on \"server\" only\n"
1282 "gamemode = %s\n"
1283 "\n",
1284 m_gamemode_StringMap[getGameMode()].m_String );
1285 fprintf( file,
1286 "## path of the data directory\n"
1287 "## - optional, default \"./data\"\n"
1288 "data = %s\n"
1289 "\n",
1290 getData() );
1291 fprintf( file,
1292 "## server name or IP address\n"
1293 "## - optional, default \"localhost\"\n"
1294 "## - can also be chosen in the menu\n"
1295 "# server = localhost\n"
1296 "\n" );
1297 fprintf( file,
1298 "## width of the world map\n"
1299 "## - optional, default 1000\n"
1300 "## - has effect on \"server\" only\n"
1301 "## - a selected theme may overwrite \"width\"\n"
1302 "width = %d\n"
1303 "\n",
1304 getWidth() );
1305 fprintf( file,
1306 "## height of the world map\n"
1307 "## - optional, default 1000\n"
1308 "## - has effect on server only\n"
1309 "## - a selected theme may overwrite \"height\"\n"
1310 "height = %d\n"
1311 "\n",
1312 getHeight() );
1313 fprintf( file,
1314 "## theme of the world's map\n"
1315 "## [standard, medium, sparse1, fossil, circle,\n"
1316 "## randomcircles]\n"
1317 "## - optional, default \"standard\"\n"
1318 "## - has effect on \"server\" only\n"
1319 "## - for a list of available themes have a look\n"
1320 "## in the configuration file\n"
1321 "## <data directory>/images/themes.conf\n"
1322 "## [standard, medium,\n"
1323 "## sparse1, fossil,\n"
1324 "## circle, sky, randomcircles]\n"
1325 "theme = %s\n"
1326 "\n",
1327 getTheme() );
1328 fprintf( file,
1329 "## view mode [window,fullscreen]\n"
1330 "## - optional, default \"window\"\n"
1331 "## - has effect on \"client\" and \"replay\" only\n"
1332 "view = %s\n"
1333 "\n",
1334 m_view_StringMap[getView()].m_String );
1335 fprintf( file,
1336 "## quiet [yes,no]\n"
1337 "## - default on \"client\" is \"no\"\n"
1338 "## - default on \"server\" is \"yes\"\n"
1339 "## - switches off/on sound\n"
1340 "quiet = %s\n"
1341 "\n",
1342 getQuiet() ? "yes" : "no" );
1343 fprintf( file,
1344 "## player name\n"
1345 "## - has effect on \"client\" only\n"
1346 "## - default \"The Dude\"\n"
1347 "## - can also be specified in option menu\n"
1348 "name = \"%s\"\n"
1349 "\n",
1350 getName() );
1351 fprintf( file,
1352 "## avatar color\n"
1353 "## - default \"255,255,255\"\n"
1354 "## - has effect on \"client\" only\n"
1355 "## - specifies the RED,GREEN,BLUE contributions\n"
1356 "## to the player's color (three comma separated\n"
1357 "## values from 0 to 255\n"
1358 "## - can also be specified in option menu\n"
1359 "color = %d,%d,%d\n"
1360 "\n",
1361 TPLCOL_RED( getPlayerColor() ),
1362 TPLCOL_GREEN( getPlayerColor() ),
1363 TPLCOL_BLUE( getPlayerColor() ) );
1364 fprintf( file,
1365 "## the team number [0,...,20]\n"
1366 "## - default 0\n"
1367 "## - has effect on \"client\" only, and only, if the\n"
1368 "## gamemode is \"teamplay\"\n"
1369 "## - can also be specified in option menu\n"
1370 "team = %d\n"
1371 "\n",
1372 getTeamID() );
1373 fprintf( file,
1374 "## keyboard layout [us,de]\n"
1375 "## - default \"us\"\n"
1376 "## - this setting generally affects, whether the rope\n"
1377 "## is triggered by \"z\" (us) or by \"y\" (de)\n"
1378 "keyboard = %s\n"
1379 "\n",
1380 getKeyboard() );
1381 fprintf( file,
1382 "## number of balls in the game\n"
1383 "## - default 2\n"
1384 "## - has effect on \"server\" only\n"
1385 "nballs = %d\n"
1386 "\n",
1387 getNumBalls() );
1388 fprintf( file,
1389 "## number of goals in the game\n"
1390 "## - default 2\n"
1391 "## - has effect on \"server\" only\n"
1392 "ngoals = %d\n"
1393 "\n",
1394 getNumGoals() );
1395 fprintf( file,
1396 "## probability for creating skwoerm zones [0.0,1.0]\n"
1397 "## - default 0.01\n"
1398 "## - has effect on \"server\" only\n"
1399 "szprob = %f\n"
1400 "\n",
1401 getSZProb() );
1402 fprintf( file,
1403 "## debug [yes,no]\n"
1404 "## - default: no\n"
1405 "## - warning: enabling turns off the SDL parachute!\n"
1406 "debug = %s\n"
1407 "\n",
1408 getDebug() ? "yes" : "no" );
1409 fprintf( file,
1410 "## juke box directory\n"
1411 "## - no default\n"
1412 "## - this setting specifies a directory where WoP\n"
1413 "## will search files of type \".wav\", \".ogg\", \".mp3\", \".mid\", \".mod\".\n"
1414 "## These files are played in random order as\n"
1415 "## background tunes during the game.\n"
1416 "## - CONTROL in the game:\n"
1417 "## F5 : volume -\n"
1418 "## F6 : volume +\n"
1419 "## F7 : toggle music on/off\n"
1420 "# musicdir = \"~/mymusic/woptracks/smooth tracks\"\n"
1421 "## on the command line you would have to write\n"
1422 "## musicdir=\"~/mymusic/woptracks/smooth\\ tracks\"\n" );
1423 String musicDir;
1424 if ( getMusicDir( musicDir ) )
1425 fprintf( file, "musicdir = %s\n", musicDir.getString() );
1426 fprintf( file,
1427 "\n"
1428 "## key configuration\n"
1429 "## - can also be changed in option menu\n"
1430 "key_left = \"%s\"\n"
1431 "key_right = \"%s\"\n"
1432 "key_up = \"%s\"\n"
1433 "key_down = \"%s\"\n"
1434 "key_shoot = \"%s\"\n"
1435 "key_jump = \"%s\"\n"
1436 "key_dig = \"%s\"\n"
1437 "key_jet = \"%s\"\n"
1438 "key_rope_on = \"%s\"\n"
1439 "key_rope_off = \"%s\"\n"
1440 "key_rope_in = \"%s\"\n"
1441 "key_rope_out = \"%s\"\n"
1442 "key_rope_rel = \"%s\"\n"
1443 "key_screenshot = \"%s\"\n"
1444 "key_debug = \"%s\"\n"
1445 "key_dec_vol = \"%s\"\n"
1446 "key_inc_vol = \"%s\"\n"
1447 "key_toggle_jukebox = \"%s\"\n"
1448 "key_weapon_1 = \"%s\"\n"
1449 "key_weapon_2 = \"%s\"\n"
1450 "key_weapon_3 = \"%s\"\n"
1451 "key_weapon_4 = \"%s\"\n"
1452 "key_weapon_5 = \"%s\"\n"
1453 "key_weapon_6 = \"%s\"\n"
1454 "key_weapon_7 = \"%s\"\n"
1455 "key_weapon_8 = \"%s\"\n"
1456 "key_weapon_9 = \"%s\"\n"
1457 "key_weapon_0 = \"%s\"\n"
1458 "key_spawn = \"%s\"\n"
1459 "key_next_weapon = \"%s\"\n"
1460 "key_prev_weapon = \"%s\"\n"
1461 "key_insert_replay_bookmark = \"%s\"\n"
1462 "key_change_focus = \"%s\"\n"
1463 "key_toggle_fullscreen = \"%s\"\n"
1464 "key_show_fps = \"%s\"\n"
1465 "key_limit_fps = \"%s\"\n",
1466 getSetting( "key_left" )->getString(),
1467 getSetting( "key_right" )->getString(),
1468 getSetting( "key_up" )->getString(),
1469 getSetting( "key_down" )->getString(),
1470 getSetting( "key_shoot" )->getString(),
1471 getSetting( "key_jump" )->getString(),
1472 getSetting( "key_dig" )->getString(),
1473 getSetting( "key_jet" )->getString(),
1474 getSetting( "key_rope_on" )->getString(),
1475 getSetting( "key_rope_off" )->getString(),
1476 getSetting( "key_rope_in" )->getString(),
1477 getSetting( "key_rope_out" )->getString(),
1478 getSetting( "key_rope_rel" )->getString(),
1479 getSetting( "key_screenshot" )->getString(),
1480 getSetting( "key_debug" )->getString(),
1481 getSetting( "key_dec_vol" )->getString(),
1482 getSetting( "key_inc_vol" )->getString(),
1483 getSetting( "key_toggle_jukebox" )->getString(),
1484 getSetting( "key_weapon_1" )->getString(),
1485 getSetting( "key_weapon_2" )->getString(),
1486 getSetting( "key_weapon_3" )->getString(),
1487 getSetting( "key_weapon_4" )->getString(),
1488 getSetting( "key_weapon_5" )->getString(),
1489 getSetting( "key_weapon_6" )->getString(),
1490 getSetting( "key_weapon_7" )->getString(),
1491 getSetting( "key_weapon_8" )->getString(),
1492 getSetting( "key_weapon_9" )->getString(),
1493 getSetting( "key_weapon_0" )->getString(),
1494 getSetting( "key_spawn" )->getString(),
1495 getSetting( "key_next_weapon" )->getString(),
1496 getSetting( "key_prev_weapon" )->getString(),
1497 getSetting( "key_insert_replay_bookmark" )->getString(),
1498 getSetting( "key_change_focus" )->getString(),
1499 getSetting( "key_toggle_fullscreen" )->getString(),
1500 getSetting( "key_show_fps" )->getString(),
1501 getSetting( "key_limit_fps" )->getString() );
1502
1503 fclose( file );
1504
1505 return true;
1506 }
1507
1508 /**********************************************************/
1509
printHelp(const int lowerHelpLevel,const int upperHelpLevel) const1510 void WopSettings::printHelp( const int lowerHelpLevel,
1511 const int upperHelpLevel ) const
1512 {
1513 SettingDataBase::printHelp( m_basicSettings,
1514 lowerHelpLevel,
1515 upperHelpLevel );
1516 }
1517
1518 /**********************************************************/
1519