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

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