00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "pldrack.h"
00029 #include "round.h"
00030 #include "turn.h"
00031 #include "player.h"
00032 #include "game.h"
00033 #include "game_factory.h"
00034 #include "debug.h"
00035
00036 using namespace std;
00037
00038
00039
00040
00041 #define IDENT_STRING "Eliot"
00042 #define IDENT_FORMAT_14 ""
00043 #define IDENT_FORMAT_15 "1.5"
00044
00045
00046
00047
00048
00049
00050
00051
00052 Game * Game::load(FILE *fin, const Dictionary& iDic)
00053 {
00054 char buff[4096];
00055
00056
00057 char delim[] = " \t\n\012\015|";
00058 char *token;
00059
00060
00061 if (fgets(buff, sizeof(buff), fin) == NULL)
00062 {
00063 debug("Game::load cannot load first line\n");
00064 return NULL;
00065 }
00066
00067 if ((token = strtok(buff, delim)) == NULL)
00068 {
00069 debug("Game::load first line is empty\n");
00070 return NULL;
00071 }
00072
00073
00074 if (string(token) != IDENT_STRING)
00075 {
00076 debug("Game::load IDENT_STRING %s unknown\n",token);
00077 return NULL;
00078 }
00079
00080 if ((token = strtok(NULL, delim)) == NULL)
00081 {
00082 debug("Game_io::loading file format 1.4\n");
00083 return Game::gameLoadFormat_14(fin,iDic);
00084 }
00085
00086 if (string(token) == string(IDENT_FORMAT_15))
00087 {
00088 debug("Game_io::loading file format 1.5\n");
00089 return Game::gameLoadFormat_15(fin,iDic);
00090 }
00091
00092 debug("Game::load unknown format %s\n",token);
00093 return NULL;
00094 }
00095
00096
00097 Game* Game::gameLoadFormat_14(FILE *fin, const Dictionary& iDic)
00098 {
00099 Tile tile;
00100 char buff[4096];
00101 char rack[20];
00102 char word[20];
00103 char pos [5];
00104 char delim[]=" \t\n\012\015";
00105 char *token;
00106 Game *pGame = NULL;
00107
00108 debug("Game::gameLoadFormat_14\n");
00109
00110 pGame = GameFactory::Instance()->createTraining(iDic);
00111 pGame->start();
00112
00113 while(fgets(buff,sizeof(buff),fin))
00114 {
00115 token = strtok(buff,delim);
00116 if (token != NULL)
00117 {
00118 if (strcmp(token,"total")==0)
00119 {
00120 break;
00121 }
00122
00123
00124 strncpy(rack,token,sizeof(rack));
00125 ((Training*)pGame)->setRack(RACK_MANUAL,false,string(rack));
00126 debug("%s ",rack);
00127
00128
00129 token = strtok(NULL,delim);
00130 if (!token || strcmp(token,"total")==0)
00131 {
00132 break;
00133 }
00134
00135 strncpy(word,token,sizeof(word));
00136 debug("\t%s ",word);
00137
00138
00139 if ((token = strtok(NULL,delim)) == NULL)
00140 break;
00141
00142
00143 if (token[0]=='*')
00144 {
00145 debug("%s\t",token);
00146 if ((token = strtok(NULL,delim)) == NULL)
00147 break;
00148 }
00149
00150
00151 if ((token = strtok(NULL,delim)) == NULL)
00152 break;
00153
00154 debug("(%s ",token);
00155 strncpy(pos,token,sizeof(pos));
00156
00157
00158 if ((token = strtok(NULL,delim)) == NULL)
00159 break;
00160
00161 debug("%s)",token);
00162 strncat(pos,token,sizeof(pos));
00163 debug("%s\n",pos);
00164
00165 debug(" play %s %s\n",pos, word);
00166 pGame->play(string(pos),string(word));
00167 }
00168 }
00169 return pGame;
00170 }
00171
00172
00173 Game* Game::gameLoadFormat_15(FILE *fin, const Dictionary& iDic)
00174 {
00175 Game *pGame = NULL;
00176 #if 0
00177 char buff[4096];
00178 int num;
00179 char rack[20];
00180 char word[20];
00181 char ref[4];
00182 int pts;
00183 int player;
00184 char *pos;
00185 Tile tile;
00186
00187 while (fgets(buff, sizeof(buff), fin))
00188 {
00189
00190 pos = strstr(buff, "Game type: ");
00191 if (pos != NULL)
00192 {
00193
00194 if (pGame != NULL)
00195 {
00196 delete pGame;
00197 return NULL;
00198 }
00199
00200 if (strstr(buff, "Training"))
00201 pGame = GameFactory::Instance()->createTraining(iDic);
00202 else if (strstr(buff, "Free game"))
00203 pGame = GameFactory::Instance()->createFreeGame(iDic);
00204 else if (strstr(buff, "Duplicate"))
00205 pGame = GameFactory::Instance()->createDuplicate(iDic);
00206 else
00207 return NULL;
00208
00209 continue;
00210 }
00211
00212
00213 pos = strstr(buff, "Player ");
00214 if (pos != NULL && pGame != NULL)
00215 {
00216 int nb = 0;
00217 char type[20];
00218 if (sscanf(pos, "Player %d: %19s", &nb, type) > 1)
00219 {
00220 if (pGame->getMode() != kTRAINING)
00221 {
00222 if (string(type) == "Human")
00223 pGame->addHumanPlayer();
00224 else if (string(type) == "Computer")
00225 pGame->addAIPlayer();
00226 else
00227 ;
00228 }
00229 }
00230
00231 continue;
00232 }
00233
00234
00235 pos = strstr(buff, "Rack ");
00236 if (pos != NULL && pGame != NULL)
00237 {
00238 int nb = 0;
00239 char letters[20];
00240 if (sscanf(pos, "Rack %d: %19s", &nb, letters) > 1)
00241 {
00242
00243 PlayedRack pldrack;
00244 char *r = letters;
00245 if (strchr(r, '+'))
00246 {
00247 while (*r != '+')
00248 {
00249 pldrack.addOld(Tile(*r));
00250 r++;
00251 }
00252 r++;
00253 }
00254 while (*r)
00255 {
00256 pldrack.addNew(Tile(*r));
00257 r++;
00258 }
00259
00260
00261 pGame->m_players[nb]->setCurrentRack(pldrack);
00262 }
00263
00264 continue;
00265 }
00266
00267
00268 if (strstr(buff, "==") != NULL ||
00269 strstr(buff, "| PTS | P |") != NULL)
00270 {
00271 continue;
00272 }
00273
00274 if (string(buff) != "\n" && pGame != NULL)
00275 {
00276 char bonus = 0;
00277 int res = sscanf(buff, " %2d | %8s | %s | %3s | %3d | %1d | %c",
00278 &num, rack, word, ref, &pts, &player, &bonus);
00279 if (res < 6)
00280 continue;
00281
00282
00283
00284 if (pts < 0)
00285 continue;
00286 if (player < 0 || player > pGame->getNPlayers())
00287 continue;
00288 if (bonus && bonus != '*')
00289 continue;
00290
00291
00292 PlayedRack pldrack;
00293 char *r = rack;
00294 if (strchr(r, '+'))
00295 {
00296 while (*r != '+')
00297 {
00298 pldrack.addOld(Tile(*r));
00299 r++;
00300 }
00301 r++;
00302 }
00303
00304 while (*r)
00305 {
00306 pldrack.addNew(Tile(*r));
00307 r++;
00308 }
00309
00310
00311 Round round;
00312 round.setPoints(pts);
00313 if (bonus == '*')
00314 round.setBonus(1);
00315
00316 if (isalpha(ref[0]))
00317 {
00318
00319 round.setDir(HORIZONTAL);
00320 round.setRow(ref[0] - 'A' + 1);
00321 round.setCol(atoi(ref + 1));
00322
00323 for (unsigned int i = 0; i < strlen(word); i++)
00324 {
00325 tile = Tile(word[i]);
00326
00327 if (!pGame->m_board.getTile(round.getRow(), round.getCol() + i).isEmpty())
00328 {
00329 round.addRightFromBoard(tile);
00330 }
00331 else
00332 {
00333 round.addRightFromRack(tile, islower(word[i]));
00334 pGame->m_bag.takeTile((islower(word[i])) ? Tile::Joker() : tile);
00335 }
00336 }
00337 }
00338 else
00339 {
00340
00341 round.setDir(Coord::VERTICAL);
00342 round.setRow(ref[strlen(ref) - 1] - 'A' + 1);
00343 round.setCol(atoi(ref));
00344
00345 for (unsigned int i = 0; i < strlen(word); i++)
00346 {
00347 tile = Tile(word[i]);
00348
00349 if (!pGame->m_board.getTile(round.getRow() + i, round.getCol()).isEmpty())
00350 {
00351 round.addRightFromBoard(tile);
00352 }
00353 else
00354 {
00355 round.addRightFromRack(tile, islower(word[i]));
00356 pGame->m_bag.takeTile((islower(word[i])) ? Tile::Joker() : tile);
00357 }
00358 }
00359 }
00360
00361 pGame->m_currPlayer = player;
00362
00363 pGame->m_players[player]->setCurrentRack(pldrack);
00364
00365 pGame->m_players[player]->playRound(num - 1, round);
00366
00367 pGame->helperPlayRound(round);
00368 }
00369 }
00370
00371
00372 if (pGame)
00373 {
00374
00375
00376 for (int i = 0; i < pGame->getNPlayers(); i++)
00377 {
00378 if (pGame->m_players[i]->isHuman())
00379 {
00380 pGame->m_currPlayer = i;
00381 break;
00382 }
00383 }
00384 }
00385 #endif
00386 return pGame;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395 void Game::save(ostream &out, game_file_format format) const
00396 {
00397 if (getMode() == kTRAINING && format == FILE_FORMAT_STANDARD)
00398 {
00399 gameSaveFormat_14(out);
00400 }
00401 else
00402 {
00403 gameSaveFormat_15(out);
00404 }
00405 }
00406
00407
00408 void Game::gameSaveFormat_14(ostream &out) const
00409 {
00410 int i;
00411 char line[100];
00412 const char decal[]=" ";
00413 out << IDENT_STRING << endl << endl;
00414
00415 for(i = 0; i < m_history.getSize(); i++)
00416 {
00417 const Turn& turn = m_history.getTurn(i);
00418 string rack = turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA);
00419 string word = turn.getRound().getWord();
00420 string coord = turn.getRound().getCoord().toString(Coord::COORD_MODE_LONG);
00421
00422
00423 sprintf(line,"%s%s%s%s%c%4d %s",
00424 rack.c_str(),
00425 string(12 - rack.size(), ' ').c_str(),
00426 word.c_str(),
00427 string(16 - word.size(), ' ').c_str(),
00428 turn.getRound().getBonus() ? '*' : ' ',
00429 turn.getRound().getPoints(),
00430 coord.c_str()
00431 );
00432
00433 out << decal << line << endl;
00434 }
00435
00436 out << endl;
00437 out << decal << "total" << string(24,' ');
00438 sprintf(line,"%4d", getCurrentPlayer().getPoints());
00439 out << line << endl;
00440 }
00441
00442
00443 void Game::gameSaveFormat_15(ostream &out) const
00444 {
00445 const string decal = " ";
00446
00447 out << IDENT_STRING << " " << IDENT_FORMAT_15 << endl << endl;
00448
00449 out << "Game type: " << getModeAsString() << endl;
00450
00451 for (int i = 0; i < getNPlayers(); i++)
00452 {
00453 out << "Player " << i << ": ";
00454 if (m_players[i]->isHuman())
00455 out << "Human" << endl;
00456 else
00457 out << "Computer" << endl;
00458 }
00459 out << endl;
00460
00461
00462 char line[100];
00463 out << decal << " N | RACK | SOLUTION | REF | PTS | P | BONUS" << endl;
00464 out << decal << "===|==========|=================|=====|=====|===|======" << endl;
00465
00466
00467 for (int i = 0; i < m_history.getSize(); i++)
00468 {
00469 const Turn& turn = m_history.getTurn(i);
00470 string word = turn.getRound().getWord();
00471 string coord = turn.getRound().getCoord().toString();
00472 sprintf(line, "%2d | %8s | %s%s | %3s | %3d | %1d | %c",
00473 i + 1,
00474 turn.getPlayedRack().toString().c_str(),
00475 word.c_str(),
00476 string(15 - word.size(), ' ').c_str(),
00477 coord.c_str(),
00478 turn.getRound().getPoints(),
00479 turn.getPlayer(),
00480 turn.getRound().getBonus() ? '*' : ' ');
00481
00482 out << decal << line << endl;
00483 }
00484
00485
00486
00487
00488
00489 out << endl;
00490 for (int i = 0; i < getNPlayers(); i++)
00491 {
00492 string rack = m_players[i]->getCurrentRack().toString();
00493 out << "Rack " << i << ": " << rack << endl;
00494 }
00495 }
00496
00497
00498
00499
00500
00501
00502