1 //--------------------------------------------------------------------------
2 // Mamer.cc - Source file for the Mamer class
4 // Matthew E. Moses & Michael A. Long
7 // $Date: 2002/07/02 00:05:19 $
9 //--------------------------------------------------------------------------
13 extern void HandleSignals(int);
15 //- Constructor ------------------------------------------------------------
18 struct tm *timeStruct;
20 theTime = time((time_t *)NULL);
21 timeStruct = localtime(&theTime);
25 memset(configFilename, '\0', MAXPATHLEN);
26 strncpy(configFilename, CONFIG_FILENAME, MIN(strlen(CONFIG_FILENAME), MAXPATHLEN));
28 channelNumber = DEFAULT_CHANNEL;
29 memset(hostname, '\0', 256);
30 strncpy(hostname, DEFAULT_HOSTNAME, MIN(strlen(DEFAULT_HOSTNAME), 256));
31 portNumber = DEFAULT_PORT;
35 memset(username, '\0', 80);
36 memset(password, '\0', 80);
37 strncpy(username, DEFAULT_USERNAME, MIN(strlen(DEFAULT_USERNAME), 80));
38 strncpy(password, DEFAULT_PASSWORD, MIN(strlen(DEFAULT_PASSWORD), 80));
40 sprintf(logFilename, "%s/%s.%04d%02d%02d",
41 DEFAULT_PATH, DEFAULT_LOG_FILE,
42 1900 + timeStruct->tm_year, timeStruct->tm_mon + 1,
45 sprintf(userFilePath, "%s/%s", DEFAULT_PATH, DEFAULT_USER_PATH);
46 sprintf(dataFilePath, "%s/%s", DEFAULT_PATH, DEFAULT_DATA_PATH);
47 sprintf(homeFilePath, "%s", DEFAULT_PATH);
49 tourneyParams.time = DEFAULT_TIME;
50 tourneyParams.inc = DEFAULT_INCREMENT;
51 tourneyParams.mode = 'r';
52 tourneyParams.style = 's';
53 tourneyParams.variant = 'r';
54 tourneyParams.rounds = DEFAULT_ROUNDS;
55 tourneyParams.ratingHigh = 9999;
56 tourneyParams.ratingLow = 0;
57 tourneyParams.maxPlayers = DEFAULT_MAX_PLAYERS;
61 //- Deconstructor ----------------------------------------------------------
67 while(0 != (u = userList.Head()))
70 while(0 != (t = tourneyList.Head()))
73 while(0 != (c = commandList.Head()))
78 //- Initialize -------------------------------------------------------------
79 int Mamer::Initialize(int argc, char **argv) {
80 struct stat statBuffer;
83 LoadConfigurationFile();
85 while(EOF != (c = getopt(argc, argv,
86 "d:D:c:C:s:S:p:P:u:U:l:L:hHa:A:n:N:"))) {
90 debugLevel = atoi(optarg);
94 channelNumber = atoi(optarg);
98 memset(hostname, '\0', 256);
99 strncpy(hostname, optarg, MIN(strlen(optarg), 256));
103 portNumber = atoi(optarg);
107 memset(userFilePath, '\0', MAXPATHLEN);
108 strncpy(userFilePath, optarg, MIN(strlen(optarg), MAXPATHLEN));
112 memset(userFilePath, '\0', MAXPATHLEN);
113 strncpy(logFilename, optarg, MIN(strlen(optarg), MAXPATHLEN));
117 memset(username, '\0', 80);
118 strncpy(username, optarg, MIN(strlen(optarg), 80));
122 memset(password, '\0', 80);
123 strncpy(password, optarg, MIN(strlen(optarg), 80));
133 if(-1 == stat(userFilePath, &statBuffer)) {
136 if(-1 == mkdir(userFilePath, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
137 perror("create user file path");
146 signal(SIGPIPE, SIG_IGN);
147 signal(SIGTERM, HandleSignals);
148 signal(SIGKILL, HandleSignals);
149 signal(SIGUSR1, HandleSignals);
150 signal(SIGUSR2, HandleSignals);
155 } //- End of Initialize
157 //- s_and_r - Search and Replace a string within a string ------------
158 char *Mamer::s_and_r(char *s, char *tofind, char *toreplace) {
159 char *toReturn = NULL;
162 char *replace_offset;
167 /* if nothing to look at, and nothing to replace.... return nothing */
168 if ( s == NULL || tofind == NULL)
171 find_len = strlen(tofind);
172 if ( toreplace != NULL )
173 toreplace_len = strlen(toreplace);
175 toreplace_len = 0; /* allow us to have nothing to replace... acts the same a delstring */
177 currSize = (strlen(s) * 2) + 100; /* add the 100 in case s is small */
178 toReturn = (char*)malloc(currSize);
179 return_offset = toReturn;
180 while ( *s != '\0' ) {
181 if ( *s == *tofind && strncmp(s, tofind, MIN(find_len, (int)strlen(s))) == 0 ) {
182 /* if the first letter matches, and so does the rest.. */
183 /* copy in the replace string */
184 replace_offset = toreplace;
185 for ( x = 0; x < toreplace_len; x++ ) {
186 *return_offset = *replace_offset;
190 /* and move up the current position in s to just past the find string */
192 } else { /* it doesn't match.... just copy to the return and continue */
198 *return_offset = '\0';
203 //- OpenServerConnection ---------------------------------------------------
204 int Mamer::OpenServerConnection(void) {
205 struct sockaddr_in socketAddr;
206 struct hostent *hostEntry = NULL;
207 // char mesg[MAXPATHLEN] = {'\0'};
208 unsigned long inAddr;
210 //- Check is we have a decimal notation host address
211 socketAddr.sin_family = AF_INET;
212 if((unsigned long)INADDR_NONE != (inAddr = inet_addr(hostname)))
213 socketAddr.sin_addr.s_addr = inAddr;
214 else { //- Try to query a namserver to get an address
215 if(NULL == (hostEntry = gethostbyname(hostname))) {
216 cerr << "ERROR: can't resolve hostname '" << hostname
222 bcopy(hostEntry->h_addr, (char *)&socketAddr.sin_addr,
223 hostEntry->h_length);
226 serverSocket = socket(AF_INET, SOCK_STREAM, 0);
227 if(0 > serverSocket) {
228 cerr << "ERROR: can't create TCP socket." << endl;
233 socketAddr.sin_port = htons(portNumber);
234 if(0 > connect(serverSocket, (struct sockaddr *)&socketAddr,
235 sizeof(struct sockaddr_in))) {
236 cerr << "ERROR: can't create connection to server '"
237 << hostname << "' on port " << portNumber << "." << endl;
238 cerr << " " << strerror(errno) << endl;
244 } //- End of OpenServerConnection
246 //- ListenLoop -------------------------------------------------------------
247 void Mamer::ListenLoop(void) {
248 struct timeval timeout;
249 char readBuffer[4096], writeBuffer[4096], commandBuffer[4096], channelCmpStr[16];
250 char *p = NULL, *buffer = NULL, *tmpBuffer = NULL;
255 sprintf(channelCmpStr, "(%d): ", channelNumber);
256 buffer = new char[4096];
258 cerr << "ERROR: problems allocating memory" << endl;
263 tmpBuffer = new char[4096];
264 if(NULL == tmpBuffer) {
265 cerr << "ERROR: problems allocating memory" << endl;
270 timeout.tv_sec = timeout.tv_usec = 0;
274 FD_SET(serverSocket, &fdMask);
277 select(serverSocket + 3, (int *)&fdMask, (int *)0, (int *)0, &timeout);
279 select(serverSocket + 3, &fdMask, (fd_set *)0, (fd_set *)0, &timeout);
282 if(FD_ISSET(serverSocket, &fdMask)) {
284 memset(readBuffer, '\0', 4096);
285 memset(writeBuffer, '\0', 4096);
286 size = read(serverSocket, readBuffer, (sizeof(readBuffer) - 1));
289 //- fix newlines/linefeeds
290 memset(buffer, '\0', 4096);
291 strncpy(buffer, readBuffer, size);
294 if(NULL != (strstr(buffer, "\n\r\\ "))) {
295 strcpy(tmpBuffer, s_and_r(buffer, "\n\r\\ ", ""));
296 memset(buffer, '\0', 4096);
297 strcpy(buffer, tmpBuffer);
298 size = strlen(buffer);
301 if(NULL != (strstr(buffer, "\r\n\\ "))) {
302 strcpy(tmpBuffer, s_and_r(buffer, "\r\n\\ ", ""));
303 memset(buffer, '\0', 4096);
304 strcpy(buffer, tmpBuffer);
305 size = strlen(buffer);
308 if(NULL != (strstr(buffer, "\n\r "))) {
309 strcpy(tmpBuffer, s_and_r(buffer, "\n\r ", ""));
310 memset(buffer, '\0', 4096);
311 strcpy(buffer, tmpBuffer);
312 size = strlen(buffer);
315 if((FALSE == loggedInFlag) &&
316 (NULL != strstr(buffer, "login:"))) {
317 sprintf(writeBuffer, "%s\n", username);
318 write(serverSocket, writeBuffer, strlen(writeBuffer));
319 } else if((FALSE == loggedInFlag) &&
320 (NULL != strstr(buffer, "password:"))) {
322 "%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",
337 write(serverSocket, writeBuffer, strlen(writeBuffer));
339 char manager[NAMELEN], filename[128];
340 sprintf(filename, "%s/managers", dataFilePath);
341 if((theFile = fopen(filename, "r"))) {
342 while(fscanf(theFile, "%s", manager) > 0) {
343 XServerCom("qtell %s %s %s %s",
344 manager, "Howdy, ", username, " is here!\n");
351 else if(TRUE == loggedInFlag) {
354 while(('\r' == buffer[i]) ||
355 ('\n' == buffer[i]) ||
356 ('%' == buffer[i]) ||
360 while(('\r' != buffer[i]) &&
361 ('\n' != buffer[i]) &&
363 commandBuffer[j++] = buffer[i++];
364 commandBuffer[j] = '\0';
366 if(NULL != (p = strstr(commandBuffer, channelCmpStr)))
367 HandleChannel(commandBuffer);
368 else if(NULL != (p = strstr(commandBuffer, "tells you:")))
369 HandleTell(commandBuffer);
370 else if(NULL != (p = strstr(commandBuffer, "has connected")))
371 HandleConnect(commandBuffer);
372 else if(NULL != (p = strstr(commandBuffer, "has disconnected")))
373 HandleDisconnect(commandBuffer);
374 else if(0 == strncmp(commandBuffer, "{Game ", 6))
375 HandleGame(commandBuffer);
376 else if(0 == strncmp(commandBuffer, "*qtell ", 7))
377 HandleQtell(commandBuffer);
378 else if(0 == strncmp(commandBuffer, "*getgi ", 7))
379 HandleGameInfo(commandBuffer);
380 else if(0 == strncmp(commandBuffer, "*getpi ", 7))
381 HandlePlayerInfo(commandBuffer);
384 cout << "Unsupported: " << commandBuffer << endl;
389 while(('\r' == buffer[i]) ||
390 ('\n' == buffer[i]) ||
391 ('%' == buffer[i]) ||
397 if((errno == EINTR) || (errno == EAGAIN) || (errno == EIO) ||
398 (errno == EBADF) || (errno == EINVAL) || (errno == EFAULT)) {
401 printf("Error = %s\n", "EINTR");
404 printf("Error = %s\n", "EAGAIN");
407 printf("Error = %s\n", "EIO");
410 printf("Error = %s\n", "EBADF");
413 printf("Error = %s\n", "EINVAL");
416 printf("Error = %s\n", "EFAULT");
431 if(NULL != tmpBuffer)
434 } //- End of ListenLoop
436 //- Start of GivePlace ----------------------------
437 int Mamer::GivePlace(int i, Tourney *t) {
438 TourneyPlayers *tp = NULL, *place = NULL;
441 LinkListIter<TourneyPlayers> playerIter(t->playerList);
446 memset(placeName, '\0', 7);
449 strcpy(placeName, "First");
452 strcpy(placeName, "Second");
455 strcpy(placeName, "Third");
461 XServerCom("%s %i %s %s %s%i %s ", "tell", channelNumber, "Tourney Results:", placeName,
462 "place in tourney #", t->number, "goes to: ");
464 opp = t->GetSortPlayer(i);
465 place = t->GetPlayer(opp->name);
466 score = place->score;
468 while((tp = playerIter.Next())) {
469 if(tp->score == score) {
470 XServerCom("%s ", tp->name);
472 u = FindUser(tp->name);
475 u = FindUser(tp->name);
478 u->AddStat(i); // Adds a first/second/third place finish to everyone with the same score as the 1st
486 //- Start of AnnounceTourneyEnd
487 void Mamer::AnnounceTourneyEnd(Tourney *t) {
488 TourneyPlayers *tp = NULL;
489 int first=0, second=0, third=0;
490 int numberOfPlayers = 0;
496 LinkListIter<TourneyPlayers> playerIter(t->playerList);
498 while((tp = playerIter.Next())) {
499 if((tp->activeFlag) && (strcasecmp(tp->name, "_BYE_") != 0))
503 first = GivePlace(1, t); //first = number of people tied for first
505 if(numberOfPlayers >= 5) {
506 if(first == 1) { second = GivePlace(2, t); }
507 if(first == 2) { third = GivePlace(3, t); }
508 if(numberOfPlayers >= 7) {
509 if(second == 1) { third = GivePlace(3, t); }
514 //- savePlayerData --------------------------------------------------------------
515 void Mamer::savePlayerData(Tourney *t) {
516 LinkListIter<TourneyPlayers> playerIter(t->playerList);
517 TourneyPlayers *tp = NULL, *tmpOpp = NULL;
518 User *u = NULL, *manager=NULL;
521 float r, tourn_expect=0.0, pre_expect=0.0, delta = 0.0;
523 manager = FindUser(t->manager); // save the manager info
524 if(manager == NULL) {
525 manager = new User(userFilePath, t->manager); // manager isn't online
526 manager->SetLast(time(0)); // so we have to load him/her
527 manager->AddManagedTourney();
528 manager->SavePlayer(userFilePath);
530 } else { // manager is online
531 manager->SetLast(time(0));
532 manager->AddManagedTourney();
533 manager->SavePlayer(userFilePath);
536 while((tp = playerIter.Next())) {
538 u = FindUser(tp->name);
540 User *newUser = NULL;
541 newUser = new User(userFilePath, tp->name);
545 cout << "savePlayerData::" << tp->name << " " << u->name << endl;
550 pre_expect = ((float)w + (0.5 * (float)d)) / r;
552 LinkListIter<Player> opponentIter(tp->opponentList); // List of opponents this player has had
553 while((opp = opponentIter.Next())) {
554 tmpOpp = t->GetPlayer(opp->name); // need the player's information to do tourn_expect
555 delta = (float)(((tp->rating != 0) ? tp->rating : 1600) -
556 ((tmpOpp->rating != 0) ? tmpOpp->rating : 1600)); // difference in rating
557 tourn_expect = tourn_expect + (1 / (1+pow(10,(delta/400.0))));
558 u->AddStat(opp->floatValue);
560 u->AddPlayedTourney();
561 if(tp->activeFlag) { // If I didn't withdraw or get forfeited reduce my abuse points
562 u->AddAbuse(-1 * t->GetRound()); // This will be the # of rounds played because the tourney is DONE
563 XServerCom("%s %s %d%s", "tournset", tp->name, 0, "\n");
565 u->CalculateRating(tourn_expect, pre_expect);
566 u->SavePlayer(userFilePath);
568 } //- End of savePlayerData ------------------------------------------
570 //- Shutdown --------------------------------------------------------------
571 void Mamer::Shutdown(void) {
572 LinkListIter<User> userIter(userList);
575 while((u = userIter.Next())) {
576 // u->SavePlayer(userFilePath);
580 write(serverSocket, "exit\n", 5);
583 } //- End of Shutdown
585 //- Usage -----------------------------------------------------------------
586 void Mamer::Usage(void) {
587 cerr << "Usage: mamer [-c channel] [-s server] [-n port number] " << endl;
588 cerr << " [-d debug level] [-u users database filename] "
590 cerr << " [-l log filename] [-a mamer account name] " << endl;
591 cerr << " [-p mamer password] [-h help] " << endl;
593 cerr << "\t-h show usage information." << endl;
594 cerr << "\t-c sets which channel mamer should work on.\n\t (default = "
595 << channelNumber << ")" << endl;
596 cerr << "\t-s sets the server hostname that mamer connects to.\n\t"
597 << " (default = " << hostname << ")" << endl;
598 cerr << "\t-n sets the port number on the server to connect to.\n\t"
599 << " (default = " << portNumber << ")" << endl;
600 cerr << "\t-a sets the username for the account to mamer logs in as.\n\t"
601 << " (default = " << username << ")" << endl;
602 cerr << "\t-p sets the password for the mamer account.\n\t"
603 << " (default = " << password << ")" << endl;
604 cerr << "\t-d sets the debugging level. This determines how much of "
605 << "the\n\t activity of mamer is written to the logs." << endl;
606 cerr << "\t-u set the location of the users database file.\n\t"
607 << " (default = " << userFilePath << ")" << endl;
608 cerr << "\t-l sets the location of the log file.\n\t (default = "
609 << logFilename << ")" << endl;
613 //- LoadConfigurationFile -------------------------------------------------
614 void Mamer::LoadConfigurationFile(void) {
615 struct stat statBuffer;
618 if(-1 != stat(configFilename, &statBuffer)) {
620 fstream theFile(configFilename, ios::in);
622 buffer = new char[MAXPATHLEN + 80];
626 memset(buffer, '\0', MAXPATHLEN + 80);
628 while(theFile.good()) {
629 theFile.getline(buffer, MAXPATHLEN + 80 - 1, '\n');
631 if(buffer[0] == '#') continue;
632 length = strlen(buffer);
635 if(0 == strncasecmp(buffer, "HOST", 4)) {
637 while(isspace(buffer[0])) buffer++;
639 memset(hostname, '\0', MAXPATHLEN);
640 strncpy(hostname, buffer, MIN(length, MAXPATHLEN));
641 } else if(0 == strncasecmp(buffer, "DATA", 4)) {
643 while(isspace(buffer[0])) buffer++;
645 memset(dataFilePath, '\0', MAXPATHLEN);
646 strncpy(dataFilePath, buffer, MIN(length, MAXPATHLEN));
647 } else if(0 == strncasecmp(buffer, "HOME", 4)) {
649 while(isspace(buffer[0])) buffer++;
651 memset(homeFilePath, '\0', MAXPATHLEN);
652 strncpy(homeFilePath, buffer, MIN(length, MAXPATHLEN));
653 } else if(0 == strncasecmp(buffer, "HELP", 4)) {
655 while(isspace(buffer[0])) buffer++;
657 memset(helpFilePath, '\0', MAXPATHLEN);
658 strncpy(helpFilePath, buffer, MIN(length, MAXPATHLEN));
659 } else if(0 == strncasecmp(buffer, "USER", 4)) {
661 while(isspace(buffer[0])) buffer++;
663 memset(username, '\0', 80);
664 strncpy(username, buffer, MIN(length, 80));
665 } else if(0 == strncasecmp(buffer, "PASS", 4)) {
667 while(isspace(buffer[0])) buffer++;
669 memset(password, '\0', 80);
670 strncpy(password, buffer, MIN(length, 80));
671 } else if(0 == strncasecmp(buffer, "PORT", 4)) {
673 while(isspace(buffer[0])) buffer++;
675 portNumber = atoi(buffer);
676 } else if(0 == strncasecmp(buffer, "CHAN", 4)) {
678 while(isspace(buffer[0])) buffer++;
680 channelNumber = atoi(buffer);
681 } else if(0 == strncasecmp(buffer, "DBUG", 4)) {
683 while(isspace(buffer[0])) buffer++;
685 debugLevel = atoi(buffer);
689 if(0 == strncasecmp(buffer, "LOG", 3)) {
691 while(isspace(buffer[0])) buffer++;
693 memset(logFilename, '\0', MAXPATHLEN);
694 strncpy(logFilename, buffer, MIN(length, MAXPATHLEN));
695 } else if((strlen(buffer) > 3) && (0 == strncasecmp(buffer, "UDB", 3))) {
697 while(isspace(buffer[0])) buffer++;
699 memset(userFilePath, '\0', MAXPATHLEN);
700 strncpy(userFilePath, buffer, MIN(length, MAXPATHLEN));
708 cerr << "ERROR: permission denied for configuration file '"
709 << configFilename << "' using compiled defaults." << endl;
713 cerr << "WARNING: configuration file '" << configFilename
714 << "' doesn't exist, using " << endl;
715 cerr << " compiled defaults." << endl;
721 } //- End of LoadConfigurationFile
723 //- DumpConfiguration -----------------------------------------------------
724 void Mamer::DumpConfiguration(void) {
725 cout << "Mamer Configuration" << endl;
726 cout << "-------------------" << endl;
727 cout << "Hostname : " << hostname << endl;
728 cout << "Port : " << portNumber << endl;
729 cout << "Channel : " << channelNumber << endl;
731 cout << "Username : " << username << endl;
732 cout << "Password : " << password << endl;
734 cout << "Home Path: " << homeFilePath << endl;
735 cout << "Data Path: " << dataFilePath << endl;
736 cout << "Help Path: " << helpFilePath << endl;
737 cout << "User File: " << userFilePath << endl;
738 cout << "Log File : " << logFilename << endl;
740 cout << "Debug Lvl: " << debugLevel << endl;
743 } //- End of DumpConfiguration
745 //- HandleQtell ------------------------------------------------------------
746 int Mamer::HandleQtell(char *message) {
748 int isOnline; // Opposite of what is returned in qtell report
750 sscanf(message, "*qtell %s %d*", name, &isOnline);
751 isOnline = !isOnline;
765 //- HandleTell ------------------------------------------------------------
766 int Mamer::HandleTell(char *message) {
767 char *p = NULL, *q = NULL, *command = NULL, *tmpCom=NULL;
768 char user[32] = {'\0'};
769 int i=0, pos = 0, tmp=0, len = 0, ret = 0, tellSize=12; /* size of " tells you:" */
771 //- Parse apart tell message
772 //- <user> tells you: <mesg>
773 //- <user>(*) tells you: <mesg>
774 //- <user>(TM)(GM)(*)..... tells you: <mesg>
775 if((p = strstr(message, "(")) && (q = strstr(message, " tells you:")) && (strlen(p) > strlen(q))) {
776 tmp = strlen(p) - strlen(q); /* get the diff to add back in later */
777 pos = strlen(message) - strlen(p);
778 memset(user, '\0', 32);
779 strncpy(user, message, MIN(pos, 31));
780 pos += (tellSize + tmp);
782 p = strstr(message, " tells you:");
783 pos = strlen(message) - strlen(p);
784 memset(user, '\0', 32);
785 strncpy(user, message, MIN(pos, 31));
791 len = strlen(&(message[pos]));
792 command = new char[len + 1]; memset(command, '\0', (len + 1));
793 tmpCom = new char[len + 1]; memset(tmpCom, '\0', (len + 1));
794 if(NULL == command) {
795 cerr << "ERROR: problems allocating memory" << endl;
799 strncpy(command, &(message[pos]), len);
801 while((command[i] != '\0') && (command[i] != ' ')) tmpCom[i] = command[i++];
804 Command *comm = NULL;
805 comm = FindCommand(tmpCom, user);
814 if(10 <= debugLevel) {
815 cout << "Tell Msg: " << message << endl;
816 cout << "User is: " << user << " Command is: " << command<< "\n" << endl;
819 if(ParseParams(comm, command) == COM_BADPARAMETERS) {
820 TellUser(comm, user);
832 CheckUser(user); // This should never happen because we did it above.
837 if((u->GetManagerLevel()) >= (comm->GetManagerLevel())) {
838 ret = (this->*(comm->userFunction))(u, comm->params);
840 cout << comm->GetCommandName() << " return value " << ret << endl;
841 if(((ret == 2) && (!(strcasecmp(comm->GetCommandName(), "setres")))) ||
842 ((ret == 1) && (!(strcasecmp(comm->GetCommandName(), "withdraw")))) ||
843 ((ret == 1) && (!(strcasecmp(comm->GetCommandName(), "forfeit"))))) {
845 } else if ((ret != 0) && (!(strcasecmp(comm->GetCommandName(), "setmanagerlevel")))) {
846 AdjustManagerList(ret, comm->params[0].val.word);
849 TellUser(NoPermissions, user);
859 } //- End of HandleTell
861 //- HandleChannel ------------------------------------------------------------
862 int Mamer::HandleChannel(char *message) {
863 char *q, *p = NULL, channel[8], mess[1024];
864 char user[NAMELEN] = {'\0'};
865 int pos = 0, index=0;
866 char *hilist[] = {"hi ", "hello ", "howdy ", "aloha ", "hola ", "bonjour ", "tag ", NULL };
867 char *thanklist[] = {"thanks ", "thank you ", "thanx ", "gracias ", NULL };
868 char *byelist[] = {"bye ", "later ", "caio ", "adios ", "hasta la vista ", NULL };
869 char *swearlist[] = {"fuck", "shit", "god damn", "asshole", "cunt", "cock", "bullshit", "nigger", "asswipe", NULL };
871 //- Parse apart channel message
872 //- <user>(1): <mesg>
873 //- <user>(*)(24): <mesg>
874 //- <user>(TM)(49): <mesg>
875 if((p = strchr(message, '('))) {
876 pos = strlen(message) - strlen(p);
877 memset(user, '\0', NAMELEN);
878 strncpy(user, message, MIN(pos, NAMELEN-1));
882 if(0 == strcasecmp(user, username)) return 1;
884 p = strchr(message, ':');
885 while(*p != '(') p--;
887 while(*p != ')') { *q++ = *p++; }
890 p = strchr(message, ':'); p++;
892 while(*p != '\0') { *q++ = *p++; }
896 printf("%s %s %s\n", user, channel, mess);
898 mess[strlen(mess)] = '\0';
903 while (swearlist[index] != NULL) {
904 if (strstr(mess, swearlist[index])) {
905 printf("ABUSE - %s %s\n", user, mess);
906 XServerCom("%s %s\n", "+ c49muzzle", user);
911 if ((strstr(mess, username)) && (pos == 0)) {
914 while (hilist[index] != NULL) {
915 if (strstr(mess, hilist[index])) {
916 XServerCom("%s %s Hi %s :-)\n", "tell", channel, user);
923 while (thanklist[index] != NULL) {
924 if (strstr(mess, thanklist[index])) {
925 XServerCom("%s %s You're welcome %s!\n", "tell", channel, user);
932 while (byelist[index] != NULL) {
933 if (strstr(mess, byelist[index])) {
934 XServerCom("%s %s Sad to see you going, %s :(\n", "tell", channel, user);
940 if (strstr(mess, "tourn"))
941 XServerCom("%s %s %s %s %s\n",
942 "tell", channel, "To see a list of tourneys type: tell", username, "lt");
945 } //- End of HandleChannel
947 //- HandleConnect ------------------------------------------------------------
948 int Mamer::HandleConnect(char *message) {
949 char *p = NULL, *reg = NULL, user[80] = {'\0'}, output[256] = {'\0'}, tmp[32] = {'\0'};
951 TourneyPlayers *tp = NULL;
952 LinkListIter<Tourney> tourneyIter(tourneyList);
953 int announceConnect = 0;
955 //- Parse apart connect message
956 //- [<user> (R: 123.123.123.123) has connected.]
958 cout << "\nConnect Msg: " << message << endl;
960 if((p = strstr(message, " (U:"))) { return(1); }
961 if(!(p = strstr(message, " (R: "))) { return(1); }
962 strncpy(user, &(message[1]), MIN(strlen(message) - strlen(p) - 1, 79));
963 reg = strstr(message, " (R: ");
964 if(reg) { //If this is a registered user
966 while((t = tourneyIter.Next())) {
967 if((tp = t->GetPlayer(user))) {
968 tp->location = ONLINE;
972 if(announceConnect) { // If the player arriving is in a tourney tell us he is arriving.
974 sprintf(output, "%s %d %s %s", "tell", channelNumber, user, "has connected. Entered in tourney(s):");
976 while((t = tourneyIter.Next())) {
977 if(t->GetStatus() != DONE) {
978 if((tp = t->GetPlayer(user))) {
979 sprintf(tmp, " %d", t->number);
985 if(announceConnect) {
986 XServerCom("%s %s %d%s", "tournset", user, 1, "\n");
987 XServerCom("%s%s", output, "\n");
991 if(15 <= debugLevel) {
992 cout << "\nConnect Msg: " << message << endl;
993 cout << "Ignoring User: " << user << endl;
997 } //- End of HandleConnect
999 //- HandleDisconnect --------------------------------------------------------
1000 int Mamer::HandleDisconnect(char *message) {
1001 char *p = NULL, user[80] = {'\0'}, output[256] = {'\0'}, tmp[32] = {'\0'};
1003 TourneyPlayers *tp = NULL;
1004 LinkListIter<Tourney> tourneyIter(tourneyList);
1005 int announceDisconnect = 0;
1007 //- Parse apart disconnect message
1008 //- [<user> has disconnected.]
1009 p = strstr(message, " has disconnected.");
1010 strncpy(user, &(message[1]), MIN(strlen(message) - strlen(p) - 1, 79));
1012 if(10 <= debugLevel) {
1013 cout << "Disconnect Msg: " << message << endl;
1014 cout << "User is: " << user << "\n" << endl;
1017 LinkListIter<User> userIter(userList);
1019 while((u = userIter.Next()))
1020 if(1 == u->IsUser(user))
1024 tourneyIter.Reset();
1025 while((t = tourneyIter.Next())) {
1026 if((tp = t->GetPlayer(user))) {
1027 tp->location = GONE;
1028 announceDisconnect = 1;
1031 if(announceDisconnect) { // If the player arriving is in a tourney tell us he is arriving.
1032 announceDisconnect = 0;
1033 sprintf(output, "%s %d %s %s", "tell", channelNumber, user, "has disconnected. Entered in tourney(s):");
1034 tourneyIter.Reset();
1035 while((t = tourneyIter.Next())) {
1036 if(t->GetStatus() != DONE) {
1037 if((tp = t->GetPlayer(user))) {
1038 sprintf(tmp, " %d", t->number);
1039 strcat(output, tmp);
1040 announceDisconnect = 1;
1044 if(announceDisconnect) {
1045 XServerCom("%s %s %d%s", "tournset", user, 1, "\n");
1046 XServerCom("%s%s", output, "\n");
1049 u->SavePlayer(userFilePath);
1054 } //- End of HandleDisconnect
1056 //- AdjustManagerList ----------------------
1057 void Mamer::AdjustManagerList(int value, char *name) {
1058 Storage *tmp=NULL, *newName=NULL;
1059 LinkListIter<Storage> managerIter(storageList);
1061 char filename[128], manager[NAMELEN];
1062 int added=0, needToAdd=1;
1064 memset(filename, '\0', 128);
1065 sprintf(filename, "%s/managers", dataFilePath);
1066 theFile = fopen(filename, "r");
1067 if(theFile == NULL) return;
1069 memset(manager, '\0', NAMELEN);
1070 while(fscanf(theFile, "%s", manager) > 0) { // build the temporary list
1071 tmp = new Storage(manager, 0);
1072 storageList.Append(tmp);
1074 memset(manager, '\0', NAMELEN);
1080 managerIter.Reset(); // remove a manager from the list that is printed later
1081 while((tmp = managerIter.Next()))
1082 if(strlen(tmp->name) == strlen(name))
1083 if(0 == (strcasecmp(tmp->name, name)))
1084 storageList.Delete(tmp);
1085 XServerCom("%s %s\n", "- mamermgr", name);
1088 newName = new Storage(name, 0);
1089 added = 0; // Add a user to the manager list that is later printed
1091 managerIter.Reset(); // Got through the list see if the name is there
1092 while((tmp = managerIter.Next()))
1093 if(strlen(tmp->name) == strlen(newName->name))
1094 if(0 == strcasecmp(tmp->name, newName->name)) {
1098 if(needToAdd) { // If its not there we have to add it
1099 managerIter.Reset();
1100 while((tmp = managerIter.Next())) // if the name in the list is > new name
1101 if((strncasecmp(tmp->name, newName->name, MIN(strlen(tmp->name), strlen(newName->name)))) > 0) {
1103 storageList.Insert(tmp, newName); // insert the new name before the list name
1106 if(!added) storageList.Append(newName);
1107 XServerCom("%s %s\n", "+ mamermgr", name);
1113 theFile = fopen(filename, "w");
1114 if(!theFile) return;
1115 managerIter.Reset(); // Lets write the new manager file
1116 while((tmp = managerIter.Next())) {
1117 fprintf(theFile, "%s\n", tmp->name);
1118 storageList.Delete(tmp);
1121 // if(newName != NULL) delete(newName);
1124 //- UserIsLoaded --------------------------
1125 int Mamer::UserIsLoaded(char *uname) {
1127 LinkListIter<User> userIter(userList);
1129 while((u = userIter.Next())) {
1130 if(0 == strcasecmp(u->name, uname))
1135 }//- end UserIsLoaded ------------------------------------------------------
1137 /* this function checks if the user is loaded and if not loads the user */
1138 //- CheckUser ---------------------------------------------------------------
1139 void Mamer::CheckUser(char *user) {
1140 if(!UserIsLoaded(user)) {
1142 cout << "CheckUser - Adding User:" << user << ":" << endl;
1144 User *newUser = NULL;
1145 newUser = new User(userFilePath, user);
1147 userList.Append(newUser);
1149 }//- end of CheckUser -----------------------------------------------------
1151 //- HandleGame ------------------------------------------------------------
1152 int Mamer::HandleGame(char *message) {
1153 char *p, *q, user1[NAMELEN], user2[NAMELEN], action[256], result[8], tmp[256];
1154 int gameNumber, clocktime, inc, rated, isPrivate, result_code, moreGames=1, moreRounds=1, madeMoreGames=0, gameType=-2;
1157 TourneyPlayers *tp = NULL;
1159 // {Game 8 (Blammor vs. Havard) Blammor resigns} 0-1
1161 sscanf(message, "{Game %d (%s vs. %s", &gameNumber, user1, user2);
1162 user2[strlen(user2)-1] = '\0';
1164 if((p = strchr(message, ')'))) {
1165 q = action; p++; p++;
1166 while((*p != '\0') && (*p != '}')) { *q++ = *p++; }
1168 } else { return 0; }
1170 memset(result, '\0', 8);
1171 if((p = strchr(message, '}')) &&
1172 ((strstr(message, ") Creating ") == NULL) && (strstr(message, ") Continuing ") == NULL))) {
1173 // sscanf(p, "} %s [%d %d %d %d", result, &clocktime, &inc, &rated, &isPrivate);
1174 sscanf(p, "} %s [%d %d %d %d %d", result, &clocktime, &inc, &rated, &isPrivate, &gameType);
1176 if(!strcmp(result, "1-0")) { result_code = 1;
1177 } else if(!strcmp(result, "0-1")) { result_code = 0;
1178 } else if(!strcmp(result, "1/2-1/2")) { result_code = 2;
1179 } else { result_code = -1; }
1182 // printf("\nGame #%d %s vs. %s action=%s result=%s time=%d inc=%d rated=%d private=%d\n",
1183 // gameNumber, user1, user2, action, result, clocktime, inc, rated, isPrivate);
1184 printf("\nGame #%d %s vs. %s action=%s result=%s time=%d inc=%d rated=%d private=%d gameType=%d\n",
1185 gameNumber, user1, user2, action, result, clocktime, inc, rated, isPrivate, gameType);
1187 LinkListIter<Tourney> tourneyIter(tourneyList);
1188 tourneyIter.Reset();
1189 while((t = tourneyIter.Next())) {
1190 if(t->GetStatus() != CLOSED) continue;
1191 LinkListIter<Game> gameIter(t->gameList);
1193 while((g = gameIter.Next())) {
1194 if(g->IsGame(user1, user2, clocktime, inc, rated, 'r')) { //- There is room to add isPrivate later
1195 XServerCom("%s %i %s %s %s %s%i %s %s %s\n", "tell", channelNumber, g->whiteName, "vs.", g->blackName,
1196 "a game in tourney #", t->number, "just ended. ", action, result);
1197 if(strcmp(result, "*") == 0) {
1201 moreGames = t->SetGameResult(user1, user2, result_code); //- SetGameResult deletes the game for us
1202 if(moreGames == 2) {
1203 moreRounds = (t->GetRoundsRemaining());
1204 LinkListIter<TourneyPlayers> playerIter(t->playerList);
1207 madeMoreGames = t->MakeAssignments();
1208 while((tp = playerIter.Next())) {
1209 sprintf(tmp, "%s tells you: listplayers %d\n", tp->name, t->number);
1213 t->TellThemWhoTheyPlay();
1214 } else { // tourney over!
1215 AnnounceTourneyEnd(t);
1218 } else { // tourney over!
1220 while((tp = playerIter.Next())) {
1221 sprintf(tmp, "%s tells you: listplayers %d\n", tp->name, t->number);
1225 AnnounceTourneyEnd(t);
1234 XServerCom("%s %s %s", "getgi", user1, "\n");
1237 } //- End of HandleGame
1239 //- HandleGameInfo ----------------------------------------------------------
1240 int Mamer::HandleGameInfo(char *message) {
1241 char white[NAMELEN], black[NAMELEN], player[NAMELEN];
1242 int gameNumber, gameTime, inc, rated, isPrivate;
1246 sscanf(message, "*getgi %s %s %s %d %d %d %d %d*", player, white, black,
1247 &gameNumber, &gameTime, &inc, &rated, &isPrivate);
1249 gameTime = gameTime / 600; // Values for getgi are in micro and nano seconds
1252 LinkListIter<Tourney> tourneyIter(tourneyList);
1253 tourneyIter.Reset();
1254 while((t = tourneyIter.Next())) {
1255 if(t->GetStatus() != CLOSED) continue;
1256 LinkListIter<Game> gameIter(t->gameList);
1258 while((g = gameIter.Next())) {
1259 if(g->IsGame(white, black, gameTime, inc, rated, 'r')) { //- There is room to add isPrivate later
1260 if(g->gameNumber < 0){
1261 XServerCom("%s %i %s %s %s %s%i %s\n", "tell", channelNumber, white, "vs.", black,
1262 "a game in tourney #", t->number, "just started.");
1264 XServerCom("%s %i %s %s %s %s%i %s\n", "tell", channelNumber, white, "vs.", black,
1265 "a game in tourney #", t->number, "just Restarted.");
1267 g->gameNumber = gameNumber;
1272 } //- End of HandleGameInfo
1274 //- HandlePlayerInfo --------------------------------------------------------
1275 int Mamer::HandlePlayerInfo(char *message) {
1276 char player[NAMELEN];
1277 int ratings[6], return_from_AddPlayer, tourneyNumber;
1281 sscanf(message, "*getpi %s %d %d %d %d %d %d*", // Scan in the info
1282 player, &ratings[0], &ratings[2], &ratings[3], &ratings[1], &ratings[4], &ratings[5]);
1285 printf("Get Player Info: %s blitz=%d stand=%d light=%d wild=%d bug=%d suicide=%d\n",
1286 player, ratings[2], ratings[3], ratings[1], ratings[0], ratings[4], ratings[5]);
1288 p = FindPending(player);
1291 tourneyNumber = p->value; // find out which tourney we want
1292 t = FindTourney(tourneyNumber); // Get the tourney. If its in the list it should be valid
1295 } //Check for valid tourney is done in CommandEntry::JoinTourney
1297 return_from_AddPlayer = t->AddPlayer(player, ratings[t->GetVariant()], 0.0);
1298 TellUser(JoinedTourney, player, return_from_AddPlayer);
1299 if(return_from_AddPlayer == 1)
1300 XServerCom("%s %s %d%s", "tournset", player, 1, "\n");
1301 pendingList.Delete(p); //This is safe cause to get here we had to find a Player p
1304 } //- End of HandlePlayerInfo
1306 //- FindPending ---------------------------------------------------------------
1307 Player *Mamer::FindPending(char *user) {
1309 LinkListIter<Player> pendingIter(pendingList);
1311 while((p = pendingIter.Next()))
1312 if(1 == p->IsPlayer(user))
1316 } //- End of FindPending
1318 //- FindUser ---------------------------------------------------------------
1319 User *Mamer::FindUser(char *user) {
1321 LinkListIter<User> userIter(userList);
1323 // printf("FindUser: %18s\n", user);
1325 while((u = userIter.Next()))
1326 if(1 == u->IsUser(user))
1330 } //- End of FindUser
1332 //- FindTourney ------------------------------------------------------------
1333 Tourney *Mamer::FindTourney(int tourn) {
1335 LinkListIter<Tourney> tourneyIter(tourneyList);
1337 while((t = tourneyIter.Next())) {
1338 if(1 == t->IsTourney(tourn))
1342 } //- End of FindUser
1344 //- FindCommand ---------------------------------------------------------------
1345 Command *Mamer::FindCommand(char *comm, char *user) {
1346 Command *c = NULL, *cnull=NULL;
1347 LinkListIter<Command> commIter(commandList);
1348 int commandsFound=0;
1349 char* output = NULL;
1351 output = new char[MAX_LINE_SIZE];
1352 memset(output, '\0', MAX_LINE_SIZE);
1354 while((c = commIter.Next())) {
1355 if(c->IsCommand(comm)) {
1357 if((int)(strlen(output) + strlen(c->GetCommandName())) < (MAX_LINE_SIZE - 1))
1358 sprintf(output, "%s %s", output, c->GetCommandName());
1361 output[strlen(output)] = '\0';
1364 while((c = commIter.Next()))
1365 if(1 == c->IsCommand(comm))
1368 switch (commandsFound) {
1370 TellUser(BadCommand, user);
1375 TellUser(MultiCommand, user, output);
1378 } //- End of FindUser
1381 Parameter string format
1383 o - an optional word
1385 p - optional integer
1387 n - optional word or integer
1389 t - optional string to end
1391 If the parameter option is given in lower case then the parameter is
1392 converted to lower case before being passsed to the function. If it is
1393 in upper case, then the parameter is passed as typed.
1395 Calling these Appends adds commands to the link list. They are called with:
1396 1) the text command Mamer should look for
1397 2) an alias or substitute for that text
1398 3) the manager level one needs to be to execute this command
1399 4) a BRIEF description of the command's function
1400 5) the parameter types for each parameter (see comments above)
1401 6) what code to use when telling the user they did something wrong (see TellUser)
1402 7) and the function pointer to the CommandEntry.cc code that is this command */
1404 //- BuildCommandList ---------------------------------------------------------
1405 void Mamer::BuildCommandList(void) {
1406 commandList.Append(new Command("addchaos", "ac", MANAGER, "Adds (or subs) chaos points.",
1407 "wp", (USERFP)&Mamer::AddAbuse));
1409 commandList.Append(new Command("announce", "ann", DIRECTOR, "Announce the tournament to the working channel.",
1410 "d", (USERFP)&Mamer::AnnounceTourney));
1412 commandList.Append(new Command("addtotourney", "att", VICE, "Add a user to a tourney.",
1413 "Wd", (USERFP)&Mamer::AddToTourney));
1415 commandList.Append(new Command("create", "cr", DIRECTOR, "Creates a new tournament.",
1416 "", (USERFP)&Mamer::CreateTourney));
1418 commandList.Append(new Command("close", "cl", DIRECTOR, "Closes and starts a tournament.",
1419 "d", (USERFP)&Mamer::CloseTourney));
1421 commandList.Append(new Command("delete", "del", DIRECTOR, "Deletes a tournament.",
1422 "d", (USERFP)&Mamer::DeleteTourney));
1424 commandList.Append(new Command("finger", "fi", USER, "Displays the stats for a user.",
1425 "O", (USERFP)&Mamer::FingerUser));
1427 commandList.Append(new Command("forfeit", "fo", DIRECTOR, "Remove a user from a tourney.",
1428 "wd", (USERFP)&Mamer::RemoveFromTourney));
1430 commandList.Append(new Command("join", "j", USER, "Request to enter a tourney.",
1431 "d", (USERFP)&Mamer::JoinTourney));
1433 commandList.Append(new Command("keep", "k", MANAGER, "Keep a tourney in memory.",
1434 "di", (USERFP)&Mamer::KeepTourney));
1436 commandList.Append(new Command("listmanagers", "lm", USER, "Displays the Managers list.",
1437 "", (USERFP)&Mamer::ListManagers));
1439 commandList.Append(new Command("listtourneys", "lt", USER, "Displays the tournament list.",
1440 "", (USERFP)&Mamer::ListTourneys));
1442 commandList.Append(new Command("listtourneyvars", "vars", USER, "Displays the tournament variables.",
1443 "d", (USERFP)&Mamer::ListTourneyVars));
1445 commandList.Append(new Command("listtourneygames", "games", USER, "Displays the tournament games.",
1446 "d", (USERFP)&Mamer::ListTourneyGames));
1448 commandList.Append(new Command("listplayers", "lp", USER, "Displays the players in the tourney.",
1449 "d", (USERFP)&Mamer::ListTourneyPlayers));
1451 commandList.Append(new Command("listrank", "rank", USER, "Displays player rank.",
1452 "n", (USERFP)&Mamer::ListRank));
1454 commandList.Append(new Command("loadedusers", "lu", MANAGER, "Displays the loaded users.",
1455 "", (USERFP)&Mamer::LoadedUsers));
1457 commandList.Append(new Command("messman", "mm", VICE, "Message all of the Managers.",
1458 "s", (USERFP)&Mamer::MessageManagers));
1460 commandList.Append(new Command("open", "ot", DIRECTOR, "Opens the tournament to players.",
1461 "d", (USERFP)&Mamer::OpenTourney));
1463 commandList.Append(new Command("setcommandlevel", "setcl", VICE, "Set the level required to execute a command.",
1464 "wd", (USERFP)&Mamer::SetCommandLevel));
1466 commandList.Append(new Command("setinfo", "si", VICE, "Set a user's finger info.",
1467 "Wddddddd", (USERFP)&Mamer::SetInfo));
1469 commandList.Append(new Command("setmanagerlevel", "sml", VICE, "Sets manager's level.",
1470 "Wd", (USERFP)&Mamer::SetManagerLevel));
1472 commandList.Append(new Command("setres", "sr", DIRECTOR, "Sets the result of a game.",
1473 "dWWi", (USERFP)&Mamer::SetResult));
1475 commandList.Append(new Command("setstat", "ss", VICE, "Sets a specific finger stat.",
1476 "Wwd", (USERFP)&Mamer::SetStat));
1478 commandList.Append(new Command("settourneyvar", "stv", DIRECTOR, "Sets a Tourney's Variables.",
1479 "dwi", (USERFP)&Mamer::SetTourneyVariable));
1481 commandList.Append(new Command("showcommands", "sc", USER, "List commands and descripts.",
1482 "o", (USERFP)&Mamer::ShowCommands));
1484 commandList.Append(new Command("showhelpfile", "shf", USER, "Shows a help file.",
1485 "o", (USERFP)&Mamer::ShowHelp));
1487 commandList.Append(new Command("help", "help", USER, "Shows a help file.",
1488 "o", (USERFP)&Mamer::ShowHelp));
1490 commandList.Append(new Command("shutdown", "sd", VICE, "Shuts down Mamer.",
1491 "", (USERFP)&Mamer::Shutdown));
1493 commandList.Append(new Command("who", "who", USER, "Displays the tournament games.",
1494 "d", (USERFP)&Mamer::ListTourneyPlayers));
1496 commandList.Append(new Command("withdraw", "with", USER, "Remove yourself from a tourney.",
1497 "d", (USERFP)&Mamer::RemoveFromTourney));
1499 } //- End of BuildCommandList
1501 //- NextRound -------------------------
1502 void Mamer::NextRound() {
1503 int moreGames=0, moreRounds=1, madeMoreGames=0;
1507 LinkListIter<Tourney> tourneyIter(tourneyList);
1508 tourneyIter.Reset();
1509 while((t = tourneyIter.Next())) {
1510 if(t->GetStatus() != CLOSED) continue;
1511 moreRounds = (t->GetRoundsRemaining());
1513 LinkListIter<Game> gameIter(t->gameList);
1515 while((g = gameIter.Next())) moreGames++;
1517 if(moreGames == 0) {
1518 if(debugLevel >= 10)
1519 cout << "No more games! Next Round Please! From Next Round" << endl;
1520 cerr << "No more games! Next Round Please! From Next Round" << endl;
1522 madeMoreGames = t->MakeAssignments();
1524 t->TellThemWhoTheyPlay();
1525 else { // tourney over!
1526 cerr << "Coulnd't make any more games. End of Tourney. From Next Round" << endl;
1527 AnnounceTourneyEnd(t);
1530 } else { // tourney over!
1531 cerr << "No more rounds. End of Tourney. From Next Round" << endl;
1532 AnnounceTourneyEnd(t);
1537 } //- End of NextRound
1539 //- XServerCom ---------------------------------------------
1540 int Mamer::XServerCom(char *fmt, ...)
1546 va_start(argptr, fmt);
1547 count = vsprintf(buffer, fmt, argptr);
1548 write(serverSocket, buffer, strlen(buffer));
1551 /* returns number of elements written */
1554 //- End of XServerCom
1556 //- TellUser ------------------------------------------------
1557 void Mamer::TellUser(reasons reason, char *name) {
1560 XServerCom("qtell %s %s notes: Sorry you do not have permission to do that.\n", name, username);
1563 XServerCom("qtell %s %s notes: Command not found.\n", name, username);
1568 }//- End of TellUser
1570 //- TellUser ------------------------------------------------
1571 void Mamer::TellUser(reasons reason, char *name, int number) {
1576 XServerCom("qtell %s %s notes: %s\n", name, username,
1577 "Can not join\\nYour rating does not fit into current limits. <check tourney vars>");
1580 XServerCom("qtell %s %s notes: %s\n", name, username, "You joined the tournament.");
1583 XServerCom("qtell %s %s notes: %s\n", name, username, "You are already in this tourney.");
1586 XServerCom("qtell %s %s notes: %s\n", name, username, "You can not join. Tourney is not open.");
1592 case NotEnoughPlayers:
1593 XServerCom("qtell %s %s notes: Tourney#%d %s\n", name, username, number, "does not have enough players.");
1596 XServerCom("qtell %s %s notes: Tourney#%d %s\n", name, username, number, "has no players.");
1598 case WillKeepTourney:
1599 XServerCom("qtell %s %s notes: Tourney#%d %s\n", name, username, number, "will be kept.");
1601 case NotKeepTourney:
1602 XServerCom("qtell %s %s notes: Tourney#%d %s\n", name, username, number, "will not be kept.");
1604 case TourneyNotFound:
1605 XServerCom("qtell %s %s notes: %s%d %s\n", name, username, "Tourney #", number, "not found.");
1608 XServerCom("qtell %s %s notes: %s%d\n", name, username, "Player not found in tourney #", number);
1610 case GameResultNotFound:
1611 XServerCom("qtell %s %s notes: %s%d\n", name, username, "Can not set result to ", number);
1614 XServerCom("qtell %s %s notes: You don't have change permissions for tourney #%d.\n", name, username, number);
1617 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that right now.",
1618 "Tourney #", number, "is not new.");
1620 case TourneyNotOpen:
1621 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that right now.",
1622 "Tourney #", number, "is not open.");
1624 case TourneyNotClosed:
1625 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that right now.",
1626 "Tourney #", number, "is not closed.");
1629 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that anymore.",
1630 "Tourney #", number, "is done.");
1633 XServerCom("qtell %s %s notes: %s %s%d %s\n", name, username, "Can not do that anymore.",
1634 "Tourney #", number, "is closed.");
1636 case TourneyDeleted:
1637 XServerCom("qtell %s %s Notes: %s %s%d %s\n", name, username, "\\n", "Tourney #",
1638 number, " has been deleted.");
1643 }//- End of TellUser
1645 //- TellUser ------------------------------------------------
1646 void Mamer::TellUser(Command *comm, char *name) {
1648 int i, length=strlen(comm->parameterList);
1650 sprintf(line, "qtell %s %s notes: Usage: %s ", name, username, comm->GetCommandName());
1652 for(i=0; i<length; i++) {
1653 switch (comm->parameterList[i]) {
1655 strcat(line, "<word> ");
1658 strcat(line, "<optional word> ");
1661 strcat(line, "<integer> ");
1664 strcat(line, "<optional int> ");
1667 strcat(line, "<word or int> ");
1670 strcat(line, "<optional word or int> ");
1673 strcat(line, "<string> ");
1676 strcat(line, "<optional string> ");
1683 write(serverSocket, line, strlen(line));
1684 }//- End of TellUser
1686 //- TellUser ------------------------------------------------
1687 void Mamer::TellUser(reasons reason, char *name, char *request) {
1690 XServerCom("qtell %s %s notes: Sorry %s is not found.\n", name, username, request);
1693 XServerCom("qtell %s %s notes: %s\n", name, username, request);
1696 XServerCom("qtell %s %s notes: Changed the info for %s.\n", name, username, request);
1698 case GameResultNotFound:
1699 XServerCom("qtell %s %s notes: %s %s\n", name, username, "Can not set result to", request);
1702 XServerCom("qtell %s %s notes: Ambiguous Command Matches:\\n %s\n", name, username, request);
1707 }//- End of TellUser
1709 //- TellUser ------------------------------------------------
1710 void Mamer::TellUser(reasons reason, char *name, char *who, char *which, int new_value) {
1713 XServerCom("qtell %s %s notes: Changed the %s stat for %s to %d.\n", name, username, which, who, new_value);
1716 switch (new_value) {
1718 XServerCom("qtell %s %s notes: The game %s(w) vs. %s(b) has been set to 1-0\n", name, username, who, which);
1721 XServerCom("qtell %s %s notes: The game %s(w) vs. %s(b) has been set to 0-1\n", name, username, who, which);
1724 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);
1731 }//- End of TellUser
1733 //- TellUser ------------------------------------------------
1734 void Mamer::TellUser(reasons reason, char *name, char *which, char *new_value) {
1737 XServerCom("qtell %s %s notes: Can not change the %s var to %s.\n", name, username, which, new_value);
1740 XServerCom("qtell %s %s notes: Changed %s to %s.\n", name, username, which, new_value);
1745 }//- End of TellUser
1748 //- TellUser ------------------------------------------------
1749 void Mamer::TellUser(reasons reason, char *name, char *uname, int new_value) {
1751 case ChangedManagerLevel:
1752 XServerCom("qtell %s %s notes: %s's Manager Level has been changed to %d\n", name, username, uname,new_value);
1754 case ChangedCommandLevel:
1755 XServerCom("qtell %s %s notes: The %s command's manager Level has been changed to %d\n",name,username,uname, new_value);
1758 XServerCom("qtell %s %s notes: %s Has been removed from tourney #%i\n", name, username, uname, new_value);
1761 XServerCom("qtell %s %s notes: %s Is not found in tourney #%i\n", name, username, uname, new_value);
1764 XServerCom("qtell %s %s notes: %s's Chaos Points have been changed to %d\n",name, username, uname, new_value);
1767 XServerCom("qtell %s %s notes: Can Not Change the %s stat to %d.\n", name, username, uname, new_value);
1770 XServerCom("qtell %s %s notes: Changed %s to %d.\n", name, username, uname, new_value);
1775 }//- End of TellUser
1777 //- ParseParams ----------------------------------------------
1778 int Mamer::ParseParams(Command *comm, char *parameters) {
1783 for (i = 0; i < MAXNUMPARAMS; i++)
1784 comm->params[i].type = TYPE_NULL; /* Set all parameters to NULL */
1785 parlen = strlen(comm->parameterList);
1786 parameters = eatWhite(parameters); /* remove and spaces before the command */
1787 parameters = eatWord(parameters); /* remove the command itself */
1788 for (i = 0; i < parlen; i++) {
1789 c = comm->parameterList[i];
1798 case 'o': /* word or optional word */
1799 parameters = eatWhite(parameters);
1801 return (c == 'o' ? COM_OK : COM_BADPARAMETERS);
1802 comm->params[i].val.word = parameters;
1803 comm->params[i].type = TYPE_WORD;
1804 parameters = eatWord(parameters);
1805 if (*parameters != '\0') {
1810 stolower(comm->params[i].val.word);
1814 case 'p': /* optional or required integer */
1815 parameters = eatWhite(parameters);
1817 return (c == 'p' ? COM_OK : COM_BADPARAMETERS);
1818 if (sscanf(parameters, "%d", &comm->params[i].val.integer) != 1)
1819 return COM_BADPARAMETERS;
1820 comm->params[i].type = TYPE_INT;
1821 parameters = eatWord(parameters);
1822 if (*parameters != '\0') {
1829 case 'n': /* optional or required word or integer */
1830 parameters = eatWhite(parameters);
1832 return (c == 'n' ? COM_OK : COM_BADPARAMETERS);
1833 if (sscanf(parameters, "%d", &comm->params[i].val.integer) != 1) {
1834 comm->params[i].val.word = parameters;
1835 comm->params[i].type = TYPE_WORD;
1837 comm->params[i].type = TYPE_INT;
1839 parameters = eatWord(parameters);
1840 if (*parameters != '\0') {
1844 if (comm->params[i].type == TYPE_WORD)
1846 stolower(comm->params[i].val.word);
1850 case 't': /* optional or required string to end */
1852 return (c == 't' ? COM_OK : COM_BADPARAMETERS);
1853 comm->params[i].val.string = parameters;
1854 comm->params[i].type = TYPE_STRING;
1856 parameters = nextWord(parameters);
1858 stolower(comm->params[i].val.string);
1863 return COM_BADPARAMETERS;
1866 } //- End ParseParams ------------------
1868 //- isWhiteSpace -------------------------------------------
1869 int Mamer::isWhiteSpace (int c) {
1870 if ((c < ' ') || (c == '\b') || (c == '\n') ||
1871 (c == '\t') || (c == ' ')) { /* white */
1876 } //- End isWhiteSpace -------
1878 //- getWord ------------------------------------------------
1879 char *Mamer::getWord (char *str) {
1881 static char word[MAX_WORD_SIZE];
1884 while (*str && !isWhiteSpace(*str)) {
1888 if (i == MAX_WORD_SIZE) {
1895 } //- End getWord -------------
1897 //- eatWord -------------------------------------------
1898 char *Mamer::eatWord (char *str) {
1899 while (*str && !isWhiteSpace(*str))
1904 //- eatWhite ------------------------------------------
1905 char *Mamer::eatWhite (char *str) {
1906 while (*str && isWhiteSpace(*str))
1909 } //- eatWhite --------
1911 //- eatTailWhite -------------------------------------------
1912 char *Mamer::eatTailWhite (char *str) {
1918 while (len > 0 && isWhiteSpace(str[len - 1]))
1922 } //- End of eatTailWhite -----------
1924 //- nextWord -----------------------------------------------
1925 char *Mamer::nextWord(char *str) {
1926 return eatWhite(eatWord(str));
1927 } //- End of nextWord
1929 char *Mamer::stolower(char *str) {
1934 for (i = 0; str[i]; i++) {
1935 if (isupper(str[i])) {
1936 str[i] = tolower(str[i]);
1942 //- GenerateTourneyNumber ----------------------------------------------
1943 int Mamer::GenerateTourneyNumber(void) {
1945 int maxT = 0, used=0, i, count=0;
1946 LinkListIter<Tourney> tourneyIter(tourneyList);
1948 if(NULL != tourneyList.Head()) {
1949 while((t = tourneyIter.Next()))
1952 for(i=1; i<=count; i++) {
1954 tourneyIter.Reset();
1955 while((t = tourneyIter.Next())) {
1958 if(t->number > maxT)
1971 // $Log: Mamer.cc,v $
1972 // Revision 1.19 2002/07/02 00:05:19 tridge
1973 // got rid of a bunch of RCS tags now that its in CVS
1975 // Revision 1.18 2002/07/02 00:02:40 tridge
1976 // - fixed compile on g++ 2.96
1977 // - updated for lasker 'rmatch'
1979 // Revision 1.17 1998/09/10 19:57:17 mlong
1980 // lots of little bug fixes and a few new features
1982 // Revision 1.16 1998/08/04 21:02:13 mlong
1983 // changes to correct a few bugs including the this->* change that
1984 // correctly uses the function pointers now
1986 // Revision 1.15 1998/06/18 18:41:30 mlong
1987 // prepairing for yet another move.
1989 // Revision 1.14 1998/06/04 19:55:00 mlong
1990 // quick change to the load config file stuff to
1991 // allow for a commented out line
1993 // Revision 1.13 1998/04/29 15:23:19 mlong
1994 // prepairing for the move to daimi
1995 // new sorting routine.
1997 // Revision 1.12 1998/04/18 18:46:04 mlong
1998 // fixed delete bug &
1999 // added delete tourney function
2001 // Revision 1.11 1998/04/17 00:14:37 mlong
2002 // fixes to the setres working with the Link delete method
2004 // Revision 1.7 1997/10/22 19:47:38 mlong
2005 // fixed bug for parsing tells into user and command.
2007 // Revision 1.6 1997/10/08 21:03:35 chess
2008 // preparing for move to oracle machine at eworks.
2010 // Revision 1.5 1997/05/15 18:27:53 chess
2011 // added Player and TourneyPlayers support
2012 // added HandleGetPlayerInfo & HandleetGameInfo
2014 // Revision 1.4 1997/04/13 03:14:35 chess
2015 // commands to do user stats manipulation added
2016 // also TellUser function added to make for easier reporting and bug checking
2017 // also added ParseParams that takes the commands parameter list definition
2018 // and parses out the input from the user to determine if the paramters
2019 // supplied are correct. If so it then sends those params to the
2022 // Revision 1.3 1997/03/21 15:31:04 moses
2023 // added the cleanup of commands
2024 // added the cleanup of tourneys
2025 // added the mamer shutdown command
2027 // Revision 1.2 1996/10/01 20:14:43 moses
2028 // Changes to incorparte the new usage of the command list
2030 // Revision 1.1 1996/09/30 20:52:48 moses