CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

MPLAYER.CPP (52637B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\mplayer.cpv   1.9   16 Oct 1995 16:51:08   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : MPLAYER.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Bill Randolph                                                *
     26  *                                                                                             *
     27  *                   Start Date : April 14, 1995                                               *
     28  *                                                                                             *
     29  *                  Last Update : July 5, 1995 [BRR]                                           *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   Select_MPlayer_Game -- prompts user for NULL-Modem, Modem, or Network game                *
     34  *   Read_MultiPlayer_Settings -- reads multi-player settings from conquer.ini                 *
     35  *   Write_MultiPlayer_Settings -- writes multi-player settings to conquer.ini                 *
     36  *   Read_Scenario_Descriptions -- reads multi-player scenario #'s # descriptions              *
     37  *   Free_Scenario_Descriptions -- frees memory for the scenario descriptions                  *
     38  *   Computer_Message -- "sends" a message from the computer                                   *
     39  *   Garble_Message -- "garbles" a message                                                     *
     40  *   Surrender_Dialog -- Prompts user for surrendering                                         *
     41  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     42 
     43 #include "function.h"
     44 #include "tcpip.h"
     45 
     46 static void Garble_Message(char *buf);
     47 
     48 int Choose_Internet_Game(void);
     49 int Get_Internet_Host_Or_Join(void);
     50 int Get_IP_Address(void);
     51 void Show_Internet_Connection_Progress(void);
     52 
     53 /***********************************************************************************************
     54  * Select_MPlayer_Game -- prompts user for NULL-Modem, Modem, or Network game                  *
     55  *                                                                                             *
     56  * INPUT:                                                                                      *
     57  *      none.                                                                                  *
     58  *                                                                                             *
     59  * OUTPUT:                                                                                     *
     60  *      GAME_NORMAL, GAME_MODEM, etc.                                                          *
     61  *                                                                                             *
     62  * WARNINGS:                                                                                   *
     63  *      none.                                                                                  *
     64  *                                                                                             *
     65  * HISTORY:                                                                                    *
     66  *   02/14/1995 BR : Created.                                                                  *
     67  *=============================================================================================*/
     68 GameType Select_MPlayer_Game (void)
     69 {
     70 //PG_TO_FIX
     71 	return GAME_NORMAL;
     72 #if (0)
     73 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
     74 	bool	ipx_avail = FALSE;
     75 	int number_of_buttons;
     76 	/*........................................................................
     77 	Dialog & button dimensions
     78 	........................................................................*/
     79 	int	d_dialog_w = 190*factor;
     80 	int	d_dialog_h = 26*4*factor;
     81 	int 	d_dialog_x = ((320*factor - d_dialog_w) / 2);
     82 //	d_dialog_y = ((200 - d_dialog_h) / 2),
     83 	int	d_dialog_y = ((136*factor - d_dialog_h) / 2);
     84 	int	d_dialog_cx = d_dialog_x + (d_dialog_w / 2);
     85 
     86 	int	d_txt6_h = 11 * factor;
     87 	int	d_margin = 7 *factor;
     88 
     89 	int	d_modemserial_w = 80*factor;
     90 	int	d_modemserial_h = 9*factor;
     91 	int 	d_modemserial_x = d_dialog_cx - d_modemserial_w / 2;
     92 	int	d_modemserial_y = d_dialog_y + d_margin + d_txt6_h + d_margin;
     93 #if (0)
     94 	int	d_internet_w = 80*factor;
     95 	int	d_internet_h = 9*factor;
     96 	int	d_internet_x = d_dialog_cx - d_internet_w / 2;
     97 	int	d_internet_y = d_modemserial_y + d_modemserial_h + 2*factor;
     98 #endif	//(0)
     99 	int 	d_ipx_w = 80*factor;
    100 	int	d_ipx_h = 9*factor;
    101 	int	d_ipx_x = d_dialog_cx - d_ipx_w / 2;
    102 	int 	d_ipx_y = d_modemserial_y + d_modemserial_h + 2*factor;
    103 //	int 	d_ipx_y = d_internet_y + d_internet_h + 2*factor;
    104 
    105 	int	d_cancel_w = 60*factor;
    106 	int 	d_cancel_h = 9*factor;
    107 	int	d_cancel_x = d_dialog_cx - d_cancel_w / 2;
    108 	int	d_cancel_y = d_ipx_y + d_ipx_h + d_margin;
    109 
    110 	CountDownTimerClass delay;
    111 
    112 	/*........................................................................
    113 	Button enumerations:
    114 	........................................................................*/
    115 	enum {
    116 		BUTTON_MODEMSERIAL = 100,
    117 #if	(0)
    118 		BUTTON_INTERNET,
    119 #endif	//(0)
    120 		BUTTON_IPX,
    121 		BUTTON_CANCEL,
    122 
    123 		NUM_OF_BUTTONS = 3,
    124 	};
    125 	number_of_buttons = NUM_OF_BUTTONS;
    126 	/*........................................................................
    127 	Redraw values: in order from "top" to "bottom" layer of the dialog
    128 	........................................................................*/
    129 	typedef enum {
    130 		REDRAW_NONE = 0,
    131 		REDRAW_BUTTONS,		// includes map interior & coord values
    132 		REDRAW_BACKGROUND,	// includes box, map bord, key, coord labels, btns
    133 		REDRAW_ALL = REDRAW_BACKGROUND
    134 	} RedrawType;
    135 	/*........................................................................
    136 	Dialog variables:
    137 	........................................................................*/
    138 	KeyNumType input;								// input from user
    139 	bool process;									// loop while true
    140 	RedrawType display;							// true = re-draw everything
    141 	GameType retval;								// return value
    142 	int selection;
    143 	bool pressed;
    144 	int curbutton;
    145 	TextButtonClass *buttons[NUM_OF_BUTTONS];
    146 
    147 	/*........................................................................
    148 	Buttons
    149 	........................................................................*/
    150 	ControlClass *commands = NULL;				// the button list
    151 
    152 	//
    153 	// If neither IPX or winsock are active then do only the modem serial dialog
    154 	//
    155 	if (Ipx.Is_IPX()){
    156 		ipx_avail = TRUE;
    157 	}
    158 
    159 
    160 	TextButtonClass modemserialbtn (BUTTON_MODEMSERIAL, TXT_MODEM_SERIAL,
    161 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    162 		d_modemserial_x, d_modemserial_y, d_modemserial_w, d_modemserial_h);
    163 #if (0)
    164 	TextButtonClass internetbtn (BUTTON_INTERNET, TXT_INTERNET,
    165 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    166 		d_internet_x, d_internet_y, d_internet_w, d_internet_h);
    167 #endif	//(0)
    168 	TextButtonClass ipxbtn (BUTTON_IPX, TXT_NETWORK,
    169 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    170 		d_ipx_x, d_ipx_y, d_ipx_w, d_ipx_h);
    171 
    172 	TextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL,
    173 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    174 		d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
    175 
    176 	/*
    177 	------------------------------- Initialize -------------------------------
    178 	*/
    179 	Set_Logic_Page(SeenBuff);
    180 
    181 	/*
    182 	............................ Create the list .............................
    183 	*/
    184 	commands = &modemserialbtn;
    185 #if (0)
    186 	internetbtn.Add_Tail(*commands);
    187 #endif	//(0)
    188 	if (ipx_avail){
    189 		ipxbtn.Add_Tail(*commands);
    190 	}
    191 	cancelbtn.Add_Tail(*commands);
    192 
    193 	/*
    194 	......................... Fill array of button ptrs ......................
    195 	*/
    196 	curbutton = 0;
    197 	buttons[0] = &modemserialbtn;
    198 #if (0)
    199 	buttons[1] = &internetbtn;
    200 #endif	//(0)
    201 	if (ipx_avail){
    202 		buttons[1] = &ipxbtn;
    203 		buttons[2] = &cancelbtn;
    204 	}else{
    205 		buttons[1] = &cancelbtn;
    206 		number_of_buttons--;
    207 	}
    208 
    209 	buttons[curbutton]->Turn_On();
    210 
    211 	Keyboard::Clear();
    212 
    213 	Fancy_Text_Print(TXT_NONE, 0, 0, CC_GREEN, TBLACK,
    214 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
    215 
    216 	/*
    217 	-------------------------- Main Processing Loop --------------------------
    218 	*/
    219 	display = REDRAW_ALL;
    220 	process = true;
    221 	pressed = false;
    222 	while (process) {
    223 		/*
    224 		** If we have just received input focus again after running in the background then
    225 		** we need to redraw.
    226 		*/
    227 		if (AllSurfaces.SurfacesRestored){
    228 			AllSurfaces.SurfacesRestored=FALSE;
    229 			display=REDRAW_ALL;
    230 		}
    231 
    232 		/*
    233 		........................ Invoke game callback .........................
    234 		*/
    235 		Call_Back();
    236 		/*
    237 		...................... Refresh display if needed ......................
    238 		*/
    239 		if (display) {
    240 			Hide_Mouse();
    241 			if (display >= REDRAW_BACKGROUND) {
    242 				/*
    243 				..................... Refresh the backdrop ......................
    244 				*/
    245 				Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
    246 				Blit_Hid_Page_To_Seen_Buff();
    247 				/*
    248 				..................... Draw the background .......................
    249 				*/
    250 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
    251 				Draw_Caption (TXT_SELECT_MPLAYER_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
    252 			}
    253 			/*
    254 			.......................... Redraw buttons ..........................
    255 			*/
    256 			if (display >= REDRAW_BUTTONS) {
    257 				commands->Flag_List_To_Redraw();
    258 			}
    259 			Show_Mouse();
    260 			display = REDRAW_NONE;
    261 		}
    262 
    263 		/*
    264 		........................... Get user input ............................
    265 		*/
    266 		input = commands->Input();
    267 
    268 		/*
    269 		............................ Process input ............................
    270 		*/
    271 		switch (input) {
    272 			case (BUTTON_MODEMSERIAL | KN_BUTTON):
    273 				selection = BUTTON_MODEMSERIAL;
    274 				pressed = true;
    275 				break;
    276 
    277 #if	(0)
    278 			case (BUTTON_INTERNET | KN_BUTTON):
    279 				selection = BUTTON_INTERNET;
    280 				pressed = true;
    281 				break;
    282 #endif	//(0)
    283 
    284 			case (BUTTON_IPX | KN_BUTTON):
    285 				selection = BUTTON_IPX;
    286 				pressed = true;
    287 				break;
    288 
    289 			case (KN_ESC):
    290 			case (BUTTON_CANCEL | KN_BUTTON):
    291 				selection = BUTTON_CANCEL;
    292 				pressed = true;
    293 				break;
    294 
    295 			case KN_UP:
    296 				buttons[curbutton]->Turn_Off();
    297 				buttons[curbutton]->Flag_To_Redraw();
    298 				curbutton--;
    299 				if (curbutton < 0)
    300 					curbutton = (number_of_buttons - 1);
    301 				buttons[curbutton]->Turn_On();
    302 				buttons[curbutton]->Flag_To_Redraw();
    303 				break;
    304 
    305 			case KN_DOWN:
    306 				buttons[curbutton]->Turn_Off();
    307 				buttons[curbutton]->Flag_To_Redraw();
    308 				curbutton++;
    309 				if (curbutton > (number_of_buttons - 1) )
    310 					curbutton = 0;
    311 				buttons[curbutton]->Turn_On();
    312 				buttons[curbutton]->Flag_To_Redraw();
    313 				break;
    314 
    315 			case KN_RETURN:
    316 				selection = curbutton + BUTTON_MODEMSERIAL;
    317 				if (!ipx_avail) selection--;
    318 				pressed = true;
    319 				break;
    320 
    321 			default:
    322 				break;
    323 		}
    324 
    325 		if (pressed) {
    326 			//
    327 			// to make sure the selection is correct in case they used the mouse
    328 			//
    329 			buttons[curbutton]->Turn_Off();
    330 			buttons[curbutton]->Flag_To_Redraw();
    331 			curbutton = selection - BUTTON_MODEMSERIAL;
    332 			buttons[curbutton]->Turn_On();
    333 //			buttons[curbutton]->Flag_To_Redraw();
    334 			buttons[curbutton]->IsPressed = true;
    335 			buttons[curbutton]->Draw_Me(true);
    336 
    337 			switch (selection) {
    338 				case (BUTTON_MODEMSERIAL):
    339 
    340 					//
    341 					// Pop up the modem/serial/com port dialog
    342 					//
    343 					retval = Select_Serial_Dialog();
    344 
    345 					if (retval != GAME_NORMAL) {
    346 						process = false;
    347 					} else {
    348 						buttons[curbutton]->IsPressed = false;
    349 						display = REDRAW_ALL;
    350 					}
    351 					break;
    352 
    353 #if	(0)
    354 				case (BUTTON_INTERNET):
    355 //#define ONLY_FOR_E3
    356 #ifdef ONLY_FOR_E3
    357 					Call_Back();
    358 					Show_Internet_Connection_Progress();		//changed to do nothing
    359 					Hide_Mouse();
    360 					Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
    361 					Blit_Hid_Page_To_Seen_Buff();
    362 					Show_Mouse();
    363 					Call_Back();
    364 					CCMessageBox().Process("Error! - Unable to ping KANE.WESTWOOD.COM");
    365 
    366 					buttons[curbutton]->IsPressed = false;
    367 					display = REDRAW_ALL;
    368 
    369 
    370 #endif	//ONLY_FOR_E3
    371 
    372 
    373 #ifdef FORCE_WINSOCK
    374 					if (Winsock.Init()){
    375 						Read_MultiPlayer_Settings ();
    376 						int result = Choose_Internet_Game();
    377 
    378 						if (!result){
    379 							Winsock.Close();
    380 							buttons[curbutton]->IsPressed = false;
    381 							display = REDRAW_ALL;
    382 							break;
    383 						}
    384 
    385 						result = Get_Internet_Host_Or_Join();
    386 						if (result == 1){
    387 							Winsock.Close();
    388 							buttons[curbutton]->IsPressed = false;
    389 							display = REDRAW_ALL;
    390 							break;
    391 						}
    392 						Server = !result;
    393 
    394 						if (Server){
    395 #if (0)
    396 							ModemGameToPlay = INTERNET_HOST;
    397 							Winsock.Start_Server();
    398 #else
    399 							result = Get_IP_Address();
    400 							if (!result){
    401 								Winsock.Close();
    402 								buttons[curbutton]->IsPressed = false;
    403 								display = REDRAW_ALL;
    404 								break;
    405 							}
    406 							Winsock.Set_Host_Address(PlanetWestwoodIPAddress);
    407 							Winsock.Start_Server();
    408 #endif
    409 
    410 						}else{
    411 							ModemGameToPlay = INTERNET_JOIN;
    412 							result = Get_IP_Address();
    413 							if (!result){
    414 								Winsock.Close();
    415 								buttons[curbutton]->IsPressed = false;
    416 								display = REDRAW_ALL;
    417 								break;
    418 							}
    419 							Winsock.Set_Host_Address(PlanetWestwoodIPAddress);
    420 							Winsock.Start_Client();
    421 						}
    422 
    423 						//CountDownTimerClass connect_timeout;
    424 						//connect_timeout.Set(15*60);
    425 
    426 						////Show_Internet_Connection_Progress();
    427 
    428 						if (!Winsock.Get_Connected()){
    429 							Winsock.Close();
    430 							return(GAME_NORMAL);
    431 						}
    432 
    433 						SerialSettingsType *settings;
    434 						settings = &SerialDefaults;
    435 						Init_Null_Modem(settings);
    436 						if (Server){
    437 							if (Com_Scenario_Dialog()){
    438 								return (GAME_INTERNET);
    439 							}else{
    440 								Winsock.Close();
    441 								return (GAME_NORMAL);
    442 							}
    443 						}else{
    444 							if (Com_Show_Scenario_Dialog()){
    445 								return (GAME_INTERNET);
    446 							}else{
    447 								Winsock.Close();
    448 								return (GAME_NORMAL);
    449 							}
    450 						}
    451 					}
    452 #endif //FORCE_WINSOCK
    453 					break;
    454 
    455 #endif	//(0)
    456 
    457 				case (BUTTON_IPX):
    458 					retval = GAME_IPX;
    459 					process = false;
    460 					break;
    461 
    462 				case (BUTTON_CANCEL):
    463 					retval = GAME_NORMAL;
    464 					process = false;
    465 					break;
    466 			}
    467 
    468 			pressed = false;
    469 		}
    470 	}
    471 	return(retval);
    472 #endif
    473 }
    474 
    475 
    476 /***********************************************************************************************
    477  * Read_MultiPlayer_Settings -- reads multi-player settings from conquer.ini                   *
    478  *                                                                                             *
    479  * INPUT:                                                                                      *
    480  *      none.                                                                                  *
    481  *                                                                                             *
    482  * OUTPUT:                                                                                     *
    483  *      none.                                                                                  *
    484  *                                                                                             *
    485  * WARNINGS:                                                                                   *
    486  *      none.                                                                                  *
    487  *                                                                                             *
    488  * HISTORY:                                                                                    *
    489  *   02/14/1995 BR : Created.                                                                  *
    490  *=============================================================================================*/
    491 void Read_MultiPlayer_Settings (void)
    492 {
    493 //PG_TO_FIX
    494 #if (0)
    495 	char *buffer;							// INI staging buffer pointer.
    496 	char *tbuffer;							// Accumulation buffer of trigger IDs.
    497 	int len;									// Length of data in buffer.
    498 	char *tokenptr;						// ptr to token
    499 	PhoneEntryClass *phone;				// a phone book entry
    500 	char *entry;							// a phone book entry
    501 	char buf[128];							// buffer for parsing INI entry
    502 	int i;
    503 	CELL cell;
    504 
    505 	/*------------------------------------------------------------------------
    506 	Fetch working pointer to the INI staging buffer. Make sure that the buffer
    507 	is cleared out before proceeding.  (Don't use the HidPage for this, since
    508 	the HidPage may be needed for various uncompressions during the INI
    509 	parsing.)
    510 	------------------------------------------------------------------------*/
    511 	buffer = (char *)_ShapeBuffer;
    512 	memset(buffer, '\0', _ShapeBufferSize);
    513 
    514 	/*------------------------------------------------------------------------
    515 	Clear the initstring entries
    516 	------------------------------------------------------------------------*/
    517 	for (i = 0; i < InitStrings.Count(); i++) {
    518 		delete[] InitStrings[i];
    519 	}
    520 	InitStrings.Clear();
    521 
    522 	/*------------------------------------------------------------------------
    523 	Clear the dialing entries
    524 	------------------------------------------------------------------------*/
    525 	for (i = 0; i < PhoneBook.Count(); i++) {
    526 		delete PhoneBook[i];
    527 	}
    528 	PhoneBook.Clear();
    529 
    530 	/*------------------------------------------------------------------------
    531 	Create filename and read the file.
    532 	------------------------------------------------------------------------*/
    533 	CCFileClass file ("CONQUER.INI");
    534 	if (!file.Is_Available()) {
    535 		return;
    536 	} else {
    537 		file.Read(buffer, _ShapeBufferSize-1);
    538 	}
    539 	file.Close();
    540 
    541 	if (!Special.IsFromWChat){
    542 		/*------------------------------------------------------------------------
    543 		Get the player's last-used Handle
    544 		------------------------------------------------------------------------*/
    545 		WWGetPrivateProfileString("MultiPlayer", "Handle", "Noname", MPlayerName,
    546 			sizeof(MPlayerName), buffer);
    547 
    548 		/*------------------------------------------------------------------------
    549 		Get the player's last-used Color
    550 		------------------------------------------------------------------------*/
    551 		MPlayerPrefColor = WWGetPrivateProfileInt("MultiPlayer", "Color", 0, buffer);
    552 		MPlayerHouse = (HousesType)WWGetPrivateProfileInt("MultiPlayer", "Side",
    553 			HOUSE_GOOD, buffer);
    554 		CurPhoneIdx = WWGetPrivateProfileInt("MultiPlayer", "PhoneIndex", -1, buffer);
    555 	}else{
    556 		CurPhoneIdx = -1;
    557 	}
    558 
    559 #if 1
    560 	TrapCheckHeap = WWGetPrivateProfileInt( "MultiPlayer", "CheckHeap", 0, buffer);
    561 #endif
    562 
    563 	/*------------------------------------------------------------------------
    564 	Read in default serial settings
    565 	------------------------------------------------------------------------*/
    566 	WWGetPrivateProfileString ("SerialDefaults", "ModemName", "NoName", SerialDefaults.ModemName, MODEM_NAME_MAX, buffer);
    567 	if (!strcmp ( SerialDefaults.ModemName, "NoName")) {
    568 		SerialDefaults.ModemName[0] = 0;
    569 	}
    570 	WWGetPrivateProfileString ("SerialDefaults", "Port", "0", buf, 5, buffer);
    571 	sscanf (buf, "%x", &SerialDefaults.Port);
    572 	SerialDefaults.IRQ = WWGetPrivateProfileInt("SerialDefaults", "IRQ", -1, buffer);
    573 	SerialDefaults.Baud = WWGetPrivateProfileInt("SerialDefaults", "Baud", -1, buffer);
    574 	SerialDefaults.Init = WWGetPrivateProfileInt("SerialDefaults", "Init", 0, buffer);
    575 	SerialDefaults.Compression = WWGetPrivateProfileInt ("SerialDefaults", "Compression", 0, buffer);
    576 	SerialDefaults.ErrorCorrection = WWGetPrivateProfileInt ("SerialDefaults", "ErrorCorrection", 0, buffer);
    577 	SerialDefaults.HardwareFlowControl = WWGetPrivateProfileInt ("SerialDefaults", "HardwareFlowControl", 1, buffer);
    578 	WWGetPrivateProfileString ("SerialDefaults", "DialMethod", "T",
    579 		buf, 2, buffer);
    580 
    581 
    582 	// find dial method
    583 
    584 	for (i = 0; i < DIAL_METHODS; i++) {
    585 		if ( !strcmpi( buf, DialMethodCheck[ i ]) ) {
    586 			SerialDefaults.DialMethod = (DialMethodType)i;
    587 			break;
    588 		}
    589 	}
    590 
    591 	// if method not found set to touch tone
    592 
    593 	if (i == DIAL_METHODS) {
    594 		SerialDefaults.DialMethod = DIAL_TOUCH_TONE;
    595 	}
    596 
    597 	SerialDefaults.InitStringIndex =
    598 											WWGetPrivateProfileInt("SerialDefaults",
    599 												"InitStringIndex", 0, buffer);
    600 
    601 	SerialDefaults.CallWaitStringIndex =
    602 											WWGetPrivateProfileInt("SerialDefaults",
    603 												"CallWaitStringIndex", CALL_WAIT_CUSTOM,
    604 												buffer);
    605 
    606 	WWGetPrivateProfileString ("SerialDefaults", "CallWaitString", "",
    607 		SerialDefaults.CallWaitString, CWAITSTRBUF_MAX, buffer);
    608 
    609 	if (SerialDefaults.IRQ == 0 ||
    610 		SerialDefaults.Baud == 0) {
    611 
    612 		SerialDefaults.Port = 0;
    613 		SerialDefaults.IRQ = -1;
    614 		SerialDefaults.Baud = -1;
    615 	}
    616 
    617 	/*------------------------------------------------------------------------
    618 	Set 'tbuffer' to point past the actual INI data
    619 	------------------------------------------------------------------------*/
    620 	len = strlen(buffer) + 2;
    621 	tbuffer = buffer + len;
    622 
    623 	/*------------------------------------------------------------------------
    624 	Read all Base-Scenario names into 'tbuffer'
    625 	------------------------------------------------------------------------*/
    626 	WWGetPrivateProfileString("InitStrings", NULL, NULL, tbuffer,
    627 		ShapeBufferSize-len, buffer);
    628 
    629 	/*------------------------------------------------------------------------
    630 	Read in & store each entry
    631 	------------------------------------------------------------------------*/
    632 	while (*tbuffer != '\0') {
    633 		entry = new char[ INITSTRBUF_MAX ];
    634 
    635 		entry[0] = 0;
    636 
    637 		WWGetPrivateProfileString("InitStrings", tbuffer, NULL, entry,
    638 			INITSTRBUF_MAX, buffer);
    639 
    640 		strupr( entry );
    641 
    642 		InitStrings.Add( entry );
    643 
    644 		tbuffer += strlen(tbuffer) + 1;
    645 	}
    646 
    647 	// if no entries then have at least one
    648 
    649 	if ( tbuffer == (buffer + len) ) {
    650 		entry = new char[ INITSTRBUF_MAX ];
    651 		strcpy( entry, "ATZ" );
    652 		InitStrings.Add( entry );
    653 		SerialDefaults.InitStringIndex = 0;
    654 	} else {
    655 		len = strlen(buffer) + 2;
    656 	}
    657 
    658 	/*------------------------------------------------------------------------
    659 	Repeat the process for the phonebook
    660 	------------------------------------------------------------------------*/
    661 	tbuffer = buffer + len;
    662 
    663 	/*------------------------------------------------------------------------
    664 	Read in all phone book listings.
    665 	Format: Name=PhoneNum,Port,IRQ,Baud,InitString
    666 	------------------------------------------------------------------------*/
    667 
    668 	/*........................................................................
    669 	Read the entry names in
    670 	........................................................................*/
    671 	WWGetPrivateProfileString("PhoneBook", NULL, NULL, tbuffer,
    672 		ShapeBufferSize-len, buffer);
    673 
    674 	while (*tbuffer != '\0') {
    675 		/*.....................................................................
    676 		Create a new phone book entry
    677 		.....................................................................*/
    678 		phone = new PhoneEntryClass();
    679 
    680 		/*.....................................................................
    681 		Read the entire entry in
    682 		.....................................................................*/
    683 		WWGetPrivateProfileString("PhoneBook", tbuffer, NULL, buf, 128, buffer);
    684 
    685 		/*.....................................................................
    686 		Extract name, phone # & serial port settings
    687 		.....................................................................*/
    688 		tokenptr = strtok( buf, "|" );
    689 		if (tokenptr) {
    690 			strcpy( phone->Name, tokenptr );
    691 			strupr( phone->Name );
    692 		} else {
    693 			phone->Name[0] = 0;
    694 		}
    695 
    696 		tokenptr = strtok( NULL, "|" );
    697 		if (tokenptr) {
    698 			strcpy( phone->Number, tokenptr );
    699 			strupr( phone->Number );
    700 		} else {
    701 			phone->Number[0] = 0;
    702 		}
    703 
    704 		tokenptr = strtok( NULL, "|" );
    705 		if (tokenptr) {
    706 			sscanf( tokenptr, "%x", &phone->Settings.Port );
    707 		} else {
    708 			phone->Settings.Port = 0;
    709 		}
    710 
    711 		tokenptr = strtok( NULL, "|" );
    712 		if (tokenptr) {
    713 			phone->Settings.IRQ = atoi( tokenptr );
    714 		} else {
    715 			phone->Settings.IRQ = -1;
    716 		}
    717 
    718 		tokenptr = strtok( NULL, "|" );
    719 		if (tokenptr) {
    720 			phone->Settings.Baud = atoi( tokenptr );
    721 		} else {
    722 			phone->Settings.Baud = -1;
    723 		}
    724 
    725 		tokenptr = strtok( NULL, "|" );
    726 		if (tokenptr) {
    727 			phone->Settings.Compression = atoi( tokenptr );
    728 		} else {
    729 			phone->Settings.Compression = 0;
    730 		}
    731 
    732 		tokenptr = strtok( NULL, "|" );
    733 		if (tokenptr) {
    734 			phone->Settings.ErrorCorrection = atoi( tokenptr );
    735 		} else {
    736 			phone->Settings.ErrorCorrection = 0;
    737 		}
    738 
    739 		tokenptr = strtok( NULL, "|" );
    740 		if (tokenptr) {
    741 			phone->Settings.HardwareFlowControl = atoi( tokenptr );
    742 		} else {
    743 			phone->Settings.HardwareFlowControl = 1;
    744 		}
    745 
    746 
    747 		tokenptr = strtok( NULL, "|" );
    748 		if (tokenptr) {
    749 			strcpy( buf, tokenptr );
    750 
    751 			// find dial method
    752 
    753 			for (i = 0; i < DIAL_METHODS; i++) {
    754 				if ( !strcmpi( buf, DialMethodCheck[ i ]) ) {
    755 					phone->Settings.DialMethod = (DialMethodType)i;
    756 					break;
    757 				}
    758 			}
    759 
    760 			// if method not found set to touch tone
    761 
    762 			if (i == DIAL_METHODS) {
    763 				phone->Settings.DialMethod = DIAL_TOUCH_TONE;
    764 			}
    765 		} else {
    766 			phone->Settings.DialMethod = DIAL_TOUCH_TONE;
    767 		}
    768 
    769 		tokenptr = strtok( NULL, "|" );
    770 		if (tokenptr) {
    771 			phone->Settings.InitStringIndex = atoi( tokenptr );
    772 		} else {
    773 			phone->Settings.InitStringIndex = 0;
    774 		}
    775 
    776 		tokenptr = strtok( NULL, "|" );
    777 		if (tokenptr) {
    778 			phone->Settings.CallWaitStringIndex = atoi( tokenptr );
    779 		} else {
    780 			phone->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;
    781 		}
    782 
    783 		tokenptr = strtok( NULL, "|" );
    784 		if (tokenptr) {
    785 			strcpy (phone->Settings.CallWaitString, tokenptr);
    786 		} else {
    787 			phone->Settings.CallWaitString[0] = 0;
    788 		}
    789 
    790 		/*.....................................................................
    791 		Add it to our list
    792 		.....................................................................*/
    793 		PhoneBook.Add(phone);
    794 
    795 		tbuffer += strlen(tbuffer) + 1;
    796 	}
    797 
    798 	/*------------------------------------------------------------------------
    799 	Read special recording playback values, to help find sync bugs
    800 	------------------------------------------------------------------------*/
    801 	if (PlaybackGame) {
    802 		TrapFrame = WWGetPrivateProfileInt ("SyncBug","Frame",0x7fffffff, buffer);
    803 
    804 		TrapObjType = (RTTIType)WWGetPrivateProfileInt ("SyncBug","Type",RTTI_NONE, buffer);
    805 		WWGetPrivateProfileString ("SyncBug","Type","NONE",buf,80,buffer);
    806 		if (!stricmp(buf,"AIRCRAFT"))
    807 			TrapObjType = RTTI_AIRCRAFT;
    808 		else if (!stricmp(buf,"ANIM"))
    809 			TrapObjType = RTTI_ANIM;
    810 		else if (!stricmp(buf,"BUILDING"))
    811 			TrapObjType = RTTI_BUILDING;
    812 		else if (!stricmp(buf,"BULLET"))
    813 			TrapObjType = RTTI_BULLET;
    814 		else if (!stricmp(buf,"INFANTRY"))
    815 			TrapObjType = RTTI_INFANTRY;
    816 		else if (!stricmp(buf,"UNIT"))
    817 			TrapObjType = RTTI_UNIT;
    818 		else {
    819 			TrapObjType = RTTI_NONE;
    820 		}
    821 
    822 		WWGetPrivateProfileString ("SyncBug","Coord","0",buf,80,buffer);
    823 		sscanf(buf,"%x",&TrapCoord);
    824 
    825 		WWGetPrivateProfileString ("SyncBug","this","0",buf,80,buffer);
    826 		sscanf(buf,"%x",&TrapThis);
    827 
    828 		WWGetPrivateProfileString ("SyncBug","Cell","0",buf,80,buffer);
    829 		cell = atoi(buf);
    830 		if (cell) {
    831 			TrapCell = &(Map[cell]);
    832 		}
    833 	}
    834 #endif
    835 }
    836 
    837 
    838 /***********************************************************************************************
    839  * Write_MultiPlayer_Settings -- writes multi-player settings to conquer.ini                   *
    840  *                                                                                             *
    841  * INPUT:                                                                                      *
    842  *      none.                                                                                  *
    843  *                                                                                             *
    844  * OUTPUT:                                                                                     *
    845  *      none.                                                                                  *
    846  *                                                                                             *
    847  * WARNINGS:                                                                                   *
    848  *      none.                                                                                  *
    849  *                                                                                             *
    850  * HISTORY:                                                                                    *
    851  *   02/14/1995 BR : Created.                                                                  *
    852  *=============================================================================================*/
    853 void Write_MultiPlayer_Settings (void)
    854 {
    855 //PG_TO_FIX
    856 #if(0)
    857 	char * buffer;			// INI staging buffer pointer.
    858 	CCFileClass file;
    859 	int i;
    860 	char entrytext[4];
    861 	char buf[128];							// buffer for parsing INI entry
    862 
    863 	/*------------------------------------------------------------------------
    864 	Get a working pointer to the INI staging buffer. Make sure that the buffer
    865 	starts cleared out of any data.
    866 	------------------------------------------------------------------------*/
    867 	buffer = (char *)_ShapeBuffer;
    868 	memset(buffer, '\0', _ShapeBufferSize);
    869 
    870 	file.Set_Name("CONQUER.INI");
    871 	if (file.Is_Available()) {
    872 		file.Open(READ);
    873 		file.Read(buffer, _ShapeBufferSize-1);
    874 		file.Close();
    875 	}
    876 
    877 	/*------------------------------------------------------------------------
    878 	Save the player's last-used Handle & Color
    879 	------------------------------------------------------------------------*/
    880 	WWWritePrivateProfileInt("MultiPlayer", "PhoneIndex", CurPhoneIdx, buffer);
    881 	WWWritePrivateProfileInt ("MultiPlayer", "Color", MPlayerPrefColor, buffer);
    882 	WWWritePrivateProfileInt ("MultiPlayer", "Side", MPlayerHouse, buffer);
    883 	WWWritePrivateProfileString("MultiPlayer", "Handle", MPlayerName, buffer);
    884 
    885 	/*------------------------------------------------------------------------
    886 	Clear all existing SerialDefault entries.
    887 	------------------------------------------------------------------------*/
    888 	WWWritePrivateProfileString ("SerialDefaults", NULL, NULL, buffer);
    889 
    890 	/*------------------------------------------------------------------------
    891 	Save default serial settings in opposite order you want to see them
    892 	------------------------------------------------------------------------*/
    893 	WWWritePrivateProfileString("SerialDefaults", "CallWaitString",
    894 		SerialDefaults.CallWaitString, buffer);
    895 	WWWritePrivateProfileInt ("SerialDefaults", "CallWaitStringIndex", SerialDefaults.CallWaitStringIndex, buffer);
    896 	WWWritePrivateProfileInt ("SerialDefaults", "InitStringIndex", SerialDefaults.InitStringIndex, buffer);
    897 	WWWritePrivateProfileInt ("SerialDefaults", "Init", SerialDefaults.Init, buffer);
    898 	WWWritePrivateProfileString("SerialDefaults", "DialMethod",
    899 		DialMethodCheck[ SerialDefaults.DialMethod ], buffer);
    900 	WWWritePrivateProfileInt ("SerialDefaults", "Baud", SerialDefaults.Baud, buffer);
    901 	WWWritePrivateProfileInt ("SerialDefaults", "IRQ", SerialDefaults.IRQ, buffer);
    902 	sprintf(buf, "%x", SerialDefaults.Port);
    903 	WWWritePrivateProfileString("SerialDefaults", "Port", buf, buffer);
    904 	WWWritePrivateProfileString("SerialDefaults", "ModemName", SerialDefaults.ModemName, buffer);
    905 	WWWritePrivateProfileInt ("SerialDefaults", "Compression", SerialDefaults.Compression , buffer);
    906 	WWWritePrivateProfileInt ("SerialDefaults", "ErrorCorrection", SerialDefaults.ErrorCorrection, buffer);
    907 	WWWritePrivateProfileInt ("SerialDefaults", "HardwareFlowControl", SerialDefaults.HardwareFlowControl, buffer);
    908 
    909 	/*------------------------------------------------------------------------
    910 	Clear all existing InitString entries.
    911 	------------------------------------------------------------------------*/
    912 	WWWritePrivateProfileString ("InitStrings", NULL, NULL, buffer);
    913 
    914 	/*------------------------------------------------------------------------
    915 	Save all InitString entries.  In descending order so they come out in
    916 	ascending order.
    917 	------------------------------------------------------------------------*/
    918 	for (i = (InitStrings.Count() - 1); i >= 0; i--) {
    919 		sprintf( buf, "%03d", i);
    920 		WWWritePrivateProfileString ("InitStrings", buf, InitStrings[i], buffer);
    921 	}
    922 
    923 	/*------------------------------------------------------------------------
    924 	Clear all existing Phone Book entries.
    925 	------------------------------------------------------------------------*/
    926 	WWWritePrivateProfileString ("PhoneBook", NULL, NULL, buffer);
    927 
    928 	/*------------------------------------------------------------------------
    929 	Save all Phone Book entries.
    930 	Format: Entry=Name,PhoneNum,Port,IRQ,Baud,InitString
    931 	------------------------------------------------------------------------*/
    932 	for (i = (PhoneBook.Count() - 1); i >= 0; i--) {
    933 		sprintf(buf,"%s|%s|%x|%d|%d|%d|%d|%d|%s|%d|%d|%s",
    934 			PhoneBook[i]->Name,
    935 			PhoneBook[i]->Number,
    936 			PhoneBook[i]->Settings.Port,
    937 			PhoneBook[i]->Settings.IRQ,
    938 			PhoneBook[i]->Settings.Baud,
    939 			PhoneBook[i]->Settings.Compression,
    940 			PhoneBook[i]->Settings.ErrorCorrection,
    941 			PhoneBook[i]->Settings.HardwareFlowControl,
    942 			DialMethodCheck[ PhoneBook[i]->Settings.DialMethod ],
    943 			PhoneBook[i]->Settings.InitStringIndex,
    944 			PhoneBook[i]->Settings.CallWaitStringIndex,
    945 			PhoneBook[i]->Settings.CallWaitString);
    946 		sprintf( entrytext, "%03d", i );
    947 		WWWritePrivateProfileString ("PhoneBook", entrytext, buf, buffer);
    948 	}
    949 
    950 	/*------------------------------------------------------------------------
    951 	Write the INI data out to a file.
    952 	------------------------------------------------------------------------*/
    953 	file.Open(WRITE);
    954 	file.Write(buffer,strlen(buffer));
    955 	file.Close();
    956 #endif
    957 }
    958 
    959 
    960 /***********************************************************************************************
    961  * Read_Scenario_Descriptions -- reads multi-player scenario #'s # descriptions                *
    962  *                                                                                             *
    963  * INPUT:                                                                                      *
    964  *      none.                                                                                  *
    965  *                                                                                             *
    966  * OUTPUT:                                                                                     *
    967  *      none.                                                                                  *
    968  *                                                                                             *
    969  * WARNINGS:                                                                                   *
    970  *      none.                                                                                  *
    971  *                                                                                             *
    972  * HISTORY:                                                                                    *
    973  *   02/14/1995 BR : Created.                                                                  *
    974  *=============================================================================================*/
    975 void Read_Scenario_Descriptions (void)
    976 {
    977 	char *buffer;							// INI staging buffer pointer.
    978 	CCFileClass file;
    979 	int i;
    980 	char fname[20];
    981 
    982 	/*------------------------------------------------------------------------
    983 	Clear the scenario description lists
    984 	------------------------------------------------------------------------*/
    985 	MPlayerScenarios.Clear();
    986 	MPlayerFilenum.Clear();
    987 
    988 	/*------------------------------------------------------------------------
    989 	Loop through all possible scenario numbers; if a file is available, add
    990 	its number to the FileNum list.
    991 	------------------------------------------------------------------------*/
    992 	for (i = 0; i < 100; i++) {
    993 		Set_Scenario_Name(ScenarioName, i, SCEN_PLAYER_MPLAYER,
    994 			SCEN_DIR_EAST, SCEN_VAR_A);
    995 		sprintf(fname,"%s.INI",ScenarioName);
    996 		file.Set_Name (fname);
    997 
    998 		if (file.Is_Available()) {
    999 			MPlayerFilenum.Add(i);
   1000 		}
   1001 	}
   1002 
   1003 	/*------------------------------------------------------------------------
   1004 	Now, for every file in the FileNum list, read in the INI file, and extract
   1005 	its description.
   1006 	------------------------------------------------------------------------*/
   1007 	for (i = 0; i < MPlayerFilenum.Count(); i++) {
   1008 		/*.....................................................................
   1009 		Fetch working pointer to the INI staging buffer. Make sure that the
   1010 		buffer is cleared out before proceeding.
   1011 		.....................................................................*/
   1012 		buffer = (char *)_ShapeBuffer;
   1013 		memset(buffer, '\0', _ShapeBufferSize);
   1014 
   1015 		/*.....................................................................
   1016 		Create filename and read the file.
   1017 		.....................................................................*/
   1018 		Set_Scenario_Name(ScenarioName, MPlayerFilenum[i], SCEN_PLAYER_MPLAYER,
   1019 			SCEN_DIR_EAST, SCEN_VAR_A);
   1020 		sprintf(fname,"%s.INI",ScenarioName);
   1021 		file.Set_Name (fname);
   1022 		file.Read(buffer, _ShapeBufferSize-1);
   1023 		file.Close();
   1024 
   1025 		/*.....................................................................
   1026 		Extract description & add it to the list.
   1027 		.....................................................................*/
   1028 		WWGetPrivateProfileString("Basic", "Name", "Nulls-Ville",
   1029 			MPlayerDescriptions[i], 40, buffer);
   1030 		MPlayerScenarios.Add(MPlayerDescriptions[i]);
   1031 	}
   1032 }
   1033 
   1034 
   1035 /***********************************************************************************************
   1036  * Free_Scenario_Descriptions -- frees memory for the scenario descriptions                    *
   1037  *                                                                                             *
   1038  * INPUT:                                                                                      *
   1039  *      none.                                                                                  *
   1040  *                                                                                             *
   1041  * OUTPUT:                                                                                     *
   1042  *      none.                                                                                  *
   1043  *                                                                                             *
   1044  * WARNINGS:                                                                                   *
   1045  *      none.                                                                                  *
   1046  *                                                                                             *
   1047  * HISTORY:                                                                                    *
   1048  *   06/05/1995 BRR : Created.                                                                 *
   1049  *=============================================================================================*/
   1050 void Free_Scenario_Descriptions(void)
   1051 {
   1052 	/*------------------------------------------------------------------------
   1053 	Clear the scenario descriptions & filenames
   1054 	------------------------------------------------------------------------*/
   1055 	MPlayerScenarios.Clear();
   1056 	MPlayerFilenum.Clear();
   1057 
   1058 //PG_TO_FIX
   1059 #if (0)
   1060 	int i;
   1061 	
   1062 	/*------------------------------------------------------------------------
   1063 	Clear the initstring entries
   1064 	------------------------------------------------------------------------*/
   1065 	for (i = 0; i < InitStrings.Count(); i++) {
   1066 		delete InitStrings[i];
   1067 	}
   1068 	InitStrings.Clear();
   1069 
   1070 	/*------------------------------------------------------------------------
   1071 	Clear the dialing entries
   1072 	------------------------------------------------------------------------*/
   1073 	for (i = 0; i < PhoneBook.Count(); i++) {
   1074 		delete PhoneBook[i];
   1075 	}
   1076 	PhoneBook.Clear();
   1077 #endif
   1078 }
   1079 
   1080 
   1081 /***************************************************************************
   1082  * Computer_Message -- "sends" a message from the computer                 *
   1083  *                                                                         *
   1084  * INPUT:                                                                  *
   1085  *      none.                                                              *
   1086  *                                                                         *
   1087  * OUTPUT:                                                                 *
   1088  *      none.                                                              *
   1089  *                                                                         *
   1090  * WARNINGS:                                                               *
   1091  *      none.                                                              *
   1092  *                                                                         *
   1093  * HISTORY:                                                                *
   1094  *   06/06/1995 BRR : Created.                                             *
   1095  *=========================================================================*/
   1096 void Computer_Message(void)
   1097 {
   1098 	int color;
   1099 	char txt[160];
   1100 	HousesType house;
   1101 	HouseClass *ptr;
   1102 
   1103 	/*------------------------------------------------------------------------
   1104 	Find the computer house that the message will be from
   1105 	------------------------------------------------------------------------*/
   1106 	for (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + MPlayerMax); house++) {
   1107 		ptr = HouseClass::As_Pointer(house);
   1108 
   1109 		if (!ptr || ptr->IsHuman || ptr->IsDefeated) {
   1110 			continue;
   1111 		}
   1112 
   1113 		/*.....................................................................
   1114 		Decode this house's color
   1115 		.....................................................................*/
   1116 		color = MPlayerTColors[ptr->RemapColor];
   1117 
   1118 		/*.....................................................................
   1119 		We now have a 1/4 chance of echoing one of the human players' messages
   1120 		back.
   1121 		.....................................................................*/
   1122 		if (IRandom(0,3) == 2) {
   1123 			/*..................................................................
   1124 			Now we have a 1/3 chance of garbling the human message.
   1125 			..................................................................*/
   1126 			if (IRandom(0,2) == 1) {
   1127 				Garble_Message(LastMessage);
   1128 			}
   1129 
   1130 			/*..................................................................
   1131 			Only add the message if there is one to add.
   1132 			..................................................................*/
   1133 			if (strlen(LastMessage)) {
   1134 				sprintf(txt,"%s %s",Text_String(TXT_FROM_COMPUTER),LastMessage);
   1135 				Messages.Add_Message(txt, color,
   1136 					TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
   1137 			}
   1138 		} else {
   1139 			sprintf(txt,"%s %s",Text_String(TXT_FROM_COMPUTER),
   1140 				Text_String(TXT_COMP_MSG1 + IRandom(0,12)));
   1141 			Messages.Add_Message(txt, color,
   1142 				TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
   1143 		}
   1144 
   1145 		return;
   1146 	}
   1147 }
   1148 
   1149 
   1150 /***************************************************************************
   1151  * Garble_Message -- "garbles" a message                                   *
   1152  *                                                                         *
   1153  * INPUT:                                                                  *
   1154  *      buf      buffer to garble; stores output message                   *
   1155  *                                                                         *
   1156  * OUTPUT:                                                                 *
   1157  *      none.                                                              *
   1158  *                                                                         *
   1159  * WARNINGS:                                                               *
   1160  *      none.                                                              *
   1161  *                                                                         *
   1162  * HISTORY:                                                                *
   1163  *   06/06/1995 BRR : Created.                                             *
   1164  *=========================================================================*/
   1165 static void Garble_Message(char *buf)
   1166 {
   1167 	char txt[80];
   1168 	char punct[20];		// for punctuation
   1169 	char *p;					// working ptr
   1170 	int numwords;			// # words in the phrase
   1171 	char *words[40];		// ptrs to various words in the phrase
   1172 	int i,j;
   1173 
   1174 	/*------------------------------------------------------------------------
   1175 	Pull off any trailing punctuation
   1176 	------------------------------------------------------------------------*/
   1177 	p = buf + strlen(buf) - 1;
   1178 	while (1) {
   1179 		if (p < buf)
   1180 			break;
   1181 		if (p[0]=='!' || p[0]=='.' || p[0]=='?') {
   1182 			p--;
   1183 		} else {
   1184 			p++;
   1185 			break;
   1186 		}
   1187 		if (strlen(p) >= (sizeof(punct) - 1) ) {
   1188 			break;
   1189 		}
   1190 	}
   1191 	strcpy (punct, p);
   1192 	p[0] = 0;
   1193 
   1194 	for (i = 0; i < 40; i++) {
   1195 		words[i] = NULL;
   1196 	}
   1197 
   1198 	/*------------------------------------------------------------------------
   1199 	Copy the original buffer
   1200 	------------------------------------------------------------------------*/
   1201 	strcpy(txt,buf);
   1202 
   1203 	/*------------------------------------------------------------------------
   1204 	Split it up into words
   1205 	------------------------------------------------------------------------*/
   1206 	p = strtok (txt, " ");
   1207 	numwords = 0;
   1208 	while (p) {
   1209 		words[numwords] = p;
   1210 		numwords++;
   1211 		p = strtok (NULL, " ");
   1212 	}
   1213 
   1214 	/*------------------------------------------------------------------------
   1215 	Now randomly put the words back.  Don't use the real random-number
   1216 	generator, since different machines will have different LastMessage's,
   1217 	and will go out of sync.
   1218 	------------------------------------------------------------------------*/
   1219 	buf[0] = 0;
   1220 	for (i = 0; i < numwords; i++) {
   1221 		j = Sim_IRandom(0,numwords);
   1222 		if (words[j] == NULL) {		// this word has been used already
   1223 			i--;
   1224 			continue;
   1225 		}
   1226 		strcat(buf,words[j]);
   1227 		words[j] = NULL;
   1228 		if (i < numwords-1)
   1229 			strcat(buf," ");
   1230 	}
   1231 	strcat(buf,punct);
   1232 }
   1233 
   1234 
   1235 /***************************************************************************
   1236  * Surrender_Dialog -- Prompts user for surrendering                       *
   1237  *                                                                         *
   1238  * INPUT:                                                                  *
   1239  *      none.                                                              *
   1240  *                                                                         *
   1241  * OUTPUT:                                                                 *
   1242  *      0 = user cancels, 1 = user wants to surrender.                     *
   1243  *                                                                         *
   1244  * WARNINGS:                                                               *
   1245  *      none.                                                              *
   1246  *                                                                         *
   1247  * HISTORY:                                                                *
   1248  *   07/05/1995 BRR : Created.                                             *
   1249  *=========================================================================*/
   1250 int Surrender_Dialog(void)
   1251 {
   1252 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
   1253 	/*........................................................................
   1254 	Dialog & button dimensions
   1255 	........................................................................*/
   1256 	int d_dialog_w = 170*factor;											// dialog width
   1257 	int d_dialog_h = 53*factor;											// dialog height
   1258 	int d_dialog_x = ((320*factor - d_dialog_w) / 2);				// centered x-coord
   1259 	int d_dialog_y = ((200*factor - d_dialog_h) / 2);				// centered y-coord
   1260 	int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);		// coord of x-center
   1261 
   1262 	int d_txt6_h = 6*factor+1;												// ht of 6-pt text
   1263 	int d_margin = 5*factor;												// margin width/height
   1264 	int d_topmargin = 20*factor;											// top margin
   1265 
   1266 	int d_ok_w = 45*factor;												// ok width
   1267 	int d_ok_h = 9*factor;													// ok height
   1268 	int d_ok_x = d_dialog_cx - d_ok_w - 5*factor;					// ok x
   1269 	int d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin;	// ok y
   1270 
   1271 	int d_cancel_w = 45*factor;											// cancel width
   1272 	int d_cancel_h = 9*factor;											// cancel height
   1273 	int d_cancel_x = d_dialog_cx + 5*factor;							// cancel x
   1274 	int d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin; // cancel y
   1275 
   1276 
   1277 	/*........................................................................
   1278 	Button enumerations
   1279 	........................................................................*/
   1280 	enum {
   1281 		BUTTON_OK = 100,
   1282 		BUTTON_CANCEL,
   1283 	};
   1284 
   1285 	/*........................................................................
   1286 	Redraw values: in order from "top" to "bottom" layer of the dialog
   1287 	........................................................................*/
   1288 	typedef enum {
   1289 		REDRAW_NONE = 0,
   1290 		REDRAW_BUTTONS,
   1291 		REDRAW_BACKGROUND,
   1292 		REDRAW_ALL = REDRAW_BACKGROUND
   1293 	} RedrawType;
   1294 
   1295 	/*........................................................................
   1296 	Dialog variables
   1297 	........................................................................*/
   1298 	RedrawType display;							// requested redraw level
   1299 	bool process;									// loop while true
   1300 	KeyNumType input;
   1301 	int retcode;
   1302 
   1303 	/*........................................................................
   1304 	Buttons
   1305 	........................................................................*/
   1306 	ControlClass *commands = NULL;		// the button list
   1307 
   1308 	TextButtonClass okbtn (BUTTON_OK, TXT_OK,
   1309 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   1310 		d_ok_x, d_ok_y, d_ok_w, d_ok_h);
   1311 
   1312 	TextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL,
   1313 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   1314 		d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
   1315 
   1316 	/*
   1317 	------------------------------- Initialize -------------------------------
   1318 	*/
   1319 	Set_Logic_Page(SeenBuff);
   1320 
   1321 	/*
   1322 	......................... Create the button list .........................
   1323 	*/
   1324 	commands = &okbtn;
   1325 	cancelbtn.Add_Tail(*commands);
   1326 
   1327 	/*
   1328 	-------------------------- Main Processing Loop --------------------------
   1329 	*/
   1330 	display = REDRAW_ALL;
   1331 	process = true;
   1332 	while (process) {
   1333 
   1334 		/*
   1335 		** If we have just received input focus again after running in the background then
   1336 		** we need to redraw.
   1337 		*/
   1338 		if (AllSurfaces.SurfacesRestored){
   1339 			AllSurfaces.SurfacesRestored=FALSE;
   1340 			display=REDRAW_ALL;
   1341 		}
   1342 
   1343 		/*
   1344 		........................ Invoke game callback .........................
   1345 		*/
   1346 		if (Main_Loop()) {
   1347 			retcode = 0;
   1348 			process = false;
   1349 		}
   1350 
   1351 		/*
   1352 		...................... Refresh display if needed ......................
   1353 		*/
   1354 		if (display) {
   1355 
   1356 			/*
   1357 			...................... Display the dialog box ......................
   1358 			*/
   1359 			Hide_Mouse();
   1360 			if (display >= REDRAW_BACKGROUND) {
   1361 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
   1362 				Draw_Caption(TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
   1363 
   1364 				/*
   1365 				....................... Draw the captions .......................
   1366 				*/
   1367 				Fancy_Text_Print(Text_String(TXT_SURRENDER),
   1368 					d_dialog_cx, d_dialog_y + d_topmargin,
   1369 					CC_GREEN, TBLACK,
   1370 					TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1371 			}
   1372 
   1373 			/*
   1374 			........................ Redraw the buttons ........................
   1375 			*/
   1376 			if (display >= REDRAW_BUTTONS) {
   1377 				commands->Flag_List_To_Redraw();
   1378 			}
   1379 			Show_Mouse();
   1380 			display = REDRAW_NONE;
   1381 		}
   1382 
   1383 		/*
   1384 		........................... Get user input ............................
   1385 		*/
   1386 		input = commands->Input();
   1387 
   1388 		/*
   1389 		............................ Process input ............................
   1390 		*/
   1391 		switch (input) {
   1392 			case (KN_RETURN):
   1393 			case (BUTTON_OK | KN_BUTTON):
   1394 				retcode = 1;
   1395 				process = false;
   1396 				break;
   1397 
   1398 			case (KN_ESC):
   1399 			case (BUTTON_CANCEL | KN_BUTTON):
   1400 				retcode = 0;
   1401 				process = false;
   1402 				break;
   1403 
   1404 			default:
   1405 				break;
   1406 		}
   1407 	}
   1408 
   1409 	/*
   1410 	--------------------------- Redraw the display ---------------------------
   1411 	*/
   1412 	HiddenPage.Clear();
   1413 	Map.Flag_To_Redraw(true);
   1414 	Map.Render();
   1415 
   1416 	return (retcode);
   1417 }