Check in modified mamer
[capablanca.git] / lasker-2.2.3 / bots / mamer / Tourney.cc
1 //--------------------------------------------------------------------------
2 // Tourney.cc - Source file for Tourney class
3 //
4 // Matthew E. Moses
5 //
6 // $Revision: 1.11 $
7 // $Date: 1998/09/10 19:57:17 $
8 //
9 // $Author: mlong $
10 // $Locker:  $
11 //
12 // $Log: Tourney.cc,v $
13 // Revision 1.11  1998/09/10 19:57:17  mlong
14 // lots of little bug fixes and a few new features
15 //
16 // Revision 1.10  1998/04/29 15:23:19  mlong
17 // prepairing for the move to daimi
18 // new sorting routine.
19 //
20 // Revision 1.9  1998/04/18 20:05:14  mlong
21 // fixed BYE bug
22 //
23 // Revision 1.8  1998/04/18 18:46:04  mlong
24 // fixed delete bug &
25 // added delete tourney function
26 //
27 // Revision 1.4  1997/10/08 21:03:35  chess
28 // preparing for move to oracle machine at eworks.
29 //
30 // Revision 1.3  1997/05/15 18:27:53  chess
31 // added pending and TourneyPlayers support
32 // added HandleGetPlayerInfo & HandleGetGameInfo
33 //
34 // Revision 1.2  1996/10/01 20:14:43  moses
35 // Added a new method IsTourney
36 //
37 // Revision 1.1  1996/09/30  20:52:48  moses
38 // Initial revision
39 //
40 //--------------------------------------------------------------------------
41
42 //static char RCSid[] = "$Id: Tourney.cc,v 1.11 1998/09/10 19:57:17 mlong Exp $";
43
44 #include "Tourney.hh"
45 #include "Mamer.hh"
46
47 extern Mamer gMamer;
48
49 //- Constructor ------------------------------------------------------------
50 Tourney::Tourney() {
51 } //- End of Tourney
52
53 Tourney::Tourney(int n,User *u, TourneyParameters *tp) {
54   InitTourney(n, u, tp->time, tp->inc, tp->mode, tp->style, tp->rounds, tp->variant, tp->ratingLow, tp->ratingHigh);
55 }
56
57 Tourney::Tourney(int n, User *u, TourneyParameters *tp, int t, int i, char m, char s, int r) {
58   InitTourney(n, u, t, i, m, s, r, tp->variant, tp->ratingLow, tp->ratingHigh);
59 }
60
61 Tourney::Tourney(int n, User *u, TourneyParameters *tp, int t, int i, char m, char s, int r, char v) {
62   InitTourney(n, u, t, i, m, s, r, v, tp->ratingLow, tp->ratingHigh);
63 }
64
65 void Tourney::InitTourney(int n, User *u, int t, int i, char m, char s, int r, char v, int rl, int rh) {
66   number = n;
67   strncpy(manager, u->name, NAMELEN - 1);
68   managerLevel = u->GetManagerLevel();
69   averageRating = 0;
70   params.time = t;
71   params.inc = i;
72   params.mode = m;
73   params.style = s;
74   params.rounds = r;
75   params.variant = v;
76   params.wild = 10;
77   params.ratingLow = rl;
78   params.ratingHigh = rh;
79   params.currentRound = 0;
80   params.maxPlayers = DEFAULT_MAX_PLAYERS;
81
82   startDate = 0;
83   endDate = 0;
84   persist = 0;
85   lastCshouted = 0;
86
87   status = NEW;
88 }
89
90 //- Deconstructor ---------------------------------------------------------
91 Tourney::~Tourney() {
92
93 } //- End of ~Tourney
94
95 //- IsTourney -------------------------------------------------------------
96 int Tourney::IsTourney(int tourn) {
97     if(tourn == number)
98         return(1);
99     else
100         return(0);
101 } //- End of IsTourney
102
103 //- IsNotNew-------------------------------------------------------------
104 short Tourney::IsNotNew(void) {
105   if(NEW != status)
106     return(TRUE);
107   return(FALSE);
108 }
109
110 //- IsNotClosed-------------------------------------------------------------
111 short Tourney::IsNotClosed(void) {
112   if(CLOSED != status)
113     return(TRUE);
114   return(FALSE);
115 }
116
117 //- AddPlayer ----------------------------------------------------------
118 int Tourney::AddPlayer(char *name, int rating, float score) {
119   TourneyPlayers *newPlayer = NULL, *tp = NULL;
120   Player *newSortPlayer = NULL;
121
122   if (status != OPEN) return 3;   // If we are not open then we can't enter the tourney
123   
124   tp = GetPlayer(name);
125
126   if(tp != NULL) return(2);   // if we are already in the tourney we can't enter it again/
127
128   if(rating >= params.ratingLow && rating <= params.ratingHigh && status == OPEN) {
129
130     newPlayer = new TourneyPlayers(name, rating, score);
131     newSortPlayer = new Player(name, 0);
132
133     playerList.Append(newPlayer);
134     SortPlayers();
135     gMamer.XServerCom("%s %i %s %s%i%s %s%i %i %s%s", "tell", gMamer.channelNumber, name, "(", rating, ")", 
136                       "has joined tourney #", number, GetPlayerCount(), "players now.", "\n");
137     CalculateAverage();
138     if(GetPlayerCount() >= params.maxPlayers)
139       CloseAndStart();
140     return(1);   // we entered the tourney
141   } else 
142     return(0); // sucks to be us cause our rating doesn't fit the params
143 }
144
145 //- RemovePlayer ----------------------------------------------------------
146 int Tourney::RemovePlayer(char *name) {
147   TourneyPlayers *tp = NULL, *p=NULL;
148   Player *opp=NULL;
149   int roundsRemaining=0;
150
151   tp = GetPlayer(name);
152   printf("forfeiting %s\n", tp->name);
153   if(tp == NULL) return -1; // Player not in THIS tourney
154
155   tp->activeFlag = 0;
156
157   roundsRemaining = GetRoundsRemaining();
158
159   // This code will go through a forfeited players list and give him a loss for current opponent
160   // with a quick modification it will give losses for all games played as well...
161   LinkListIter<Player> opponentIter(tp->opponentList);  // List of opponents this player has had
162   opponentIter.Reset();
163   while((opp = opponentIter.Next())) {
164     if(strcmp("_BYE_", opp->name) != 0) {  // If I am not _BYE_
165       p = GetPlayer(opp->name);
166       if(opp->floatValue == -1) {  // floatValue stores the game result for this player
167         if(opp->value) {  // if player leaving was white
168           SetGameResult(tp->name, opp->name, 0);
169         } else {
170           SetGameResult(opp->name, tp->name, 1);
171         }
172         roundsRemaining++;
173       }
174     }
175   }
176   
177   LinkListIter<TourneyPlayers> playerIter(playerList);
178   playerIter.Reset();
179   while((p = playerIter.Next())) {
180     if(strcmp(p->name, "_BYE_") == 0)  { 
181       if(p->activeFlag != 0)
182         p->activeFlag = 0;
183       else
184         p->activeFlag = 1;
185       break;
186     }
187   }
188
189   SortPlayers();
190
191   return roundsRemaining;
192 }
193
194 //- GetPlayer ----------------------------------------------------------
195 TourneyPlayers *Tourney::GetPlayer(char *name) {
196   LinkListIter<TourneyPlayers> playerIter(playerList);
197   TourneyPlayers *tp = NULL;
198   
199   playerIter.Reset();
200   while((tp = playerIter.Next()))
201     if(!strcasecmp(tp->name, name))  
202       return tp;
203   
204   return NULL;
205 }
206
207 //- GetRound ----------------------------------------------------------
208 int Tourney::GetRound() {
209   return params.currentRound;
210 }//- end of GetRound --------------------------------------------------
211
212 //- GetRoundsRemaining ------------------------------------------------
213 int Tourney::GetRoundsRemaining() {
214   return (params.rounds - params.currentRound);
215 }//- end of GetRoundsRemaining -----------------------------------------
216
217 //- SortPlayers ----------------------------------
218 void Tourney::SortPlayers() {
219   Player          *temp=NULL, *s=NULL;
220   TourneyPlayers  *tp = NULL;
221   int             i=0, added=0;
222
223   LinkListIter<TourneyPlayers> playerIter(playerList);
224   LinkListIter<Player> sortIter(sortList);
225
226   sortIter.Reset();
227   while((s = sortIter.Next())) sortList.Delete(s);
228
229   i=0;
230   while((tp = playerIter.Next())) {
231     (tp->activeFlag) ? tp->sortValue = (tp->score + tp->rating/10000.0) : tp->sortValue = -1.0;
232   //  tp->ClearWhites();
233   //  tp->ClearBlacks();
234     if((status == OPEN) && (i < (GetPlayerCount()/2)))
235       (i % 2) ? tp->AddWhite() : tp->AddBlack();
236     i++;
237   }
238
239   playerIter.Reset();
240   while((tp = playerIter.Next())) {
241     added=0;
242     sortIter.Reset();
243     temp = new Player(tp->name, tp->sortValue);
244     while((s = sortIter.Next())) {
245       if(tp->sortValue > s->floatValue) {
246         sortList.Insert(s, temp);
247         added = 1;
248         break;
249       }
250     }
251     if(!added)
252       sortList.Append(temp);
253   }
254
255   i = 1;
256   sortIter.Reset();
257   while((s = sortIter.Next())) { 
258     s->value = i;
259     if(gMamer.debugLevel >= 10) printf("%4d %-18s\n", s->value, s->name); 
260     i++;
261   }
262 }//- end of Sort Players ----------------------
263
264 //- GetSortValueCount -------------------------------------------------------
265 int Tourney::GetSortValueCount(double value) {
266   LinkListIter<TourneyPlayers> playerIter(playerList);
267   int count=0;
268   TourneyPlayers *tp=NULL;
269   Player *s=NULL;
270
271   while((tp = playerIter.Next())) {
272     if(tp->sortValue == value) {
273       s = GetSortPlayer(tp->name);
274       if(s->value != 0)
275         count++;
276     }
277   }
278   
279   return count;
280 }
281
282 //- GetSortPlayer ----------
283 Player *Tourney::GetSortPlayer(char *name) {
284   Player *p = NULL;
285   LinkListIter<Player> sortIter(sortList);
286
287   while((p = sortIter.Next())) {
288     if(strcasecmp(p->name, name) == 0) {
289       return p;
290     }
291   }
292
293   return p;
294 }//- end of GetSortPlayer -----
295
296 //- GetSortPlayer ------------------------------
297 Player *Tourney::GetSortPlayer(int place) {
298   Player *p = NULL;
299   LinkListIter<Player> sortIter(sortList);
300
301   while((p = sortIter.Next())) {
302     if(p->value == place) {
303       return p;
304     }
305   }
306   
307   return p;
308 }//- end of GetSortPlayer -----
309
310 //- CalculateAverage --------------------------------------------------
311 void Tourney::CalculateAverage(void) {
312   int total=0, count=0;
313   TourneyPlayers *p;
314   LinkListIter<TourneyPlayers> playerIter(playerList);
315   
316   while((p = playerIter.Next())) {
317     if(p->rating > 0) {
318       total += p->rating;
319       count++;
320     }
321   }
322   if(count)
323     averageRating = ((float)total/(float)count);
324   else
325     averageRating = 0;
326 }//- end CalculateAverage
327
328 //- GetAverageRating ----------------------------------------------------------
329 float Tourney::GetAverageRating(void) {
330   return averageRating;
331 }//end GetAverageRating
332
333 //- GetVariant ----------------------------------------------------------
334 int Tourney::GetVariant(void) {
335   float eTime;
336
337   switch(params.variant) {
338   case 'w':
339     return(0);
340   case 'r':
341     eTime = (float)params.time + (0.6666667 * (float)params.inc);
342     if(eTime < 3)
343       return(1);
344     else if(eTime < 15)
345       return(2);
346     else 
347       return(3);
348   case 'b':
349     return(4);
350   case 's':
351     return(5);
352   default:
353     return(2);
354   }
355 }
356
357 //- Open ----------------------------------------------------------
358 int Tourney::Open(void) {
359   if(status == NEW) {
360     status = OPEN;
361     return 1;
362   } else {
363     return 0;
364   }
365 }
366
367 //- GetPlayerCount ----------------------------------------------------------
368 int Tourney::GetPlayerCount() {
369   int count=0;
370   TourneyPlayers *p;
371   LinkListIter<TourneyPlayers> playerIter(playerList);
372   
373   while((p = playerIter.Next())) {
374     if(p->activeFlag != 0)
375       count++;
376   }
377
378   return count;
379 }//- end GetPlayerCount ----------------------------------
380
381 //- SetPersist -------------------------------------------------------------
382 void Tourney::SetPersist(int i) {
383   persist = i;
384 } //- end SetPersist
385
386 //- GetPersist -------------------------------------------------------------
387 int Tourney::GetPersist() {
388   return persist;
389 } //- end GetPersist
390
391 //- SetEndDate -------------------------------------------------------------
392 void Tourney::SetEndDate() {
393   endDate = time(0);
394 } //- end of SetEndDate ----------------------------------------------------
395
396 //- CloseAndStart ----------------------------------------------------------
397 void Tourney::CloseAndStart(void) {
398   TourneyPlayers *tp = NULL;
399   status = CLOSED;
400   params.currentRound = 0;
401
402   LinkListIter<TourneyPlayers> playerIter(playerList);
403
404   startDate = time(0);
405
406   cout << "tourney started at: " << ctime(&startDate) << endl;
407
408   if(params.rounds == 0) { 
409     switch(params.style) {
410     case 'r':
411       params.rounds = GetPlayerCount() - 1;
412       break;
413     case 's':
414       params.rounds = (int)ceil(log2(GetPlayerCount())); 
415       break;
416     default:
417       params.rounds = DEFAULT_ROUNDS;
418       break;
419     }
420   }
421
422   // this is to stop a 4 player tourney from having 2 rounds
423   params.rounds = (params.rounds < MINIMUM_ROUNDS) ? MINIMUM_ROUNDS : params.rounds;
424   
425   playerIter.Reset(); // [HGM] this code moved here from SortPlayers
426   while((tp = playerIter.Next())) {
427     tp->ClearWhites();
428     tp->ClearBlacks();
429     tp->ClearTotalWhites();
430     tp->ClearTotalBlacks();
431   }
432
433   MakeAssignments();
434   TellThemWhoTheyPlay();  // tell them who they play 
435 }
436
437 int Tourney::PopLastPairedPlayer() {
438   Storage *p=NULL, *lastPlayer=NULL;
439   LinkListIter<Storage> pairedIter(pairedPlayers);
440   int last=0;
441
442   while((p = pairedIter.Next())) {
443     lastPlayer = p;
444     last = p->value;
445   }
446
447   if(last) {
448     cout << "Popping: " << lastPlayer->name << " from the paired list " << endl;
449     pairedPlayers.Delete(lastPlayer);
450   } else
451     cout << "Popping: _NOBODY_" << " from the paired list " << endl;
452
453   return last;
454 }
455
456 void Tourney::ClearPairedPlayers() {
457   Storage *p=NULL;
458   LinkListIter<Storage> pairedIter(pairedPlayers);
459
460   while((p = pairedIter.Next())) pairedPlayers.Delete(p);
461 }
462
463 int Tourney::MakeAssignments(void) {
464   TourneyPlayers *tp = NULL, *opponent = NULL, *bye = NULL;
465   Storage *newPairedPlayer=NULL;
466   Player *p=NULL, *opp=NULL;
467   int everybodyPaired=0, byeFlag=1, playerCount=0, i=1;
468   LinkListIter<TourneyPlayers> playerIter(playerList);
469   
470   params.currentRound++;
471   if(params.currentRound > params.rounds) {
472     cout << "Returning because current round is > rounds" << endl;
473     cerr << "Returning because current round is > rounds" << endl;
474     return 0;
475   }  
476   // Initialize a few things...make sure nobody is paired,
477   playerIter.Reset();
478   while((tp = playerIter.Next())) {
479     UnPairPlayer(tp);
480     if(strcmp(tp->name, "_BYE_") == 0)  { byeFlag = 0; }  // unset the byeFlag
481   }
482   playerCount = GetPlayerCount();
483   if((byeFlag) && (playerCount % 2)){   // we need to add a bye
484     bye = new TourneyPlayers("_BYE_", 0, 0);  
485     playerList.Append(bye);                  // add the bye to the tourney players list
486     SortPlayers();
487     playerCount++;
488   }
489   
490   // Set up the PairingScores
491   playerIter.Reset();
492   while((tp = playerIter.Next())) { if(!tp->IsPaired()) SetPairingScores(tp); }
493   
494   playerIter.Reset();
495   while((tp = playerIter.Next())) { UnPairPlayer(tp); tp->oppChoice=0; }  // unpair all the players
496   
497   i = 1;
498   ClearPairedPlayers();
499   while(everybodyPaired == 0) {
500     everybodyPaired = 0;
501     p = GetSortPlayer(i);
502     tp = GetPlayer(p->name);
503     opponent = (TourneyPlayers *)NULL;
504     // PrintPotentialLists();
505     if((tp->IsPaired() == FALSE) && tp->activeFlag) { // If I am not paired and I am active pair me
506       if((opponent = FindBestOpponent(tp))) {
507         newPairedPlayer = new Storage(tp->name, i);
508         pairedPlayers.Append(newPairedPlayer);
509         cerr << "Adding: " << tp->name << " " << i << " " << "to the paired list " << opponent->name << endl;
510         everybodyPaired = PairPlayers(tp, opponent);  // Actually Pair me
511         i++;                                // go to the next player
512       } else {                              // If there is no opponent for me go back and repair up the tree
513         if(tp->oppChoice > playerCount) {  // If I have tried all my opponents
514           tp->oppChoice = 0;               // reset me so I can try again later
515           i = PopLastPairedPlayer();          // returns the last player paired & removes him from the paired list
516           cerr << "i=" << i << endl;
517           if(i <= 0)  {                         // this would be really bad means we can't even find 
518             cout << "Returning because we can't find pairings" << endl;
519             cerr << "Returning because we can't find pairings" << endl;
520             return 0;                       // an opponent for the first player.  Tourney has to be over now
521           }
522           p = GetSortPlayer(i);
523           tp = GetPlayer(p->name);
524           opponent = GetPlayer(tp->oppName);
525           cout << "UnPairing: " << tp->name << " " << opponent->name << " choice: " << tp->oppChoice << endl;
526           tp->RemoveLastOpponent();           // removes the person we were planning on playing
527           opponent->RemoveLastOpponent();
528           UnPairPlayer(tp);                   // unpair us so we can be re-paired
529           UnPairPlayer(opponent);
530           tp->oppChoice++;                           // try his next possible opponent
531         } else {
532           tp->oppChoice++;   // Try my next opponent
533         }
534       }
535     } else {  // if I am already paired go to the next player and pair him
536       i++;
537     }
538   }
539
540   if(everybodyPaired > 0) {
541     playerIter.Reset();
542     while((tp = playerIter.Next())) UnPairPlayer(tp);  // unpair all players so we can use that to tell
543     playerIter.Reset();                                 // if they have been assiged a color
544     while((tp = playerIter.Next())) {
545       if((!tp->IsPaired()) && (tp->activeFlag != 0)) {
546         opponent = GetPlayer(tp->oppName);
547         AssignColors(tp, opponent);
548         tp->NowPaired(TRUE);               // mark BOTH players as having a color
549         opponent->NowPaired(TRUE);         // this is important for when we hit this player later in the Iter
550       }
551     }
552   }
553
554   playerIter.Reset();
555   while((tp = playerIter.Next()))  {
556     if(0 == strcmp(tp->name, "_BYE_")) {  // If I am the bye
557       LinkListIter<Player> opponentIter(tp->opponentList);
558       while((opp = opponentIter.Next())) { // Got through my opponents and find the one I am playing now
559         if(0 == strcasecmp(opp->name, tp->oppName)) { // & Give him a win
560           if(opp->value)
561             SetGameResult(tp->name, tp->oppName, 0);
562           else
563             SetGameResult(tp->oppName, tp->name, 1);
564           gMamer.XServerCom("tell %s you get a BYE this round.%s", opp->name, "\n");
565         }
566       }
567     }
568   }
569   return 1;
570 }
571
572 //- PrintPotentialLists
573 void Tourney::PrintPotentialLists() {
574   TourneyPlayers *tp=NULL;
575   Player *o=NULL;
576
577   LinkListIter<TourneyPlayers> playerIter(playerList);
578
579   while((tp = playerIter.Next())) {
580     printf("%-10s %i\n", tp->name, tp->oppChoice);
581     LinkListIter<Player> oppIter(tp->potentialOpponentList);    
582     while((o = oppIter.Next())) {
583       printf("%d %-10s ", o->value, o->name);
584     }
585     printf("\n\n");
586   }
587 }
588
589 //- Start of FindBestOpponent
590 TourneyPlayers *Tourney::FindBestOpponent(TourneyPlayers *tp) {
591   Player *tmp = NULL;
592   
593   LinkListIter<Player> opponentIter(tp->potentialOpponentList);
594   while((tmp = opponentIter.Next())) {
595     if((tmp->value == tp->oppChoice) && (0 == GetPlayer(tmp->name)->IsPaired())) {
596       return GetPlayer(tmp->name);
597     }
598   }
599
600   return NULL;
601 }
602
603 //- Start of SetPairingSores -------------------------------
604 void Tourney::SetPairingScores(TourneyPlayers *tp) {
605   double score;
606   TourneyPlayers *opponent = NULL;
607   Player *temp=NULL, *newOpp=NULL, *t=NULL, *me=NULL;
608   int offset=2, place=1, i=0, added=0;
609   
610   tp->RemovePotentialOppList();
611
612   LinkListIter<TourneyPlayers> playerIter(playerList);
613   
614   SortPlayers();
615   
616   while((opponent = playerIter.Next())) {
617     if((strcmp(tp->name, opponent->name) != 0) && 
618        (tp->score == opponent->score)) {
619       offset++;
620       if(opponent->rating > tp->rating) {
621         place++;
622       }
623     }
624   }
625   offset = offset / 2;
626   if(place > offset) { offset *= -1; }
627
628   me = GetSortPlayer(tp->name);
629   playerIter.Reset();
630   while((opponent = playerIter.Next())) {
631     if(strcmp(tp->name, opponent->name) && (tp->activeFlag !=0)) { // If this isn't MY name & I am active
632       if((!tp->AlreadyPlayed(opponent->name)) && (!opponent->IsPaired()) && (opponent->activeFlag != 0)) { 
633         // and I haven't played this person and this person is active. (not forfeited)
634         t = GetSortPlayer(opponent->name);
635         score = ((abs(t->value - (me->value + offset))) * 1000);
636         if(opponent->score >= tp->score) {
637           score = score + ((opponent->score - tp->score) * 10.0);
638         } else {
639           score = score + ((tp->score - opponent->score) * 10.0);
640         }
641         score += abs(opponent->ColorDue() - tp->ColorDue());
642         score += (abs(opponent->rating - tp->rating)) * 0.0001;
643
644         if(!strcmp(opponent->name, "_BYE_")) { score = 999999; }
645
646         added=0;
647         newOpp = new Player(opponent->name, score);
648         LinkListIter<Player> opponentIter(tp->potentialOpponentList);
649         opponentIter.Reset();
650         while((temp = opponentIter.Next())) {
651           if(score < temp->floatValue) {
652             tp->potentialOpponentList.Insert(temp, newOpp);
653             added = 1;
654             break;
655           }
656         }
657         if(!added)
658           tp->potentialOpponentList.Append(newOpp);
659         opponentIter.Reset();
660         i = 0;
661         while((temp = opponentIter.Next())) {
662           temp->value = i;
663           i++;
664         }
665       }
666     }
667   }
668 }
669
670 //- Start of PairPlayers ----------------------------------
671 int Tourney::PairPlayers(TourneyPlayers *p1, TourneyPlayers *p2) {
672   TourneyPlayers *tp;
673   Player *temp = NULL;
674
675   LinkListIter<TourneyPlayers> playerIter(playerList);
676
677   temp = new Player(p2->name, -1.0, 0, p2->rating);
678   p1->opponentList.Append(temp);
679   p1->NowPaired(TRUE);
680   strcpy(p1->oppName, p2->name);
681
682   temp = new Player(p1->name, -1.0, 0, p1->rating);
683   p2->opponentList.Append(temp);
684   p2->NowPaired(TRUE);
685   strcpy(p2->oppName, p1->name);
686
687   playerIter.Reset();
688   while((tp = playerIter.Next())) {
689     if((!tp->IsPaired()) && (tp->activeFlag != 0))
690       return 0;
691   }
692   
693   return 1;
694 }
695
696 //- Start of UnPairPlayer ----------------------------------
697 void Tourney::UnPairPlayer(TourneyPlayers *p1) {
698   if(p1 != NULL)
699     p1->NowPaired(FALSE);
700 }//- end of UnPairPlayer
701
702 //- intcmp ----
703 int Tourney::intcmp(int a, int b) {
704   if(a > b) {
705     return 1;
706   } else {
707     if (a == b) {
708       return 0;
709     } else {
710       return -1;
711     }
712   }
713 }
714 //- end intcmp ----
715
716 //- AssignColors ----------------------------------------------------------
717 void Tourney::AssignColors(TourneyPlayers *p1, TourneyPlayers *p2) {
718   int p1Color=0, rated = 1;
719   Game *g = NULL;
720   Player *opp1 = NULL, *opp2 = NULL;
721
722   cerr << "P1: " << p1->name << " due=" << p1->ColorDue() << " total=" << p1->GetTotalWhites() << "/" << p1->GetTotalBlacks()
723         << " consecutive=" << p1->GetConsecutiveWhites() << "/" << p1->GetConsecutiveBlacks() << endl;
724   cerr << "P2: " << p2->name << " due=" << p2->ColorDue() << " total=" << p2->GetTotalWhites() << "/" << p2->GetTotalBlacks()
725         << " consecutive=" << p2->GetConsecutiveWhites() << "/" << p2->GetConsecutiveBlacks() << endl;
726   if(params.mode != 'r') { rated = 0; }
727   if(intcmp(p1->ColorDue(), p2->ColorDue()) != 0) {
728     if(p1->ColorDue()) { p1Color = 1; }
729   } else {
730     if(p1->ColorDue()) {   // Both are due white; need to find out how due.
731       switch (intcmp(p1->GetConsecutiveBlacks(), p2->GetConsecutiveBlacks())) {
732       case 1:
733         p1Color = 1;
734         break;
735       case -1: break;
736       case 0:
737         switch (intcmp(p1->GetTotalBlacks(), p2->GetTotalBlacks())) {
738         case 1:
739           p1Color = 1;
740           break;
741         case -1: break;
742         case 0:
743           if((p1->score * 10000 + p1->rating) >= (p2->score * 10000 + p2->rating))
744             p1Color = 1;
745           break;
746         }
747         break;
748       }
749     } else {
750       switch (intcmp(p1->GetConsecutiveWhites(), p2->GetConsecutiveWhites())) {
751       case 1: break;
752       case -1:
753         p1Color = 1;
754         break;
755       case 0:
756         switch (intcmp(p1->GetTotalWhites(), p2->GetTotalWhites())) {
757         case 1: break;
758         case -1:
759           p1Color = 1;
760           break;
761         case 0:
762           if((p1->score * 10000 + p1->rating) >= (p2->score * 10000 + p2->rating))
763             p1Color = 1;
764           break;
765         }
766         break;
767       }
768     }
769   }
770   LinkListIter<Player> opponentIter1(p1->opponentList);
771   LinkListIter<Player> opponentIter2(p2->opponentList);
772   while((opp1 = opponentIter1.Next())) {
773     if(!strcasecmp(opp1->name, p2->name)) { break; }
774   }
775   while((opp2 = opponentIter2.Next())) {
776     if(!strcasecmp(opp2->name, p1->name)) { break; }
777   }
778   cerr << "assigned color = " << p1Color << endl;
779   if(p1Color) { 
780     p1->AddWhite(); p2->AddBlack();
781     opp1->value = 1;
782     g = new Game(p1->name, p2->name, params.time, params.inc, rated, 'r');
783   } else { 
784     p1->AddBlack(); p2->AddWhite();
785     opp2->value = 1;
786     g = new Game(p2->name, p1->name, params.time, params.inc, rated, 'r');
787   }
788   gameList.Append(g);
789 }
790
791 //- GetStatus --------------------------------------------------------
792 int Tourney::GetStatus(void) {
793   return status;
794 }
795
796 //- EndTourney -----------------------
797 void Tourney::EndTourney(void) {
798   status = DONE;
799 }//- End EndTourney
800
801 //- Announce ----------------------------------------------------------
802 void Tourney::Announce(void) {
803   char temp[128];
804   char *announce;
805   long now=0;
806
807   announce = new char[MAX_LINE_SIZE];
808   memset(announce, '\0', MAX_LINE_SIZE);
809   sprintf(announce, "*****Tourney Announcement***** %80s Trny #%d  %d %d %c ", 
810           "", number, params.time, params.inc, params.mode);
811   if(params.style == 's') { strcat(announce, " SWISS"); } else { strcat(announce, " RR"); }
812   switch(params.variant) {
813   case 'w':
814     strcat(announce, " Wild ");
815     strcat(announce, GetWild(params.wild));
816     break;
817   case 'b':
818     strcat(announce, " Bug"); break;
819   case 's':
820     strcat(announce, " Suicide"); break;
821   default:
822     break;
823   }
824   memset(temp, '\0', 128);
825   sprintf(temp, " %i-%i %i plr(s).  tell %s join %d. Avg: %5.1f", 
826           params.ratingLow, params.ratingHigh, GetPlayerCount(), gMamer.username, number, averageRating);
827   strcat(announce, temp);
828
829   printf("%s  + cha 49\n", announce);
830   fflush(stdout);
831   
832   gMamer.XServerCom("%s %i %s%s", "tell", gMamer.channelNumber, announce, "\n");
833
834   now = time(0);
835   if((now - lastCshouted) > (SEC_BETWEEN_CSHOUTS)) {
836     gMamer.XServerCom("%s %s%s", "cshout", announce, "\n");
837     lastCshouted = now;
838   }
839
840   delete(announce);
841 }
842
843 //- SetVariable ---------------------------------------------------------------
844 void Tourney::SetVariable(int why, int newValue) {
845
846   switch (why) {
847   case 0:
848     if((newValue >= 0) && (newValue <= MAX_TIME))
849       params.time = newValue;
850     break;
851   case 1:
852     if((newValue >= 0) && (newValue <= MAX_INCREMENT))
853       params.inc = newValue;
854     break;
855   case 2:
856     params.rounds = newValue;
857     params.rounds = MIN(params.rounds, MAX_ROUNDS);
858     params.rounds = MIN((params.maxPlayers - 1), params.rounds);
859     break;
860   case 6:
861     if(((newValue >= 0) && (newValue <= 5)) || 
862        ((newValue >= 8) || (newValue <= 10)))
863       params.wild = newValue;
864     break;
865   case 7:
866     params.ratingLow = newValue;
867     params.ratingLow = MAX(0, params.ratingLow);
868     if(params.ratingLow >= (params.ratingHigh - 200)) 
869       params.ratingLow = params.ratingHigh - 200;
870     break;
871   case 8:
872     params.ratingHigh = newValue;
873     if(params.ratingHigh <= (params.ratingLow + 200))
874       params.ratingHigh = params.ratingLow + 200;
875     break;
876   case 9:
877     params.maxPlayers = newValue;
878     params.maxPlayers = MAX(params.maxPlayers, MINIMUM_PLAYERS);
879     params.maxPlayers = MAX(params.maxPlayers, (params.rounds + 1));
880     break;
881   default:
882     break;
883   }
884 }//- End SetVariable
885
886 //- SetVariable ---------------------------------------------------------------
887 void Tourney::SetVariable(int why, char *newValue) {
888
889   switch (why) {
890   case 3:
891     if((newValue[0] == 's') || (newValue[0] == 'r')) 
892       params.style = newValue[0];
893     break;
894   case 4:
895     if((newValue[0] == 'r') || (newValue[0] == 'w') || (newValue[0] == 'b') || (newValue[0] == 's'))
896       params.variant = newValue[0];
897     break;
898   case 5:
899     if((newValue[0] == 'r') || (newValue[0] == 'u'))
900       params.mode = newValue[0];
901     break;
902   default:
903     break;
904   }
905 }//- End SetVariable
906
907 //- Begin GetWild - take a int return a string
908 char *Tourney::GetWild(int w) {
909   switch (w) {
910   case 0:
911     return "0";
912   case 1:
913     return "1";
914   case 2: 
915     return "2";
916   case 3:
917     return "3";
918   case 4:
919     return "4";
920   case 5:
921     return "5";
922   case 8:
923     return "8";
924   case 9:
925     return "8a";
926   case 10:
927     return "fr";
928   default:
929     return "";
930   }
931 }//- end GetWild
932
933 //- TellThemWhoTheyPlay ------------------------------------------
934 void Tourney::TellThemWhoTheyPlay() {
935   Game *g = NULL;
936   LinkListIter<Game> gameIter(gameList);  // List of games in this tourney
937   char *Variant=new char[MAX_LINE_SIZE];
938
939   memset(Variant, '\0', MAX_LINE_SIZE);
940
941   if(params.variant == 'w')
942     sprintf(Variant, "wild %2s", GetWild(params.wild));
943   else if(params.variant == 's')
944     sprintf(Variant, "suicide");
945   else if(params.variant == 'b')
946     sprintf(Variant, "bug");
947
948   while((g = gameIter.Next())) {
949           /* note that we rely on rmatch and on the ; separated commands from lasker */
950           gMamer.XServerCom("rmatch %s %s %i %i %c %s white ; rmatch %s %s %i %i %c %s black\n", 
951                             g->whiteName, g->blackName, g->time, g->inc, params.mode, Variant,
952                             g->blackName, g->whiteName, g->time, g->inc, params.mode, Variant);
953   }
954   delete(Variant);
955 }//- end TellThemWhoTheyPlay --------------------------------------
956
957 //- SetGameResult --------------------------------------------
958 int Tourney::SetGameResult(char *white, char *black, int result) {
959   Player *opp1 = NULL, *opp2 = NULL;
960   TourneyPlayers *tp1 = NULL, *tp2 = NULL;
961   Game *g = NULL;
962   int found=0;
963
964   tp1 = GetPlayer(white);
965   tp2 = GetPlayer(black);
966
967   if((NULL == tp1) || (NULL == tp2)) { return 0; }
968
969   LinkListIter<Player> opponentIter1(tp1->opponentList);  // List of opponents this player has had
970   while((opp1 = opponentIter1.Next())) {
971     if(!strcasecmp(opp1->name, black)) { break; }
972   }
973   LinkListIter<Player> opponentIter2(tp2->opponentList);
974   while((opp2 = opponentIter2.Next())) {
975     if(!strcasecmp(opp2->name, white)) { break; }
976   }
977   if((NULL == opp1) || (NULL == opp2)) { return -1; }
978
979   switch (result) {    // set the result
980   case 1:
981     opp1->floatValue = 1.0; 
982     opp2->floatValue = 0.0; 
983     break;
984   case 0:
985     opp1->floatValue = 0.0; 
986     opp2->floatValue = 1.0; 
987     break;
988   case 2:
989     opp1->floatValue = 0.5; 
990     opp2->floatValue = 0.5; 
991     break;
992   default:
993     return 0;
994   }
995   tp1->CalculateScore();  
996   tp2->CalculateScore();
997
998   LinkListIter<Game> gameIter(gameList);  // List of games in this tourney
999   while((g = gameIter.Next())) {
1000     if(!(strcasecmp(g->whiteName, white)) && !(strcasecmp(g->blackName, black))) {
1001       gameList.Delete(g);
1002       found=1;
1003       break;
1004     }
1005   }
1006   if(found) {
1007     gameIter.Reset();
1008     if((g = gameIter.Next())) {
1009       return 1;
1010     } else {
1011       return 2;
1012     }
1013   } else {
1014     return 1;
1015   }
1016 } //- End SetGameResult --------------------------------------
1017
1018 //- GetStartDate ---------------------------------------------
1019 long Tourney::GetStartDate() {
1020   return startDate;
1021 } //- end of GetStartDate ------------------------------------
1022
1023 //- GetEndDate ---------------------------------------------
1024 long Tourney::GetEndDate() {
1025   return endDate;
1026 } //- end of GetEndDate ------------------------------------