W32COMM.C
上传用户:kesirui
上传日期:2007-01-07
资源大小:263k
文件大小:42k
源码类别:

Internet/网络编程

开发平台:

WINDOWS

  1. #include <time.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <windows.h>
  5. #include "merc.h"
  6. #include "merc-win.rh"
  7. /*
  8.  * Global variables.
  9.  */
  10. DESCRIPTOR_DATA *   descriptor_free; /* Free list for descriptors */
  11. DESCRIPTOR_DATA *   descriptor_list; /* All open descriptors */
  12. DESCRIPTOR_DATA *   d_next; /* Next descriptor in loop */
  13. FILE *     fpReserve; /* Reserved file handle */
  14. bool     god; /* All new chars are gods! */
  15. bool     merc_down; /* Shutdown */
  16. bool     wizlock; /* Game is wizlocked */
  17. char     str_boot_time[MAX_INPUT_LENGTH];
  18. time_t     current_time; /* Time of this pulse */
  19. /*
  20.  * Other local functions (OS-independent).
  21.  */
  22. bool check_parse_name args( ( char *name ) );
  23. bool check_reconnect args( ( DESCRIPTOR_DATA *d, char *name,
  24.     bool fConn ) );
  25. bool check_playing args( ( DESCRIPTOR_DATA *d, char *name ) );
  26. int main args( ( int argc, char **argv ) );
  27. void nanny args( ( DESCRIPTOR_DATA *d, char *argument ) );
  28. bool process_output args( ( DESCRIPTOR_DATA *d, bool fPrompt ) );
  29. void read_from_buffer args( ( DESCRIPTOR_DATA *d ) );
  30. void stop_idling args( ( CHAR_DATA *ch ) );
  31. void    bust_a_prompt           args( ( CHAR_DATA *ch ) );
  32. // @@@ My junk
  33. char      UserMessage[512];
  34. BOOL      fUserReady;
  35. //#define crypt(d,s) strcpy(d,s)
  36. const char echo_off_str [] = { '' };
  37. const char echo_on_str [] = { '' };
  38. const char  go_ahead_str [] = { '' };
  39. bool write_to_descriptor args( ( int desc, char *txt, int length ) );
  40. void send_to_char args( ( const char *txt, CHAR_DATA *ch ) )
  41. {
  42.     if ( txt == NULL || ch->desc == NULL )
  43.         return;
  44.     ch->desc->showstr_head = alloc_mem( strlen( txt ) + 1 );
  45.     strcpy( ch->desc->showstr_head, txt );
  46.     ch->desc->showstr_point = ch->desc->showstr_head;
  47.     show_string( ch->desc, "" );
  48. }
  49. void gettimeofday( struct timeval *tp, void *tzp )
  50. {
  51.     tp->tv_sec  = time( NULL );
  52.     tp->tv_usec = 0;
  53. }
  54. bool read_from_descriptor( DESCRIPTOR_DATA *d )
  55. {
  56.     int iStart;
  57.     /* Hold horses if pending command already. */
  58.     if ( d->incomm[0] != '' )
  59. return TRUE;
  60.     /* Check for overflow. */
  61.     iStart = strlen(d->inbuf);
  62.     if ( iStart >= sizeof(d->inbuf) - 10 )
  63.     {
  64. sprintf( log_buf, "%s input overflow!", d->host );
  65. log_string( log_buf );
  66. write_to_descriptor( d->descriptor,
  67.     "nr*** PUT A LID ON IT!!! ***nr", 0 );
  68. return FALSE;
  69.     }
  70. #if 0
  71.     /* Snarf input. */
  72.     for ( ; ; )
  73.     {
  74. int c;
  75. c = getc( stdin );
  76. if ( c == '' || c == EOF )
  77.     break;
  78. putc( c, stdout );
  79. if ( c == 'r' )
  80.     putc( 'n', stdout );
  81. d->inbuf[iStart++] = c;
  82. if ( iStart > sizeof(d->inbuf) - 10 )
  83.     break;
  84.     }
  85. #else
  86.     if (fUserReady)
  87.        {
  88.        int nLen = strlen(UserMessage);
  89.        fUserReady = FALSE;
  90.        if (iStart + nLen <= sizeof d->inbuf - 10)
  91.           {
  92.           memcpy(d->inbuf + iStart, UserMessage, nLen);
  93.           iStart += nLen;
  94.           d->inbuf[iStart++] = 'r';
  95.           }
  96.        }
  97. #endif
  98.     d->inbuf[iStart] = '';
  99.     return TRUE;
  100. }
  101. /*
  102.  * Transfer one line from input buffer to input line.
  103.  */
  104. void read_from_buffer( DESCRIPTOR_DATA *d )
  105. {
  106.     int i, j, k;
  107.     /*
  108.      * Hold horses if pending command already.
  109.      */
  110.     if ( d->incomm[0] != '' )
  111. return;
  112.     /*
  113.      * Look for at least one new line.
  114.      */
  115.     for ( i = 0; d->inbuf[i] != 'n' && d->inbuf[i] != 'r'; i++ )
  116.     {
  117. if ( d->inbuf[i] == '' )
  118.     return;
  119.     }
  120.     /*
  121.      * Canonical input processing.
  122.      */
  123.     for ( i = 0, k = 0; d->inbuf[i] != 'n' && d->inbuf[i] != 'r'; i++ )
  124.     {
  125. if ( k >= MAX_INPUT_LENGTH - 2 )
  126. {
  127.     write_to_descriptor( d->descriptor, "Line too long.nr", 0 );
  128.     /* skip the rest of the line */
  129.     for ( ; d->inbuf[i] != ''; i++ )
  130.     {
  131. if ( d->inbuf[i] == 'n' || d->inbuf[i] == 'r' )
  132.     break;
  133.     }
  134.     d->inbuf[i]   = 'n';
  135.     d->inbuf[i+1] = '';
  136.     break;
  137. }
  138. if ( d->inbuf[i] == 'b' && k > 0 )
  139.     --k;
  140. else if ( isascii(d->inbuf[i]) && isprint(d->inbuf[i]) )
  141.     d->incomm[k++] = d->inbuf[i];
  142.     }
  143.     /*
  144.      * Finish off the line.
  145.      */
  146.     if ( k == 0 )
  147. d->incomm[k++] = ' ';
  148.     d->incomm[k] = '';
  149.     /*
  150.      * Deal with bozos with #repeat 1000 ...
  151.      */
  152.     if ( k > 1 || d->incomm[0] == '!' )
  153.     {
  154.      if ( d->incomm[0] != '!' && strcmp( d->incomm, d->inlast ) )
  155. {
  156.     d->repeat = 0;
  157. }
  158. else
  159. {
  160.     if ( ++d->repeat >= 20 )
  161.     {
  162. sprintf( log_buf, "%s input spamming!", d->host );
  163. log_string( log_buf );
  164. write_to_descriptor( d->descriptor,
  165.     "nr*** PUT A LID ON IT!!! ***nr", 0 );
  166. strcpy( d->incomm, "quit" );
  167.     }
  168. }
  169.     }
  170.     /*
  171.      * Do '!' substitution.
  172.      */
  173.     if ( d->incomm[0] == '!' )
  174. strcpy( d->incomm, d->inlast );
  175.     else
  176. strcpy( d->inlast, d->incomm );
  177.     /*
  178.      * Shift the input buffer.
  179.      */
  180.     while ( d->inbuf[i] == 'n' || d->inbuf[i] == 'r' )
  181. i++;
  182.     for ( j = 0; ( d->inbuf[j] = d->inbuf[i+j] ) != ''; j++ )
  183. ;
  184.     return;
  185. }
  186. void CloseMerc(void)
  187. {
  188. }
  189. HINSTANCE hInst;
  190. HWND      hQryDlgBox;                         // handle of modeless dialog box
  191. HWND      hWndMain;
  192. HWND      hWndOutput;
  193. char      UserMessage[512];
  194. BOOL      fUserReady;
  195. LRESULT CALLBACK _export MercWndProc(HWND hWnd, UINT message,
  196.                              WPARAM wParam, LPARAM lParam)
  197. {
  198.     switch (message)
  199.     {
  200.         case WM_MOVE:
  201.             // Move the dialog box on top of our main window every
  202.             // time the main window moves.
  203.             if (IsWindow(hQryDlgBox))
  204.                 SendMessage(hQryDlgBox, message, wParam, lParam);
  205.             break;
  206.         case WM_SETFOCUS:
  207.             // Always set the input focus to the dialog box.
  208.             if (IsWindow(hQryDlgBox))
  209.                 SendMessage(hQryDlgBox, message, wParam, lParam);
  210.             break;
  211.         case WM_CLOSE:
  212.             // Tell windows to destroy our window.
  213.             DestroyWindow(hWnd);
  214.             break;
  215.         case WM_QUERYENDSESSION:
  216.             // If we return TRUE we are saying it's ok with us to end the
  217. // windows session.
  218.             return((long) TRUE);  // we agree to end session.
  219.         case WM_ENDSESSION:
  220.             // If wParam is not zero, it meany every application said ok
  221.             // to WM_QUERYENDSESSION messages, so we are really ending.
  222.             if (wParam)           // if all apps aggreed to end session.
  223.                 CloseMerc();     // This is the end. We will not get a
  224.                                    // WM_DESTROY message on end session.
  225.             break;
  226.         case WM_DESTROY:
  227.             // This is the end if we were closed by a DestroyWindow call.
  228.             CloseMerc();
  229. PostQuitMessage(0);
  230.             break;
  231.         default:
  232.             return(DefWindowProc(hWnd, message, wParam, lParam));
  233.     }
  234.     return(0L);
  235. }
  236. BOOL CALLBACK _export MercDlgProc(HWND hDlg, UINT message,
  237.                            WPARAM wParam, LPARAM lParam)
  238. {
  239.     static RECT   wrect;
  240.     int           x, y, w, h, i;
  241.     long          rc;
  242. //    char         *cp, *cpd, tmp[30], sdrives[30];
  243. //    HANDLE        hCursor;
  244.     HWND hWndInput;
  245.     switch (message)
  246.     {
  247.         case WM_INITDIALOG:
  248.             // Save the handle of this proc for use by main window proc.
  249.             hQryDlgBox = hDlg;
  250.             // Save the handle to the output window
  251.             hWndOutput = GetDlgItem(hDlg, 102);
  252.             SendMessage(hWndOutput, WM_SETFONT,
  253.                (WPARAM) GetStockObject(SYSTEM_FIXED_FONT), 0);
  254.             SetFocus(GetDlgItem(hDlg, 101));
  255.             // Get position of dialog box window.
  256.             GetWindowRect(hDlg, (LPRECT) &wrect);
  257.             w = wrect.right - wrect.left;
  258.             h = wrect.bottom - wrect.top;
  259.             // Move main application window to same position.
  260.             SetWindowPos(hWndMain, hDlg,
  261.                          wrect.left, wrect.top, w, h,
  262.                          0);
  263.             break;
  264.         case WM_MOVE:
  265.             // Always keep this dialog box on top of main window.
  266.             GetWindowRect(hWndMain, (LPRECT) &wrect);
  267.             x = wrect.left;
  268.             y = wrect.top;
  269.             w = wrect.right - wrect.left;
  270.             h = wrect.bottom - wrect.top;
  271.             MoveWindow(hDlg, x, y, w, h, 1);
  272.             break;
  273.         case WM_SYSCOMMAND:
  274.             // Pass WM_SYSCOMMAND messages on to main window so both
  275.             // main window and dialog box get iconized, minimized etc.
  276.             // in parallel.
  277.             SendMessage(hWndMain, message, wParam, lParam);
  278.             break;
  279.         case WM_COMMAND:
  280.             switch (LOWORD(wParam))
  281.             {
  282.                 case IDOK:
  283.                     hWndInput = GetDlgItem(hDlg, 101);
  284.                     SendMessage(hWndInput, WM_GETTEXT, sizeof UserMessage, (LPARAM) UserMessage);
  285.                     SendMessage(hWndInput, WM_SETTEXT, 0, (LPARAM) "");
  286.                     SetFocus(hWndInput);
  287.                     fUserReady = TRUE;
  288.                     break;
  289.                 case IDCANCEL:                  // Cancel button
  290.                     // Tell main application window we want to quit.
  291.                     SendMessage(hWndMain, WM_CLOSE, 0, 0L);
  292.                     break;
  293.                 default:
  294.                     break;
  295.             }
  296.             break;
  297.         case WM_CLOSE:
  298.             // Unlock dialog resource we locked above.
  299.             // Zero handle to this dialog window.
  300.             hQryDlgBox = 0;
  301.             // Tell main window to close.
  302.             PostMessage(hWndMain, WM_CLOSE, 0, 0L);
  303.             // Destroy ourseleves.
  304.             DestroyWindow(hDlg);
  305.             break;
  306.         default:
  307.             return FALSE;
  308.     }
  309.     return(TRUE);
  310. }
  311. void InitMerc22(HINSTANCE hInstance, int cmdShow)
  312. {
  313.     WNDCLASS wcMercClass;
  314.     // Define the window class for this application.
  315.     wcMercClass.lpszClassName = "Merc22";
  316.     wcMercClass.hInstance     = hInstance;
  317.     wcMercClass.lpfnWndProc   = MercWndProc;
  318.     wcMercClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  319. //    wcMercClass.hIcon         = LoadIcon(hInstance, SetUpData.szAppName);
  320.     wcMercClass.hIcon         = 0;
  321.     wcMercClass.lpszMenuName  = (LPSTR) NULL;
  322.     wcMercClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  323.     wcMercClass.style         = CS_HREDRAW | CS_VREDRAW;
  324.     wcMercClass.cbClsExtra    = 0;
  325.     wcMercClass.cbWndExtra    = 0;
  326.     // Register the class
  327.     if (RegisterClass(&wcMercClass) == 0)
  328.        {
  329.        MessageBox(0, "Could not create Window", "@@@", MB_ICONHAND|MB_OK);
  330.        exit(1);
  331.        }
  332.     hInst = hInstance;       // save for use by window procs
  333.     // Create applications main window.
  334.     hWndMain = CreateWindow(
  335.                   "Merc22",
  336.                   "Welcome to Merc22/Win32",
  337.                     WS_BORDER |
  338.                     WS_CAPTION |
  339.                     WS_SYSMENU |
  340.                     WS_MINIMIZEBOX,
  341.                   10,
  342.                   19,
  343.                   256,
  344.                   123,
  345.                   NULL,
  346.                   NULL,
  347.                   hInstance,
  348.                   NULL
  349.                   );
  350.     CreateDialog(hInst, MAKEINTRESOURCE(1), hWndMain, (DLGPROC) MercDlgProc);
  351.     ShowWindow(hWndMain, cmdShow);
  352.     UpdateWindow(hWndMain);
  353. }
  354. int SpinTheMessageLoop()
  355. {
  356.    MSG msg;
  357.    if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
  358.       {
  359.       if (msg.message == WM_QUIT)
  360.          return FALSE;
  361.       if (!IsDialogMessage(hQryDlgBox, &msg))
  362.          {
  363.          TranslateMessage(&msg);
  364.          DispatchMessage(&msg);
  365.          }
  366.       }
  367.    return TRUE;
  368. }
  369. WPARAM game_loop_win32(HINSTANCE hInstance, HINSTANCE hPrevInstance, int nCmdShow)
  370. {
  371.     static DESCRIPTOR_DATA dcon;
  372.     DESCRIPTOR_DATA *d;
  373.     MSG   msg;
  374.     DWORD dwTick = 0;
  375.     int   fBackground;
  376. extern char * help_greeting;
  377.     /*
  378.      * New_descriptor analogue.
  379.      */
  380.     dcon.descriptor = 0;
  381.     dcon.connected = CON_GET_NAME;
  382.     dcon.host = str_dup( "localhost" );
  383.     dcon.outsize = 2000;
  384.     dcon.outbuf = alloc_mem( dcon.outsize );
  385.     dcon.next = descriptor_list;
  386.     descriptor_list = &dcon;
  387.     /*
  388.      * Send the greeting.
  389.      */
  390. if ( help_greeting[0] == '.' )
  391.     write_to_buffer( &dcon, help_greeting+1, 0 );
  392. else
  393.     write_to_buffer( &dcon, help_greeting  , 0 );
  394.     /* Main loop */
  395.     // Go init this application.
  396.     InitMerc22(hInstance, nCmdShow);
  397.     // Get and dispatch messages for this applicaton.
  398.     fBackground = FALSE;
  399.     for ( ;; )
  400.         {
  401.         // Always give Windows messages priority over Merc execution
  402.         if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
  403.             {
  404.             if (msg.message == WM_QUIT)
  405.                break;
  406.             if (!IsDialogMessage(hQryDlgBox, &msg))
  407.                {
  408.                TranslateMessage(&msg);
  409.                DispatchMessage(&msg);
  410.                }
  411.             }
  412.        else if (!fBackground)
  413.           {
  414.           fBackground++;
  415.     time( &current_time );
  416. /*
  417.  * Autonomous game motion.
  418.  * (Synchronize to a clock.
  419.  * Busy wait (blargh).)
  420.  */
  421.     if (GetTickCount() - dwTick >= 1000 / PULSE_PER_SECOND)
  422.        {
  423.        dwTick = GetTickCount();
  424. /*
  425.  * Process input.
  426.  */
  427. for ( d = descriptor_list; d != NULL; d = d_next )
  428.    {
  429.        // Give Windows a change to run other programs
  430. //       if (!SpinTheMessageLoop())
  431. //          goto merc_done;
  432.    d_next = d->next;
  433.    d->fcommand = FALSE;
  434.    if ( d->character != NULL )
  435.         d->character->timer = 0;
  436.        // Did the user break connection?
  437.    if ( !read_from_descriptor( d ) )
  438.       {
  439.     if ( d->character != NULL )
  440. save_char_obj( d->character );
  441.     d->outtop = 0;
  442.     close_socket( d );
  443.     continue;
  444.     }
  445.     if ( d->character != NULL && d->character->wait > 0 )
  446.         {
  447.     --d->character->wait;
  448.     continue;
  449.         }
  450.     read_from_buffer( d );
  451.     if ( d->incomm[0] != '' )
  452.     {
  453. d->fcommand = TRUE;
  454. stop_idling( d->character );
  455. if ( d->connected == CON_PLAYING )
  456.     if ( d->showstr_point )
  457.         show_string( d, d->incomm );
  458.     else
  459.         interpret( d->character, d->incomm );
  460. else
  461.     nanny( d, d->incomm );
  462. d->incomm[0] = '';
  463.     }
  464.    }
  465.        update_handler( );
  466. /*
  467.  * Output.
  468.  */
  469. for ( d = descriptor_list; d != NULL; d = d_next )
  470. {
  471.        // Give Windows a change to run other programs
  472. //       if (!SpinTheMessageLoop())
  473. //          goto merc_done;
  474.     d_next = d->next;
  475.     if ( ( d->fcommand || d->outtop > 0 ) )
  476.     {
  477. if ( !process_output( d, TRUE ) )
  478. {
  479.     if ( d->character != NULL )
  480. save_char_obj( d->character );
  481.     d->outtop = 0;
  482.     close_socket( d );
  483. }
  484.     }
  485. }
  486. #if 0
  487. now_time = last_time;
  488. for ( ; ; )
  489. {
  490.     int delta;
  491.     {
  492. if ( dcon.character != NULL )
  493.     dcon.character->timer = 0;
  494. if ( !read_from_descriptor( &dcon ) )
  495. {
  496.     if ( dcon.character != NULL )
  497. save_char_obj( d->character );
  498.     dcon.outtop = 0;
  499.     close_socket( &dcon );
  500. }
  501. #if defined(MSDOS)
  502. break;
  503. #endif
  504.     }
  505.     gettimeofday( &now_time, NULL );
  506.     delta = ( now_time.tv_sec  - last_time.tv_sec  ) * 1000 * 1000
  507.   + ( now_time.tv_usec - last_time.tv_usec );
  508.     if ( delta >= 1000000 / PULSE_PER_SECOND )
  509. break;
  510. }
  511. last_time    = now_time;
  512. current_time = (time_t) last_time.tv_sec;
  513. #endif
  514.        }
  515.    fBackground--;
  516.           }
  517.        }
  518. merc_done:
  519.     return(msg.wParam);
  520. }
  521. //int main( int argc, char **argv )
  522. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpszCmdLine, int nCmdShow)
  523. {
  524.     struct timeval now_time;
  525. //    int port;
  526. #if defined(unix)
  527.     int control;
  528. #endif
  529.     /*
  530.      * Memory debugging if needed.
  531.      */
  532. #if defined(MALLOC_DEBUG)
  533.     malloc_debug( 2 );
  534. #endif
  535.     /*
  536.      * Init time.
  537.      */
  538.     gettimeofday( &now_time, NULL );
  539.     current_time = (time_t) now_time.tv_sec;
  540.     strcpy( str_boot_time, ctime( &current_time ) );
  541.     /*
  542.      * Macintosh console initialization.
  543.      */
  544. #if defined(macintosh)
  545.     console_options.nrows = 31;
  546.     cshow( stdout );
  547.     csetmode( C_RAW, stdin );
  548.     cecho2file( "log file", 1, stderr );
  549. #endif
  550. #if 0
  551.     /*
  552.      * Reserve one channel for our use.
  553.      */
  554.     if ( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL )
  555.     {
  556. perror( NULL_FILE );
  557. return 1;
  558.     }
  559. #endif
  560. #if 0
  561.     /*
  562.      * Get the port number.
  563.      */
  564.     port = 1234;
  565.     if ( lpszCmdLine[0] )
  566.     {
  567. if ( !is_number( lpszCmdLine ) )
  568. {
  569.     fprintf( stderr, "Usage: WinMerc [port #]n" );
  570.     return 1;
  571. }
  572. else if ( ( port = atoi( lpszCmdLine ) ) <= 1024 )
  573. {
  574.     fprintf( stderr, "Port number must be above 1024.n" );
  575.     return 1;
  576. }
  577.     }
  578. #endif
  579. #if 0
  580.     /*
  581.      * Run the game.
  582.      */
  583. #if defined(macintosh) || defined(MSDOS)
  584.     boot_db( );
  585.     log_string( "Merc is ready to rock." );
  586.     game_loop_mac_msdos( );
  587. #endif
  588. #if defined(unix)
  589.     control = init_socket( port );
  590.     boot_db( );
  591.     sprintf( log_buf, "Merc is ready to rock on port %d.", port );
  592.     log_string( log_buf );
  593.     game_loop_unix( control );
  594.     close( control );
  595. #endif
  596. #else
  597.     boot_db( );
  598. //    MessageBox(0, "Merc is ready to rock", "@@@", MB_ICONINFORMATION|MB_OK);
  599.     log_string( "Merc is ready to rock." );
  600.     game_loop_win32(hInstance, hPrev, nCmdShow);
  601. #endif
  602.     /*
  603.      * That's all, folks.
  604.      */
  605.     log_string( "Normal termination of game." );
  606.     return 0;
  607. }
  608. // @@@ Orig junk
  609. /*
  610.  * The primary output interface for formatted output.
  611.  */
  612. void act( const char *format, CHAR_DATA *ch, const void *arg1,
  613.  const void *arg2, int type )
  614. {
  615.     static char * const he_she [] = { "it",  "he",  "she" };
  616.     static char * const him_her [] = { "it",  "him", "her" };
  617.     static char * const his_her [] = { "its", "his", "her" };
  618.     char buf[MAX_STRING_LENGTH];
  619.     char fname[MAX_INPUT_LENGTH];
  620.     CHAR_DATA *to;
  621.     CHAR_DATA *vch = (CHAR_DATA *) arg2;
  622.     OBJ_DATA *obj1 = (OBJ_DATA  *) arg1;
  623.     OBJ_DATA *obj2 = (OBJ_DATA  *) arg2;
  624.     const char *str;
  625.     const char *i;
  626.     char *point;
  627.     /*
  628.      * Discard null and zero-length messages.
  629.      */
  630.     if ( format == NULL || format[0] == '' )
  631. return;
  632.     to = ch->in_room->people;
  633.     if ( type == TO_VICT )
  634.     {
  635. if ( vch == NULL )
  636. {
  637.     bug( "Act: null vch with TO_VICT.", 0 );
  638.     return;
  639. }
  640. to = vch->in_room->people;
  641.     }
  642.     
  643.     for ( ; to != NULL; to = to->next_in_room )
  644.     {
  645. if ( ( to->desc == NULL 
  646.     && ( IS_NPC( to ) && !(to->pIndexData->progtypes & ACT_PROG ) ) )
  647.     || !IS_AWAKE(to) )
  648.     continue;
  649. if ( type == TO_CHAR && to != ch )
  650.     continue;
  651. if ( type == TO_VICT && ( to != vch || to == ch ) )
  652.     continue;
  653. if ( type == TO_ROOM && to == ch )
  654.     continue;
  655. if ( type == TO_NOTVICT && (to == ch || to == vch) )
  656.     continue;
  657. point = buf;
  658. str = format;
  659. while ( *str != '' )
  660. {
  661.     if ( *str != '$' )
  662.     {
  663. *point++ = *str++;
  664. continue;
  665.     }
  666.     ++str;
  667.     if ( arg2 == NULL && *str >= 'A' && *str <= 'Z' )
  668.     {
  669. bug( "Act: missing arg2 for code %d.", *str );
  670. i = " <@@@> ";
  671.     }
  672.     else
  673.     {
  674. switch ( *str )
  675. {
  676. default:  bug( "Act: bad code %d.", *str );
  677.   i = " <@@@> "; break;
  678. /* Thx alex for 't' idea */
  679. case 't': i = (char *) arg1; break;
  680. case 'T': i = (char *) arg2;           break;
  681. case 'n': i = PERS( ch,  to  ); break;
  682. case 'N': i = PERS( vch, to  ); break;
  683. case 'e': i = he_she  [URANGE(0, ch  ->sex, 2)]; break;
  684. case 'E': i = he_she  [URANGE(0, vch ->sex, 2)]; break;
  685. case 'm': i = him_her [URANGE(0, ch  ->sex, 2)]; break;
  686. case 'M': i = him_her [URANGE(0, vch ->sex, 2)]; break;
  687. case 's': i = his_her [URANGE(0, ch  ->sex, 2)]; break;
  688. case 'S': i = his_her [URANGE(0, vch ->sex, 2)]; break;
  689. case 'p':
  690.     i = can_see_obj( to, obj1 )
  691.     ? obj1->short_descr
  692.     : "something";
  693.     break;
  694. case 'P':
  695.     i = can_see_obj( to, obj2 )
  696.     ? obj2->short_descr
  697.     : "something";
  698.     break;
  699. case 'd':
  700.     if ( arg2 == NULL || ((char *) arg2)[0] == '' )
  701.     {
  702. i = "door";
  703.     }
  704.     else
  705.     {
  706. one_argument( (char *) arg2, fname );
  707. i = fname;
  708.     }
  709.     break;
  710. }
  711.     }
  712.     ++str;
  713.     while ( ( *point = *i ) != '' )
  714. ++point, ++i;
  715. }
  716. *point++ = 'n';
  717. *point++ = 'r';
  718. buf[0]   = UPPER(buf[0]);
  719. if (to->desc)
  720.   write_to_buffer( to->desc, buf, point - buf );
  721. if (MOBtrigger)
  722.   mprog_act_trigger( buf, to, ch, obj1, vch );
  723.                                             /* Added by Kahn */
  724.     }
  725.     MOBtrigger = TRUE;
  726.     return;
  727. }
  728. /*
  729.  * Append onto an output buffer.
  730.  */
  731. void write_to_buffer( DESCRIPTOR_DATA *d, const char *txt, int length )
  732. {
  733.     /* @@@ ECS */
  734.     if (d == 0)
  735.        return;
  736.        
  737.     /*
  738.      * Find length in case caller didn't.
  739.      */
  740.     if ( length <= 0 )
  741. length = strlen(txt);
  742.     /*
  743.      * Initial nr if needed.
  744.      */
  745.     if ( d->outtop == 0 && !d->fcommand )
  746.     {
  747. d->outbuf[0] = 'n';
  748. d->outbuf[1] = 'r';
  749. d->outtop = 2;
  750.     }
  751.     /*
  752.      * Expand the buffer as needed.
  753.      */
  754.     while ( d->outtop + length >= d->outsize )
  755.     {
  756. char *outbuf;
  757. outbuf      = alloc_mem( 2 * d->outsize );
  758. strncpy( outbuf, d->outbuf, d->outtop );
  759. free_mem( d->outbuf, d->outsize );
  760. d->outbuf   = outbuf;
  761. d->outsize *= 2;
  762.     }
  763.     /*
  764.      * Copy.
  765.      */
  766.     strcpy( d->outbuf + d->outtop, txt );
  767.     d->outtop += length;
  768.     return;
  769. }
  770. void close_socket( DESCRIPTOR_DATA *dclose )
  771. {
  772.     CHAR_DATA *ch;
  773.     if ( dclose->outtop > 0 )
  774. process_output( dclose, FALSE );
  775.     if ( dclose->snoop_by != NULL )
  776.     {
  777. write_to_buffer( dclose->snoop_by,
  778.     "Your victim has left the game.nr", 0 );
  779.     }
  780.     {
  781. DESCRIPTOR_DATA *d;
  782. for ( d = descriptor_list; d != NULL; d = d->next )
  783. {
  784.     if ( d->snoop_by == dclose )
  785. d->snoop_by = NULL;
  786. }
  787.     }
  788.     if ( ( ch = dclose->character ) != NULL )
  789.     {
  790. sprintf( log_buf, "Closing link to %s.", ch->name );
  791. log_string( log_buf );
  792. if ( dclose->connected == CON_PLAYING )
  793. {
  794.     act( "$n has lost $s link.", ch, NULL, NULL, TO_ROOM );
  795.     ch->desc = NULL;
  796. }
  797. else
  798. {
  799.     free_char( dclose->character );
  800. }
  801.     }
  802.     if ( d_next == dclose )
  803. d_next = d_next->next;
  804.     if ( dclose == descriptor_list )
  805.     {
  806. descriptor_list = descriptor_list->next;
  807.     }
  808.     else
  809.     {
  810. DESCRIPTOR_DATA *d;
  811. for ( d = descriptor_list; d && d->next != dclose; d = d->next )
  812.     ;
  813. if ( d != NULL )
  814.     d->next = dclose->next;
  815. else
  816.     bug( "Close_socket: dclose not found.", 0 );
  817.     }
  818. //    close( dclose->descriptor );
  819.     free_string( dclose->host );
  820.     dclose->next = descriptor_free;
  821.     descriptor_free = dclose;
  822. //@@@#if defined(MSDOS) || defined(macintosh)
  823.     exit(1);
  824. //@@@#endif
  825.     return;
  826. }
  827. /*
  828.  * Lowest level output function.
  829.  * Write a block of text to the file descriptor.
  830.  * If this gives errors on very long blocks (like 'ofind all'),
  831.  *   try lowering the max block size.
  832.  */
  833. bool write_to_descriptor( int desc, char *txt, int length )
  834. {
  835.     int iStart;
  836.     int nWrite;
  837.     int nBlock;
  838. #if defined(macintosh) || defined(MSDOS)
  839.     if ( desc == 0 )
  840. desc = 1;
  841. #endif
  842.    char c;
  843.    int n;
  844.    char *p;
  845.       char szBuffer[32767];
  846.     if ( length <= 0 )
  847. length = strlen(txt);
  848. #if 0
  849.     for ( iStart = 0; iStart < length; iStart += nWrite )
  850.     {
  851. nBlock = UMIN( length - iStart, 4096 );
  852. if ( ( nWrite = write( desc, txt + iStart, nBlock ) ) < 0 )
  853.     { perror( "Write_to_descriptor" ); return FALSE; }
  854.     }
  855. #else
  856.    c = txt[length];
  857.    txt[length] = '';
  858. //   MessageBox(0, txt, "@@@", MB_ICONINFORMATION|MB_OK);
  859. //   SendMessage(hWndOutput, WM_SETTEXT, 0, (LPARAM) txt);
  860.    SendMessage(hWndOutput, WM_GETTEXT, 32767, (LPARAM) szBuffer);
  861.    /* Count the newlines */
  862.    for (p = szBuffer, n = 0; *p; p++)
  863.       if (*p == 'n')
  864.          n++;
  865.    for (p = txt; *p; p++)
  866.       if (*p == 'n')
  867.          n++;
  868.    if (n < 22) // @@@ Totally font dependent...
  869.       {
  870. //      strcpy(szBuffer+n, txt);
  871.       strcat(szBuffer, "n");
  872.       strcat(szBuffer, txt);
  873.       SendMessage(hWndOutput, WM_SETTEXT, 0, (LPARAM) szBuffer);
  874.       }
  875.    else
  876.       SendMessage(hWndOutput, WM_SETTEXT, 0, (LPARAM) txt);
  877.    txt[length] = c;
  878. #endif
  879.     return TRUE;
  880. }
  881. /*
  882.  * Deal with sockets that haven't logged in yet.
  883.  */
  884. void nanny( DESCRIPTOR_DATA *d, char *argument )
  885. {
  886.     char buf[MAX_STRING_LENGTH];
  887.     CHAR_DATA *ch;
  888.     NOTE_DATA *pnote;
  889.     char *pwdnew;
  890.     char *p;
  891.     int iClass;
  892.     int lines;
  893.     int notes;
  894.     bool fOld;
  895.     while ( isspace(*argument) )
  896. argument++;
  897.     ch = d->character;
  898.     switch ( d->connected )
  899.     {
  900.     default:
  901. bug( "Nanny: bad d->connected %d.", d->connected );
  902. close_socket( d );
  903. return;
  904.     case CON_GET_NAME:
  905. if ( argument[0] == '' )
  906. {
  907.     close_socket( d );
  908.     return;
  909. }
  910. argument[0] = UPPER(argument[0]);
  911. if ( !check_parse_name( argument ) )
  912. {
  913.     write_to_buffer( d, "Illegal name, try another.nrName: ", 0 );
  914.     return;
  915. }
  916. fOld = load_char_obj( d, argument );
  917. ch   = d->character;
  918. if ( IS_SET(ch->act, PLR_DENY) )
  919. {
  920.     sprintf( log_buf, "Denying access to %s@%s.", argument, d->host );
  921.     log_string( log_buf );
  922.     write_to_buffer( d, "You are denied access.nr", 0 );
  923.     close_socket( d );
  924.     return;
  925. }
  926. if ( check_reconnect( d, argument, FALSE ) )
  927. {
  928.     fOld = TRUE;
  929. }
  930. else
  931. {
  932.     if ( wizlock && !IS_HERO( ch ) && !ch->wizbit )
  933.     {
  934. write_to_buffer( d, "The game is wizlocked.nr", 0 );
  935. close_socket( d );
  936. return;
  937.     }
  938. }
  939. if ( fOld )
  940. {
  941.     /* Old player */
  942.     write_to_buffer( d, "Password: ", 0 );
  943.     write_to_buffer( d, echo_off_str, 0 );
  944.     d->connected = CON_GET_OLD_PASSWORD;
  945.     return;
  946. }
  947. else
  948. {
  949.     /* New player */
  950.     /* New characters with same name fix by Salem's Lot */
  951.     if ( check_playing( d, ch->name ) )
  952.         return;
  953.     sprintf( buf, "Did I get that right, %s (Y/N)? ", argument );
  954.     write_to_buffer( d, buf, 0 );
  955.     d->connected = CON_CONFIRM_NEW_NAME;
  956.     return;
  957. }
  958. //@@@ break;
  959.     case CON_GET_OLD_PASSWORD:
  960. #if defined(unix)
  961. write_to_buffer( d, "nr", 2 );
  962. #endif
  963. if ( strcmp( crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) )
  964. {
  965.     write_to_buffer( d, "Wrong password.nr", 0 );
  966.     close_socket( d );
  967.     return;
  968. }
  969. write_to_buffer( d, echo_on_str, 0 );
  970. if ( check_reconnect( d, ch->name, TRUE ) )
  971.     return;
  972. if ( check_playing( d, ch->name ) )
  973.     return;
  974.     
  975. sprintf( log_buf, "%s@%s has connected.", ch->name, d->host );
  976. log_string( log_buf );
  977. lines = ch->pcdata->pagelen;
  978. ch->pcdata->pagelen = 20;
  979. if ( IS_HERO(ch) )
  980.     do_help( ch, "imotd" );
  981. do_help( ch, "motd" );
  982. ch->pcdata->pagelen = lines;
  983. d->connected = CON_READ_MOTD;
  984. break;
  985.     case CON_CONFIRM_NEW_NAME:
  986. switch ( *argument )
  987. {
  988. case 'y': case 'Y':
  989.     sprintf( buf, "New character.nrGive me a password for %s: %s",
  990. ch->name, echo_off_str );
  991.     write_to_buffer( d, buf, 0 );
  992.     d->connected = CON_GET_NEW_PASSWORD;
  993.     break;
  994. case 'n': case 'N':
  995.     write_to_buffer( d, "Ok, what IS it, then? ", 0 );
  996.     free_char( d->character );
  997.     d->character = NULL;
  998.     d->connected = CON_GET_NAME;
  999.     break;
  1000. default:
  1001.     write_to_buffer( d, "Please type Yes or No? ", 0 );
  1002.     break;
  1003. }
  1004. break;
  1005.     case CON_GET_NEW_PASSWORD:
  1006. #if defined(unix)
  1007. write_to_buffer( d, "nr", 2 );
  1008. #endif
  1009. if ( strlen(argument) < 3 )
  1010. {
  1011.     write_to_buffer( d,
  1012. "Password must be at least three characters long.nrPassword: ",
  1013. 0 );
  1014.     return;
  1015. }
  1016. pwdnew = crypt( argument, ch->name );
  1017. for ( p = pwdnew; *p != ''; p++ )
  1018. {
  1019.     if ( *p == '~' )
  1020.     {
  1021. write_to_buffer( d,
  1022.     "New password not acceptable, try again.nrPassword: ",
  1023.     0 );
  1024. return;
  1025.     }
  1026. }
  1027. free_string( ch->pcdata->pwd );
  1028. ch->pcdata->pwd = str_dup( pwdnew );
  1029. write_to_buffer( d, "Please retype password: ", 0 );
  1030. d->connected = CON_CONFIRM_NEW_PASSWORD;
  1031. break;
  1032.     case CON_CONFIRM_NEW_PASSWORD:
  1033. #if defined(unix)
  1034. write_to_buffer( d, "nr", 2 );
  1035. #endif
  1036. if ( strcmp( crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) )
  1037. {
  1038.     write_to_buffer( d, "Passwords don't match.nrRetype password: ",
  1039. 0 );
  1040.     d->connected = CON_GET_NEW_PASSWORD;
  1041.     return;
  1042. }
  1043. write_to_buffer( d, echo_on_str, 0 );
  1044. write_to_buffer( d, "What is your sex (M/F/N)? ", 0 );
  1045. d->connected = CON_GET_NEW_SEX;
  1046. break;
  1047.     case CON_GET_NEW_SEX:
  1048. switch ( argument[0] )
  1049. {
  1050. case 'm': case 'M': ch->sex = SEX_MALE;    break;
  1051. case 'f': case 'F': ch->sex = SEX_FEMALE;  break;
  1052. case 'n': case 'N': ch->sex = SEX_NEUTRAL; break;
  1053. default:
  1054.     write_to_buffer( d, "That's not a sex.nrWhat IS your sex? ", 0 );
  1055.     return;
  1056. }
  1057. strcpy( buf, "Select a class [" );
  1058. for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
  1059. {
  1060.     if ( iClass > 0 )
  1061. strcat( buf, " " );
  1062.     strcat( buf, class_table[iClass].who_name );
  1063. }
  1064. strcat( buf, "]: " );
  1065. write_to_buffer( d, buf, 0 );
  1066. d->connected = CON_GET_NEW_CLASS;
  1067. break;
  1068.     case CON_GET_NEW_CLASS:
  1069. for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
  1070. {
  1071.     if ( !str_cmp( argument, class_table[iClass].who_name ) )
  1072.     {
  1073. ch->class = iClass;
  1074. break;
  1075.     }
  1076. }
  1077. if ( iClass == MAX_CLASS )
  1078. {
  1079.     write_to_buffer( d,
  1080. "That's not a class.nrWhat IS your class? ", 0 );
  1081.     return;
  1082. }
  1083. sprintf( log_buf, "%s@%s new player.", ch->name, d->host );
  1084. log_string( log_buf );
  1085. write_to_buffer( d, "nr", 2 );
  1086. ch->pcdata->pagelen = 20;
  1087. ch->prompt = "<%hhp %mm %vmv> ";
  1088. do_help( ch, "motd" );
  1089. d->connected = CON_READ_MOTD;
  1090. break;
  1091.     case CON_READ_MOTD:
  1092. ch->next = char_list;
  1093. char_list = ch;
  1094. d->connected = CON_PLAYING;
  1095. send_to_char(
  1096.     "nrWelcome to Merc Diku Mud.  May your visit here be ... Mercenary.nr",
  1097.     ch );
  1098. if ( ch->level == 0 )
  1099. {
  1100.     OBJ_DATA *obj;
  1101.     switch ( class_table[ch->class].attr_prime )
  1102.     {
  1103.     case APPLY_STR: ch->pcdata->perm_str = 16; break;
  1104.     case APPLY_INT: ch->pcdata->perm_int = 16; break;
  1105.     case APPLY_WIS: ch->pcdata->perm_wis = 16; break;
  1106.     case APPLY_DEX: ch->pcdata->perm_dex = 16; break;
  1107.     case APPLY_CON: ch->pcdata->perm_con = 16; break;
  1108.     }
  1109.     ch->level = 1;
  1110.     ch->exp = 1000;
  1111.     ch->hit = ch->max_hit;
  1112.     ch->mana = ch->max_mana;
  1113.     ch->move = ch->max_move;
  1114.     sprintf( buf, "the %s",
  1115. title_table [ch->class] [ch->level]
  1116. [ch->sex == SEX_FEMALE ? 1 : 0] );
  1117.     set_title( ch, buf );
  1118.     obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_BANNER), 0 );
  1119.     obj_to_char( obj, ch );
  1120.     equip_char( ch, obj, WEAR_LIGHT );
  1121.     obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_VEST), 0 );
  1122.     obj_to_char( obj, ch );
  1123.     equip_char( ch, obj, WEAR_BODY );
  1124.     obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_SHIELD), 0 );
  1125.     obj_to_char( obj, ch );
  1126.     equip_char( ch, obj, WEAR_SHIELD );
  1127.     obj = create_object( get_obj_index(class_table[ch->class].weapon),
  1128. 0 );
  1129.     obj_to_char( obj, ch );
  1130.     equip_char( ch, obj, WEAR_WIELD );
  1131.     char_to_room( ch, get_room_index( ROOM_VNUM_SCHOOL ) );
  1132. }
  1133. else if ( ch->in_room != NULL )
  1134. {
  1135.     char_to_room( ch, ch->in_room );
  1136. }
  1137. else if ( IS_IMMORTAL(ch) )
  1138. {
  1139.     char_to_room( ch, get_room_index( ROOM_VNUM_CHAT ) );
  1140. }
  1141. else
  1142. {
  1143.     char_to_room( ch, get_room_index( ROOM_VNUM_TEMPLE ) );
  1144. }
  1145. act( "$n has entered the game.", ch, NULL, NULL, TO_ROOM );
  1146. do_look( ch, "auto" );
  1147. /* check for new notes */
  1148. notes = 0;
  1149. for ( pnote = note_list; pnote != NULL; pnote = pnote->next )
  1150.     if ( is_note_to( ch, pnote ) && str_cmp( ch->name, pnote->sender )
  1151. && pnote->date_stamp > ch->last_note )
  1152.         notes++;
  1153. if ( notes == 1 )
  1154.     send_to_char( "nrYou have one new note waiting.nr", ch );
  1155. else
  1156.     if ( notes > 1 )
  1157.     {
  1158. sprintf( buf, "nrYou have %d new notes waiting.nr",
  1159. notes );
  1160. send_to_char( buf, ch );
  1161.     }
  1162. break;
  1163.     }
  1164.     return;
  1165. }
  1166. /*
  1167.  * Parse a name for acceptability.
  1168.  */
  1169. bool check_parse_name( char *name )
  1170. {
  1171.     /*
  1172.      * Reserved words.
  1173.      */
  1174.     if ( is_name( name, "all auto immortal self someone" ) )
  1175. return FALSE;
  1176.     /*
  1177.      * Length restrictions.
  1178.      */
  1179.     if ( strlen(name) <  3 )
  1180. return FALSE;
  1181. #if defined(MSDOS)
  1182.     if ( strlen(name) >  8 )
  1183. return FALSE;
  1184. #endif
  1185. #if defined(macintosh) || defined(unix)
  1186.     if ( strlen(name) > 12 )
  1187. return FALSE;
  1188. #endif
  1189.     /*
  1190.      * Alphanumerics only.
  1191.      * Lock out IllIll twits.
  1192.      */
  1193.     {
  1194. char *pc;
  1195. bool fIll;
  1196. fIll = TRUE;
  1197. for ( pc = name; *pc != ''; pc++ )
  1198. {
  1199.     if ( !isalpha(*pc) )
  1200. return FALSE;
  1201.     if ( LOWER(*pc) != 'i' && LOWER(*pc) != 'l' )
  1202. fIll = FALSE;
  1203. }
  1204. if ( fIll )
  1205.     return FALSE;
  1206.     }
  1207.     /*
  1208.      * Prevent players from naming themselves after mobs.
  1209.      */
  1210.     {
  1211. extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
  1212. MOB_INDEX_DATA *pMobIndex;
  1213. int iHash;
  1214. for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
  1215. {
  1216.     for ( pMobIndex  = mob_index_hash[iHash];
  1217.   pMobIndex != NULL;
  1218.   pMobIndex  = pMobIndex->next )
  1219.     {
  1220. if ( is_name( name, pMobIndex->player_name ) )
  1221.     return FALSE;
  1222.     }
  1223. }
  1224.     }
  1225.     return TRUE;
  1226. }
  1227. /*
  1228.  * Look for link-dead player to reconnect.
  1229.  */
  1230. bool check_reconnect( DESCRIPTOR_DATA *d, char *name, bool fConn )
  1231. {
  1232.     CHAR_DATA *ch;
  1233.     OBJ_DATA *obj;
  1234.     for ( ch = char_list; ch != NULL; ch = ch->next )
  1235.     {
  1236. if ( !IS_NPC(ch)
  1237. && ( !fConn || ch->desc == NULL )
  1238. &&   !str_cmp( d->character->name, ch->name ) )
  1239. {
  1240.     if ( fConn == FALSE )
  1241.     {
  1242. free_string( d->character->pcdata->pwd );
  1243. d->character->pcdata->pwd = str_dup( ch->pcdata->pwd );
  1244.     }
  1245.     else
  1246.     {
  1247. free_char( d->character );
  1248. d->character = ch;
  1249. ch->desc  = d;
  1250. ch->timer  = 0;
  1251. send_to_char( "Reconnecting.nr", ch );
  1252. act( "$n has reconnected.", ch, NULL, NULL, TO_ROOM );
  1253. sprintf( log_buf, "%s@%s reconnected.", ch->name, d->host );
  1254. log_string( log_buf );
  1255. d->connected = CON_PLAYING;
  1256. /*
  1257.  * Contributed by Gene Choi
  1258.  */
  1259. if ( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) != NULL
  1260.     && obj->item_type == ITEM_LIGHT
  1261.     && obj->value[2] != 0
  1262.     && ch->in_room != NULL )
  1263.     ++ch->in_room->light;
  1264.     }
  1265.     return TRUE;
  1266. }
  1267.     }
  1268.     return FALSE;
  1269. }
  1270. /*
  1271.  * Check if already playing.
  1272.  */
  1273. bool check_playing( DESCRIPTOR_DATA *d, char *name )
  1274. {
  1275.     DESCRIPTOR_DATA *dold;
  1276.     for ( dold = descriptor_list; dold; dold = dold->next )
  1277.     {
  1278. if ( dold != d
  1279. &&   dold->character != NULL
  1280. &&   dold->connected != CON_GET_NAME
  1281. &&   dold->connected != CON_GET_OLD_PASSWORD
  1282. &&   !str_cmp( name, dold->original
  1283.          ? dold->original->name : dold->character->name ) )
  1284. {
  1285.     write_to_buffer( d, "Already playing.nrName: ", 0 );
  1286.     d->connected = CON_GET_NAME;
  1287.     if ( d->character != NULL )
  1288.     {
  1289. free_char( d->character );
  1290. d->character = NULL;
  1291.     }
  1292.     return TRUE;
  1293. }
  1294.     }
  1295.     return FALSE;
  1296. }
  1297. void stop_idling( CHAR_DATA *ch )
  1298. {
  1299.     if ( ch == NULL
  1300.     ||   ch->desc == NULL
  1301.     ||   ch->desc->connected != CON_PLAYING
  1302.     ||   ch->was_in_room == NULL
  1303.     ||   ch->in_room != get_room_index( ROOM_VNUM_LIMBO ) )
  1304. return;
  1305.     ch->timer = 0;
  1306.     char_from_room( ch );
  1307.     char_to_room( ch, ch->was_in_room );
  1308.     ch->was_in_room = NULL;
  1309.     act( "$n has returned from the void.", ch, NULL, NULL, TO_ROOM );
  1310.     return;
  1311. }
  1312. /*
  1313.  * Low level output function.
  1314.  */
  1315. bool process_output( DESCRIPTOR_DATA *d, bool fPrompt )
  1316. {
  1317.     extern bool merc_down;
  1318.     /*
  1319.      * Bust a prompt.
  1320.      */
  1321.     if ( fPrompt && !merc_down && d->connected == CON_PLAYING )
  1322.         if ( d->showstr_point )
  1323.     write_to_buffer( d,
  1324.   "[Please type (c)ontinue, (r)efresh, (b)ack, (h)elp, (q)uit, or RETURN]:  ",
  1325.     0 );
  1326. else
  1327. {
  1328.     CHAR_DATA *ch;
  1329.     ch = d->original ? d->original : d->character;
  1330.     if ( IS_SET(ch->act, PLR_BLANK) )
  1331.         write_to_buffer( d, "nr", 2 );
  1332.     if ( IS_SET(ch->act, PLR_PROMPT) )
  1333.         bust_a_prompt( ch );
  1334.     if ( IS_SET(ch->act, PLR_TELNET_GA) )
  1335.         write_to_buffer( d, go_ahead_str, 0 );
  1336. }
  1337.     /*
  1338.      * Short-circuit if nothing to write.
  1339.      */
  1340.     if ( d->outtop == 0 )
  1341. return TRUE;
  1342.     /*
  1343.      * Snoop-o-rama.
  1344.      */
  1345.     if ( d->snoop_by != NULL )
  1346.     {
  1347. write_to_buffer( d->snoop_by, "% ", 2 );
  1348. write_to_buffer( d->snoop_by, d->outbuf, d->outtop );
  1349.     }
  1350.     /*
  1351.      * OS-dependent output.
  1352.      */
  1353.     if ( !write_to_descriptor( d->descriptor, d->outbuf, d->outtop ) )
  1354.     {
  1355. d->outtop = 0;
  1356. return FALSE;
  1357.     }
  1358.     else
  1359.     {
  1360. d->outtop = 0;
  1361. return TRUE;
  1362.     }
  1363. }
  1364. /*
  1365.  * Bust a prompt (player settable prompt)
  1366.  * coded by Morgenes for Aldara Mud
  1367.  */
  1368. void bust_a_prompt( CHAR_DATA *ch )
  1369. {
  1370.    char buf[MAX_STRING_LENGTH];
  1371.    char buf2[MAX_STRING_LENGTH];
  1372.    const char *str;
  1373.    const char *i;
  1374.    char *point;
  1375.    if( ch->prompt == NULL || ch->prompt[0] == '' )
  1376.    {
  1377.       send_to_char( "nrnr", ch );
  1378.       return;
  1379.    }
  1380.    point = buf;
  1381.    str = ch->prompt;
  1382.    while( *str != '' )
  1383.    {
  1384.       if( *str != '%' )
  1385.       {
  1386.          *point++ = *str++;
  1387.          continue;
  1388.       }
  1389.       ++str;
  1390.       switch( *str )
  1391.       {
  1392.          default :
  1393.             i = " "; break;
  1394.          case 'h' :
  1395.             sprintf( buf2, "%d", ch->hit );
  1396.             i = buf2; break;
  1397.          case 'H' :
  1398.             sprintf( buf2, "%d", ch->max_hit );
  1399.             i = buf2; break;
  1400.          case 'm' :
  1401.             sprintf( buf2, "%d", ch->mana );
  1402.             i = buf2; break;
  1403.          case 'M' :
  1404.             sprintf( buf2, "%d", ch->max_mana );
  1405.             i = buf2; break;
  1406.          case 'v' :
  1407.             sprintf( buf2, "%d", ch->move );
  1408.             i = buf2; break;
  1409.          case 'V' :
  1410.             sprintf( buf2, "%d", ch->max_move );
  1411.             i = buf2; break;
  1412.          case 'x' :
  1413.             sprintf( buf2, "%d", ch->exp );
  1414.             i = buf2; break;
  1415.          case 'g' :
  1416.             sprintf( buf2, "%d", ch->gold);
  1417.             i = buf2; break;
  1418.          case 'a' :
  1419.             if( ch->level < 5 )
  1420.                sprintf( buf2, "%d", ch->alignment );
  1421.             else
  1422.                sprintf( buf2, "%s", IS_GOOD(ch) ? "good" : IS_EVIL(ch) ? 
  1423.                 "evil" : "neutral" );
  1424.             i = buf2; break;
  1425.          case 'r' :
  1426.             if( ch->in_room != NULL )
  1427.                sprintf( buf2, "%s", ch->in_room->name );
  1428.             else
  1429.                sprintf( buf2, " " );
  1430.             i = buf2; break;
  1431.          case 'R' :
  1432.             if( IS_IMMORTAL( ch ) && ch->in_room != NULL )
  1433.                sprintf( buf2, "%d", ch->in_room->vnum );
  1434.             else
  1435.                sprintf( buf2, " " );
  1436.             i = buf2; break;
  1437.          case 'z' :
  1438.             if( IS_IMMORTAL( ch ) && ch->in_room != NULL )
  1439.                sprintf( buf2, "%s", ch->in_room->area->name );
  1440.             else
  1441.                sprintf( buf2, " " );
  1442.             i = buf2; break;
  1443.          case '%' :
  1444.             sprintf( buf2, "%%" );
  1445.             i = buf2; break;
  1446.       } 
  1447.       ++str;
  1448.       while( (*point = *i) != '' )
  1449.          ++point, ++i;
  1450.    }
  1451.    write_to_buffer( ch->desc, buf, point - buf );
  1452.    return;
  1453. }
  1454. /* The heart of the pager.  Thanks to N'Atas-Ha, ThePrincedom
  1455.    for porting this SillyMud code for MERC 2.0 and laying down the groundwork.
  1456.    Thanks to Blackstar, hopper.cs.uiowa.edu 4000 for which
  1457.    the improvements to the pager was modeled from.  - Kahn */
  1458. void show_string(struct descriptor_data *d, char *input)
  1459. {
  1460.   char buffer[ MAX_STRING_LENGTH ];
  1461.   char buf[ MAX_INPUT_LENGTH ];
  1462.   register char *scan, *chk;
  1463.   int lines = 0, toggle=1;
  1464.   one_argument(input, buf);
  1465.   switch( UPPER( buf[0] ) )
  1466.   {
  1467.   case '':
  1468.   case 'C': /* show next page of text */
  1469.     lines = 0;
  1470.     break;
  1471.   case 'R': /* refresh current page of text */
  1472.     lines = - 1 - (d->character->pcdata->pagelen);
  1473.     break;
  1474.   case 'B': /* scroll back a page of text */
  1475.     lines = -(2*d->character->pcdata->pagelen);
  1476.     break;
  1477.   case 'H': /* Show some help */
  1478.     write_to_buffer( d,
  1479.         "C, or Return = continue, R = redraw this page,nr", 0 );
  1480.     write_to_buffer( d,
  1481.         "B = back one page, H = this help, Q or other keys = exit.nrnr",
  1482.     0 );
  1483.     lines = - 1 - (d->character->pcdata->pagelen);
  1484.     break;
  1485.   default: /*otherwise, stop the text viewing */
  1486.     if ( d->showstr_head )
  1487.     {
  1488.       free_string( d->showstr_head );
  1489.       d->showstr_head  = 0;
  1490.     }
  1491.     d->showstr_point = 0;
  1492.     return;
  1493.   }
  1494.   /* do any backing up necessary */
  1495.   if (lines < 0)
  1496.   {
  1497.     for ( scan = d->showstr_point; scan > d->showstr_head; scan-- )
  1498.          if ( ( *scan == 'n' ) || ( *scan == 'r' ) )
  1499.  {
  1500.      toggle = -toggle;
  1501.      if ( toggle < 0 )
  1502.          if ( !( ++lines ) )
  1503.      break;
  1504.  }
  1505.     d->showstr_point = scan;
  1506.   }
  1507.   /* show a chunk */
  1508.   lines  = 0;
  1509.   toggle = 1;
  1510.   for ( scan = buffer; ; scan++, d->showstr_point++ )
  1511.        if ( ( ( *scan = *d->showstr_point ) == 'n' || *scan == 'r' )
  1512.    && ( toggle = -toggle ) < 0 )
  1513.    lines++;
  1514.        else
  1515.    if ( !*scan || ( d->character && !IS_NPC( d->character )
  1516.   && lines >= d->character->pcdata->pagelen) )
  1517.    {
  1518.        *scan = '';
  1519.        write_to_buffer( d, buffer, strlen( buffer ) );
  1520.      /* See if this is the end (or near the end) of the string */
  1521.        for ( chk = d->showstr_point; isspace( *chk ); chk++ );
  1522.        if ( !*chk )
  1523.        {
  1524.    if ( d->showstr_head )
  1525.    {
  1526.       free_string( d->showstr_head );
  1527.       d->showstr_head  = 0;
  1528.    }
  1529.    d->showstr_point = 0;
  1530.        }
  1531.        return;
  1532.    }
  1533. //@@@  return;
  1534. }