00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "config.h"
00021 #if ENABLE_NLS
00022 # include <libintl.h>
00023 # define _(String) gettext(String)
00024 #else
00025 # define _(String) String
00026 #endif
00027
00028 #include <ctype.h>
00029 #include <fstream>
00030
00031 #include "ncurses.h"
00032 #include "dic.h"
00033 #include "dic_search.h"
00034 #include "game_factory.h"
00035 #include "training.h"
00036 #include "duplicate.h"
00037 #include "freegame.h"
00038 #include "player.h"
00039
00040 using namespace std;
00041
00042
00043 CursesIntf::CursesIntf(WINDOW *win, Game& iGame)
00044 : m_win(win), m_game(&iGame), m_state(DEFAULT), m_dying(false),
00045 m_boxStart(0), m_boxLines(0), m_boxLinesData(0), m_boxY(0),
00046 m_showDots(false)
00047 {
00048 }
00049
00050
00051 CursesIntf::~CursesIntf()
00052 {
00053 GameFactory::Instance()->releaseGame(*m_game);
00054 }
00055
00056
00057 void CursesIntf::drawBox(WINDOW *win, int y, int x, int h, int w,
00058 const string& iTitle)
00059 {
00060 if (w > 3 && h > 2)
00061 {
00062 int i_len = iTitle.size();
00063
00064 if (i_len > w - 2) i_len = w - 2;
00065
00066 mvwaddch(win, y, x, ACS_ULCORNER);
00067 mvwhline(win, y, x+1, ACS_HLINE, ( w-i_len-2)/2);
00068 mvwprintw(win,y, x+1+(w-i_len-2)/2, "%s", iTitle.c_str());
00069 mvwhline(win, y, x+(w-i_len)/2+i_len,
00070 ACS_HLINE, w - 1 - ((w-i_len)/2+i_len));
00071 mvwaddch(win, y, x+w-1,ACS_URCORNER);
00072
00073 mvwvline(win, y+1, x, ACS_VLINE, h-2);
00074 mvwvline(win, y+1, x+w-1, ACS_VLINE, h-2);
00075
00076 mvwaddch(win, y+h-1, x, ACS_LLCORNER);
00077 mvwhline(win, y+h-1, x+1, ACS_HLINE, w - 2);
00078 mvwaddch(win, y+h-1, x+w-1, ACS_LRCORNER);
00079 }
00080 }
00081
00082
00083 void CursesIntf::clearRect(WINDOW *win, int y, int x, int h, int w)
00084 {
00085 for (int i = 0; i < h; i++)
00086 {
00087 mvwhline(win, y + i, x, ' ', w);
00088 }
00089 }
00090
00091
00092 void CursesIntf::boxPrint(WINDOW *win, int y, int x, const char *fmt, ...)
00093 {
00094 if (y < m_boxStart || y - m_boxStart >= m_boxLines)
00095 return;
00096
00097 va_list vl_args;
00098 char *buf = NULL;
00099 va_start(vl_args, fmt);
00100 vasprintf(&buf, fmt, vl_args);
00101 va_end(vl_args);
00102
00103 if (buf == NULL)
00104 {
00105 return;
00106 }
00107 mvwprintw(win, m_boxY + y - m_boxStart, x, "%s", buf);
00108 }
00109
00110
00111 void CursesIntf::drawStatus(WINDOW *win, int y, int x,
00112 const string& iMessage, bool error)
00113 {
00114 if (error)
00115 wattron(win, COLOR_PAIR(COLOR_YELLOW));
00116 mvwprintw(win, y, x, iMessage.c_str());
00117 whline(win, ' ', COLS - x - 1 - iMessage.size());
00118 if (error)
00119 wattron(win, COLOR_PAIR(COLOR_WHITE));
00120 }
00121
00122
00123 void CursesIntf::drawBoard(WINDOW *win, int y, int x) const
00124 {
00125
00126 drawBox(win, y + 1, x + 3, 17, 47, "");
00127
00128
00129 for (int i = 0; i < 15; i++)
00130 {
00131 mvwaddch(win, y + i + 2, x + 1, 'A' + i);
00132 mvwaddch(win, y + i + 2, x + 51, 'A' + i);
00133 mvwprintw(win, y, x + 3 * i + 5, "%d", i + 1);
00134 mvwprintw(win, y + 18, x + 3 * i + 5, "%d", i + 1);
00135 }
00136
00137
00138 for (int row = 1; row < 16; row++)
00139 {
00140 for (int col = 1; col < 16; col++)
00141 {
00142
00143 int wm = m_game->getBoard().getWordMultiplier(row, col);
00144 int lm = m_game->getBoard().getLetterMultiplier(row, col);
00145 if (wm == 3)
00146 wattron(win, COLOR_PAIR(COLOR_RED));
00147 else if (wm == 2)
00148 wattron(win, COLOR_PAIR(COLOR_MAGENTA));
00149 else if (lm == 3)
00150 wattron(win, COLOR_PAIR(COLOR_BLUE));
00151 else if (lm == 2)
00152 wattron(win, COLOR_PAIR(COLOR_CYAN));
00153 else
00154 wattron(win, COLOR_PAIR(COLOR_WHITE));
00155
00156
00157 mvwprintw(win, y + row + 1, x + 3 * col + 1, " ");
00158
00159
00160 char c = m_game->getBoard().getChar(row, col);
00161 if (c)
00162 {
00163 if (islower(c))
00164 mvwaddch(win, y + row + 1, x + 3 * col + 2,
00165 c | A_BOLD | COLOR_PAIR(COLOR_GREEN));
00166 else
00167 mvwaddch(win, y + row + 1, x + 3 * col + 2, c);
00168 }
00169 else
00170 {
00171
00172 if (m_showDots)
00173 mvwaddch(win, y + row + 1, x + 3 * col + 2, '.');
00174 }
00175 }
00176 }
00177 wattron(win, COLOR_PAIR(COLOR_WHITE));
00178 }
00179
00180
00181 void CursesIntf::drawScoresRacks(WINDOW *win, int y, int x) const
00182 {
00183 drawBox(win, y, x, m_game->getNPlayers() + 2, 25, _(" Scores "));
00184 for (int i = 0; i < m_game->getNPlayers(); i++)
00185 {
00186 if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
00187 attron(A_BOLD);
00188 mvwprintw(win, y + i + 1, x + 2,
00189 _("Player %d: %d"), i, m_game->getPlayer(i).getPoints());
00190 if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
00191 attroff(A_BOLD);
00192 }
00193
00194
00195 int yOff = m_game->getNPlayers() + 3;
00196
00197 drawBox(win, y + yOff, x, m_game->getNPlayers() + 2, 25, _(" Racks "));
00198 for (int i = 0; i < m_game->getNPlayers(); i++)
00199 {
00200 if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
00201 attron(A_BOLD);
00202 mvwprintw(win, y + yOff + i + 1, x + 2,
00203 _("Player %d: %s"), i, m_game->getPlayerRack(i).c_str());
00204 if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
00205 attroff(A_BOLD);
00206
00207 whline(win, ' ', 7 - m_game->getPlayerRack(i).size());
00208 }
00209
00210
00211 if (m_game->getMode() == Game::kTRAINING &&
00212 static_cast<Training*>(m_game)->getHistory().getSize())
00213 {
00214 mvwprintw(win, y + 2*yOff - 1, x + 2, _("Search complete"));
00215 }
00216 else
00217 mvwhline(win, y + 2*yOff - 1, x + 2, ' ', strlen(_("Search complete")));
00218 }
00219
00220
00221 void CursesIntf::drawResults(WINDOW *win, int y, int x)
00222 {
00223 if (m_game->getMode() != Game::kTRAINING)
00224 return;
00225 Training *tr_game = static_cast<Training*>(m_game);
00226
00227 int h = 17;
00228 drawBox(win, y, x, h, 25, _(" Search results "));
00229 m_boxY = y + 1;
00230 m_boxLines = h - 2;
00231 m_boxLinesData = tr_game->getHistory().getSize();
00232
00233 int i;
00234 const Results& res = tr_game->getResults();
00235 for (i = m_boxStart; i < res.size() &&
00236 i < m_boxStart + m_boxLines; i++)
00237 {
00238 const Round &r = res.get(i);
00239 string coord = r.getCoord().toString();
00240 boxPrint(win, i, x + 1, "%3d %s%s %3s",
00241 r.getPoints(),
00242 r.getWord().c_str(),
00243 string(h - 3 - r.getWordLen(), ' ').c_str(),
00244 coord.c_str());
00245 }
00246
00247 for (; i < m_boxStart + m_boxLines; i++)
00248 {
00249 boxPrint(win, i, x + 1, string(23, ' ').c_str());
00250 }
00251 }
00252
00253
00254 void CursesIntf::drawHistory(WINDOW *win, int y, int x)
00255 {
00256
00257 clear();
00258
00259 drawBox(win, y, x, LINES - y, COLS - x, _(" History of the game "));
00260 m_boxY = y + 1;
00261 m_boxLines = LINES - y - 2;
00262 m_boxLinesData = m_game->getHistory().getSize();
00263
00264
00265 boxPrint(win, m_boxStart, x + 2,
00266 _(" N | RACK | SOLUTION | REF | PTS | P | BONUS"));
00267 mvwhline(win, y + 2, x + 2, ACS_HLINE, 55);
00268
00269 int i;
00270 for (i = m_boxStart + 0; i < m_game->getHistory().getSize() &&
00271 i < m_boxStart + m_boxLines; i++)
00272 {
00273 const Turn& t = m_game->getHistory().getTurn(i);
00274 const Round& r = t.getRound();
00275 string word = r.getWord();
00276 string coord = r.getCoord().toString();
00277 boxPrint(win, i + 2, x + 2,
00278 "%2d %8s %s%s %3s %3d %1d %c",
00279 i + 1, t.getPlayedRack().toString().c_str(), word.c_str(),
00280 string(15 - word.size(), ' ').c_str(),
00281 coord.c_str(), r.getPoints(),
00282 t.getPlayer(), r.getBonus() ? '*' : ' ');
00283 }
00284 mvwvline(win, y + 1, x + 5, ACS_VLINE, min(i + 2 - m_boxStart, m_boxLines));
00285 mvwvline(win, y + 1, x + 16, ACS_VLINE, min(i + 2 - m_boxStart, m_boxLines));
00286 mvwvline(win, y + 1, x + 34, ACS_VLINE, min(i + 2 - m_boxStart, m_boxLines));
00287 mvwvline(win, y + 1, x + 40, ACS_VLINE, min(i + 2 - m_boxStart, m_boxLines));
00288 mvwvline(win, y + 1, x + 46, ACS_VLINE, min(i + 2 - m_boxStart, m_boxLines));
00289 mvwvline(win, y + 1, x + 50, ACS_VLINE, min(i + 2 - m_boxStart, m_boxLines));
00290 }
00291
00292
00293 void CursesIntf::drawHelp(WINDOW *win, int y, int x)
00294 {
00295
00296 clear();
00297
00298 drawBox(win, y, x, LINES - y, COLS - x, _(" Help "));
00299 m_boxY = y + 1;
00300 m_boxLines = LINES - y - 2;
00301
00302 int n = 0;
00303 boxPrint(win, n++, x + 2, _("[Global]"));
00304 boxPrint(win, n++, x + 2, _(" h, H, ? Show/hide help box"));
00305 boxPrint(win, n++, x + 2, _(" y, Y Show/hide history of the game"));
00306 boxPrint(win, n++, x + 2, _(" e, E Show/hide dots on empty squares of the board"));
00307 boxPrint(win, n++, x + 2, _(" d, D Check the existence of a word in the dictionary"));
00308 boxPrint(win, n++, x + 2, _(" j, J Play a word"));
00309 boxPrint(win, n++, x + 2, _(" s, S Save the game"));
00310 boxPrint(win, n++, x + 2, _(" l, L Load a game"));
00311 boxPrint(win, n++, x + 2, _(" q, Q Quit"));
00312 boxPrint(win, n++, x + 2, "");
00313
00314 boxPrint(win, n++, x + 2, _("[Training mode]"));
00315 boxPrint(win, n++, x + 2, _(" * Take a random rack"));
00316 boxPrint(win, n++, x + 2, _(" + Complete the current rack randomly"));
00317 boxPrint(win, n++, x + 2, _(" t, T Set the rack manually"));
00318 boxPrint(win, n++, x + 2, _(" c, C Compute all the possible words"));
00319 boxPrint(win, n++, x + 2, _(" r, R Show/hide search results"));
00320 boxPrint(win, n++, x + 2, "");
00321
00322 boxPrint(win, n++, x + 2, _("[Duplicate mode]"));
00323 boxPrint(win, n++, x + 2, _(" n, N Switch to the next human player"));
00324 boxPrint(win, n++, x + 2, "");
00325
00326 boxPrint(win, n++, x + 2, _("[Free game mode]"));
00327 boxPrint(win, n++, x + 2, _(" p, P Pass your turn (with or without changing letters)"));
00328 boxPrint(win, n++, x + 2, "");
00329
00330 boxPrint(win, n++, x + 2, _("[Miscellaneous]"));
00331 boxPrint(win, n++, x + 2, _(" <up>, <down> Navigate in a box line by line"));
00332 boxPrint(win, n++, x + 2, _(" <pgup>, <pgdown> Navigate in a box page by page"));
00333 boxPrint(win, n++, x + 2, _(" Ctrl-l Refresh the screen"));
00334
00335 m_boxLinesData = n;
00336 }
00337
00338
00339 void CursesIntf::playWord(WINDOW *win, int y, int x)
00340 {
00341 drawBox(win, y, x, 4, 32, _(" Play a word "));
00342 mvwprintw(win, y + 1, x + 2, _("Played word:"));
00343 mvwprintw(win, y + 2, x + 2, _("Coordinates:"));
00344 wrefresh(win);
00345
00346
00347
00348
00349
00350 int l1 = strlen(_("Played word:"));
00351 int l2 = strlen(_("Coordinates:"));
00352 int xOff;
00353 if (l1 > l2)
00354 xOff = l1 + 3;
00355 else
00356 xOff = l2 + 3;
00357
00358 string word, coord;
00359 if (readString(win, y + 1, x + xOff, 15, word) &&
00360 readString(win, y + 2, x + xOff, 3, coord))
00361 {
00362 int res = m_game->play(coord, word);
00363 if (res)
00364 {
00365 drawStatus(win, LINES - 1, 0, _("Incorrect or misplaced word"));
00366 }
00367 }
00368 m_state = DEFAULT;
00369 clearRect(win, y, x, 4, 32);
00370 }
00371
00372
00373 void CursesIntf::checkWord(WINDOW *win, int y, int x)
00374 {
00375 drawBox(win, y, x, 4, 32, _(" Dictionary "));
00376 mvwprintw(win, y + 1, x + 2, _("Enter the word to check:"));
00377 wrefresh(win);
00378
00379 string word;
00380 if (readString(win, y + 2, x + 2, 15, word))
00381 {
00382 int res = Dic_search_word(m_game->getDic(), word.c_str());
00383 char s[100];
00384 if (res)
00385 snprintf(s, 100, _("The word '%s' exists"), word.c_str());
00386 else
00387 snprintf(s, 100, _("The word '%s' does not exist"), word.c_str());
00388 drawStatus(win, LINES - 1, 0, s);
00389 }
00390 m_state = DEFAULT;
00391 clearRect(win, y, x, 4, 32);
00392 }
00393
00394
00395 void CursesIntf::saveGame(WINDOW *win, int y, int x)
00396 {
00397 drawBox(win, y, x, 4, 32, _(" Save the game "));
00398 mvwprintw(win, y + 1, x + 2, _("Enter the file name:"));
00399 wrefresh(win);
00400
00401 string filename;
00402 if (readString(win, y + 2, x + 2, 28, filename, kFILENAME))
00403 {
00404 ofstream fout(filename.c_str());
00405 char s[100];
00406 if (fout.rdstate() == ios::failbit)
00407 {
00408 snprintf(s, 100, _("Cannot open file %s for writing"),
00409 filename.c_str());
00410 }
00411 else
00412 {
00413 m_game->save(fout);
00414 fout.close();
00415 snprintf(s, 100, _("Game saved in %s"), filename.c_str());
00416 }
00417 drawStatus(win, LINES - 1, 0, s);
00418 }
00419 m_state = DEFAULT;
00420 clearRect(win, y, x, 4, 32);
00421 }
00422
00423
00424 void CursesIntf::loadGame(WINDOW *win, int y, int x)
00425 {
00426 drawBox(win, y, x, 4, 32, _(" Load a game "));
00427 mvwprintw(win, y + 1, x + 2, _("Enter the file name:"));
00428 wrefresh(win);
00429
00430 string filename;
00431 if (readString(win, y + 2, x + 2, 28, filename, kFILENAME))
00432 {
00433 char s[100];
00434 FILE *fin;
00435 if ((fin = fopen(filename.c_str(), "r")) == NULL)
00436 {
00437 snprintf(s, 100, _("Cannot open file %s for reading"),
00438 filename.c_str());
00439 }
00440 else
00441 {
00442 Game *loaded = Game::load(fin, m_game->getDic());
00443 if (loaded == NULL)
00444 {
00445 snprintf(s, 100, _("Invalid saved game"));
00446 }
00447 else
00448 {
00449 snprintf(s, 100, _("Game loaded"));
00450 GameFactory::Instance()->releaseGame(*m_game);
00451 m_game = loaded;
00452 }
00453 fclose(fin);
00454 }
00455 drawStatus(win, LINES - 1, 0, s);
00456 }
00457 m_state = DEFAULT;
00458 clearRect(win, y, x, 4, 32);
00459 }
00460
00461
00462 void CursesIntf::passTurn(WINDOW *win, int y, int x, FreeGame &iGame)
00463 {
00464 drawBox(win, y, x, 4, 32, _(" Pass your turn "));
00465 mvwprintw(win, y + 1, x + 2, _("Enter the letters to change:"));
00466 wrefresh(win);
00467
00468 string letters;
00469 if (readString(win, y + 2, x + 2, 7, letters))
00470 {
00471 int res = iGame.pass(letters, m_game->currPlayer());
00472 if (res)
00473 {
00474 drawStatus(win, LINES - 1, 0, _("Cannot pass the turn"));
00475 }
00476 }
00477 m_state = DEFAULT;
00478 clearRect(win, y, x, 4, 32);
00479 }
00480
00481
00482 void CursesIntf::setRack(WINDOW *win, int y, int x, Training &iGame)
00483 {
00484 drawBox(win, y, x, 4, 32, _(" Set rack "));
00485 mvwprintw(win, y + 1, x + 2, _("Enter the new letters:"));
00486 wrefresh(win);
00487
00488 string letters;
00489 if (readString(win, y + 2, x + 2, 7, letters, kJOKER))
00490 {
00491 iGame.setRackManual(false, letters);
00492 }
00493 m_state = DEFAULT;
00494 clearRect(win, y, x, 4, 32);
00495 }
00496
00497
00498 bool CursesIntf::readString(WINDOW *win, int y, int x, int n, string &oString,
00499 unsigned int flag)
00500 {
00501 int c;
00502 wmove(win, y, x);
00503 curs_set(1);
00504 while ((c = getch()) != 0)
00505 {
00506 if (c == 0x1b )
00507 {
00508 curs_set(0);
00509 return false;
00510 }
00511 else if (c == KEY_ENTER || c == 0xD)
00512 {
00513 curs_set(0);
00514 return true;
00515 }
00516 else if (c == 0x0c)
00517 {
00518
00519 redraw(win);
00520 wmove(win, y, x);
00521 }
00522 else if (c == KEY_BACKSPACE && oString.size() > 0)
00523 {
00524 x--;
00525 mvwprintw(win, y, x, " ");
00526 wmove(win, y, x);
00527 oString.erase(oString.size() - 1);
00528 }
00529 else if (isalnum(c) && oString.size() < (unsigned int)n)
00530 {
00531 mvwprintw(win, y, x, "%c", c);
00532 x++;
00533 oString += (char)c;
00534 }
00535 else
00536 {
00537 if (flag & kJOKER && c == '?')
00538 {
00539 mvwprintw(win, y, x, "%c", c);
00540 x++;
00541 oString += (char)c;
00542 }
00543 if (flag & kFILENAME)
00544 {
00545 if (c == '/' || c == '.' || c == '-' || c == '_' || c == ' ')
00546 {
00547 mvwprintw(win, y, x, "%c", c);
00548 x++;
00549 oString += (char)c;
00550 }
00551 }
00552 }
00553
00554
00555 }
00556 curs_set(0);
00557 return 0;
00558 }
00559
00560
00561 int CursesIntf::handleKeyForGame(int iKey, Training &iGame)
00562 {
00563 switch (iKey)
00564 {
00565 case '*':
00566 iGame.setRackRandom(0, false, Game::RACK_ALL);
00567 return 1;
00568
00569 case '+':
00570 iGame.setRackRandom(0, false, Game::RACK_NEW);
00571 return 1;
00572
00573 case 't':
00574 case 'T':
00575 setRack(m_win, 22, 10, iGame);
00576 return 1;
00577
00578 case 'c':
00579 case 'C':
00580 iGame.search();
00581 return 1;
00582
00583 default:
00584 return 2;
00585 }
00586 }
00587
00588
00589 int CursesIntf::handleKeyForGame(int iKey, Duplicate &iGame)
00590 {
00591 switch (iKey)
00592 {
00593 case 'n':
00594 case 'N':
00595 iGame.nextHumanPlayer();
00596 return 1;
00597
00598 default:
00599 return 2;
00600 }
00601 }
00602
00603
00604 int CursesIntf::handleKeyForGame(int iKey, FreeGame &iGame)
00605 {
00606 switch (iKey)
00607 {
00608 case 'p':
00609 case 'P':
00610 passTurn(m_win, 22, 10, iGame);
00611 return 1;
00612
00613 default:
00614 return 2;
00615 }
00616 }
00617
00618
00619 int CursesIntf::handleKey(int iKey)
00620 {
00621 if (m_state == DEFAULT)
00622 {
00623 int res;
00624 if (m_game->getMode() == Game::kTRAINING)
00625 {
00626 res = handleKeyForGame(iKey, (Training&)*m_game);
00627 }
00628 else if (m_game->getMode() == Game::kDUPLICATE)
00629 {
00630 res = handleKeyForGame(iKey, (Duplicate&)*m_game);
00631 }
00632 else
00633 {
00634 res = handleKeyForGame(iKey, (FreeGame&)*m_game);
00635 }
00636
00637 if (res != 2)
00638 return res;
00639 }
00640 else
00641 {
00642 switch (iKey)
00643 {
00644 case KEY_HOME:
00645 if (m_boxLinesData <= m_boxLines && m_boxStart > 0)
00646 return 0;
00647 m_boxStart = 0;
00648 return 1;
00649 case KEY_END:
00650 if (m_boxLinesData <= m_boxLines &&
00651 m_boxStart < m_boxLinesData - 1)
00652 return 0;
00653 m_boxStart = m_boxLinesData - 1;
00654 return 1;
00655 case KEY_UP:
00656 if (m_boxLinesData <= m_boxLines || m_boxStart <= 0)
00657 return 0;
00658 m_boxStart--;
00659 return 1;
00660 case KEY_DOWN:
00661 if (m_boxLinesData <= m_boxLines ||
00662 m_boxStart >= m_boxLinesData - 1)
00663 return 0;
00664 m_boxStart++;
00665 return 1;
00666 case KEY_PPAGE:
00667 if (m_boxLinesData <= m_boxLines)
00668 return 0;
00669 m_boxStart -= m_boxLines;
00670 if (m_boxStart < 0)
00671 m_boxStart = 0;
00672 return 1;
00673 case KEY_NPAGE:
00674 if (m_boxLinesData <= m_boxLines)
00675 return 0;
00676 m_boxStart += m_boxLines;
00677 if (m_boxStart > m_boxLinesData - 1)
00678 m_boxStart = m_boxLinesData - 1;
00679 return 1;
00680 }
00681 }
00682
00683 switch (iKey)
00684 {
00685
00686 case 'h':
00687 case 'H':
00688 case '?':
00689 if (m_state == HELP)
00690 m_state = DEFAULT;
00691 else
00692 m_state = HELP;
00693 m_boxStart = 0;
00694 clear();
00695 return 1;
00696
00697
00698 case 'y':
00699 case 'Y':
00700 if (m_state == HISTORY)
00701 m_state = DEFAULT;
00702 else
00703 m_state = HISTORY;
00704 m_boxStart = 0;
00705 clear();
00706 return 1;
00707
00708
00709 case 'r':
00710 case 'R':
00711 if (m_game->getMode() != Game::kTRAINING)
00712 return 0;
00713 if (m_state == RESULTS)
00714 m_state = DEFAULT;
00715 else
00716 m_state = RESULTS;
00717 m_boxStart = 0;
00718 clear();
00719 return 1;
00720
00721
00722 case 'e':
00723 case 'E':
00724 m_showDots = !m_showDots;
00725 return 1;
00726
00727
00728 case 'd':
00729 case 'D':
00730 if (m_state != DEFAULT)
00731 return 0;
00732 checkWord(m_win, 22, 10);
00733 return 1;
00734
00735
00736 case 'j':
00737 case 'J':
00738 if (m_state != DEFAULT)
00739 return 0;
00740 playWord(m_win, 22, 10);
00741 return 1;
00742
00743
00744 case 0x0c:
00745 clear();
00746 return 1;
00747
00748 case 'l':
00749 case 'L':
00750 if (m_state != DEFAULT)
00751 return 0;
00752 loadGame(m_win, 22, 10);
00753 return 1;
00754
00755 case 's':
00756 case 'S':
00757 if (m_state != DEFAULT)
00758 return 0;
00759 saveGame(m_win, 22, 10);
00760 return 1;
00761
00762
00763 case 'q':
00764 case 'Q':
00765 case 0x1b:
00766 m_dying = true;
00767 return 0;
00768
00769 default:
00770 return 0;
00771 }
00772 }
00773
00774
00775 void CursesIntf::redraw(WINDOW *win)
00776 {
00777 if (m_state == DEFAULT)
00778 {
00779 drawScoresRacks(win, 3, 54);
00780 drawBoard(win, 2, 0);
00781 }
00782 else if (m_state == RESULTS)
00783 {
00784 drawResults(win, 3, 54);
00785 drawBoard(win, 2, 0);
00786 }
00787 else if (m_state == HELP)
00788 {
00789 drawHelp(win, 1, 0);
00790 }
00791 else if (m_state == HISTORY)
00792 {
00793 drawHistory(win, 1, 0);
00794 }
00795
00796
00797 attron(A_REVERSE);
00798 string mode;
00799 if (m_game->getMode() == Game::kTRAINING)
00800 mode = _("Training mode");
00801 else if (m_game->getMode() == Game::kFREEGAME)
00802 mode = _("Free game mode");
00803 else if (m_game->getMode() == Game::kDUPLICATE)
00804 mode = _("Duplicate mode");
00805 string variant = "";
00806 if (m_game->getVariant() == Game::kJOKER)
00807 variant = string(" - ") + _("Joker game");
00808 string title = "Eliot (" + mode + variant + ") " + _("[h for help]");
00809 mvwprintw(win, 0, 0, title.c_str());
00810 whline(win, ' ', COLS - title.size());
00811 attroff(A_REVERSE);
00812
00813 wrefresh(win);
00814 }
00815
00816
00817 int main(int argc, char ** argv)
00818 {
00819 #ifdef HAVE_SETLOCALE
00820
00821 setlocale(LC_ALL, "");
00822 #endif
00823
00824 #if ENABLE_NLS
00825
00826 bindtextdomain(PACKAGE, LOCALEDIR);
00827 textdomain(PACKAGE);
00828 #endif
00829
00830 srand(time(NULL));
00831
00832 Game *game = GameFactory::Instance()->createFromCmdLine(argc, argv);
00833 if (game == NULL)
00834 return 1;
00835
00836 game->start();
00837
00838
00839 WINDOW *wBoard = initscr();
00840 keypad(wBoard, true);
00841
00842 cbreak();
00843
00844 nonl();
00845
00846 curs_set(0);
00847
00848 if (has_colors())
00849 {
00850 start_color();
00851
00852
00853 init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
00854 init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
00855 init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
00856 init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
00857
00858 init_pair(COLOR_BLUE, COLOR_BLACK, COLOR_BLUE);
00859 init_pair(COLOR_CYAN, COLOR_BLACK, COLOR_CYAN);
00860 init_pair(COLOR_MAGENTA, COLOR_BLACK, COLOR_MAGENTA);
00861 init_pair(COLOR_RED, COLOR_BLACK, COLOR_RED);
00862 }
00863
00864
00865 noecho();
00866
00867
00868 CursesIntf mainIntf(wBoard, *game);
00869 mainIntf.redraw(wBoard);
00870
00871 while (!mainIntf.isDying())
00872 {
00873 int c = getch();
00874 if (mainIntf.handleKey(c) == 1)
00875 {
00876 mainIntf.redraw(wBoard);
00877 }
00878 }
00879
00880 delwin(wBoard);
00881
00882
00883 endwin();
00884
00885 GameFactory::Destroy();
00886
00887 return 0;
00888 }