[PATCH] Allow Human_Controller to move scouts further
[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) : 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)
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) : 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)
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
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                         theBoard.Draw(toReveal);
505                 #endif //BUILD_GRAPHICS
506                 
507                 turn = Piece::RED;
508                 blue->Pause();
509                 red->Continue();
510                 if (!Board::HaltResult(result))
511                 {
512                         result = CheckVictoryAttrition();
513                 }
514                 if (Board::HaltResult(result))
515                         break;
516
517                 logMessage( "%d RED: ", turnCount);
518                 result = red->MakeMove(buffer);
519                 red->Message(buffer);
520                 blue->Message(buffer);
521                 logMessage( "%s\n", buffer.c_str());
522
523                 if (!Board::HaltResult(result))
524                 {
525                         result = CheckVictoryAttrition();
526                 }
527                 if (Board::HaltResult(result))
528                         break;
529
530                 if (stallTime >= 0)
531                         Wait(stallTime);
532                 else
533                         ReadUserCommand();
534
535                 if (blue->HumanController() && red->HumanController())
536                         toReveal = Piece::BLUE;
537                 if (printBoard)
538                 {
539                         system("clear");
540                         fprintf(stdout, "%d RED:\n", turnCount);
541                         theBoard.PrintPretty(stdout, toReveal);
542                         fprintf(stdout, "\n\n");
543                 }
544                 
545                 #ifdef BUILD_GRAPHICS
546                 if (graphicsEnabled)
547                         theBoard.Draw(toReveal);
548                 #endif //BUILD_GRAPHICS
549
550                 
551                 
552                 turn = Piece::BLUE;
553                 red->Pause();
554                 blue->Continue();
555                 if (!Board::HaltResult(result))
556                 {
557                         result = CheckVictoryAttrition();
558                 }
559                 if (Board::HaltResult(result))
560                         break;
561
562                 logMessage( "%d BLU: ", turnCount);
563                 result = blue->MakeMove(buffer);
564                 blue->Message(buffer);
565                 red->Message(buffer);
566                 logMessage( "%s\n", buffer.c_str());
567
568                 if (!Board::HaltResult(result))
569                 {
570                         result = CheckVictoryAttrition();
571                 }
572                 if (Board::HaltResult(result))
573                         break;
574
575                 if (theBoard.MobilePieces(Piece::RED) == 0)
576                         result = MovementResult::DRAW;
577
578                 if (theBoard.MobilePieces(Piece::RED) == 0)
579                 {
580                         if (theBoard.MobilePieces(Piece::BLUE) == 0)
581                                 result = MovementResult::DRAW;
582                         else
583                                 result = MovementResult::VICTORY_ATTRITION;
584                         break;                  
585                 }
586
587                 if (stallTime >= 0)
588                         Wait(stallTime);
589                 else
590                         ReadUserCommand();
591         
592                 
593
594                 ++turnCount;
595         }
596
597         if ((maxTurns >= 0 && turnCount >= maxTurns) && result == MovementResult::OK)
598         {
599                 result = MovementResult::DRAW_DEFAULT;
600         }
601
602         
603         return result;
604
605                 
606
607 }
608
609 /**
610  * Logs a message to the game's log file if it exists
611  * @param format the format string
612  * @param additional parameters - printed using va_args
613  * @returns the result of vfprintf or a negative number if the log file does not exist
614  */
615 int Game::logMessage(const char * format, ...)
616 {
617         if (log == NULL)
618                 return -666;
619                 va_list ap;
620         va_start(ap, format);
621
622         int result = vfprintf(log, format, ap);
623         va_end(ap);
624
625         return result;
626 }
627
628 /**
629  * Waits for a user command
630  * Currently ignores the command.
631  */
632 void Game::ReadUserCommand()
633 {
634         fprintf(stdout, "Waiting for user to press enter... (type QUIT to exit)\n");
635         string command("");
636         for (char c = fgetc(stdin); c != '\n' && (int)(c) != EOF; c = fgetc(stdin))
637         {
638                 command += c;
639         }
640
641         if (command == "QUIT")
642         {
643                 fprintf(stdout, "Ordered to quit... exiting...\n");
644                 exit(EXIT_SUCCESS);
645         }
646 }
647
648 MovementResult FileController::QuerySetup(const char * opponentName, std::string setup[])
649 {
650
651         char c = fgetc(file);
652         name = "";
653         while (c != ' ')
654         {
655                 name += c;
656                 c = fgetc(file);
657         }
658
659         while (fgetc(file) != '\n');
660
661         for (int y = 0; y < 4; ++y)
662         {
663                 setup[y] = "";
664                 for (int x = 0; x < Game::theGame->theBoard.Width(); ++x)
665                 {
666                         setup[y] += fgetc(file);
667                 }
668
669                 if (fgetc(file) != '\n')
670                 {
671                         return MovementResult::BAD_RESPONSE;
672                 }
673         }
674         return MovementResult::OK;
675
676         
677 }
678
679 MovementResult FileController::QueryMove(std::string & buffer)
680 {
681         //This bit is kind of hacky and terrible, and yes I am mixing C with C++
682         //Yes I should have used fstream for the whole thing and it would be much easier.
683         //Oh well.
684
685         char buf[BUFSIZ];
686
687         fgets(buf, sizeof(buf), file);
688         char * s = (char*)(buf);
689         while (*s != ':' && *s != '\0')
690                 ++s;
691         
692         //Move forward to the start of the move information
693         for (int i=0; i < 2; ++i)
694         {
695                 if (*s != '\0' && *s != '\n')
696                         ++s;
697         }
698         
699         //Unfortunately we can't just copy the whole line
700         buffer = string(s);
701         //We have to remove the movement result tokens
702         
703
704         vector<string> tokens;
705         Game::Tokenise(tokens, buffer, ' ');
706         buffer.clear();
707
708         if (tokens.size() < 1)
709                 return MovementResult::BAD_RESPONSE;
710         buffer += tokens[0];
711
712         
713         if (tokens[0] == "NO_MOVE") //tokens[0] is either the x coordinate, or "NO_MOVE"
714                 return MovementResult::OK;
715         if (tokens.size() < 2)
716                 return MovementResult::BAD_RESPONSE;
717         buffer += " ";
718         buffer += tokens[1]; //The y coordinate
719         buffer += " ";
720         buffer += tokens[2]; //The direction
721         
722         //Check for a possible multiplier. If tokens[3] is an integer it will be the multiplier, otherwise it won't be.
723         if (tokens.size() > 3 && atoi(tokens[3].c_str()) != 0)
724         {
725                 buffer += " ";
726                 buffer += tokens[3];
727         }
728         else
729         {
730                 //(tokens[3] should include a new line)
731                 //buffer += "\n";
732         }
733
734         
735
736         
737         
738         
739         return MovementResult::OK;
740 }
741
742 /**
743  * Tokenise a string
744  */
745 int Game::Tokenise(std::vector<string> & buffer, std::string & str, char split)
746 {
747         string token = "";
748         for (unsigned int x = 0; x < str.size(); ++x)
749         {
750                 if (str[x] == split && token.size() > 0)
751                 {
752                         buffer.push_back(token);
753                         token = "";
754                 }
755                 if (str[x] != split)
756                         token += str[x];
757         }
758         if (token.size() > 0)
759                 buffer.push_back(token);
760         return buffer.size();
761 }
762
763 /**
764  * Creates Controller baseds off strings. Takes into account controllers other than AI_Controller.
765  * @param redPath - Either the path to an AI_Controller compatable executable, or one of %human or %network or %network:[IP_ADDRESS]
766  * @param bluePath - Ditto
767  * Sets this->red to a controller using redPath, and this->blue to a controller using bluePath
768  * TODO: Make nicer (this function should be ~half the length)
769  */
770 void Game::MakeControllers(const char * redPath, const char * bluePath)
771 {
772         Network * redNetwork = NULL;
773         Network * blueNetwork = NULL;
774         //To allow for running two network controllers (I don't know why you would, but beside the point...) use two ports
775         static const int port1 = 4560;
776         static const int port2 = 4561;
777
778         if (redPath[0] == '@')
779         {
780                 if (strcmp(redPath, "@human") == 0)
781                         red = new Human_Controller(Piece::RED, graphicsEnabled);
782                 else
783                 {
784                         const char * network = strstr(redPath, "@network");
785                         if (network == NULL)
786                         {
787                                 red = NULL;
788                                 return;
789                         }
790                         network = strstr(network, ":");
791                 
792                         if (network == NULL)
793                         {
794                                 logMessage("Creating server for red AI... ");
795                                 redNetwork = new Server(port1);
796                                 logMessage("Successful!\n");
797
798                         }
799                         else
800                         {
801                                 network = (const char*)(network+1);
802                                 logMessage("Creating client for red AI... ");
803                                 redNetwork = new Client(network, port2);
804                                 logMessage("Connected to address %s\n", network);
805                         }
806
807                         logMessage("    (Red's responses will be received over the connection)\n");
808                         red = new NetworkReceiver(Piece::RED, redNetwork);
809                 }               
810         }
811         else
812                 red = new AI_Controller(Piece::RED, redPath, timeoutTime);
813
814         if (bluePath[0] == '@')
815         {
816                 if (strcmp(bluePath, "@human") == 0)
817                         blue = new Human_Controller(Piece::BLUE, graphicsEnabled);
818                 else
819                 {
820                         const char * network = strstr(bluePath, "@network");
821                         if (network == NULL)
822                         {
823                                 blue = NULL;
824                                 return;
825                         }
826                         network = strstr(network, ":");
827                 
828                         if (network == NULL)
829                         {
830                                 logMessage("Creating server for blue AI... ");
831                                 blueNetwork = new Server(port2);
832                                 logMessage("Successful!\n");
833
834                         }
835                         else
836                         {
837                                 network = (const char*)(network+1);
838                                 logMessage("Creating client for blue AI... ");
839                                 blueNetwork = new Client(network, port1);
840                                 logMessage("Connected to address %s\n", network);
841                         }
842                         logMessage("    (Blue's responses will be received over the connection)\n");
843                         blue = new NetworkReceiver(Piece::BLUE, blueNetwork);
844                 }               
845         }
846         else
847                 blue = new AI_Controller(Piece::BLUE, bluePath, timeoutTime);
848
849         if (redNetwork != NULL)
850         {
851                 
852                 blue = new NetworkSender(Piece::BLUE,blue, redNetwork);
853                 logMessage("    (Blue's responses will be copied over the connection)\n");
854         }
855         if (blueNetwork != NULL)
856         {
857                 
858                 red = new NetworkSender(Piece::RED, red, blueNetwork);
859                 logMessage("    (Red's responses will be copied over the connection)\n");
860         }
861         
862 }
863

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