1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name stratagus.cpp - The main file. */
12 //
13 // (c) Copyright 1998-2015 by Lutz Sammer, Francois Beerten,
14 // Jimmy Salmon, Pali Rohár and cybermind
15 //
16 // This program is free software; you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation; only version 2 of the License.
19 //
20 // This program is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU General Public License for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with this program; if not, write to the Free Software
27 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 // 02111-1307, USA.
29 //
30
31 //@{
32
33 /**
34 ** @mainpage
35 **
36 ** @section Introduction Introduction
37 **
38 ** Welcome to the source code documentation of the Stratagus engine.
39 ** Extract the source documentation with doxygen (http://www.doxygen.org) tool.
40 **
41 ** Any help to improve this documention is welcome. If you didn't
42 ** understand something or you found an error or a wrong spelling
43 ** or wrong grammar please write an email (including a patch :).
44 **
45 ** @section Information Information
46 **
47 ** Visit the https://github.com/Wargus/stratagus web page for the latest news and
48 ** <A HREF="../index.html">Stratagus Info</A> for other documentation.
49 **
50 ** @section Modules Modules
51 **
52 ** This are the main modules of the Stratagus engine.
53 **
54 ** @subsection Map Map
55 **
56 ** Handles the map. A map is made from tiles.
57 **
58 ** @see map.h @see map.cpp @see tileset.h @see tileset.cpp
59 **
60 ** @subsection Unit Unit
61 **
62 ** Handles units. Units are ships, flyers, buildings, creatures,
63 ** machines.
64 **
65 ** @see unit.h @see unit.cpp @see unittype.h @see unittype.cpp
66 **
67 ** @subsection Missile Missile
68 **
69 ** Handles missiles. Missiles are all other sprites on map
70 ** which are no unit.
71 **
72 ** @see missile.h @see missile.cpp
73 **
74 ** @subsection Player Player
75 **
76 ** Handles players, all units are owned by a player. A player
77 ** could be controlled by a human or a computer.
78 **
79 ** @see player.h @see player.cpp @see ::CPlayer
80 **
81 ** @subsection Sound Sound
82 **
83 ** Handles the high and low level of the sound. There are the
84 ** background music support, voices and sound effects.
85 ** Following low level backends are supported: OSS and SDL.
86 **
87 ** @todo adpcm file format support for sound effects
88 ** @todo better separation of low and high level, assembler mixing
89 ** support.
90 ** @todo Streaming support of ogg/mp3 files.
91 **
92 ** @see sound.h @see sound.cpp
93 ** @see script_sound.cpp @see sound_id.cpp @see sound_server.cpp
94 ** @see unitsound.cpp
95 ** @see sdl_audio.cpp
96 ** @see ogg.cpp @see wav.cpp
97 **
98 ** @subsection Video Video
99 **
100 ** Handles the high and low level of the graphics.
101 ** This also contains the sprite and linedrawing routines.
102 **
103 ** See page @ref VideoModule for more information upon supported
104 ** features and video platforms.
105 **
106 ** @see video.h @see video.cpp
107 **
108 ** @subsection Network Network
109 **
110 ** Handles the high and low level of the network protocol.
111 ** The network protocol is needed for multiplayer games.
112 **
113 ** See page @ref NetworkModule for more information upon supported
114 ** features and API.
115 **
116 ** @see network.h @see network.cpp
117 **
118 ** @subsection Pathfinder Pathfinder
119 **
120 ** @see pathfinder.h @see pathfinder.cpp
121 **
122 ** @subsection AI AI
123 **
124 ** There are currently two AI's. The old one is very hardcoded,
125 ** but does things like placing buildings better than the new.
126 ** The old AI shouldn't be used. The new is very flexible, but
127 ** very basic. It includes none optimations.
128 **
129 ** See page @ref AiModule for more information upon supported
130 ** features and API.
131 **
132 ** @see ai_local.h
133 ** @see ai.h @see ai.cpp
134 **
135 ** @subsection CCL CCL
136 **
137 ** CCL is Craft Configuration Language, which is used to
138 ** configure and customize Stratagus.
139 **
140 ** @see script.h @see script.cpp
141 **
142 ** @subsection Icon Icon
143 **
144 ** @see icons.h @see icons.cpp
145 **
146 ** @subsection Editor Editor
147 **
148 ** This is the integrated editor, it shouldn't be a perfect
149 ** editor. It is used to test new features of the engine.
150 **
151 ** See page @ref EditorModule for more information upon supported
152 ** features and API.
153 **
154 ** @see editor.h @see editor.cpp
155 */
156
157 /*----------------------------------------------------------------------------
158 -- Includes
159 ----------------------------------------------------------------------------*/
160
161 #include <ctype.h>
162
163 #ifdef USE_BEOS
164 #include <fcntl.h>
165 #include <sys/types.h>
166 #include <sys/stat.h>
167
168 extern void beos_init(int argc, char **argv);
169
170 #endif
171
172 #ifdef MAC_BUNDLE
173 #define Button ButtonOSX
174 #include <Carbon/Carbon.h>
175 #undef Button
176 #endif
177
178 #include "SDL.h"
179
180 #include "stratagus.h"
181
182 #include "ai.h"
183 #include "editor.h"
184 #include "game.h"
185 #include "guichan.h"
186 #include "interface.h"
187 #include "iocompat.h"
188 #include "iolib.h"
189 #include "map.h"
190 #include "netconnect.h"
191 #include "network.h"
192 #include "parameters.h"
193 #include "player.h"
194 #include "replay.h"
195 #include "results.h"
196 #include "settings.h"
197 #include "sound_server.h"
198 #include "title.h"
199 #include "translate.h"
200 #include "ui.h"
201 #include "unit_manager.h"
202 #include "version.h"
203 #include "video.h"
204 #include "widgets.h"
205 #include "util.h"
206
207 #include "missile.h" //for FreeBurningBuildingFrames
208
209 #ifdef USE_STACKTRACE
210 #include <stdexcept>
211 #include <stacktrace/call_stack.hpp>
212 #include <stacktrace/stack_exception.hpp>
213 #else
214 #include "st_backtrace.h"
215 #endif
216
217 #include <stdlib.h>
218 #include <stdio.h>
219
220 #ifdef USE_WIN32
221 #include <windows.h>
222 #include <dbghelp.h>
223 #endif
224
225 #if defined(USE_WIN32) && ! defined(NO_STDIO_REDIRECT)
226 #include "windows.h"
227 #define REDIRECT_OUTPUT
228 #endif
229
230 #if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT)
231 #include "SetupConsole_win32.h"
232 #endif
233
234 /*----------------------------------------------------------------------------
235 -- Variables
236 ----------------------------------------------------------------------------*/
237
238 std::string StratagusLibPath; /// Path for data directory
239
240 /// Name, Version, Copyright
241 const char NameLine[] = NAME " v" VERSION ", " COPYRIGHT;
242
243 std::string CliMapName; /// Filename of the map given on the command line
244 std::string MenuRace;
245
246 bool EnableDebugPrint; /// if enabled, print the debug messages
247 bool EnableAssert; /// if enabled, halt on assertion failures
248 bool EnableUnitDebug; /// if enabled, a unit info dump will be created
249
250 #ifdef DEBUG
251 bool IsDebugEnabled {true}; /// Is debug enabled? Flag to pass into lua code.
252 #else
253 bool IsDebugEnabled {false}; /// Is debug enabled? Flag to pass into lua code.
254 #endif
255 bool EnableWallsInSinglePlayer {false}; /// Enables ability to build walls in the single player games
256 /// used for debug purposes
257
258 /*============================================================================
259 == MAIN
260 ============================================================================*/
261
262 /**
263 ** Pre menu setup.
264 */
PreMenuSetup()265 void PreMenuSetup()
266 {
267 //
268 // Initial menus require some gfx.
269 //
270 SetDefaultTextColors(FontYellow, FontWhite);
271
272 LoadFonts();
273
274 InitVideoCursors();
275
276 if (MenuRace.empty()) {
277 LoadCursors(PlayerRaces.Name[0]);
278 } else {
279 LoadCursors(MenuRace);
280 }
281
282 InitSettings();
283
284 InitUserInterface();
285 UI.Load();
286 }
287
288 /**
289 ** Run the guichan main menus loop.
290 **
291 ** @return 0 for success, else exit.
292 */
MenuLoop()293 static int MenuLoop()
294 {
295 int status;
296
297 initGuichan();
298 InterfaceState = IfaceStateMenu;
299 // Clear screen
300 Video.ClearScreen();
301 Invalidate();
302
303 ButtonUnderCursor = -1;
304 OldButtonUnderCursor = -1;
305 CursorState = CursorStatePoint;
306 GameCursor = UI.Point.Cursor;
307
308 // FIXME delete this when switching to full guichan GUI
309 const std::string filename = LibraryFileName("scripts/guichan.lua");
310 status = LuaLoadFile(filename);
311
312 // We clean up later in Exit
313 return status;
314 }
315
316 //----------------------------------------------------------------------------
317
318 /**
319 ** Print headerline, copyright, ...
320 */
PrintHeader()321 static void PrintHeader()
322 {
323 std::string CompileOptions =
324 #ifdef DEBUG
325 "DEBUG "
326 #endif
327 #ifdef USE_ZLIB
328 "ZLIB "
329 #endif
330 #ifdef USE_BZ2LIB
331 "BZ2LIB "
332 #endif
333 #ifdef USE_VORBIS
334 "VORBIS "
335 #endif
336 #ifdef USE_THEORA
337 "THEORA "
338 #endif
339 #ifdef USE_WIN32
340 "WIN32 "
341 #endif
342 #ifdef USE_LINUX
343 "LINUX "
344 #endif
345 #ifdef USE_BSD
346 "BSD "
347 #endif
348 #ifdef USE_BEOS
349 "BEOS "
350 #endif
351 #ifdef USE_MAC
352 "MAC "
353 #endif
354 "";
355
356 fprintf(stdout,
357 "%s\n written by Lutz Sammer, Fabrice Rossi, Vladi Shabanski, Patrice Fortier,\n"
358 " Jon Gabrielson, Andreas Arens, Nehal Mistry, Jimmy Salmon, Pali Rohar,\n"
359 " cybermind and others.\n"
360 "\t" HOMEPAGE "\n"
361 "Compile options %s",
362 NameLine, CompileOptions.c_str());
363 }
364
PrintLicense()365 void PrintLicense()
366 {
367 printf("\n"
368 "\n"
369 "Stratagus may be copied only under the terms of the GNU General Public License\n"
370 "which may be found in the Stratagus source kit.\n"
371 "\n"
372 "DISCLAIMER:\n"
373 "This software is provided as-is. The author(s) can not be held liable for any\n"
374 "damage that might arise from the use of this software.\n"
375 "Use it at your own risk.\n"
376 "\n");
377 }
378
379
380 /**
381 ** Exit the game.
382 **
383 ** @param err Error code to pass to shell.
384 */
Exit(int err)385 void Exit(int err)
386 {
387 if (GameRunning) {
388 StopGame(GameExit);
389 return;
390 }
391
392 StopMusic();
393 QuitSound();
394 NetworkQuitGame();
395
396 ExitNetwork1();
397 CleanModules();
398 FreeBurningBuildingFrames();
399 FreeSounds();
400 FreeGraphics();
401 FreePlayerColors();
402 FreeButtonStyles();
403 FreeAllContainers();
404 freeGuichan();
405 DebugPrint("Frames %lu, Slow frames %d = %ld%%\n" _C_
406 FrameCounter _C_ SlowFrameCounter _C_
407 (SlowFrameCounter * 100) / (FrameCounter ? FrameCounter : 1));
408 lua_settop(Lua, 0);
409 lua_close(Lua);
410 DeInitVideo();
411 DeInitImageLoaders();
412
413 fprintf(stdout, "%s", _("Thanks for playing Stratagus.\n"));
414 exit(err);
415 }
416
417 /**
418 ** Do a fatal exit.
419 ** Called on out of memory or crash.
420 **
421 ** @param err Error code to pass to shell.
422 */
ExitFatal(int err)423 void ExitFatal(int err)
424 {
425 #ifdef USE_STACKTRACE
426 throw stacktrace::stack_runtime_error((const char*)err);
427 #else
428 print_backtrace();
429 #endif
430 exit(err);
431 }
432
433 /**
434 ** Display the usage.
435 */
Usage()436 static void Usage()
437 {
438 PrintHeader();
439 printf(
440 "\n\nUsage: %s [OPTIONS] [map.smp|map.smp.gz]\n"
441 "\t-a\t\tEnables asserts check in engine code (for debugging)\n"
442 "\t-c file.lua\tConfiguration start file (default stratagus.lua)\n"
443 "\t-d datapath\tPath to stratagus data (default current directory)\n"
444 "\t-D depth\tVideo mode depth = pixel per point\n"
445 "\t-e\t\tStart editor (instead of game)\n"
446 "\t-E file.lua\tEditor configuration start file (default editor.lua)\n"
447 "\t-F\t\tFull screen video mode\n"
448 "\t-g\t\tForce software rendering (implies no shaders)\n"
449 "\t-G \"options\"\tGame options (passed to game scripts)\n"
450 "\t-h\t\tHelp shows this page\n"
451 "\t-i\t\tEnables unit info dumping into log (for debugging)\n"
452 "\t-I addr\t\tNetwork address to use\n"
453 "\t-l\t\tDisable command log\n"
454 "\t-N name\t\tName of the player\n"
455 "\t-p\t\tEnables debug messages printing in console\n"
456 "\t-P port\t\tNetwork port to use\n"
457 "\t-s sleep\tNumber of frames for the AI to sleep before it starts\n"
458 "\t-S speed\tSync speed (100 = 30 frames/s)\n"
459 "\t-u userpath\tPath where stratagus saves preferences, log and savegame. Use 'userhome' to force platform-default userhome directory.\n"
460 "\t-v mode\t\tVideo mode resolution in format <xres>x<yres>\n"
461 "\t-W\t\tWindowed video mode. Optionally takes a window size in <xres>x<yres>\n"
462 "map is relative to StratagusLibPath=datapath, use ./map for relative to cwd\n",
463 Parameters::Instance.applicationName.c_str());
464 }
465
466 #ifdef REDIRECT_OUTPUT
467
468 static std::string stdoutFile;
469 static std::string stderrFile;
470
CleanupOutput()471 static void CleanupOutput()
472 {
473 fclose(stdout);
474 fclose(stderr);
475
476 struct stat st;
477 if (stat(stdoutFile.c_str(), &st) == 0 && st.st_size == 0) {
478 unlink(stdoutFile.c_str());
479 }
480 if (stat(stderrFile.c_str(), &st) == 0 && st.st_size == 0) {
481 unlink(stderrFile.c_str());
482 }
483 }
484
RedirectOutput()485 static void RedirectOutput()
486 {
487 std::string path = Parameters::Instance.GetUserDirectory();
488
489 makedir(path.c_str(), 0777);
490
491 stdoutFile = path + "\\stdout.txt";
492 stderrFile = path + "\\stderr.txt";
493
494 if (!freopen(stdoutFile.c_str(), "w", stdout)) {
495 printf("freopen stdout failed");
496 }
497 if (!freopen(stderrFile.c_str(), "w", stderr)) {
498 printf("freopen stderr failed");
499 }
500 atexit(CleanupOutput);
501 }
502 #endif
503
ParseCommandLine(int argc,char ** argv,Parameters & parameters)504 void ParseCommandLine(int argc, char **argv, Parameters ¶meters)
505 {
506 char *sep;
507 for (;;) {
508 switch (getopt(argc, argv, "ac:d:D:eE:FgG:hiI:lN:oOP:ps:S:u:v:W?-")) {
509 case 'a':
510 EnableAssert = true;
511 continue;
512 case 'c':
513 parameters.luaStartFilename = optarg;
514 if (strlen(optarg) > 4 &&
515 !(strstr(optarg, ".lua") == optarg + strlen(optarg) - 4)) {
516 parameters.luaStartFilename += ".lua";
517 }
518 continue;
519 case 'd': {
520 StratagusLibPath = optarg;
521 size_t index;
522 while ((index = StratagusLibPath.find('\\')) != std::string::npos) {
523 StratagusLibPath[index] = '/';
524 }
525 continue;
526 }
527 case 'D':
528 Video.Depth = atoi(optarg);
529 continue;
530 case 'e':
531 Editor.Running = EditorCommandLine;
532 continue;
533 case 'E':
534 parameters.luaEditorStartFilename = optarg;
535 continue;
536 case 'F':
537 VideoForceFullScreen = 1;
538 Video.FullScreen = 1;
539 continue;
540 case 'g':
541 SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER, "software", SDL_HINT_OVERRIDE);
542 continue;
543 case 'G':
544 parameters.luaScriptArguments = optarg;
545 continue;
546 case 'i':
547 EnableUnitDebug = true;
548 continue;
549 case 'I':
550 CNetworkParameter::Instance.localHost = optarg;
551 continue;
552 case 'l':
553 CommandLogDisabled = true;
554 continue;
555 case 'N':
556 parameters.LocalPlayerName = optarg;
557 continue;
558 case 'P':
559 CNetworkParameter::Instance.localPort = atoi(optarg);
560 continue;
561 case 'p':
562 EnableDebugPrint = true;
563 continue;
564 case 's':
565 AiSleepCycles = atoi(optarg);
566 continue;
567 case 'S':
568 VideoSyncSpeed = atoi(optarg);
569 continue;
570 case 'u':
571 if (!strcmp(optarg, "userhome")) {
572 Parameters::Instance.SetUserDirectory("");
573 } else {
574 Parameters::Instance.SetUserDirectory(optarg);
575 }
576 continue;
577 case 'v': {
578 sep = strchr(optarg, 'x');
579 if (!sep || !*(sep + 1)) {
580 fprintf(stderr, "%s: incorrect format of video mode resolution -- '%s'\n", argv[0], optarg);
581 Usage();
582 exit(-1);
583 }
584 Video.Height = atoi(sep + 1);
585 *sep = 0;
586 Video.Width = atoi(optarg);
587 if (!Video.Height || !Video.Width) {
588 fprintf(stderr, "%s: incorrect format of video mode resolution -- '%sx%s'\n", argv[0], optarg, sep + 1);
589 Usage();
590 exit(-1);
591 }
592 continue;
593 }
594 case 'W':
595 if (optind < argc && argv[optind] && argv[optind][0] != '-') {
596 // allow -W to take an optional argument in a POSIX compliant way
597 optarg = argv[optind];
598 sep = strchr(optarg, 'x');
599 if (!sep || !*(sep + 1)) {
600 fprintf(stderr, "%s: incorrect window size -- '%s'\n", argv[0], optarg);
601 Usage();
602 exit(-1);
603 }
604 Video.WindowHeight = atoi(sep + 1);
605 *sep = 0;
606 Video.WindowWidth = atoi(optarg);
607 if (!Video.WindowHeight || !Video.WindowWidth) {
608 fprintf(stderr, "%s: incorrect window size -- '%sx%s'\n", argv[0], optarg, sep + 1);
609 Usage();
610 exit(-1);
611 }
612 optind += 1; // skip the optional window size argument
613 }
614 VideoForceFullScreen = 1;
615 Video.FullScreen = 0;
616 continue;
617 case -1:
618 break;
619 case '?':
620 case 'h':
621 default:
622 Usage();
623 exit(-1);
624 }
625 break;
626 }
627
628 if (argc - optind > 1) {
629 fprintf(stderr, "too many map files. if you meant to pass game arguments, these go after '--'\n");
630 Usage();
631 ExitFatal(-1);
632 }
633
634 if (argc - optind) {
635 size_t index;
636 CliMapName = argv[optind];
637 while ((index = CliMapName.find('\\')) != std::string::npos) {
638 CliMapName[index] = '/';
639 }
640 }
641 }
642
643 #ifdef USE_WIN32
CreateDumpFile(EXCEPTION_POINTERS * ExceptionInfo)644 static LONG WINAPI CreateDumpFile(EXCEPTION_POINTERS *ExceptionInfo)
645 {
646 HANDLE hFile = CreateFile("crash.dmp", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
647 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
648 MINIDUMP_EXCEPTION_INFORMATION mei;
649 mei.ThreadId = GetCurrentThreadId();
650 mei.ClientPointers = TRUE;
651 mei.ExceptionPointers = ExceptionInfo;
652 MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mei, NULL, NULL);
653 fprintf(stderr, "Stratagus crashed!\n");
654 fprintf(stderr, "A mini dump file \"crash.dmp\" has been created in the Stratagus folder.\n");
655 fprintf(stderr, "Please send it to our bug tracker: https://github.com/Wargus/stratagus/issues\n");
656 fprintf(stderr, "and tell us what caused this bug to occur.\n");
657 return EXCEPTION_EXECUTE_HANDLER;
658 }
659 #endif
660
661 /**
662 ** The main program: initialise, parse options and arguments.
663 **
664 ** @param argc Number of arguments.
665 ** @param argv Vector of arguments.
666 */
stratagusMain(int argc,char ** argv)667 int stratagusMain(int argc, char **argv)
668 {
669 #ifdef USE_BEOS
670 // Parse arguments for BeOS
671 beos_init(argc, argv);
672 #endif
673 #ifdef USE_WIN32
674 SetUnhandledExceptionFilter(CreateDumpFile);
675 #endif
676 #if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT)
677 SetupConsole();
678 #endif
679 // Setup some defaults.
680 #ifndef MAC_BUNDLE
681 StratagusLibPath = ".";
682 #else
683 freopen("/tmp/stdout.txt", "w", stdout);
684 freopen("/tmp/stderr.txt", "w", stderr);
685 // Look for the specified data set inside the application bundle
686 // This should be a subdir of the Resources directory
687 CFURLRef pluginRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
688 CFSTR(MAC_BUNDLE_DATADIR), NULL, NULL);
689 CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, kCFURLPOSIXPathStyle);
690 const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());
691 Assert(pathPtr);
692 StratagusLibPath = pathPtr;
693 #endif
694 try {
695 Parameters ¶meters = Parameters::Instance;
696 parameters.SetDefaultValues();
697 parameters.SetLocalPlayerNameFromEnv();
698
699 #ifdef REDIRECT_OUTPUT
700 RedirectOutput();
701 #endif
702
703 if (argc > 0) {
704 parameters.applicationName = argv[0];
705 }
706
707 // FIXME: Parse options before or after scripts?
708 ParseCommandLine(argc, argv, parameters);
709 // Init the random number generator.
710 InitSyncRand();
711
712 makedir(parameters.GetUserDirectory().c_str(), 0777);
713
714 // Init Lua and register lua functions!
715 InitLua();
716 LuaRegisterModules();
717
718 // Initialise AI module
719 InitAiModule();
720
721 // Setup sound card, must be done before loading sounds, so that
722 // SDL_mixer can auto-convert to the target format
723 if (!InitSound()) {
724 InitMusic();
725 }
726
727 LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments);
728
729 // Setup video display
730 InitVideo();
731
732 PrintHeader();
733 PrintLicense();
734
735 #ifndef DEBUG // For debug it's better not to have:
736 srand(time(NULL)); // Random counter = random each start
737 #endif
738
739 // Show title screens.
740 SetDefaultTextColors(FontYellow, FontWhite);
741 LoadFonts();
742 SetClipping(0, 0, Video.Width - 1, Video.Height - 1);
743 Video.ClearScreen();
744 ShowTitleScreens();
745
746 // Init player data
747 ThisPlayer = NULL;
748 //Don't clear the Players structure as it would erase the allowed units.
749 // memset(Players, 0, sizeof(Players));
750 NumPlayers = 0;
751
752 UnitManager.Init(); // Units memory management
753 PreMenuSetup(); // Load everything needed for menus
754
755 MenuLoop();
756
757 Exit(0);
758 } catch (const std::exception &e) {
759 fprintf(stderr, "Stratagus crashed!\n");
760 fprintf(stderr, "Please send this call stack to our bug tracker: https://github.com/Wargus/stratagus/issues\n");
761 fprintf(stderr, "and tell us what caused this bug to occur.\n");
762 fprintf(stderr, " === exception state traceback === \n");
763 fprintf(stderr, "%s", e.what());
764 exit(1);
765 }
766 return 0;
767 }
768
769 //@}
770