home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume19 / mines / part01 < prev    next >
Encoding:
Text File  |  1993-04-27  |  24.1 KB  |  804 lines

  1. Newsgroups: comp.sources.x
  2. From: thompson@mv.us.adobe.com (Ross Thompson)
  3. Subject: v19i036:  mines - Yet another mines game, Part01/01
  4. Message-ID: <1993Mar10.224112.5143@sparky.imd.sterling.com>
  5. X-Md4-Signature: ad9d810fec82496d8c617bc8a53b7a3f
  6. Date: Wed, 10 Mar 1993 22:41:12 GMT
  7. Approved: chris@sparky.imd.sterling.com
  8.  
  9. Submitted-by: thompson@mv.us.adobe.com (Ross Thompson)
  10. Posting-number: Volume 19, Issue 36
  11. Archive-name: mines/part01
  12. Environment: X11
  13.  
  14. Here is a little game that I coded up, based on a Mac game that I
  15. enjoyed.  Although the game is a derivative work, based on someone
  16. else's idea, the sources are original, and may be freely used in any
  17. way.  (I think I'm safe stealing this guy's game idea, since he offers
  18. to give away his sources for the Mac version for free.)
  19.  
  20. Have fun.
  21.  
  22. - Ross
  23.  
  24. #!/bin/sh
  25. # This is a shell archive (produced by shar 3.49)
  26. # To extract the files from this archive, save it to a file, remove
  27. # everything above the "!/bin/sh" line above, and type "sh file_name".
  28. #
  29. # made 09/01/1992 17:47 UTC by thompson@rhythmic
  30. # Source directory /usr/export/home/renault/thompson/src/xapps/mines
  31. #
  32. # existing files will NOT be overwritten unless -c is specified
  33. # This format requires very little intelligence at unshar time.
  34. # "if test", "echo", "true", and "sed" may be needed.
  35. #
  36. # This shar contains:
  37. # length  mode       name
  38. # ------ ---------- ------------------------------------------
  39. #    144 -rw-rw---- Imakefile
  40. #    130 -rw-rw---- Makefile.std
  41. #   1658 -rw-rw---- README
  42. #  16877 -rw-rw---- mines.c
  43. #   1760 -rw-r----- mines.man
  44. #     41 -rw-rw---- patchlevel.h
  45. #
  46. # ============= Imakefile ==============
  47. if test -f 'Imakefile' -a X"$1" != X"-c"; then
  48.     echo 'x - skipping Imakefile (File already exists)'
  49. else
  50. sed 's/^X//' << 'SHAR_EOF' > 'Imakefile' &&
  51. XSTD_INCLUDES = 
  52. XCC = gcc
  53. X
  54. XDEFINES =
  55. XSRCS = mines.c
  56. XOBJS = mines.o
  57. XLOCAL_LIBRARIES = $(XLIB)
  58. XDEPLIBS =
  59. XComplexProgramTarget(mines)
  60. X
  61. Xall :: mines
  62. SHAR_EOF
  63. true || echo 'restore of Imakefile failed'
  64. fi
  65. # ============= Makefile.std ==============
  66. if test -f 'Makefile.std' -a X"$1" != X"-c"; then
  67.     echo 'x - skipping Makefile.std (File already exists)'
  68. else
  69. sed 's/^X//' << 'SHAR_EOF' > 'Makefile.std' &&
  70. XCOPTS =  -o $@ -I/usr/local/X11R4/include -O
  71. XXLIB = /usr/local/X11R4/lib/libX11.a
  72. X
  73. Xmines: mines.c
  74. X    $(CC) $(COPTS) mines.c $(XLIB)
  75. SHAR_EOF
  76. true || echo 'restore of Makefile.std failed'
  77. fi
  78. # ============= README ==============
  79. if test -f 'README' -a X"$1" != X"-c"; then
  80.     echo 'x - skipping README (File already exists)'
  81. else
  82. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  83. XThe mines game is played on a grid.  Every cell of the grid either has
  84. Xa bomb on it, or it doesn't.  If you move onto a cell that has a bomb
  85. Xon it, you lose your leg.  If you move onto a cell that doesn't have a
  86. Xbomb on it, a integer between 0 and eight will be displayed, letting
  87. Xyou know how many bombs are in cells adjecent to the one you just
  88. Xmoved to.  (Adjecent, in this game, means one cell away in any
  89. Xdirection: up, down, left, right, or diagonal.)  Zeros are displayed
  90. Xas blanks, to avoid cluttering the display.  Additionally, since you
  91. Xcan obviously move in any direction from a zero, you automatically
  92. Xclaim the territory adjacent to cells which are blank.  You are only
  93. Xallowed to move to cells adjacent to ones you already own.  Cells you
  94. Xown are indicated by being printed in black; ones you don't own are in
  95. Xwhite.  The object of the game is to (eventually) claim the lower
  96. Xright hand corner of the grid.
  97. X
  98. XThe left button is for claiming new territory.  The right button
  99. Xstarts a new game.  The middle button displays a bomb.  This is a note
  100. Xto yourself about where you think a bomb is; there is no feedback as
  101. Xto whether you have guessed right or not.
  102. X
  103. XKeyboard entries:
  104. X'n' gives you a new game.
  105. X'q' quits the program.
  106. X's' cheats.  plays the game with the same information you have
  107. X    and some very simple rules.  Doesn't win every winable
  108. X    game, but it does save stupid mistakes.
  109. X
  110. XThe slider at the bottom of the window is for adjusting how many mines
  111. Xyou have in the grid.  You can also resize the window if you want to
  112. Xplay on a grid of a different size.  The maximum number of bombs you
  113. Xcan have is half the number of cells in the grid.
  114. SHAR_EOF
  115. true || echo 'restore of README failed'
  116. fi
  117. # ============= mines.c ==============
  118. if test -f 'mines.c' -a X"$1" != X"-c"; then
  119.     echo 'x - skipping mines.c (File already exists)'
  120. else
  121. sed 's/^X//' << 'SHAR_EOF' > 'mines.c' &&
  122. X/* mines.c: play in a mine field.
  123. X   Source based on a Mac game by Danial Griscom of the Computer
  124. X   Museum, Boston Mass, which was in turn based on a SunTools
  125. X   version by Tom Anderson.
  126. X   Bomb Icon ray traced by Steven Hawley.
  127. X*/
  128. X
  129. X#include "X11/Xlib.h"
  130. X#include "X11/Xatom.h"
  131. X#include "X11/Xutil.h"
  132. X#include <stdio.h>
  133. X#include <sys/time.h>
  134. X#include <malloc.h>
  135. X
  136. X#define max(a, b) ((a) > (b) ? (a) : (b))
  137. X#define min(a, b) ((a) < (b) ? (a) : (b))
  138. X
  139. X#define cell_width 17
  140. X#define cell_height 17
  141. Xstatic char bomb_bits[] = {
  142. X   0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x01, 0x00, 0x01,
  143. X   0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x19, 0xf0, 0x1b, 0xf0, 0x1f, 0xf0, 0x1f,
  144. X   0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x00, 0x00};
  145. X
  146. Xstatic char ok_bits[] = {
  147. X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x42, 0x24, 0x22,
  148. X   0x42, 0x12, 0x42, 0x0a, 0x42, 0x06, 0x42, 0x0a, 0x42, 0x12, 0x24, 0x22,
  149. X   0x18, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  150. X
  151. X#define slider_width 10
  152. X#define slider_height 25
  153. Xstatic char slider_bits[] = {
  154. X   0xff, 0x03, 0x03, 0x03, 0x85, 0x02, 0x79, 0x02, 0x59, 0x02, 0x49, 0x02,
  155. X   0x69, 0x02, 0x49, 0x02, 0x59, 0x02, 0x49, 0x02, 0x69, 0x02, 0x49, 0x02,
  156. X   0x79, 0x02, 0x49, 0x02, 0x69, 0x02, 0x49, 0x02, 0x59, 0x02, 0x49, 0x02,
  157. X   0x69, 0x02, 0x49, 0x02, 0x59, 0x02, 0x79, 0x02, 0x85, 0x02, 0x03, 0x03,
  158. X   0xff, 0x03};
  159. X
  160. X#define icon_width 40
  161. X#define icon_height 40
  162. Xstatic char icon_bits[] = {
  163. X   0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00,
  164. X   0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x80, 0xad, 0x00, 0x00, 0x7d, 0x61,
  165. X   0x5f, 0x00, 0xc0, 0xaf, 0xc7, 0x07, 0x00, 0x70, 0x7d, 0x7d, 0x0f, 0x00,
  166. X   0xb8, 0xab, 0xdf, 0x15, 0x00, 0xf6, 0x6e, 0x7a, 0x1f, 0x00, 0x5d, 0xb7,
  167. X   0xba, 0x0b, 0x00, 0xfb, 0x4a, 0xda, 0x06, 0x80, 0xae, 0x37, 0xf4, 0x03,
  168. X   0x40, 0x7b, 0x95, 0xe8, 0x05, 0x80, 0xdf, 0x16, 0x50, 0x03, 0xc0, 0x7a,
  169. X   0x2b, 0xd2, 0x05, 0xc0, 0xd7, 0x96, 0x50, 0x0f, 0xa0, 0xfe, 0x55, 0xaa,
  170. X   0x05, 0xe0, 0xab, 0xae, 0x64, 0x0f, 0x40, 0xff, 0x55, 0xb5, 0x0d, 0xe0,
  171. X   0x55, 0x7f, 0x6d, 0x0f, 0xa0, 0xff, 0xaa, 0xf5, 0x05, 0xe0, 0x55, 0xef,
  172. X   0xbe, 0x0e, 0x40, 0xff, 0x5d, 0xeb, 0x0b, 0xc0, 0x56, 0xf7, 0xbd, 0x06,
  173. X   0xe0, 0xfb, 0xae, 0xf7, 0x0b, 0x80, 0xbe, 0xfb, 0x5a, 0x05, 0x80, 0xeb,
  174. X   0x6e, 0xef, 0x03, 0x80, 0xbd, 0xdb, 0xfb, 0x02, 0x00, 0x77, 0x6f, 0xaf,
  175. X   0x01, 0x00, 0xdc, 0xfb, 0xf5, 0x00, 0x00, 0x76, 0xad, 0x5f, 0x00, 0x00,
  176. X   0xb8, 0xff, 0x35, 0x00, 0x00, 0xe0, 0xaa, 0x2e, 0x00, 0x00, 0x54, 0xff,
  177. X   0x57, 0x01, 0xa0, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x55, 0x55, 0x55, 0x00,
  178. X   0x00, 0xa0, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  179. X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  180. X
  181. X
  182. X#define Border 4
  183. X#define SliderHeight slider_height
  184. X#define SliderWidth 128
  185. X#define ControlHeight (SliderHeight + Border)
  186. X#define ControlWidth (SliderWidth + 50)
  187. X
  188. X#define WindowWidth(x) max(((x) * cell_width + (Border << 1)), ControlWidth)
  189. X#define WindowHeight(x) ((x) * cell_height + (Border << 1) + ControlHeight)
  190. X#define MinRows 6
  191. X#define MinCols 6
  192. X
  193. X#define MINHEIGHT WindowHeight(MinRows)
  194. X#define MINWIDTH WindowWidth(MinCols)
  195. X
  196. X#define ds() DefaultScreen(display)
  197. X#define rw() RootWindow(display, ds())
  198. X#define black() BlackPixel(display, ds())
  199. X#define white() WhitePixel(display, ds())
  200. X
  201. X/* special values for a square. */
  202. X#define Bomb -1
  203. X#define Ok -2 /* never used for "actual" */
  204. X#define Void -3  /* never used for "actual" */
  205. X
  206. Xtypedef struct {
  207. X    int row, col; /* address of this cell */
  208. X    int disp, actual; /* contents of this cell */
  209. X    int mark; /* used for determining a legitimate game. */
  210. X} Cell;
  211. X
  212. Xtypedef struct {
  213. X    int numrows, numcols;
  214. X    Cell *cells;
  215. X} Board;
  216. X
  217. XBoard board;
  218. Xunsigned int depth;
  219. XPixmap BombIcon, OkIcon, SliderIcon, IconIcon;
  220. Xenum {initializing, playing, won, lost} game_state;
  221. X
  222. X/* returns the cell (x, y) of a board. */
  223. X#define Square(board, x, y) ((board).cells[(x) * (board).numcols + (y)])
  224. X
  225. XDisplay *display;
  226. XWindow win;
  227. XGC gc;
  228. Xint width, height; /* window dimensions */
  229. X
  230. Xstruct {
  231. X    int xcells, ycells;
  232. X    int maxbombs;
  233. X    int bombcount;
  234. X} configuration;
  235. X
  236. XNewConfig(r, c)
  237. X{
  238. X    configuration.xcells = c;
  239. X    configuration.ycells = r;
  240. X    configuration.maxbombs = (c * r) / 2;
  241. X    if (configuration.bombcount > configuration.maxbombs)
  242. X    configuration.bombcount = configuration.maxbombs;
  243. X}
  244. X
  245. Xint rest(usec) unsigned long usec;
  246. X{
  247. X    struct timeval timeout;
  248. X
  249. X    if (!usec) return 0;
  250. X    timeout.tv_usec = usec % (unsigned long) 1000000;
  251. X    timeout.tv_sec = usec / (unsigned long) 1000000;
  252. X    select(0, (void *) 0, (void *) 0, (void *) 0, &timeout);
  253. X    return 0;
  254. X}
  255. X
  256. XNewBoard()
  257. X{
  258. X    int i, j, nr, nc;
  259. X    Cell *c;
  260. X
  261. X    nr = configuration.ycells;
  262. X    nc = configuration.xcells;
  263. X    if (board.cells && board.numrows * board.numcols != nr * nc) {
  264. X    free(board.cells);
  265. X    board.cells = 0; }
  266. X    board.numrows = nr, board.numcols = nc;
  267. X    if (!board.cells)
  268. X    board.cells =
  269. X        (Cell *) malloc(sizeof(Cell) * nr * nc);
  270. X    for (c = board.cells, i = 0; i < nr; i++)
  271. X    for (j = 0; j < nc; j++, c++) {
  272. X        c->row = i;
  273. X        c->col = j;
  274. X        c->disp = Void;
  275. X        c->actual = 0;
  276. X        c->mark = 0; }
  277. X}
  278. X
  279. X#define ForEachNeighbor(cell) \
  280. X    int i, j, minr, maxr, minc, maxc; Cell *c2; \
  281. X    minr = max(0, (cell)->row - 1); \
  282. X    maxr = min(board.numrows - 1, (cell)->row + 1); \
  283. X    minc = max(0, (cell)->col - 1); \
  284. X    maxc = min(board.numcols - 1, (cell)->col + 1); \
  285. X    for ( i = minr; i <= maxr; i++) \
  286. X    for (j = minc, c2 = &Square(board, i, j); \
  287. X         j <= maxc; j++, c2 = &Square(board, i, j))
  288. X
  289. XSearch(r, c)
  290. X{
  291. X    Cell *cell;
  292. X
  293. X    if (r == board.numrows - 1 && c == board.numcols - 1)
  294. X    return 1;
  295. X    cell = &Square(board, r, c);
  296. X    cell->mark = 1;
  297. X    {ForEachNeighbor(cell)
  298. X     if (!c2->mark && c2->actual >= 0 && Search(i, j))
  299. X         return 1; }
  300. X    return 0;
  301. X}
  302. X
  303. XPlaceBombs()
  304. X{
  305. X    int i;
  306. X    int r, c, nr, nc;
  307. X    Cell *cell;
  308. X
  309. X    nr = board.numrows;
  310. X    nc = board.numcols;
  311. X    while (1) {
  312. X    for (i = configuration.bombcount; i--; ) {
  313. X        do {r = random() % nr;
  314. X        c = random() % nc;
  315. X        cell = &Square(board, r, c); }
  316. X        while ((r < 2 && c < 2) || (nr - r < 3 && nc - c < 3) ||
  317. X           cell->actual == Bomb);
  318. X        cell->actual = Bomb;
  319. X        {ForEachNeighbor(cell) {
  320. X        if (c2->actual != Bomb)
  321. X            c2->actual++; }}}
  322. X    /* we built a board.  Search for a solution. */
  323. X    for (i = nr * nc, cell = board.cells; i--; cell++)
  324. X        cell->mark = 0;
  325. X    if (Search(0, 0)) break; /* if solution found, return to caller. */
  326. X    for (i = nr * nc, cell = board.cells; i--; cell++)
  327. X        cell->actual = 0; }
  328. X}
  329. X
  330. X/* 0 means normal move.  1 means guess a bomb.  2 means print "ok" */
  331. XShowCell(r, c, flag) int r, c; int flag;
  332. X{
  333. X    Cell *cell;
  334. X    char s[3];
  335. X
  336. X    cell = &Square(board, r, c);
  337. X    switch (flag) {
  338. X      case 0: cell->disp = cell->actual; break;
  339. X      case 1: cell->disp = cell->disp == Bomb ? Void : Bomb; break;
  340. X      case 2: cell->disp = Ok; }
  341. X
  342. X    if (cell->disp == Void) {
  343. X    XSetForeground(display, gc, white());
  344. X    XFillRectangle(display, win, gc,
  345. X               Border + c * cell_width + 1,
  346. X               Border + r * cell_height + 1,
  347. X               cell_width - 1, cell_height - 1);
  348. X    XSetForeground(display, gc, black()); }
  349. X    else if (cell->disp == Bomb) {
  350. X    XSetFunction(display, gc, GXcopy);
  351. X    XCopyArea(display, BombIcon, win, gc, 0, 0,
  352. X          cell_width - 1, cell_height - 1,
  353. X          Border + c * cell_width + 1, Border + r * cell_height + 1); }
  354. X    else if (cell->disp == Ok) {
  355. X    XSetFunction(display, gc, GXcopy);
  356. X    XCopyArea(display, OkIcon, win, gc, 0, 0,
  357. X          cell_width - 1, cell_height - 1,
  358. X          Border + c * cell_width + 1, Border + r * cell_height + 1); }
  359. X    else {
  360. X    if (cell->disp > 0) {
  361. X        s[0] = '0' + cell->disp;
  362. X        s[1] = 0;
  363. X        XDrawString(display, win, gc,
  364. X            c * cell_width + Border + (cell_width >> 1) - 4,
  365. X            (r + 1) * cell_height + Border - 4, s, 1); }
  366. X    XSetFunction(display, gc, GXinvert);
  367. X    XFillRectangle(display, win, gc,
  368. X               Border + c * cell_width + 1,
  369. X               Border + r * cell_height + 1,
  370. X               cell_width, cell_height);
  371. X    XSetFunction(display, gc, GXcopy); }
  372. X}
  373. X
  374. XShowBombs()
  375. X{
  376. X    int i, j;
  377. X    Cell *c;
  378. X
  379. X    for (i = 0, c = board.cells; i < board.numrows; i++)
  380. X    for (j = 0; j < board.numcols; j++, c++) {
  381. X        if (c->actual == Bomb) ShowCell(i, j, 0);
  382. X        else if (c->disp == Bomb) ShowCell(i, j, 2); }
  383. X}
  384. X
  385. XWin()
  386. X{
  387. X    game_state = won;
  388. X    ShowBombs();
  389. X}
  390. X
  391. XLose()
  392. X{
  393. X    int i;
  394. X
  395. X    game_state = lost;
  396. X
  397. X    ShowBombs();
  398. X    XSetFunction(display, gc, GXinvert);
  399. X    for (i = 6; i--; ) {
  400. X    XFillRectangle(display, win, gc, 0, 0, width, height);
  401. X    rest(250); }
  402. X    XSetFunction(display, gc, GXcopy);
  403. X}
  404. X
  405. XClaimSquare(r, c)
  406. X{
  407. X    Cell *cell;
  408. X
  409. X    cell = &Square(board, r, c);
  410. X    if (cell->actual != Bomb && cell->disp == Bomb) {
  411. X    /* player guessed wrong.  Erase the bomb first. */
  412. X    ShowCell(r, c, 1); }
  413. X    ShowCell(r, c, 0);
  414. X    if (r == board.numrows - 1 && c == board.numcols - 1) Win();
  415. X    else if (cell->actual == Bomb) Lose();
  416. X    if (cell->disp == 0) {
  417. X    ForEachNeighbor(cell)
  418. X        if (c2->disp == Void || c2->disp == Bomb)
  419. X        ClaimSquare(i, j); }
  420. X}
  421. X
  422. XDrawGrid()
  423. X{
  424. X    int i;
  425. X
  426. X    /* ResizeWindow(); */
  427. X
  428. X    XSetForeground(display, gc, white());
  429. X    XFillRectangle(display, win, gc, 0, 0, width, height);
  430. X    XSetForeground(display, gc, black());
  431. X    for (i = Border + (board.numrows * cell_width); i > 0 ; i -= cell_width) {
  432. X    XDrawLine(display, win, gc, Border, i, width - Border, i); }
  433. X    for (i = Border + (board.numcols * cell_height); i > 0; i -= cell_height) {
  434. X    XDrawLine(display, win, gc,
  435. X          i, Border, i, height - Border - ControlHeight); }
  436. X}
  437. X
  438. Xint slider_position;
  439. XDrawSlider(val) int val;
  440. X{
  441. X    int sp;
  442. X    char buf[10];
  443. X
  444. X    if (val < 0) val = configuration.bombcount;
  445. X    sp = ((SliderWidth - slider_width) * val) / configuration.maxbombs;
  446. X    XDrawRectangle(display, win, gc, Border,
  447. X           height - ControlHeight + (slider_height >> 1) - 2,
  448. X           SliderWidth, 4);
  449. X    XCopyArea(display, SliderIcon, win, gc, 0, 0,
  450. X          slider_width, slider_height,
  451. X          Border + sp, height - ControlHeight);
  452. X    sprintf(buf, "%d", val);
  453. X    XDrawString(display, win, gc, SliderWidth + (Border << 1),
  454. X        height - Border, buf, strlen(buf));
  455. X    slider_position = sp;
  456. X}
  457. X
  458. XUpdateSlider(val) int val;
  459. X{
  460. X    XSetForeground(display, gc, white());
  461. X    XFillRectangle(display, win, gc,
  462. X           Border + slider_position, height - ControlHeight,
  463. X           slider_width, slider_height);
  464. X    XFillRectangle(display, win, gc,
  465. X           (Border << 1) + SliderWidth, height - ControlHeight,
  466. X           50, ControlHeight);
  467. X    XSetForeground(display, gc, black());
  468. X    DrawSlider(val);
  469. X}
  470. X
  471. XShowBoard()
  472. X{
  473. X    int i, j;
  474. X    Cell *c;
  475. X
  476. X    DrawGrid();
  477. X    for (i = 0, c = board.cells; i < board.numrows; i++)
  478. X    for (j = 0; j < board.numcols; j++, c++)
  479. X        if (c->disp != Void) ShowCell(i, j, 0);
  480. X    DrawSlider(-1);
  481. X}    
  482. X
  483. XNewGame()
  484. X{
  485. X    game_state = playing;
  486. X    NewBoard();
  487. X    DrawGrid();
  488. X    PlaceBombs();
  489. X    ClaimSquare(0, 0);
  490. X    DrawSlider(-1);
  491. X}
  492. X
  493. XRule1()
  494. X{
  495. X    int b, v, n, pctr;
  496. X    Cell *c;
  497. X
  498. X    for (c = board.cells, pctr = board.numrows * board.numcols;
  499. X     pctr--; c++) {
  500. X    if (c->disp == Void) continue;
  501. X    b = v = n = 0;
  502. X    {ForEachNeighbor(c) {
  503. X        if (c2 == c) continue;
  504. X        n++;
  505. X        if (c2->disp == Bomb) b++;
  506. X        if (c2->disp == Void) v++; }}
  507. X    if (v == 0) continue;
  508. X    if (c->actual == b) {
  509. X        ForEachNeighbor(c)
  510. X        if (c2->disp == Void)
  511. X            ClaimSquare(i, j);
  512. X        return 1; }
  513. X    else if (c->actual == v + b) {
  514. X        ForEachNeighbor(c)
  515. X        if (c2->disp == Void)
  516. X            ShowCell(i, j, 1); /* it's a bomb */
  517. X        return 1; }}
  518. X    return 0;
  519. X}
  520. X
  521. XSolve()
  522. X{
  523. X    if (game_state != playing) {
  524. X    NewGame();
  525. X    XFlush(display);
  526. X    rest(5000); }
  527. X
  528. X    /* apply rule 1 when possible.  If rule 1 cannot make progress,
  529. X       apply rule 2.  If this fails, return. */
  530. X    while (game_state == playing && (Rule1() /* || Rule2() */)) {
  531. X    XFlush(display);
  532. X    rest(5000); }
  533. X}
  534. X
  535. X/* flag is false for move, true for bomb guess */
  536. XMouseSquare(pe, flag) XEvent *pe; int flag;
  537. X{
  538. X    int r, c;
  539. X    Cell *cell;
  540. X
  541. X    r = ((pe->xbutton.y - Border + cell_height) / cell_height) - 1;
  542. X    c = ((pe->xbutton.x - Border + cell_width) / cell_width) - 1;
  543. X    if (r < 0 || r >= board.numrows ||
  544. X    c < 0 || c >= board.numcols) {
  545. X    return 0; }
  546. X
  547. X    if (game_state != playing) return 1;
  548. X
  549. X    cell = &Square(board, r, c);
  550. X    if (cell->disp != Void && (cell->disp != Bomb || !flag)) return 1; 
  551. X
  552. X    if (flag) ShowCell(r, c, 1);
  553. X    else {
  554. X    ForEachNeighbor(cell)
  555. X        if (c2->disp >= 0) {
  556. X        ClaimSquare(r, c);
  557. X        return 1; }
  558. X    /* beep(); */ }
  559. X    return 1;
  560. X}
  561. X
  562. XMouseControl(evt) XEvent *evt;
  563. X{
  564. X    Window rt, kid;
  565. X    int rx, ry, x, y, nb, ov;
  566. X    unsigned int msk;
  567. X
  568. X    if (evt->xbutton.y > height - ControlHeight &&
  569. X    evt->xbutton.x < ControlWidth + Border) {
  570. X    ov = -1;
  571. X    nb = configuration.bombcount;
  572. X    while (!XCheckTypedEvent(display, ButtonRelease, evt)) {
  573. X        XQueryPointer(display, win, &rt, &kid, &rx, &ry, &x, &y, &msk);
  574. X        nb = ((x - Border) * configuration.maxbombs) /
  575. X        (SliderWidth- slider_width); 
  576. X        if (nb > configuration.maxbombs) nb = configuration.maxbombs;
  577. X        else if (nb < 0) nb = 0;
  578. X        if (ov == nb) continue;
  579. X        ov = nb;
  580. X        UpdateSlider(nb); }
  581. X    if (nb != configuration.bombcount) {
  582. X        configuration.bombcount = nb;
  583. X        NewGame(); }}
  584. X}
  585. X
  586. X#define BUFSIZE 4
  587. X
  588. XProcessEvents()
  589. X{
  590. X    XEvent pe;
  591. X    char buf[BUFSIZE];
  592. X
  593. X    while(1) {
  594. X    XNextEvent(display, &pe);
  595. X    switch(pe.type) {
  596. X      case Expose:
  597. X        XSetForeground(display, gc, black());
  598. X        if (game_state == initializing) NewGame();
  599. X        else ShowBoard();
  600. X        break;
  601. X      case ConfigureNotify: {
  602. X          int nr, nc;
  603. X          width = pe.xconfigure.width;
  604. X          height = pe.xconfigure.height;
  605. X          nr = (height - ControlHeight - (Border << 1)) / cell_height;
  606. X          nc = (width - (Border << 1)) / cell_width;
  607. X          if (configuration.xcells != nc || configuration.ycells != nr) {
  608. X          NewConfig(nr, nc);
  609. X          NewGame(); }}
  610. X        break;
  611. X      case KeyPress:        
  612. X        XLookupString((XKeyEvent *) &pe, buf, BUFSIZE, NULL, NULL);
  613. X        switch(tolower(buf[0])) {
  614. X          case 's':
  615. X        Solve();
  616. X        break;
  617. X          case 'q':
  618. X        XDestroyWindow(display, win);
  619. X        XFreeGC(display, gc);
  620. X        XCloseDisplay(display);
  621. X        exit(0);
  622. X          case 'n':
  623. X        NewGame();
  624. X        break; }
  625. X        break;
  626. X      case ButtonPress:
  627. X        switch(pe.xbutton.button) {
  628. X          case Button1:
  629. X          case Button2:
  630. X        if (!MouseSquare(&pe, pe.xbutton.button == Button2))
  631. X            MouseControl(&pe);
  632. X        break;
  633. X          case Button3:
  634. X        NewGame();
  635. X        break; }
  636. X        break;
  637. X      case ButtonRelease:
  638. X      case GraphicsExpose:
  639. X      case NoExpose:
  640. X      case ReparentNotify:
  641. X      case MapNotify:
  642. X      case UnmapNotify:
  643. X        break;
  644. X      default:
  645. X        printf("event %d.\n", pe.type); }
  646. X    XFlush(display); }
  647. X}
  648. X
  649. XBuildWindow(argc, argv) int argc; char *argv[];
  650. X{
  651. X    Pixmap pm;
  652. X    GC gc2;
  653. X    XColor color;
  654. X    XSizeHints hints;
  655. X
  656. X    IconIcon = XCreatePixmapFromBitmapData(display, rw(), icon_bits,
  657. X                       icon_width, icon_height, 1, 0, 1);
  658. X    BombIcon = XCreatePixmapFromBitmapData(display, rw(), bomb_bits,
  659. X                       cell_width - 1, cell_height - 1,
  660. X                       black(), white(), depth);
  661. X    OkIcon = XCreatePixmapFromBitmapData(display, rw(), ok_bits,
  662. X                       cell_width - 1, cell_height - 1,
  663. X                       black(), white(), depth);
  664. X    SliderIcon = XCreatePixmapFromBitmapData(display, rw(), slider_bits,
  665. X                         slider_width, slider_height,
  666. X                         black(), white(), depth);
  667. X
  668. X    width = WindowWidth(configuration.xcells);
  669. X    height = WindowHeight(configuration.ycells);
  670. X    win = XCreateSimpleWindow(display, rw(), 0, 0, width, height,
  671. X                  2, black(), white());
  672. X    hints.min_width = MINWIDTH;
  673. X    hints.min_height = MINHEIGHT;
  674. X    hints.width_inc = cell_width;
  675. X    hints.height_inc = cell_height;
  676. X    hints.flags = PMinSize | PResizeInc;
  677. X    XSetStandardProperties(display, win, "boom", "mines", IconIcon,
  678. X               argv, argc, &hints);
  679. X    XSelectInput(display, win,
  680. X         ExposureMask | ButtonPressMask | ButtonReleaseMask |
  681. X         KeyPressMask | StructureNotifyMask);
  682. X    gc = XCreateGC(display, win, 0, 0);
  683. X    XSetPlaneMask(display, gc, black());
  684. X    XMapWindow(display, win);
  685. X
  686. X}
  687. X
  688. XInstallDefaults()
  689. X{
  690. X    configuration.bombcount = 30;
  691. X    NewConfig(16, 16);
  692. X}
  693. X
  694. Xchar *ProgramName;
  695. X
  696. Xusage()
  697. X{
  698. X    fprintf(stderr, "\nusage: %s\n", ProgramName);
  699. X    exit(-1);
  700. X}
  701. X
  702. XParseOptions(argc, argv) int argc; char *argv[];
  703. X{
  704. X#if 0
  705. X    for (argc--, argv++; argc--; argv++) {
  706. X    if (**argv != '-') usage();
  707. X     else switch(*(*argv + 1)) {
  708. X      /* default: ignore */  }}
  709. X#endif
  710. X}
  711. X
  712. Xmain(argc, argv) int argc; char *argv[];
  713. X{
  714. X    int x, y;
  715. X    unsigned int width, height, bwidth;
  716. X    Window root;
  717. X
  718. X    ProgramName = *argv;
  719. X    board.cells = 0;
  720. X    game_state = initializing;
  721. X
  722. X    if (!(display = XOpenDisplay(NULL))) {
  723. X    perror("Cannot open display\n");
  724. X    exit(-1); }
  725. X
  726. X    if (!(XGetGeometry(display, rw(),
  727. X                       &root, &x, &y, &width, &height, &bwidth, &depth))) {
  728. X        fprintf(stderr, "Cannot get root window geometry\n");
  729. X        exit (-1); }
  730. X
  731. X    InstallDefaults();
  732. X    ParseOptions(argc, argv);
  733. X    BuildWindow(argc, argv);
  734. X
  735. X    srandom(time(0));
  736. X
  737. X    ProcessEvents();
  738. X}
  739. SHAR_EOF
  740. true || echo 'restore of mines.c failed'
  741. fi
  742. # ============= mines.man ==============
  743. if test -f 'mines.man' -a X"$1" != X"-c"; then
  744.     echo 'x - skipping mines.man (File already exists)'
  745. else
  746. sed 's/^X//' << 'SHAR_EOF' > 'mines.man' &&
  747. X.TH MINES 1L "1 Sep 1992"
  748. X.SH NAME
  749. Xmines \- play in a mine field
  750. X.SH SYNTAX
  751. X.B glcheck
  752. X.SH DESCRIPTION
  753. X
  754. XThe mines game is played on a grid.  Every cell of the grid either has
  755. Xa bomb on it, or it doesn't.  If you move onto a cell that has a bomb
  756. Xon it, you lose your leg.  If you move onto a cell that doesn't have a
  757. Xbomb on it, a integer between 0 and eight will be displayed, letting
  758. Xyou know how many bombs are in cells adjecent to the one you just
  759. Xmoved to.  (Adjecent, in this game, means one cell away in any
  760. Xdirection: up, down, left, right, or diagonal.)  Zeros are displayed
  761. Xas blanks, to avoid cluttering the display.  Additionally, since you
  762. Xcan obviously move in any direction from a zero, you automatically
  763. Xclaim the territory adjacent to cells which are blank.  You are only
  764. Xallowed to move to cells adjacent to ones you already own.  Cells you
  765. Xown are indicated by being printed in black; ones you don't own are in
  766. Xwhite.  The object of the game is to (eventually) claim the lower
  767. Xright hand corner of the grid.
  768. X
  769. XThe left button is for claiming new territory.  The right button
  770. Xstarts a new game.  The middle button displays a bomb.  This is a note
  771. Xto yourself about where you think a bomb is; there is no feedback as
  772. Xto whether you have guessed right or not.
  773. X
  774. XKeyboard entries: 'n' gives you a new game. 'q' quits the program.
  775. X's' cheats.  plays the game with the same information you have and
  776. Xsome very simple rules.  Doesn't win every winable game, but it does
  777. Xsave stupid mistakes.
  778. X
  779. XThe slider at the bottom of the window is for adjusting how many mines
  780. Xyou have in the grid.  You can also resize the window if you want to
  781. Xplay on a grid of a different size.  The maximum number of bombs you
  782. Xcan have is half the number of cells in the grid.
  783. SHAR_EOF
  784. true || echo 'restore of mines.man failed'
  785. fi
  786. # ============= patchlevel.h ==============
  787. if test -f 'patchlevel.h' -a X"$1" != X"-c"; then
  788.     echo 'x - skipping patchlevel.h (File already exists)'
  789. else
  790. sed 's/^X//' << 'SHAR_EOF' > 'patchlevel.h' &&
  791. X/* patchlevel.h */
  792. X
  793. X#define PATCHLEVEL 0
  794. SHAR_EOF
  795. true || echo 'restore of patchlevel.h failed'
  796. fi
  797. exit 0
  798. exit 0 # Just in case...
  799. -- 
  800.   // chris@IMD.Sterling.COM            | Send comp.sources.x submissions to:
  801. \X/  Amiga - The only way to fly!      |
  802.  "It's intuitively obvious to the most |    sources-x@imd.sterling.com
  803.   casual observer..."                  |
  804.