Merge branch 'networking' of mussel.ucc.asn.au:progcomp2012
[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
212
213
214         #ifdef BUILD_GRAPHICS
215
216
217         if (!graphicsEnabled)
218         {
219                 usleep(1000000*wait); //Wait in seconds
220                 return;
221         }
222
223         TimerThread timer(wait*1000000); //Wait in seconds
224         timer.Start();
225         while (!timer.Finished())
226         {
227         
228                 SDL_Event  event;
229                 while (SDL_PollEvent(&event))
230                 {
231                         switch (event.type)
232                         {
233                                 case SDL_QUIT:
234                                         timer.Stop();
235                                         exit(EXIT_SUCCESS);
236                                         break;
237                         }
238                 }
239         }
240         timer.Stop();
241
242         #else
243         usleep(wait*1000000); //Wait in seconds
244         #endif //BUILD_GRAPHICS
245         
246 }
247
248 void Game::HandleBrokenPipe(int sig)
249 {
250         if (theGame == NULL)
251         {
252                 fprintf(stderr, "ERROR - Recieved SIGPIPE during game exit!\n");
253                 exit(EXIT_FAILURE);
254         }
255         if (theGame->turn == Piece::RED)
256         {
257                 theGame->logMessage("Game ends on RED's turn - REASON: ");
258                 if (theGame->blue->Valid()) //Should probably check this
259                         theGame->blue->Message("DEFAULT");      
260         }
261         else if (theGame->turn == Piece::BLUE)
262         {
263         
264                 theGame->logMessage("Game ends on BLUE's turn - REASON: ");
265                 if (theGame->red->Valid()) //Should probably check this
266                         theGame->red->Message("DEFAULT");
267         }
268         else
269         {
270                 theGame->logMessage("Game ends on ERROR's turn - REASON: ");
271                         
272         }
273         
274         theGame->logMessage("SIGPIPE - Broken pipe (AI program no longer running)\n");
275
276         if (Game::theGame->printBoard)
277                 Game::theGame->theBoard.PrintPretty(stdout, Piece::BOTH);
278
279         
280         #ifdef BUILD_GRAPHICS
281         if (Game::theGame->graphicsEnabled && theGame->log == stdout)
282         {
283                 theGame->logMessage("CLOSE WINDOW TO EXIT\n");
284                 Game::theGame->theBoard.Draw(Piece::BOTH);
285                 while (true)
286                 {
287                         SDL_Event  event;
288                         while (SDL_PollEvent(&event))
289                         {
290                                 switch (event.type)
291                                 {
292                                         case SDL_QUIT:
293                                                 exit(EXIT_SUCCESS);
294                                                 break;
295                                 }
296                         }                       
297                 }
298         }
299         else
300         #endif //BUILD_GRAPHICS
301         {
302                 if (theGame->log == stdout || theGame->log == stderr)
303                 {
304                         theGame->logMessage( "PRESS ENTER TO EXIT\n");
305                         theGame->theBoard.Print(theGame->log);
306                         while (fgetc(stdin) != '\n');
307                 }
308         }
309         
310
311         exit(EXIT_SUCCESS);
312 }
313
314 void Game::PrintEndMessage(const MovementResult & result)
315 {
316         if (turnCount == 0)
317         {
318                 logMessage("Game ends in the SETUP phase - REASON: ");
319         }
320         else
321         {
322                 if (turn == Piece::RED)
323                 {
324                         logMessage("Game ends on RED's turn - REASON: ");       
325                 }
326                 else if (turn == Piece::BLUE)
327                 {
328                         logMessage("Game ends on BLUE's turn - REASON: ");
329                 }
330                 else
331                 {
332                         logMessage("Game ends on ERROR's turn - REASON: ");
333                         
334                 }
335         }
336         switch (result.type)
337         {
338                 case MovementResult::OK:
339                         logMessage("Status returned OK, unsure why game halted...\n");
340                         break;
341                 case MovementResult::DIES:
342                         logMessage("Status returned DIES, unsure why game halted...\n");
343                         break;
344                 case MovementResult::KILLS:
345                         logMessage("Status returned KILLS, unsure why game halted...\n");
346                         break;
347                 case MovementResult::BOTH_DIE:
348                         logMessage("Status returned BOTH_DIE, unsure why game halted...\n");
349                         break;
350                 case MovementResult::NO_BOARD:
351                         logMessage("Board does not exit?!\n");
352                         break;
353                 case MovementResult::INVALID_POSITION:
354                         logMessage("Coords outside board\n");
355                         break;
356                 case MovementResult::NO_SELECTION:
357                         logMessage("Move does not select a piece\n");
358                         break;
359                 case MovementResult::NOT_YOUR_UNIT:
360                         logMessage("Selected piece belongs to other player\n");
361                         break;
362                 case MovementResult::IMMOBILE_UNIT:
363                         logMessage("Selected piece is not mobile (FLAG or BOMB)\n");
364                         break;
365                 case MovementResult::INVALID_DIRECTION:
366                         logMessage("Selected unit cannot move that way\n");
367                         break;
368                 case MovementResult::POSITION_FULL:
369                         logMessage("Attempted move into square occupied by neutral or allied piece\n");
370                         break;
371                 case MovementResult::VICTORY_FLAG:
372                         logMessage("Captured the flag\n");
373                         break;
374                 case MovementResult::VICTORY_ATTRITION:
375                         logMessage("Destroyed all mobile enemy pieces\n");
376                         break;
377                 case MovementResult::BAD_RESPONSE:
378                         logMessage("Unintelligable response\n");
379                         break;
380                 case MovementResult::NO_MOVE:
381                         logMessage("Response timeout after %2f seconds.\n", timeoutTime);
382                         break;
383                 case MovementResult::COLOUR_ERROR:
384                         logMessage("Internal controller error - COLOUR_ERROR\n");
385                         break;
386                 case MovementResult::ERROR:
387                         logMessage("Internal controller error - Unspecified ERROR\n");
388                         break;
389                 case MovementResult::DRAW_DEFAULT:
390                         logMessage("Game declared a draw after %d turns\n", turnCount);
391                         break;
392                 case MovementResult::DRAW:
393                         logMessage("Game declared a draw because neither player has mobile pieces\n");
394                         break;
395                 case MovementResult::SURRENDER:
396                         logMessage("This player has surrendered!\n");
397                         break;
398                 case MovementResult::BAD_SETUP:
399                         switch (turn)
400                         {
401                                 case Piece::RED:
402                                         logMessage("An illegal setup was made by RED\n");
403                                         break;
404                                 case Piece::BLUE:
405                                         logMessage("An illegal setup was made by BLUE\n");
406                                         break;
407                                 case Piece::BOTH:
408                                         logMessage("An illegal setup was made by BOTH players\n");
409                                         break;
410                                 case Piece::NONE:
411                                         logMessage("Unknown internal error.\n");
412                                         break;
413                         }
414                         break;
415
416         }
417
418         if (printBoard)
419         {
420                 system("clear");
421                 fprintf(stdout, "%d Final State\n", turnCount);
422                 theBoard.PrintPretty(stdout, Piece::BOTH);
423                 fprintf(stdout, "\n");
424         }
425
426         #ifdef BUILD_GRAPHICS
427         if (graphicsEnabled && log == stdout)
428         {
429                 logMessage("CLOSE WINDOW TO EXIT\n");
430                 theBoard.Draw(Piece::BOTH);
431                 while (true)
432                 {
433                         SDL_Event  event;
434                         while (SDL_PollEvent(&event))
435                         {
436                                 switch (event.type)
437                                 {
438                                         case SDL_QUIT:
439                                                 exit(EXIT_SUCCESS);
440                                                 break;
441                                 }
442                         }                       
443                 }
444         }
445         else
446         #endif //BUILD_GRAPHICS
447         {
448                 if (log == stdout)
449                 {
450                         logMessage("PRESS ENTER TO EXIT\n");
451                         while (fgetc(stdin) != '\n');
452                         exit(EXIT_SUCCESS); //Might want to actually exit, you foolish fool
453                 }
454         }
455
456 }
457 /** Checks for victory by attrition (destroying all mobile pieces)
458  *
459  *  @returns OK for no victory, 
460  *      DRAW if both players have no pieces, or 
461  *      VICTORY_ATTRITION  if the current player has won by attrition
462  */
463 MovementResult Game::CheckVictoryAttrition()
464 {
465         if (theBoard.MobilePieces(Piece::OppositeColour(turn)) == 0)
466         {
467                 if (theBoard.MobilePieces(turn) == 0)
468                         return MovementResult::DRAW;
469                 else
470                         return MovementResult::VICTORY_ATTRITION;
471         }
472         return MovementResult::OK;
473
474 }
475 MovementResult Game::Play()
476 {
477
478         MovementResult result = MovementResult::OK;
479         turnCount = 1;
480         string buffer;
481
482         Piece::Colour toReveal = reveal;
483         
484         
485         
486
487 //      logMessage("Messaging red with \"START\"\n");
488         red->Message("START");
489         
490         int moveCount = 0;
491
492         while (!Board::HaltResult(result) && (turnCount < maxTurns || maxTurns < 0))
493         {
494                 if (red->HumanController() && blue->HumanController())
495                         toReveal = Piece::RED;
496                 if (printBoard)
497                 {
498                         system("clear");
499                         if (turnCount == 0)
500                                 fprintf(stdout, "START:\n");
501                         else
502                                 fprintf(stdout, "%d BLUE:\n", turnCount);
503                         theBoard.PrintPretty(stdout, toReveal);
504                         fprintf(stdout, "\n\n");
505                 }
506
507                 #ifdef BUILD_GRAPHICS
508                 if (graphicsEnabled)
509                 {
510                         theBoard.Draw(toReveal);
511                         if (imageOutput != "")
512                         {
513                                 string imageFile = "" + imageOutput + "/"+ itostr(moveCount) + ".bmp";
514                                 Graphics::ScreenShot(imageFile.c_str());
515                         }
516
517                 }
518                 #endif //BUILD_GRAPHICS
519                 
520                 turn = Piece::RED;
521                 blue->Pause();
522                 red->Continue();
523                 if (!Board::HaltResult(result))
524                 {
525                         result = CheckVictoryAttrition();
526                 }
527                 if (Board::HaltResult(result))
528                         break;
529
530                 logMessage( "%d RED: ", turnCount);
531                 result = red->MakeMove(buffer);
532                 red->Message(buffer);
533                 blue->Message(buffer);
534                 logMessage( "%s\n", buffer.c_str());
535
536                 if (!Board::HaltResult(result))
537                 {
538                         result = CheckVictoryAttrition();
539                 }
540                 if (Board::HaltResult(result))
541                         break;
542
543                 if (stallTime >= 0)
544                         Wait(stallTime);
545                 else
546                         ReadUserCommand();
547
548                 if (blue->HumanController() && red->HumanController())
549                         toReveal = Piece::BLUE;
550                 if (printBoard)
551                 {
552                         system("clear");
553                         fprintf(stdout, "%d RED:\n", turnCount);
554                         theBoard.PrintPretty(stdout, toReveal);
555                         fprintf(stdout, "\n\n");
556                 }
557
558                 ++moveCount;
559                 
560                 #ifdef BUILD_GRAPHICS
561                 if (graphicsEnabled)
562                 {
563                         theBoard.Draw(toReveal);
564                         if (imageOutput != "")
565                         {
566                                 string imageFile = "" + imageOutput + "/" + itostr(moveCount) + ".bmp";
567                                 Graphics::ScreenShot(imageFile.c_str());
568                         }
569                 }
570                 #endif //BUILD_GRAPHICS
571
572                 
573                 
574                 turn = Piece::BLUE;
575                 red->Pause();
576                 blue->Continue();
577                 if (!Board::HaltResult(result))
578                 {
579                         result = CheckVictoryAttrition();
580                 }
581                 if (Board::HaltResult(result))
582                         break;
583
584                 logMessage( "%d BLU: ", turnCount);
585                 result = blue->MakeMove(buffer);
586                 blue->Message(buffer);
587                 red->Message(buffer);
588                 logMessage( "%s\n", buffer.c_str());
589
590                 if (!Board::HaltResult(result))
591                 {
592                         result = CheckVictoryAttrition();
593                 }
594                 if (Board::HaltResult(result))
595                         break;
596
597                 if (theBoard.MobilePieces(Piece::RED) == 0)
598                         result = MovementResult::DRAW;
599
600                 if (theBoard.MobilePieces(Piece::RED) == 0)
601                 {
602                         if (theBoard.MobilePieces(Piece::BLUE) == 0)
603                                 result = MovementResult::DRAW;
604                         else
605                                 result = MovementResult::VICTORY_ATTRITION;
606                         break;                  
607                 }
608
609                 if (stallTime >= 0)
610                         Wait(stallTime);
611                 else
612                         ReadUserCommand();
613         
614                 ++moveCount;
615
616                 ++turnCount;
617         }
618
619         if ((maxTurns >= 0 && turnCount >= maxTurns) && result == MovementResult::OK)
620         {
621                 result = MovementResult::DRAW_DEFAULT;
622         }
623
624         
625         return result;
626
627                 
628
629 }
630
631 /**
632  * Logs a message to the game's log file if it exists
633  * @param format the format string
634  * @param additional parameters - printed using va_args
635  * @returns the result of vfprintf or a negative number if the log file does not exist
636  */
637 int Game::logMessage(const char * format, ...)
638 {
639         if (log == NULL)
640                 return -666;
641                 va_list ap;
642         va_start(ap, format);
643
644         int result = vfprintf(log, format, ap);
645         va_end(ap);
646
647         return result;
648 }
649
650 /**
651  * Waits for a user command
652  * Currently ignores the command.
653  */
654 void Game::ReadUserCommand()
655 {
656         fprintf(stdout, "Waiting for user to press enter... (type QUIT to exit)\n");
657         string command("");
658         for (char c = fgetc(stdin); c != '\n' && (int)(c) != EOF; c = fgetc(stdin))
659         {
660                 command += c;
661         }
662
663         if (command == "QUIT")
664         {
665                 fprintf(stdout, "Ordered to quit... exiting...\n");
666                 exit(EXIT_SUCCESS);
667         }
668 }
669
670 MovementResult FileController::QuerySetup(const char * opponentName, std::string setup[])
671 {
672
673         char c = fgetc(file);
674         name = "";
675         while (c != ' ')
676         {
677                 name += c;
678                 c = fgetc(file);
679         }
680
681         while (fgetc(file) != '\n');
682
683         for (int y = 0; y < 4; ++y)
684         {
685                 setup[y] = "";
686                 for (int x = 0; x < Game::theGame->theBoard.Width(); ++x)
687                 {
688                         setup[y] += fgetc(file);
689                 }
690
691                 if (fgetc(file) != '\n')
692                 {
693                         return MovementResult::BAD_RESPONSE;
694                 }
695         }
696         return MovementResult::OK;
697
698         
699 }
700
701 MovementResult FileController::QueryMove(std::string & buffer)
702 {
703         //This bit is kind of hacky and terrible, and yes I am mixing C with C++
704         //Yes I should have used fstream for the whole thing and it would be much easier.
705         //Oh well.
706
707         char buf[BUFSIZ];
708
709         fgets(buf, sizeof(buf), file);
710         char * s = (char*)(buf);
711         while (*s != ':' && *s != '\0')
712                 ++s;
713         
714         //Move forward to the start of the move information
715         for (int i=0; i < 2; ++i)
716         {
717                 if (*s != '\0' && *s != '\n')
718                         ++s;
719         }
720         
721         //Unfortunately we can't just copy the whole line
722         buffer = string(s);
723         //We have to remove the movement result tokens
724         
725
726         vector<string> tokens;
727         Game::Tokenise(tokens, buffer, ' ');
728         buffer.clear();
729
730         if (tokens.size() < 1)
731                 return MovementResult::BAD_RESPONSE;
732         buffer += tokens[0];
733
734         
735         if (tokens[0] == "NO_MOVE") //tokens[0] is either the x coordinate, or "NO_MOVE"
736                 return MovementResult::OK;
737         if (tokens.size() < 2)
738                 return MovementResult::BAD_RESPONSE;
739         buffer += " ";
740         buffer += tokens[1]; //The y coordinate
741         buffer += " ";
742         buffer += tokens[2]; //The direction
743         
744         //Check for a possible multiplier. If tokens[3] is an integer it will be the multiplier, otherwise it won't be.
745         if (tokens.size() > 3 && atoi(tokens[3].c_str()) != 0)
746         {
747                 buffer += " ";
748                 buffer += tokens[3];
749         }
750         else
751         {
752                 //(tokens[3] should include a new line)
753                 //buffer += "\n";
754         }
755
756         
757
758         
759         
760         
761         return MovementResult::OK;
762 }
763
764 /**
765  * Tokenise a string
766  */
767 int Game::Tokenise(std::vector<string> & buffer, std::string & str, char split)
768 {
769         string token = "";
770         for (unsigned int x = 0; x < str.size(); ++x)
771         {
772                 if (str[x] == split && token.size() > 0)
773                 {
774                         buffer.push_back(token);
775                         token = "";
776                 }
777                 if (str[x] != split)
778                         token += str[x];
779         }
780         if (token.size() > 0)
781                 buffer.push_back(token);
782         return buffer.size();
783 }
784
785 /**
786  * Creates Controller baseds off strings. Takes into account controllers other than AI_Controller.
787  * @param redPath - Either the path to an AI_Controller compatable executable, or one of %human or %network or %network:[IP_ADDRESS]
788  * @param bluePath - Ditto
789  * Sets this->red to a controller using redPath, and this->blue to a controller using bluePath
790  * TODO: Make nicer (this function should be ~half the length)
791  */
792 void Game::MakeControllers(const char * redPath, const char * bluePath)
793 {
794         Network * redNetwork = NULL;
795         Network * blueNetwork = NULL;
796         //To allow for running two network controllers (I don't know why you would, but beside the point...) use two ports
797         static const int port1 = 4560;
798         static const int port2 = 4561;
799
800         if (redPath[0] == '@')
801         {
802                 if (strcmp(redPath, "@human") == 0)
803                         red = new Human_Controller(Piece::RED, graphicsEnabled);
804                 else
805                 {
806                         const char * network = strstr(redPath, "@network");
807                         if (network == NULL)
808                         {
809                                 red = NULL;
810                                 return;
811                         }
812                         network = strstr(network, ":");
813                 
814                         if (network == NULL)
815                         {
816                                 logMessage("Creating server for red AI... ");
817                                 redNetwork = new Server(port1);
818                                 logMessage("Successful!\n");
819
820                         }
821                         else
822                         {
823                                 network = (const char*)(network+1);
824                                 logMessage("Creating client for red AI... ");
825                                 redNetwork = new Client(network, port2);
826                                 logMessage("Connected to address %s\n", network);
827                         }
828
829                         logMessage("    (Red's responses will be received over the connection)\n");
830                         red = new NetworkReceiver(Piece::RED, redNetwork);
831                 }               
832         }
833         else
834                 red = new AI_Controller(Piece::RED, redPath, timeoutTime);
835
836         if (bluePath[0] == '@')
837         {
838                 if (strcmp(bluePath, "@human") == 0)
839                         blue = new Human_Controller(Piece::BLUE, graphicsEnabled);
840                 else
841                 {
842                         const char * network = strstr(bluePath, "@network");
843                         if (network == NULL)
844                         {
845                                 blue = NULL;
846                                 return;
847                         }
848                         network = strstr(network, ":");
849                 
850                         if (network == NULL)
851                         {
852                                 logMessage("Creating server for blue AI... ");
853                                 blueNetwork = new Server(port2);
854                                 logMessage("Successful!\n");
855
856                         }
857                         else
858                         {
859                                 network = (const char*)(network+1);
860                                 logMessage("Creating client for blue AI... ");
861                                 blueNetwork = new Client(network, port1);
862                                 logMessage("Connected to address %s\n", network);
863                         }
864                         logMessage("    (Blue's responses will be received over the connection)\n");
865                         blue = new NetworkReceiver(Piece::BLUE, blueNetwork);
866                 }               
867         }
868         else
869                 blue = new AI_Controller(Piece::BLUE, bluePath, timeoutTime);
870
871         if (redNetwork != NULL)
872         {
873                 
874                 blue = new NetworkSender(Piece::BLUE,blue, redNetwork);
875                 logMessage("    (Blue's responses will be copied over the connection)\n");
876         }
877         if (blueNetwork != NULL)
878         {
879                 
880                 red = new NetworkSender(Piece::RED, red, blueNetwork);
881                 logMessage("    (Red's responses will be copied over the connection)\n");
882         }
883
884         red->FixName(); blue->FixName();
885         
886 }
887
888 string itostr(int i)
889 {
890         stringstream s;
891         s << i;
892         return s.str();
893 }
894

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