Alter Makefile to force 32-bit compile
[capablanca.git] / lasker-2.2.3 / bots / mamer / Tourney.cc
index 0532f44..e37b85c 100644 (file)
@@ -3,17 +3,13 @@
 //
 // Matthew E. Moses
 //
-// $Revision: 1.12 $
-// $Date: 2002/07/02 00:02:40 $
+// $Revision: 1.11 $
+// $Date: 1998/09/10 19:57:17 $
 //
-// $Author: tridge $
+// $Author: mlong $
 // $Locker:  $
 //
 // $Log: Tourney.cc,v $
-// Revision 1.12  2002/07/02 00:02:40  tridge
-// - fixed compile on g++ 2.96
-// - updated for lasker 'rmatch'
-//
 // Revision 1.11  1998/09/10 19:57:17  mlong
 // lots of little bug fixes and a few new features
 //
@@ -43,7 +39,7 @@
 //
 //--------------------------------------------------------------------------
 
-//static char RCSid[] = "$Id: Tourney.cc,v 1.12 2002/07/02 00:02:40 tridge Exp $";
+//static char RCSid[] = "$Id: Tourney.cc,v 1.11 1998/09/10 19:57:17 mlong Exp $";
 
 #include "Tourney.hh"
 #include "Mamer.hh"
@@ -89,6 +85,7 @@ void Tourney::InitTourney(int n, User *u, int t, int i, char m, char s, int r, c
   lastCshouted = 0;
 
   status = NEW;
+  paused = FALSE;
 }
 
 //- Deconstructor ---------------------------------------------------------
@@ -123,7 +120,8 @@ int Tourney::AddPlayer(char *name, int rating, float score) {
   TourneyPlayers *newPlayer = NULL, *tp = NULL;
   Player *newSortPlayer = NULL;
 
-  if (status != OPEN) return 3;   // If we are not open then we can't enter the tourney
+  if (status != OPEN   // If we are not open then we can't enter the tourney
+      && !(score != 0. && status == CLOSED)) return 3; // [HGM] unless the manager adds us as late join!
   
   tp = GetPlayer(name);
 
@@ -131,7 +129,9 @@ int Tourney::AddPlayer(char *name, int rating, float score) {
 
   if(rating >= params.ratingLow && rating <= params.ratingHigh && status == OPEN) {
 
-    newPlayer = new TourneyPlayers(name, rating, score);
+    if(GetPlayerCount() >= params.maxPlayers) return(0); // [HGM] never exceed max players (or would it be safe to do so?)
+
+    newPlayer = new TourneyPlayers(name, rating, 0.); // [HGM] always set start score = 0.
     newSortPlayer = new Player(name, 0);
 
     playerList.Append(newPlayer);
@@ -139,6 +139,29 @@ int Tourney::AddPlayer(char *name, int rating, float score) {
     gMamer.XServerCom("%s %i %s %s%i%s %s%i %i %s%s", "tell", gMamer.channelNumber, name, "(", rating, ")", 
                      "has joined tourney #", number, GetPlayerCount(), "players now.", "\n");
     CalculateAverage();
+
+    if(status == CLOSED) { // [HGM] late join; do some stuff already done in CloseAndStart for the others
+       newPlayer->ClearWhites();
+       newPlayer->ClearBlacks();
+       newPlayer->ClearTotalWhites();
+       newPlayer->ClearTotalBlacks();
+
+       // give the player a BYE (which we might have to add)
+       LinkListIter<TourneyPlayers> playerIter(playerList);
+       playerIter.Reset();
+       while((tp = playerIter.Next())) {
+           if(strcmp(tp->name, "_BYE_") == 0)  break;
+       }
+       if(!tp) {
+           tp = new TourneyPlayers("_BYE_", 0, 0);  
+           playerList.Append(tp);                  // add the bye to the tourney players list
+           SortPlayers();
+       }
+       newPlayer->opponentList.Append(new Player("_BYE_", 0., 0, 0)); // add a BYE for missed round, to prevent it can get a second
+       
+       return 1; // in any case never start automatically
+    }
+
     if(GetPlayerCount() >= params.maxPlayers)
       CloseAndStart();
     return(1);   // we entered the tourney
@@ -233,8 +256,8 @@ void Tourney::SortPlayers() {
   i=0;
   while((tp = playerIter.Next())) {
     (tp->activeFlag) ? tp->sortValue = (tp->score + tp->rating/10000.0) : tp->sortValue = -1.0;
-    tp->ClearWhites();
-    tp->ClearBlacks();
+  //  tp->ClearWhites();
+  //  tp->ClearBlacks();
     if((status == OPEN) && (i < (GetPlayerCount()/2)))
       (i % 2) ? tp->AddWhite() : tp->AddBlack();
     i++;
@@ -399,9 +422,12 @@ void Tourney::SetEndDate() {
 
 //- CloseAndStart ----------------------------------------------------------
 void Tourney::CloseAndStart(void) {
+  TourneyPlayers *tp = NULL;
   status = CLOSED;
   params.currentRound = 0;
 
+  LinkListIter<TourneyPlayers> playerIter(playerList);
+
   startDate = time(0);
 
   cout << "tourney started at: " << ctime(&startDate) << endl;
@@ -423,6 +449,14 @@ void Tourney::CloseAndStart(void) {
   // this is to stop a 4 player tourney from having 2 rounds
   params.rounds = (params.rounds < MINIMUM_ROUNDS) ? MINIMUM_ROUNDS : params.rounds;
   
+  playerIter.Reset(); // [HGM] this code moved here from SortPlayers
+  while((tp = playerIter.Next())) {
+    tp->ClearWhites();
+    tp->ClearBlacks();
+    tp->ClearTotalWhites();
+    tp->ClearTotalBlacks();
+  }
+
   MakeAssignments();
   TellThemWhoTheyPlay();  // tell them who they play 
 }
@@ -457,7 +491,7 @@ int Tourney::MakeAssignments(void) {
   TourneyPlayers *tp = NULL, *opponent = NULL, *bye = NULL;
   Storage *newPairedPlayer=NULL;
   Player *p=NULL, *opp=NULL;
-  int everybodyPaired=0, byeFlag=1, playerCount=0, i=1;
+  int everybodyPaired=0, playerCount=0, i=1;
   LinkListIter<TourneyPlayers> playerIter(playerList);
   
   params.currentRound++;
@@ -470,14 +504,16 @@ int Tourney::MakeAssignments(void) {
   playerIter.Reset();
   while((tp = playerIter.Next())) {
     UnPairPlayer(tp);
-    if(strcmp(tp->name, "_BYE_") == 0)  { byeFlag = 0; }  // unset the byeFlag
+    if(strcmp(tp->name, "_BYE_") == 0)  { bye = tp; tp->activeFlag = 0; }  // unset the byeFlag [HGM] and remember bye and deactivate
   }
   playerCount = GetPlayerCount();
-  if((byeFlag) && (playerCount % 2)){   // we need to add a bye
+  if(playerCount % 2){   // we need to add a bye
+   if(bye) bye->activeFlag = 1; else { // [HGM] if bye existed, re-activate it
     bye = new TourneyPlayers("_BYE_", 0, 0);  
     playerList.Append(bye);                  // add the bye to the tourney players list
     SortPlayers();
     playerCount++;
+   }
   }
   
   // Set up the PairingScores
@@ -622,7 +658,20 @@ void Tourney::SetPairingScores(TourneyPlayers *tp) {
   playerIter.Reset();
   while((opponent = playerIter.Next())) {
     if(strcmp(tp->name, opponent->name) && (tp->activeFlag !=0)) { // If this isn't MY name & I am active
-      if((!tp->AlreadyPlayed(opponent->name)) && (!opponent->IsPaired()) && (opponent->activeFlag != 0)) { 
+      if((!tp->AlreadyPlayed(opponent->name)) && (!opponent->IsPaired()) && (opponent->activeFlag != 0)
+         && (tp->ColorDue() != opponent->ColorDue() // they are due different color, never a problem
+            || tp->ColorDue() ? // both are due white. Check if one of them could accept black without breaking 'absolute' color rules
+                                tp->GetConsecutiveBlacks() < 2 &&
+                                tp->GetTotalBlacks() - tp->GetTotalWhites() < 2 ||
+                                opponent->GetConsecutiveBlacks() < 2 &&
+                                opponent->GetTotalBlacks() - opponent->GetTotalWhites() < 2
+                              : // both are due black. Check if any of them can accept white
+                                tp->GetConsecutiveWhites() < 2 &&
+                                tp->GetTotalWhites() - tp->GetTotalBlacks() < 2 ||
+                                opponent->GetConsecutiveWhites() < 2 &&
+                                opponent->GetTotalWhites() - opponent->GetTotalBlacks() < 2
+            )
+       ) { 
        // and I haven't played this person and this person is active. (not forfeited)
        t = GetSortPlayer(opponent->name);
        score = ((abs(t->value - (me->value + offset))) * 1000);
@@ -712,6 +761,10 @@ void Tourney::AssignColors(TourneyPlayers *p1, TourneyPlayers *p2) {
   Game *g = NULL;
   Player *opp1 = NULL, *opp2 = NULL;
 
+  cerr << "P1: " << p1->name << " due=" << p1->ColorDue() << " total=" << p1->GetTotalWhites() << "/" << p1->GetTotalBlacks()
+       << " consecutive=" << p1->GetConsecutiveWhites() << "/" << p1->GetConsecutiveBlacks() << endl;
+  cerr << "P2: " << p2->name << " due=" << p2->ColorDue() << " total=" << p2->GetTotalWhites() << "/" << p2->GetTotalBlacks()
+       << " consecutive=" << p2->GetConsecutiveWhites() << "/" << p2->GetConsecutiveBlacks() << endl;
   if(params.mode != 'r') { rated = 0; }
   if(intcmp(p1->ColorDue(), p2->ColorDue()) != 0) {
     if(p1->ColorDue()) { p1Color = 1; }
@@ -764,6 +817,7 @@ void Tourney::AssignColors(TourneyPlayers *p1, TourneyPlayers *p2) {
   while((opp2 = opponentIter2.Next())) {
     if(!strcasecmp(opp2->name, p1->name)) { break; }
   }
+  cerr << "assigned color = " << p1Color << endl;
   if(p1Color) { 
     p1->AddWhite(); p2->AddBlack();
     opp1->value = 1;
@@ -786,6 +840,16 @@ void Tourney::EndTourney(void) {
   status = DONE;
 }//- End EndTourney
 
+//- IsPaused --------------------------------------------------------
+int Tourney::IsPaused(void) {
+  return paused;
+}
+
+//- SetPause -----------------------
+void Tourney::SetPause(int x) {
+  paused = x;
+}//- End SetPause
+
 //- Announce ----------------------------------------------------------
 void Tourney::Announce(void) {
   char temp[128];
@@ -935,6 +999,7 @@ void Tourney::TellThemWhoTheyPlay() {
 
   while((g = gameIter.Next())) {
          /* note that we rely on rmatch and on the ; separated commands from lasker */
+         sleep(2);
          gMamer.XServerCom("rmatch %s %s %i %i %c %s white ; rmatch %s %s %i %i %c %s black\n", 
                            g->whiteName, g->blackName, g->time, g->inc, params.mode, Variant,
                            g->blackName, g->whiteName, g->time, g->inc, params.mode, Variant);