Fixed error in Java AI
[progcomp2012.git] / judge / manager / game.cpp
1 #include "game.h"
2 #include <stdarg.h>
3 using namespace std;
4
5
6
7 Game* Game::theGame = NULL;
8 bool Game::gameCreated = false;
9
10 Game::Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const  Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime, const char * newImageOutput) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime), imageOutput(newImageOutput)
11 {
12         gameCreated = false;
13         if (gameCreated)
14         {
15                 fprintf(stderr, "Game::Game - Error - Tried to create more than one Game!\n");
16                 exit(EXIT_FAILURE);
17         }
18         gameCreated = true;
19         Game::theGame = this;
20         signal(SIGPIPE, Game::HandleBrokenPipe);
21
22
23         #ifdef BUILD_GRAPHICS
24         if (graphicsEnabled && (!Graphics::Initialised()))
25                         Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32);
26         #endif //BUILD_GRAPHICS
27
28
29
30         MakeControllers(redPath, bluePath);
31
32         if (red == NULL || blue == NULL)
33         {
34                 fprintf(stderr, "Game::Game - Error creating controller: ");
35                 if (red == NULL)
36                 {
37                         if (blue == NULL)
38                                 fprintf(stderr, " BOTH! (red: \"%s\", blue: \"%s\"\n", redPath, bluePath);
39                         else
40                                 fprintf(stderr, " RED! (red: \"%s\")\n", redPath);
41                 }
42                 else
43                         fprintf(stderr, "BLUE! (blue: \"%s\")\n", bluePath);
44                 exit(EXIT_FAILURE);
45         }
46 //      logMessage("Game initialised.\n");
47 }
48
49 Game::Game(const char * fromFile, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const  Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime,const char * newImageOutput) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime), imageOutput(newImageOutput)
50 {
51         gameCreated = false;
52         if (gameCreated)
53         {
54                 fprintf(stderr, "Game::Game - Error - Tried to create more than one Game!\n");
55                 exit(EXIT_FAILURE);
56         }
57         gameCreated = true;
58         Game::theGame = this;
59         signal(SIGPIPE, Game::HandleBrokenPipe);
60
61         #ifdef BUILD_GRAPHICS
62         if (graphicsEnabled && (!Graphics::Initialised()))
63                         Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32);
64         #endif //BUILD_GRAPHICS
65
66         input = fopen(fromFile, "r");
67
68         red = new FileController(Piece::RED, input);
69         blue = new FileController(Piece::BLUE, input);
70
71
72 }
73
74 Game::~Game()
75 {
76         
77         delete red;
78         delete blue;
79
80         if (log != NULL && log != stdout && log != stderr)
81                 fclose(log);
82
83         if (input != NULL && input != stdin)
84                 fclose(input);
85 }
86
87 /**
88  * Attempts to setup the board and controllers
89  * @param redName the name of the red AI
90  * @param blueName the name of the blue AI
91  * @returns A colour, indicating if there were any errors
92         Piece::NONE indicates no errors
93         Piece::BOTH indicates errors with both AI
94         Piece::RED / Piece::BLUE indicates an error with only one of the two AI
95  */
96 Piece::Colour Game::Setup(const char * redName, const char * blueName)
97 {
98
99         if (!red->Valid())
100         {
101                 logMessage("Controller for Player RED is invalid!\n");
102                 if (!red->HumanController())
103                         logMessage("Check that executable \"%s\" exists and has executable permissions set.\n", redName);
104         }
105         if (!blue->Valid())
106         {
107                 logMessage("Controller for Player BLUE is invalid!\n");
108                 if (!blue->HumanController())
109                         logMessage("Check that executable \"%s\" exists and has executable permissions set.\n", blueName);
110         }
111         if (!red->Valid())
112         {
113                 if (!blue->Valid())
114                         return Piece::BOTH;
115                 return Piece::RED;
116         }
117         else if (!blue->Valid())
118         {
119                 return Piece::BLUE;
120         }
121
122         for (int y = 4; y < 6; ++y)
123         {
124                 for (int x = 2; x < 4; ++x)
125                 {
126                         theBoard.AddPiece(x,y,Piece::BOULDER, Piece::NONE);
127                 }
128                 for (int x = 6; x < 8; ++x)
129                 {
130                         theBoard.AddPiece(x,y,Piece::BOULDER, Piece::NONE);
131                 }
132         }
133
134
135         MovementResult redSetup = red->Setup(blueName);
136         MovementResult blueSetup = blue->Setup(redName);
137
138
139         Piece::Colour result = Piece::NONE;
140         if (redSetup != MovementResult::OK)
141         {       
142                 if (blueSetup != MovementResult::OK)
143                 {
144                         logMessage("BOTH players give invalid setup!\n");
145                         result = Piece::BOTH;
146                 }
147                 else
148                 {
149                         //logMessage("Player RED gave an invalid setup!\n");
150                         result = Piece::RED;
151                 }
152                 
153         }
154         else if (blueSetup != MovementResult::OK)
155         {
156                 //logMessage("Player BLUE gave an invalid setup!\n");
157                 result = Piece::BLUE;
158         }
159
160
161         logMessage("%s RED SETUP\n", red->name.c_str());
162         if (redSetup == MovementResult::OK)
163         {
164                 for (int y=0; y < 4; ++y)
165                 {
166                         for (int x=0; x < theBoard.Width(); ++x)
167                         {
168                                 if (theBoard.GetPiece(x, y) != NULL)
169                                         logMessage("%c", Piece::tokens[(int)(theBoard.GetPiece(x, y)->type)]);
170                                 else
171                                         logMessage(".");
172                         }
173                         logMessage("\n");
174                 }       
175         }
176         else
177         {
178                 logMessage("INVALID!\n");
179         }
180
181         logMessage("%s BLUE SETUP\n", blue->name.c_str());
182         if (blueSetup == MovementResult::OK)
183         {
184                 for (int y=0; y < 4; ++y)
185                 {
186                         for (int x=0; x < theBoard.Width(); ++x)
187                         {
188                                 if (theBoard.GetPiece(x, theBoard.Height()-4+y) != NULL)
189                                         logMessage("%c", Piece::tokens[(int)(theBoard.GetPiece(x, theBoard.Height()-4+y)->type)]);
190                                 else
191                                         logMessage(".");
192                         }
193                         logMessage("\n");
194                 }       
195         }
196         else
197         {
198                 logMessage("INVALID!\n");
199         }
200
201         
202         return result;
203
204 }
205
206 void Game::Wait(double wait)
207 {
208         if (wait <= 0)
209                 return;
210
211         TimerThread timer(wait*1000000); //Wait in seconds
212         timer.Start();
213
214         #ifdef BUILD_GRAPHICS
215         if (!graphicsEnabled)
216         {
217                 while (!timer.Finished());
218                 timer.Stop();
219                 return;
220         }
221         #endif //BUILD_GRAPHICS
222
223         while (!timer.Finished())
224         {
225                 #ifdef BUILD_GRAPHICS
226                 SDL_Event  event;
227                 while (SDL_PollEvent(&event))
228                 {
229                         switch (event.type)
230                         {
231                                 case SDL_QUIT:
232                                         timer.Stop();
233                                         exit(EXIT_SUCCESS);
234                                         break;
235                         }
236                 }
237                 #endif //BUILD_GRAPHICS
238         }
239         timer.Stop();
240         
241 }
242
243 void Game::HandleBrokenPipe(int sig)
244 {
245         if (theGame == NULL)
246         {
247                 fprintf(stderr, "ERROR - Recieved SIGPIPE during game exit!\n");
248                 exit(EXIT_FAILURE);
249         }
250         if (theGame->turn == Piece::RED)
251         {
252                 theGame->logMessage("Game ends on RED's turn - REASON: ");
253                 if (theGame->blue->Valid()) //Should probably check this
254                         theGame->blue->Message("DEFAULT");      
255         }
256         else if (theGame->turn == Piece::BLUE)
257         {
258         
259                 theGame->logMessage("Game ends on BLUE's turn - REASON: ");
260                 if (theGame->red->Valid()) //Should probably check this
261                         theGame->red->Message("DEFAULT");
262         }
263         else
264         {
265                 theGame->logMessage("Game ends on ERROR's turn - REASON: ");
266                         
267         }
268         
269         theGame->logMessage("SIGPIPE - Broken pipe (AI program no longer running)\n");
270
271         if (Game::theGame->printBoard)
272                 Game::theGame->theBoard.PrintPretty(stdout, Piece::BOTH);
273
274         
275         #ifdef BUILD_GRAPHICS
276         if (Game::theGame->graphicsEnabled && theGame->log == stdout)
277         {
278                 theGame->logMessage("CLOSE WINDOW TO EXIT\n");
279                 Game::theGame->theBoard.Draw(Piece::BOTH);
280                 while (true)
281                 {
282                         SDL_Event  event;
283                         while (SDL_PollEvent(&event))
284                         {
285                                 switch (event.type)
286                                 {
287                                         case SDL_QUIT:
288                                                 exit(EXIT_SUCCESS);
289                                                 break;
290                                 }
291                         }                       
292                 }
293         }
294         else
295         #endif //BUILD_GRAPHICS
296         {
297                 if (theGame->log == stdout || theGame->log == stderr)
298                 {
299                         theGame->logMessage( "PRESS ENTER TO EXIT\n");
300                         theGame->theBoard.Print(theGame->log);
301                         while (fgetc(stdin) != '\n');
302                 }
303         }
304         
305
306         exit(EXIT_SUCCESS);
307 }
308
309 void Game::PrintEndMessage(const MovementResult & result)
310 {
311         if (turnCount == 0)
312         {
313                 logMessage("Game ends in the SETUP phase - REASON: ");
314         }
315         else
316         {
317                 if (turn == Piece::RED)
318                 {
319                         logMessage("Game ends on RED's turn - REASON: ");       
320                 }
321                 else if (turn == Piece::BLUE)
322                 {
323                         logMessage("Game ends on BLUE's turn - REASON: ");
324                 }
325                 else
326                 {
327                         logMessage("Game ends on ERROR's turn - REASON: ");
328                         
329                 }
330         }
331         switch (result.type)
332         {
333                 case MovementResult::OK:
334                         logMessage("Status returned OK, unsure why game halted...\n");
335                         break;
336                 case MovementResult::DIES:
337                         logMessage("Status returned DIES, unsure why game halted...\n");
338                         break;
339                 case MovementResult::KILLS:
340                         logMessage("Status returned KILLS, unsure why game halted...\n");
341                         break;
342                 case MovementResult::BOTH_DIE:
343                         logMessage("Status returned BOTH_DIE, unsure why game halted...\n");
344                         break;
345                 case MovementResult::NO_BOARD:
346                         logMessage("Board does not exit?!\n");
347                         break;
348                 case MovementResult::INVALID_POSITION:
349                         logMessage("Coords outside board\n");
350                         break;
351                 case MovementResult::NO_SELECTION:
352                         logMessage("Move does not select a piece\n");
353                         break;
354                 case MovementResult::NOT_YOUR_UNIT:
355                         logMessage("Selected piece belongs to other player\n");
356                         break;
357                 case MovementResult::IMMOBILE_UNIT:
358                         logMessage("Selected piece is not mobile (FLAG or BOMB)\n");
359                         break;
360                 case MovementResult::INVALID_DIRECTION:
361                         logMessage("Selected unit cannot move that way\n");
362                         break;
363                 case MovementResult::POSITION_FULL:
364                         logMessage("Attempted move into square occupied by neutral or allied piece\n");
365                         break;
366                 case MovementResult::VICTORY_FLAG:
367                         logMessage("Captured the flag\n");
368                         break;
369                 case MovementResult::VICTORY_ATTRITION:
370                         logMessage("Destroyed all mobile enemy pieces\n");
371                         break;
372                 case MovementResult::BAD_RESPONSE:
373                         logMessage("Unintelligable response\n");
374                         break;
375                 case MovementResult::NO_MOVE:
376                         logMessage("Response timeout after %2f seconds.\n", timeoutTime);
377                         break;
378                 case MovementResult::COLOUR_ERROR:
379                         logMessage("Internal controller error - COLOUR_ERROR\n");
380                         break;
381                 case MovementResult::ERROR:
382                         logMessage("Internal controller error - Unspecified ERROR\n");
383                         break;
384                 case MovementResult::DRAW_DEFAULT:
385                         logMessage("Game declared a draw after %d turns\n", turnCount);
386                         break;
387                 case MovementResult::DRAW:
388                         logMessage("Game declared a draw because neither player has mobile pieces\n");
389                         break;
390                 case MovementResult::SURRENDER:
391                         logMessage("This player has surrendered!\n");
392                         break;
393                 case MovementResult::BAD_SETUP:
394                         switch (turn)
395                         {
396                                 case Piece::RED:
397                                         logMessage("An illegal setup was made by RED\n");
398                                         break;
399                                 case Piece::BLUE:
400                                         logMessage("An illegal setup was made by BLUE\n");
401                                         break;
402                                 case Piece::BOTH:
403                                         logMessage("An illegal setup was made by BOTH players\n");
404                                         break;
405                                 case Piece::NONE:
406                                         logMessage("Unknown internal error.\n");
407                                         break;
408                         }
409                         break;
410
411         }
412
413         if (printBoard)
414         {
415                 system("clear");
416                 fprintf(stdout, "%d Final State\n", turnCount);
417                 theBoard.PrintPretty(stdout, Piece::BOTH);
418                 fprintf(stdout, "\n");
419         }
420
421         #ifdef BUILD_GRAPHICS
422         if (graphicsEnabled && log == stdout)
423         {
424                 logMessage("CLOSE WINDOW TO EXIT\n");
425                 theBoard.Draw(Piece::BOTH);
426                 while (true)
427                 {
428                         SDL_Event  event;
429                         while (SDL_PollEvent(&event))
430                         {
431                                 switch (event.type)
432                                 {
433                                         case SDL_QUIT:
434                                                 exit(EXIT_SUCCESS);
435                                                 break;
436                                 }
437                         }                       
438                 }
439         }
440         else
441         #endif //BUILD_GRAPHICS
442         {
443                 if (log == stdout)
444                 {
445                         logMessage("PRESS ENTER TO EXIT\n");
446                         while (fgetc(stdin) != '\n');
447                         exit(EXIT_SUCCESS); //Might want to actually exit, you foolish fool
448                 }
449         }
450
451 }
452 /** Checks for victory by attrition (destroying all mobile pieces)
453  *
454  *  @returns OK for no victory, 
455  *      DRAW if both players have no pieces, or 
456  *      VICTORY_ATTRITION  if the current player has won by attrition
457  */
458 MovementResult Game::CheckVictoryAttrition()
459 {
460         if (theBoard.MobilePieces(Piece::OppositeColour(turn)) == 0)
461         {
462                 if (theBoard.MobilePieces(turn) == 0)
463                         return MovementResult::DRAW;
464                 else
465                         return MovementResult::VICTORY_ATTRITION;
466         }
467         return MovementResult::OK;
468
469 }
470 MovementResult Game::Play()
471 {
472
473         MovementResult result = MovementResult::OK;
474         turnCount = 1;
475         string buffer;
476
477         Piece::Colour toReveal = reveal;
478         
479         
480         
481
482 //      logMessage("Messaging red with \"START\"\n");
483         red->Message("START");
484         
485         int moveCount = 0;
486
487         while (!Board::HaltResult(result) && (turnCount < maxTurns || maxTurns < 0))
488         {
489                 if (red->HumanController() && blue->HumanController())
490                         toReveal = Piece::RED;
491                 if (printBoard)
492                 {
493                         system("clear");
494                         if (turnCount == 0)
495                                 fprintf(stdout, "START:\n");
496                         else
497                                 fprintf(stdout, "%d BLUE:\n", turnCount);
498                         theBoard.PrintPretty(stdout, toReveal);
499                         fprintf(stdout, "\n\n");
500                 }
501
502                 #ifdef BUILD_GRAPHICS
503                 if (graphicsEnabled)
504                 {
505                         theBoard.Draw(toReveal);
506                         if (imageOutput != "")
507                         {
508                                 string imageFile = "" + imageOutput + "/"+ itostr(moveCount) + ".bmp";
509                                 Graphics::ScreenShot(imageFile.c_str());
510                         }
511
512                 }
513                 #endif //BUILD_GRAPHICS
514                 
515                 turn = Piece::RED;
516                 blue->Pause();
517                 red->Continue();
518                 if (!Board::HaltResult(result))
519                 {
520                         result = CheckVictoryAttrition();
521                 }
522                 if (Board::HaltResult(result))
523                         break;
524
525                 logMessage( "%d RED: ", turnCount);
526                 result = red->MakeMove(buffer);
527                 red->Message(buffer);
528                 blue->Message(buffer);
529                 logMessage( "%s\n", buffer.c_str());
530
531                 if (!Board::HaltResult(result))
532                 {
533                         result = CheckVictoryAttrition();
534                 }
535                 if (Board::HaltResult(result))
536                         break;
537
538                 if (stallTime >= 0)
539                         Wait(stallTime);
540                 else
541                         ReadUserCommand();
542
543                 if (blue->HumanController() && red->HumanController())
544                         toReveal = Piece::BLUE;
545                 if (printBoard)
546                 {
547                         system("clear");
548                         fprintf(stdout, "%d RED:\n", turnCount);
549                         theBoard.PrintPretty(stdout, toReveal);
550                         fprintf(stdout, "\n\n");
551                 }
552
553                 ++moveCount;
554                 
555                 #ifdef BUILD_GRAPHICS
556                 if (graphicsEnabled)
557                 {
558                         theBoard.Draw(toReveal);
559                         if (imageOutput != "")
560                         {
561                                 string imageFile = "" + imageOutput + "/" + itostr(moveCount) + ".bmp";
562                                 Graphics::ScreenShot(imageFile.c_str());
563                         }
564                 }
565                 #endif //BUILD_GRAPHICS
566
567                 
568                 
569                 turn = Piece::BLUE;
570                 red->Pause();
571                 blue->Continue();
572                 if (!Board::HaltResult(result))
573                 {
574                         result = CheckVictoryAttrition();
575                 }
576                 if (Board::HaltResult(result))
577                         break;
578
579                 logMessage( "%d BLU: ", turnCount);
580                 result = blue->MakeMove(buffer);
581                 blue->Message(buffer);
582                 red->Message(buffer);
583                 logMessage( "%s\n", buffer.c_str());
584
585                 if (!Board::HaltResult(result))
586                 {
587                         result = CheckVictoryAttrition();
588                 }
589                 if (Board::HaltResult(result))
590                         break;
591
592                 if (theBoard.MobilePieces(Piece::RED) == 0)
593                         result = MovementResult::DRAW;
594
595                 if (theBoard.MobilePieces(Piece::RED) == 0)
596                 {
597                         if (theBoard.MobilePieces(Piece::BLUE) == 0)
598                                 result = MovementResult::DRAW;
599                         else
600                                 result = MovementResult::VICTORY_ATTRITION;
601                         break;                  
602                 }
603
604                 if (stallTime >= 0)
605                         Wait(stallTime);
606                 else
607                         ReadUserCommand();
608         
609                 ++moveCount;
610
611                 ++turnCount;
612         }
613
614         if ((maxTurns >= 0 && turnCount >= maxTurns) && result == MovementResult::OK)
615         {
616                 result = MovementResult::DRAW_DEFAULT;
617         }
618
619         
620         return result;
621
622                 
623
624 }
625
626 /**
627  * Logs a message to the game's log file if it exists
628  * @param format the format string
629  * @param additional parameters - printed using va_args
630  * @returns the result of vfprintf or a negative number if the log file does not exist
631  */
632 int Game::logMessage(const char * format, ...)
633 {
634         if (log == NULL)
635                 return -666;
636                 va_list ap;
637         va_start(ap, format);
638
639         int result = vfprintf(log, format, ap);
640         va_end(ap);
641
642         return result;
643 }
644
645 /**
646  * Waits for a user command
647  * Currently ignores the command.
648  */
649 void Game::ReadUserCommand()
650 {
651         fprintf(stdout, "Waiting for user to press enter... (type QUIT to exit)\n");
652         string command("");
653         for (char c = fgetc(stdin); c != '\n' && (int)(c) != EOF; c = fgetc(stdin))
654         {
655                 command += c;
656         }
657
658         if (command == "QUIT")
659         {
660                 fprintf(stdout, "Ordered to quit... exiting...\n");
661                 exit(EXIT_SUCCESS);
662         }
663 }
664
665 MovementResult FileController::QuerySetup(const char * opponentName, std::string setup[])
666 {
667
668         char c = fgetc(file);
669         name = "";
670         while (c != ' ')
671         {
672                 name += c;
673                 c = fgetc(file);
674         }
675
676         while (fgetc(file) != '\n');
677
678         for (int y = 0; y < 4; ++y)
679         {
680                 setup[y] = "";
681                 for (int x = 0; x < Game::theGame->theBoard.Width(); ++x)
682                 {
683                         setup[y] += fgetc(file);
684                 }
685
686                 if (fgetc(file) != '\n')
687                 {
688                         return MovementResult::BAD_RESPONSE;
689                 }
690         }
691         return MovementResult::OK;
692
693         
694 }
695
696 MovementResult FileController::QueryMove(std::string & buffer)
697 {
698         //This bit is kind of hacky and terrible, and yes I am mixing C with C++
699         //Yes I should have used fstream for the whole thing and it would be much easier.
700         //Oh well.
701
702         char buf[BUFSIZ];
703
704         fgets(buf, sizeof(buf), file);
705         char * s = (char*)(buf);
706         while (*s != ':' && *s != '\0')
707                 ++s;
708         
709         //Move forward to the start of the move information
710         for (int i=0; i < 2; ++i)
711         {
712                 if (*s != '\0' && *s != '\n')
713                         ++s;
714         }
715         
716         //Unfortunately we can't just copy the whole line
717         buffer = string(s);
718         //We have to remove the movement result tokens
719         
720
721         vector<string> tokens;
722         Game::Tokenise(tokens, buffer, ' ');
723         buffer.clear();
724
725         if (tokens.size() < 1)
726                 return MovementResult::BAD_RESPONSE;
727         buffer += tokens[0];
728
729         
730         if (tokens[0] == "NO_MOVE") //tokens[0] is either the x coordinate, or "NO_MOVE"
731                 return MovementResult::OK;
732         if (tokens.size() < 2)
733                 return MovementResult::BAD_RESPONSE;
734         buffer += " ";
735         buffer += tokens[1]; //The y coordinate
736         buffer += " ";
737         buffer += tokens[2]; //The direction
738         
739         //Check for a possible multiplier. If tokens[3] is an integer it will be the multiplier, otherwise it won't be.
740         if (tokens.size() > 3 && atoi(tokens[3].c_str()) != 0)
741         {
742                 buffer += " ";
743                 buffer += tokens[3];
744         }
745         else
746         {
747                 //(tokens[3] should include a new line)
748                 //buffer += "\n";
749         }
750
751         
752
753         
754         
755         
756         return MovementResult::OK;
757 }
758
759 /**
760  * Tokenise a string
761  */
762 int Game::Tokenise(std::vector<string> & buffer, std::string & str, char split)
763 {
764         string token = "";
765         for (unsigned int x = 0; x < str.size(); ++x)
766         {
767                 if (str[x] == split && token.size() > 0)
768                 {
769                         buffer.push_back(token);
770                         token = "";
771                 }
772                 if (str[x] != split)
773                         token += str[x];
774         }
775         if (token.size() > 0)
776                 buffer.push_back(token);
777         return buffer.size();
778 }
779
780 /**
781  * Creates Controller baseds off strings. Takes into account controllers other than AI_Controller.
782  * @param redPath - Either the path to an AI_Controller compatable executable, or one of %human or %network or %network:[IP_ADDRESS]
783  * @param bluePath - Ditto
784  * Sets this->red to a controller using redPath, and this->blue to a controller using bluePath
785  * TODO: Make nicer (this function should be ~half the length)
786  */
787 void Game::MakeControllers(const char * redPath, const char * bluePath)
788 {
789         Network * redNetwork = NULL;
790         Network * blueNetwork = NULL;
791         //To allow for running two network controllers (I don't know why you would, but beside the point...) use two ports
792         static const int port1 = 4560;
793         static const int port2 = 4561;
794
795         if (redPath[0] == '@')
796         {
797                 if (strcmp(redPath, "@human") == 0)
798                         red = new Human_Controller(Piece::RED, graphicsEnabled);
799                 else
800                 {
801                         const char * network = strstr(redPath, "@network");
802                         if (network == NULL)
803                         {
804                                 red = NULL;
805                                 return;
806                         }
807                         network = strstr(network, ":");
808                 
809                         if (network == NULL)
810                         {
811                                 logMessage("Creating server for red AI... ");
812                                 redNetwork = new Server(port1);
813                                 logMessage("Successful!\n");
814
815                         }
816                         else
817                         {
818                                 network = (const char*)(network+1);
819                                 logMessage("Creating client for red AI... ");
820                                 redNetwork = new Client(network, port2);
821                                 logMessage("Connected to address %s\n", network);
822                         }
823
824                         logMessage("    (Red's responses will be received over the connection)\n");
825                         red = new NetworkReceiver(Piece::RED, redNetwork);
826                 }               
827         }
828         else
829                 red = new AI_Controller(Piece::RED, redPath, timeoutTime);
830
831         if (bluePath[0] == '@')
832         {
833                 if (strcmp(bluePath, "@human") == 0)
834                         blue = new Human_Controller(Piece::BLUE, graphicsEnabled);
835                 else
836                 {
837                         const char * network = strstr(bluePath, "@network");
838                         if (network == NULL)
839                         {
840                                 blue = NULL;
841                                 return;
842                         }
843                         network = strstr(network, ":");
844                 
845                         if (network == NULL)
846                         {
847                                 logMessage("Creating server for blue AI... ");
848                                 blueNetwork = new Server(port2);
849                                 logMessage("Successful!\n");
850
851                         }
852                         else
853                         {
854                                 network = (const char*)(network+1);
855                                 logMessage("Creating client for blue AI... ");
856                                 blueNetwork = new Client(network, port1);
857                                 logMessage("Connected to address %s\n", network);
858                         }
859                         logMessage("    (Blue's responses will be received over the connection)\n");
860                         blue = new NetworkReceiver(Piece::BLUE, blueNetwork);
861                 }               
862         }
863         else
864                 blue = new AI_Controller(Piece::BLUE, bluePath, timeoutTime);
865
866         if (redNetwork != NULL)
867         {
868                 
869                 blue = new NetworkSender(Piece::BLUE,blue, redNetwork);
870                 logMessage("    (Blue's responses will be copied over the connection)\n");
871         }
872         if (blueNetwork != NULL)
873         {
874                 
875                 red = new NetworkSender(Piece::RED, red, blueNetwork);
876                 logMessage("    (Red's responses will be copied over the connection)\n");
877         }
878
879         red->FixName(); blue->FixName();
880         
881 }
882
883 string itostr(int i)
884 {
885         stringstream s;
886         s << i;
887         return s.str();
888 }
889

UCC git Repository :: git.ucc.asn.au