File: zen.cpp

package info (click to toggle)
opencity 0.0.6.4stable-4
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 12,624 kB
  • ctags: 3,534
  • sloc: cpp: 26,121; xml: 4,453; sh: 3,743; ansic: 585; makefile: 472
file content (744 lines) | stat: -rw-r--r-- 20,592 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
/***************************************************************************
						zen.cpp  -  description
							-------------------
	project              : OpenCity
	codename             : ZeN server
	begin                : november 26th, 2006
	copyright            : (C) 2006-2008 by Duong Khang NGUYEN
	email                : neoneurone @ gmail com

	$Id: zen.cpp 375 2008-10-28 14:47:15Z neoneurone $
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   any later version.                                                    *
 *                                                                         *
 ***************************************************************************/

// Useful enumerations
#include "opencity_direction.h"
#include "opencity_structure_type.h"

// OpenCity headers
#include "zen.h"
#include "city.h"				// The heart of the project
#include "conf.h"				// Parser for .conf file
#include "agentpolice.h"		// MAS testing
#include "agentdemonstrator.h"

// Global settings
#include "globalvar.h"
extern GlobalVar gVars;

// Libraries headers
#include "SDL_image.h"
#include "binreloc.h"			// BinReloc routines from AutoPackage
#include "tinyxml.h"
#include "SimpleOpt.h"			// Simple command line argument parser

// Standard headers
#include <cmath>				// For log10
#include <cstdlib>				// For getenv
#include <ctime>				// For time


   /*=====================================================================*/
   /*                           LOCAL     MACROS                          */
   /*=====================================================================*/
#ifndef __WIN32__
	#include <sys/stat.h>		// mkdir
#else
// Win32 specifics
	#include <shlobj.h>			// Windows shell technologies
	#define DATADIR "C:/Program Files"
	#define SYSCONFDIR DATADIR
#endif

// Window's settings
	#define OC_WINDOW_POS_X			20
	#define OC_WINDOW_POS_Y			20
	#define OC_WINDOW_WIDTH			750
	#define OC_WINDOW_HEIGHT		560
	#define OC_WINDOW_BPP_DEFAULT	32				// OC uses this by default
	#define OC_WINDOW_BPP_16		16
	#define OC_FULLSCREEN_WIDTH		1024
	#define OC_FULLSCREEN_HEIGHT	768

// Exit code
	#define OC_CONFIG_NOT_FOUND		-1
	#define OC_CONFIG_PARSE_ERROR	-2

// Settings file
	#define OC_CONFIG_FILE_FILENAME	"config/opencity.xml"

// Others macros
	#define OC_WINDOW_NAME PACKAGE VERSION
	#define OC_PROGRAM_NAME			"OpenCity ZeN server application"



   /*=====================================================================*/
   /*                         LOCAL    VARIABLES                          */
   /*=====================================================================*/
/// The current user interface is pointed by this pointer
	static UI* uipCurrentUI		= NULL;

/// Set to true when the user request to quit the program
	static bool boolQuit		= false;
	static bool bRestart		= false;

/// Static so that the others can not access this
	static string sDataDir		= "";
	static string sSaveDir		= "";
	static string sConfigDir	= "";


   /*=====================================================================*/
void ocActive( const SDL_ActiveEvent & e)
{
	OPENCITY_DEBUG( "Active event received" );

	if (e.state & SDL_APPACTIVE) {
		gVars.gboolActive = (e.gain == 1);
	}
}


   /*=====================================================================*/
void ocQuit( const int quit_code )
{
	cout << "Quit requested, quit code is : " << quit_code
	     << endl
	     << "Bye bye !"
	     << endl;
	boolQuit = true;
}


   /*=====================================================================*/
void ocRestart()
{
	cout << "Restart with a new city from scratch. " << endl;
	bRestart = true;
}


   /*=====================================================================*/
void ocProcessSDLEvents( void )
{
	static SDL_Event event;

// Grab all the events off the queue.
	while( SDL_PollEvent( &event ) ) {

		switch( event.type ) {
		case SDL_ACTIVEEVENT:
			ocActive( event.active );
			break;

		case SDL_QUIT:
		// Handle quit requests (like Ctrl-c).
			cout << "Quit requested, stoping " << OC_PROGRAM_NAME << "..." << endl;
			boolQuit = true;
			break;
		}
	}
}


   /*=====================================================================*/
void ocSetNewUI( UI * pcNewUI)
{
	uipCurrentUI = pcNewUI;
}


   /*=====================================================================*/
string
formatPath(const string& rcsPath)
{
	string result = rcsPath;

	if (result.size() > 0) {
	// Delete all quotes "
		string::size_type pos;
		while ( (pos = result.find( '\"' )) != result.npos ) {
		    result.erase( pos );
		}
	// Append the "/" to path
		if (result[ result.size()-1 ] != '/')
			result += '/';
	}
	else {
		result = "/";
	}

	return result;
}


   /*=====================================================================*/
void parseArg(int argc, char *argv[])
{
	enum {
		OPT_DATADIR,
		OPT_CONFDIR,
		OPT_HELP
	};

	CSimpleOpt::SOption g_rgOptions[] = {
		{ OPT_DATADIR,	(char*)"--datadir",		SO_REQ_SEP	},
		{ OPT_DATADIR,	(char*)"-dd",			SO_REQ_SEP	},
		{ OPT_CONFDIR,	(char*)"--confdir",		SO_REQ_SEP	},
		{ OPT_CONFDIR,	(char*)"-cd",			SO_REQ_SEP	},
		{ OPT_HELP,		(char*)"--help",		SO_NONE		},
		{ OPT_HELP,		(char*)"-h",			SO_NONE		},
		SO_END_OF_OPTIONS // END
	};

	CSimpleOpt args(argc, argv, g_rgOptions, SO_O_EXACT | SO_O_NOSLASH | SO_O_SHORTARG | SO_O_CLUMP );
	while (args.Next()) {
		switch (args.LastError()) {
		case SO_OPT_INVALID:
			cout << "<OPTION> " << args.OptionText() << " unrecognized" << endl;
			break;
		case SO_OPT_MULTIPLE:
			cout << "<OPTION> " << args.OptionText() << " matched multiple options" << endl;
			break;
		case SO_ARG_INVALID:
			cout << "<OPTION> " << args.OptionText() << " does not accept any argument" << endl;
			break;
		case SO_ARG_INVALID_TYPE:
			cout << "<OPTION> " << args.OptionText() << " has an invalid argument format" << endl;
			break;
		case SO_ARG_MISSING:
			cout << "<OPTION> " << args.OptionText() << " requires an argument" << endl;
			break;
		case SO_ARG_INVALID_DATA:
			cout << "<OPTION> " << args.OptionText() << " has an invalid argument data" << endl;
			break;
		case SO_SUCCESS:
			cout << "<OPTION> " << args.OptionText() << " detected" << endl;
			break;
		}

		// Exit the program on error
		if (args.LastError() != SO_SUCCESS) {
			cout << "Try " << argv[0] << " --help for usage information" << endl;
			exit( -1 );
		}

		switch (args.OptionId()) {
		case OPT_DATADIR:
			sDataDir = formatPath(args.OptionArg());
			cout << "<OPTION> DataDir is: \"" << sDataDir << "\"" << endl;
			break;

		case OPT_CONFDIR:
			sConfigDir = formatPath(args.OptionArg());
			cout << "<OPTION> ConfDir is: \"" << sConfigDir << "\"" << endl;
			break;

		case OPT_HELP:
			cout << "Usage: " << argv[0]
				 << " [-dd|--datadir newDataPath] [-cd|--confdir newConfigPath]" << endl << endl;
			cout << "Warning: the command option overwrite the config file settings."
				 << endl;
			exit( -2 );
			break;
		} // switch
	} // while
}


   /*=====================================================================*/
void displayStatus( const string & str )
{
	cout << str << endl;
}


   /*=====================================================================*/
int serverMode()
{
// Initialize the video system in order to capture Ctrl-C !
	SDL_Init(SDL_INIT_VIDEO);

// Create the mutex first
	gVars.gpmutexSim = SDL_CreateMutex();

// Create the global renderer in order to use its text rendering functions
//	gVars.gpRenderer = new Renderer( gVars.guiCityWidth, gVars.guiCityLength );

// AudioManager's initialization
//	displayStatus( "Looking for GPU freezing system... ");
//	gVars.gpAudioMgr = new AudioManager();

// Create the other required global managers
	displayStatus( "Initializing the vibration detector..." );
	gVars.gpMapMaker = new MapGen::MapMaker(
		gVars.guiCityWidth, gVars.guiCityLength,
		gVars.gsGeneratorHeightMap,
		gVars.guiGeneratorMapType,
		gVars.guiGeneratorWaterType,
		gVars.guiGeneratorMapShapeType,
		gVars.guiGeneratorTreeDensityType,
		gVars.guiGeneratorSeed
	);

	displayStatus( "Activating embedded GPS...");
	gVars.gpMapMgr = new Map( gVars.guiCityWidth, gVars.guiCityLength );

//	displayStatus( "Calibrating earthquake subsystem...");
//	gVars.gpGraphicMgr = new GraphicManager();

	displayStatus( "Shaking DNA mixer thread...");
	gVars.gpPropertyMgr = new PropertyManager();

	displayStatus( "Mounting intergalactic hyperlink ...");
	gVars.gpNetworking = new Networking();

	displayStatus( "Initializing the particle handler ...");
	gVars.gpMoveMgr = new MovementManager( gVars.gpGraphicMgr, gVars.gpMapMgr );


// Create a new city map
	City* pNewCity = new City( gVars.guiCityWidth, gVars.guiCityLength, false );
	if (pNewCity == NULL) {
		OPENCITY_FATAL( "Error while creating new city" );
		return (-15);
	}

// Start the server
	boolQuit = (gVars.gpNetworking->StartServer() == OC_NET_OK) ? false : true;
	if (!boolQuit)
		displayStatus( "Online world conquero activated");
	else
		displayStatus( "Online world conquero activation has failed" );

// The main loop
	while (!boolQuit) {
	// Run the city at the LAST_SPEED (default parameter)
		cout << ".";
		(void)gVars.gpNetworking->ProcessServerData();
		ocProcessSDLEvents();
		pNewCity->Run();

		cout.flush();
		SDL_Delay( gVars.guiMsPerFrame );
	}

// Stop the zen server and close the network connection
	(void)gVars.gpNetworking->StopServer();
	gVars.gpNetworking->Close();

// WARNING: the deleting/creating order is very important !
	delete pNewCity;

	delete gVars.gpMoveMgr;
	delete gVars.gpNetworking;
	delete gVars.gpPropertyMgr;
//	delete gVars.gpGraphicMgr;
	delete gVars.gpMapMgr;

// Close the audio device then delete the audio manager
//	gVars.gpAudioMgr->CloseAudio();
//	delete gVars.gpAudioMgr;

//	delete gVars.gpRenderer;

// Delete the simulators' mutex now
	SDL_DestroyMutex( gVars.gpmutexSim );

	gVars.gpVideoSrf = NULL;
	SDL_Quit();					// WARNING: Calls free() on an invalid pointer. Detected by glibc
	return 0;
}


   /*=====================================================================*/
void printCopyright() {
// Output the copyright text
	cout << "Welcome to " << PACKAGE << " version " << VERSION << endl;
	cout << "Copyright (C) by Duong Khang NGUYEN. All rights reserved." << endl;
	cout << "   web  : http://www.opencity.info" << endl;
	cout << "   email: neoneurone @ gmail com" << endl << endl;

	cout << "This program is released under the terms of" << endl;
	cout << "GNU General Public License (See the COPYING file for more details)" << endl << endl;

	cout << "Starting " << OC_PROGRAM_NAME << "..." << endl << endl;
}


   /*=====================================================================*/
/** Return the save directory.
	\return The pointer to the absolute directory. The caller must free
the pointer if it's not used anymore.
*/
char* findSaveDir()
{
	char* ret = NULL;

#ifndef __WIN32__
// Get the home directory from the environment variable
	char* env = getenv("HOME");
	if (env != NULL) {
		ret = (char*)malloc( strlen(env) + 1 );
		strcpy( ret, env );
	}
#else
// Find the directory: "C:\Documents and Settings\username\Application Data"
// Required shell DLL version: 5.0 or later
// header: shlobj.h
// lib: shell32.lib ?
// dll: shell32.dll

	TCHAR szPath[MAX_PATH];
	
	if(SUCCEEDED(
		SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath)
		)) {
		ret = (char*)malloc( strlen(szPath) + 1 );
		strcpy( ret, szPath );
	}
#endif

// The required save directory does not exist, use the current directory
	if (ret == NULL) {
		ret = (char*)malloc( 2 );
		strcpy( ret, "." );
	}

	return ret;
}


   /*=====================================================================*/
/** Try to detect and set the datadir, the confdir and the savedir using
BinReloc library and win32 standard function
*/
void detectProgramPath()
{
	char* pTemp = NULL;
	BrInitError brError;

// IF the datadir is not set THEN try to get it from BinReloc routines
	if (sDataDir == "") {
	// Default system directory settings
		sDataDir = DATADIR;

	// Init the BinReloc routines
		if (br_init(&brError) != 1) {
			OPENCITY_INFO(
				"Failed to initialized BinReloc routines to search for the datadir. " <<
				"The error was: " << brError
			);
		}

	// Construct the datadir from the prefix
		pTemp = br_find_data_dir( sDataDir.c_str() );
		sDataDir = pTemp;
		sDataDir += "/";
		sDataDir += PACKAGE;
		sDataDir = formatPath( sDataDir );
		free(pTemp);
	}

// IF the configdir is not set THEN try to get it from BinReloc routines
	if (sConfigDir == "") {
	// Default system directory settings
		sConfigDir = SYSCONFDIR;

	// Init the BinReloc routines
		if (br_init(&brError) != 1) {
			OPENCITY_INFO(
				"Failed to initialized BinReloc routines to search for the confdir. " <<
				"The error was: " << brError
			);
		}

	// Construct the pkgsysconfdir from the prefix
		pTemp = br_find_etc_dir( sConfigDir.c_str() );
		sConfigDir = pTemp;
		sConfigDir += "/";
		sConfigDir += PACKAGE;
		sConfigDir = formatPath( sConfigDir );
		free(pTemp);
	}

// IF the save directory is not set the find it
	if (sSaveDir == "") {
		pTemp = findSaveDir();
		sSaveDir = pTemp;
		free(pTemp);
#ifndef __WIN32__
		sSaveDir += "/.opencity/";
		mkdir( sSaveDir.c_str(), 0755 );
#else
	// Win32 uses \ as directory separtor
		sSaveDir += "\\opencity\\";
        CreateDirectory( sSaveDir.c_str(), NULL );		
    // Replace \ by /
	    string::size_type pos;
	    while ( (pos = sSaveDir.find( '\\' )) != sSaveDir.npos ) {
		    sSaveDir.replace( pos, 1, "/" );
		}
#endif
	}

// Print out some information
	OPENCITY_INFO( "Detected data directory   : " << sDataDir );
	OPENCITY_INFO( "Detected config directory : " << sConfigDir );
	OPENCITY_INFO( "Detected save directory   : " << sSaveDir );
}


   /*=====================================================================*/
/** Read the OpenCity's main settings file "opencity.xml"
	\return "" if OK, otherwise the error description
		0: if OK
		OC_CONFIG_NOT_FOUND: the config file has not been found
		OC_CONFIG_PARSE_ERROR: the was a parse error
*/
string readSettings()
{
	string errorString = "";
	TiXmlDocument settings;

// Now try to open the config file then read it
	OPENCITY_INFO(
		"Reading XML config file: \"" << ocConfigDirPrefix(OC_CONFIG_FILE_FILENAME) << "\""
	);

// Load the settings file
	string fn = ocConfigDirPrefix(OC_CONFIG_FILE_FILENAME);
	if (!settings.LoadFile(fn)) {
		errorString = settings.ErrorDesc();
		return errorString;
	}

// Error testing
	if (settings.Error()) {
		errorString = settings.ErrorDesc();
		return errorString;
	}

// Get the root element
	TiXmlNode* pRoot = settings.RootElement();
	if (pRoot == NULL) {
		errorString = settings.ErrorDesc();
		return errorString;
	}

// Parse the settings
	TiXmlElement* pElement = pRoot->FirstChildElement();
	int i = 0;
	while (pElement != NULL)
	{
// Debug
//		cout << i++ << "||" << *pElement << std::endl;
	// "city" element, read the city's size
		if (pElement->ValueStr() == "city") {
			TiXmlElement* pChild = pElement->FirstChildElement();
			while (pChild != NULL) {
				cout << i++ << "||" << *pChild << std::endl;
				if (pChild->ValueStr() == "width") {
					pChild->QueryIntAttribute("value", (int*)&gVars.guiCityWidth);
				}
				else if (pChild->ValueStr() == "length") {
					pChild->QueryIntAttribute("value", (int*)&gVars.guiCityLength);
				}
				pChild = pChild->NextSiblingElement();
			}
		}
	// "msPerFrame" element
		else if (pElement->ValueStr() == "msPerFrame") {
			pElement->QueryIntAttribute("value", (int*)&gVars.guiMsPerFrame);
		}
	// "zenServer" element
		else if (pElement->ValueStr() == "zenServer") {
			if (pElement->GetText() != NULL)
				gVars.gsZenServer = pElement->GetText();
		}

		pElement = pElement->NextSiblingElement();
	}

	return errorString;
}


   /*=====================================================================*/
void initGlobalVar()
{
// Config file and command line options
	gVars.gboolUseAudio				= true;
	gVars.gboolFullScreen			= false;
	gVars.gboolServerMode			= false;
	gVars.guiCityWidth				= OC_CITY_W;
	gVars.guiCityLength				= OC_CITY_L;
	gVars.guiMsPerFrame				= OC_MS_PER_FRAME;
	gVars.guiScreenWidth			= OC_WINDOW_WIDTH;
	gVars.guiScreenHeight			= OC_WINDOW_HEIGHT;
	gVars.guiVideoBpp				= OC_WINDOW_BPP_DEFAULT;

	gVars.gsGeneratorHeightMap			= "";
	gVars.guiGeneratorSeed				= time(NULL);
	gVars.guiGeneratorMapType			= MapGen::MapMaker::PLAIN;
	gVars.guiGeneratorWaterType			= MapGen::MapMaker::LAKE;
	gVars.guiGeneratorMapShapeType		= MapGen::MapMaker::NONE;
	gVars.guiGeneratorTreeDensityType	= MapGen::MapMaker::SPARSE;

	gVars.gfMsSimDelayMax			= 0;
	gVars.gsZenServer				= "localhost";

// Application status
	gVars.gboolActive				= true;		// the application is active at start

// The mutex that all the simulators depend on
	gVars.gpmutexSim				= NULL;

// The famous renderer
	gVars.gpRenderer				= NULL;

// Datamanagers
	gVars.gpAudioMgr				= NULL;		// global Audio Manager
	gVars.gpGraphicMgr				= NULL;		// global Graphic Manager
	gVars.gpPropertyMgr				= NULL;		// global Property Manager
	gVars.gpMapMaker				= NULL;		// global map maker
	gVars.gpMapMgr					= NULL;		// global height Map Manager
	gVars.gpNetworking				= NULL;		// global networking support class
	gVars.gpPathFinder				= NULL;		// global pathfinder class
	gVars.gpMoveMgr					= NULL;		// global movement manager

// Multi-Agent System
	gVars.gpKernel					= NULL;		// global MAS Kernel
	gVars.gpEnvironment				= NULL;		// global Environement class

// The SDL video surface
	gVars.gpVideoSrf				= NULL;		// global video screen surface
}


   /*=====================================================================*/
#ifdef __WIN32__
extern "C"
#endif
int main(int argc, char *argv[])
{
// Initialize the global settings variable to the default values
	initGlobalVar();

// Print out the copyright
	printCopyright();

// Parse the command-line options
	parseArg( argc, argv );

// Detect the main path: sDataDir and sSaveDir
	detectProgramPath();

// Read the application settings from the XML settings file
	string errorDesc = readSettings();
	if (errorDesc != "") {
		OPENCITY_FATAL(
			"The was an error while loading the settings file: \"" << errorDesc << "\"" << endl
			<< "If the main config file \"" << OC_CONFIG_FILE_FILENAME << "\" has not been found then" << endl
			<< "try to specify the data directory with ""--datadir"" "
			<< "and the configuration directory with ""--confdir""." << endl
			<< "For example:" << endl
			<< "    " << argv[0] << " --datadir \"/absolute/path/to/opencity/data\" "
			<< "--confdir \"/absolute/path/to/opencity/conf\"" << endl
			<< "or" << endl
			<< "    " << argv[0] << " --datadir \"../relative/path/to/opencity/data\" "
			<< "--confdir \"../relative/path/to/opencity/conf\"" << endl
		);
		exit(OC_CONFIG_NOT_FOUND);
	}

// Initialization of global variables
	uipCurrentUI = NULL;
	gVars.gfMsSimDelayMax = log10((OC_FLOAT)gVars.guiCityWidth*gVars.guiCityLength + 1) * OC_MS_GLOBAL_LOG_FACTOR;

// Initialize the random number generator
	srand( time(NULL) );

// Launch the server
	int returnCode = serverMode();

	return returnCode;
}


   /*=====================================================================*/
   /*                       GLOBAL       FUNCTIONS                        */
   /*=====================================================================*/
string
ocDataDirPrefix( const string& s )
{
	return sDataDir + s;
}


   /*=====================================================================*/
string
ocConfigDirPrefix( const string& s )
{
	return sConfigDir + s;
}


   /*=====================================================================*/
string
ocSaveDirPrefix( const string& s )
{
	return sSaveDir + s;
}


   /*=====================================================================*/
string ocStrVersion()
{
	std::ostringstream oss;

	oss << OC_VERSION << "." << OC_PATCHLEVEL << "." << OC_SUBLEVEL;
	return oss.str();
}


   /*=====================================================================*/
long ocLongVersion()
{
	long lVersion = 0;

	lVersion = OC_VERSION*65536 + OC_PATCHLEVEL*256 + OC_SUBLEVEL;
	return lVersion;
}