1 //--------------------------------------------------------------------------
2 // Mamer.cc - Source file for the Mamer class
4 // Matthew E. Moses & Michael A. Long
7 // $Date: 1998/09/10 19:57:17 $
12 //--------------------------------------------------------------------------
14 // static char RCSid[] = "$Id: Mamer.cc,v 1.17 1998/09/10 19:57:17 mlong Exp $";
18 extern void HandleSignals(int);
20 //- Constructor ------------------------------------------------------------
23 struct tm *timeStruct;
25 theTime = time((time_t *)NULL);
26 timeStruct = localtime(&theTime);
30 memset(configFilename, '\0', MAXPATHLEN);
31 strncpy(configFilename, CONFIG_FILENAME, MIN(strlen(CONFIG_FILENAME), MAXPATHLEN));
33 channelNumber = DEFAULT_CHANNEL;
34 memset(hostname, '\0', 256);
35 strncpy(hostname, DEFAULT_HOSTNAME, MIN(strlen(DEFAULT_HOSTNAME), 256));
36 portNumber = DEFAULT_PORT;
40 memset(username, '\0', 80);
41 memset(password, '\0', 80);
42 strncpy(username, DEFAULT_USERNAME, MIN(strlen(DEFAULT_USERNAME), 80));
43 strncpy(password, DEFAULT_PASSWORD, MIN(strlen(DEFAULT_PASSWORD), 80));
45 sprintf(logFilename, "%s/%s.%04d%02d%02d",
46 DEFAULT_PATH, DEFAULT_LOG_FILE,
47 1900 + timeStruct->tm_year, timeStruct->tm_mon + 1,
50 sprintf(userFilePath, "%s/%s", DEFAULT_PATH, DEFAULT_USER_PATH);
51 sprintf(dataFilePath, "%s/%s", DEFAULT_PATH, DEFAULT_DATA_PATH);
52 sprintf(homeFilePath, "%s", DEFAULT_PATH);
54 tourneyParams.time = DEFAULT_TIME;
55 tourneyParams.inc = DEFAULT_INCREMENT;
56 tourneyParams.mode = 'r';
57 tourneyParams.style = 's';
58 tourneyParams.variant = 'r';
59 tourneyParams.rounds = DEFAULT_ROUNDS;
60 tourneyParams.ratingHigh = 9999;
61 tourneyParams.ratingLow = 0;
62 tourneyParams.maxPlayers = DEFAULT_MAX_PLAYERS;
66 //- Deconstructor ----------------------------------------------------------
72 while(0 != (u = userList.Head()))
75 while(0 != (t = tourneyList.Head()))
78 while(0 != (c = commandList.Head()))
83 //- Initialize -------------------------------------------------------------
84 int Mamer::Initialize(int argc, char **argv) {
85 struct stat statBuffer;
88 LoadConfigurationFile();
90 while(EOF != (c = getopt(argc, argv,
91 "d:D:c:C:s:S:p:P:u:U:l:L:hHa:A:n:N:"))) {
95 debugLevel = atoi(optarg);
99 channelNumber = atoi(optarg);
103 memset(hostname, '\0', 256);
104 strncpy(hostname, optarg, MIN(strlen(optarg), 256));
108 portNumber = atoi(optarg);
112 memset(userFilePath, '\0', MAXPATHLEN);
113 strncpy(userFilePath, optarg, MIN(strlen(optarg), MAXPATHLEN));
117 memset(userFilePath, '\0', MAXPATHLEN);
118 strncpy(logFilename, optarg, MIN(strlen(optarg), MAXPATHLEN));
122 memset(username, '\0', 80);
123 strncpy(username, optarg, MIN(strlen(optarg), 80));
127 memset(password, '\0', 80);
128 strncpy(password, optarg, MIN(strlen(optarg), 80));
138 if(-1 == stat(userFilePath, &statBuffer)) {
141 if(-1 == mkdir(userFilePath, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
142 printf("name = '%s'\n", userFilePath);
143 perror("create user file path");
152 signal(SIGPIPE, SIG_IGN);
153 signal(SIGTERM, HandleSignals);
154 signal(SIGKILL, HandleSignals);
155 signal(SIGUSR1, HandleSignals);
156 signal(SIGUSR2, HandleSignals);
161 } //- End of Initialize
163 //- s_and_r - Search and Replace a string within a string ------------
164 char *Mamer::s_and_r(char *s, char *tofind, char *toreplace) {
165 char *toReturn = NULL;
168 char *replace_offset;
173 /* if nothing to look at, and nothing to replace.... return nothing */
174 if ( s == NULL || tofind == NULL)
177 find_len = strlen(tofind);
178 if ( toreplace != NULL )
179 toreplace_len = strlen(toreplace);
181 toreplace_len = 0; /* allow us to have nothing to replace... acts the same a delstring */
183 currSize = (strlen(s) * 2) + 100; /* add the 100 in case s is small */
184 toReturn = (char*)malloc(currSize);
185 return_offset = toReturn;
186 while ( *s != '\0' ) {
187 if ( *s == *tofind && strncmp(s, tofind, MIN(find_len, (int)strlen(s))) == 0 ) {
188 /* if the first letter matches, and so does the rest.. */
189 /* copy in the replace string */
190 replace_offset = toreplace;
191 for ( x = 0; x < toreplace_len; x++ ) {
192 *return_offset = *replace_offset;
196 /* and move up the current position in s to just past the find string */
198 } else { /* it doesn't match.... just copy to the return and continue */
204 *return_offset = '\0';
209 //- OpenServerConnection ---------------------------------------------------
210 int Mamer::OpenServerConnection(void) {
211 struct sockaddr_in socketAddr;
212 struct hostent *hostEntry = NULL;
213 // char mesg[MAXPATHLEN] = {'\0'};
214 unsigned long inAddr;
216 //- Check is we have a decimal notation host address
217 socketAddr.sin_family = AF_INET;
218 if((unsigned long)INADDR_NONE != (inAddr = inet_addr(hostname)))
219 socketAddr.sin_addr.s_addr = inAddr;
220 else { //- Try to query a namserver to get an address
221 if(NULL == (hostEntry = gethostbyname(hostname))) {
222 cerr << "ERROR: can't resolve hostname '" << hostname
228 bcopy(hostEntry->h_addr, (char *)&socketAddr.sin_addr,
229 hostEntry->h_length);
232 serverSocket = socket(AF_INET, SOCK_STREAM, 0);
233 if(0 > serverSocket) {
234 cerr << "ERROR: can't create TCP socket." << endl;
239 socketAddr.sin_port = htons(portNumber);
240 if(0 > connect(serverSocket, (struct sockaddr *)&socketAddr,
241 sizeof(struct sockaddr_in))) {
242 cerr << "ERROR: can't create connection to server '"
243 << hostname << "' on port " << portNumber << "." << endl;
244 cerr << " " << strerror(errno) << endl;
250 } //- End of OpenServerConnection
252 //- ListenLoop -------------------------------------------------------------
253 void Mamer::ListenLoop(void) {
254 struct timeval timeout;
255 char readBuffer[4096], writeBuffer[4096], commandBuffer[4096], channelCmpStr[16];
256 char *p = NULL, *buffer = NULL, *tmpBuffer = NULL;
261 sprintf(channelCmpStr, "(%d): ", channelNumber);
262 buffer = new char[4096];
264 cerr << "ERROR: problems allocating memory" << endl;
269 tmpBuffer = new char[4096];
270 if(NULL == tmpBuffer) {
271 cerr << "ERROR: problems allocating memory" << endl;
276 timeout.tv_sec = timeout.tv_usec = 0;
280 FD_SET(serverSocket, &fdMask);
283 select(serverSocket + 3, (int *)&fdMask, (int *)0, (int *)0, &timeout);
285 select(serverSocket + 3, &fdMask, (fd_set *)0, (fd_set *)0, &timeout);
288 if(FD_ISSET(serverSocket, &fdMask)) {
290 memset(readBuffer, '\0', 4096);
291 memset(writeBuffer, '\0', 4096);
292 size = read(serverSocket, readBuffer, (sizeof(readBuffer) - 1));
295 //- fix newlines/linefeeds
296 memset(buffer, '\0', 4096);
297 strncpy(buffer, readBuffer, size);
300 if(NULL != (strstr(buffer, "\n\r\\ "))) {
301 strcpy(tmpBuffer, s_and_r(buffer, "\n\r\\ ", ""));
302 memset(buffer, '\0', 4096);
303 strcpy(buffer, tmpBuffer);
304 size = strlen(buffer);
307 if(NULL != (strstr(buffer, "\r\n\\ "))) {
308 strcpy(tmpBuffer, s_and_r(buffer, "\r\n\\ ", ""));
309 memset(buffer, '\0', 4096);
310 strcpy(buffer, tmpBuffer);
311 size = strlen(buffer);
314 if(NULL != (strstr(buffer, "\n\r "))) {
315 strcpy(tmpBuffer, s_and_r(buffer, "\n\r ", ""));
316 memset(buffer, '\0', 4096);
317 strcpy(buffer, tmpBuffer);
318 size = strlen(buffer);
321 if((FALSE == loggedInFlag) &&
322 (NULL != strstr(buffer, "login:"))) {
323 sprintf(writeBuffer, "%s\n", username);
324 write(serverSocket, writeBuffer, strlen(writeBuffer));
325 } else if((FALSE == loggedInFlag) &&
326 (NULL != strstr(buffer, "password:"))) {
328 "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s %d\n",
343 write(serverSocket, writeBuffer, strlen(writeBuffer));
345 char manager[NAMELEN], filename[128];
346 sprintf(filename, "%s/managers", dataFilePath);
347 if((theFile = fopen(filename, "r"))) {
348 while(fscanf(theFile, "%s", manager) > 0) {
349 XServerCom("qtell %s %s %s %s",
350 manager, "Howdy, ", username, " is here!\n");
357 else if(TRUE == loggedInFlag) {
360 while(('\r' == buffer[i]) ||
361 ('\n' == buffer[i]) ||
362 ('%' == buffer[i]) ||
366 while(('\r' != buffer[i]) &&
367 ('\n' != buffer[i]) &&
369 commandBuffer[j++] = buffer[i++];
370 commandBuffer[j] = '\0';
372 if(NULL != (p = strstr(commandBuffer, channelCmpStr)))
373 HandleChannel(commandBuffer);
374 else if(NULL != (p = strstr(commandBuffer, "tells you:")))
375 HandleTell(commandBuffer);
376 else if(NULL != (p = strstr(commandBuffer, "has connected")))
377 HandleConnect(commandBuffer);
378 else if(NULL != (p = strstr(commandBuffer, "has disconnected")))
379 HandleDisconnect(commandBuffer);
380 else if(0 == strncmp(commandBuffer, "{Game ", 6))
381 HandleGame(commandBuffer);
382 else if(0 == strncmp(commandBuffer, "*qtell ", 7))
383 HandleQtell(commandBuffer);
384 else if(0 == strncmp(commandBuffer, "*getgi ", 7))
385 HandleGameInfo(commandBuffer);
386 else if(0 == strncmp(commandBuffer, "*getpi ", 7))
387 HandlePlayerInfo(commandBuffer);
390 cout << "Unsupported: " << commandBuffer << endl;
395 while(('\r' == buffer[i]) ||
396 ('\n' == buffer[i]) ||
397 ('%' == buffer[i]) ||
403 if((errno == EINTR) || (errno == EAGAIN) || (errno == EIO) ||
404 (errno == EBADF) || (errno == EINVAL) || (errno == EFAULT)) {
407 printf("Error = %s\n", "EINTR");
410 printf("Error = %s\n", "EAGAIN");
413 printf("Error = %s\n", "EIO");
416 printf("Error = %s\n", "EBADF");
419 printf("Error = %s\n", "EINVAL");
422 printf("Error = %s\n", "EFAULT");
437 if(NULL != tmpBuffer)
440 } //- End of ListenLoop
442 //- Start of GivePlace ----------------------------
443 int Mamer::GivePlace(int i, Tourney *t) {
444 TourneyPlayers *tp = NULL, *place = NULL;
447 LinkListIter<TourneyPlayers> playerIter(t->playerList);
452 memset(placeName, '\0', 7);
455 strcpy(placeName, "First");
458 strcpy(placeName, "Second");
461 strcpy(placeName, "Third");
467 XServerCom("%s %i %s %s %s%i %s ", "tell", channelNumber, "Tourney Results:", placeName,
468 "place in tourney #", t->number, "goes to: ");
470 opp = t->GetSortPlayer(i);
471 place = t->GetPlayer(opp->name);
472 score = place->score;
474 while((tp = playerIter.Next())) {
475 if(tp->score == score) {
476 XServerCom("%s ", tp->name);
478 u = FindUser(tp->name);
481 u = FindUser(tp->name);
484 u->AddStat(i); // Adds a first/second/third place finish to everyone with the same score as the 1st
492 //- Start of AnnounceTourneyEnd
493 void Mamer::AnnounceTourneyEnd(Tourney *t) {
494 TourneyPlayers *tp = NULL;
495 int first=0, second=0, third=0;
496 int numberOfPlayers = 0;
502 LinkListIter<TourneyPlayers> playerIter(t->playerList);
504 while((tp = playerIter.Next())) {
505 if((tp->activeFlag) && (strcasecmp(tp->name, "_BYE_") != 0))
509 first = GivePlace(1, t); //first = number of people tied for first
511 if(numberOfPlayers >= 5) {
512 if(first == 1) { second = GivePlace(2, t); }
513 if(first == 2) { third = GivePlace(3, t); }
514 if(numberOfPlayers >= 7) {
515 if(second == 1) { third = GivePlace(3, t); }
520 //- savePlayerData --------------------------------------------------------------
521 void Mamer::savePlayerData(Tourney *t) {
522 LinkListIter<TourneyPlayers> playerIter(t->playerList);
523 TourneyPlayers *tp = NULL, *tmpOpp = NULL;
524 User *u = NULL, *manager=NULL;
527 float r, tourn_expect=0.0, pre_expect=0.0, delta = 0.0;
529 manager = FindUser(t->manager); // save the manager info
530 if(manager == NULL) {
531 manager = new User(userFilePath, t->manager); // manager isn't online
532 manager->SetLast(time(0)); // so we have to load him/her
533 manager->AddManagedTourney();
534 manager->SavePlayer(userFilePath);
536 } else { // manager is online
537 manager->SetLast(time(0));
538 manager->AddManagedTourney();
539 manager->SavePlayer(userFilePath);
542 while((tp = playerIter.Next())) {
544 u = FindUser(tp->name);
546 User *newUser = NULL;
547 newUser = new User(userFilePath, tp->name);
551 cout << "savePlayerData::" << tp->name << " " << u->name << endl;
556 pre_expect = ((float)w + (0.5 * (float)d)) / r;
558 LinkListIter<Player> opponentIter(tp->opponentList); // List of opponents this player has had
559 while((opp = opponentIter.Next())) {
560 tmpOpp = t->GetPlayer(opp->name); // need the player's information to do tourn_expect
561 delta = (float)(((tp->rating != 0) ? tp->rating : 1600) -
562 ((tmpOpp->rating != 0) ? tmpOpp->rating : 1600)); // difference in rating
563 tourn_expect = tourn_expect + (1 / (1+pow(10,(delta/400.0))));
564 u->AddStat(opp->floatValue);
566 u->AddPlayedTourney();
567 if(tp->activeFlag) { // If I didn't withdraw or get forfeited reduce my abuse points
568 u->AddAbuse(-1 * t->GetRound()); // This will be the # of rounds played because the tourney is DONE
569 XServerCom("%s %s %d%s", "tournset", tp->name, 0, "\n");
571 u->CalculateRating(tourn_expect, pre_expect);
572 u->SavePlayer(userFilePath);
574 } //- End of savePlayerData ------------------------------------------
576 //- Shutdown --------------------------------------------------------------
577 void Mamer::Shutdown(void) {
578 LinkListIter<User> userIter(userList);
581 while((u = userIter.Next())) {
582 // u->SavePlayer(userFilePath);
586 write(serverSocket, "exit\n", 5);
589 } //- End of Shutdown
591 //- Usage -----------------------------------------------------------------
592 void Mamer::Usage(void) {
593 cerr << "Usage: mamer [-c channel] [-s server] [-n port number] " << endl;
594 cerr << " [-d debug level] [-u users database filename] "
596 cerr << " [-l log filename] [-a mamer account name] " << endl;
597 cerr << " [-p mamer password] [-h help] " << endl;
599 cerr << "\t-h show usage information." << endl;
600 cerr << "\t-c sets which channel mamer should work on.\n\t (default = "
601 << channelNumber << ")" << endl;
602 cerr << "\t-s sets the server hostname that mamer connects to.\n\t"
603 << " (default = " << hostname << ")" << endl;
604 cerr << "\t-n sets the port number on the server to connect to.\n\t"
605 << " (default = " << portNumber << ")" << endl;
606 cerr << "\t-a sets the username for the account to mamer logs in as.\n\t"
607 << " (default = " << username << ")" << endl;
608 cerr << "\t-p sets the password for the mamer account.\n\t"
609 << " (default = " << password << ")" << endl;
610 cerr << "\t-d sets the debugging level. This determines how much of "
611 << "the\n\t activity of mamer is written to the logs." << endl;
612 cerr << "\t-u set the location of the users database file.\n\t"
613 << " (default = " << userFilePath << ")" << endl;
614 cerr << "\t-l sets the location of the log file.\n\t (default = "
615 << logFilename << ")" << endl;
619 //- LoadConfigurationFile -------------------------------------------------
620 void Mamer::LoadConfigurationFile(void) {
621 struct stat statBuffer;
624 if(-1 != stat(configFilename, &statBuffer)) {
626 fstream theFile(configFilename, ios::in);
628 buffer = new char[MAXPATHLEN + 80];
632 memset(buffer, '\0', MAXPATHLEN + 80);
634 while(theFile.good()) {
635 theFile.getline(buffer, MAXPATHLEN + 80 - 1, '\n');
637 if(buffer[0] == '#') continue;
638 length = strlen(buffer);
641 if(0 == strncasecmp(buffer, "HOST", 4)) {
643 while(isspace(buffer[0])) buffer++;
645 memset(hostname, '\0', MAXPATHLEN);
646 strncpy(hostname, buffer, MIN(length, MAXPATHLEN));
647 } else if(0 == strncasecmp(buffer, "DATA", 4)) {
649 while(isspace(buffer[0])) buffer++;
651 memset(dataFilePath, '\0', MAXPATHLEN);
652 strncpy(dataFilePath, buffer, MIN(length, MAXPATHLEN));
653 } else if(0 == strncasecmp(buffer, "HOME", 4)) {
655 while(isspace(buffer[0])) buffer++;
657 memset(homeFilePath, '\0', MAXPATHLEN);
658 strncpy(homeFilePath, buffer, MIN(length, MAXPATHLEN));
659 } else if(0 == strncasecmp(buffer, "HELP", 4)) {
661 while(isspace(buffer[0])) buffer++;
663 memset(helpFilePath, '\0', MAXPATHLEN);
664 strncpy(helpFilePath, buffer, MIN(length, MAXPATHLEN));
665 } else if(0 == strncasecmp(buffer, "USER", 4)) {
667 while(isspace(buffer[0])) buffer++;
669 memset(username, '\0', 80);
670 strncpy(username, buffer, MIN(length, 80));
671 } else if(0 == strncasecmp(buffer, "PASS", 4)) {
673 while(isspace(buffer[0])) buffer++;
675 memset(password, '\0', 80);
676 strncpy(password, buffer, MIN(length, 80));
677 } else if(0 == strncasecmp(buffer, "PORT", 4)) {
679 while(isspace(buffer[0])) buffer++;
681 portNumber = atoi(buffer);
682 } else if(0 == strncasecmp(buffer, "CHAN", 4)) {
684 while(isspace(buffer[0])) buffer++;
686 channelNumber = atoi(buffer);
687 } else if(0 == strncasecmp(buffer, "DBUG", 4)) {
689 while(isspace(buffer[0])) buffer++;
691 debugLevel = atoi(buffer);
695 if(0 == strncasecmp(buffer, "LOG", 3)) {
697 while(isspace(buffer[0])) buffer++;
699 memset(logFilename, '\0', MAXPATHLEN);
700 strncpy(logFilename, buffer, MIN(length, MAXPATHLEN));
701 } else if((strlen(buffer) > 3) && (0 == strncasecmp(buffer, "UDB", 3))) {
703 while(isspace(buffer[0])) buffer++;
705 memset(userFilePath, '\0', MAXPATHLEN);
706 strncpy(userFilePath, buffer, MIN(length, MAXPATHLEN));
714 cerr << "ERROR: permission denied for configuration file '"
715 << configFilename << "' using compiled defaults." << endl;
719 cerr << "WARNING: configuration file '" << configFilename
720 << "' doesn't exist, using " << endl;
721 cerr << " compiled defaults." << endl;
727 } //- End of LoadConfigurationFile
729 //- DumpConfiguration -----------------------------------------------------
730 void Mamer::DumpConfiguration(void) {
731 cout << "Mamer Configuration" << endl;
732 cout << "-------------------" << endl;
733 cout << "Hostname : " << hostname << endl;
734 cout << "Port : " << portNumber << endl;
735 cout << "Channel : " << channelNumber << endl;
737 cout << "Username : " << username << endl;
738 cout << "Password : " << password << endl;
740 cout << "Home Path: " << homeFilePath << endl;
741 cout << "Data Path: " << dataFilePath << endl;
742 cout << "Help Path: " << helpFilePath << endl;
743 cout << "User File: " << userFilePath << endl;
744 cout << "Log File : " << logFilename << endl;
746 cout << "Debug Lvl: " << debugLevel << endl;
749 } //- End of DumpConfiguration
751 //- HandleQtell ------------------------------------------------------------
752 int Mamer::HandleQtell(char *message) {
754 int isOnline; // Opposite of what is returned in qtell report
756 sscanf(message, "*qtell %s %d*", name, &isOnline);
757 isOnline = !isOnline;
771 //- HandleTell ------------------------------------------------------------
772 int Mamer::HandleTell(char *message) {
773 char *p = NULL, *q = NULL, *command = NULL, *tmpCom=NULL;
774 char user[32] = {'\0'};
775 int i=0, pos = 0, tmp=0, len = 0, ret = 0, tellSize=12; /* size of " tells you:" */
777 //- Parse apart tell message
778 //- <user> tells you: <mesg>
779 //- <user>(*) tells you: <mesg>
780 //- <user>(TM)(GM)(*)..... tells you: <mesg>
781 if((p = strstr(message, "(")) && (q = strstr(message, " tells you:")) && (strlen(p) > strlen(q))) {
782 tmp = strlen(p) - strlen(q); /* get the diff to add back in later */
783 pos = strlen(message) - strlen(p);
784 memset(user, '\0', 32);
785 strncpy(user, message, MIN(pos, 31));
786 pos += (tellSize + tmp);
788 p = strstr(message, " tells you:");
789 pos = strlen(message) - strlen(p);
790 memset(user, '\0', 32);
791 strncpy(user, message, MIN(pos, 31));
797 len = strlen(&(message[pos]));
798 command = new char[len + 1]; memset(command, '\0', (len + 1));
799 tmpCom = new char[len + 1]; memset(tmpCom, '\0', (len + 1));
800 if(NULL == command) {
801 cerr << "ERROR: problems allocating memory" << endl;
805 strncpy(command, &(message[pos]), len);
807 while((command[i] != '\0') && (command[i] != ' ')) tmpCom[i] = command[i++];
810 Command *comm = NULL;
811 comm = FindCommand(tmpCom, user);
820 if(10 <= debugLevel) {
821 cout << "Tell Msg: " << message << endl;
822 cout << "User is: " << user << " Command is: " << command<< "\n" << endl;
825 if(ParseParams(comm, command) == COM_BADPARAMETERS) {
826 TellUser(comm, user);
838 CheckUser(user); // This should never happen because we did it above.
843 if((u->GetManagerLevel()) >= (comm->GetManagerLevel())) {
844 ret = (this->*(comm->userFunction))(u, comm->params);
846 cout << comm->GetCommandName() << " return value " << ret << endl;
847 if(((ret == 2) && (!(strcasecmp(comm->GetCommandName(), "setres")))) ||
848 ((ret == 1) && (!(strcasecmp(comm->GetCommandName(), "withdraw")))) ||
849 ((ret == 1) && (!(strcasecmp(comm->GetCommandName(), "forfeit"))))) {
851 } else if ((ret != 0) && (!(strcasecmp(comm->GetCommandName(), "setmanagerlevel")))) {
852 AdjustManagerList(ret, comm->params[0].val.word);
855 TellUser(NoPermissions, user);
865 } //- End of HandleTell
867 //- HandleChannel ------------------------------------------------------------
868 int Mamer::HandleChannel(char *message) {
869 char *q, *p = NULL, channel[8], mess[1024];
870 char user[NAMELEN] = {'\0'};
871 int pos = 0, index=0;
872 char *hilist[] = {"hi ", "hello ", "howdy ", "aloha ", "hola ", "bonjour ", "tag ", NULL };
873 char *thanklist[] = {"thanks ", "thank you ", "thanx ", "gracias ", NULL };
874 char *byelist[] = {"bye ", "later ", "caio ", "adios ", "hasta la vista ", NULL };
875 char *swearlist[] = {"fuck", "shit", "god damn", "asshole", "cunt", "cock", "bullshit", "nigger", "asswipe", NULL };
877 //- Parse apart channel message
878 //- <user>(1): <mesg>
879 //- <user>(*)(24): <mesg>
880 //- <user>(TM)(49): <mesg>
881 if((p = strchr(message, '('))) {
882 pos = strlen(message) - strlen(p);
883 memset(user, '\0', NAMELEN);
884 strncpy(user, message, MIN(pos, NAMELEN-1));
888 if(0 == strcasecmp(user, username)) return 1;
890 p = strchr(message, ':');
891 while(*p != '(') p--;
893 while(*p != ')') { *q++ = *p++; }
896 p = strchr(message, ':'); p++;
898 while(*p != '\0') { *q++ = *p++; }
902 printf("%s %s %s\n", user, channel, mess);
904 mess[strlen(mess)] = '\0';
909 while (swearlist[index] != NULL) {
910 if (strstr(mess, swearlist[index])) {
911 printf("ABUSE - %s %s\n", user, mess);
912 XServerCom("%s %s\n", "+ c49muzzle", user);
917 if ((strstr(mess, username)) && (pos == 0)) {
920 while (hilist[index] != NULL) {
921 if (strstr(mess, hilist[index])) {
922 XServerCom("%s %s Hi %s :-)\n", "tell", channel, user);
929 while (thanklist[index] != NULL) {
930 if (strstr(mess, thanklist[index])) {
931 XServerCom("%s %s You're welcome %s!\n", "tell", channel, user);
938 while (byelist[index] != NULL) {
939 if (strstr(mess, byelist[index])) {
940 XServerCom("%s %s Sad to see you going, %s :(\n", "tell", channel, user);
946 if (strstr(mess, "tourn"))
947 XServerCom("%s %s %s %s %s\n",
948 "tell", channel, "To see a list of tourneys type: tell", username, "lt");
951 } //- End of HandleChannel
953 //- HandleConnect ------------------------------------------------------------
954 int Mamer::HandleConnect(char *message) {
955 char *p = NULL, *reg = NULL, user[80] = {'\0'}, output[256] = {'\0'}, tmp[32] = {'\0'};
957 TourneyPlayers *tp = NULL;
958 LinkListIter<Tourney> tourneyIter(tourneyList);
959 int announceConnect = 0;
961 //- Parse apart connect message
962 //- [<user> (R: 123.123.123.123) has connected.]
964 cout << "\nConnect Msg: " << message << endl;
966 if((p = strstr(message, " (U:"))) { return(1); }
967 if(!(p = strstr(message, " (R: "))) { return(1); }
968 strncpy(user, &(message[1]), MIN(strlen(message) - strlen(p) - 1, 79));
969 reg = strstr(message, " (R: ");
970 if(reg) { //If this is a registered user
972 while((t = tourneyIter.Next())) {
973 if((tp = t->GetPlayer(user))) {
974 tp->location = ONLINE;
978 if(announceConnect) { // If the player arriving is in a tourney tell us he is arriving.
980 sprintf(output, "%s %d %s %s", "tell", channelNumber, user, "has connected. Entered in tourney(s):");
982 while((t = tourneyIter.Next())) {
983 if(t->GetStatus() != DONE) {
984 if((tp = t->GetPlayer(user))) {
985 sprintf(tmp, " %d", t->number);
991 if(announceConnect) {
992 XServerCom("%s %s %d%s", "tournset", user, 1, "\n");
993 XServerCom("%s%s", output, "\n");
997 if(15 <= debugLevel) {
998 cout << "\nConnect Msg: " << message << endl;
999 cout << "Ignoring User: " << user << endl;
1003 } //- End of HandleConnect
1005 //- HandleDisconnect --------------------------------------------------------
1006 int Mamer::HandleDisconnect(char *message) {
1007 char *p = NULL, user[80] = {'\0'}, output[256] = {'\0'}, tmp[32] = {'\0'};
1009 TourneyPlayers *tp = NULL;
1010 LinkListIter<Tourney> tourneyIter(tourneyList);
1011 int announceDisconnect = 0;
1013 //- Parse apart disconnect message
1014 //- [<user> has disconnected.]
1015 p = strstr(message, " has disconnected.");
1016 strncpy(user, &(message[1]), MIN(strlen(message) - strlen(p) - 1, 79));
1018 if(10 <= debugLevel) {
1019 cout << "Disconnect Msg: " << message << endl;
1020 cout << "User is: " << user << "\n" << endl;
1023 LinkListIter<User> userIter(userList);
1025 while((u = userIter.Next()))
1026 if(1 == u->IsUser(user))
1030 tourneyIter.Reset();
1031 while((t = tourneyIter.Next())) {
1032 if((tp = t->GetPlayer(user))) {
1033 tp->location = GONE;
1034 announceDisconnect = 1;
1037 if(announceDisconnect) { // If the player arriving is in a tourney tell us he is arriving.
1038 announceDisconnect = 0;
1039 sprintf(output, "%s %d %s %s", "tell", channelNumber, user, "has disconnected. Entered in tourney(s):");
1040 tourneyIter.Reset();
1041 while((t = tourneyIter.Next())) {
1042 if(t->GetStatus() != DONE) {
1043 if((tp = t->GetPlayer(user))) {
1044 sprintf(tmp, " %d", t->number);
1045 strcat(output, tmp);
1046 announceDisconnect = 1;
1050 if(announceDisconnect) {
1051 XServerCom("%s %s %d%s", "tournset", user, 1, "\n");
1052 XServerCom("%s%s", output, "\n");
1055 u->SavePlayer(userFilePath);
1060 } //- End of HandleDisconnect
1062 //- AdjustManagerList ----------------------
1063 void Mamer::AdjustManagerList(int value, char *name) {
1064 Storage *tmp=NULL, *newName=NULL;
1065 LinkListIter<Storage> managerIter(storageList);
1067 char filename[128], manager[NAMELEN];
1068 int added=0, needToAdd=1;
1070 memset(filename, '\0', 128);
1071 sprintf(filename, "%s/managers", dataFilePath);
1072 theFile = fopen(filename, "r");
1073 if(theFile == NULL) return;
1075 memset(manager, '\0', NAMELEN);
1076 while(fscanf(theFile, "%s", manager) > 0) { // build the temporary list
1077 tmp = new Storage(manager, 0);
1078 storageList.Append(tmp);
1080 memset(manager, '\0', NAMELEN);
1086 managerIter.Reset(); // remove a manager from the list that is printed later
1087 while((tmp = managerIter.Next()))
1088 if(strlen(tmp->name) == strlen(name))
1089 if(0 == (strcasecmp(tmp->name, name)))
1090 storageList.Delete(tmp);
1091 XServerCom("%s %s\n", "- mamermgr", name);
1094 newName = new Storage(name, 0);
1095 added = 0; // Add a user to the manager list that is later printed
1097 managerIter.Reset(); // Got through the list see if the name is there
1098 while((tmp = managerIter.Next()))
1099 if(strlen(tmp->name) == strlen(newName->name))
1100 if(0 == strcasecmp(tmp->name, newName->name)) {
1104 if(needToAdd) { // If its not there we have to add it
1105 managerIter.Reset();
1106 while((tmp = managerIter.Next())) // if the name in the list is > new name
1107 if((strncasecmp(tmp->name, newName->name, MIN(strlen(tmp->name), strlen(newName->name)))) > 0) {
1109 storageList.Insert(tmp, newName); // insert the new name before the list name
1112 if(!added) storageList.Append(newName);
1113 XServerCom("%s %s\n", "+ mamermgr", name);
1119 theFile = fopen(filename, "w");
1120 if(!theFile) return;
1121 managerIter.Reset(); // Lets write the new manager file
1122 while((tmp = managerIter.Next())) {
1123 fprintf(theFile, "%s\n", tmp->name);
1124 storageList.Delete(tmp);
1127 // if(newName != NULL) delete(newName);
1130 //- UserIsLoaded --------------------------
1131 int Mamer::UserIsLoaded(char *uname) {
1133 LinkListIter<User> userIter(userList);
1135 while((u = userIter.Next())) {
1136 if(0 == strcasecmp(u->name, uname))
1141 }//- end UserIsLoaded ------------------------------------------------------
1143 /* this function checks if the user is loaded and if not loads the user */
1144 //- CheckUser ---------------------------------------------------------------
1145 void Mamer::CheckUser(char *user) {
1146 if(!UserIsLoaded(user)) {
1148 cout << "CheckUser - Adding User:" << user << ":" << endl;
1150 User *newUser = NULL;
1151 newUser = new User(userFilePath, user);
1153 userList.Append(newUser);
1155 }//- end of CheckUser -----------------------------------------------------
1157 //- HandleGame ------------------------------------------------------------
1158 int Mamer::HandleGame(char *message) {
1159 char *p, *q, user1[NAMELEN], user2[NAMELEN], action[256], result[8], tmp[256];
1160 int gameNumber, clocktime, inc, rated, isPrivate, result_code, moreGames=1, moreRounds=1, madeMoreGames=0, gameType=-2;
1163 TourneyPlayers *tp = NULL;
1165 printf("MESSAGE: %s\n", message);
1167 // {Game 8 (Blammor vs. Havard) Blammor resigns} 0-1
1169 sscanf(message, "{Game %d (%s vs. %s", &gameNumber, user1, user2);
1170 user2[strlen(user2)-1] = '\0';
1172 if((p = strchr(message, ')'))) {
1173 q = action; p++; p++;
1174 while((*p != '\0') && (*p != '}')) { *q++ = *p++; }
1176 } else { return 0; }
1178 memset(result, '\0', 8);
1179 if((p = strchr(message, '}')) &&
1180 ((strstr(message, ") Creating ") == NULL) && (strstr(message, ") Continuing ") == NULL))) {
1181 // sscanf(p, "} %s [%d %d %d %d", result, &clocktime, &inc, &rated, &isPrivate);
1182 sscanf(p, "} %s [%d %d %d %d %d", result, &clocktime, &inc, &rated, &isPrivate, &gameType);
1184 if(!strcmp(result, "1-0")) { result_code = 1;
1185 } else if(!strcmp(result, "0-1")) { result_code = 0;
1186 } else if(!strcmp(result, "1/2-1/2")) { result_code = 2;
1187 } else { result_code = -1; }
1190 // printf("\nGame #%d %s vs. %s action=%s result=%s time=%d inc=%d rated=%d private=%d\n",
1191 // gameNumber, user1, user2, action, result, clocktime, inc, rated, isPrivate);
1192 printf("\nGame #%d %s vs. %s action=%s result=%s time=%d inc=%d rated=%d private=%d gameType=%d\n",
1193 gameNumber, user1, user2, action, result, clocktime, inc, rated, isPrivate, gameType);
1195 LinkListIter<Tourney> tourneyIter(tourneyList);
1196 tourneyIter.Reset();
1197 while((t = tourneyIter.Next())) {
1198 if(t->GetStatus() != CLOSED) continue;
1199 LinkListIter<Game> gameIter(t->gameList);
1201 while((g = gameIter.Next())) {
1202 if(g->IsGame(user1, user2, clocktime, inc, rated, 'r')) { //- There is room to add isPrivate later
1203 XServerCom("%s %i %s %s %s %s%i %s %s %s\n", "tell", channelNumber, g->whiteName, "vs.", g->blackName,
1204 "a game in tourney #", t->number, "just ended. ", action, result);
1205 if(strcmp(result, "*") == 0) {
1209 moreGames = t->SetGameResult(user1, user2, result_code); //- SetGameResult deletes the game for us
1210 if(moreGames == 2 && !t->IsPaused()) {
1211 moreRounds = (t->GetRoundsRemaining());
1212 LinkListIter<TourneyPlayers> playerIter(t->playerList);
1215 madeMoreGames = t->MakeAssignments();
1216 while((tp = playerIter.Next())) {
1217 sprintf(tmp, "%s tells you: listplayers %d\n", tp->name, t->number);
1221 t->TellThemWhoTheyPlay();
1222 } else { // tourney over!
1223 AnnounceTourneyEnd(t);
1226 } else { // tourney over!
1228 while((tp = playerIter.Next())) {
1229 sprintf(tmp, "%s tells you: listplayers %d\n", tp->name, t->number);
1233 AnnounceTourneyEnd(t);
1242 XServerCom("%s %s %s", "getgi", user1, "\n");
1245 } //- End of HandleGame
1247 //- HandleGameInfo ----------------------------------------------------------
1248 int Mamer::HandleGameInfo(char *message) {
1249 char white[NAMELEN], black[NAMELEN], player[NAMELEN];
1250 int gameNumber, gameTime, inc, rated, isPrivate;
1254 sscanf(message, "*getgi %s %s %s %d %d %d %d %d*", player, white, black,
1255 &gameNumber, &gameTime, &inc, &rated, &isPrivate);
1257 gameTime = gameTime / 600; // Values for getgi are in micro and nano seconds
1260 LinkListIter<Tourney> tourneyIter(tourneyList);
1261 tourneyIter.Reset();
1262 while((t = tourneyIter.Next())) {
1263 if(t->GetStatus() != CLOSED) continue;
1264 LinkListIter<Game> gameIter(t->gameList);
1266 while((g = gameIter.Next())) {
1267 if(g->IsGame(white, black, gameTime, inc, rated, 'r')) { //- There is room to add isPrivate later
1268 if(g->gameNumber < 0){
1269 XServerCom("%s %i %s %s %s %s%i %s\n", "tell", channelNumber, white, "vs.", black,
1270 "a game in tourney #", t->number, "just started.");
1272 XServerCom("%s %i %s %s %s %s%i %s\n", "tell", channelNumber, white, "vs.", black,
1273 "a game in tourney #", t->number, "just Restarted.");
1275 g->gameNumber = gameNumber;
1280 } //- End of HandleGameInfo
1282 //- HandlePlayerInfo --------------------------------------------------------
1283 int Mamer::HandlePlayerInfo(char *message) {
1284 char player[NAMELEN];
1285 int ratings[6], return_from_AddPlayer, tourneyNumber;
1289 sscanf(message, "*getpi %s %d %d %d %d %d %d*", // Scan in the info
1290 player, &ratings[0], &ratings[2], &ratings[3], &ratings[1], &ratings[4], &ratings[5]);
1293 printf("Get Player Info: %s blitz=%d stand=%d light=%d wild=%d bug=%d suicide=%d\n",
1294 player, ratings[2], ratings[3], ratings[1], ratings[0], ratings[4], ratings[5]);
1296 p = FindPending(player);
1297 printf("player p=%d\n", p);
1299 tourneyNumber = p->value; // find out which tourney we want
1300 t = FindTourney(tourneyNumber); // Get the tourney. If its in the list it should be valid
1303 } //Check for valid tourney is done in CommandEntry::JoinTourney
1305 return_from_AddPlayer = t->AddPlayer(player, ratings[t->GetVariant()], 0.0);
1306 printf("ret = %d\n", return_from_AddPlayer);
1307 TellUser(JoinedTourney, player, return_from_AddPlayer);
1308 if(return_from_AddPlayer == 1)
1309 XServerCom("%s %s %d%s", "tournset", player, 1, "\n");
1310 pendingList.Delete(p); //This is safe cause to get here we had to find a Player p
1313 } //- End of HandlePlayerInfo
1315 //- FindPending ---------------------------------------------------------------
1316 Player *Mamer::FindPending(char *user) {
1318 LinkListIter<Player> pendingIter(pendingList);
1320 while((p = pendingIter.Next()))
1321 if(1 == p->IsPlayer(user))
1325 } //- End of FindPending
1327 //- FindUser ---------------------------------------------------------------
1328 User *Mamer::FindUser(char *user) {
1330 LinkListIter<User> userIter(userList);
1332 // printf("FindUser: %18s\n", user);
1334 while((u = userIter.Next()))
1335 if(1 == u->IsUser(user))
1339 } //- End of FindUser
1341 //- FindTourney ------------------------------------------------------------
1342 Tourney *Mamer::FindTourney(int tourn) {
1344 LinkListIter<Tourney> tourneyIter(tourneyList);
1346 while((t = tourneyIter.Next())) {
1347 if(1 == t->IsTourney(tourn))
1351 } //- End of FindUser
1353 //- FindCommand ---------------------------------------------------------------
1354 Command *Mamer::FindCommand(char *comm, char *user) {
1355 Command *c = NULL, *cnull=NULL;
1356 LinkListIter<Command> commIter(commandList);
1357 int commandsFound=0;
1358 char* output = NULL;
1360 output = new char[MAX_LINE_SIZE];
1361 memset(output, '\0', MAX_LINE_SIZE);
1363 while((c = commIter.Next())) {
1364 if(c->IsCommand(comm)) {
1366 if((int)(strlen(output) + strlen(c->GetCommandName())) < (MAX_LINE_SIZE - 1))
1367 sprintf(output, "%s %s", output, c->GetCommandName());
1370 output[strlen(output)] = '\0';
1373 while((c = commIter.Next()))
1374 if(1 == c->IsCommand(comm))
1377 switch (commandsFound) {
1379 TellUser(BadCommand, user);
1384 TellUser(MultiCommand, user, output);
1387 } //- End of FindUser
1390 Parameter string format
1392 o - an optional word
1394 p - optional integer
1396 n - optional word or integer
1398 t - optional string to end
1400 If the parameter option is given in lower case then the parameter is
1401 converted to lower case before being passsed to the function. If it is
1402 in upper case, then the parameter is passed as typed.
1404 Calling these Appends adds commands to the link list. They are called with:
1405 1) the text command Mamer should look for
1406 2) an alias or substitute for that text
1407 3) the manager level one needs to be to execute this command
1408 4) a BRIEF description of the command's function
1409 5) the parameter types for each parameter (see comments above)
1410 6) what code to use when telling the user they did something wrong (see TellUser)
1411 7) and the function pointer to the CommandEntry.cc code that is this command */
1413 //- BuildCommandList ---------------------------------------------------------
1414 void Mamer::BuildCommandList(void) {
1415 commandList.Append(new Command("addchaos", "ac", MANAGER, "Adds (or subs) chaos points.",
1416 "wp", (USERFP)&Mamer::AddAbuse));
1418 commandList.Append(new Command("announce", "ann", DIRECTOR, "Announce the tournament to the working channel.",
1419 "d", (USERFP)&Mamer::AnnounceTourney));
1421 commandList.Append(new Command("addtotourney", "att", VICE, "Add a user to a tourney.",
1422 "Wd", (USERFP)&Mamer::AddToTourney));
1424 commandList.Append(new Command("create", "cr", DIRECTOR, "Creates a new tournament.",
1425 "", (USERFP)&Mamer::CreateTourney));
1427 commandList.Append(new Command("close", "cl", DIRECTOR, "Closes and starts a tournament.",
1428 "d", (USERFP)&Mamer::CloseTourney));
1430 commandList.Append(new Command("delete", "del", DIRECTOR, "Deletes a tournament.",
1431 "d", (USERFP)&Mamer::DeleteTourney));
1433 commandList.Append(new Command("finger", "fi", USER, "Displays the stats for a user.",
1434 "O", (USERFP)&Mamer::FingerUser));
1436 commandList.Append(new Command("forfeit", "fo", DIRECTOR, "Remove a user from a tourney.",
1437 "wd", (USERFP)&Mamer::RemoveFromTourney));
1439 commandList.Append(new Command("join", "j", USER, "Request to enter a tourney.",
1440 "d", (USERFP)&Mamer::JoinTourney));
1442 commandList.Append(new Command("keep", "k", MANAGER, "Keep a tourney in memory.",
1443 "di", (USERFP)&Mamer::KeepTourney));
1445 commandList.Append(new Command("listmanagers", "lm", USER, "Displays the Managers list.",
1446 "", (USERFP)&Mamer::ListManagers));
1448 commandList.Append(new Command("listtourneys", "lt", USER, "Displays the tournament list.",
1449 "", (USERFP)&Mamer::ListTourneys));
1451 commandList.Append(new Command("listtourneyvars", "vars", USER, "Displays the tournament variables.",
1452 "d", (USERFP)&Mamer::ListTourneyVars));
1454 commandList.Append(new Command("listtourneygames", "games", USER, "Displays the tournament games.",
1455 "d", (USERFP)&Mamer::ListTourneyGames));
1457 commandList.Append(new Command("listplayers", "lp", USER, "Displays the players in the tourney.",
1458 "d", (USERFP)&Mamer::ListTourneyPlayers));
1460 commandList.Append(new Command("listrank", "rank", USER, "Displays player rank.",
1461 "n", (USERFP)&Mamer::ListRank));
1463 commandList.Append(new Command("loadedusers", "lu", MANAGER, "Displays the loaded users.",
1464 "", (USERFP)&Mamer::LoadedUsers));
1466 commandList.Append(new Command("messman", "mm", VICE, "Message all of the Managers.",
1467 "s", (USERFP)&Mamer::MessageManagers));
1469 commandList.Append(new Command("open", "ot", DIRECTOR, "Opens the tournament to players.",
1470 "d", (USERFP)&Mamer::OpenTourney));
1472 commandList.Append(new Command("pause", "pa", DIRECTOR, "Supresses start of new round.",
1473 "d", (USERFP)&Mamer::PauseTourney));
1475 commandList.Append(new Command("resume", "re", DIRECTOR, "Resumes a paused tournament.",
1476 "d", (USERFP)&Mamer::ResumeTourney));
1478 commandList.Append(new Command("setcommandlevel", "setcl", VICE, "Set the level required to execute a command.",
1479 "wd", (USERFP)&Mamer::SetCommandLevel));
1481 commandList.Append(new Command("setinfo", "si", VICE, "Set a user's finger info.",
1482 "Wddddddd", (USERFP)&Mamer::SetInfo));
1484 commandList.Append(new Command("setmanagerlevel", "sml", VICE, "Sets manager's level.",
1485 "Wd", (USERFP)&Mamer::SetManagerLevel));
1487 commandList.Append(new Command("setres", "sr", DIRECTOR, "Sets the result of a game.",
1488 "dWWi", (USERFP)&Mamer::SetResult));
1490 commandList.Append(new Command("setstat", "ss", VICE, "Sets a specific finger stat.",
1491 "Wwd", (USERFP)&Mamer::SetStat));
1493 commandList.Append(new Command("settourneyvar", "stv", DIRECTOR, "Sets a Tourney's Variables.",
1494 "dwi", (USERFP)&Mamer::SetTourneyVariable));
1496 commandList.Append(new Command("showcommands", "sc", USER, "List commands and descripts.",
1497 "o", (USERFP)&Mamer::ShowCommands));
1499 commandList.Append(new Command("showhelpfile", "shf", USER, "Shows a help file.",
1500 "o", (USERFP)&Mamer::ShowHelp));
1502 commandList.Append(new Command("help", "help", USER, "Shows a help file.",
1503 "o", (USERFP)&Mamer::ShowHelp));
1505 commandList.Append(new Command("shutdown", "sd", VICE, "Shuts down Mamer.",
1506 "", (USERFP)&Mamer::Shutdown));
1508 commandList.Append(new Command("who", "who", USER, "Displays the tournament games.",
1509 "d", (USERFP)&Mamer::ListTourneyPlayers));
1511 commandList.Append(new Command("withdraw", "with", USER, "Remove yourself from a tourney.",
1512 "d", (USERFP)&Mamer::RemoveFromTourney));
1514 } //- End of BuildCommandList
1516 //- NextRound -------------------------
1517 void Mamer::NextRound() {
1518 int moreGames=0, moreRounds=1, madeMoreGames=0;
1522 LinkListIter<Tourney> tourneyIter(tourneyList);
1523 tourneyIter.Reset();
1524 while((t = tourneyIter.Next())) {
1525 if(t->GetStatus() != CLOSED || t->IsPaused()) continue;
1526 moreRounds = (t->GetRoundsRemaining());
1528 LinkListIter<Game> gameIter(t->gameList);
1530 while((g = gameIter.Next())) moreGames++;
1532 if(moreGames == 0) {
1533 if(debugLevel >= 10)
1534 cout << "No more games! Next Round Please! From Next Round" << endl;
1535 cerr << "No more games! Next Round Please! From Next Round" << endl;
1537 madeMoreGames = t->MakeAssignments();
1539 t->TellThemWhoTheyPlay();
1540 else { // tourney over!
1541 cerr << "Couldn't make any more games. End of Tourney. From Next Round" << endl;
1542 AnnounceTourneyEnd(t);
1545 } else { // tourney over!
1546 cerr << "No more rounds. End of Tourney. From Next Round" << endl;
1547 AnnounceTourneyEnd(t);
1552 } //- End of NextRound
1554 //- XServerCom ---------------------------------------------
1555 int Mamer::XServerCom(char *fmt, ...)
1561 va_start(argptr, fmt);
1562 count = vsprintf(buffer, fmt, argptr);
1563 write(serverSocket, buffer, strlen(buffer));
1566 /* returns number of elements written */
1569 //- End of XServerCom
1571 //- TellUser ------------------------------------------------
1572 void Mamer::TellUser(reasons reason, char *name) {
1575 XServerCom("qtell %s %s notes: Sorry you do not have permission to do that.\n", name, username);
1578 XServerCom("qtell %s %s notes: Command not found.\n", name, username);
1583 }//- End of TellUser
1585 //- TellUser ------------------------------------------------
1586 void Mamer::TellUser(reasons reason, char *name, int number) {
1591 XServerCom("qtell %s %s notes: %s\n", name, username,
1592 "Can not join\\nYour rating does not fit into current limits. <check tourney vars>");
1595 XServerCom("qtell %s %s notes: %s\n", name, username, "You joined the tournament.");
1598 XServerCom("qtell %s %s notes: %s\n", name, username, "You are already in this tourney.");
1601 XServerCom("qtell %s %s notes: %s\n", name, username, "You can not join. Tourney is not open.");
1607 case NotEnoughPlayers:
1608 XServerCom("qtell %s %s notes: Tourney#%d %s\n", name, username, number, "does not have enough players.");
1611 XServerCom("qtell %s %s notes: Tourney#%d %s\n", name, username, number, "has no players.");
1613 case WillKeepTourney:
1614 XServerCom("qtell %s %s notes: Tourney#%d %s\n", name, username, number, "will be kept.");
1616 case NotKeepTourney:
1617 XServerCom("qtell %s %s notes: Tourney#%d %s\n", name, username, number, "will not be kept.");
1619 case TourneyNotFound:
1620 XServerCom("qtell %s %s notes: %s%d %s\n", name, username, "Tourney #", number, "not found.");
1623 XServerCom("qtell %s %s notes: %s%d\n", name, username, "Player not found in tourney #", number);
1625 case GameResultNotFound:
1626 XServerCom("qtell %s %s notes: %s%d\n", name, username, "Can not set result to ", number);
1629 XServerCom("qtell %s %s notes: You don't have change permissions for tourney #%d.\n", name, username, number);
1632 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that right now.",
1633 "Tourney #", number, "is not new.");
1635 case TourneyNotOpen:
1636 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that right now.",
1637 "Tourney #", number, "is not open.");
1639 case TourneyNotClosed:
1640 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that right now.",
1641 "Tourney #", number, "is not closed.");
1644 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that anymore.",
1645 "Tourney #", number, "is done.");
1648 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that anymore.",
1649 "Tourney #", number, "is closed.");
1651 case TourneyDeleted:
1652 XServerCom("qtell %s %s Notes: %s %s%d %s\n", name, username, "\\n", "Tourney #",
1653 number, " has been deleted.");
1658 }//- End of TellUser
1660 //- TellUser ------------------------------------------------
1661 void Mamer::TellUser(Command *comm, char *name) {
1663 int i, length=strlen(comm->parameterList);
1665 sprintf(line, "qtell %s %s notes: Usage: %s ", name, username, comm->GetCommandName());
1667 for(i=0; i<length; i++) {
1668 switch (comm->parameterList[i]) {
1670 strcat(line, "<word> ");
1673 strcat(line, "<optional word> ");
1676 strcat(line, "<integer> ");
1679 strcat(line, "<optional int> ");
1682 strcat(line, "<word or int> ");
1685 strcat(line, "<optional word or int> ");
1688 strcat(line, "<string> ");
1691 strcat(line, "<optional string> ");
1698 write(serverSocket, line, strlen(line));
1699 }//- End of TellUser
1701 //- TellUser ------------------------------------------------
1702 void Mamer::TellUser(reasons reason, char *name, char *request) {
1705 XServerCom("qtell %s %s notes: Sorry %s is not found.\n", name, username, request);
1708 XServerCom("qtell %s %s notes: %s\n", name, username, request);
1711 XServerCom("qtell %s %s notes: Changed the info for %s.\n", name, username, request);
1713 case GameResultNotFound:
1714 XServerCom("qtell %s %s notes: %s %s\n", name, username, "Can not set result to", request);
1717 XServerCom("qtell %s %s notes: Ambiguous Command Matches:\\n %s\n", name, username, request);
1722 }//- End of TellUser
1724 //- TellUser ------------------------------------------------
1725 void Mamer::TellUser(reasons reason, char *name, char *who, char *which, int new_value) {
1728 XServerCom("qtell %s %s notes: Changed the %s stat for %s to %d.\n", name, username, which, who, new_value);
1731 switch (new_value) {
1733 XServerCom("qtell %s %s notes: The game %s(w) vs. %s(b) has been set to 1-0\n", name, username, who, which);
1736 XServerCom("qtell %s %s notes: The game %s(w) vs. %s(b) has been set to 0-1\n", name, username, who, which);
1739 XServerCom("qtell %s %s notes: The game %s(w) vs. %s(b) has been set to 1/2-1/2\n", name, username, who, which);
1746 }//- End of TellUser
1748 //- TellUser ------------------------------------------------
1749 void Mamer::TellUser(reasons reason, char *name, char *which, char *new_value) {
1752 XServerCom("qtell %s %s notes: Can not change the %s var to %s.\n", name, username, which, new_value);
1755 XServerCom("qtell %s %s notes: Changed %s to %s.\n", name, username, which, new_value);
1760 }//- End of TellUser
1763 //- TellUser ------------------------------------------------
1764 void Mamer::TellUser(reasons reason, char *name, char *uname, int new_value) {
1766 case ChangedManagerLevel:
1767 XServerCom("qtell %s %s notes: %s's Manager Level has been changed to %d\n", name, username, uname,new_value);
1769 case ChangedCommandLevel:
1770 XServerCom("qtell %s %s notes: The %s command's manager Level has been changed to %d\n",name,username,uname, new_value);
1773 XServerCom("qtell %s %s notes: %s Has been removed from tourney #%i\n", name, username, uname, new_value);
1776 XServerCom("qtell %s %s notes: %s Is not found in tourney #%i\n", name, username, uname, new_value);
1779 XServerCom("qtell %s %s notes: %s's Chaos Points have been changed to %d\n",name, username, uname, new_value);
1782 XServerCom("qtell %s %s notes: Can Not Change the %s stat to %d.\n", name, username, uname, new_value);
1785 XServerCom("qtell %s %s notes: Changed %s to %d.\n", name, username, uname, new_value);
1790 }//- End of TellUser
1792 //- ParseParams ----------------------------------------------
1793 int Mamer::ParseParams(Command *comm, char *parameters) {
1798 for (i = 0; i < MAXNUMPARAMS; i++)
1799 comm->params[i].type = TYPE_NULL; /* Set all parameters to NULL */
1800 parlen = strlen(comm->parameterList);
1801 parameters = eatWhite(parameters); /* remove and spaces before the command */
1802 parameters = eatWord(parameters); /* remove the command itself */
1803 for (i = 0; i < parlen; i++) {
1804 c = comm->parameterList[i];
1813 case 'o': /* word or optional word */
1814 parameters = eatWhite(parameters);
1816 return (c == 'o' ? COM_OK : COM_BADPARAMETERS);
1817 comm->params[i].val.word = parameters;
1818 comm->params[i].type = TYPE_WORD;
1819 parameters = eatWord(parameters);
1820 if (*parameters != '\0') {
1825 stolower(comm->params[i].val.word);
1829 case 'p': /* optional or required integer */
1830 parameters = eatWhite(parameters);
1832 return (c == 'p' ? COM_OK : COM_BADPARAMETERS);
1833 if (sscanf(parameters, "%d", &comm->params[i].val.integer) != 1)
1834 return COM_BADPARAMETERS;
1835 comm->params[i].type = TYPE_INT;
1836 parameters = eatWord(parameters);
1837 if (*parameters != '\0') {
1844 case 'n': /* optional or required word or integer */
1845 parameters = eatWhite(parameters);
1847 return (c == 'n' ? COM_OK : COM_BADPARAMETERS);
1848 if (sscanf(parameters, "%d", &comm->params[i].val.integer) != 1) {
1849 comm->params[i].val.word = parameters;
1850 comm->params[i].type = TYPE_WORD;
1852 comm->params[i].type = TYPE_INT;
1854 parameters = eatWord(parameters);
1855 if (*parameters != '\0') {
1859 if (comm->params[i].type == TYPE_WORD)
1861 stolower(comm->params[i].val.word);
1865 case 't': /* optional or required string to end */
1867 return (c == 't' ? COM_OK : COM_BADPARAMETERS);
1868 comm->params[i].val.string = parameters;
1869 comm->params[i].type = TYPE_STRING;
1871 parameters = nextWord(parameters);
1873 stolower(comm->params[i].val.string);
1878 return COM_BADPARAMETERS;
1881 } //- End ParseParams ------------------
1883 //- isWhiteSpace -------------------------------------------
1884 int Mamer::isWhiteSpace (int c) {
1885 if ((c < ' ') || (c == '\b') || (c == '\n') ||
1886 (c == '\t') || (c == ' ')) { /* white */
1891 } //- End isWhiteSpace -------
1893 //- getWord ------------------------------------------------
1894 char *Mamer::getWord (char *str) {
1896 static char word[MAX_WORD_SIZE];
1899 while (*str && !isWhiteSpace(*str)) {
1903 if (i == MAX_WORD_SIZE) {
1910 } //- End getWord -------------
1912 //- eatWord -------------------------------------------
1913 char *Mamer::eatWord (char *str) {
1914 while (*str && !isWhiteSpace(*str))
1919 //- eatWhite ------------------------------------------
1920 char *Mamer::eatWhite (char *str) {
1921 while (*str && isWhiteSpace(*str))
1924 } //- eatWhite --------
1926 //- eatTailWhite -------------------------------------------
1927 char *Mamer::eatTailWhite (char *str) {
1933 while (len > 0 && isWhiteSpace(str[len - 1]))
1937 } //- End of eatTailWhite -----------
1939 //- nextWord -----------------------------------------------
1940 char *Mamer::nextWord(char *str) {
1941 return eatWhite(eatWord(str));
1942 } //- End of nextWord
1944 char *Mamer::stolower(char *str) {
1949 for (i = 0; str[i]; i++) {
1950 if (isupper(str[i])) {
1951 str[i] = tolower(str[i]);
1957 //- GenerateTourneyNumber ----------------------------------------------
1958 int Mamer::GenerateTourneyNumber(void) {
1960 int maxT = 0, used=0, i, count=0;
1961 LinkListIter<Tourney> tourneyIter(tourneyList);
1963 if(NULL != tourneyList.Head()) {
1964 while((t = tourneyIter.Next()))
1967 for(i=1; i<=count; i++) {
1969 tourneyIter.Reset();
1970 while((t = tourneyIter.Next())) {
1973 if(t->number > maxT)
1986 // $Log: Mamer.cc,v $
1987 // Revision 1.17 1998/09/10 19:57:17 mlong
1988 // lots of little bug fixes and a few new features
1990 // Revision 1.16 1998/08/04 21:02:13 mlong
1991 // changes to correct a few bugs including the this->* change that
1992 // correctly uses the function pointers now
1994 // Revision 1.15 1998/06/18 18:41:30 mlong
1995 // prepairing for yet another move.
1997 // Revision 1.14 1998/06/04 19:55:00 mlong
1998 // quick change to the load config file stuff to
1999 // allow for a commented out line
2001 // Revision 1.13 1998/04/29 15:23:19 mlong
2002 // prepairing for the move to daimi
2003 // new sorting routine.
2005 // Revision 1.12 1998/04/18 18:46:04 mlong
2006 // fixed delete bug &
2007 // added delete tourney function
2009 // Revision 1.11 1998/04/17 00:14:37 mlong
2010 // fixes to the setres working with the Link delete method
2012 // Revision 1.7 1997/10/22 19:47:38 mlong
2013 // fixed bug for parsing tells into user and command.
2015 // Revision 1.6 1997/10/08 21:03:35 chess
2016 // preparing for move to oracle machine at eworks.
2018 // Revision 1.5 1997/05/15 18:27:53 chess
2019 // added Player and TourneyPlayers support
2020 // added HandleGetPlayerInfo & HandleetGameInfo
2022 // Revision 1.4 1997/04/13 03:14:35 chess
2023 // commands to do user stats manipulation added
2024 // also TellUser function added to make for easier reporting and bug checking
2025 // also added ParseParams that takes the commands parameter list definition
2026 // and parses out the input from the user to determine if the paramters
2027 // supplied are correct. If so it then sends those params to the
2030 // Revision 1.3 1997/03/21 15:31:04 moses
2031 // added the cleanup of commands
2032 // added the cleanup of tourneys
2033 // added the mamer shutdown command
2035 // Revision 1.2 1996/10/01 20:14:43 moses
2036 // Changes to incorparte the new usage of the command list
2038 // Revision 1.1 1996/09/30 20:52:48 moses