home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume15 / xbomb / part02 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  51.8 KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v15i049:  xbomb - minesweeper game with extra features, Part02/04
  5. Message-ID: <4224@master.CNA.TEK.COM>
  6. Date: 18 Jan 93 20:09:04 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2295
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1548
  11.  
  12. Submitted-by: johnh@FICUS.CS.UCLA.EDU (John Heidemann)
  13. Posting-number: Volume 15, Issue 49
  14. Archive-name: xbomb/Part02
  15. Environment: X11, Xlib
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 2 (of 4)."
  24. # Contents:  Imakefile actions.c bitmap.files infer_solver.c main.c
  25. #   pattern_solver.c score.c solver_io.c solvers.c
  26. # Wrapped by billr@saab on Mon Jan 18 12:03:06 1993
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'Imakefile'\"
  30. else
  31. echo shar: Extracting \"'Imakefile'\" \(4916 characters\)
  32. sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
  33. X
  34. X/**/#
  35. X/**/# xbomb imakefile
  36. X/**/#
  37. X/**/# @(#)Imakefile    1.16 (UCLA) 10/22/92
  38. X/**/#
  39. X
  40. X
  41. X
  42. X
  43. X/**/#
  44. X/**/# BEGIN: User customizable things.
  45. X/**/#
  46. X
  47. X/**/# You probably want to change where things go
  48. X         EXEDIR = /usr/dist/games
  49. X       XBLIBDIR = /usr/dist/games/lib/xbomb
  50. X      SCOREFILE = $(XBLIBDIR)/xbomb_score
  51. X      BITMAPDIR = $(XBLIBDIR)/bitmaps
  52. X/* solverdir will contain executables */
  53. X      SOLVERDIR = $(XBLIBDIR)/solvers
  54. X
  55. X/**/# You may want to make things not-setuid.
  56. X/**/# If so, scores must be world-writable.
  57. X     XBOMBFLAGS = -o games -m 4755
  58. X    SOLVERFLAGS = -o games
  59. X    BITMAPFLAGS = -o games -m 644
  60. X     SCOREFLAGS = -o games -m 644
  61. X    CDEBUGFLAGS = -g
  62. X
  63. X/*
  64. X * You may not have perl, or wish to install the perl solvers.
  65. X * If you don't have perl, comment out the next line in the Imakefile.
  66. X */
  67. X#define INSTALLPERLSOLVERS 1
  68. X           PERL = /usr/local/bin/perl
  69. X
  70. X/**/# Your man pages may have funny endings.
  71. X GAMESMANSUFFIX = 6
  72. X
  73. X/**/# Things for various kinds of system brain-damange.
  74. X/*
  75. X * If your make doesn't have +=, uncomment this line.
  76. X * (It seems like this should be in Imake somewhere.)
  77. X * Or get GNU Make or pmake, a real persons make.
  78. X */
  79. X/* #define StupidMakeLacksPlusEquals */
  80. X
  81. X/**/# If your C libraries lack strdup, define LACKS_STRDUP.
  82. X/**/# (It's such a hard thing to QA, I can see why they don't provide it.)
  83. X/* Uncomment the following line, if necessary. */
  84. X/* #define StupidLibcLacksStrdup */
  85. X
  86. X/**/#
  87. X/**/# END: User customizable things.
  88. X/**/#
  89. X
  90. X
  91. X
  92. X#ifdef StupidLibcLacksStrdup
  93. X#define ProvideStrdup -DLACKS_STRDUP
  94. X#else
  95. X#define ProvideStrdup
  96. X#endif
  97. X
  98. XDEFINES = -D_PATH_SCORE='"$(SCOREFILE)"' -D_PATH_SOLVERS='"$(SOLVERDIR)"' -D_PATH_BITMAPS='"$(BITMAPDIR)"' ProvideStrdup
  99. X
  100. X
  101. X/*
  102. X * Some helpful targets
  103. X */
  104. X#ifdef StupidMakeLacksPlusEquals
  105. X#define SharFiles(files)
  106. X#else
  107. X#define SharFiles(files) TOSHAR += files
  108. X#endif
  109. X
  110. X#define SolverTarget(EXE,OBJS)                        @@\
  111. X                                    @@\
  112. XAllTarget(EXE)                                @@\
  113. X                                    @@\
  114. XNormalProgramTarget(EXE,OBJS solver_io.o,/**/,/**/,/**/)        @@\
  115. XInstallProgramWithFlags(EXE,$(SOLVERDIR),$(SOLVERFLAGS))        @@\
  116. X                                    @@\
  117. Xclean::                                    @@\
  118. X    $(RM) $(PROGRAM)
  119. X
  120. X#define PerlifyScript(src,dest)                        @@\
  121. X
  122. X
  123. X#define PerlSolverTarget(exe)                        @@\
  124. X                                    @@\
  125. Xexe.script: exe                                @@\
  126. X    sed "s;/usr/.*/perl;$(PERL);" <exe >exe.script            @@\
  127. X                                    @@\
  128. XSharFiles(exe)                                @@\
  129. X                                    @@\
  130. XInstallScript(exe,$(SOLVERDIR))
  131. X
  132. X/*
  133. X * We have our own InstallManPage so that we can put things
  134. X * in the games directory.  What a pain.  Don't those people
  135. X * at MIT play any games?
  136. X */
  137. X#define    InstallGamesManPage(file)                    @@\
  138. Xinstall.man:: file.man                            @@\
  139. X    MakeDir($(DESTDIR)$(OURMANSUFFIX))                @@\
  140. X    $(INSTALL) -c $(INSTMANFLAGS) file.man $(MANSOURCEPATH)$(GAMESMANSUFFIX)/file.$(GAMESMANSUFFIX)
  141. X
  142. X
  143. X/*
  144. X * The real work
  145. X */
  146. X
  147. XSRCS = $(XBOMB_SRCS) pattern_solver.c forced_solver.c prob_solver.c \
  148. X    solver_io.c infer_solver.c
  149. XSharFiles($(SRCS))
  150. X
  151. XHFILES = patchlevel.h solver_io.h xbomb.h icon.bit
  152. XSharFiles($(HFILES))
  153. X
  154. XMANPAGE = xbomb.man
  155. X
  156. XSharFiles($(MANPAGE))
  157. X
  158. X
  159. X/**/#
  160. X/**/# xbomb is done by hand
  161. X/**/#
  162. XXBOMB_SRCS = main.c map.c applications.c actions.c graphics.c solvers.c score.c
  163. XXBOMB_OBJS = main.o map.o applications.o actions.o graphics.o solvers.o score.o
  164. X
  165. XAllTarget(xbomb)
  166. XNormalProgramTarget(xbomb,$(XBOMB_OBJS),/**/,/**/,$(XLIB))
  167. XInstallProgramWithFlags(xbomb,$(EXEDIR),$(XBOMBFLAGS))
  168. X
  169. XInstallGamesManPage(xbomb)
  170. X
  171. Xclean::
  172. X    $(RM) xbomb
  173. X
  174. X
  175. X/**/#
  176. X/**/# solvers follow
  177. X/**/#
  178. XSolverTarget(pattern_solver,pattern_solver.o)
  179. X
  180. XSolverTarget(forced_solver,forced_solver.o)
  181. X
  182. XSolverTarget(prob_solver,prob_solver.o)
  183. X
  184. XSolverTarget(infer_solver,infer_solver.o)
  185. X
  186. X#ifdef INSTALLPERLSOLVERS
  187. XPerlSolverTarget(statistics)
  188. X
  189. XPerlSolverTarget(debug_solver)
  190. X#endif
  191. X
  192. X
  193. X/**/#
  194. X/**/# administrative stuff
  195. X/**/#
  196. X
  197. XDependTarget()
  198. X
  199. X/**/# scorefile installation
  200. Xinstall.scorefile:
  201. X    install  $(SCOREFLAGS) /dev/null $(SCOREFILE)
  202. X
  203. Xinstall:: install.scorefile
  204. X
  205. X/**/# bitmap installation
  206. X
  207. Xinstall:: install.bitmaps
  208. X
  209. X/* This bogosity is my fault.  -JSH */
  210. Xinstall.bitmaps: bitmap.files
  211. X    MakeDir($(BITMAPDIR))
  212. X    for i in `cat bitmap.files`; \
  213. X    do \
  214. X        j=`echo $$i|sed 's:^./bitmaps:./:'`; \
  215. X        if [ "$$j" != "./" ]; then \
  216. X            if [ -d $$i ]; then \
  217. X                echo Installing dir $$i...; \
  218. X                test -d $(BITMAPDIR)/$$j || $(MKDIRHIER) $(BITMAPDIR)/$$j; \
  219. X            else \
  220. X                echo Installing bitmap $$i...; \
  221. X                $(INSTALL) -c $(BITMAPFLAGS) $$i $(BITMAPDIR)/`dirname $$j`; \
  222. X            fi; \
  223. X        fi; \
  224. X    done
  225. X    @echo Bitmaps installed.
  226. X
  227. X/**/#
  228. X/**/# distribution
  229. X/**/#
  230. X
  231. XSharFiles(README TODO Imakefile Makefile.std)
  232. X
  233. Xbitmap.files:
  234. X    find ./bitmaps \( -name \*.bit -o -type d \) -print >bitmap.files
  235. X
  236. X#ifdef StupidMakeLacksPlusEquals
  237. Xkit:
  238. X    @echo 'Your make lacks +=, so make kit is disabled.'
  239. X
  240. Xshar:
  241. X    @echo 'Your make lacks +=, so make shar is disabled.'
  242. X#else
  243. Xkit: Makefile.std
  244. X    makekit $(TOSHAR) `cat bitmap.files`
  245. X
  246. Xshar: Makefile.std
  247. X    shar $(TOSHAR) `cat bitmap.files` >xbomb.shar
  248. X#endif
  249. X
  250. XMakefile.std:
  251. X    cp Makefile Makefile.std
  252. X
  253. END_OF_FILE
  254. if test 4916 -ne `wc -c <'Imakefile'`; then
  255.     echo shar: \"'Imakefile'\" unpacked with wrong size!
  256. fi
  257. # end of 'Imakefile'
  258. fi
  259. if test -f 'actions.c' -a "${1}" != "-c" ; then 
  260.   echo shar: Will not clobber existing file \"'actions.c'\"
  261. else
  262. echo shar: Extracting \"'actions.c'\" \(3046 characters\)
  263. sed "s/^X//" >'actions.c' <<'END_OF_FILE'
  264. X
  265. X/*
  266. X * actions.c
  267. X * @(#)actions.c    1.4 (UCLA) 10/15/92
  268. X *
  269. X * xbomb is Copyright (C) 1992 by Matthew Merzbacher, Los Angeles, CA.
  270. X * All rights reserved.  Permission is granted to freely distribute
  271. X * this as long as this copyright message is retained intact.
  272. X * Permission to distribute this as part of a commerical product
  273. X * requires explicit permission of the author.
  274. X *
  275. X */
  276. X
  277. X#include "xbomb.h"
  278. X
  279. X
  280. Xvoid
  281. Xmove_somewhere(column, row)
  282. Xint column, row;
  283. X{
  284. X    if (map[column][row].status == EMPTY) {
  285. X        if (map[column][row].flag) numflags++;
  286. X        map[column][row].status = KEMPTY;
  287. X        numempty--;
  288. X        if (shouldfollow(column, row)) {
  289. X            if (follow(column,row))
  290. X                dead = 1;
  291. X        };
  292. X    }
  293. X    if (map[column][row].status == BOMB)
  294. X        dead = 1;
  295. X}
  296. X
  297. Xvoid
  298. Xplace_flag(column, row)
  299. Xint column, row;
  300. X{
  301. X    if ((map[column][row].status == EMPTY) ||
  302. X        (map[column][row].status == BOMB)) {
  303. X        if (map[column][row].flag) {
  304. X            numflags++;
  305. X            map[column][row].flag = 0;
  306. X        }
  307. X        else {
  308. X            numflags--;
  309. X            map[column][row].flag = 1;
  310. X        }
  311. X    }
  312. X}
  313. X
  314. X
  315. Xint
  316. Xplace_em()
  317. X{
  318. X    int x, y, ret = 0;
  319. X    
  320. X    for (x = 1; x <= width; x++)
  321. X        for (y = 1; y <= height; y++) {
  322. X            map[x][y].neighbor_unknowns = 0;
  323. X            apply_neighbor(x,y,apply_inc_if_unknown,&map[x][y].neighbor_unknowns);
  324. X        };
  325. X    
  326. X    for (x = 1; x <= width; x++)
  327. X        for (y = 1; y <= height; y++)
  328. X            if (map[x][y].status==KEMPTY && 
  329. X                map[x][y].neighbors - map[x][y].neighbor_kbombs ==
  330. X                map[x][y].neighbor_unknowns) {
  331. X                ret |= apply_neighbor(x,y,apply_flag_if_unknown, NULL);
  332. X            };
  333. X    return(ret);
  334. X}
  335. X
  336. Xint scan_em()
  337. X{
  338. X    int c, r, ret = 0;
  339. X    
  340. X    for (c = 1; c <= width; c++)
  341. X        for (r = 1; r <= height; r++)
  342. X            if (map[c][r].flag && 
  343. X                map[c][r].status == EMPTY) {
  344. X                dead = 1;
  345. X                return(0);
  346. X            }
  347. X    
  348. X    for (c = 1; c <= width; c++)
  349. X        for (r = 1; r <= height; r++)
  350. X            if (map[c][r].flag && map[c][r].status == BOMB) {
  351. X                map[c][r].status = KBOMB;
  352. X                ret |= apply_neighbor(c,r,apply_add_neighbor_kbombs, (void*)1);
  353. X                putpix(c,r);
  354. X            }
  355. X    return(ret);
  356. X}
  357. X
  358. Xshouldfollow(x, y)
  359. X    int x, y;
  360. X{
  361. X    return (map[x][y].neighbors == 0 ||
  362. X        (betterfollow && map[x][y].neighbors - map[x][y].neighbor_kbombs == 0));
  363. X}
  364. X
  365. Xfollow(c,r)
  366. X    int c, r;
  367. X{
  368. X    int x, y;
  369. X    
  370. X    for (x = c-1; x <= c+1; x++)
  371. X        for (y = r-1; y <= r+1; y++) {
  372. X            if (map[x][y].status == EMPTY) {
  373. X                if (map[x][y].flag) numflags++;
  374. X                map[x][y].status = KEMPTY;
  375. X                numempty--;
  376. X                putpix(x, y);
  377. X                if (shouldfollow(x,y))
  378. X                    follow(x,y);
  379. X            }
  380. X        }
  381. X    return 0;   /* OK */
  382. X}
  383. X
  384. X
  385. X
  386. X
  387. Xint
  388. Xplace_random(what) 
  389. X    int what;
  390. X{
  391. X    int numct, row, column;
  392. X
  393. X    numct = (numempty + numflags - 1);
  394. X    if (numct == 0)    /* already solved */
  395. X        return(1);
  396. X
  397. X    numct = lrand48()%numct + 1;
  398. X
  399. X    for (row = 1; row <= height; row++) {
  400. X        for (column = 1; column <= width; column++) {
  401. X              if (is_unknown(map[column][row].status)) numct--;
  402. X            if (numct == 0) {
  403. X                if (what == BOMB) place_flag(column, row);
  404. X                else if (what == EMPTY) move_somewhere(column, row);
  405. X                else bail("invalid what in place_random");
  406. X
  407. X                putpix(column,row);
  408. X                return(0);
  409. X                }
  410. X            }
  411. X        }
  412. X    fprintf(stderr, "This message shouldn't happen (but it does)!\n");
  413. X    return(0);
  414. X}
  415. X
  416. END_OF_FILE
  417. if test 3046 -ne `wc -c <'actions.c'`; then
  418.     echo shar: \"'actions.c'\" unpacked with wrong size!
  419. fi
  420. # end of 'actions.c'
  421. fi
  422. if test -f 'bitmap.files' -a "${1}" != "-c" ; then 
  423.   echo shar: Will not clobber existing file \"'bitmap.files'\"
  424. else
  425. echo shar: Extracting \"'bitmap.files'\" \(1168 characters\)
  426. sed "s/^X//" >'bitmap.files' <<'END_OF_FILE'
  427. X./bitmaps
  428. X./bitmaps/old
  429. X./bitmaps/old/bomb.bit
  430. X./bitmaps/old/ebomb.bit
  431. X./bitmaps/old/empty.bit
  432. X./bitmaps/old/flag.bit
  433. X./bitmaps/old/icon.bit
  434. X./bitmaps/old/known0.bit
  435. X./bitmaps/old/known1.bit
  436. X./bitmaps/old/known2.bit
  437. X./bitmaps/old/known3.bit
  438. X./bitmaps/old/known4.bit
  439. X./bitmaps/old/known5.bit
  440. X./bitmaps/old/known6.bit
  441. X./bitmaps/old/known7.bit
  442. X./bitmaps/old/known8.bit
  443. X./bitmaps/old/known9.bit
  444. X./bitmaps/roman
  445. X./bitmaps/roman/known0.bit
  446. X./bitmaps/roman/known1.bit
  447. X./bitmaps/roman/known2.bit
  448. X./bitmaps/roman/known3.bit
  449. X./bitmaps/roman/known4.bit
  450. X./bitmaps/roman/known5.bit
  451. X./bitmaps/roman/known6.bit
  452. X./bitmaps/roman/known7.bit
  453. X./bitmaps/roman/known8.bit
  454. X./bitmaps/roman/known9.bit
  455. X./bitmaps/standard
  456. X./bitmaps/standard/blank.bit
  457. X./bitmaps/standard/bomb.bit
  458. X./bitmaps/standard/ebomb.bit
  459. X./bitmaps/standard/empty.bit
  460. X./bitmaps/standard/flag.bit
  461. X./bitmaps/standard/known0.bit
  462. X./bitmaps/standard/known1.bit
  463. X./bitmaps/standard/known2.bit
  464. X./bitmaps/standard/known3.bit
  465. X./bitmaps/standard/known4.bit
  466. X./bitmaps/standard/known5.bit
  467. X./bitmaps/standard/known6.bit
  468. X./bitmaps/standard/known7.bit
  469. X./bitmaps/standard/known8.bit
  470. X./bitmaps/standard/known9.bit
  471. X./bitmaps/standard/think.bit
  472. END_OF_FILE
  473. if test 1168 -ne `wc -c <'bitmap.files'`; then
  474.     echo shar: \"'bitmap.files'\" unpacked with wrong size!
  475. fi
  476. # end of 'bitmap.files'
  477. fi
  478. if test -f 'infer_solver.c' -a "${1}" != "-c" ; then 
  479.   echo shar: Will not clobber existing file \"'infer_solver.c'\"
  480. else
  481. echo shar: Extracting \"'infer_solver.c'\" \(7830 characters\)
  482. sed "s/^X//" >'infer_solver.c' <<'END_OF_FILE'
  483. X
  484. X/*
  485. X * infer_solver
  486. X * %W% (UCLA) %G%
  487. X *
  488. X * xbomb is Copyright (C) 1992 by Matthew Merzbacher, Los Angeles, CA.
  489. X * All rights reserved.  Permission is granted to freely distribute
  490. X * this as long as this copyright message is retained intact.
  491. X * Permission to distribute this as part of a commerical product
  492. X * requires explicit permission of the author.
  493. X *
  494. X */
  495. X
  496. X#include <stdio.h>
  497. X#include <sys/file.h>
  498. X#include <sys/wait.h>
  499. X#include "solver_io.h"
  500. X
  501. X#ifndef _PATH_SOLVERS
  502. X#ifdef DEBUG
  503. X#define     _PATH_SOLVERS     "."
  504. X#else
  505. X#define     _PATH_SOLVERS     "/usr/dist/games/lib/xbomb"
  506. X#endif
  507. X#endif
  508. X
  509. X
  510. X#define KNOWN(s) ((s == empty) || (s == bomb) || (s == edge))
  511. X
  512. Xstruct point {
  513. X    int x, y;
  514. X    };
  515. X
  516. Xstruct neighbor_set {
  517. X    int size;
  518. X    struct point points[8];
  519. X    };
  520. X
  521. Xstruct neighbor_set mymap[MAXWIDTH][MAXHEIGHT];
  522. X
  523. Xstruct act {
  524. X        int x, y;
  525. X    char action;
  526. X    struct act *next;
  527. X      };
  528. X
  529. Xstruct act *acts[8];
  530. X
  531. Xint solver_pid = 0;
  532. XFILE *solver_rfps, *solver_wfps;
  533. X
  534. X
  535. Xadd_em(i, x, y, action)
  536. Xint i, x, y;
  537. Xchar action;
  538. X{
  539. X        struct act *newact;
  540. X
  541. X    newact = (struct act *) (malloc(sizeof(struct act)));
  542. X    
  543. X    newact->x = x;
  544. X    newact->y = y;
  545. X    newact->action = action;
  546. X    newact->next = acts[i];
  547. X    acts[i] = newact;
  548. X#ifdef DEBUG
  549. X    fprintf(stderr,"    adding... %d %d %c\n", x, y, action);
  550. X#endif DEBUG
  551. X      }
  552. X
  553. Xcompare_em(n) 
  554. Xint n;
  555. X{
  556. X      int i;
  557. X      struct act *cur, *cp;
  558. X     int same, found;
  559. X  
  560. X    for (cur = acts[0]; cur != NULL; cur = cur->next) {
  561. X            same = 1;
  562. X              for (i = 1; same && (i < n); i++) {
  563. X            found = 0;
  564. X                  for (cp = acts[i]; !found && cp != NULL; cp = cp->next) {
  565. X                      if ((cur->x == cp->x)  &&
  566. X                              (cur->y == cp->y)  &&
  567. X                            (cur->action == cp->action)) found = 1;
  568. X                }
  569. X            same = found;
  570. X            }
  571. X          if (same) 
  572. X            fprintf(stderr, "%d %d %c\n", cur->x, cur->y, cur->action);
  573. X        }
  574. X    for (i = 0; i < n; i++) {
  575. X          cur = acts[i]; 
  576. X        while (cur != NULL) {
  577. X            cp = cur->next;
  578. X            free(cur);
  579. X            cur = cp;
  580. X            }
  581. X        }
  582. X}
  583. X    
  584. X
  585. X    
  586. Xint
  587. Xapply_empty_if_unknown(x, y, ptr)
  588. X    int x, y;
  589. X    void *ptr;
  590. X{
  591. X    if (map[x][y].status==unknown) {
  592. X        printf ("%d %d e\n", x, y);
  593. X    };
  594. X}
  595. X
  596. Xint 
  597. Xapply_flag_if_unknown(x, y, ptr)
  598. X    int x, y;
  599. X    void *ptr;
  600. X{
  601. X    if (map[x][y].status==unknown) {
  602. X        map[x][y].status = bomb_flag;
  603. X        printf ("%d %d f\n", x, y);
  604. X        return(1);
  605. X    };
  606. X    return(0);
  607. X}
  608. X
  609. Xint
  610. Xrun4(x, y, dx, dy)
  611. X{
  612. X    int ct = 0;
  613. X
  614. X    if (map[x][y].status == unknown) ct++;
  615. X    if (map[x+dx][y].status == unknown) ct++;
  616. X    if (map[x][y+dy].status == unknown) ct++;
  617. X    if (map[x+dx][y+dy].status == unknown) ct++;
  618. X
  619. X    return(ct);
  620. X}
  621. X
  622. Xvoid
  623. Xadd_neighbor(x, y, dx, dy)
  624. Xint x, y, dx, dy;
  625. X{
  626. X    int s;
  627. X
  628. X    s = mymap[x][y].size;
  629. X    mymap[x][y].points[s].x = x+dx;
  630. X    mymap[x][y].points[s].y = y+dy;
  631. X    mymap[x][y].size ++;
  632. X    }
  633. X
  634. Xvoid
  635. Xmake_neighbors(status, x, y, dx, dy)
  636. Xint status, x, y;
  637. X{
  638. X    int i, j, fix;
  639. X
  640. X    for (j = 0; j < mymap[x+dx][y+dy].size; j++) {
  641. X        fix = 1;
  642. X        for (i = 0; fix && (i < mymap[x][y].size); i++) {
  643. X            if ((mymap[x][y].points[i].x == mymap[x+dx][y+dy].points[j].x) &&
  644. X                (mymap[x][y].points[i].y == mymap[x+dx][y+dy].points[j].y)) {
  645. X                fix = 0;
  646. X                }
  647. X            }
  648. X        if (fix) {
  649. X            printf ("%d %d %c\n", mymap[x+dx][y+dy].points[j].x, mymap[x+dx][y+dy].points[j].y, (status == empty)?'m':'f');
  650. X            }
  651. X        }
  652. X}
  653. X
  654. Xint
  655. Xsubset_of(x1, y1, x2, y2)
  656. Xint x1, y1, x2, y2;
  657. X{
  658. X    int i, j, found;
  659. X
  660. X    for (i = 0; i < mymap[x1][y1].size; i++) {
  661. X        found = 0;
  662. X        for (j = 0; !found && j < mymap[x2][y2].size; j++) {
  663. X            if ((mymap[x1][y1].points[i].x == mymap[x2][y2].points[j].x) &&
  664. X                (mymap[x1][y1].points[i].y == mymap[x2][y2].points[j].y))
  665. X                found = 1;
  666. X                }
  667. X        if (!found) return(0);
  668. X        }
  669. X    
  670. X    return(1);
  671. X    }
  672. X
  673. Xint
  674. Xplace_em()
  675. X{
  676. X    int x, y, i, ret = 0, dx, dy, nx, ny;
  677. X
  678. X    for (x = 1; x <= width; x++)
  679. X        for (y = 1; y <= height; y++) {
  680. X            mymap[x][y].size = 0;
  681. X            if (map[x][y].status == empty &&
  682. X                map[x][y].ted >= 1)
  683. X                for (dx = -1; dx <= 1; dx++)
  684. X                    for (dy = -1; dy <= 1; dy++)
  685. X                        if (((dx != 0) || (dy != 0)) &&
  686. X                            (! KNOWN(map[x+dx][y+dy].status)))
  687. X                            add_neighbor(x, y, dx, dy);
  688. X                        }
  689. X
  690. X
  691. X    for (x = 1; x <= width; x++)
  692. X        for (y = 1; y <= height; y++) {
  693. X            if (map[x][y].status == empty && 
  694. X                map[x][y].ted >= 1) 
  695. X                {
  696. X#ifdef DEBUG
  697. X                fprintf(stderr, "Inferring %d, %d\n", x, y);
  698. X#endif DEBUG
  699. X                    for (i = 0; i < mymap[x][y].size; i++) {
  700. X#ifdef DEBUG
  701. X                      fprintf(stderr," start of %d\n", i);
  702. X#endif DEBUG
  703. X                      acts[i] = NULL;
  704. X                      nx = mymap[x][y].points[i].x;
  705. X                      ny = mymap[x][y].points[i].y;
  706. X                      map[nx][ny].status = bomb;
  707. X                      invoke_solver(i);
  708. X                      map[nx][ny].status = empty;
  709. X#ifdef DEBUG
  710. X                      fprintf(stderr," end of %d\n", i);
  711. X#endif DEBUG
  712. X                    }
  713. X                compare_em(mymap[x][y].size);
  714. X                  }
  715. X              }
  716. X    
  717. X    return(ret);
  718. X           
  719. X      }
  720. X
  721. X
  722. X
  723. X
  724. Xvoid
  725. Xrevoke_solvers()   /* Kill them ALL!  Yeah!  Slaughter! */
  726. X{
  727. X    int i;
  728. X
  729. X        if (solver_pid) {
  730. X            fclose(solver_rfps);
  731. X            fclose(solver_wfps);
  732. X        };
  733. X}
  734. X
  735. X
  736. Xvoid
  737. Xdump_map(fp)
  738. X    FILE *fp;
  739. X{
  740. X    int x, y;
  741. X    char ch;
  742. X
  743. X    fprintf (fp, "%d\n", numbombs);
  744. X    for (y = 1; y <= height; y++) {
  745. X        for (x = 1; x <= width; x++) {
  746. X            if (map[x][y].status == bomb)
  747. X                ch = 'X';
  748. X            else if (map[x][y].status == bomb_flag)
  749. X                ch = 'f';
  750. X            else if (! KNOWN(map[x][y].status))
  751. X                ch = '.';
  752. X            else ch = map[x][y].neighbors + '0';
  753. X            fprintf (fp, "%c", ch);
  754. X        };
  755. X        fprintf (fp, "\n");
  756. X    };
  757. X    fprintf (fp, "\n");   /* blank line==end of dataset */
  758. X    fflush(fp);
  759. X}
  760. X
  761. X
  762. Xvoid
  763. Xreap_children()
  764. X{
  765. X    int pid, status;
  766. X    int i;
  767. X
  768. X    for (;;) {
  769. X        pid = waitpid(-1, &status, WNOHANG);
  770. X        if (pid==-1 || pid==0) return;  /* no children */
  771. X
  772. X        if (solver_pid == pid) {
  773. X            fclose(solver_rfps);
  774. X            fclose(solver_wfps);
  775. X            solver_rfps = solver_wfps = NULL;
  776. X            solver_pid = 0;
  777. X            break;
  778. X            };
  779. X    }
  780. X}
  781. X
  782. X
  783. Xint
  784. Xinvoke_solver(i)
  785. X        int i;
  786. X{
  787. X    int subproc;
  788. X    int rp[2], wp[2];
  789. X    FILE *rfp, *wfp;
  790. X    int ret;
  791. X    int error, status;
  792. X
  793. X    reap_children();
  794. X
  795. X    if (solver_pid == 0) {
  796. X        if (-1==pipe(rp))
  797. X            bail("pipe");
  798. X        if (-1==pipe(wp))
  799. X            bail("pipe");
  800. X        if (0==(subproc=fork())) {
  801. X            if (-1==dup2 (wp[0], 0))
  802. X                bail ("dup2-a");
  803. X            if (-1==dup2 (rp[1], 1))
  804. X                bail ("dup2-b");
  805. X            close (rp[0]);
  806. X            close (rp[1]);
  807. X            close (wp[0]);
  808. X            close (wp[1]);
  809. X            /*
  810. X             * Plug the security hole.
  811. X             */
  812. X            if (-1==seteuid(getuid()))
  813. X                bail("seteuid");
  814. X            if (-1==setegid(getgid()))
  815. X                bail("setegid");
  816. X            if (-1==exec_solver("pattern_solver")) {
  817. X                char tmps[80];
  818. X                sprintf (tmps, "cannot invoke solver\n");
  819. X                bail (tmps);
  820. X            };
  821. X            /*NOTREACHED*/
  822. X        };
  823. X        if (subproc == -1)
  824. X            bail ("fork");
  825. X        solver_pid = subproc;
  826. X        close (rp[1]);
  827. X        close (wp[0]);
  828. X        solver_rfps = fdopen (rp[0], "r");
  829. X        solver_wfps = fdopen (wp[1], "w");
  830. X    };
  831. X    dump_map(solver_wfps);
  832. X    ret = read_response(i, solver_rfps);
  833. X    reap_children();
  834. X    return(ret);
  835. X}
  836. X
  837. X
  838. X
  839. Xint
  840. Xread_response(i, fp)
  841. X        FILE *fp;
  842. X        int i;
  843. X{
  844. X        int x, y, ret = 0;
  845. X        char action;
  846. X#define SLEN 80
  847. X        char s[SLEN];
  848. X
  849. X        for (;;) {
  850. X                if (NULL==fgets (s, SLEN, fp))
  851. X                        break;
  852. X                if (s[0] == 0 || s[0] =='\n')
  853. X                        break;
  854. X                if (3 != sscanf (s, "%d %d %c", &x, &y, &action))
  855. X                        break;
  856. X                ret = 1;
  857. X                
  858. X        add_em(i, x, y, action);
  859. X                };
  860. X                
  861. X
  862. X        return(ret);
  863. X
  864. X}
  865. X
  866. Xexec_solver(s)
  867. X        char *s;
  868. X{
  869. X        char tmps[512];
  870. X        int error;
  871. X        if (-1==(error = execl (s, s, NULL))) {
  872. X                sprintf (tmps, "%s/%s", _PATH_SOLVERS, s);
  873. X                error = execl(tmps,tmps,NULL);
  874. X                if (error)
  875. X                        fprintf (stderr, "Solver not found as either %s or %s.\n", s, tmps);
  876. X        };
  877. X        return error;
  878. X}
  879. X
  880. X
  881. X    
  882. Xmain()
  883. X{
  884. X    int ret; int x, y;
  885. X
  886. X    while (!feof(stdin)) {
  887. X        read_data();
  888. X        if (counts[bomb_flag])
  889. X            exit (1);   /* we don't allow flags, yet */
  890. X        calc_em();
  891. X        ret = place_em();
  892. X        printf ("\n");   /* terminate output */
  893. X        fflush(stdout);
  894. X    };
  895. X    exit (0);
  896. X}
  897. END_OF_FILE
  898. if test 7830 -ne `wc -c <'infer_solver.c'`; then
  899.     echo shar: \"'infer_solver.c'\" unpacked with wrong size!
  900. fi
  901. # end of 'infer_solver.c'
  902. fi
  903. if test -f 'main.c' -a "${1}" != "-c" ; then 
  904.   echo shar: Will not clobber existing file \"'main.c'\"
  905. else
  906. echo shar: Extracting \"'main.c'\" \(9883 characters\)
  907. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  908. X
  909. X/*
  910. X * main.c
  911. X * @(#)main.c    1.32 (UCLA) 10/22/92
  912. X *
  913. X * xbomb is Copyright (C) 1992 by Matthew Merzbacher, Los Angeles, CA.
  914. X * All rights reserved.  Permission is granted to freely distribute
  915. X * this as long as this copyright message is retained intact.
  916. X * Permission to distribute this as part of a commerical product
  917. X * requires explicit permission of the author.
  918. X *
  919. X */
  920. X
  921. X#include "xbomb.h"
  922. X#include "patchlevel.h"
  923. X
  924. Xint    dead = 0,            /* true if you won or lost */
  925. X    numflags,     /* number of bombs left to place */
  926. X    emptylen,     /* number of places reserved for printing numflags */
  927. X    numempty,     /* number of empty spaces */
  928. X    button,     /* current button pressed */
  929. X    shifted,    /* was the shift key down? */
  930. X    numbombs = -1,     /* number of bombs placed */
  931. X    width = -1,    /* width of puzzle */
  932. X    height = -1,     /* height of puzzle */
  933. X    ted = -1,    /* ted mode = reduce nums when bomb detected */
  934. X    onlyprint = -1;    /* print scores, but don't update 'em */
  935. X    randomE = -1,    /* random number of empties */
  936. X    randomB = -1,    /* random number of bombs */
  937. X    seed = -1;    /* seed to pass to srand48 */
  938. X    showscore = -1,    /* should the score be shown? */
  939. X    betterfollow = -1,    /* use advanced following algorithm */
  940. X    startwithzero = -1,    /* start with a (almost) guaranteed zero */
  941. X    playagain = -1;         /* should we automatically restart */
  942. X
  943. X#define MAX_SOLVERS 10
  944. Xchar *solvers[MAX_SOLVERS];
  945. XFILE *solver_rfps[MAX_SOLVERS], *solver_wfps[MAX_SOLVERS];
  946. Xint solver_pids[MAX_SOLVERS];
  947. X
  948. X
  949. X#define is_bomb(s)  ((s == BOMB)?1:0)
  950. X#define is_bomb_or_flag(s) ((s==BOMB || s==FLAG)?1:0)
  951. X#define is_unknown(s) ((s==BOMB || s==EMPTY)?1:0)
  952. X
  953. Xstruct cell map[MAXWIDTH+2][MAXHEIGHT+2];
  954. X
  955. X
  956. Xvoid
  957. Xcleanup()
  958. X{
  959. X    cleanup_pixmaps();
  960. X    revoke_solvers();
  961. X}
  962. X
  963. X
  964. Xvoid
  965. Xfinish()
  966. X{
  967. X    cleanup();
  968. X    log_score();
  969. X
  970. X    exit(0);
  971. X}
  972. X
  973. X
  974. Xvoid
  975. Xbail(s)
  976. X    char *s;
  977. X{
  978. X    perror (s);
  979. X    cleanup();
  980. X    exit(1);
  981. X}
  982. X
  983. X
  984. X#ifdef LACKS_STRDUP
  985. Xchar *
  986. Xstrdup(s)
  987. X    char *s;
  988. X{
  989. X    char *ss = NULL;
  990. X    if (s) {
  991. X        if (ss = malloc(strlen(s)+1)) {
  992. X            strcpy(ss, s);
  993. X        };
  994. X    };
  995. X    return ss;
  996. X}
  997. X#endif
  998. X
  999. X
  1000. X
  1001. Xstatic char *help_message[] = {
  1002. X    "where options include:",
  1003. X    "    -d host:display        Specify which X server to use",
  1004. X    "    -g +x+y                Upper left-hand corner of puzzle",
  1005. X    "    -fg color              Color for bombs and numbers",
  1006. X    "    -bg color              Color for background",
  1007. X    "    -bd color              Color for border",
  1008. X    "    -bw width              Width of border (in pixels)",
  1009. X    " ",
  1010. X    "    -A                     AutoPlay - default is to play again",
  1011. X    "    -bitmaps bitdir        Use bitmaps found in bitdir subdirectory",
  1012. X    "    -h height              Bomb layout height (default 20)",
  1013. X    "    -w width               Bomb layout width (default 20)",
  1014. X    "    -n numberBombs         Number of bombs (default h*w/4)",
  1015. X    "    -name player           Play with a different name",
  1016. X    "    -f                     Make obvious moves (follow)",
  1017. X    "    -q                     Only print scores when changed (quiet)",
  1018. X    "    -r seed                Specify the seed (no highscore)",
  1019. X    "    -Rb b                  randomly select b bombed squares at start",
  1020. X    "    -Re e                  randomly select e empty squares at start",
  1021. X    "    -s                     show scorefile",
  1022. X    "    -S N Solver            Assign Solver #N",
  1023. X    "    -t                     Deduct numbers for placed bombs (ted mode)",
  1024. X    "    -z                     Start with a zero, instead of upper left",
  1025. X    " ",
  1026. X    "The authors recommend: -h 24 -w 34 -f -t -q -A",
  1027. X    NULL
  1028. X};
  1029. X
  1030. Xvoid
  1031. Xusage(name)
  1032. X    char *name;
  1033. X{
  1034. X    char **cpp;
  1035. X
  1036. X    fprintf(stderr, "usage: %s [-options ...]\n(Version %d.%d)\n", name,
  1037. X        VERSION, PATCHLEVEL);
  1038. X    for (cpp = help_message; *cpp; cpp++) {
  1039. X        fprintf(stderr, "%s\n", *cpp);
  1040. X    }
  1041. X    fprintf(stderr, "\n");
  1042. X    exit(1);
  1043. X}
  1044. X
  1045. X
  1046. XParseAndStart(argc, argv)
  1047. X    int argc;
  1048. X    char *argv[];
  1049. X{
  1050. X    char *ProgName, *server, *borderColor;
  1051. X    char *foreGround, *backGround;
  1052. X    int i, temp;
  1053. X    int num_solvers = 0;
  1054. X    char *def;
  1055. X    char solve_str[80];
  1056. X    char *solve_num = solve_str + 6;
  1057. X
  1058. X    strcpy (solve_str, "Solver0");
  1059. X
  1060. X    server = "";
  1061. X    borderColor = "";
  1062. X    foreGround = "";
  1063. X    backGround = "";
  1064. X
  1065. X    ProgName = argv[0];
  1066. X
  1067. X    /* parse command line options */
  1068. X
  1069. X    for (i=1; i<argc; i++) {
  1070. X        char *arg = argv[i];
  1071. X
  1072. X        if (arg[0] == '-') {
  1073. X            switch (arg[1]) {
  1074. X                case 'A':
  1075. X                    playagain = 1;
  1076. X                    continue;
  1077. X                case 'b':
  1078. X                    if (arg[2] == 'g') {
  1079. X                        if (++i >= argc) usage(ProgName);
  1080. X                        backGround = argv[i];
  1081. X                        continue;
  1082. X                        }
  1083. X                    else if (arg[2] == 'w') {
  1084. X                        if (++i >= argc) usage(ProgName);
  1085. X                        borderWidth = atoi(argv[i]);
  1086. X                        continue;
  1087. X                        }
  1088. X                    else if (arg[2] == 'd') {
  1089. X                        if (++i >= argc) usage(ProgName);
  1090. X                        borderColor = argv[i];
  1091. X                        continue;
  1092. X                        }
  1093. X                    else if (arg[2] == 'i') {
  1094. X                        if (++i >= argc) usage(ProgName);
  1095. X                        bitdir = argv[i];
  1096. X                        continue;
  1097. X                            }
  1098. X                    else usage(ProgName);
  1099. X                    break;
  1100. X                case 'd':
  1101. X                    if (++i >= argc) usage(ProgName);
  1102. X                    server = argv[i];
  1103. X                    continue;
  1104. X                case 'f':
  1105. X                    if (arg[2] == 'g') {
  1106. X                        if (++i >= argc) usage(ProgName);
  1107. X                        foreGround = argv[i];
  1108. X                        continue;
  1109. X                        }
  1110. X                    else if (arg[2] == 0) {
  1111. X                        betterfollow = 1;
  1112. X                        continue;
  1113. X                        }
  1114. X                    else usage(ProgName);
  1115. X                    break;
  1116. X                case 'g':
  1117. X                    if (++i >= argc) usage(ProgName);
  1118. X                    geom = argv[i];
  1119. X                    continue;
  1120. X                case 'h':
  1121. X                    if (++i >= argc) usage(ProgName);
  1122. X                    height = atoi(argv[i]);
  1123. X                    continue;
  1124. X                case 'n':
  1125. X                    if (arg[2] == 0) {
  1126. X                        if (++i >= argc) usage(ProgName);
  1127. X                        numbombs = atoi(argv[i]);
  1128. X                        continue;
  1129. X                        }
  1130. X                    else if (arg[2] == 'a') {
  1131. X                        if (++i >= argc) usage(ProgName);
  1132. X                        name = argv[i];
  1133. X                        continue;
  1134. X                        }
  1135. X                case 'q':
  1136. X                    showscore = 0;
  1137. X                    continue;
  1138. X                case 'r':
  1139. X                    if (++i >= argc) usage(ProgName);
  1140. X                    seed = atoi(argv[i]);
  1141. X                    continue;
  1142. X                case 'R':
  1143. X                    if (arg[2] == 'e') {
  1144. X                        if (++i >= argc) usage(ProgName);
  1145. X                        randomE = atoi(argv[i]);
  1146. X                        continue;
  1147. X                        }
  1148. X                    else if (arg[2] == 'b') {
  1149. X                        if (++i >= argc) usage(ProgName);
  1150. X                        randomB = atoi(argv[i]);
  1151. X                        continue;
  1152. X                        }
  1153. X                    else usage(ProgName);
  1154. X                    break;
  1155. X                case 's':
  1156. X                    /* so score won't be updated */
  1157. X                    onlyprint = 1;   
  1158. X                    log_score();
  1159. X                    exit(0);
  1160. X                case 'S':
  1161. X                    if (++i >= argc) usage(ProgName);
  1162. X                    if (isdigit(arg[2])) {
  1163. X                        temp = arg[2] - '0';
  1164. X                        temp = (temp + 9) % 10;
  1165. X                        solvers[temp] = strdup(argv[i]);
  1166. X                        num_solvers = temp + 1;
  1167. X                        }
  1168. X                    else {
  1169. X                        solvers[num_solvers++] = strdup(argv[i]);
  1170. X                        }
  1171. X                    continue;
  1172. X                case 't':
  1173. X                    ted = 1;
  1174. X                    continue;
  1175. X                case 'w':
  1176. X                    if (++i >= argc) usage(ProgName);
  1177. X                    width = atoi(argv[i]);
  1178. X                    continue;
  1179. X                case 'z':
  1180. X                    startwithzero = 1;
  1181. X                    onlyprint = 1;
  1182. X                    continue;
  1183. X                default:
  1184. X                    usage(ProgName);
  1185. X                    continue;
  1186. X                }
  1187. X            }
  1188. X        else
  1189. X            usage(ProgName);
  1190. X        }
  1191. X
  1192. X    dpy = XOpenDisplay(server);
  1193. X    if (dpy == NULL) {
  1194. X        fprintf(stderr, "can't open display \"%s\"\n",server);
  1195. X        exit(1);
  1196. X    }
  1197. X    screen = DefaultScreen(dpy);
  1198. X
  1199. X    if (backGround[0] == '\0') {
  1200. X        def = XGetDefault(dpy, "xbomb", "Background");
  1201. X            backGround = def ? def: "white";
  1202. X        }
  1203. X    if (foreGround[0] == '\0') {
  1204. X        def = XGetDefault(dpy, "xbomb", "Foreground");
  1205. X            foreGround = def ? def: "black";
  1206. X        }
  1207. X    if (borderWidth < 0) {
  1208. X        def = XGetDefault(dpy, "xbomb", "BorderWidth");
  1209. X            borderWidth = def ? atoi(def) : 1;
  1210. X        }
  1211. X    if (borderColor[0] == '\0') {
  1212. X        def = XGetDefault(dpy, "xbomb", "BorderColor");
  1213. X            borderColor = def ? def: "black";
  1214. X        }
  1215. X    if (server[0] == '\0') {
  1216. X        def = XGetDefault(dpy, "xbomb", "Display");
  1217. X            server = def ? def: "black";
  1218. X        }
  1219. X    if (betterfollow < 0) {
  1220. X        def = XGetDefault(dpy, "xbomb", "Follow");
  1221. X            betterfollow = def ? 1 : 0;
  1222. X        }
  1223. X    if (bitdir == NULL) {
  1224. X        if (def = XGetDefault(dpy, "xbomb", "Bitmaps"))
  1225. X                bitdir = def;
  1226. X    }
  1227. X    if (geom[0] == '\0') {
  1228. X        if (def = XGetDefault(dpy, "xbomb", "Geometry"))
  1229. X                geom = def;
  1230. X        }
  1231. X    if (width < 0) {
  1232. X        def = XGetDefault(dpy, "xbomb", "Width");
  1233. X            width = def ? atoi(def) : 20;
  1234. X        }
  1235. X    if (height < 0) {
  1236. X        def = XGetDefault(dpy, "xbomb", "Height");
  1237. X            height = def ? atoi(def) : 20;
  1238. X        }
  1239. X    if (numbombs < 0) {
  1240. X        def = XGetDefault(dpy, "xbomb", "NumberBombs");
  1241. X            numbombs = def ? atoi(def) : 0;
  1242. X        }
  1243. X    if (name == NULL) {
  1244. X        def = XGetDefault(dpy, "xbomb", "Name");
  1245. X        if (def) name = def;
  1246. X        }
  1247. X    if (randomE < 0) {
  1248. X        def = XGetDefault(dpy, "xbomb", "RandomEmpty");
  1249. X            randomE = def ? atoi(def) : 0;
  1250. X        }
  1251. X    if (randomB < 0) {
  1252. X        def = XGetDefault(dpy, "xbomb", "RandomBombs");
  1253. X            randomB = def ? atoi(def) : 0;
  1254. X        }
  1255. X    if (playagain < 0) {
  1256. X        def = XGetDefault(dpy, "xbomb", "PlayAgain");
  1257. X            playagain = def ? 1 : 0;
  1258. X        }
  1259. X    if (showscore < 0) {
  1260. X        def = XGetDefault(dpy, "xbomb", "Quiet");
  1261. X            showscore = def ? 0 : 1;
  1262. X        }
  1263. X    for (i = 0; i <= 9; i++) {
  1264. X        if (solvers[i] == NULL) {
  1265. X            solve_num[0] = (i+1)%10 + '0';
  1266. X            if (def = XGetDefault(dpy, "xbomb", solve_str))
  1267. X                    solvers[i] = def;
  1268. X            }
  1269. X        }
  1270. X    if (ted < 0) {
  1271. X        def = XGetDefault(dpy, "xbomb", "TedMode");
  1272. X            ted = def ? 1 : 0;
  1273. X        }
  1274. X    if (startwithzero < 0) {
  1275. X        def = XGetDefault(dpy, "xbomb", "StartWithZero");
  1276. X            onlyprint = startwithzero = def ? 1 : 0;
  1277. X        }
  1278. X
  1279. X    if (startwithzero && showscore) 
  1280. X        printf("Warning: starting with zero means no high score\n");
  1281. X
  1282. X    FgPixel = requestColor(foreGround);
  1283. X    BgPixel = requestColor(backGround);
  1284. X    BdPixel = requestColor(borderColor);
  1285. X}
  1286. X
  1287. X
  1288. X
  1289. Xmain(argc,argv)
  1290. X    int argc;
  1291. X    char **argv;
  1292. X{
  1293. X    int i, ret, temp;
  1294. X
  1295. X    ParseAndStart(argc, argv);
  1296. X
  1297. X    graphics_main(argc, argv);
  1298. X    
  1299. X    if (seed==-1) {
  1300. X        seed=time(NULL) + getpid();
  1301. X    } else {
  1302. X        onlyprint=1;
  1303. X        }
  1304. X
  1305. X    /* 
  1306. X     * Pass an int instead of 48 bit number to srand48 so we can easily use
  1307. X     * atoi to read in the number if given as an argument
  1308. X     */
  1309. X        srand48(seed);
  1310. X
  1311. X    do {
  1312. X
  1313. X        create_map();
  1314. X
  1315. X        for (temp = numflags, emptylen = 1; temp > 0; 
  1316. X             temp/=10,emptylen++);
  1317. X
  1318. X
  1319. X        if (dead) {
  1320. X            dead = 0;
  1321. X            repaint();
  1322. X            
  1323. X        }
  1324. X
  1325. X        for (i = 0; i < randomB + randomE; i++)
  1326. X            place_random((i < randomB)?BOMB:EMPTY);
  1327. X
  1328. X        ret = eventloop();
  1329. X
  1330. X        log_score();
  1331. X    } while (ret == 1);
  1332. X
  1333. X    cleanup();
  1334. X    exit(0) ;
  1335. X}
  1336. X
  1337. X
  1338. END_OF_FILE
  1339. if test 9883 -ne `wc -c <'main.c'`; then
  1340.     echo shar: \"'main.c'\" unpacked with wrong size!
  1341. fi
  1342. # end of 'main.c'
  1343. fi
  1344. if test -f 'pattern_solver.c' -a "${1}" != "-c" ; then 
  1345.   echo shar: Will not clobber existing file \"'pattern_solver.c'\"
  1346. else
  1347. echo shar: Extracting \"'pattern_solver.c'\" \(5407 characters\)
  1348. sed "s/^X//" >'pattern_solver.c' <<'END_OF_FILE'
  1349. X
  1350. X/*
  1351. X * pattern_solver
  1352. X * @(#)pattern_solver.c    1.7 (UCLA) 10/6/92
  1353. X *
  1354. X * xbomb is Copyright (C) 1992 by Matthew Merzbacher, Los Angeles, CA.
  1355. X * All rights reserved.  Permission is granted to freely distribute
  1356. X * this as long as this copyright message is retained intact.
  1357. X * Permission to distribute this as part of a commerical product
  1358. X * requires explicit permission of the author.
  1359. X *
  1360. X */
  1361. X
  1362. X#include <stdio.h>
  1363. X#include "solver_io.h"
  1364. X
  1365. X
  1366. X#define KNOWN(s) ((s == empty) || (s == bomb) || (s == edge))
  1367. X
  1368. Xstruct point {
  1369. X    int x, y;
  1370. X    };
  1371. X
  1372. Xstruct neighbor_set {
  1373. X    int size;
  1374. X    struct point points[8];
  1375. X    };
  1376. X
  1377. Xstruct neighbor_set mymap[MAXWIDTH][MAXHEIGHT];
  1378. X    
  1379. Xint
  1380. Xapply_empty_if_unknown(x, y, ptr)
  1381. X    int x, y;
  1382. X    void *ptr;
  1383. X{
  1384. X    if (map[x][y].status==unknown) {
  1385. X        printf ("%d %d e\n", x, y);
  1386. X    };
  1387. X}
  1388. X
  1389. Xint 
  1390. Xapply_flag_if_unknown(x, y, ptr)
  1391. X    int x, y;
  1392. X    void *ptr;
  1393. X{
  1394. X    if (map[x][y].status==unknown) {
  1395. X        map[x][y].status = bomb_flag;
  1396. X        printf ("%d %d f\n", x, y);
  1397. X        return(1);
  1398. X    };
  1399. X    return(0);
  1400. X}
  1401. X
  1402. Xint
  1403. Xrun4(x, y, dx, dy)
  1404. X{
  1405. X    int ct = 0;
  1406. X
  1407. X    if (map[x][y].status == unknown) ct++;
  1408. X    if (map[x+dx][y].status == unknown) ct++;
  1409. X    if (map[x][y+dy].status == unknown) ct++;
  1410. X    if (map[x+dx][y+dy].status == unknown) ct++;
  1411. X
  1412. X    return(ct);
  1413. X}
  1414. X
  1415. Xvoid
  1416. Xadd_neighbor(x, y, dx, dy)
  1417. Xint x, y, dx, dy;
  1418. X{
  1419. X    int s;
  1420. X
  1421. X    s = mymap[x][y].size;
  1422. X    mymap[x][y].points[s].x = x+dx;
  1423. X    mymap[x][y].points[s].y = y+dy;
  1424. X    mymap[x][y].size ++;
  1425. X    }
  1426. X
  1427. Xvoid
  1428. Xmake_neighbors(status, x, y, dx, dy)
  1429. Xint status, x, y;
  1430. X{
  1431. X    int i, j, fix;
  1432. X
  1433. X    for (j = 0; j < mymap[x+dx][y+dy].size; j++) {
  1434. X        fix = 1;
  1435. X        for (i = 0; fix && (i < mymap[x][y].size); i++) {
  1436. X            if ((mymap[x][y].points[i].x == mymap[x+dx][y+dy].points[j].x) &&
  1437. X                (mymap[x][y].points[i].y == mymap[x+dx][y+dy].points[j].y)) {
  1438. X                fix = 0;
  1439. X                }
  1440. X            }
  1441. X        if (fix) {
  1442. X            printf ("%d %d %c\n", mymap[x+dx][y+dy].points[j].x, mymap[x+dx][y+dy].points[j].y, (status == empty)?'m':'f');
  1443. X            }
  1444. X        }
  1445. X}
  1446. X
  1447. Xint
  1448. Xsubset_of(x1, y1, x2, y2)
  1449. Xint x1, y1, x2, y2;
  1450. X{
  1451. X    int i, j, found;
  1452. X
  1453. X    for (i = 0; i < mymap[x1][y1].size; i++) {
  1454. X        found = 0;
  1455. X        for (j = 0; !found && j < mymap[x2][y2].size; j++) {
  1456. X            if ((mymap[x1][y1].points[i].x == mymap[x2][y2].points[j].x) &&
  1457. X                (mymap[x1][y1].points[i].y == mymap[x2][y2].points[j].y))
  1458. X                found = 1;
  1459. X                }
  1460. X        if (!found) return(0);
  1461. X        }
  1462. X    
  1463. X    return(1);
  1464. X    }
  1465. X
  1466. Xint
  1467. Xplace_em()
  1468. X{
  1469. X    int x, y, ret = 0, dx, dy;
  1470. X
  1471. X    for (x = 1; x <= width; x++)
  1472. X        for (y = 1; y <= height; y++) {
  1473. X            mymap[x][y].size = 0;
  1474. X            if (map[x][y].status == empty &&
  1475. X                map[x][y].ted >= 1)
  1476. X                for (dx = -1; dx <= 1; dx++)
  1477. X                    for (dy = -1; dy <= 1; dy++)
  1478. X                        if (((dx != 0) || (dy != 0)) &&
  1479. X                            (! KNOWN(map[x+dx][y+dy].status)))
  1480. X                            add_neighbor(x, y, dx, dy);
  1481. X                        }
  1482. X
  1483. X
  1484. X    for (x = 1; x <= width; x++)
  1485. X        for (y = 1; y <= height; y++) {
  1486. X
  1487. X/***
  1488. X            if (map[x][y].status == empty &&
  1489. X                map[x][y].ted == 1)
  1490. X                {
  1491. X                for (dx = -1; dx <= 1; dx += 2)
  1492. X                    if (map[x+dx][y].status == empty &&
  1493. X                        map[x+dx][y].ted == 1 &&
  1494. X                        KNOWN(map[x-dx][y-1].status) &&
  1495. X                        KNOWN(map[x-dx][y].status) &&
  1496. X                        KNOWN(map[x-dx][y+1].status)) {
  1497. X                        apply_empty_if_unknown(x+2*dx,
  1498. X                                       y+1,NULL);
  1499. X                        apply_empty_if_unknown(x+2*dx,
  1500. X                                       y,NULL);
  1501. X                        apply_empty_if_unknown(x+2*dx,
  1502. X                                       y-1,NULL);
  1503. X                    };
  1504. X
  1505. X                for (dy = -1; dy <= 1; dy += 2)
  1506. X                    if (map[x][y+dy].status==empty &&
  1507. X                        map[x][y+dy].ted == 1 &&
  1508. X                        KNOWN(map[x-1][y-dy].status) &&
  1509. X                        KNOWN(map[x][y-dy].status) &&
  1510. X                        KNOWN(map[x+1][y-dy].status)) {
  1511. X                        apply_empty_if_unknown(x+1,y+2*dy,NULL);
  1512. X                        apply_empty_if_unknown(x,y+2*dy,NULL);
  1513. X                        apply_empty_if_unknown(x-1,y+2*dy,NULL);
  1514. X                    };
  1515. X            };
  1516. X
  1517. X***/
  1518. X
  1519. X            if (map[x][y].status == empty && 
  1520. X                map[x][y].ted > 1 &&
  1521. X                map[x][y].neighbor_unknowns - map[x][y].ted == 1
  1522. X                )
  1523. X                {
  1524. X                for (dx = -1; dx <= 1; dx += 2)
  1525. X                    if (map[x-dx][y].status == empty &&
  1526. X                        map[x-dx][y].ted == 1 &&
  1527. X                        run4(x-dx, y-1, dx, 2) == 2
  1528. X                        ) 
  1529. X                        {
  1530. X                          apply_flag_if_unknown(x+dx,
  1531. X                                y-1,NULL);
  1532. X                          apply_flag_if_unknown(x+dx,
  1533. X                                y,NULL);
  1534. X                          apply_flag_if_unknown(x+dx,
  1535. X                                y+1,NULL);
  1536. X                          }
  1537. X
  1538. X                for (dy = -1; dy <= 1; dy += 2)
  1539. X                    if (map[x][y-dy].status == empty &&
  1540. X                        map[x][y-dy].ted == 1 &&
  1541. X                        run4(x-1, y-dy, 2, dy) == 2
  1542. X                        )
  1543. X                        {
  1544. X                          apply_flag_if_unknown(x-1,
  1545. X                                y+dy,NULL);
  1546. X                          apply_flag_if_unknown(x,
  1547. X                                y+dy,NULL);
  1548. X                          apply_flag_if_unknown(x+1,
  1549. X                                y+dy,NULL);
  1550. X                          }
  1551. X                
  1552. X            };
  1553. X        };
  1554. X
  1555. X
  1556. X    for (x = 1; x <= width; x++) for (y = 1; y <= height; y++)
  1557. X        if (map[x][y].status == empty &&
  1558. X            map[x][y].ted >= 1)
  1559. X            for (dx = -2; dx <= 2; dx++)
  1560. X                for (dy = -2; dy <= 2; dy++)
  1561. X                    if (((dx != 0) || (dy != 0)) &&
  1562. X                        (x+dx <= width) &&
  1563. X                        (x+dx >= 1) &&
  1564. X                        (y+dy <= height) &&
  1565. X                        (y+dy >= 1) && 
  1566. X                        (map[x+dx][y+dy].status == empty) &&
  1567. X                            (map[x+dx][y+dy].ted >= 1) &&
  1568. X                        subset_of(x, y, x+dx, y+dy)) {
  1569. X                        if (map[x][y].ted == map[x+dx][y+dy].ted)
  1570. X                            make_neighbors(empty, x, y, dx, dy);
  1571. X                        if (map[x][y].ted == map[x+dx][y+dy].ted + mymap[x][y].size - mymap[x+dx][y+dy].size)
  1572. X                            make_neighbors(bomb, x, y, dx, dy);
  1573. X                            }
  1574. X    
  1575. X    return(ret);
  1576. X}
  1577. X    
  1578. Xmain()
  1579. X{
  1580. X    int ret; int x, y;
  1581. X
  1582. X    while (!feof(stdin)) {
  1583. X        read_data();
  1584. X        if (counts[bomb_flag])
  1585. X            exit (1);   /* we don't allow flags, yet */
  1586. X        calc_em();
  1587. X        ret = place_em();
  1588. X        printf ("\n");   /* terminate output */
  1589. X        fflush(stdout);
  1590. X    };
  1591. X    exit (0);
  1592. X}
  1593. END_OF_FILE
  1594. if test 5407 -ne `wc -c <'pattern_solver.c'`; then
  1595.     echo shar: \"'pattern_solver.c'\" unpacked with wrong size!
  1596. fi
  1597. # end of 'pattern_solver.c'
  1598. fi
  1599. if test -f 'score.c' -a "${1}" != "-c" ; then 
  1600.   echo shar: Will not clobber existing file \"'score.c'\"
  1601. else
  1602. echo shar: Extracting \"'score.c'\" \(6614 characters\)
  1603. sed "s/^X//" >'score.c' <<'END_OF_FILE'
  1604. X
  1605. X/*
  1606. X * score.c
  1607. X * @(#)score.c    1.29 (UCLA) 10/13/92
  1608. X *
  1609. X * xbomb is Copyright (C) 1992 by Matthew Merzbacher, Los Angeles, CA.
  1610. X * All rights reserved.  Permission is granted to freely distribute
  1611. X * this as long as this copyright message is retained intact.
  1612. X * Permission to distribute this as part of a commerical product
  1613. X * requires explicit permission of the author.
  1614. X *
  1615. X * This scoring code is completely Matthew's thieving fault
  1616. X * (thanks to the authors of ATC).
  1617. X */
  1618. X
  1619. X#include "xbomb.h"
  1620. X
  1621. Xchar    *name = NULL;    /* the player's name */
  1622. X    
  1623. Xint
  1624. Xcompar(a, b)
  1625. X    struct score *a, *b;
  1626. X{
  1627. X    return (b->score - a->score);
  1628. X}
  1629. X
  1630. Xprint_score()
  1631. X{
  1632. X    int cf, d, ct;
  1633. X    
  1634. X    ct = emptylen;
  1635. X    cf = numflags;
  1636. X    if (cf < 0) cf = 0;
  1637. X
  1638. X    while (ct > 1) {
  1639. X        d = cf%10;
  1640. X        if ((d == 0) && (cf == 0) && (numflags > 0)) {
  1641. X            XCopyPlane(dpy, pixmaps[BLANK], puzzleWindow, gc,
  1642. X               0, 0, WIDTH, HEIGHT, ct*WIDTH, 0, 1);
  1643. X        }
  1644. X        else {
  1645. X            XCopyPlane(dpy, pixmaps[d], puzzleWindow, gc,
  1646. X               0, 0, WIDTH, HEIGHT, ct*WIDTH, 0, 1);
  1647. X        }
  1648. X        ct--;
  1649. X        cf = cf/10;
  1650. X    }
  1651. X}
  1652. X
  1653. Xint
  1654. Xfigure_score()
  1655. X{
  1656. X    int s, x, y;
  1657. X    s=0;
  1658. X    for (x = 1; x <= width; x++)
  1659. X        for (y = 1; y <= height; y++)
  1660. X            if (map[x][y].status == KEMPTY)
  1661. X                s += map[x][y].neighbors * map[x][y].neighbors;
  1662. X    return s;
  1663. X}
  1664. X
  1665. Xchar *
  1666. Xformattime(t)
  1667. X    time_t *t;
  1668. X{
  1669. X#define SLEN 80
  1670. X    static char s[SLEN];
  1671. X    strftime(s, SLEN, "%e-%b-%y", localtime(t));
  1672. X    return s;
  1673. X
  1674. X}
  1675. X
  1676. Xlog_score()
  1677. X{
  1678. X    register int    c, r, place, change = 0, ct, i, fd, nnum_scores = 0, 
  1679. X    num_scores = 0, good, nscoreid = -1;
  1680. X    int botscore;
  1681. X    struct passwd    *pw;
  1682. X    FILE        *fp;
  1683. X    char        *cp, *index(), *rindex();
  1684. X    struct score    nscore[NUM_SCORES + 1], score[NUM_SCORES + 1], thisscore;
  1685. X    char        *tmp, s[101];
  1686. X    char        scorechar;
  1687. X    struct score    ascore;
  1688. X    
  1689. X    umask(0);
  1690. X    fd = open(_PATH_SCORE, O_CREAT|O_RDWR, 0644);
  1691. X    if (fd < 0) {
  1692. X        perror(_PATH_SCORE);
  1693. X        return (-1);
  1694. X    }
  1695. X    /*
  1696. X     * This is done to take advantage of stdio, while still 
  1697. X     * allowing a O_CREAT during the open(2) of the log file.
  1698. X     */
  1699. X    fp = fdopen(fd, "r+");
  1700. X    if (fp == NULL) {
  1701. X        perror(_PATH_SCORE);
  1702. X        return (-1);
  1703. X    }
  1704. X    if (flock(fileno(fp), LOCK_EX) < 0)
  1705. X    {
  1706. X        perror("flock");
  1707. X        return (-1);
  1708. X    }
  1709. X    
  1710. X    for (;;) {
  1711. X        if (fgets(s, 100, fp) == NULL) break;
  1712. X
  1713. X#define REQFIELDS 8
  1714. X        good = sscanf(s, "%c %s %d %d %d %d %d %d",
  1715. X                  &scorechar,
  1716. X                  ascore.name,
  1717. X                  &ascore.size, 
  1718. X                  &ascore.bombs,
  1719. X                  &ascore.defused, 
  1720. X                  &ascore.won,
  1721. X                  &ascore.score,
  1722. X                  &ascore.time);
  1723. X        if (good == REQFIELDS-1)
  1724. X            ascore.time = 717701220;   /* when the time field was added */
  1725. X        ascore.mine = 0;
  1726. X        if (scorechar == 'P') {
  1727. X            nscore[nnum_scores] = ascore;
  1728. X            if (ascore.bombs == numbombs)
  1729. X                nscoreid = nnum_scores;
  1730. X            if (good != REQFIELDS || ++nnum_scores >= NUM_SCORES)
  1731. X                break;
  1732. X        } else if (scorechar == 'H') {
  1733. X            score[num_scores] = ascore;
  1734. X            if (good != REQFIELDS || ++num_scores >= NUM_SCORES)
  1735. X                break;
  1736. X        } else {
  1737. X            bail("Corrupt score file.");
  1738. X        };
  1739. X    };
  1740. X
  1741. X    if (name == NULL) {
  1742. X        if ((pw = (struct passwd *) getpwuid(getuid())) == NULL) {
  1743. X            fprintf(stderr, 
  1744. X                "getpwuid failed for uid %d.  Who are you?\n",
  1745. X                getuid());
  1746. X            return (-1);
  1747. X        }
  1748. X        strcpy(thisscore.name, pw->pw_name);
  1749. X        }
  1750. X    else {
  1751. X        strncpy(thisscore.name, name, 8);
  1752. X        thisscore.name[8] = '\0';
  1753. X        }
  1754. X
  1755. X    thisscore.size = width * height;
  1756. X    thisscore.bombs = numbombs;
  1757. X    thisscore.defused = numbombs - numflags;
  1758. X    for (c = 1; c <= width; c++)
  1759. X        for (r = 1; r <= height; r++)
  1760. X            if (map[c][r].flag && 
  1761. X                ((map[c][r].status == EMPTY) || 
  1762. X                 (map[c][r].status == KEMPTY)))
  1763. X                thisscore.defused--;
  1764. X    thisscore.won = dead?0:1;
  1765. X    thisscore.score = figure_score();
  1766. X/* Old scoring function:
  1767. X *    thisscore.score = 
  1768. X *        (thisscore.won + 1)*(thisscore.size * thisscore.defused);
  1769. X */
  1770. X    thisscore.time = time(NULL);
  1771. X    thisscore.mine = 1;
  1772. X    
  1773. X    ct = 0;
  1774. X    botscore = 0;
  1775. X    for (i = 0; i < num_scores; i++) {
  1776. X        if (strcmp(thisscore.name, score[i].name) == 0) {
  1777. X            botscore = score[i].score;
  1778. X            ct++;
  1779. X            place = i;
  1780. X        }
  1781. X    }
  1782. X    
  1783. X    if (ct >= MAX_PER_PLAYER) {
  1784. X        if (thisscore.score > botscore) {
  1785. X            bcopy(&thisscore, &score[place], sizeof (score[place]));
  1786. X            qsort(score, num_scores, sizeof (*score), compar);
  1787. X            change = 1;
  1788. X        }
  1789. X    }
  1790. X    else {
  1791. X        bcopy(&thisscore, &score[num_scores], sizeof (score[place]));
  1792. X        qsort(score, num_scores + 1, sizeof (*score), compar);
  1793. X        if (thisscore.score >= score[num_scores].score) change = 1;
  1794. X        if (num_scores < NUM_SCORES) num_scores++;
  1795. X    }
  1796. X    
  1797. X    if (nscoreid == -1) {
  1798. X        bcopy(&thisscore, &nscore[nnum_scores++], sizeof (nscore[0]));
  1799. X        change = 1;
  1800. X        nscoreid = nnum_scores;
  1801. X    }
  1802. X    
  1803. X    if (nscore[nscoreid].defused < thisscore.defused) {
  1804. X        bcopy(&thisscore, &nscore[nscoreid], sizeof (nscore[nscoreid]));
  1805. X        change = 1;
  1806. X    }
  1807. X    
  1808. X    if (change && !onlyprint) {
  1809. X        rewind(fp);
  1810. X        for (i = 0; i < num_scores; i++)
  1811. X            fprintf(fp, "H %s %d %d %d %d %d %d\n",
  1812. X                score[i].name, score[i].size,
  1813. X                score[i].bombs, score[i].defused,
  1814. X                score[i].won, score[i].score,
  1815. X                score[i].time);
  1816. X        for (i = 0; i < nnum_scores; i++)
  1817. X            fprintf(fp, "P %s %d %d %d %d %d %d\n",
  1818. X                nscore[i].name, nscore[i].size,
  1819. X                nscore[i].bombs, nscore[i].defused,
  1820. X                nscore[i].won, nscore[i].score,
  1821. X                nscore[i].time);
  1822. X    }
  1823. X    
  1824. X    flock(fileno(fp), LOCK_UN);
  1825. X    fclose(fp);
  1826. X
  1827. X    if (showscore || change) {
  1828. X        printf("%2s:  %-8s  %-9s  %7s  %4s  %5s  %5s  %3s\n",
  1829. X               "#", "name", "date",
  1830. X               "score", "size", "bombs", "flags", "won");
  1831. X        printf("---------------------------------------------------------\n");
  1832. X        for (i = 0; i < num_scores; i++) {
  1833. X            if (i <= TOP_PRINT || 
  1834. X               (strcmp(thisscore.name, score[i].name) == 0) || onlyprint)
  1835. X                printf("%2d:  %-8s  %-9s  %7d  %4d  %5d  %5d %3s %6s\n",
  1836. X                       i + 1,
  1837. X                       score[i].name, formattime(&score[i].time),
  1838. X                       score[i].score, 
  1839. X                       score[i].size, score[i].bombs, 
  1840. X                       score[i].defused,
  1841. X                       (score[i].won)?" Y":" N",
  1842. X                       (score[i].mine)?"  <---":" ");
  1843. X            }
  1844. X        
  1845. X        if (!onlyprint) {
  1846. X            printf("\nYour stats:\n     %-8s  %-9s  %7d  %4d  %5d  %5d %3s %6s\n",
  1847. X                   thisscore.name, 
  1848. X                   formattime(&thisscore.time),
  1849. X                   thisscore.score,  
  1850. X                   thisscore.size, 
  1851. X                   thisscore.bombs, 
  1852. X                   thisscore.defused,
  1853. X                   (thisscore.won)?" Y":" N", 
  1854. X                   (thisscore.mine)?"  <---":" ");
  1855. X            
  1856. X            printf("\nMost defused with %d bombs\n     %-8s  %-9s  %7d  %4d  %5d  %5d %3s %6s\n",
  1857. X                   nscore[nscoreid].bombs,
  1858. X                   nscore[nscoreid].name, 
  1859. X                   formattime(&nscore[nscoreid].time),
  1860. X                   nscore[nscoreid].score,  
  1861. X                   nscore[nscoreid].size, 
  1862. X                   nscore[nscoreid].bombs, 
  1863. X                   nscore[nscoreid].defused,
  1864. X                   (nscore[nscoreid].won)?" Y":" N", 
  1865. X                   (nscore[nscoreid].mine)?"  <---":" ");
  1866. X            }
  1867. X        }
  1868. X    return (0);
  1869. X}
  1870. END_OF_FILE
  1871. if test 6614 -ne `wc -c <'score.c'`; then
  1872.     echo shar: \"'score.c'\" unpacked with wrong size!
  1873. fi
  1874. # end of 'score.c'
  1875. fi
  1876. if test -f 'solver_io.c' -a "${1}" != "-c" ; then 
  1877.   echo shar: Will not clobber existing file \"'solver_io.c'\"
  1878. else
  1879. echo shar: Extracting \"'solver_io.c'\" \(3128 characters\)
  1880. sed "s/^X//" >'solver_io.c' <<'END_OF_FILE'
  1881. X
  1882. X/*
  1883. X * solver_io.c
  1884. X * @(#)solver_io.c    1.3 (UCLA) 10/6/92
  1885. X *
  1886. X * xbomb is Copyright (C) 1992 by Matthew Merzbacher, Los Angeles, CA.
  1887. X * All rights reserved.  Permission is granted to freely distribute
  1888. X * this as long as this copyright message is retained intact.
  1889. X * Permission to distribute this as part of a commerical product
  1890. X * requires explicit permission of the author.
  1891. X *
  1892. X */
  1893. X
  1894. X#include <stdio.h>
  1895. X#include "solver_io.h"
  1896. X
  1897. Xstruct generic_cell map[MAXWIDTH+2][MAXHEIGHT+2];
  1898. X
  1899. Xint numbombs;
  1900. Xint width, height;
  1901. X
  1902. Xint mouse_x, mouse_y;
  1903. X
  1904. X
  1905. Xint counts[(int)last_status];
  1906. X
  1907. X
  1908. Xvoid
  1909. Xbail(s)
  1910. X    char *s;
  1911. X{
  1912. X    perror (s);
  1913. X    exit(1);
  1914. X}
  1915. X        
  1916. X
  1917. Xvoid
  1918. Xread_data()
  1919. X{
  1920. X    char s[MAXWIDTH+3];
  1921. X    int x, y;
  1922. X    char *p;
  1923. X    static char *delimiters = " \t\n";
  1924. X    extern char *strtok();
  1925. X
  1926. X    for (x=0; x<=MAXWIDTH+1; x++)
  1927. X        for (y=0; y<=MAXHEIGHT+1; y++)
  1928. X            map[x][y].status = edge;
  1929. X
  1930. X    for (;;) {
  1931. X        if (NULL==fgets (s, MAXWIDTH+3, stdin))
  1932. X            break;
  1933. X        if (s[0] == '\n' || s[0]  == 0)
  1934. X            break;
  1935. X        s[strlen(s)-1] = 0;  /* chop newline */
  1936. X        p = strtok(s, delimiters);  /* get & terminate first word */
  1937. X        if (strcmp(s,"numbombs")==0) {
  1938. X            sscanf(p, "%d", &numbombs);
  1939. X        } else if (strcmp(s,"mouse")==0) {
  1940. X            sscanf(p, "%d %d", &mouse_x, &mouse_y);
  1941. X        } else if (strcmp(s,"map")==0) {
  1942. X            break;
  1943. X        };
  1944. X    };
  1945. X    for (y=1;;y++) {
  1946. X        if (NULL==fgets (s, MAXWIDTH+3, stdin))
  1947. X            break;
  1948. X        /* emtpy line terminates input */
  1949. X        if (s[0] == '\n' || s[0]  == 0)
  1950. X            break;
  1951. X        width = strlen(s) - 1;
  1952. X        for (x=1, p=s; *p && *p != '\n'; p++, x++) {
  1953. X            switch (*p) {
  1954. X            case 'X':
  1955. X                map[x][y].status = bomb;
  1956. X                break;
  1957. X            case 'f':
  1958. X                map[x][y].status = bomb_flag;
  1959. X                break;
  1960. X            case 'e':
  1961. X                bail("Known empty squares not yet handled.");
  1962. X                break;
  1963. X            case '0':
  1964. X            case '1':
  1965. X            case '2':
  1966. X            case '3':
  1967. X            case '4':
  1968. X            case '5':
  1969. X            case '6':
  1970. X            case '7':
  1971. X            case '8':
  1972. X            case '9':
  1973. X                map[x][y].status = empty;
  1974. X                map[x][y].neighbors = *p - '0';
  1975. X                break;
  1976. X            case '.':
  1977. X                map[x][y].status = unknown;
  1978. X                break;
  1979. X            default:
  1980. X                bail("Bad square value.");
  1981. X            };
  1982. X            counts[map[x][y].status]++;
  1983. X        };
  1984. X    };
  1985. X    height = y-1;
  1986. X}
  1987. X
  1988. X
  1989. Xint
  1990. Xapply_inc_if_unknown(x, y, ptr)
  1991. X    int x, y;
  1992. X    void *ptr;
  1993. X{
  1994. X    int *ip = (int*)ptr;
  1995. X    if (map[x][y].status==unknown)
  1996. X        (*ip)++;
  1997. X    return(0);
  1998. X}
  1999. X
  2000. Xint
  2001. Xapply_inc_if_bomb(x, y, ptr)
  2002. X    int x, y;
  2003. X    void *ptr;
  2004. X{
  2005. X    int *ip = (int*)ptr;
  2006. X    if (map[x][y].status==bomb)
  2007. X        (*ip)++;
  2008. X    return(0);
  2009. X}
  2010. X
  2011. Xint
  2012. Xapply_neighbor(c,r, f, ptr)
  2013. X    int c,r;
  2014. X    int (*f)();
  2015. X    void *ptr;
  2016. X{
  2017. X    int x, y, ret = 0;
  2018. X    
  2019. X    for (x = c-1; x <= c+1; x++)
  2020. X        for (y = r-1; y <= r+1; y++) {
  2021. X            if (x==c && y==r)
  2022. X                continue;
  2023. X            ret |= (*f)(x, y, ptr);
  2024. X        };
  2025. X    
  2026. X    return(ret);
  2027. X}
  2028. X
  2029. X
  2030. Xint
  2031. Xcalc_em()
  2032. X{
  2033. X    int x, y, ret = 0, dx, dy;
  2034. X    
  2035. X    for (x = 1; x <= width; x++)
  2036. X        for (y = 1; y <= height; y++) {
  2037. X            map[x][y].neighbor_unknowns = 0;
  2038. X            apply_neighbor(x,y,apply_inc_if_unknown,&map[x][y].neighbor_unknowns);
  2039. X        };
  2040. X    
  2041. X    for (x = 1; x <= width; x++)
  2042. X        for (y = 1; y <= height; y++) {
  2043. X            map[x][y].neighbor_bombs = 0;
  2044. X            apply_neighbor(x,y,apply_inc_if_bomb,&map[x][y].neighbor_bombs);
  2045. X        };
  2046. X
  2047. X    for (x = 1; x <= width; x++)
  2048. X        for (y = 1; y <= height; y++)
  2049. X            if (map[x][y].status == empty)
  2050. X                map[x][y].ted = map[x][y].neighbors -
  2051. X                    map[x][y].neighbor_bombs;
  2052. X    
  2053. X}
  2054. END_OF_FILE
  2055. if test 3128 -ne `wc -c <'solver_io.c'`; then
  2056.     echo shar: \"'solver_io.c'\" unpacked with wrong size!
  2057. fi
  2058. # end of 'solver_io.c'
  2059. fi
  2060. if test -f 'solvers.c' -a "${1}" != "-c" ; then 
  2061.   echo shar: Will not clobber existing file \"'solvers.c'\"
  2062. else
  2063. echo shar: Extracting \"'solvers.c'\" \(4137 characters\)
  2064. sed "s/^X//" >'solvers.c' <<'END_OF_FILE'
  2065. X
  2066. X/*
  2067. X * solvers.c
  2068. X * @(#)solvers.c    1.29 (UCLA) 10/15/92
  2069. X *
  2070. X * xbomb is Copyright (C) 1992 by Matthew Merzbacher, Los Angeles, CA.
  2071. X * All rights reserved.  Permission is granted to freely distribute
  2072. X * this as long as this copyright message is retained intact.
  2073. X * Permission to distribute this as part of a commerical product
  2074. X * requires explicit permission of the author.
  2075. X *
  2076. X */
  2077. X
  2078. X#include "xbomb.h"
  2079. X
  2080. X
  2081. X#define MAX_SOLVERS 10
  2082. Xchar *solvers[MAX_SOLVERS];
  2083. XFILE *solver_rfps[MAX_SOLVERS], *solver_wfps[MAX_SOLVERS];
  2084. Xint solver_pids[MAX_SOLVERS];
  2085. X
  2086. X
  2087. X    
  2088. Xvoid
  2089. Xrevoke_solvers()   /* Kill them ALL!  Yeah!  Slaughter! */
  2090. X{
  2091. X    int i;
  2092. X    for (i=0; i<MAX_SOLVERS; i++)
  2093. X        if (solver_pids[i]) {
  2094. X            fclose(solver_rfps[i]);
  2095. X            fclose(solver_wfps[i]);
  2096. X        };
  2097. X}
  2098. X
  2099. X
  2100. Xvoid
  2101. Xdump_map(fp, column, row)
  2102. X    FILE *fp;
  2103. X    int column, row;
  2104. X{
  2105. X    int x, y;
  2106. X    char ch;
  2107. X
  2108. X    fprintf (fp, "numbombs %d\n", numbombs);
  2109. X    fprintf (fp, "mouse %d %d\n", column, row);
  2110. X    fprintf (fp, "map\n");
  2111. X    for (y = 1; y <= height; y++) {
  2112. X        for (x = 1; x <= width; x++) {
  2113. X            if (map[x][y].status == KBOMB)
  2114. X                ch = 'X';
  2115. X            else if (map[x][y].flag)
  2116. X                ch = 'f';
  2117. X            else if (is_unknown(map[x][y].status))
  2118. X                ch = '.';
  2119. X            else ch = map[x][y].neighbors + '0';
  2120. X            fprintf (fp, "%c", ch);
  2121. X        };
  2122. X        fprintf (fp, "\n");
  2123. X    };
  2124. X    fprintf (fp, "\n");   /* blank line==end of dataset */
  2125. X    fflush(fp);
  2126. X}
  2127. X
  2128. X
  2129. Xvoid
  2130. Xreap_children()
  2131. X{
  2132. X    int pid, status;
  2133. X    int i;
  2134. X
  2135. X    for (;;) {
  2136. X        pid = waitpid(-1, &status, WNOHANG);
  2137. X        if (pid==-1 || pid==0)
  2138. X            return;  /* no children */
  2139. X        for (i=0; i<MAX_SOLVERS; i++)
  2140. X            if ((solvers[i] != NULL) && (solver_pids[i] == pid)) {
  2141. X                fclose(solver_rfps[i]);
  2142. X                fclose(solver_wfps[i]);
  2143. X                solver_rfps[i] = solver_wfps[i] = NULL;
  2144. X                solver_pids[i] = 0;
  2145. X                break;
  2146. X            };
  2147. X        if (i >= MAX_SOLVERS)
  2148. X            fprintf(stderr,"warning: %d reaped, but not sown\n",
  2149. X                pid);
  2150. X    };
  2151. X}
  2152. X
  2153. X
  2154. X        
  2155. Xint
  2156. Xexec_solver(s)
  2157. X    char *s;
  2158. X{
  2159. X    char tmps[512];
  2160. X    int error;
  2161. X    if (-1==(error = execl (s, s, NULL))) {
  2162. X        sprintf (tmps, "%s/%s", _PATH_SOLVERS, s);
  2163. X        error = execl(tmps,tmps,NULL);
  2164. X        if (error)
  2165. X            fprintf (stderr, "Solver not found as either %s or %s.\n",
  2166. X                 s, tmps);
  2167. X    };
  2168. X    return error;
  2169. X}
  2170. X
  2171. X
  2172. Xint
  2173. Xread_response(fp)
  2174. X    FILE *fp;
  2175. X{
  2176. X    int x, y, ret = 0;
  2177. X    char action;
  2178. X#define SLEN 80
  2179. X    char s[SLEN];
  2180. X
  2181. X    for (;;) {
  2182. X        if (NULL==fgets (s, SLEN, fp))
  2183. X            break;
  2184. X        if (s[0] == 0 || s[0] =='\n')
  2185. X            break;
  2186. X        if (3 != sscanf (s, "%d %d %c", &x, &y, &action))
  2187. X            break;
  2188. X        ret = 1;
  2189. X        switch (action) {
  2190. X        case 'f':
  2191. X            if (! map[x][y].flag)
  2192. X                place_flag(x,y);
  2193. X            break;
  2194. X        case 'm':
  2195. X            move_somewhere(x,y);
  2196. X            break;
  2197. X        case 'e':
  2198. X            fprintf (stderr, "Flagging empties not yet implemented.\n");
  2199. X            break;
  2200. X        default:
  2201. X            fprintf (stderr, "unknown action '%c'\n", action);
  2202. X            break;
  2203. X        };
  2204. X        putpix(x,y);
  2205. X    };
  2206. X
  2207. X    return(ret);
  2208. X    
  2209. X}
  2210. X
  2211. X
  2212. Xint
  2213. Xinvoke_solvers(n, column, row)
  2214. X    int n;
  2215. X    int column, row;
  2216. X{
  2217. X    int subproc;
  2218. X    int rp[2], wp[2];
  2219. X    FILE *rfp, *wfp;
  2220. X    int ret;
  2221. X    int error, status;
  2222. X
  2223. X    if (solvers[n] == NULL) { 
  2224. X        fprintf (stderr, "No solver #%d\n", n+1);
  2225. X        return 0;
  2226. X    };
  2227. X
  2228. X    reap_children();
  2229. X
  2230. X    /* put up a thinking light */
  2231. X    XCopyPlane(dpy, pixmaps[THINK], puzzleWindow, gc,
  2232. X               0, 0, WIDTH, HEIGHT, 5, 5, 1);
  2233. X    XFlush(dpy);
  2234. X
  2235. X    if (solver_pids[n] == 0) {
  2236. X        if (-1==pipe(rp))
  2237. X            bail("pipe");
  2238. X        if (-1==pipe(wp))
  2239. X            bail("pipe");
  2240. X        if (0==(subproc=fork())) {
  2241. X            if (-1==dup2 (wp[0], 0))
  2242. X                bail ("dup2-a");
  2243. X            if (-1==dup2 (rp[1], 1))
  2244. X                bail ("dup2-b");
  2245. X            close (rp[0]);
  2246. X            close (rp[1]);
  2247. X            close (wp[0]);
  2248. X            close (wp[1]);
  2249. X            /*
  2250. X             * Plug the security hole.
  2251. X             */
  2252. X            if (-1==seteuid(getuid()))
  2253. X                bail("seteuid");
  2254. X            if (-1==setegid(getgid()))
  2255. X                bail("setegid");
  2256. X            if (-1==exec_solver(solvers[n])) {
  2257. X                char tmps[80];
  2258. X                sprintf (tmps, "cannot invoke solver: %s\n", solvers[n]);
  2259. X                bail (tmps);
  2260. X            };
  2261. X            /*NOTREACHED*/
  2262. X        };
  2263. X        if (subproc == -1)
  2264. X            bail ("fork");
  2265. X        solver_pids[n] = subproc;
  2266. X        close (rp[1]);
  2267. X        close (wp[0]);
  2268. X        solver_rfps[n] = fdopen (rp[0], "r");
  2269. X        solver_wfps[n] = fdopen (wp[1], "w");
  2270. X    };
  2271. X    dump_map(solver_wfps[n], column, row);
  2272. X    ret = read_response(solver_rfps[n]);
  2273. X    reap_children();
  2274. X
  2275. X    /* take down thinking light */
  2276. X    XCopyPlane(dpy, pixmaps[BLANK], puzzleWindow, gc,
  2277. X               0, 0, WIDTH, HEIGHT, 5, 5, 1);
  2278. X    XFlush(dpy);
  2279. X
  2280. X    return(ret);
  2281. X}
  2282. X
  2283. END_OF_FILE
  2284. if test 4137 -ne `wc -c <'solvers.c'`; then
  2285.     echo shar: \"'solvers.c'\" unpacked with wrong size!
  2286. fi
  2287. # end of 'solvers.c'
  2288. fi
  2289. echo shar: End of archive 2 \(of 4\).
  2290. cp /dev/null ark2isdone
  2291. MISSING=""
  2292. for I in 1 2 3 4 ; do
  2293.     if test ! -f ark${I}isdone ; then
  2294.     MISSING="${MISSING} ${I}"
  2295.     fi
  2296. done
  2297. if test "${MISSING}" = "" ; then
  2298.     echo You have unpacked all 4 archives.
  2299.     rm -f ark[1-9]isdone
  2300. else
  2301.     echo You still need to unpack the following archives:
  2302.     echo "        " ${MISSING}
  2303. fi
  2304. ##  End of shell archive.
  2305. exit 0
  2306.