Subversion Repositories Games.Chess Giants

Rev

Rev 140 | Rev 171 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // network.cpp
  2.  
  3. #include "common.h"
  4.  
  5.  
  6. // prototypes of local functions
  7. static void EvaluateServerReply (player_t *player);
  8.  
  9.  
  10. bool Network_Init (void)
  11. {
  12.    // this function initializes the network subsystem on operating systems that require it
  13.  
  14. #ifdef _WIN32
  15.    static bool is_winsock_initialized = false;
  16.    WSADATA wsa_data;
  17.  
  18.    if (!is_winsock_initialized)
  19.       is_winsock_initialized = (WSAStartup (MAKEWORD (2, 2), &wsa_data) == 0);
  20.  
  21.    return (is_winsock_initialized); // return whether the network subsystem was successfully initialized
  22. #else // !_WIN32
  23.    return (true); // all other systems than Win32 don't need to initialize the network
  24. #endif // _WIN32
  25. }
  26.  
  27.  
  28. bool PlayerNetwork_Init (player_t *player)
  29. {
  30.    // this function initializes the network layer and connects to the chess server
  31.  
  32.    struct hostent *hostinfo;
  33.    struct sockaddr_in service;
  34.    unsigned long nonblocking_mode;
  35.    char ascii_hostname[256];
  36.  
  37.    onlineplayers = NULL; // ensure the online players array is empty
  38.    onlineplayer_count = 0; // and reset the online players count
  39.    onlineplayers_updated = false;
  40.  
  41.    soughtgames = NULL; // ensure the sought games array is empty
  42.    soughtgame_count = 0; // and reset the sought games count
  43.    soughtgames_updated = false;
  44.    lastsought_time = 0;
  45.  
  46.    chatterchannels = NULL; // ensure the chatter channels array is empty
  47.    chatterchannel_count = 0; // and reset the chatter channels count
  48.    chatterchannels_updated = false;
  49.    selected_chatterchannel = NULL;
  50.  
  51.    PlayerCards_Init (); // initialize the player cards array
  52.    Challenges_Init (); // initialize the challenges array
  53.    Interlocutors_Init (); // initialize the interlocutors array
  54.  
  55.    server_motd[0] = 0; // reset the server MOTD
  56.  
  57.    player->is_connected = false; // remember we aren't connected yet
  58.    player->is_logged_in = false; // and not logged in either
  59.    player->is_in_game = false; // we aren't in game either
  60.    player->game_number = 0;
  61.    player->remaining_seconds = 0;
  62.    player->our_socket = INVALID_SOCKET; // and that we have no socket yet
  63.    player->name[0] = 0; // player name undefined
  64.  
  65.    // initialize the network subsystem if required
  66.    if (!Network_Init ())
  67.    {
  68.       messagebox.hWndParent = hMainWnd;
  69.       wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage"));
  70.       wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed"));
  71.       messagebox.flags = MB_ICONWARNING | MB_OK;
  72.       DialogBox_Message (&messagebox); // display a modeless error message box
  73.  
  74.       PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message
  75.       return (false);
  76.    }
  77.  
  78.    // get the chess server's IP address from the host name
  79.    ConvertTo7BitASCII (ascii_hostname, sizeof (ascii_hostname), options.network.server_address);
  80.    hostinfo = gethostbyname (ascii_hostname);
  81.    if (hostinfo == NULL)
  82.    {
  83.       messagebox.hWndParent = hMainWnd;
  84.       wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage"));
  85.       wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed"));
  86.       messagebox.flags = MB_ICONWARNING | MB_OK;
  87.       DialogBox_Message (&messagebox); // display a modeless error message box
  88.  
  89.       PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message
  90.       return (false);
  91.    }
  92.  
  93.    // fill in the sockaddr server structure with the server hostinfo data
  94.    service.sin_family = AF_INET;
  95.    service.sin_addr.s_addr = inet_addr (inet_ntoa (*(struct in_addr *) hostinfo->h_addr_list[0]));
  96.    service.sin_port = htons (options.network.server_port);
  97.  
  98.    // create our socket
  99.    if ((player->our_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
  100.    {
  101.       messagebox.hWndParent = hMainWnd;
  102.       wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage"));
  103.       wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed"));
  104.       messagebox.flags = MB_ICONWARNING | MB_OK;
  105.       DialogBox_Message (&messagebox); // display a modeless error message box
  106.  
  107.       PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message
  108.       return (false);
  109.    }
  110.  
  111.    // connect the game to the chess server using that socket
  112.    if (connect (player->our_socket, (struct sockaddr *) &service, sizeof (service)) == -1)
  113.    {
  114.       messagebox.hWndParent = hMainWnd;
  115.       wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage"));
  116.       wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed"));
  117.       messagebox.flags = MB_ICONWARNING | MB_OK;
  118.       DialogBox_Message (&messagebox); // display a modeless error message box
  119.  
  120.       PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message
  121.       return (false);
  122.    }
  123.  
  124.    // set it to be non-blocking (but only AFTER the connection is made)
  125.    nonblocking_mode = 1;
  126.    if (ioctlsocket (player->our_socket, FIONBIO, &nonblocking_mode) == SOCKET_ERROR)
  127.    {
  128.       messagebox.hWndParent = hMainWnd;
  129.       wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage"));
  130.       wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed"));
  131.       messagebox.flags = MB_ICONWARNING | MB_OK;
  132.       DialogBox_Message (&messagebox); // display a modeless error message box
  133.  
  134.       PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message
  135.       return (false);
  136.    }
  137.  
  138.    // initialize the debug log file
  139.    Debug_Init (L"Chess server output.txt");
  140.  
  141.    player->is_connected = true; // remember we are connected
  142.    return (true); // finished, we have a valid, connected socket
  143. }
  144.  
  145.  
  146. void PlayerNetwork_Shutdown (player_t *player)
  147. {
  148.    // this function shutdowns the network layer
  149.  
  150.    int chatterchannel_index;
  151.  
  152.    // shutdown the socket if it is open. This will disconnect us from the server.
  153.    if (player->our_socket != INVALID_SOCKET)
  154.       closesocket (player->our_socket); // close the network socket
  155.    player->our_socket = INVALID_SOCKET;
  156.  
  157.    player->is_connected = false; // remember we are no longer connected
  158.    player->is_logged_in = false; // and not logged in either
  159.    player->is_in_game = false; // we aren't in game either
  160.    player->game_number = 0;
  161.    player->remaining_seconds = 0;
  162.    player->name[0] = 0; // player name undefined
  163.  
  164.    server_motd[0] = 0; // reset the server MOTD
  165.  
  166.    // cycle through all chatter channels we know...
  167.    for (chatterchannel_index = 0; chatterchannel_index < chatterchannel_count; chatterchannel_index++)
  168.    {
  169.       SAFE_free ((void **) &chatterchannels[chatterchannel_index].members); // free their member list
  170.       chatterchannels[chatterchannel_index].member_count = 0; // reset their members count
  171.    }
  172.    SAFE_free ((void **) &chatterchannels); // free the chatter channels array
  173.    chatterchannel_count = 0; // and reset the chatter channels count
  174.    chatterchannels_updated = false;
  175.    selected_chatterchannel = NULL;
  176.  
  177.    SAFE_free ((void **) &soughtgames); // free the sought games array
  178.    soughtgame_count = 0; // and reset the sought games count
  179.    soughtgames_updated = false;
  180.  
  181.    SAFE_free ((void **) &onlineplayers); // free the online players array
  182.    onlineplayer_count = 0; // and reset the online players count
  183.    onlineplayers_updated = false;
  184.  
  185.    Interlocutors_Shutdown (); // shutdown the interlocutors
  186.    Challenges_Shutdown (); // shutdown the challenges
  187.    PlayerCards_Shutdown (); // shutdown the player cards
  188.  
  189.    // shutdown all possible opened UI windows
  190.    if (IsWindow (hChatterChannelsWnd))
  191.       DestroyWindow (hChatterChannelsWnd);
  192.    hChatterChannelsWnd = NULL;
  193.    if (IsWindow (hGamesWnd))
  194.       DestroyWindow (hGamesWnd);
  195.    hGamesWnd = NULL;
  196.    if (IsWindow (hMOTDWnd))
  197.       DestroyWindow (hMOTDWnd);
  198.    hMOTDWnd = NULL;
  199.    if (IsWindow (hOpponentsWnd))
  200.       DestroyWindow (hOpponentsWnd);
  201.    hOpponentsWnd = NULL;
  202.    if (IsWindow (hSoughtWnd))
  203.       DestroyWindow (hSoughtWnd);
  204.    hSoughtWnd = NULL;
  205.  
  206.    // shutdown WinSock
  207.    WSACleanup ();
  208.  
  209.    return; // finished
  210. }
  211.  
  212.  
  213. bool PlayerNetwork_Think (player_t *player)
  214. {
  215.    // this function is called once per game tick to listen to the network and react to what the server tells us. Returns TRUE
  216.    // if we need to update the scene.
  217.  
  218.    player_t *local_player;
  219.    char *block_start;
  220.    char *block_end;
  221.    char *ascii_sendbuffer; // mallocated
  222.    wchar_t *widechar_buffer; // mallocated
  223.    wchar_t *widechar_line;
  224.    int send_retval;
  225.    int recv_retval;
  226.    int byte_index;
  227.    int rewrite_index;
  228.    int length;
  229.    bool do_update;
  230.  
  231.    // are we NOT connected yet ?
  232.    if (!player->is_connected)
  233.       return (false); // consistency check: if we aren't connected, don't do anything
  234.  
  235.    // are we NOT logged in yet AND is our socket valid AND is there nothing in the center of the screen yet ?
  236.    if (!player->is_logged_in && (player->our_socket != INVALID_SOCKET) && !the_scene.gui.central_text.is_displayed)
  237.    {
  238.       Scene_UpdateText (&the_scene.gui.central_text, RGBA_TO_RGBACOLOR (255, 255, 255, 191), DURATION_INFINITE, true, LOCALIZE (L"Connecting")); // display "connecting" in the middle of the screen
  239.       the_scene.gui.want_spinwheel = true; // start spinning wheel
  240.    }
  241.  
  242.    do_update = false; // assume we don't need to update the scene until told otherwise
  243.  
  244.    ////////////////////////////
  245.    // BEGIN listening to server
  246.  
  247.    // proceed in filling the ascii buffer with what's coming
  248.  
  249.    // get a hand on the end of the player's recv buffer and compute its remaining size
  250.    length = strlen (player->ascii_recvbuffer);
  251.  
  252.    // if the server sent us something, append it to what we've received
  253.    recv_retval = recv (player->our_socket, &player->ascii_recvbuffer[length], player->recvbuffer_size - length, 0);
  254.    if (recv_retval > 0)
  255.    {
  256.       // parse all received data and eradicate all carriage returns. Also convert %'s to a safer glyph.
  257.       rewrite_index = 0;
  258.       for (byte_index = 0; byte_index < recv_retval; byte_index++)
  259.          if (player->ascii_recvbuffer[length + byte_index] != '\r')
  260.          {
  261.             if (player->ascii_recvbuffer[length + byte_index] == '%')
  262.                player->ascii_recvbuffer[length + rewrite_index] = '¤';
  263.             else
  264.                player->ascii_recvbuffer[length + rewrite_index] = player->ascii_recvbuffer[length + byte_index];
  265.             rewrite_index++;
  266.          }
  267.       player->ascii_recvbuffer[length + rewrite_index] = 0; // terminate the buffer ourselves
  268.       length = strlen (player->ascii_recvbuffer); // and update the new recvbuffer's length
  269.    }
  270.    else if (recv_retval == SOCKET_ERROR)
  271.    {
  272.       recv_retval = WSAGetLastError (); // ask Windows to be more specific about the error
  273.       if (recv_retval == WSAEWOULDBLOCK)
  274.          ; // it's okay. We're a non-blocking socket.
  275.       else if (recv_retval == WSAETIMEDOUT)
  276.       {
  277.          messagebox.hWndParent = hMainWnd;
  278.          wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage"));
  279.          wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_ConnectionToChessServerLost"));
  280.          messagebox.flags = MB_ICONWARNING | MB_OK;
  281.          DialogBox_Message (&messagebox); // display a modeless error message box
  282.  
  283.          PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message
  284.          return (false);
  285.       }
  286.    }
  287.  
  288.    // END listening to server
  289.    //////////////////////////
  290.  
  291.    //////////////////////////////////
  292.    // BEGIN evaluating server replies
  293.  
  294.    // are we NOT logged in yet ?
  295.    if (!player->is_logged_in)
  296.    {
  297.       // is it a login prompt ?
  298.       if ((length > 7) && (strcmp (&player->ascii_recvbuffer[length - 7], "login: ") == 0))
  299.       {
  300.          Player_SendBuffer_Add (player, 1000, L"%s\n", options.network.login); // send the login string
  301.          player->ascii_recvbuffer[0] = 0; // and discard recvbuffer as we've processed this message
  302.       }
  303.  
  304.       // else is it a password prompt ?
  305.       else if (((length > 10) && (strcmp (&player->ascii_recvbuffer[length - 10], "password: ") == 0))
  306.                || ((length > 3) && (strcmp (&player->ascii_recvbuffer[length - 3], "\":\n") == 0)))
  307.       {
  308.          Player_SendBuffer_Add (player, 1000, L"%s\n", options.network.password); // send the password string
  309.          player->ascii_recvbuffer[0] = 0; // and discard recvbuffer as we've processed this message
  310.       }
  311.  
  312.       // else is it a confirmation that we've successfully logged in ?
  313.       else if (((block_start = strstr (player->ascii_recvbuffer, "\n**** Starting FICS session as ")) != NULL)
  314.                && (block_end = strstr (player->ascii_recvbuffer, " ****\n")))
  315.       {
  316.          player->is_logged_in = true; // remember we are logged in
  317.          the_scene.gui.central_text.disappear_time = current_time + 1.0f; // fade the "connecting" phrase out now (FIXME: ugly)
  318.          the_scene.gui.want_spinwheel = false; // stop spinning wheel
  319.          do_update = true; // and update the scene
  320.  
  321.          block_start += 31; // skip the "\n**** Starting FICS session as " substring
  322.          local_player = Player_FindByType (PLAYER_HUMAN); // get a pointer to the local player
  323.  
  324.          // copy out local player's login name, as reported by server, and convert it to wchar_t
  325.          for (byte_index = 0; (byte_index < WCHAR_SIZEOF (local_player->name)) && isalpha (block_start[byte_index]); byte_index++)
  326.             local_player->name[byte_index] = (wchar_t) block_start[byte_index]; // copy nickname one character after the other. Very dirty conversion.
  327.          if (byte_index < WCHAR_SIZEOF (local_player->name))
  328.             local_player->name[byte_index] = 0; // finish the string ourselves
  329.          else
  330.             local_player->name[WCHAR_SIZEOF (local_player->name) - 1] = 0; // truncate it if neeeded
  331.  
  332.          server_motd[0] = 0; // remember we haven't read the MOTD yet
  333.          the_board.reevaluate = true; // reeevaluate the board (to update the title bar)
  334.  
  335.          // see if there's more data to parse after this message, in which case move it in place
  336.          length = strlen (block_end + 6);
  337.          if (length > 0)
  338.             memmove (player->ascii_recvbuffer, block_end + 6, length + 1);
  339.          else
  340.             player->ascii_recvbuffer[0] = 0; // else discard recvbuffer as we've processed this message
  341.       }
  342.    }
  343.  
  344.    // else we are logged in
  345.    else
  346.    {
  347.       // see if we have a complete reply block (remember: percent sign was replaced with '¤')
  348.       block_end = strstr (player->ascii_recvbuffer, "\nfics¤ ");
  349.  
  350.       // as long as we can find some...
  351.       while (block_end != NULL)
  352.       {
  353.          *block_end = 0; // break the string here
  354.  
  355.          // convert the block to wide char and evaluate it, taking action if needed
  356.          ConvertToWideChar (player->recvbuffer, player->recvbuffer_size, player->ascii_recvbuffer);
  357.          Debug_Log (L"RECEIVED:[%s]\n", player->recvbuffer); // log what we've received
  358.          EvaluateServerReply (player); // and evaluate it
  359.  
  360.          // see if there's more data to parse after this message, in which case move it in place
  361.          length = strlen (block_end + 7);
  362.          if (length > 0)
  363.             memmove (player->ascii_recvbuffer, block_end + 7, length + 1);
  364.          else
  365.          {
  366.             player->ascii_recvbuffer[0] = 0;
  367.             break; // it was the last prompt, so discard recvbuffer as we've processed this message
  368.          }
  369.          block_end = strstr (player->ascii_recvbuffer, "\nfics¤ "); // remember: percent sign was replaced with '¤'
  370.       }
  371.    }
  372.  
  373.    // END evaluating server replies
  374.    ////////////////////////////////
  375.  
  376.    // have we been notified that the current player just changed, has at least one move been played AND is it the remote player's turn now ?
  377.    if (the_board.has_playerchanged && (the_board.move_count > 1) && (Board_ColorToMove (&the_board) == player->color))
  378.    {
  379.       Debug_Log (L"===Local player just played, sending the chosen move to chess server===\n");
  380.       Player_SendBuffer_Add (player, 1000, L"%s\n", the_board.moves[the_board.move_count - 1].pgntext); // send the move string to the chess server
  381.    }
  382.  
  383.    // has the user entered some chatter text ?
  384.    if (!the_scene.gui.is_entering_text && (the_scene.gui.entered_ccreply.text != NULL))
  385.    {
  386.       // is player logged in AND has a chatter channel been selected ? if so, send chat string to server
  387.       if (player->is_logged_in && (selected_chatterchannel != NULL))
  388.          Player_SendBuffer_Add (player, 1000, L"+channel %d\ntell %d %s\n", selected_chatterchannel->id, selected_chatterchannel->id, the_scene.gui.entered_ccreply.text);
  389.  
  390.       // reset the entered text buffer
  391.       SAFE_free ((void **) &the_scene.gui.entered_ccreply.text); // reset the entered text buffer
  392.       the_scene.gui.entered_ccreply.text_length = 0; // and set its length to zero
  393.    }
  394.  
  395.    // does the local player want to cancel its last move ? this can be either HIS move or HIS OPPONENTS's move...
  396.    local_player = Player_FindByType (PLAYER_HUMAN); // get a pointer to the local player
  397.    if ((local_player != NULL) && local_player->wants_cancel)
  398.    {
  399.       Player_SendBuffer_Add (player, 1000, L"takeback\n"); // send the takeback request to our opponent
  400.       Interlocutor_Notify (Interlocutor_FindOrCreate (player->name), LOCALIZE (L"Chat_TakebackRequestSent"), player->name); // send a notification to its chat window
  401.       the_board.game_state = STATE_PLAYING; // remember the game is now playing (in case we wanted to cancel the closing move of a finished game, this opens the game again)
  402.       local_player->wants_cancel = false; // don't do this all day long
  403.    }
  404.    if (player->wants_cancel)
  405.    {
  406.       Player_SendBuffer_Add (player, 1000, L"takeback\n"); // send the takeback request to our opponent
  407.       Interlocutor_Notify (Interlocutor_FindOrCreate (player->name), LOCALIZE (L"Chat_TakebackRequestSent"), player->name); // send a notification to its chat window
  408.       the_board.game_state = STATE_PLAYING; // remember the game is now playing (in case we wanted to cancel the closing move of a finished game, this opens the game again)
  409.       player->wants_cancel = false; // don't do this all day long
  410.    }
  411.  
  412.    // if we have something to send, do it
  413.    if (!player->sendbuffer_locked && (player->sendbuffer[0] != 0) && (animation_endtime + 1.0f < current_time))
  414.    {
  415.       // log what we're sending
  416.       Debug_Log (L"SENDING:[%s]\n", player->sendbuffer);
  417.  
  418.       player->sendbuffer_locked = true; // lock the buffer
  419.  
  420.       // now read line per line (mallocate a line buffer as large as necessary)
  421.       length = wcslen (player->sendbuffer) + 1 + 1; // +1 for \n, +1 for null terminator
  422.       ascii_sendbuffer = (char *) SAFE_malloc (length, sizeof (char), false);
  423.       widechar_buffer = (wchar_t *) SAFE_malloc (length, sizeof (wchar_t), false);
  424.       widechar_line = player->sendbuffer; // start at the first character
  425.       while ((widechar_line = wcsgets (widechar_buffer, length, widechar_line)) != NULL)
  426.       {
  427.          wcscat_s (widechar_buffer, length, L"\n"); // put the carriage return back
  428.          ConvertTo7BitASCII (ascii_sendbuffer, length, widechar_buffer); // convert to ASCII
  429.          send_retval = send (player->our_socket, ascii_sendbuffer, strlen (ascii_sendbuffer), 0); // send data
  430.       }
  431.       SAFE_free ((void **) &widechar_buffer); // we no longer need the line buffer, so free it
  432.       SAFE_free ((void **) &ascii_sendbuffer);
  433.  
  434.       player->sendbuffer[0] = 0; // what we had to send has been sent, reset the send buffer
  435.       player->sendbuffer_locked = false; // and unlock it
  436.  
  437.       // did send() report an error ?
  438.       if (send_retval == SOCKET_ERROR)
  439.       {
  440.          messagebox.hWndParent = hMainWnd;
  441.          wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage"));
  442.          wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_ConnectionToChessServerLost"));
  443.          messagebox.flags = MB_ICONERROR | MB_OK;
  444.          DialogBox_Message (&messagebox); // display a modeless error message box
  445.  
  446.          PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message
  447.          return (true); // on error, cancel
  448.       }
  449.    }
  450.  
  451.    return (do_update); // finished
  452. }
  453.  
  454.  
  455. static void EvaluateServerReply (player_t *player)
  456. {
  457.    // this function parses a network reply and evaluates it, deciding what to do
  458.  
  459.    //////////////////////
  460.    // OUT OF GAME REPLIES
  461.  
  462.    // the MOTD is the first reply to be evaluated
  463.    EvaluateServerReply_MOTD (player);
  464.  
  465.    // evaluate dangerous replies first, i.e. those that contain user-settable text
  466.    EvaluateServerReply_Announcement (player);
  467.    EvaluateServerReply_ChannelMessage (player);
  468.    EvaluateServerReply_PrivateMessage (player);
  469.    EvaluateServerReply_Finger (player);
  470.  
  471.    // the less dangerous replies can now be evaluated without ambiguity
  472.    EvaluateServerReply_Seek (player);
  473.    EvaluateServerReply_Challenge (player);
  474.    EvaluateServerReply_ChallengeAccepted (player);
  475.    EvaluateServerReply_ChallengeDeclined (player);
  476.    EvaluateServerReply_Takeback (player);
  477.    EvaluateServerReply_TakebackDeclinedByOther (player);
  478.    EvaluateServerReply_TakebackDeclinedByYou (player);
  479.    EvaluateServerReply_PlayNotAllowed (player);
  480.    EvaluateServerReply_PlayUnexistent (player);
  481.    EvaluateServerReply_PlayWrongRating (player);
  482.    EvaluateServerReply_ChannelsAndMembers (player);
  483.    EvaluateServerReply_SoughtList (player);
  484.    EvaluateServerReply_PlayersList (player);
  485.  
  486.    //////////////////
  487.    // IN GAME REPLIES
  488.  
  489.    EvaluateServerReply_GameStarting (player);
  490.    EvaluateServerReply_GameState (player);
  491.    EvaluateServerReply_GameResults (player);
  492.  
  493.    return; // finished evaluating this reply
  494. }
  495.