[Tux4kids-commits] r1152 - tuxmath/branches/lan/server
David Bruce
dbruce-guest at alioth.debian.org
Tue Jul 7 00:40:23 UTC 2009
Author: dbruce-guest
Date: 2009-07-07 00:40:23 +0000 (Tue, 07 Jul 2009)
New Revision: 1152
Modified:
tuxmath/branches/lan/server/mathcards.c
tuxmath/branches/lan/server/mathcards.h
tuxmath/branches/lan/server/server.c
tuxmath/branches/lan/server/server.h
tuxmath/branches/lan/server/testclient.c
tuxmath/branches/lan/server/transtruct.h
Log:
further implementation of server and command-line client
Modified: tuxmath/branches/lan/server/mathcards.c
===================================================================
--- tuxmath/branches/lan/server/mathcards.c 2009-07-06 22:03:24 UTC (rev 1151)
+++ tuxmath/branches/lan/server/mathcards.c 2009-07-07 00:40:23 UTC (rev 1152)
@@ -185,6 +185,7 @@
MC_Options* math_opts = 0;
MC_MathQuestion* question_list = 0;
MC_MathQuestion* wrong_quests = 0;
+MC_MathQuestion* active_quests = 0;
MC_MathQuestion* next_wrong_quest = 0;
int initialized = 0;
int quest_list_length = 0;
@@ -352,7 +353,9 @@
question_list = NULL;
delete_list(wrong_quests);
wrong_quests = NULL;
-
+ delete_list(active_quests);
+ active_quests = NULL;
+
/* clear the time list */
if (time_per_question_list != NULL) {
free(time_per_question_list);
@@ -442,6 +445,8 @@
question_list = wrong_quests;
wrong_quests = 0;
next_wrong_quest = 0;
+ delete_list(active_quests);
+ active_quests = 0;
/* initialize counters for new game: */
quest_list_length = list_length(question_list);
unanswered = starting_length = quest_list_length;
@@ -503,11 +508,12 @@
/* 'draw' - copy over the first question */
copy_card(&question_list->card, fc);
- /* 'discard' - take first question node out of list and free it */
+ /* take first question node out of list and move it into active_quests list: */
question_list = remove_node(question_list, question_list);
- free_node(ptr);
+// free_node(ptr);
quest_list_length--;
questions_pending++;
+ append_node(active_quests, ptr);
#ifdef MC_DEBUG
printf("\nnext question is:");
@@ -519,6 +525,8 @@
return 1;
}
+
+
/* MC_AnsweredCorrectly() is how the user interface */
/* tells MathCards that the question has been answered */
/* correctly. Returns 1 if no errors. */
@@ -541,6 +549,7 @@
print_card(*fc);
#endif
+ //FIXME we need to take the question out of the active_quests list
answered_correctly++;
questions_pending--;
@@ -575,6 +584,11 @@
return 1;
}
+int MC_AnsweredCorrectly_id(int id)
+{
+ return 1;
+}
+
/* MC_NotAnsweredCorrectly() is how the user interface */
/* tells MathCards that the player failed to answer the */
/* question correctly. Returns 1 if no errors. */
Modified: tuxmath/branches/lan/server/mathcards.h
===================================================================
--- tuxmath/branches/lan/server/mathcards.h 2009-07-06 22:03:24 UTC (rev 1151)
+++ tuxmath/branches/lan/server/mathcards.h 2009-07-07 00:40:23 UTC (rev 1152)
@@ -205,6 +205,7 @@
/* tells MathCards that the question has been answered */
/* correctly. Returns 1 if no errors. */
int MC_AnsweredCorrectly(MC_FlashCard* q);
+int MC_AnsweredCorrectly_id(int id);
/* MC_NotAnsweredCorrectly() is how the user interface */
/* tells MathCards that the question has not been */
Modified: tuxmath/branches/lan/server/server.c
===================================================================
--- tuxmath/branches/lan/server/server.c 2009-07-06 22:03:24 UTC (rev 1151)
+++ tuxmath/branches/lan/server/server.c 2009-07-07 00:40:23 UTC (rev 1152)
@@ -49,9 +49,10 @@
void start_game(int i);
int SendQuestion(MC_FlashCard flash, TCPsocket client_sock);
int SendMessage(int message, int ques_id,char *name, TCPsocket client_sock);
+int player_msg(int i, char* msg);
+void broadcast_msg(char* msg);
+void throttle(int loop_msec);
-
-
/* "Local globals" for server.c: */
TCPsocket server_sock = NULL; /* Socket descriptor for server */
IPaddress ip;
@@ -82,9 +83,9 @@
/* ------------- Main server loop: ------------------ */
while (!quit)
{
- frame++;
- /* See if our existing clients are really still there. For */
- /* performance reasons, we don't do this on every loop: */
+// frame++;
+// /* See if our existing clients are really still there. For */
+// /* performance reasons, we don't do this on every loop: */
// if(frame%1000 == 0)
// test_connections();
@@ -92,6 +93,11 @@
update_clients();
/* Check for any pending messages from clients already connected: */
check_messages();
+ /* Limit frame rate to keep from eating all CPU: */
+ /* NOTE almost certainly could make this longer wtihout noticably */
+ /* affecting performance, but even throttling to 1 msec/loop cuts */
+ /* CPU from 100% to ~2% on my desktop - DSB */
+ throttle(1); //min loop time 1 msec
}
/* ----- Free resources before exiting: ------- */
@@ -197,7 +203,6 @@
//update_clients() sees if anyone is trying to connect, and connects if a slot
//is open and the game is not in progress. The purpose is to make sure our
//client set accurately reflects the current state.
-//FIXME we need to be able to test to see if the clients are really still connected
void update_clients(void)
{
TCPsocket temp_sock = NULL; /* Just used when client can't be accepted */
@@ -264,7 +269,13 @@
{
strncpy(client[slot].name, buffer, NAME_SIZE);
printf(" JOINED ::: %s\n", client[slot].name);
+ //Announcement for all clients:
+ snprintf(buffer, NET_BUF_LEN,
+ "Player %s has connected to the server\n",
+ client[slot].name);
+ broadcast_msg(buffer);
+
/* Add client socket to set: */
sockets_used = SDLNet_TCP_AddSocket(client_set, client[slot].sock);
if(sockets_used == -1) //No way this should happen
@@ -329,7 +340,7 @@
//NOTE Does this belong here? Seems to have more to do wth client connections.
if(game_in_progress==1)
{
- for(i = 0; i <MAX_CLIENTS; i++)
+ for(i = 0; i < MAX_CLIENTS; i++)
{
if(client[i].sock != NULL)
{
@@ -431,6 +442,7 @@
#ifdef LAN_DEBUG
printf("Buffer received from client: %s\n", buffer);
#endif
+
sscanf (buffer,"%s %d\n",
command,
&id);
@@ -450,7 +462,10 @@
game_msg_quit(i);
return(1);
}
-
+ else
+ {
+ printf("command %s not recognized\n", command);
+ }
return(0);
}
@@ -458,20 +473,18 @@
void game_msg_correct_answer(int i,int id)
{
int n;
- printf("question id %d was answered correctly by %s",id,client[i].name);
-
- /*Send score notification to all the clients except the one who answered it*/
- for(n = 0; n < MAX_CLIENTS && client[n].sock; n++)
- {
- if(n==i) /*I dont think , we would like to send it to the client who answered it*/
- continue;
- if(!SendMessage(ANSWER_CORRECT,id,client[i].name,client[n].sock))
- {
- printf("Unable to score changes\n");
- }
- }
+ char buf[NET_BUF_LEN];
+ //Announcement for server and all clients:
+ snprintf(buf, NET_BUF_LEN,
+ "question id %d was answered correctly by %s\n",
+ id, client[i].name);
+ printf("%s", buf);
+ broadcast_msg(buf);
+ //Tell mathcards so lists get updated:
+ MC_AnsweredCorrectly_id(id);
+
if (!MC_NextQuestion(&flash))
{
/* no more questions available */
@@ -560,7 +573,7 @@
remove_client(i);
}
-
+//FIXME don't think we want to allow players to shut down the server
void game_msg_quit(int i)
{
printf("Server has been shut down by %s\n",client[i].name);
@@ -576,8 +589,8 @@
int x,j;
game_in_progress = 1; //setting the game_in_progress flag to '1'
snprintf(buf, NET_BUF_LEN,
- "%s\n",
- "Success"); //FIXME what did we succeed at? This is basically a sort of handshaking signal , although it is not much needed here , but since we have a blocking recv call in the client for the case of game_in_progress , so no client join , therefore it is in accordance with that SDL_NetRecv()
+ "Player %s added for next math game\n",
+ client[i].name);
x = SDLNet_TCP_Send(client[i].sock, buf, sizeof(buf));
client[i].game_ready = 1; // Means this player is ready to start game
@@ -751,117 +764,86 @@
}
-//Commented-out copy of old check_messages() to keep ping work from
-//being lost
-// int check_messages(void)
-// {
-// int i = 0;
-// int actives = 0;
-// int msg_found = 0;
-// char buffer[NET_BUF_LEN];
-//
-// /* Check the client socket set for activity: */
-// actives = SDLNet_CheckSockets(client_set, 0);
-// if(actives == -1)
-// {
-// printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
-// //most of the time this is a system error, where perror might help you.
-// perror("SDLNet_CheckSockets");
-// }
-//
-// else if(actives)
-// {
-// #ifdef LAN_DEBUG
-// printf("There are %d sockets with activity\n", actives);
-// #endif
-//
-// // check all sockets with SDLNet_SocketReady and handle the active ones.
-// // NOTE we have to check all the slots in the set because
-// // the set will become discontinuous if someone disconnects
-// for(i = 0; i < MAX_CLIENTS; i++)
-// {
-// if((client[i].sock != NULL)
-// && (SDLNet_SocketReady(client[i].sock)))
-// {
-// #ifdef LAN_DEBUG
-// printf("client socket %d is ready\n", i);
-// #endif
-// if (SDLNet_TCP_Recv(client[i].sock, buffer, NET_BUF_LEN) > 0)
-// {
-// #ifdef LAN_DEBUG
-// printf("buffer received from client %d is: %s\n", i, buffer);
-// #endif
-// msg_found++;
-//
-// /* Here we pass the client number and the message buffer */
-// /* to a suitable function for further action: */
-// if(game_in_progress==1)
-// {
-// if(handle_client_game_msg(i, buffer))
-// return(1);
-// }
-// if(game_in_progress==0)
-// handle_client_nongame_msg(i,buffer);
-//
-// }
-// }
-// } // end of for() loop - all client sockets checked
-// // Make sure all the active sockets reported by SDLNet_CheckSockets()
-// // are accounted for:
-// if(actives == 0)
-// {
-// printf("Warning: SDLNet_CheckSockets() reported %d active sockets,\n"
-// "but only %d messages received.\n", actives, msg_found);
-// /* We can investigate further - maybe ping all the sockets, etc. */
-// for(i = 0; i < MAX_CLIENTS; i++)
-// {
-// ping_client(i);
-// }
-//
-//
-// /* Check the client socket set for activity: */
-// actives = SDLNet_CheckSockets(client_set, 5000);
-// if(actives == 0)
-// {
-// printf("No clients , All clients have disconnected...=(\n");
-// }
-//
-// else if(actives == -1)
-// {
-// printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
-// //most of the time this is a system error, where perror might help you.
-// perror("SDLNet_CheckSockets");
-// }
-//
-// else if(actives)
-// {
-// #ifdef LAN_DEBUG
-// printf("There are %d sockets with activity\n", actives);
-// #endif
-//
-// // check all sockets with SDLNet_SocketReady and handle the active ones.
-// // NOTE we have to check all the slots in the set because
-// // the set will become discontinuous if someone disconnects
-// for(i = 0; i < MAX_CLIENTS; i++)
-// {
-// if((client[i].sock != NULL)
-// && (SDLNet_SocketReady(client[i].sock)))
-// {
-// #ifdef LAN_DEBUG
-// printf("client socket %d is ready\n", i);
-// #endif
-// if (SDLNet_TCP_Recv(client[i].sock, buffer, NET_BUF_LEN) > 0)
-// {
-// #ifdef LAN_DEBUG
-// printf("buffer received from client %d is: %s\n", i, buffer);
-// #endif
-// if(strncmp(buffer,"PING_BACK",9))
-// printf("%s is connected =) \n",client[i].name);
-// }
-// }
-// }
-// }
-// }
-// }
-// }
+/* Sends a string to be displayed to player: */
+/* NOTE similar in concept to SendMessage(), but I think that */
+/* SendMessage() is too complicated -DSB */
+int player_msg(int i, char* msg)
+{
+ char buf[NET_BUF_LEN];
+
+ //Validate arguments;
+ if(i < 0 || i > MAX_CLIENTS)
+ {
+#ifdef LAN_DEBUG
+ printf("player_msg() - invalid index argument\n");
+#endif
+ return 0;
+ }
+
+ if(!client[i].sock)
+ {
+#ifdef LAN_DEBUG
+ printf("player_msg() - client socket is NULL\n");
+#endif
+ return 0;
+ }
+
+ if(!msg)
+ {
+#ifdef LAN_DEBUG
+ printf("player_msg() - msg argument is NULL\n");
+#endif
+ return 0;
+ }
+
+ //transmit:
+ snprintf(buf, NET_BUF_LEN, "%s\t%s\n", "PLAYER_MSG", msg);
+ if(SDLNet_TCP_Send(client[i].sock, buf, NET_BUF_LEN) < NET_BUF_LEN)
+ {
+ printf("The client %s is disconnected\n", client[i].name);
+ remove_client(i);
+ return 0;
+ }
+ //Success:
+ return 1;
+}
+
+
+void broadcast_msg(char* msg)
+{
+ int i = 0;
+ if (!msg)
+ return;
+ for(i = 0; i < MAX_CLIENTS; i++)
+ player_msg(i, msg);
+}
+
+
+
+void throttle(int loop_msec)
+{
+ static Uint32 now_t, last_t; //These will be zero first time through
+ int wait_t;
+
+ //Target loop time must be between 0 and 100 msec:
+ if(loop_msec < 0)
+ loop_msec = 0;
+ if(loop_msec > 100)
+ loop_msec = 100;
+
+ if (now_t == 0) //For sane behavior first time through:
+ last_t = SDL_GetTicks();
+ else
+ last_t = now_t;
+ now_t = SDL_GetTicks();
+ wait_t = (last_t + loop_msec) - now_t;
+
+ //Avoid problem if we somehow wrap past uint32 size
+ if(wait_t < 0)
+ wait_t = 0;
+ if(wait_t > loop_msec)
+ wait_t = loop_msec;
+
+ SDL_Delay(wait_t);
+}
Modified: tuxmath/branches/lan/server/server.h
===================================================================
--- tuxmath/branches/lan/server/server.h 2009-07-06 22:03:24 UTC (rev 1151)
+++ tuxmath/branches/lan/server/server.h 2009-07-07 00:40:23 UTC (rev 1152)
@@ -11,12 +11,13 @@
*/
+#ifndef SERVER_H
+#define SERVER_H
+
#include "SDL_net.h"
#define NAME_SIZE 50
-#ifndef SERVER_H
-#define SERVER_H
typedef struct client_type {
int game_ready; //game_ready = 1 , if client has said OK to start, and 0 otherwise
char name[NAME_SIZE];
Modified: tuxmath/branches/lan/server/testclient.c
===================================================================
--- tuxmath/branches/lan/server/testclient.c 2009-07-06 22:03:24 UTC (rev 1151)
+++ tuxmath/branches/lan/server/testclient.c 2009-07-07 00:40:23 UTC (rev 1152)
@@ -28,109 +28,57 @@
#include "mathcards.h"
#include "testclient.h"
-
+/* Local (to testclient.c) "globals": */
TCPsocket sd; /* Server socket descriptor */
SDLNet_SocketSet set;
-
+IPaddress ip; /* Server address */
+int len = 0;
+int sockets_used = 0;
+int quit = 0;
MC_FlashCard flash; //current question
-int quit = 0;
+/* Local function prototypes: */
+int setup_client(int argc, char **argv);
+void cleanup_client(void);
int Make_Flashcard(char *buf, MC_FlashCard* fc);
int LAN_AnsweredCorrectly(MC_FlashCard* fc);
int playgame(void);
void server_pinged(void);
+int player_msg_recvd(char* buf);
+int read_stdin_nonblock(char* buf, size_t max_length);
+void throttle(int loop_msec);
+
+
int main(int argc, char **argv)
{
- IPaddress ip; /* Server address */
- int len, sockets_used;
char buf[NET_BUF_LEN]; // for network messages from server
char buffer[NET_BUF_LEN]; // for command-line input
- char *check1;
- char name[NAME_SIZE];
-
-
-
- /* Simple parameter checking */
- if (argc < 3)
+ /* Connect to server, create socket set, get player nickname, etc: */
+ if(!setup_client(argc, argv))
{
- fprintf(stderr, "Usage: %s host port\n", argv[0]);
+ printf("setup_client() failed - exiting.\n");
exit(EXIT_FAILURE);
}
- if (SDLNet_Init() < 0)
- {
- fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
- exit(EXIT_FAILURE);
- }
-
- /* Resolve the host we are connecting to */
- if (SDLNet_ResolveHost(&ip, argv[1], atoi(argv[2])) < 0)
- {
- fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
- exit(EXIT_FAILURE);
- }
-
- /* Open a connection with the IP provided (listen on the host's port) */
- if (!(sd = SDLNet_TCP_Open(&ip)))
- {
- fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
- exit(EXIT_FAILURE);
- }
- /* We create a socket set so we can check for activity: */
- set = SDLNet_AllocSocketSet(1);
- if(!set) {
- printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());
- exit(EXIT_FAILURE);
- }
- sockets_used = SDLNet_TCP_AddSocket(set, sd);
- if(sockets_used == -1) {
- printf("SDLNet_AddSocket: %s\n", SDLNet_GetError());
- // perhaps you need to restart the set and make it bigger...
- }
+ printf("Welcome to the Tux Math Test Client!\n");
-
- /* Now we are connected. Take in nickname and send to server. */
-
- /* first just take in the name */
- printf("Enter your Name.\n");
- check1=gets(name);
- if(check1==NULL)
- printf(" gets() failed...\n");
-
- snprintf(buffer, NET_BUF_LEN,
- "%s\n",
- name);
-
- if (SDLNet_TCP_Send(sd, (void *)buffer, NET_BUF_LEN) < NET_BUF_LEN)
- {
- fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
- exit(EXIT_FAILURE);
- }
-
-#ifdef LAN_DEBUG
- printf("Sent the name of the player %s\n",check1);
-#endif
-
-
-
/* Send messages */
quit = 0;
do
{
//Get user input from command line and send it to server:
/*now display the options*/
- printf("Welcome to the Tux Math Test Client!\n");
printf("Type:\n"
"'game' to start math game;\n"
"'exit' to end client leaving server running;\n"
"'quit' to end both client and server\n>\n");
- char *check;
+ char* check;
check = fgets(buffer, NET_BUF_LEN, stdin);
//Figure out if we are trying to quit:
@@ -147,7 +95,6 @@
}
else if (strncmp(buffer, "game",4) == 0)
{
- printf("Starting Tux, of the Math Command Line ;-)\n");
playgame();
printf("Math game finished.\n");
}
@@ -158,6 +105,8 @@
"'exit' to end client leaving server running;\n"
"'quit' to end both client and server\n\n>\n");
}
+ //Limit loop to once per 10 msec so we don't eat all CPU
+ throttle(10);
}while(!quit);
SDLNet_TCP_Close(sd);
@@ -170,7 +119,86 @@
}
+/* Establish networking and identify player to server: */
+int setup_client(int argc, char **argv)
+{
+ char* check1 = NULL;
+ char name[NAME_SIZE];
+ char buffer[NET_BUF_LEN]; // for command-line input
+
+ /* Simple parameter checking */
+ if (argc < 2)
+ {
+ fprintf(stderr, "Usage: %s host\n", argv[0]);
+ return 0;
+ }
+
+ if (SDLNet_Init() < 0)
+ {
+ fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
+ return 0;
+ }
+
+ /* Resolve the host we are connecting to */
+ if (SDLNet_ResolveHost(&ip, argv[1], DEFAULT_PORT) < 0)
+ {
+ fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
+ return 0;
+ }
+
+ /* Open a connection with the IP provided (listen on the host's port) */
+ if (!(sd = SDLNet_TCP_Open(&ip)))
+ {
+ fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
+ return 0;
+ }
+
+ /* We create a socket set so we can check for activity: */
+ set = SDLNet_AllocSocketSet(1);
+ if(!set)
+ {
+ printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());
+ return 0;
+ }
+
+ sockets_used = SDLNet_TCP_AddSocket(set, sd);
+ if(sockets_used == -1)
+ {
+ printf("SDLNet_AddSocket: %s\n", SDLNet_GetError());
+ // perhaps you need to restart the set and make it bigger...
+ return 0;
+ }
+ /* Now we are connected. Take in nickname and send to server. */
+ printf("Please enter your name:\n>\n");
+ check1 = fgets(buffer, NAME_SIZE, stdin);
+ strncpy(name, check1, NAME_SIZE);
+ /* If no nickname received, use default: */
+ if(strlen(name) == 1)
+ strcpy(name, "Anonymous Coward");
+
+ printf("name is %s, length %d\n", name, strlen(name));
+ printf("buffer is %s, length %d\n", buffer, strlen(buffer));
+
+ snprintf(buffer, NET_BUF_LEN, "%s", name);
+
+
+ if (SDLNet_TCP_Send(sd, (void*)buffer, NET_BUF_LEN) < NET_BUF_LEN)
+ {
+ fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
+ return 0;
+ }
+
+#ifdef LAN_DEBUG
+ printf("Sent the name of the player %s\n",check1);
+#endif
+
+ return 1;
+}
+
+
+
+
int LAN_AnsweredCorrectly(MC_FlashCard* fc)
{
int len;
@@ -267,28 +295,27 @@
char buf[NET_BUF_LEN];
char buffer[NET_BUF_LEN];
char ch;
- char* term;
- size_t bytes_read = 0;
/* Set stdin to be non-blocking: */
+ /* FIXME we might need to turn this back to blocking when we leave playgame() */
fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NONBLOCK);
-#ifdef LAN_DEBUG
- printf("Entering playgame()\n");
-#endif
+ printf("\nStarting Tux, of the Math Command Line ;-)\n");
+ printf("Waiting for other players to be ready...\n\n");
+
- snprintf(buffer, NET_BUF_LEN,
+ snprintf(buffer, NET_BUF_LEN,
"%s\n",
"START_GAME");
- len = strlen(buffer) + 1;
- if (SDLNet_TCP_Send(sd, (void *)buffer, NET_BUF_LEN) < NET_BUF_LEN)
- {
- fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
- exit(EXIT_FAILURE);
- }
- #ifdef LAN_DEBUG
- printf("Sent the game notification %s\n",buffer);
+ len = strlen(buffer) + 1;
+ if (SDLNet_TCP_Send(sd, (void *)buffer, NET_BUF_LEN) < NET_BUF_LEN)
+ {
+ fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
+ exit(EXIT_FAILURE);
+ }
+#ifdef LAN_DEBUG
+ printf("Sent the game notification %s\n",buffer);
#endif
@@ -361,9 +388,12 @@
// Presumably we want to print the message to stdout
printf("%s\n", buf);
}
-
- else if(strncmp(command,"PING", strlen("PING")) == 0)
+ else if(strncmp(command,"PLAYER_MSG", strlen("PLAYER_MSG")) == 0)
{
+ player_msg_recvd(buf);
+ }
+ else if(strncmp(command,"PING", strlen("PING")) == 0)
+ {
server_pinged();
}
}
@@ -375,57 +405,47 @@
#endif
//Now we check for any user responses
-// while(have_question && !end)
- {
- buf[0] = '\0';
- bytes_read = fread (buf, 1, NET_BUF_LEN, stdin);
- term = strchr(buf, '\n');
- if (term)
- *term = '\0';
-
-#ifdef LAN_DEBUG
-// printf("\nbytes_read is %d\n", bytes_read);
-// printf("buf is %s\n", buf);
-#endif
-
- if(bytes_read == 0)
+ //This function returns 1 and updates buf with input from
+ //stdin if input is present.
+ //If no input, it returns 0 without blocking or waiting
+ if(read_stdin_nonblock(buf, NET_BUF_LEN))
+ {
+ if ((strncmp(buf, "quit", 4) == 0)
+ ||(strncmp(buf, "exit", 4) == 0)
+ ||(strncmp(buf, "q", 1) == 0))
{
-// printf("no input\n");
-// SDL_Delay(2000);
+ quit = 1; //So we exit loop in main()
+ end = 1; //Exit our loop in playgame()
}
+ else if(strncmp(buf,"PLAYER_MSG", strlen("PLAYER_MSG")) == 0)
+ {
+ player_msg_recvd(buf);
+ }
else
{
- if ((strncmp(buf, "quit", 4) == 0)
- ||(strncmp(buf, "exit", 4) == 0)
- ||(strncmp(buf, "q", 1) == 0))
- {
- quit = 1; //So we exit loop in main()
- end = 1; //Exit our loop in playgame()
+ /*NOTE atoi() will return zero for any string that is not
+ a valid int, not just '0' - should not be a big deal for
+ our test program - DSB */
+ ans = atoi(buf);
+ if(have_question && (ans == flash.answer))
+ {
+ have_question = 0;
+ printf("%s is correct!\nRequesting next question...\n>\n", buf);
+
+ //Tell server we answered it right:
+ if(!LAN_AnsweredCorrectly(&flash))
+ {
+ printf("Unable to communicate the same to server\n");
+ exit(EXIT_FAILURE);
+ }
}
- else
- {
- /*NOTE atoi() will return zero for any string that is not
- a valid int, not just '0' - should not be a big deal for
- our test program - DSB */
- ans = atoi(buf);
- if(have_question && (ans == flash.answer))
- {
- have_question = 0;
- printf("%s is correct!\nRequesting next question...\n>\n", buf);
+ else //we got input, but not the correct answer:
+ printf("Sorry, %s is incorrect. Try again!\n>\n", buf);
+ } //input wasn't any of our keywords
+ } // Input was received
- //Tell server we answered it right:
- if(!LAN_AnsweredCorrectly(&flash))
- {
- printf("Unable to communicate the same to server\n");
- exit(EXIT_FAILURE);
- }
- }
- else //we got input, but not the correct answer:
- printf("Sorry, %s is incorrect. Try again!\n>\n", buf);
- } //input wasn't any of our keywords
- } // Input was received
- } // End of while loop
+ throttle(10); //so don't eat all CPU
} //End of game loop
#ifdef LAN_DEBUG
printf("Leaving playgame()\n");
@@ -433,3 +453,71 @@
}
+//Goes past the title field in the tab-delimited buffer
+//and prints the rest to stdout:
+int player_msg_recvd(char* buf)
+{
+ char* p = strchr(buf, '\t');
+ if(p)
+ {
+ p++;
+ printf("%s\n", p);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+//Here we read up to max_length bytes from stdin into the buffer.
+//The first '\n' in the buffer, if present, is replaced with a
+//null terminator.
+//returns 0 if no data ready, 1 if at least one byte read.
+
+int read_stdin_nonblock(char* buf, size_t max_length)
+{
+ int bytes_read = 0;
+ char* term = NULL;
+ buf[0] = '\0';
+
+ bytes_read = fread (buf, 1, max_length, stdin);
+ term = strchr(buf, '\n');
+ if (term)
+ *term = '\0';
+
+ if(bytes_read > 0)
+ bytes_read = 1;
+ else
+ bytes_read = 0;
+
+ return bytes_read;
+}
+
+
+
+void throttle(int loop_msec)
+{
+ static Uint32 now_t, last_t; //These will be zero first time through
+ int wait_t;
+
+ //Target loop time must be between 0 and 100 msec:
+ if(loop_msec < 0)
+ loop_msec = 0;
+ if(loop_msec > 100)
+ loop_msec = 100;
+
+ if (now_t == 0) //For sane behavior first time through:
+ last_t = SDL_GetTicks();
+ else
+ last_t = now_t;
+ now_t = SDL_GetTicks();
+ wait_t = (last_t + loop_msec) - now_t;
+
+ //Avoid problem if we somehow wrap past uint32 size
+ if(wait_t < 0)
+ wait_t = 0;
+ if(wait_t > loop_msec)
+ wait_t = loop_msec;
+
+ SDL_Delay(wait_t);
+}
+
Modified: tuxmath/branches/lan/server/transtruct.h
===================================================================
--- tuxmath/branches/lan/server/transtruct.h 2009-07-06 22:03:24 UTC (rev 1151)
+++ tuxmath/branches/lan/server/transtruct.h 2009-07-07 00:40:23 UTC (rev 1152)
@@ -14,7 +14,7 @@
#ifndef TRANSTRUCT_H
#define TRANSTRUCT_H
-//#define LAN_DEBUG
+#define LAN_DEBUG
#define NET_BUF_LEN 512
#define DEFAULT_PORT 4779
#define NAME_SIZE 50
More information about the Tux4kids-commits
mailing list