knight.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. /****************************************************************************
  2. * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. *
  3. * *
  4. * Permission is hereby granted, free of charge, to any person obtaining a *
  5. * copy of this software and associated documentation files (the *
  6. * "Software"), to deal in the Software without restriction, including *
  7. * without limitation the rights to use, copy, modify, merge, publish, *
  8. * distribute, distribute with modifications, sublicense, and/or sell *
  9. * copies of the Software, and to permit persons to whom the Software is *
  10. * furnished to do so, subject to the following conditions: *
  11. * *
  12. * The above copyright notice and this permission notice shall be included *
  13. * in all copies or substantial portions of the Software. *
  14. * *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
  16. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
  18. * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
  19. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
  20. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
  21. * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
  22. * *
  23. * Except as contained in this notice, the name(s) of the above copyright *
  24. * holders shall not be used in advertising or otherwise to promote the *
  25. * sale, use or other dealings in this Software without prior written *
  26. * authorization. *
  27. ****************************************************************************/
  28. /*
  29. * Knight's Tour - a brain game
  30. *
  31. * The original of this game was anonymous. It had an unbelievably bogus
  32. * interface, you actually had to enter square coordinates! Redesign by
  33. * Eric S. Raymond <esr@snark.thyrsus.com> July 22 1995. Mouse support
  34. * added September 20th 1995.
  35. *
  36. * $Id: knight.c,v 1.28 2008/08/03 23:04:26 tom Exp $
  37. */
  38. #include <test.priv.h>
  39. /* board size */
  40. #define BDEPTH 8
  41. #define BWIDTH 8
  42. /* where to start the instructions */
  43. #define INSTRY 2
  44. #define INSTRX 35
  45. /* corner of board */
  46. #define BOARDY 2
  47. #define BOARDX 0
  48. /* notification line */
  49. #define NOTIFYY 21
  50. /* virtual color values */
  51. #define TRAIL_COLOR 1
  52. #define PLUS_COLOR 2
  53. #define MINUS_COLOR 3
  54. #define CX(x) (2 + 4 * (x))
  55. #define CY(y) (1 + 2 * (y))
  56. #define cellmove(y, x) wmove(boardwin, CY(y), CX(x))
  57. #define CXINV(x) (((x) - 1) / 4)
  58. #define CYINV(y) (((y) - 2) / 2)
  59. typedef struct {
  60. short x, y;
  61. } cell;
  62. static WINDOW *boardwin; /* the board window */
  63. static WINDOW *helpwin; /* the help window */
  64. static WINDOW *msgwin; /* the message window */
  65. static cell history[BDEPTH * BWIDTH + 1]; /* choice history */
  66. static chtype minus = '-'; /* possible-move character */
  67. static chtype oldch;
  68. static chtype plus = '+'; /* cursor hot-spot character */
  69. static chtype trail = '#'; /* trail character */
  70. static int movecount; /* count of moves so far */
  71. static int trialcount; /* count of trials so far */
  72. static short board[BDEPTH][BWIDTH]; /* the squares */
  73. /* *INDENT-OFF* */
  74. static const struct {
  75. int y;
  76. int x;
  77. } offsets[] = {
  78. { 2, 1 },
  79. { 1, 2 },
  80. { -1, 2 },
  81. { -2, 1 },
  82. { -2, -1 },
  83. { -1, -2 },
  84. { 1, -2 },
  85. { 2, -1 },
  86. };
  87. /* *INDENT-ON* */
  88. static void
  89. init_program(void)
  90. {
  91. setlocale(LC_ALL, "");
  92. srand((unsigned) getpid());
  93. initscr();
  94. cbreak(); /* immediate char return */
  95. noecho(); /* no immediate echo */
  96. boardwin = newwin(BDEPTH * 2 + 1, BWIDTH * 4 + 1, BOARDY, BOARDX);
  97. helpwin = newwin(0, 0, INSTRY, INSTRX);
  98. msgwin = newwin(1, INSTRX - 1, NOTIFYY, 0);
  99. scrollok(msgwin, TRUE);
  100. keypad(boardwin, TRUE);
  101. if (has_colors()) {
  102. int bg = COLOR_BLACK;
  103. start_color();
  104. #if HAVE_USE_DEFAULT_COLORS
  105. if (use_default_colors() == OK)
  106. bg = -1;
  107. #endif
  108. (void) init_pair(TRAIL_COLOR, COLOR_CYAN, bg);
  109. (void) init_pair(PLUS_COLOR, COLOR_RED, bg);
  110. (void) init_pair(MINUS_COLOR, COLOR_GREEN, bg);
  111. trail |= COLOR_PAIR(TRAIL_COLOR);
  112. plus |= COLOR_PAIR(PLUS_COLOR);
  113. minus |= COLOR_PAIR(MINUS_COLOR);
  114. }
  115. #ifdef NCURSES_MOUSE_VERSION
  116. (void) mousemask(BUTTON1_CLICKED, (mmask_t *) NULL);
  117. #endif /* NCURSES_MOUSE_VERSION */
  118. oldch = minus;
  119. }
  120. static void
  121. help1(void)
  122. /* game explanation -- initial help screen */
  123. {
  124. (void) waddstr(helpwin, "Knight's move is a solitaire puzzle. Your\n");
  125. (void) waddstr(helpwin, "objective is to visit each square of the \n");
  126. (void) waddstr(helpwin, "chessboard exactly once by making knight's\n");
  127. (void) waddstr(helpwin, "moves (one square right or left followed \n");
  128. (void) waddstr(helpwin, "by two squares up or down, or two squares \n");
  129. (void) waddstr(helpwin, "right or left followed by one square up or\n");
  130. (void) waddstr(helpwin, "down). You may start anywhere.\n\n");
  131. (void) waddstr(helpwin, "Use arrow keys to move the cursor around.\n");
  132. (void) waddstr(helpwin, "When you want to move your knight to the \n");
  133. (void) waddstr(helpwin, "cursor location, press <space> or Enter.\n");
  134. (void) waddstr(helpwin, "Illegal moves will be rejected with an \n");
  135. (void) waddstr(helpwin, "audible beep.\n\n");
  136. (void) waddstr(helpwin, "The program will detect if you solve the\n");
  137. (void) waddstr(helpwin, "puzzle; also inform you when you run out\n");
  138. (void) waddstr(helpwin, "of legal moves.\n\n");
  139. (void) mvwaddstr(helpwin, NOTIFYY - INSTRY, 0,
  140. "Press `?' to go to keystroke help.");
  141. }
  142. static void
  143. help2(void)
  144. /* keystroke help screen */
  145. {
  146. (void) waddstr(helpwin, "Possible moves are shown with `-'.\n\n");
  147. (void) waddstr(helpwin, "You can move around with the arrow keys or\n");
  148. (void) waddstr(helpwin, "with the rogue/hack movement keys. Other\n");
  149. (void) waddstr(helpwin, "commands allow you to undo moves or redraw.\n");
  150. (void) waddstr(helpwin, "Your mouse may work; try left-button to\n");
  151. (void) waddstr(helpwin, "move to the square under the pointer.\n\n");
  152. (void) waddstr(helpwin, "x,q -- exit y k u 7 8 9\n");
  153. (void) waddstr(helpwin, "r -- redraw screen \\|/ \\|/ \n");
  154. (void) waddstr(helpwin, "bksp -- undo move h-+-l 4-+-6\n");
  155. (void) waddstr(helpwin, "a -- autojump /|\\ /|\\ \n");
  156. (void) waddstr(helpwin, " b j n 1 2 3\n");
  157. (void) waddstr(helpwin, "\nYou can place your knight on the selected\n");
  158. (void) waddstr(helpwin, "square with spacebar, Enter, or the keypad\n");
  159. (void) waddstr(helpwin, "center key. Use F/B to review the path.\n");
  160. (void) mvwaddstr(helpwin, NOTIFYY - INSTRY, 0,
  161. "Press `?' to go to game explanation");
  162. }
  163. static void
  164. show_help(bool * keyhelp)
  165. {
  166. werase(helpwin);
  167. if (*keyhelp) {
  168. help1();
  169. *keyhelp = FALSE;
  170. } else {
  171. help2();
  172. *keyhelp = TRUE;
  173. }
  174. wrefresh(helpwin);
  175. }
  176. static bool
  177. chksqr(int r1, int c1)
  178. {
  179. if ((r1 < 0) || (r1 > BDEPTH - 1))
  180. return (FALSE);
  181. if ((c1 < 0) || (c1 > BWIDTH - 1))
  182. return (FALSE);
  183. return ((!board[r1][c1]) ? TRUE : FALSE);
  184. }
  185. static bool
  186. chkmoves(int rw, int col)
  187. /* check to see if valid moves are available */
  188. {
  189. unsigned n;
  190. for (n = 0; n < SIZEOF(offsets); n++)
  191. if (chksqr(rw + offsets[n].y, col + offsets[n].x))
  192. return (TRUE);
  193. return (FALSE);
  194. }
  195. static void
  196. dosquares(void)
  197. {
  198. int i, j;
  199. mvaddstr(0, 20, "KNIGHT'S MOVE -- a logical solitaire");
  200. move(BOARDY, BOARDX);
  201. waddch(boardwin, ACS_ULCORNER);
  202. for (j = 0; j < 7; j++) {
  203. waddch(boardwin, ACS_HLINE);
  204. waddch(boardwin, ACS_HLINE);
  205. waddch(boardwin, ACS_HLINE);
  206. waddch(boardwin, ACS_TTEE);
  207. }
  208. waddch(boardwin, ACS_HLINE);
  209. waddch(boardwin, ACS_HLINE);
  210. waddch(boardwin, ACS_HLINE);
  211. waddch(boardwin, ACS_URCORNER);
  212. for (i = 1; i < BDEPTH; i++) {
  213. move(BOARDY + i * 2 - 1, BOARDX);
  214. waddch(boardwin, ACS_VLINE);
  215. for (j = 0; j < BWIDTH; j++) {
  216. waddch(boardwin, ' ');
  217. waddch(boardwin, ' ');
  218. waddch(boardwin, ' ');
  219. waddch(boardwin, ACS_VLINE);
  220. }
  221. move(BOARDY + i * 2, BOARDX);
  222. waddch(boardwin, ACS_LTEE);
  223. for (j = 0; j < BWIDTH - 1; j++) {
  224. waddch(boardwin, ACS_HLINE);
  225. waddch(boardwin, ACS_HLINE);
  226. waddch(boardwin, ACS_HLINE);
  227. waddch(boardwin, ACS_PLUS);
  228. }
  229. waddch(boardwin, ACS_HLINE);
  230. waddch(boardwin, ACS_HLINE);
  231. waddch(boardwin, ACS_HLINE);
  232. waddch(boardwin, ACS_RTEE);
  233. }
  234. move(BOARDY + i * 2 - 1, BOARDX);
  235. waddch(boardwin, ACS_VLINE);
  236. for (j = 0; j < BWIDTH; j++) {
  237. waddch(boardwin, ' ');
  238. waddch(boardwin, ' ');
  239. waddch(boardwin, ' ');
  240. waddch(boardwin, ACS_VLINE);
  241. }
  242. move(BOARDY + i * 2, BOARDX);
  243. waddch(boardwin, ACS_LLCORNER);
  244. for (j = 0; j < BWIDTH - 1; j++) {
  245. waddch(boardwin, ACS_HLINE);
  246. waddch(boardwin, ACS_HLINE);
  247. waddch(boardwin, ACS_HLINE);
  248. waddch(boardwin, ACS_BTEE);
  249. }
  250. waddch(boardwin, ACS_HLINE);
  251. waddch(boardwin, ACS_HLINE);
  252. waddch(boardwin, ACS_HLINE);
  253. waddch(boardwin, ACS_LRCORNER);
  254. }
  255. static void
  256. mark_possibles(int prow, int pcol, chtype mark)
  257. {
  258. unsigned n;
  259. for (n = 0; n < SIZEOF(offsets); n++) {
  260. if (chksqr(prow + offsets[n].y, pcol + offsets[n].x)) {
  261. cellmove(prow + offsets[n].y, pcol + offsets[n].x);
  262. waddch(boardwin, mark);
  263. }
  264. }
  265. }
  266. static void
  267. find_next_move(int *y, int *x)
  268. {
  269. unsigned j, k;
  270. int found = -1;
  271. int first = -1;
  272. int next = 0;
  273. int oldy, oldx;
  274. int newy, newx;
  275. if (movecount > 1) {
  276. oldy = history[movecount - 1].y;
  277. oldx = history[movecount - 1].x;
  278. for (j = 0; j < SIZEOF(offsets) * 2; j++) {
  279. k = j % SIZEOF(offsets);
  280. newy = oldy + offsets[k].y;
  281. newx = oldx + offsets[k].x;
  282. if (chksqr(newy, newx)) {
  283. if (first < 0)
  284. first = k;
  285. if (newy == *y
  286. && newx == *x) {
  287. found = k;
  288. } else if (found >= 0) {
  289. next = k;
  290. break;
  291. }
  292. }
  293. }
  294. if (found < 0)
  295. next = first;
  296. if (next >= 0) {
  297. *y = oldy + offsets[next].y;
  298. *x = oldx + offsets[next].x;
  299. }
  300. } else {
  301. beep();
  302. }
  303. }
  304. static void
  305. unmarkcell(int row, int column)
  306. {
  307. cellmove(row, column);
  308. waddch(boardwin, '\b');
  309. waddch(boardwin, ' ');
  310. waddch(boardwin, minus);
  311. waddch(boardwin, ' ');
  312. }
  313. static void
  314. markcell(chtype tchar, int row, int column)
  315. {
  316. cellmove(row, column);
  317. waddch(boardwin, '\b');
  318. waddch(boardwin, tchar);
  319. waddch(boardwin, tchar);
  320. waddch(boardwin, tchar);
  321. }
  322. static void
  323. drawmove(chtype tchar, int oldy, int oldx, int row, int column)
  324. /* place the stars, update board & currents */
  325. {
  326. if (movecount <= 1) {
  327. int i, j;
  328. for (i = 0; i < BDEPTH; i++) {
  329. for (j = 0; j < BWIDTH; j++) {
  330. if (movecount == 0) {
  331. unmarkcell(i, j);
  332. } else {
  333. cellmove(i, j);
  334. if (winch(boardwin) == minus)
  335. waddch(boardwin, movecount ? ' ' : minus);
  336. }
  337. }
  338. }
  339. } else {
  340. markcell(tchar, oldy, oldx);
  341. mark_possibles(oldy, oldx, ' ');
  342. }
  343. if (row >= 0 && column >= 0) {
  344. markcell(trail, row, column);
  345. mark_possibles(row, column, minus);
  346. board[row][column] = TRUE;
  347. }
  348. wprintw(msgwin, "\nMove %d", movecount);
  349. if (trialcount != movecount)
  350. wprintw(msgwin, " (%d tries)", trialcount);
  351. wclrtoeol(msgwin);
  352. }
  353. static int
  354. iabs(int num)
  355. {
  356. if (num < 0)
  357. return (-num);
  358. else
  359. return (num);
  360. }
  361. static bool
  362. evalmove(int row, int column)
  363. /* evaluate move */
  364. {
  365. if (movecount == 1)
  366. return (TRUE);
  367. else if (board[row][column] == TRUE) {
  368. waddstr(msgwin, "\nYou've already been there.");
  369. return (FALSE);
  370. } else {
  371. int rdif = iabs(row - history[movecount - 1].y);
  372. int cdif = iabs(column - history[movecount - 1].x);
  373. if (!((rdif == 1) && (cdif == 2)) && !((rdif == 2) && (cdif == 1))) {
  374. waddstr(msgwin, "\nThat's not a legal knight's move.");
  375. return (FALSE);
  376. }
  377. }
  378. return (TRUE);
  379. }
  380. static int
  381. completed(void)
  382. {
  383. int i, j, count = 0;
  384. for (i = 0; i < BDEPTH; i++)
  385. for (j = 0; j < BWIDTH; j++)
  386. if (board[i][j] != 0)
  387. count += 1;
  388. return (count == (BWIDTH * BDEPTH) ? -1 : count);
  389. }
  390. static void
  391. no_previous_move(void)
  392. {
  393. waddstr(msgwin, "\nNo previous move.");
  394. beep();
  395. }
  396. static void
  397. play(void)
  398. /* play the game */
  399. {
  400. bool keyhelp; /* TRUE if keystroke help is up */
  401. int i, j, count;
  402. int lastcol = 0; /* last location visited */
  403. int lastrow = 0;
  404. int ny = 0, nx = 0;
  405. int review = 0; /* review history */
  406. int rw = 0, col = 0; /* current row and column */
  407. do {
  408. /* clear screen and draw board */
  409. werase(boardwin);
  410. werase(helpwin);
  411. werase(msgwin);
  412. dosquares();
  413. help1();
  414. wnoutrefresh(stdscr);
  415. wnoutrefresh(helpwin);
  416. wnoutrefresh(msgwin);
  417. wnoutrefresh(boardwin);
  418. doupdate();
  419. movecount = 0;
  420. for (i = 0; i < BDEPTH; i++) {
  421. for (j = 0; j < BWIDTH; j++) {
  422. board[i][j] = FALSE;
  423. unmarkcell(i, j);
  424. }
  425. }
  426. memset(history, 0, sizeof(history));
  427. history[0].y = history[0].x = -1;
  428. history[1].y = history[1].x = -1;
  429. lastrow = lastcol = -2;
  430. movecount = 1;
  431. trialcount = 1;
  432. keyhelp = FALSE;
  433. show_help(&keyhelp);
  434. for (;;) {
  435. if (rw != lastrow || col != lastcol) {
  436. if (lastrow >= 0 && lastcol >= 0) {
  437. cellmove(lastrow, lastcol);
  438. if (board[lastrow][lastcol])
  439. waddch(boardwin, trail);
  440. else
  441. waddch(boardwin, oldch);
  442. }
  443. cellmove(rw, col);
  444. oldch = winch(boardwin);
  445. lastrow = rw;
  446. lastcol = col;
  447. }
  448. cellmove(rw, col);
  449. waddch(boardwin, plus);
  450. cellmove(rw, col);
  451. wrefresh(msgwin);
  452. switch (wgetch(boardwin)) {
  453. case 'k':
  454. case '8':
  455. case KEY_UP:
  456. ny = rw + BDEPTH - 1;
  457. nx = col;
  458. break;
  459. case 'j':
  460. case '2':
  461. case KEY_DOWN:
  462. ny = rw + 1;
  463. nx = col;
  464. break;
  465. case 'h':
  466. case '4':
  467. case KEY_LEFT:
  468. ny = rw;
  469. nx = col + BWIDTH - 1;
  470. break;
  471. case 'l':
  472. case '6':
  473. case KEY_RIGHT:
  474. ny = rw;
  475. nx = col + 1;
  476. break;
  477. case 'y':
  478. case '7':
  479. case KEY_A1:
  480. ny = rw + BDEPTH - 1;
  481. nx = col + BWIDTH - 1;
  482. break;
  483. case 'b':
  484. case '1':
  485. case KEY_C1:
  486. ny = rw + 1;
  487. nx = col + BWIDTH - 1;
  488. break;
  489. case 'u':
  490. case '9':
  491. case KEY_A3:
  492. ny = rw + BDEPTH - 1;
  493. nx = col + 1;
  494. break;
  495. case 'n':
  496. case '3':
  497. case KEY_C3:
  498. ny = rw + 1;
  499. nx = col + 1;
  500. break;
  501. #ifdef NCURSES_MOUSE_VERSION
  502. case KEY_MOUSE:
  503. {
  504. MEVENT myevent;
  505. getmouse(&myevent);
  506. if (myevent.y >= CY(0) && myevent.y <= CY(BDEPTH)
  507. && myevent.x >= CX(0) && myevent.x <= CX(BWIDTH)) {
  508. nx = CXINV(myevent.x);
  509. ny = CYINV(myevent.y);
  510. ungetch('\n');
  511. break;
  512. } else {
  513. beep();
  514. continue;
  515. }
  516. }
  517. #endif /* NCURSES_MOUSE_VERSION */
  518. case KEY_B2:
  519. case '\n':
  520. case ' ':
  521. review = 0;
  522. if (evalmove(rw, col)) {
  523. drawmove(trail,
  524. history[movecount - 1].y,
  525. history[movecount - 1].x,
  526. rw, col);
  527. history[movecount].y = rw;
  528. history[movecount].x = col;
  529. movecount++;
  530. trialcount++;
  531. if (!chkmoves(rw, col)) {
  532. if (completed() < 0) {
  533. waddstr(msgwin, "\nYou won.");
  534. } else {
  535. waddstr(msgwin,
  536. "\nNo further moves are possible.");
  537. }
  538. }
  539. } else {
  540. beep();
  541. }
  542. break;
  543. case KEY_UNDO:
  544. case KEY_BACKSPACE:
  545. case '\b':
  546. review = 0;
  547. if (movecount <= 0) {
  548. no_previous_move();
  549. } else if (movecount <= 1) {
  550. ny = history[movecount].y;
  551. nx = history[movecount].x;
  552. if (nx < 0 || ny < 0) {
  553. ny = lastrow;
  554. nx = lastcol;
  555. }
  556. movecount = 0;
  557. board[ny][nx] = FALSE;
  558. oldch = minus;
  559. drawmove(' ', ny, nx, -1, -1);
  560. movecount = 1;
  561. trialcount = 1;
  562. no_previous_move();
  563. } else {
  564. int oldy = history[movecount - 1].y;
  565. int oldx = history[movecount - 1].x;
  566. if (!board[rw][col]) {
  567. cellmove(rw, col);
  568. waddch(boardwin, ' ');
  569. }
  570. board[oldy][oldx] = FALSE;
  571. --movecount;
  572. ny = history[movecount - 1].y;
  573. nx = history[movecount - 1].x;
  574. if (nx < 0 || ny < 0) {
  575. ny = oldy;
  576. nx = oldx;
  577. }
  578. drawmove(' ', oldy, oldx, ny, nx);
  579. /* avoid problems if we just changed the current cell */
  580. cellmove(lastrow, lastcol);
  581. oldch = winch(boardwin);
  582. }
  583. break;
  584. case 'a':
  585. nx = col;
  586. ny = rw;
  587. find_next_move(&ny, &nx);
  588. break;
  589. case 'F':
  590. if (review > 0) {
  591. review--;
  592. ny = history[movecount - review - 1].y;
  593. nx = history[movecount - review - 1].x;
  594. } else {
  595. beep();
  596. }
  597. break;
  598. case 'B':
  599. if (review < movecount - 2) {
  600. review++;
  601. ny = history[movecount - review - 1].y;
  602. nx = history[movecount - review - 1].x;
  603. } else {
  604. beep();
  605. }
  606. break;
  607. case KEY_REDO:
  608. case '\f':
  609. case 'r':
  610. clearok(curscr, TRUE);
  611. wnoutrefresh(stdscr);
  612. wnoutrefresh(boardwin);
  613. wnoutrefresh(msgwin);
  614. wnoutrefresh(helpwin);
  615. doupdate();
  616. break;
  617. case 'q':
  618. case 'x':
  619. goto dropout;
  620. case '?':
  621. show_help(&keyhelp);
  622. break;
  623. default:
  624. beep();
  625. break;
  626. }
  627. col = nx % BWIDTH;
  628. rw = ny % BDEPTH;
  629. }
  630. dropout:
  631. if ((count = completed()) < 0)
  632. wprintw(msgwin, "\nYou won. Care to try again? ");
  633. else
  634. wprintw(msgwin, "\n%d squares filled. Try again? ", count);
  635. wclrtoeol(msgwin);
  636. } while
  637. (tolower(wgetch(msgwin)) == 'y');
  638. }
  639. int
  640. main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
  641. {
  642. init_program();
  643. play();
  644. endwin();
  645. ExitProgram(EXIT_SUCCESS);
  646. }
  647. /* knight.c ends here */