void Input_loop(void)
{
    int			rfds,
			tfds,
			max,
			n,
			netfd,
			result,
			clientfd;
    struct timeval	tv;

    if ((result = Net_input()) == -1) {
	error("Bad server input");
	return;
    }
    if (Client_input(2) == -1) {
	return;
    }
    if (Net_flush() == -1) {
	return;
    }
    if ((clientfd = Client_fd()) == -1) {
	error("Bad client filedescriptor");
	return;
    }
    if ((netfd = Net_fd()) == -1) {
	error("Bad socket filedescriptor");
	return;
    }
    rfds = 0;
    rfds |= (1 << clientfd);
    rfds |= (1 << netfd);
    max = (clientfd > netfd) ? clientfd : netfd;
    for (tfds = rfds; ; rfds = tfds) {
	if (scoresChanged != 0 && ++scoresChanged > SCORE_UPDATE_DELAY
	    || result > 1) {
	    if (scoresChanged > 2 * SCORE_UPDATE_DELAY) {
		Client_score_table();
		tv.tv_sec = 10;
		tv.tv_usec = 0;
	    } else {
		tv.tv_sec = 0;
		tv.tv_usec = 0;
	    }
	} else {
	    tv.tv_sec = 10;
	    tv.tv_usec = 0;
	}
	if ((n = select(max + 1, (fd_set *)&rfds, NULL, NULL, &tv)) == -1) {
	    if (errno == EINTR) {
		continue;
	    }
	    error("Select failed");
	    return;
	}
	if (n == 0) {
	    if (scoresChanged > SCORE_UPDATE_DELAY) {
		Client_score_table();
		if (Client_input(2) == -1) {
		    return;
		}
		continue;
	    }
	    else if (result <= 1) {
		errno = 0;
		error("No response from server");
		continue;
	    }
	}
	if ((rfds & (1 << clientfd)) != 0) {
	    if (Client_input(1) == -1) {
		return;
	    }
	    if (Net_flush() == -1) {
		error("Bad net flush after X input");
		return;
	    }
	}
	if ((rfds & (1 << netfd)) != 0 || result > 1) {
	    if ((result = Net_input()) == -1) {
		error("Bad net input");
		return;
	    }
	    if (result > 0) {
		/*
		 * Now there's a frame being drawn by the X server.
		 * So we shouldn't try to send more drawing
		 * requests to the X server or it might get
		 * overloaded which could cause problems with
		 * keyboard input.  Besides, we wouldn't even want
		 * to send more drawing requests because there
		 * may arive a more recent frame update soon
		 * and using the CPU now may even slow down the X server
		 * if it is running on the same CPU.
		 * So we only check if the X server has sent any more
		 * keyboard events and then we wait until the X server
		 * has finished the drawing of our current frame.
		 */
		if (Client_input(1) == -1) {
		    return;
		}
		if (Net_flush() == -1) {
		    error("Bad net flush before sync");
		    return;
		}
		Client_sync();
		if (Client_input(1) == -1) {
		    return;
		}
	    }
	}
    }
}
/*
 * This is a Game_loop that uses X specific hacks to improve
 * responsiveness. Basically it uses the same mechanism as the 
 * X client to listen to network and user input.
 */
void Game_loop(void)
{
    fd_set rfds, tfds;
    int max, n, netfd, result, clientfd;
    struct timeval tv;
    SDL_SysWMinfo info;

    SDL_VERSION(&info.version);
    if (!SDL_GetWMInfo(&info)) {
	error("SDL_GetWMInfo not supported");
	return;
    }

    if ((result = Net_input()) == -1) {
	error("Bad server input");
	return;
    }
    if (Poll_input())
	return;

    if (Net_flush() == -1)
	return;

    if ((clientfd = ConnectionNumber(info.info.x11.display)) == -1) {
	error("Bad client filedescriptor");
	return;
    }
    if ((netfd = Net_fd()) == -1) {
	error("Bad socket filedescriptor");
	return;
    }
    Net_key_change();
    FD_ZERO(&rfds);
    FD_SET(clientfd, &rfds);
    FD_SET(netfd, &rfds);
    max = (clientfd > netfd) ? clientfd : netfd;
    for (tfds = rfds; ; rfds = tfds) {

	tv.tv_sec = 1;
	tv.tv_usec = 0;

	if (maxMouseTurnsPS > 0) {
	    int t = Client_check_pointer_move_interval();

	    assert(t > 0);
	    tv.tv_sec = t / 1000000;
	    tv.tv_usec = t % 1000000;
	}

	if ((n = select(max + 1, &rfds, NULL, NULL, &tv)) == -1) {
	    if (errno == EINTR)
		continue;
	    error("Select failed");
	    return;
	}
	
	if (n == 0) {
	    if (maxMouseTurnsPS > 0 &&
		cumulativeMouseMovement != 0)
		continue;

	    if (result <= 1) {
		warn("No response from server");
		continue;
	    }
	}
	if (FD_ISSET(clientfd, &rfds)) {
	    if (Poll_input())
		return;
	    if (Net_flush() == -1) {
		error("Bad net flush after input");
		return;
	    }
	}
	if (FD_ISSET(netfd, &rfds) || result > 1) {
	    if ((result = Net_input()) == -1) {
		warn("Bad net input.  Have a nice day!");
		return;
	    }
	    if (result > 0) {
		if (Poll_input())
		    return;
		if (Net_flush() == -1) {
		    error("Bad net flush");
		    return;
		}
		if (Poll_input())
		    return;
	    }
	}
    }
}