home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume28 / ldb / part01 < prev    next >
Encoding:
Text File  |  1992-03-14  |  51.7 KB  |  1,598 lines

  1. Newsgroups: comp.sources.misc
  2. From: ROSS@emf780.den.mmc.com ("Perry R. Ross")
  3. Subject:  REPOST: v28i093:  ldb - Play backgammon by e-mail, Part01/05
  4. Message-ID: <1992Mar13.183858.21284@sparky.imd.sterling.com>
  5. X-Md4-Signature: 91d542f66eedfd13b6d8c224f5982fb5
  6. Date: Fri, 13 Mar 1992 18:38:58 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: ROSS@emf780.den.mmc.com (Perry R. Ross)
  10. Posting-number: Volume 28, Issue 93
  11. Archive-name: ldb/part01
  12. Environment: UNIX, C, VMS, VAXC, CURSES, 32BIT
  13.  
  14.         Long Distance Backgammon
  15.  
  16.     This is a program that lets two people easily play backgammon
  17. by e-mail.  It currently runs only on character-oriented terminals
  18. (or emulators thereof) under the curses package.  It should work
  19. on any 32 bit UNIX system, as well as under VMS with VAX C.
  20.  
  21.     Ldb takes care of rolling dice, checking moves, and
  22. communicating with your opponent's ldb via e-mail.  Duplicated mail
  23. messages are rejected, and lost messages may be regenerated easily.
  24. Gammons and backgammons are detected, and the game value is automatically
  25. calculated at the end of the game.  Doubling is fully supported, and
  26. automatic doubles (when there is a tied opening roll) may be enabled
  27. at the user's option.  Ldb also allows you to enclose a two-line message
  28. with each move which will be displayed on your opponent's screen.
  29.  
  30.     To start a game, you only need to know your opponent's e-mail
  31. address.  Ldb will handle all negotiations involved with starting the
  32. game, performing the opening roll, re-rolling when there is a tie, etc.
  33. The README file has instructions for getting started quickly, and
  34. the manual has more detailed information.
  35.  
  36.     Note that this program does not play backgammon itself, it
  37. is merely enables two humans connected only by e-mail to do so.
  38. ----------
  39. #! /bin/sh
  40. # This is a shell archive.  Remove anything before this line, then unpack
  41. # it by saving it into a file and typing "sh file".  To overwrite existing
  42. # files, type "sh file -c".  You can also feed this as standard input via
  43. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  44. # will see the following message at the end:
  45. #        "End of archive 1 (of 5)."
  46. # Contents:  MANIFEST Makefile README board.c check.c control.c game.c
  47. #   makeldb.com move.c patchlevel.h readmail.c t_email.c
  48. # Wrapped by ross@emf780 on Tue Mar 10 09:24:11 1992
  49. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  50. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  51.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  52. else
  53. echo shar: Extracting \"'MANIFEST'\" \(1450 characters\)
  54. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  55. X   File Name        Archive #    Description
  56. X-----------------------------------------------------------
  57. X MANIFEST                   1    List of files
  58. X Makefile                   1    Compilation instructions
  59. X README                     1    Info file
  60. X board.c                    1    Routines pertaining to setting up boards
  61. X check.c                    1    Routines that check for legal moves
  62. X control.c                  1    Function to handle the -control option
  63. X fe_curses.c                5    Front end routines, based on curses package
  64. X game.c                     1    Functions to create/delete/find games
  65. X ldb.h                      2    Master include file
  66. X ldb.man                    4    The user's manual source ("make ldb.doc")
  67. X main.c                     2    The main program
  68. X makeldb.com                1    Command file to build ldb under vax c
  69. X misc.c                     2    Miscellaneous handy routines
  70. X move.c                     1    Performing/checking moves
  71. X patchlevel.h               1    Patch level (for patch program)
  72. X process.c                  3    Routines to perform local game processing
  73. X r_xrand.c                  2    Roll routine, based on xrand
  74. X rcvop.c                    3    Routines to handle received operations
  75. X readmail.c                 1    Routines that read & process incoming mail
  76. X save.c                     3    Routines that save and load things
  77. X t_email.c                  1    Transport routine, based on mail
  78. X vars.c                     2    All global variables.
  79. END_OF_FILE
  80. if test 1450 -ne `wc -c <'MANIFEST'`; then
  81.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  82. fi
  83. # end of 'MANIFEST'
  84. fi
  85. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  86.   echo shar: Will not clobber existing file \"'Makefile'\"
  87. else
  88. echo shar: Extracting \"'Makefile'\" \(3201 characters\)
  89. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  90. X# Makefile for ldb    8/3/91
  91. X#
  92. X# Copyright 1991  Perry R. Ross
  93. X#
  94. X# Permission to use, copy, modify, and distribute this software and its
  95. X# documentation without fee is hereby granted, subject to the restrictions
  96. X# detailed in the README file, which is included here by reference.
  97. X# Any other use requires written permission from the author.  This software
  98. X# is distributed "as is" without any warranty, including any implied
  99. X# warranties of merchantability or fitness for a particular purpose.
  100. X# The author shall not be liable for any damages resulting from the
  101. X# use of this software.  By using this software, the user agrees
  102. X# to these terms.
  103. X
  104. X### INSTALLATION OPTIONS ###
  105. X# If your host uses an ancient version of curses (e.g. VAX-C, Sequent),
  106. X# uncomment the following line.  To tell if you need this option,
  107. X# first try compiling without it and see if your linker complains
  108. X# about cbreak() and nocbreak() not being defined.  If it does,
  109. X# you need this option.
  110. XCDEFS=
  111. X# CDEFS=-DOLD_CURSES
  112. X
  113. X# Uncomment the following lines only if you are using Eunice.
  114. X# If you don't know what it is, believe me, you're not using it.
  115. XUNIXTOVMS=true
  116. XVMSTOUNIX=true
  117. X# UNIXTOVMS=unixtovms
  118. X# VMSTOUNIX=vmstounix
  119. X
  120. X# Put the name of the front-end you want to compile in here.
  121. X# NOTE: there is currently only one available front-end (curses).
  122. XFE_FILE=fe_curses
  123. X
  124. X# Put the name of the transport you want to compile in here.
  125. X# NOTE: there is currently only one available transport (email).
  126. XT_FILE=t_email
  127. X
  128. X# Put the name of the dice roller you want to compile in here.
  129. X# If you want to write your own dice roller, you can.  I would
  130. X# prefer people all used the same one, since that is more fair,
  131. X# but as long as it is really a random number generator, you're ok.
  132. X# If you put in a fake dice roller (e.g. one that asks you what
  133. X# roll you want), you are in violation of the copyright.  Read
  134. X# the README file for more information.
  135. XR_FILE=r_xrand
  136. X
  137. X# Put compiler flags here.
  138. XCFLAGS=-O $(CDEFS)
  139. XLINTFLAGS=
  140. X
  141. X# Page length to format manual with.  62 for VMS or Eunice, 66 for most others.
  142. XPAGELEN=66
  143. X
  144. X### END OF INSTALLATION OPTIONS ###
  145. X
  146. XCFILES=    board.c game.c main.c misc.c move.c process.c rcvop.c control.c \
  147. X    check.c readmail.c save.c vars.c $(FE_FILE).c $(T_FILE).c $(R_FILE).c
  148. XHFILES=ldb.h patchlevel.h
  149. XOFILES=    board.o game.o main.o misc.o move.o process.o rcvop.o control.o \
  150. X    check.o readmail.o save.o vars.o $(FE_FILE).o $(T_FILE).o $(R_FILE).o
  151. XSHARFILES=MANIFEST README Makefile $(CFILES) $(HFILES) makeldb.com ldb.man
  152. X
  153. Xldb: $(OFILES)
  154. X    cc $(CFLAGS) -s -o ldb $(OFILES) -lcurses -ltermcap
  155. X
  156. Xall: ldb ldb.doc
  157. X
  158. Xldb.doc: ldb.man
  159. X    nroff -rT$(PAGELEN) -man ldb.man >ldb.doc
  160. X    $(UNIXTOVMS) ldb.doc
  161. X
  162. Xldb.doc60: ldb.man
  163. X    nroff -rT60 -man ldb.man >ldb.doc60
  164. X    $(UNIXTOVMS) ldb.doc60
  165. X
  166. Xldb.doc62: ldb.man
  167. X    nroff -rT62 -man ldb.man >ldb.doc62
  168. X    $(UNIXTOVMS) ldb.doc62
  169. X
  170. Xldb.doc66: ldb.man
  171. X    nroff -rT66 -man ldb.man >ldb.doc66
  172. X    $(UNIXTOVMS) ldb.doc66
  173. X
  174. Xlint: .XXX
  175. X    lint $(LINTFLAGS) $(CFILES) > lint.out
  176. X
  177. Xclean: .XXX
  178. X    rm -f $(OFILES) ldb *.obj ldb.exe make.out .mk lint.out MANIFEST.BAK
  179. X
  180. Xshar: $(SHARFILES)
  181. X    $(VMSTOUNIX) $(SHARFILES)
  182. X    makekit -m
  183. X
  184. Xtags: .XXX
  185. X    ctags $(CFILES)
  186. X    sed 's/Mmain/main/' <tags | sort >.tags
  187. X    mv .tags tags
  188. X
  189. X.XXX:
  190. END_OF_FILE
  191. if test 3201 -ne `wc -c <'Makefile'`; then
  192.     echo shar: \"'Makefile'\" unpacked with wrong size!
  193. fi
  194. chmod +x 'Makefile'
  195. # end of 'Makefile'
  196. fi
  197. if test -f 'README' -a "${1}" != "-c" ; then 
  198.   echo shar: Will not clobber existing file \"'README'\"
  199. else
  200. echo shar: Extracting \"'README'\" \(4907 characters\)
  201. sed "s/^X//" >'README' <<'END_OF_FILE'
  202. X        Long Distance Backgammon
  203. X        ------------------------
  204. X
  205. X    This is a program that lets two people easily play backgammon
  206. Xby e-mail.  It currently runs only on character-oriented terminals
  207. X(or emulators thereof) under the curses package.
  208. X
  209. X    To build ldb, create a directory, copy all the parts into
  210. Xthat directory, strip the usenet or mail headers with a text editor,
  211. Xand execute them with a shell (e.g. sh Part1; sh Part2; ...).
  212. XThe installation options are documented in the Makefile.  The only
  213. Xone of any importance is the one that allows the OLD_CURSES symbol
  214. Xto be defined.  If you get linker errors complaining about cbreak()
  215. Xand nocbreak(), you will need to enable this option.  If your system
  216. Xneeds this, and you know a unique symbol your preprocessor predefines,
  217. Xsend it to me and I'll include it in future releases.
  218. X
  219. X    Suggestions and problems are cheerfully accepted, all the more
  220. Xso when accompanied by appropriate patches, in any format the patch
  221. Xprogram understands (e.g. context diff).  E-mail to ross@emf780.den.mmc.com.
  222. X
  223. X    The first time ldb is run, it will create a file in your home
  224. Xdirectory called ".ldbrc".  If this name is inconvenient, define the
  225. Xenvironment variable LDBRC to be the name you want before running it
  226. Xthe first time (and all times after that).  Ldb will ask for your
  227. Xpersonal, human-type name and your e-mail address.  All other options
  228. Xwill be set to their defaults, as explained in the manual.
  229. X
  230. X    To start a game, type:
  231. X        ldb -start opponent's-email-address
  232. X    and everything is automatic from there.  You may have to exchange
  233. Xseveral mail messages before you are ready to play, since your ldb has to
  234. Xdo the initial roll with the remote ldb, and if there is a tie, the
  235. Xinitial roll is repeated.  Eventually, you will see a board drawn on
  236. Xthe screen.  The commands are in the bottom right corner.  The moves by
  237. Xyou and your opponent are above that, on the right side of the screen, and
  238. Xthe bottom of the screen contains a place for you to enclose a 2-line
  239. Xmessage with each move.  This is useful for taunting, pleading, etc.
  240. XYou will need to press 'r' to roll the dice, then press the number of the roll
  241. Xyou want to use followed by the point you want to move from.  For example,
  242. Xif you roll 5 2, and you want to move the piece on the 11 point 5, press
  243. X5 1 1.  You don't need to hit return, but if the point number is 1 digit,
  244. Xyou will need to type some non-numeric digit after it to finish the
  245. X2 characters.  After you have used one of your rolls, there are 3 shortcuts
  246. Xyou can use for the remainder of your roll:
  247. X    <space bar>    Continues the last move.  The piece you last moved
  248. X            is moved by the amount of the other/next roll.
  249. X    <return>    Repeat the last move.  The other/next roll is applied
  250. X            to the same point you moved from last time.
  251. X    p        Make point.  This gets a little tricky.  Ldb attempts
  252. X            to use the other/next roll to move one of your pieces
  253. X            so that it ends up on the same point as your last move
  254. X            ended on.  That is, if you roll 5 2 and use the 5
  255. X            to move from the 6 point to the 11 point, and hit "p",
  256. X            ldb will move one of your pieces from the 9 point to
  257. X            the 11 point to make the 11 point.  This assumes,
  258. X            of course, that you have a piece on the 9 point.
  259. X
  260. X    Ldb checks your moves for a number of common errors.  These 
  261. Xare listed in the manual.
  262. X
  263. X    For more options, read the manual and the comments at the top
  264. Xof main.c.
  265. X
  266. X    Good luck!
  267. X
  268. X                        Perry R. Ross
  269. X                        ross@emf780.den.mmc.com
  270. X
  271. X-----------------------------------------------------------------------------
  272. X
  273. X    Really Scary and Hopefully Bulletproof Legal Statement:
  274. X
  275. XThis software is copyright 1991 by Perry R. Ross.  Permission to use,
  276. Xcopy, modify, and redistribute it is granted provided:
  277. X    (1) It is not sold.
  278. X    (2) This notice accompanies all copies, and is kept intact.
  279. X    (3) Users do not cheat by any method, including but not limited to:
  280. X        A. modifying the roll generated by the random number generator,
  281. X        B. modifying the code to provide any roll other than that
  282. X           generated by a bona-fide random number generator,
  283. X        C. taking advantage of any non-randomness in a random
  284. X           number generator to predict upcoming rolls,
  285. X        D. changing the contents of an incoming message or of the
  286. X           .ldbdata file to modify the normal progression of a
  287. X           game in any way, or
  288. X        E. generating a roll before offering to double.
  289. X       Persons guilty of cheating in any way while using this software
  290. X       are denied permission to use or distribute this software
  291. X       in perpetuity.  Excluded from the definition of cheating is
  292. X       any action whose intention is to test or debug this software,
  293. X       as long as the opponent is aware that these actions are being
  294. X       performed, and the game is considered "unofficial".
  295. XThe above restrictions are made in all seriousness, and with every
  296. Xintention of enforcement by any and all legal means where practical.
  297. X
  298. X(Sounds almost as good as the real thing, doesn't it?)
  299. END_OF_FILE
  300. if test 4907 -ne `wc -c <'README'`; then
  301.     echo shar: \"'README'\" unpacked with wrong size!
  302. fi
  303. chmod +x 'README'
  304. # end of 'README'
  305. fi
  306. if test -f 'board.c' -a "${1}" != "-c" ; then 
  307.   echo shar: Will not clobber existing file \"'board.c'\"
  308. else
  309. echo shar: Extracting \"'board.c'\" \(2195 characters\)
  310. sed "s/^X//" >'board.c' <<'END_OF_FILE'
  311. X/* board.c        8/3/91
  312. X *
  313. X * Copyright 1991  Perry R. Ross
  314. X *
  315. X * Permission to use, copy, modify, and distribute this software and its
  316. X * documentation without fee is hereby granted, subject to the restrictions
  317. X * detailed in the README file, which is included here by reference.
  318. X * Any other use requires written permission from the author.  This software
  319. X * is distributed "as is" without any warranty, including any implied
  320. X * warranties of merchantability or fitness for a particular purpose.
  321. X * The author shall not be liable for any damages resulting from the
  322. X * use of this software.  By using this software, the user agrees
  323. X * to these terms.
  324. X */
  325. X
  326. X#include "ldb.h"
  327. X
  328. X/*----------------------------------------------------------------------
  329. X *    newboard -- set up a board array for a new game
  330. X *
  331. X * This function initializes a board array so that it is set up
  332. X * properly for a new game.  It is passed two characters that are
  333. X * used to draw the pieces for the board.  C1 is the color for the
  334. X * upbound player, and c2 is the color for the downbound player.
  335. X *----------------------------------------------------------------------
  336. X */
  337. X
  338. Xnewboard(b,c1,c2)
  339. Xboard b;
  340. Xchar c1, c2;
  341. X{
  342. Xint i;
  343. X
  344. Xfor (i = 0; i < BOARDSIZE; i++) {
  345. X    b[i].qty = 0;            /* init to empty */
  346. X    b[i].color = 'x';        /* init to invalid color */
  347. X    }
  348. Xb[1].qty = 2;                /* 2 c1's on 1 point */
  349. Xb[1].color = c1;
  350. Xb[6].qty = 5;                /* 5 c2's on 6 point */
  351. Xb[6].color = c2;
  352. Xb[8].qty = 3;                /* 3 c2's on 8 point */
  353. Xb[8].color = c2;
  354. Xb[12].qty = 5;                /* 5 c1's on 12 point */
  355. Xb[12].color = c1;
  356. Xb[13].qty = 5;                /* 5 c2's on 13 point */
  357. Xb[13].color = c2;
  358. Xb[17].qty = 3;                /* 3 c1's on 17 point */
  359. Xb[17].color = c1;
  360. Xb[19].qty = 5;                /* 5 c1's on 19 point */
  361. Xb[19].color = c1;
  362. Xb[24].qty = 2;                /* 2 c2's on 24 point */
  363. Xb[24].color = c2;
  364. X}
  365. X
  366. X
  367. X/*----------------------------------------------------------------------
  368. X *    copyboard -- make a copy a board array
  369. X *
  370. X * This is a convenience function that copies an entire board. The
  371. X * source is given as "f", and the destination as "t".
  372. X *----------------------------------------------------------------------
  373. X */
  374. X
  375. Xcopyboard(f,t)
  376. Xboard f, t;
  377. X{
  378. Xint i;
  379. X
  380. Xfor (i = 0; i < BOARDSIZE; i++)
  381. X    t[i] = f[i];
  382. X}
  383. END_OF_FILE
  384. if test 2195 -ne `wc -c <'board.c'`; then
  385.     echo shar: \"'board.c'\" unpacked with wrong size!
  386. fi
  387. chmod +x 'board.c'
  388. # end of 'board.c'
  389. fi
  390. if test -f 'check.c' -a "${1}" != "-c" ; then 
  391.   echo shar: Will not clobber existing file \"'check.c'\"
  392. else
  393. echo shar: Extracting \"'check.c'\" \(5300 characters\)
  394. sed "s/^X//" >'check.c' <<'END_OF_FILE'
  395. X/*    check.c        10/29/91
  396. X *
  397. X * Copyright 1991  Perry R. Ross
  398. X *
  399. X * Permission to use, copy, modify, and distribute this software and its
  400. X * documentation without fee is hereby granted, subject to the restrictions
  401. X * detailed in the README file, which is included here by reference.
  402. X * Any other use requires written permission from the author.  This software
  403. X * is distributed "as is" without any warranty, including any implied
  404. X * warranties of merchantability or fitness for a particular purpose.
  405. X * The author shall not be liable for any damages resulting from the
  406. X * use of this software.  By using this software, the user agrees
  407. X * to these terms.
  408. X */
  409. X
  410. X#include "ldb.h"
  411. X
  412. X/*======================================================================
  413. X * This file contains the functions that check for unused moves.
  414. X *======================================================================
  415. X */
  416. X
  417. X
  418. XPRIVATE int maxused, hiused, nlegal;
  419. X
  420. Xstruct legal *rmlegal();
  421. X
  422. X
  423. Xlegalmoves(g)
  424. Xstruct game *g;
  425. X{
  426. Xstruct game tmp;
  427. Xint i;
  428. Xstruct legal *l;
  429. X
  430. Xtmp = *g;            /* we don't want to change actual game */
  431. Xfor (i = 0; i < 4; tmp.mvs[i++].pt = -1);    /* mark all unused */
  432. Xmaxused = -1;            /* init to not all used */
  433. Xhiused = 0;            /* init to 0 */
  434. Xnlegal = 0;            /* init to no legal moves*/
  435. Xlhead = NULL;
  436. Xltail = NULL;
  437. Xif (tmp.mvs[0].roll == tmp.mvs[1].roll)
  438. X    scanmvs(&tmp,0,3);    /* there is only one ordering */
  439. Xelse {
  440. X    scanmvs(&tmp,0,1);        /* scan for one ordering */
  441. X    i = tmp.mvs[0].roll;    /* reverse rolls */
  442. X    tmp.mvs[0].roll = tmp.mvs[1].roll;
  443. X    tmp.mvs[1].roll = i;
  444. X    for (i = 0; i < 4; tmp.mvs[i++].pt = -1);    /* mark all unused */
  445. X    scanmvs(&tmp,0,1);        /* scan for other ordering */
  446. X    }
  447. Xtrimunused();
  448. Xtrimlowused();
  449. Xtrimequal();
  450. Xg->maxused = maxused;
  451. Xg->hiused = hiused;
  452. Xif (nlegal == 0) {
  453. X    if (g->dispmsg != NULL)
  454. X        free(g->dispmsg);
  455. X    g->dispmsg = save("You don't have any legal moves.");
  456. X    }
  457. Xelse if (nlegal == 1) {
  458. X    if (g->dispmsg != NULL)
  459. X        free(g->dispmsg);
  460. X    g->dispmsg = save("You only have one legal move.");
  461. X    if (*rc.automove == 'y') {
  462. X        if ( (lhead->nmove==0) && (lhead->mvs[0].roll!=g->mvs[0].roll))
  463. X            g->mvs[1] = g->mvs[0];
  464. X        for (i = 0; i <= lhead->nmove; i++) {
  465. X            g->mvs[i] = lhead->mvs[i];
  466. X            apply(g,1,i,0,NULL);
  467. X            }
  468. X        }
  469. X    }
  470. X
  471. X    /* we have no use for the legal moves list, so free it */
  472. X    /* maybe in the future we will have a use for it */
  473. X
  474. Xfor (l = lhead; l != NULL; l = l->next)
  475. X    free(l);
  476. Xlhead = NULL;
  477. Xltail = NULL;
  478. X}
  479. X
  480. X
  481. Xscanmvs(g,mn,max)
  482. Xstruct game *g;
  483. X{
  484. Xint i;
  485. Xboard sv;
  486. X
  487. Xcopyboard(g->board,sv);
  488. Xfor (i = 0; i <= 24; i++) {
  489. X    if (i == 0)
  490. X        g->mvs[mn].pt = BARPT(g->mydir);
  491. X    else
  492. X        g->mvs[mn].pt = i;
  493. X    if (apply(g,1,mn,0,NULL) < 0)    /* can't move from this pt */
  494. X        continue;
  495. X    addlegal(mn,g->mvs[mn].roll,g->mvs[mn].pt);
  496. X    if (mn < max)
  497. X        scanmvs(g,mn+1,max);
  498. X    copyboard(sv,g->board);
  499. X    }
  500. X}
  501. X
  502. X
  503. Xaddlegal(mn,r,pt)
  504. Xint mn, r, pt;
  505. X{
  506. Xint i;
  507. Xstruct legal *n;
  508. X
  509. Xif ( (n = (struct legal *) calloc(sizeof(struct legal),1)) == NULL) {
  510. X    FeFinishSession();
  511. X    TFinishSession();
  512. X    fprintf(stderr,"Out of memory!\n");
  513. X    exit(1);
  514. X    }
  515. Xclearmvs(n->mvs);
  516. Xif (ltail != NULL)
  517. X    for (i = 0; i < mn; i++)        /* copy prefix from prev move */
  518. X        n->mvs[i] = ltail->mvs[i];
  519. Xn->mvs[mn].roll = r;
  520. Xn->mvs[mn].pt = pt;
  521. Xn->next = NULL;
  522. Xif (lhead == NULL) {
  523. X    n->prev = NULL;
  524. X    lhead = n;
  525. X    ltail = n;
  526. X    }
  527. Xelse {
  528. X    n->prev = ltail;
  529. X    ltail->next = n;
  530. X    ltail = n;
  531. X    }
  532. Xn->himove = 0;
  533. Xfor (i = 0; i <= mn; i++)
  534. X    if (n->mvs[i].roll > n->himove)
  535. X        n->himove = n->mvs[i].roll;
  536. Xif (mn > maxused)        /* keep track of whether it is possible */
  537. X    maxused = mn;    /* to use all of the rolls */
  538. Xnlegal++;
  539. Xn->nmove = mn;
  540. X}
  541. X
  542. X
  543. Xtrimunused()
  544. X{
  545. Xstruct legal *l;
  546. X
  547. Xl = lhead;
  548. Xwhile (l != NULL) {
  549. X    if (l->nmove < maxused)
  550. X        l = rmlegal(l);
  551. X    else
  552. X        l = l->next;
  553. X    }
  554. X}
  555. X
  556. X
  557. Xtrimlowused()
  558. X{
  559. Xstruct legal *l;
  560. X
  561. Xl = lhead;
  562. Xwhile (l != NULL) {
  563. X    if (l->himove < hiused)
  564. X        l = rmlegal(l);
  565. X    else
  566. X        l = l->next;
  567. X    }
  568. X}
  569. X
  570. X
  571. Xtrimequal()
  572. X{
  573. Xstruct legal *l, *p;
  574. Xstruct mv m1[4], m2[4];
  575. Xint i, n;
  576. X
  577. Xfor (l = lhead; l != NULL; l = l->next) {
  578. X    extractmvs(l,m1);
  579. X    n = l->nmove;
  580. X    p = l->next;
  581. X    while (p != NULL) {
  582. X        if (p->nmove != n) {
  583. X            p = p->next;
  584. X            continue;
  585. X            }
  586. X        extractmvs(p,m2);
  587. X        for (i = 0; i <= n; i++)
  588. X            if ((m1[i].roll != m2[i].roll)||(m1[i].pt != m2[i].pt))
  589. X                break;
  590. X        if (i <= n)
  591. X            p = p->next;
  592. X        else
  593. X            p = rmlegal(p);
  594. X        }
  595. X    }
  596. X}
  597. X
  598. X
  599. Xstruct legal *rmlegal(l)
  600. Xstruct legal *l;
  601. X{
  602. Xstruct legal *t;
  603. X
  604. Xt = l;
  605. Xif (l == lhead) {
  606. X    lhead = l->next;
  607. X    l = lhead;
  608. X    }
  609. Xelse {
  610. X    if ( (l->prev->next = l->next) != NULL)
  611. X        l->next->prev = l->prev;
  612. X    l = l->next;
  613. X    }
  614. Xfree(t);
  615. Xnlegal--;
  616. Xreturn(l);
  617. X}
  618. X
  619. X
  620. Xextractmvs(l,m)
  621. Xstruct legal *l;
  622. Xstruct mv *m;
  623. X{
  624. Xint i, n, s;
  625. Xstruct mv tmp;
  626. X
  627. Xclearmvs(m);
  628. Xfor (i = 0; i <= l->nmove; i++)        /* extract the moves */
  629. X    m[i] = l->mvs[i];
  630. Xn = l->nmove;
  631. Xdo {            /* sort by increasing roll then increasing point */
  632. X    s = 0;
  633. X    for (i = 0; i < n; i++) {        /* long live bubblesort */
  634. X        if (m[i].roll < m[i+1].roll)
  635. X            continue;
  636. X        else if ( (m[i].roll == m[i+1].roll) && (m[i].pt < m[i+1].pt) )
  637. X            continue;
  638. X        tmp = m[i];
  639. X        m[i] = m[i+1];
  640. X        m[i+1] = tmp;
  641. X        s = 1;
  642. X        }
  643. X    n--;
  644. X    } while (s);
  645. X}
  646. X
  647. X
  648. Xcheckused(g)
  649. Xstruct game *g;
  650. X{
  651. Xint h, i;
  652. X
  653. Xh = 0;
  654. Xfor (i = 0; i <= g->maxused; i++) {
  655. X    if (g->mvs[i].pt < 0) {
  656. X        FeMessage("You left a roll unused.");
  657. X        return(1);
  658. X        }
  659. X    if (h < g->mvs[i].roll)
  660. X        h = g->mvs[i].roll;
  661. X    }
  662. Xif (g->hiused > h) {
  663. X    FeMessage("You can use the higher roll.");
  664. X    return(1);
  665. X    }
  666. Xreturn(0);
  667. X}
  668. END_OF_FILE
  669. if test 5300 -ne `wc -c <'check.c'`; then
  670.     echo shar: \"'check.c'\" unpacked with wrong size!
  671. fi
  672. chmod +x 'check.c'
  673. # end of 'check.c'
  674. fi
  675. if test -f 'control.c' -a "${1}" != "-c" ; then 
  676.   echo shar: Will not clobber existing file \"'control.c'\"
  677. else
  678. echo shar: Extracting \"'control.c'\" \(3519 characters\)
  679. sed "s/^X//" >'control.c' <<'END_OF_FILE'
  680. X/*    control.c        9/12/91
  681. X *
  682. X * Copyright 1991  Perry R. Ross
  683. X *
  684. X * Permission to use, copy, modify, and distribute this software and its
  685. X * documentation without fee is hereby granted, subject to the restrictions
  686. X * detailed in the README file, which is included here by reference.
  687. X * Any other use requires written permission from the author.  This software
  688. X * is distributed "as is" without any warranty, including any implied
  689. X * warranties of merchantability or fitness for a particular purpose.
  690. X * The author shall not be liable for any damages resulting from the
  691. X * use of this software.  By using this software, the user agrees
  692. X * to these terms.
  693. X */
  694. X
  695. X#include "ldb.h"
  696. X
  697. X/*----------------------------------------------------------------------
  698. X *    control -- control a game
  699. X *
  700. X * This function is called to process the -control command line option.
  701. X * It currently allows the following:
  702. X *    -    The board may be inverted.  The points are still numbered the
  703. X *    same, the board is merely drawn upside down.  This can help users
  704. X *    who are playing a number of games simultaneously by allowing him
  705. X *    to make all of his games move in the same direction on the screen.
  706. X *    - The last packet sent may be resent.  This is useful when moves
  707. X *    are lost in the mail, or if players forget whose turn it is.
  708. X *    Ldb rejects packets that have already been received, so both
  709. X *    players may simply resend their last packet, and ldb will display
  710. X *    the board to the player who is supposed to move.
  711. X *----------------------------------------------------------------------
  712. X */
  713. X
  714. Xcontrol()
  715. X{
  716. Xregister struct game *g;
  717. Xstatic char *m[] = {"Invert","Resend","Delete Game","Next Game","Quit",NULL};
  718. Xchar buf[60], c, done;
  719. Xint mod;
  720. X
  721. Xif (ghead == NULL) {
  722. X    printf("You don't have any games in progress.\n");
  723. X    printf("Use the -start option to start one.\n");
  724. X    usage(0);
  725. X    exit(1);
  726. X    }
  727. Xmod = 0;                /* init to no mods */
  728. XFeInitialize();                /* initialize front end */
  729. XFeDrawScreen();                /* draw board outline */
  730. Xdone = 0;
  731. Xfor (g = ghead; (done < 2) && (g != NULL); g = g->next) {/* for all games */
  732. X    g->curbd = BD_CUR;        /* make sure we draw the current bd */
  733. X    FeDrawGame(g);
  734. X    FeDrawMenu(m);
  735. X    sprintf(buf,"Current state: %s",states[g->state]);
  736. X    FeMessage(buf);
  737. X    done = 0;
  738. X    while (! done) {
  739. X        c = FeMenu(m,0,0," \n\r");
  740. X        switch (c) {
  741. X        case 'I':            /* invert board */
  742. X            g->flags ^= F_INVERT;    /* toggle invert bit */
  743. X            FeDrawGame(g);        /* redraw the screen */
  744. X            mod++;            /* games have been modified */
  745. X            break;
  746. X        case 'R':            /* resend last packet */
  747. X            sendpkt(g,g->lastop);
  748. X            FeMessage("Last packet re-sent.");
  749. X            break;
  750. X        case 'D':            /* delete game */
  751. X            mod++;            /* games have been modified */
  752. X            if (g->flags & F_DELETE) {    /* undelete */
  753. X                g->flags &= ~F_DELETE;
  754. X                FeMessage("Game undeleted.");
  755. X                }
  756. X            else {
  757. X                g->flags |= F_DELETE;    /* delete */
  758. X                FeMessage(
  759. X                 "Game deleted -- press D again to undelete.");
  760. X                }
  761. X            break;
  762. X        case 'Q':            /* exit ldb */
  763. X            done = 2;        /* 2 means Really done */
  764. X            break;
  765. X        case 'N':
  766. X        case ' ':
  767. X        case '\n':
  768. X        case '\r':
  769. X            done = 1;    /* 1 means just done with this game */
  770. X            break;        /* go to next game */
  771. X            }
  772. X        }
  773. X    }
  774. XFeFinishSession();
  775. Xwhile (mod) {
  776. X    printf("Save changes? [yn]: ");
  777. X    if ( ( (c = getchar()) == 'y') || (c == 'Y') ) {
  778. X        writegames(rc.gfile,rc.gbackup);
  779. X        break;
  780. X        }
  781. X    if ( (c == 'n') || (c == 'N') ) {
  782. X        printf("Changes discarded.\n");
  783. X        break;
  784. X        }
  785. X    if ( (c != '\n') && (c != EOF) )
  786. X        while ( ( (c = getchar()) != '\n') && (c != EOF) );
  787. X    printf("Please respond with y or n.\n");
  788. X    }
  789. X}
  790. END_OF_FILE
  791. if test 3519 -ne `wc -c <'control.c'`; then
  792.     echo shar: \"'control.c'\" unpacked with wrong size!
  793. fi
  794. chmod +x 'control.c'
  795. # end of 'control.c'
  796. fi
  797. if test -f 'game.c' -a "${1}" != "-c" ; then 
  798.   echo shar: Will not clobber existing file \"'game.c'\"
  799. else
  800. echo shar: Extracting \"'game.c'\" \(6317 characters\)
  801. sed "s/^X//" >'game.c' <<'END_OF_FILE'
  802. X/*    game.c        8/3/91
  803. X *
  804. X * Copyright 1991  Perry R. Ross
  805. X *
  806. X * Permission to use, copy, modify, and distribute this software and its
  807. X * documentation without fee is hereby granted, subject to the restrictions
  808. X * detailed in the README file, which is included here by reference.
  809. X * Any other use requires written permission from the author.  This software
  810. X * is distributed "as is" without any warranty, including any implied
  811. X * warranties of merchantability or fitness for a particular purpose.
  812. X * The author shall not be liable for any damages resulting from the
  813. X * use of this software.  By using this software, the user agrees
  814. X * to these terms.
  815. X */
  816. X
  817. X#include "ldb.h"
  818. X
  819. X/*----------------------------------------------------------------------
  820. X *    startgame -- start a game
  821. X *
  822. X * This function is called in response to the -start command line
  823. X * option to start a game with another user.  It allocates a game
  824. X * record and fills it in, then sends a START packet to the opponent.
  825. X * The arguments are:
  826. X *    The email address of the opponent
  827. X *    The direction I want to play
  828. X *    The color I want to play
  829. X *    The color I want the opponent to play
  830. X *----------------------------------------------------------------------
  831. X */
  832. X
  833. Xstruct game *startgame(addr,d,mc,oc)
  834. Xchar *addr;            /* path to opponent */
  835. Xint d;
  836. Xchar mc, oc;
  837. X{
  838. Xstruct game *g;
  839. Xchar c1, c2, *newid;
  840. X
  841. Xnewid = makeid();        /* give it a unique id */
  842. Xg = addgame();            /* allocate new game */
  843. Xg->gameid = newid;        /* store new id */
  844. Xg->opaddr = save(addr);        /* save opponent's mail addr */
  845. Xg->opname = NULL;        /* we don't know his name yet */
  846. Xg->mycolor = mc;        /* set starting colors */
  847. Xg->opcolor = oc;
  848. Xg->mydir = d;            /* set starting directions */
  849. Xg->opdir = REV(d);
  850. Xg->gameval = 1;            /* no doubles yet */
  851. Xg->adcnt = 0;            /* no autodoubles yet */
  852. Xg->admax = rc.autodouble;    /* max allowed autodoubles */
  853. Xg->flags = 0;
  854. Xg->state = ST_OPSTART;        /* need to send first roll */
  855. Xg->seq = 1;            /* start with sequence number = 1 */
  856. Xif (d > 0) {
  857. X    c1 = mc;    /* upbound color is mine */
  858. X    c2 = oc;    /* downbound color is opponent's */
  859. X    }
  860. Xelse {
  861. X    c1 = oc;    /* upbound color is opponent's */
  862. X    c2 = mc;    /* downbound color is mine */
  863. X    }
  864. Xclearmvs(g->mvs);
  865. Xclearmvs(g->opmvs);
  866. Xnewboard(g->opbd,c1,c2);    /* set up boards for new game */
  867. Xnewboard(g->mybd,c1,c2);
  868. Xnewboard(g->board,c1,c2);
  869. Xg->mvs[0].roll = Rolldie();    /* roll an initial die */
  870. Xsendpkt(g,START);        /* send the start message */
  871. Xreturn(g);            /* and return pointer to new game */
  872. X}
  873. X
  874. X
  875. X/*----------------------------------------------------------------------
  876. X *    makeid -- create a unique game identifier.
  877. X *
  878. X * This function creates a string that is guaranteed unique among all
  879. X * ldb games worldwide, provided that email addresses are unique.
  880. X * This should be a good assumption, since if there is a duplicate,
  881. X * the users with the duplicate id's will have a great deal of difficulty
  882. X * getting mail delivered, and therefore won't be able to play ldb anyway.
  883. X * To make id's created by the same user unique, the time is
  884. X * appended to the mail address; to make sure the time is unique when
  885. X * the user creates more than 1 game per second, the games list is searched
  886. X * for a new id before it is returned and, if it is found, we sleep for
  887. X * 1 second and try again.
  888. X *----------------------------------------------------------------------
  889. X */
  890. X
  891. Xchar *makeid()
  892. X{
  893. Xchar *n;
  894. X
  895. Xif ( (n = calloc(strlen(rc.myaddr)+10,1)) == NULL) {
  896. X    FeFinishSession();    /* close down front-end */
  897. X    TFinishSession();    /* close down transport */
  898. X    fprintf(stderr,"ERROR: Out of memory!\n");
  899. X    exit(1);
  900. X    }
  901. Xdo {
  902. X    sprintf(n,"%s|%08x",rc.myaddr,time(0));
  903. X    if (findgame(n) == NULL)
  904. X        return(n);
  905. X    sleep(1);
  906. X    } while (1);
  907. X}
  908. X
  909. X
  910. X/*---------------------------------------------------------------------------
  911. X *    addgame -- allocate a game struct and link it into the game list
  912. X *
  913. X * This function allocates a game structure and links it into the
  914. X * doubly-linked game list.  The head of this list is ghead, and the
  915. X * tail is gtail.
  916. X *
  917. X * NOTE: the memory-zeroing feature of calloc is depended on to
  918. X *     initialize the allocated game struct.
  919. X *---------------------------------------------------------------------------
  920. X */
  921. X
  922. Xstruct game *addgame()
  923. X{
  924. Xstruct game *g;
  925. X
  926. Xif ( (g = (struct game *)calloc(sizeof(struct game),1)) == NULL) {
  927. X    FeFinishSession();    /* close down front-end */
  928. X    TFinishSession();    /* close down transport */
  929. X    fprintf(stderr,"Out of memory!\n");
  930. X    exit(1);
  931. X    }
  932. Xg->next = NULL;
  933. Xif (gtail == NULL) {        /* this is the first game in the list */
  934. X    ghead = g;
  935. X    gtail = g;
  936. X    g->prev = NULL;
  937. X    }
  938. Xelse {
  939. X    g->prev = gtail;    /* link onto end of list */
  940. X    gtail->next = g;
  941. X    gtail = g;
  942. X    }
  943. Xreturn(g);
  944. X}
  945. X
  946. X
  947. X/*----------------------------------------------------------------------
  948. X *    deletegame -- delete a game from the game list
  949. X *
  950. X * This function removes a game from the game list by linking around
  951. X * it, then frees the memory associated with the game structure.
  952. X *----------------------------------------------------------------------
  953. X */
  954. X
  955. Xdeletegame(g)
  956. Xstruct game *g;
  957. X{
  958. X
  959. Xif (g == ghead) {        /* deleting first game in list */
  960. X    ghead = g->next;    /* move head pointer to next game */
  961. X    if (ghead == NULL)    /* we just deleted the last game */
  962. X        gtail = NULL;    /* set both ptrs to NULL */
  963. X    else
  964. X        ghead->prev = NULL;    /* first in list has no prev */
  965. X    }
  966. Xelse if (g == gtail) {        /* deleting last game in list */
  967. X    gtail = g->prev;    /* move tail pointer back */
  968. X    gtail->next = NULL;    /* last game has no next */
  969. X    }
  970. Xelse {
  971. X    g->next->prev = g->prev;    /* link back link around g */
  972. X    g->prev->next = g->next;    /* and forward link too */
  973. X    }
  974. Xif (g->gameid != NULL)
  975. X    free(g->gameid);        /* free string space */
  976. Xif (g->opname != NULL)
  977. X    free(g->opname);
  978. Xif (g->opaddr != NULL)
  979. X    free(g->opaddr);
  980. Xfree(g);            /* free the memory */
  981. X}
  982. X
  983. X
  984. X/*----------------------------------------------------------------------
  985. X *    findgame -- find a game based on its game id
  986. X *
  987. X * This function performs a linear search through the game list
  988. X * for a game id.  It returns a pointer to the game, or NULL if
  989. X * the game does not exist.
  990. X *----------------------------------------------------------------------
  991. X */
  992. X
  993. Xstruct game *findgame(gid)
  994. Xchar *gid;
  995. X{
  996. Xstruct game *g;
  997. X
  998. Xfor (g = ghead; g != NULL; g = g->next)
  999. X    if (strcmp(gid,g->gameid) == 0)        /* is this it? */
  1000. X        return(g);            /* yup, return it */
  1001. Xreturn(NULL);                    /* no such game */
  1002. X}
  1003. END_OF_FILE
  1004. if test 6317 -ne `wc -c <'game.c'`; then
  1005.     echo shar: \"'game.c'\" unpacked with wrong size!
  1006. fi
  1007. chmod +x 'game.c'
  1008. # end of 'game.c'
  1009. fi
  1010. if test -f 'makeldb.com' -a "${1}" != "-c" ; then 
  1011.   echo shar: Will not clobber existing file \"'makeldb.com'\"
  1012. else
  1013. echo shar: Extracting \"'makeldb.com'\" \(540 characters\)
  1014. sed "s/^X//" >'makeldb.com' <<'END_OF_FILE'
  1015. X$ set verify
  1016. X$ assign "sys$library" vaxc$include
  1017. X$ cc/nolist board
  1018. X$ cc/nolist game
  1019. X$ cc/nolist main
  1020. X$ cc/nolist misc
  1021. X$ cc/nolist move
  1022. X$ cc/nolist process
  1023. X$ cc/nolist rcvop
  1024. X$ cc/nolist control
  1025. X$ cc/nolist readmail
  1026. X$ cc/nolist save
  1027. X$ cc/nolist vars
  1028. X$ cc/nolist fe_curses
  1029. X$ cc/nolist t_email
  1030. X$ cc/nolist r_xrand
  1031. X$ cc/nolist check
  1032. X$ link/exe=ldb sys$input/opt
  1033. Xboard,game,main,misc,move,process,rcvop,control,readmail,save,vars
  1034. Xfe_curses,t_email,r_xrand,check
  1035. Xsys$share:vaxccurse.olb/library
  1036. Xsys$share:vaxcrtl.olb/library
  1037. X$ set noverify
  1038. X$ exit
  1039. END_OF_FILE
  1040. if test 540 -ne `wc -c <'makeldb.com'`; then
  1041.     echo shar: \"'makeldb.com'\" unpacked with wrong size!
  1042. fi
  1043. # end of 'makeldb.com'
  1044. fi
  1045. if test -f 'move.c' -a "${1}" != "-c" ; then 
  1046.   echo shar: Will not clobber existing file \"'move.c'\"
  1047. else
  1048. echo shar: Extracting \"'move.c'\" \(5354 characters\)
  1049. sed "s/^X//" >'move.c' <<'END_OF_FILE'
  1050. X/*    move.c        8/5/91
  1051. X *
  1052. X * Copyright 1991  Perry R. Ross
  1053. X *
  1054. X * Permission to use, copy, modify, and distribute this software and its
  1055. X * documentation without fee is hereby granted, subject to the restrictions
  1056. X * detailed in the README file, which is included here by reference.
  1057. X * Any other use requires written permission from the author.  This software
  1058. X * is distributed "as is" without any warranty, including any implied
  1059. X * warranties of merchantability or fitness for a particular purpose.
  1060. X * The author shall not be liable for any damages resulting from the
  1061. X * use of this software.  By using this software, the user agrees
  1062. X * to these terms.
  1063. X */
  1064. X
  1065. X#include "ldb.h"
  1066. X
  1067. X/*-----------------------------------------------------------------------
  1068. X *    apply -- apply a move to a board
  1069. X *
  1070. X * Apply applies a move to a board, detecting the following errors:
  1071. X *    RJ_NOROLL    The mv struct did not contain a valid roll.
  1072. X *    RJ_ONBAR    The move attempted to move from a point other than
  1073. X *            the bar when pieces are on the bar.
  1074. X *    RJ_NOOFF    The move attempted to move pieces off before all
  1075. X *            pieces are in the inner table.
  1076. X *    RJ_NOPIECE    The move attempted to take a piece from an empty point.
  1077. X *    RJ_NOTYOURS    The move attempted to move the opponent's piece.
  1078. X *    RJ_OCC        The move attempted to move to an occupied point.
  1079. X *    RJ_EXACT    The move attempted to bear off a piece with a
  1080. X *            larger roll than necessary when that piece was
  1081. X *            not the outermost piece.
  1082. X * If the move was legal, apply returns:
  1083. X *    MVOK        if no blot was hit, or
  1084. X *    point number    where the blot was before it was hit.
  1085. X * Note that blot numbers are in the range [1-24], MVOK is 0, and
  1086. X * the reject codes are negative.  When the move is rejected,
  1087. X * the board is unchanged.  When a blot is hit, it is moved to the
  1088. X * appropriate bar point automatically.
  1089. X *
  1090. X * If A_REDRAW is set in flags, apply redraws the relevant portions of
  1091. X * the screen to reflect the move.  If A_CHKONLY is set in flags, the
  1092. X * move is checked but the board is not modified.
  1093. X *-----------------------------------------------------------------------
  1094. X */
  1095. X
  1096. Xapply(g,who,mn,flags,dest)
  1097. Xstruct game *g;            /* game structure */
  1098. Xint who;            /* 0 = opponent, 1 = me */
  1099. Xint mn;                /* which element of mv array */
  1100. Xint flags;            /* A_* */
  1101. Xint *dest;            /* where to store destination point */
  1102. X{
  1103. Xint i, j, blot;
  1104. Xint op, np;
  1105. Xint dir;
  1106. Xchar clr;
  1107. Xstruct mv *m;
  1108. Xregister struct point *b = g->board;
  1109. X
  1110. Xdir = who ? g->mydir : g->opdir;
  1111. Xclr = who ? g->mycolor : g->opcolor;
  1112. Xblot = MVOK;            /* no blot hit yet */
  1113. Xm = who ? &g->mvs[mn] : &g->opmvs[mn];
  1114. Xif (m->roll <= 0)        /* sanity check */
  1115. X    return(RJ_NOROLL);    /* reject move */
  1116. Xop = m->pt;        /* starting point number */
  1117. Xif (op < 0)        /* this roll is unused */
  1118. X    return(MVOK);    /* and that's ok */
  1119. Xif ( (op == 0) || (op == 25) )    /* moving off bar */
  1120. X    op = BARPT(dir);    /* use correct bar point */
  1121. Xelse {            /* not moving off bar */
  1122. X    j = BARPT(dir);    /* make sure no pieces still on bar */
  1123. X    if (b[j].qty > 0)
  1124. X        return(RJ_ONBAR);    /* can't move, pieces on bar */
  1125. X    }
  1126. Xnp = op + m->roll*dir;    /* move piece correct number of pts */
  1127. Xif ( (np <= 0) || (np >= 25) ) {
  1128. X    i = (dir > 0) ? 19 : 1;
  1129. X    j = (dir > 0) ? 24 : 6;
  1130. X    if (addpcs(b,clr,i,j)+b[OFFPT(dir)].qty < 15) /* all pcs not */
  1131. X        return(RJ_NOOFF);    /* in inner table, can't move off */
  1132. X    if ( (np != 0) && (np != 25) ) {/* using bigger roll than needed */
  1133. X        i = (dir > 0) ? 19   : op+1; /* check for pcs on higher pts */
  1134. X        j = (dir > 0) ? op-1 : 6;
  1135. X        if (addpcs(b,clr,i,j) > 0)    /* there are some */
  1136. X            return(RJ_EXACT);    /* must use roll on them */
  1137. X        }
  1138. X    np = OFFPT(dir);    /* this piece is moving off */
  1139. X    }
  1140. Xif (b[op].qty <= 0)        /* no piece here to move */
  1141. X    return(RJ_NOPIECE);
  1142. Xif (b[op].color != clr)    /* trying to move opponent's pieces? */
  1143. X    return(RJ_NOTYOURS);
  1144. Xif (b[np].qty == 0)        /* moving to an empty point */
  1145. X    b[np].color = b[op].color;    /* copy color */
  1146. Xif (b[np].color != b[op].color) {    /* moving to occupied pt */
  1147. X    if (b[np].qty == 1) {        /* whacked a blot */
  1148. X        blot = np;        /* save point number for return */
  1149. X        if ( (flags & A_CHKONLY) == 0) {
  1150. X            b[np].qty = 0;        /* bye bye */
  1151. X            j = BARPT(REV(dir));    /* send it to opponents bar */
  1152. X            b[j].color = b[np].color; /* copy color to bar pt */
  1153. X            b[j].qty++;        /* bump counter */
  1154. X            if (flags & A_REDRAW)    /* update screen */
  1155. X                FeDrawPoint(b,j,0,g->flags & F_INVERT);
  1156. X            b[np].color = b[op].color;    /* my point now */
  1157. X            }
  1158. X        }
  1159. X    else
  1160. X        return(RJ_OCC);        /* point is occupied */
  1161. X    }
  1162. Xif ( (flags & A_CHKONLY) == 0) {
  1163. X    b[op].qty--;                /* take piece from old pt */
  1164. X    b[np].qty++;                /* and put in on new pt */
  1165. X    if (flags & A_REDRAW) {
  1166. X        FeDrawPoint(b,op,0,g->flags & F_INVERT);/* update the screen */
  1167. X        FeDrawPoint(b,np,0,g->flags & F_INVERT);
  1168. X        }
  1169. X    }
  1170. Xif (dest != NULL)            /* return new position */
  1171. X    *dest = np;
  1172. Xreturn(blot);                /* succeeded, return MVOK or blot */
  1173. X}
  1174. X
  1175. X
  1176. X/*----------------------------------------------------------------------
  1177. X *    addpcs -- add the number of pieces in a range of points
  1178. X *
  1179. X * This function returns the number of pieces of a certain color
  1180. X * that reside within a range of points.
  1181. X *----------------------------------------------------------------------
  1182. X */
  1183. X
  1184. Xaddpcs(b,clr,f,t)
  1185. Xboard b;
  1186. Xchar clr;
  1187. Xint f, t;
  1188. X{
  1189. Xint i, q;
  1190. X
  1191. Xq = 0;                /* quantity we have found so far */
  1192. Xfor (i = f; i <= t; i++)
  1193. X    if (b[i].color == clr)    /* found some */
  1194. X        q += b[i].qty;    /* count them */
  1195. Xreturn(q);            /* return quantity found */
  1196. X}
  1197. END_OF_FILE
  1198. if test 5354 -ne `wc -c <'move.c'`; then
  1199.     echo shar: \"'move.c'\" unpacked with wrong size!
  1200. fi
  1201. chmod +x 'move.c'
  1202. # end of 'move.c'
  1203. fi
  1204. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  1205.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  1206. else
  1207. echo shar: Extracting \"'patchlevel.h'\" \(1366 characters\)
  1208. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  1209. X/*    patchlevel.h    9/9/91
  1210. X *
  1211. X * adapted from the file "patchlevel", which is part of the
  1212. X * "xloadimage" package by Jim Frost, and used within the terms
  1213. X * of the original copyright notice, which appears below.
  1214. X * Please note that the copyright notice below applies only to
  1215. X * this file.
  1216. X */
  1217. X
  1218. X/*
  1219. X * Copyright 1989, 1990, 1991 Jim Frost
  1220. X *
  1221. X * Permission to use, copy, modify, distribute, and sell this software
  1222. X * and its documentation for any purpose is hereby granted without fee,
  1223. X * provided that the above copyright notice appear in all copies and
  1224. X * that both that copyright notice and this permission notice appear
  1225. X * in supporting documentation.  The author makes no representations
  1226. X * about the suitability of this software for any purpose.  It is
  1227. X * provided "as is" without express or implied warranty.
  1228. X *
  1229. X * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  1230. X * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  1231. X * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  1232. X * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  1233. X * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  1234. X * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
  1235. X * USE OR PERFORMANCE OF THIS SOFTWARE.
  1236. X */
  1237. X
  1238. X#define VERSION        1
  1239. X#define PATCHLEVEL    0
  1240. X#define AUTHOR_EMAIL    "ross@emf780.den.mmc.com"
  1241. END_OF_FILE
  1242. if test 1366 -ne `wc -c <'patchlevel.h'`; then
  1243.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  1244. fi
  1245. chmod +x 'patchlevel.h'
  1246. # end of 'patchlevel.h'
  1247. fi
  1248. if test -f 'readmail.c' -a "${1}" != "-c" ; then 
  1249.   echo shar: Will not clobber existing file \"'readmail.c'\"
  1250. else
  1251. echo shar: Extracting \"'readmail.c'\" \(5482 characters\)
  1252. sed "s/^X//" >'readmail.c' <<'END_OF_FILE'
  1253. X/*    rcv.c        8/7/91
  1254. X *
  1255. X * Copyright 1991  Perry R. Ross
  1256. X *
  1257. X * Permission to use, copy, modify, and distribute this software and its
  1258. X * documentation without fee is hereby granted, subject to the restrictions
  1259. X * detailed in the README file, which is included here by reference.
  1260. X * Any other use requires written permission from the author.  This software
  1261. X * is distributed "as is" without any warranty, including any implied
  1262. X * warranties of merchantability or fitness for a particular purpose.
  1263. X * The author shall not be liable for any damages resulting from the
  1264. X * use of this software.  By using this software, the user agrees
  1265. X * to these terms.
  1266. X */
  1267. X
  1268. X#include "ldb.h"
  1269. X
  1270. X
  1271. X/*----------------------------------------------------------------------
  1272. X *    readmail -- read the incoming mail and process it
  1273. X *
  1274. X * This function extracts each packet from the mail file and applies it
  1275. X * to the appropriate game structure.  Most packets are processed by
  1276. X * calling the handler found in the func array, which is a 2-dimensional
  1277. X * array indexed by the current game state and the received opcode.
  1278. X * The handlers are responsible for transforming the game state as
  1279. X * necessary.  The START and RSTART opcodes receive special processing,
  1280. X * since they apply to games that do not exist and thus have no state.
  1281. X * START packets result in the creation of a game, whose state is set
  1282. X * such that the correct handler will be called.  The RSTART opcode
  1283. X * is processed in the same way as the -start command line argument;
  1284. X * the packet is then discarded.
  1285. X *----------------------------------------------------------------------
  1286. X */
  1287. X
  1288. Xreadmail(file)
  1289. Xchar *file;
  1290. X{
  1291. XFILE *fp;
  1292. Xint d, c1, c2;
  1293. X
  1294. Xif ( (fp = fopen(file,"r")) == NULL)
  1295. X    return;
  1296. Xwhile (getpkt(fp) > 0) {    /* as long as we found a valid packet */
  1297. X    if (P.gameptr == NULL) {
  1298. X        if (P.opcode == START) {
  1299. X            P.gameptr = addgame(); /* init later in start() */
  1300. X            P.gameptr->gameid = P.gameid;
  1301. X            P.gameptr->state = ST_OPSTART;
  1302. X            }
  1303. X        else if (P.opcode == RSTART) {    /* remote start packet */
  1304. X            if (P.dir == NULL)    /* if no direction was given */
  1305. X                d = cr_mydir;    /* use my default */
  1306. X            else            /* dir was given, grab it */
  1307. X                d = (*P.dir == 'u') ? 1 : -1;
  1308. X            if (P.colors == NULL) {    /* if no colors were given */
  1309. X                c1 = cr_mycolor;    /* use my defaults */
  1310. X                c2 = cr_opcolor;
  1311. X                }
  1312. X            else {                /* colors were given */
  1313. X                c1 = *P.colors;        /* use them */
  1314. X                c2 = P.colors[1];
  1315. X                }
  1316. X            startgame(P.addr,d,c1,c2);    /* start a game */
  1317. X            continue;        /* discard this packet */
  1318. X            }
  1319. X        else {
  1320. X            fprintf(stderr,"ERROR: no such gameid: %s (ignored)\n",
  1321. X                P.gameid);
  1322. X            continue;
  1323. X            }
  1324. X        }
  1325. X    if (P.gameptr->state >= OPSTATES) {    /* hey, it's still my turn */
  1326. X        fprintf(stderr,
  1327. X            "ERROR: move out of turn: %s (ignored)\n",P.gameid);
  1328. X        continue;
  1329. X        }
  1330. X    if (P.name != NULL)        /* snarf opponent's name */
  1331. X        P.gameptr->opname = P.name;
  1332. X    (*func[P.gameptr->state][P.opcode])(P.gameptr);    /* call handler */
  1333. X    }
  1334. X}
  1335. X
  1336. X
  1337. X/*---------------------------------------------------------------------------
  1338. X *    getpkt -- read one packet from a file
  1339. X *
  1340. X * This function reads the next packet from the specified file.
  1341. X * Getpkt() is passed a open file pointer to the file it is to scan.
  1342. X * Lines are read and discarded until a line is found that contains only:
  1343. X *        <<<===LDB===>>>
  1344. X * Subsequent lines should contain name/value pairs as specified
  1345. X * in nv_packet.  The packet ends with end of file or a line beginning
  1346. X * with "end=".  Getpkt reads from the input file until one
  1347. X * packet has been found and processed, then returns.  Subsequent calls
  1348. X * to getpkt with the same file pointer will process additional packets.
  1349. X * Getpkt returns 1 if a valid packet was read, 0 if EOF was encountered.
  1350. X * Getpkt ignores incoming packets with the incorrect sequence number.
  1351. X *---------------------------------------------------------------------------
  1352. X */
  1353. X
  1354. Xgetpkt(fp)
  1355. XFILE *fp;
  1356. X{
  1357. Xstatic char buf[128];
  1358. Xint i;
  1359. X
  1360. Xwhile (fgets(buf,sizeof(buf),fp) != NULL) {
  1361. X    if (strcmp(buf,"<<<===LDB===>>>\n"))/* skip all other lines */
  1362. X        continue;
  1363. X    P.gameid = NULL;    /* init P structure */
  1364. X    P.timestamp = 0L;
  1365. X    P.opcode = -1;
  1366. X    P.name = NULL;
  1367. X    P.addr = NULL;
  1368. X    P.comment = NULL;
  1369. X    P.comment2 = NULL;
  1370. X    P.seq = -1;
  1371. X    P.autodbl = NULL;
  1372. X    clearmvs(P.mvs);
  1373. X    P.gameptr = NULL;
  1374. X    nvscan(fp,nv_packet,&P,opcodes);    /* scan the packet into P */
  1375. X    if (P.gameid == NULL) {        /* didn't get a gameid */
  1376. X        fprintf(stderr,"ERROR: missing gameid in packet -- ignored\n");
  1377. X        continue;
  1378. X        }
  1379. X    if ( (P.gameptr = findgame(P.gameid)) == NULL)    /* doesn't exist */
  1380. X        i = 1;            /* initial seq == 1 */
  1381. X    else
  1382. X        i = P.gameptr->seq+1;    /* get current seq */
  1383. X    if (P.seq != i) {        /* sequence number is wrong */
  1384. X        if (P.seq > i)        /* rec'd seq # is too big */
  1385. X            fprintf(stderr,        /* shouldn't happen */
  1386. X            "WARNING: game %s, seq no. is %d, s/b %d -- ignored.\n"
  1387. X            ,P.gameid,P.seq,i);
  1388. X        continue;        /* ignore pkts with bad sequence #s */
  1389. X        }
  1390. X    if ( (P.opcode < 0) || (P.opcode >= NOP) ) {    /* bad opcode */
  1391. X        fprintf(stderr,
  1392. X            "ERROR: bad opcode for game %s: %d -- ignored.\n",
  1393. X            P.gameid,P.opcode);
  1394. X        continue;
  1395. X        }
  1396. X    if (P.gameptr != NULL) {
  1397. X        P.gameptr->seq += 2;    /* bump sequence number */
  1398. X        if (P.gameptr->opcmt != NULL)
  1399. X            free(P.gameptr->opcmt);    /* discard old comment */
  1400. X        P.gameptr->opcmt = P.comment;    /* copy new comment */
  1401. X        if (P.gameptr->opcmt2 != NULL)
  1402. X            free(P.gameptr->opcmt2);/* discard old comment */
  1403. X        P.gameptr->opcmt2 = P.comment2;    /* copy new comment */
  1404. X        }
  1405. X    return(1);            /* return success */
  1406. X    }
  1407. Xreturn(0);        /* return this to mean end of file */
  1408. X}
  1409. END_OF_FILE
  1410. if test 5482 -ne `wc -c <'readmail.c'`; then
  1411.     echo shar: \"'readmail.c'\" unpacked with wrong size!
  1412. fi
  1413. chmod +x 'readmail.c'
  1414. # end of 'readmail.c'
  1415. fi
  1416. if test -f 't_email.c' -a "${1}" != "-c" ; then 
  1417.   echo shar: Will not clobber existing file \"'t_email.c'\"
  1418. else
  1419. echo shar: Extracting \"'t_email.c'\" \(4738 characters\)
  1420. sed "s/^X//" >'t_email.c' <<'END_OF_FILE'
  1421. X/*    t_email.c        9/5/91
  1422. X *
  1423. X * Copyright 1991  Perry R. Ross
  1424. X *
  1425. X * Permission to use, copy, modify, and distribute this software and its
  1426. X * documentation without fee is hereby granted, subject to the restrictions
  1427. X * detailed in the README file, which is included here by reference.
  1428. X * Any other use requires written permission from the author.  This software
  1429. X * is distributed "as is" without any warranty, including any implied
  1430. X * warranties of merchantability or fitness for a particular purpose.
  1431. X * The author shall not be liable for any damages resulting from the
  1432. X * use of this software.  By using this software, the user agrees
  1433. X * to these terms.
  1434. X */
  1435. X
  1436. X#include "ldb.h"
  1437. X
  1438. X/*======================================================================
  1439. X * This file is the e-mail transport for the ldb program.  It is
  1440. X * modularized to allow other transports to be substituted, most
  1441. X * notably a socket transport to allow interactive network backgammon.
  1442. X * For now, though, this is the only transport available.
  1443. X *
  1444. X * Packets are sent via TSendPacket, which takes an instance of
  1445. X * struct packet and an address, and sends the packet to that address.
  1446. X * TInitialize must be called before any calls to TSendPacket, and
  1447. X * TFinishSession must be called before exiting.
  1448. X *
  1449. X * Individual files may be sent by calling TSendFile.  These files
  1450. X * need not be related to a game.
  1451. X *======================================================================
  1452. X */
  1453. X
  1454. XPRIVATE PStringSub();
  1455. X
  1456. X
  1457. X/*----------------------------------------------------------------------
  1458. X *    TInitialize -- initialize the transport
  1459. X *
  1460. X * This function is called before the transport is used.  As you can
  1461. X * see, email doesn't require a great deal of initialization.
  1462. X *----------------------------------------------------------------------
  1463. X */
  1464. X
  1465. XTInitialize()
  1466. X{
  1467. X}
  1468. X
  1469. X
  1470. X/*----------------------------------------------------------------------
  1471. X *    FeDrawMenu -- draw menu choices in menu box
  1472. X *
  1473. X * This function closes down the transport.
  1474. X *----------------------------------------------------------------------
  1475. X */
  1476. X
  1477. XTFinishSession()
  1478. X{
  1479. X}
  1480. X
  1481. X
  1482. X
  1483. X/*----------------------------------------------------------------------
  1484. X *    TSendPacket -- send a packet to an email address
  1485. X *
  1486. X * This function sends a packet to an email address.
  1487. X *----------------------------------------------------------------------
  1488. X */
  1489. X
  1490. XTSendPacket(p,addr)
  1491. Xstruct packet *p;
  1492. Xchar *addr;
  1493. X{
  1494. Xchar subject[80];
  1495. XFILE *fp;
  1496. X
  1497. X
  1498. Xif ((fp = fopen(rc.tempfile,"w")) == NULL) {    /* open temp file */
  1499. X    fprintf(stderr,"ERROR: can't create %s!\n",rc.tempfile);
  1500. X    return;
  1501. X    }
  1502. Xfprintf(fp,"<<<===LDB===>>>\n");    /* send magic header text */
  1503. Xnvwrite(fp,nv_packet,p,opcodes);    /* write the contents of the packet */
  1504. Xfclose(fp);                /* close temp file */
  1505. Xsprintf(subject,"<=LDB=> from %s (Long Distance Backgammon)", rc.myname);
  1506. XTSendFile(addr,rc.tempfile,subject);
  1507. Xunlink(rc.tempfile);        /* delete the temp file */
  1508. X}
  1509. X
  1510. X
  1511. X/*----------------------------------------------------------------------
  1512. X *    TSendFile -- send a file to an address
  1513. X *
  1514. X * This function takes an e-mail address, a file, and a subject line,
  1515. X * and sends the contents of the file to the specified address.  The
  1516. X * subject is set to the contents of the subject argument, which should
  1517. X * be one line.
  1518. X *----------------------------------------------------------------------
  1519. X */
  1520. X
  1521. XTSendFile(addr,file,subj)
  1522. Xchar *addr, *file, *subj;
  1523. X{
  1524. Xchar cmd[256];
  1525. Xchar *subs[3];
  1526. X
  1527. Xsubs[0] = addr;            /* substitute $a with opponent address */
  1528. Xsubs[1] = file;            /* substitue $f with file */
  1529. Xsubs[2] = subj;            /* substitute $s with subject */
  1530. XPStringSub(rc.sendcmd,"afs",subs,cmd);
  1531. Xsystem(cmd);            /* execute email command */
  1532. X}
  1533. X
  1534. X
  1535. X
  1536. X/*----------------------------------------------------------------------
  1537. X *    PStringSub -- substitute variables in a string
  1538. X *
  1539. X * This function copies str to obuf, replacing occurrences of $x to
  1540. X * a corresponding string.  The characters which can appear after
  1541. X * the $ are passed in a single string in the "chars" argument, and
  1542. X * the strings to replace them with are passed, in the same order as
  1543. X * the characters appear in "chars", in the "strings" argument.
  1544. X *----------------------------------------------------------------------
  1545. X */
  1546. X
  1547. XPRIVATE PStringSub(str,chars,strings,obuf)
  1548. Xchar *str, *chars, *strings[], obuf[];
  1549. X{
  1550. Xchar *s, *o, *t;
  1551. X
  1552. Xfor (s = str, o = obuf; *s; s++) {
  1553. X    if (*s != '$') {    /* as long as we don't see a $ */
  1554. X        *o++ = *s;    /* just keep copying */
  1555. X        continue;
  1556. X        }
  1557. X    s++;
  1558. X    if (*s == '$') {    /* $$ is a single $ */
  1559. X        *o++ = '$';
  1560. X        continue;
  1561. X        }
  1562. X    if ( (t = strchr(chars,*s)) == NULL)    /* skip invalid $ subs */
  1563. X        continue;
  1564. X    t = strings[t - chars];        /* get ptr to replacement string */
  1565. X    while (*t)            /* copy it to obuf */
  1566. X        *o++ = *t++;
  1567. X    }
  1568. X*o = '\0';                /* null terminate obuf */
  1569. X}
  1570. END_OF_FILE
  1571. if test 4738 -ne `wc -c <'t_email.c'`; then
  1572.     echo shar: \"'t_email.c'\" unpacked with wrong size!
  1573. fi
  1574. chmod +x 't_email.c'
  1575. # end of 't_email.c'
  1576. fi
  1577. echo shar: End of archive 1 \(of 5\).
  1578. cp /dev/null ark1isdone
  1579. MISSING=""
  1580. for I in 1 2 3 4 5 ; do
  1581.     if test ! -f ark${I}isdone ; then
  1582.     MISSING="${MISSING} ${I}"
  1583.     fi
  1584. done
  1585. if test "${MISSING}" = "" ; then
  1586.     echo You have unpacked all 5 archives.
  1587.     rm -f ark[1-9]isdone
  1588. else
  1589.     echo You still need to unpack the following archives:
  1590.     echo "        " ${MISSING}
  1591. fi
  1592. ##  End of shell archive.
  1593. exit 0
  1594.  
  1595.  
  1596. exit 0 # Just in case...
  1597. exit 0 # Just in case...
  1598.