From a716951dab4b788d9156d6c448611f3f7abc1a3e Mon Sep 17 00:00:00 2001 From: acn Date: Wed, 1 Jul 2020 15:29:48 +0200 Subject: [PATCH] Moved to vt100-games repository --- Compiling.md | 62 -- Original/backgmmn.c | 2278 ----------------------------------------- Original/backgmmn.com | Bin 30976 -> 0 bytes Original/backgmmn.lbr | Bin 69888 -> 0 bytes Original/backgmmn.sub | 14 - Original/gameplan.c | 866 ---------------- Original/gameplan.hdr | 42 - Original/mylib2.c | 541 ---------- Original/read.me | 56 - backgmmn.c | 1968 ----------------------------------- backgmmn.com | Bin 30592 -> 0 bytes bgclean.sub | 8 - bgmake.sub | 13 - gameplan.c | 866 ---------------- gameplan.hdr | 42 - mylib2.c | 541 ---------- 16 files changed, 7297 deletions(-) delete mode 100644 Compiling.md delete mode 100644 Original/backgmmn.c delete mode 100644 Original/backgmmn.com delete mode 100644 Original/backgmmn.lbr delete mode 100644 Original/backgmmn.sub delete mode 100644 Original/gameplan.c delete mode 100644 Original/gameplan.hdr delete mode 100644 Original/mylib2.c delete mode 100644 Original/read.me delete mode 100644 backgmmn.c delete mode 100644 backgmmn.com delete mode 100644 bgclean.sub delete mode 100644 bgmake.sub delete mode 100644 gameplan.c delete mode 100644 gameplan.hdr delete mode 100644 mylib2.c diff --git a/Compiling.md b/Compiling.md deleted file mode 100644 index 6ea1289..0000000 --- a/Compiling.md +++ /dev/null @@ -1,62 +0,0 @@ -# Compiling Gammon IV - -## Requirements - -To compile this program, you need the following: - -* The Software Toolworks' C/80 v3.1 compiler for CP/M -* Microsoft MACRO-80 assembler (M80.com) -* Microsoft LINK-80 linker (L80.COM) - -All of these tools can be found here: -http://www.retroarchive.org/cpm/lang/lang.htm - -## Configuration - -The C compiler needs to be configured in order to be able to compile Gammon IV. - -Just use CCONFIG.COM to make the following settings: - - Symbol table size: 512 - String constant table: 3200 - Dump constants after each routine: YES - Macro table size: 500 - Switch table size: 128 - Structure table size: 200 - Merge duplicate string constants: YES - Assembler: C/80's AS - Initialize arrays to zero: < 256 BYES ONLY - Generate ROMable code in Macro-80: YES - Screen size: 24 (doesn't matter) - Generate slightly larger, faster code: NO - Sign extension on char to int conversion: YES - Device for library files: A: (your choice) - -## Compilation - -I assume that all of the following files are placed on a hard disk or "big" floppy disk. -If you are compiling this game on a old system with limited disk space, please look into backgmmn.c, where you can find tips on how to distribute the files onto several disks. - -The following files are needed: - BACKGMMN.C, GAMEPLAN.C, GAMEPLAN.HDR, MYLIB2.C, - -From the C compiler: - PRINTF.C, STDLIB.REL, CLIBRARY.REL, C.COM - -Assembler/Linker: - L80.COM, M80.COM - -To use the submit scripts, you also need ``SUBMIT.COM`` from your CP/M installation. - -Using ``SUBMIT BGMAKE``, all steps of compiling, assembling and linking will run. - -Using ``SUBMIT BGCLEAN``, all compiled files and intermediary files will be deleted. - -If you don't want to use the script or just want to compile some parts, these steps are taken in the script: - - c -m backgmmn - m80 =backgmmn - c -m gameplan - m80 =gameplan - l80 backgmmn,gameplan,stdlib/s,clibrary/s,backgmmn/n/e - diff --git a/Original/backgmmn.c b/Original/backgmmn.c deleted file mode 100644 index ff20aed..0000000 --- a/Original/backgmmn.c +++ /dev/null @@ -1,2278 +0,0 @@ -/* backgmmn.c */ - -/*************************************************************************** - - GAMMON IV, Version 2 - - Author: David C. Oshel - 1219 Harding Avenue - Ames, Iowa 50010 - - Date: March 26, 1986 - - Gammon IV is probably the best backgammon game currently available for - CP/M. I wrote it because I was disgusted with the price and dullness - of all other programs which allegedly play backgammon on CP/M systems. - - This program has THREE DIFFERENT PLAYING STYLES, any one of which can - consistently beat a novice player, and occasionally beat a good player. - In all three levels, the computer's strategy can even seem brilliant; - there is nothing routine about it. - - This version incorporates a few minor changes and bug fixes which make it - different from previous editions which have appeared on various bulletin - boards and club offerings around the country. This is a public domain - program. Feel free to distribute or improve it. Credit to the original - author (me) will be appreciated, but is not strictly required since the - copyright owners are abnormally mild-mannered (and extremely distant; - see Acknowledgments, below.) - - Version 2: - - a) Fixed the bug in which the doubling cube might revert to its - default value if the computer took back a move, and if the cube - had been doubled one or more times during the opening roll-off - but not yet offered. - - b) Fixed an odd bug in the Arrange command which occasionally caused - stones to switch allegiance to the opponent's color, or else to - mysteriously multiply to more than 15 on a side. - - c) An improved error handler now hints that BAR and HOME are words - used in the game; also, slows down the incorrect entry routine so - that it is less mysterious than before. - - d) Added a Graphic toggle to main command line. Same as Control-K, - as in previous versions; turns on/off the Kaypro '84 video graphics; - uses the alternate token set defined in the CRT module below. - - e) Changed the break character back to Control-C. The proximity of - the ESCAPE key to the 1 digit on the Kaypro keyboard sometimes - caused a game to be inadvertently paused during play. - - f) There is no longer a sanction against cheating; if you type - Control-C during play and re-Arrange the stones, your opponent - does not change. - - g) As before, the computer will not always take (or find) a forced - move. The rule is that the player must take both dice if possible, - or the larger if both are possible singly but not together. - The playing algorithm attempts to find the legally required move, - but will sometimes fail. It is sometimes advantageous to avoid a - forced move but the computer cannot make that distinction, in this - version; the program allows the same lenience for the human player. - - The cube is doubled when doubles are thrown during the opening - rolloff to decide who goes first. However, if the cube reaches 8, - further pairs on the dice during rolloff have no effect. - - Gammon IV knows all the other OFFICIAL rules of the game; - U.S. Navy and/or Saloon rules don't count. - - h) Improved coding in some routines, especially putstone(), which was - far more baroque than necessary. There is also some occasional - re-coding, where I could not prevent myself. The game strategy - has not been changed, mostly because I don't fully understand it - anymore, even though the documentation there is better than usual. - It was written months ago in a white heat of inspiration; but I - feel reluctant to submit myself to that strain again, without the - prospect of remuneration. - - - Acknowledgments: - - The opening dialogue, in which you chose your computer opponent, - is freely adapted from Alexei Panshin's long out-of-print, and - now classic, "Star Well" travelogues. Scholars of computer history - will recognize many allusions to this same opus in various passages - of Mike Goetz's 550-point Adventure (especially in the Ice Caverns!). - - The Xochitl Sodality, which owns the copyright on Gammon IV, is a - philanthropic society first publicized by Panshin. Persons who wish - to obtain information on site licensing for Gammon IV should contact - the Monist Association imaginary properties secretary at the following - address: - Monist Association I.P.S. - c/o Xochitl Sodality - Semichastny House - Delbalso, Nash. Emp. - - - Special Instructions: - - Terminal must be Lear-Siegler ADM-3A compatible, or else have - the same graphics capability as a Kaypro 10, 2X or 4'84. This - requirement is fully configurable in the video section below, - however. - - This program requires the Software Toolworks' C/80 v3.1 compiler - for CP/M 2.2. C/80 has a configuration program. C/80 must be - configured as follows, or else this program WILL NOT compile: - - Symbol table size: 512 - String constant table: 3200 - Dump constants after each routine: YES - Macro table size: 500 - Switch table size: 128 - Structure table size: 200 - Merge duplicate string constants: YES -NB: Assembler: C/80's AS - Initialize arrays to zero: < 256 BYES ONLY - Generate ROMable code in Macro-80: YES - Screen size: 24 (doesn't matter) - Generate slightly larger, faster code: NO - Sign extension on char to int conversion: YES - Device for library files: A: (your choice) - - Compilation: - -NB: Microsoft's MACRO-80 assembler and LINK-80 linker are required, - and are specified in the (-m) compiler switch! This is a moderately - complex compile, so the procedure is directed by batch SUBMIT files. - Distribute files as follows: - - On Drive A: - - BACKGMMN.C, BACKGMMN.SUB, CLIBRARY.REL, GAMEPLAN.C, - GAMEPLAN.HDR, MYLIB2.C, PRINTF.C, STDLIB.REL, SUBMIT.COM - - On Drive B: - - C.COM, L80.COM, M80.COM, WS.COM, WSMSGS.OVR, WSOVLY1.OVR - - Then, SUBMIT BACKGMMN to compile, assemble & link the game. You will - need about 180k of free space on Drive A. - - You must pay strict attention to the Special Instructions above, - regarding C/80 configuration. - - - Absent Files: - - M80.COM and L80.COM are from Microsoft, and are not part - of this distribution. C.COM, STDLIB.REL, CLIBRARY.REL and - PRINTF.C are from Software Toolworks, and are not part of - this distribution either. SUBMIT.COM is a CP/M transient - command; it came with your computer when you bought it. - - - Notes: - - Gammon IV is impossible to implement in any C which does not allow - functions to be passed as parameters to another function -- K & R must - be followed on this point! - - THIS CODE ASSUMES INTEL 8080 CPU. Inline code simulates an old, - archaic version of SetJump() and LongJump(), which are not features - of C/80 3.1. Use of inline code means you need 8080 compatibility. - - By isolating the game-playing algorithm into a separately compiled - module, I have allowed for the possibility that someone else may come - up with significant improvements in strategy, AND BE GIVEN CREDIT FOR - THEM, without having to re-design primitive parts of the program. - - The single exception to this rule is the code which decides when the - computer will offer, accept or reject the doubling cube; that is - considered primitive, even though the cube is a major factor in human - strategies when playing for blood or money. Gammon IV always plays - for the simple fun of aggravating humans, so cube tactics are neither - daring nor profound. Gammon IV does not bluff with the cube; if it - offers the cube, it is almost sure to win. - -*****************************************************************************/ - -#define TRUE 1 -#define FALSE 0 -#define ME 1 -#define YU 2 -#define YRBAR 0 -#define MYBAR 25 -#define YRHOME 26 -#define MYHOME 27 -#define ERROR 999 /* anything well out of range */ -#define MYLEVEL 2 - -/* put CRT stuff first so version differences won't affect it */ -#asm -; -; Note: Assumes assembly by M80.COM -; -; *========================= CRT Module =========================* -; * * -; * User Patch Area: ALL DB STRINGS MUST TERMINATE WITH A NULL * -; * Use contiguous data area for all console functions, so user * -; * may configure the program for some terminal not a Kaypro 10 * -; * * -; * CLEAR SCREEN and GOTOXY are Required Minimum Functions * -; * CRTNIT, CRTXIT, CURSON, CURSOF are Optional and Recommended * -; * * -; * The tokens TK1..TK4 comprise two sets each of playing tokens * -; * for the computer & human player. 24 bytes are reserved for * -; * EACH token, so that users may turn on video enhancements -- * -; * see the Kaypro '84 recommended settings for examples. * -; * * -; * The tokens TK5..TK8 and the KRTNIT, etc. strings implement * -; * the Control-K command to toggle the Kaypro '84 display. * -; * These should only be patched if you are configuring for two * -; * levels of terminal characteristics, as vis-as-vis the "old" * -; * and "new" Kaypro terminals. These two levels must use the * -; * same basic protocols for cursor address and clear screen. * -; * * -; * Command Strings must terminate with 0, and the 0 byte CANNOT * -; * be sent to the console. 0 is INCLUDED in the reserved area. * -; * * -; * GAMMON IV no longer uses any console command function not * -; * specifically mentioned here. In particular, the clear-to- * -; * end-of-line function is now handled in a more general way. * -; *==============================================================* -; -; Gammon IV.09 (Universal Version) User Patch Area, D.C.OSHEL, 6/15/85 -;---------------------------------------------------------------------------- -; -; * REQUIRED * -; reserve 24 bytes apiece for the players' tokens (must terminate with 0) -; these settings are recommended for Lear Siegler ADM-3A (old Kaypros) -; - DB 'USER PATCH AREA ' - DB 'ALL STRINGS MUST HAVE ZERO TERMINATOR->' - DB 'TOKEN1:' -TK1: DB '(',')',0,0,0,0,0,0 ; computer's token, () - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 'TOKEN2:' -TK2: DB '[',']',0,0,0,0,0,0 ; player's token, [] - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 'TOKEN3:' -TK3: DB 'q','b',0,0,0,0,0,0 ; computer's token (alternate, qb ) - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 'TOKEN4:' -TK4: DB 'C','3',0,0,0,0,0,0 ; player's token (alternate, C3 ) - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -;---------------------------------------------------------------------------- -; -; * Optional * -; reserve 8 bytes apiece for the OPTIONAL console function strings -; patch the first byte to 0 for each function NOT implemented -; - DB 'CRTNIT:' -CRTNIT: DB 0,0,0,0,0,0,0,0 ; crt init, e.g., video mode on - DB 'CRTXIT:' -CRTXIT: DB 0,0,0,0,0,0,0,0 ; crt exit, e.g., video mode off - DB 'CURSON:' -CURSON: DB 0,0,0,0,0,0,0,0 ; cursor ON (show cursor) - DB 'CURSOF:' -CURSOF: DB 0,0,0,0,0,0,0,0 ; cursor OFF (hide cursor) -;---------------------------------------------------------------------------- -; -; * REQUIRED * -; clear screen and gotoxy (0,0 is top left of screen) are NOT optional -; default settings are for the Lear Siegler ADM-3A terminal (old Kaypros) -; - DB 'CLS->' -CLS: DB 26,0,0,0,0,0,0,0 ; clear screen command - DB 'GOTOXY->' -GOXY: DB 27,'=',0,0,0,0,0,0 ; cursor address prefix - DB 'YB4X BYTE:' -YB4X: DB 1 ;BYTE 1 = YX: Send Row, Then Col (ADM-3A); 0 = XY: Col, Row - DB 'XOFS BYTE:' -XOFS: DB 32 ;BYTE offset to add to x in gotoxy sequence (ADM-3A = 20H) - DB 'YOFS BYTE:' -YOFS: DB 32 ;BYTE offset to add to y in gotoxy sequence (ADM-3A = 20H) -; -; these strings must terminate with 0, and 8 bytes are reserved for each -; -; -;---------------------------------------------------------------------------- -;: The following strings implement the Control-K command for Kaypro '84 -;: video able terminals. -;---------------------------------------------------------------------------- -;: -;: * Kaypro '84 * -;: recommended tokens for the video able Kaypro '84s (10s, 4'84s, etc) -;: the second set requires that "video mode" be set in the CRTNIT string -;: the first set uses Kaypro underline, inverse and low intensity commands -;: to form the players' stones (24 bytes are reserved for each token) -;: - DB 'ENHANCED ALTERNATES->' - DB 'TOKEN5:' -TK5: DB 27,'B1' ; computer's token - DB 27,'B0' - DB 27,'B3' - DB '><' - DB 27,'C3' - DB 27,'C0' - DB 27,'C1' - DB 0,0,0,0 - DB 'TOKEN6:' -TK6: DB 27,'B3' ; player's token - DB 27,'B0' - DB '[]' - DB 27,'C0' - DB 27,'C3' - DB 0,0,0,0,0,0,0,0,0,0 - DB 'TOKEN7:' -TK7: DB 128,233,129,150,0,0,0,0 ; computer's "black chiclet" - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 'TOKEN8:' -TK8: DB 128,253,129,190,0,0,0,0 ; player's "white chiclet" - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -; -;---------------------------------------------------------------------------- -;: -;: * Kaypro '84 * -;: recommended settings for Kaypro '84s (strings must terminate with 0) -;: - DB 'KRTNIT:' -KRTNIT: DB 27,'B5',0,0,0,0,0 ; crt init, e.g., video mode on - DB 'KRTXIT:' -KRTXIT: DB 27,'C5',0,0,0,0,0 ; crt exit, e.g., video mode off - DB 'KURSON:' -KURSON: DB 27,'B4',0,0,0,0,0 ; cursor ON (show cursor) - DB 'KURSOF:' -KURSOF: DB 27,'C4',0,0,0,0,0 ; cursor OFF (hide cursor) - DB '<-END USER PATCH AREA' -;---------------------------------------------------------------------------- -; LOF LG -#endasm - -static int kaypro; - -get1tkn() { -#asm - LXI H,TK1 ;load string pointer for token 1 -#endasm -} - -get2tkn() { -#asm - LXI H,TK2 ;load string pointer for token 2 -#endasm -} - -get3tkn() { -#asm - LXI H,TK3 ;load string pointer for token 3 -#endasm -} - -get4tkn() { -#asm - LXI H,TK4 ;load string pointer for token 4 -#endasm -} - -get5tkn() { -#asm - LXI H,TK5 ;load string pointer for token 1 -#endasm -} - -get6tkn() { -#asm - LXI H,TK6 ;load string pointer for token 2 -#endasm -} - -get7tkn() { -#asm - LXI H,TK7 ;load string pointer for token 3 -#endasm -} - -get8tkn() { -#asm - LXI H,TK8 ;load string pointer for token 4 -#endasm -} - -getcls() { -#asm - LXI H,CLS -#endasm -} - -getcini() { -#asm - LXI H,CRTNIT -#endasm -} - -getcxit() { -#asm - LXI H,CRTXIT -#endasm -} - -getcof() { -#asm - LXI H,CURSOF -#endasm -} - -getcon() { -#asm - LXI H,CURSON -#endasm -} - -getkini() { -#asm - LXI H,KRTNIT -#endasm -} - -getkxit() { -#asm - LXI H,KRTXIT -#endasm -} - -getkof() { -#asm - LXI H,KURSOF -#endasm -} - -getkon() { -#asm - LXI H,KURSON -#endasm -} - -gotoxy(x,y) int x,y; { /* this is solid gold! */ -#asm - POP H ; get return address - POP D ; get Y - POP B ; get X - PUSH B ; restore all to keep C happy - PUSH D ; ditto - PUSH H ; ditto -; - LXI H,GOXY ; blast out the prefix - CALL STOUT -; - LDA YB4X ; sending row, i.e. Y, first? - ORA A - JZ @X1 ; no, do it the other way -; - LDA YOFS ; yes indeed, here's Y - ADD E - CALL COUT -; - LDA XOFS ; and here's X - ADD C - CALL COUT - RET ; thank you very much, we're done - -@X1: LDA XOFS ; your weird terminal wants X first? ok - ADD C - CALL COUT -; - LDA YOFS ; now Y - ADD E - CALL COUT - RET ; tyvm, we done -; -STOUT: MOV A,M ; string pointer in HL on entry, trash A, HL - ORA A - RZ - CALL COUT - INX H - JMP STOUT -; -COUT: PUSH H ; char in A on entry, disturb nothing - PUSH D - PUSH B - PUSH PSW - MVI C,6 - MOV E,A - CALL 5 - POP PSW - POP B - POP D - POP H - RET -#endasm -/* using this C code instead of inline will slow things down perceptibly */ -/* puts( getprfx() ); - if ( ybefore() ) { - putc(y + getyofs(),0); putc(x + getxofs(),0); - } - else { - putc(x + getxofs(),0); putc(y + getyofs(),0); - } -*/ -} /* end: gotoxy */ - - -crtinit() { - if (kaypro) puts( getkini() ); - else puts ( getcini() ); -} /* here, turn 2 byte graph chars on */ - -crtexit() { - if (kaypro) puts( getkxit() ); - else puts ( getcxit() ); -} /* and off again on exit... */ - -clr_screen() { puts ( getcls() ); } /* standard */ - -on_cursor() { - if (kaypro) puts( getkon() ); - else puts ( getcon() ); -} /* optional "hide cursor" command */ - -off_cursor() { - if (kaypro) puts( getkof() ); - else puts ( getcof() ); -} /* optional "show cursor" command */ - - -#include "printf.c" - -extern char *bgversion; - -char *backtalk[] = { - "VILLIERS: At your service!", - "LOUISA: Delighted!", - "TORVE: Is interesting line of occurrence. Thurb!", - "Copyright (c) 1985 by The Xochitl Sodality Wonders & Marvels Committee", - }; - -int list[2][28]; /* two dice, two lists */ - -struct board { - int stones, /* number of stones on that point */ - owner, /* and whose they are */ - x,y, /* x and y coordinates of point base */ - lastx,lasty, /* last location drawn on this point */ - cx,cy; /* coordinates for column numbers */ - } - point[28], bdsave[28]; /* 24 points, plus 2 bars, 2 homes */ - - -struct { int cube, whosecube; } doubles; - - -struct { int fr,to,flag; } pending; - - -int level, dice[2], myscore, yrscore, player, movesleft, cantuse, myturns, - swapped, tswap, deciding, expert, tone, show, moremsgline, - firstmove, helpdisabled, yrdice, lookforit, startcubevalue; - -char *token1, *token2, chatter[80], buzzard[8]; - -/*====================================================================== - - OPPONENT -- A little scenario, in which to select level of play - -========================================================================*/ - - -char *chooseplayer() { -int ch; char *q; - - dissemble(); -loo: ch = getkey(); - switch (ch) { - case 'A': - case 'V': { level = 0; break; } - case 'L': - case 'P': { level = 1; break; } - case 'T': { level = 2; break; } - default: goto loo; - } - q = backtalk[ level ]; - clr_screen(); draw_board(q); - return(q); - -} /* end: chooseplayer */ - -/*==================================================================== - MAIN -======================================================================*/ - -main() { -static int ch; -static char *p1 = "P(lay, R(everse, S(wap, A(rrange, N(ew, G(raphic, Q(uit ", - *p2 = "U(se %s dice, O(pponent, X(pert, B(eep, C(ount, Z(ero ", - *myline; - - level = MYLEVEL + 1; /* fetch copyright notice */ - setup(); - hint(); - - while (TRUE) { - moremsgline = FALSE; /* show first command line on entry */ - debug(""); /* erase messages */ - myline = backtalk[ level ]; /* did level change? */ - msg( myline ); - firstmove = TRUE; - newboard(); /* note, sets starting cube value to 1 */ - - deciding = TRUE; - while (deciding) { - - /* display command line */ - - off_cursor(); - if (show) { mytotal(); yrtotal(); } - else { gotoxy(0,3); puts(" "); gotoxy(0,19); puts(" "); } - if (tone) beep(); - if (expert) msg("Your pleasure? "); - else { - msg("Select: "); - if (moremsgline) printf(p2,(yrdice? "my": "your")); - else printf(p1); - } - - /* get response and do it */ - - - ch = getkey(); - switch (ch) { - case 'Q': { /* quit play, exit to CP/M */ - finishup(); - break; - } - case 'A': { /* arrange stones (or cheat?) */ - /* play is suspended, so don't use the long */ - /* messages that assist game play */ - helpdisabled = TRUE; - arrange(); - update(); - debug(""); - break; - } - case 'R': { /* mirror board image */ - reverse(); - update(); - break; - } - case 'C': { /* show mytotal, yrtotal counts */ - show ^= TRUE; - break; - } - case 'S': { /* SWAP Command - exchange stones */ - swaptokens(); - update(); - break; - } - case 'B': { /* kill the beep */ - tone ^= TRUE; break; - } - case 'X': /* expert mode toggle(s) */ - case 27 : { - expert ^= TRUE; - break; - } - case 'D': { /* use my dice or your dice? */ - case 'U': - yrdice ^= TRUE; - break; - } - case 'O': { /* change opponents and skill level */ - myline = chooseplayer(); - deciding = FALSE; - break; - } - case 'P': { /* play the game as board is arranged */ - helpdisabled = FALSE; - if (level > MYLEVEL ) { - myline = chooseplayer(); - update(); - } - play(); - break; - } - case 'G': /* graphic screen switch, same as: */ - case 11: { /* control-K, toggle Kaypro '84 display */ - crtexit(); - kaypro ^= TRUE; - crtinit(); - swaptokens(); swaptokens(); - swaptokens(); swaptokens(); - update(); - break; - } - case 'N': { /* abandon game without quitting */ - deciding = FALSE; player = 0; - break; - } - case 'Z': { /* zero the score */ - myscore = yrscore = 0; putscore(); - break; - } - default: { moremsgline ^= TRUE; break; } - }} - } -} /* end: main */ - - - - -/*======================================================================= - - PLAY Command - this is the command that initiates the 2-player game - -=========================================================================*/ - -play() { - -/* any vars here MUST be STATIC */ - -#asm - MOV B,H ;set up to exit this function by saving caller's - LXI H,0 ;stack pointer for use in deeply-nested scope - DAD SP ;WARNING: this function must not use dynamic variables - SHLD _fool ;CAUTION: risky business if called with parameters?? - MOV H,B ;HL is restored on general principles, BC is trashed -#endasm - - whofirst(); - taketurns(); - -} /* end: play */ - - - -whofirst() { -int ch, myval, yrval; - - if (yrdice || (player < 0)) { /* board has been re-arranged */ - msg("Is it my "); puts(token1); - puts(" turn or your "); puts(token2); - puts(" turn? "); - loo: ch = toupper(getc(0)); - if (!(ch == 'M' || ch == 'Y')) goto loo; - if (ch == 'M') player = YU; /* player says Me, of course! */ - else player = ME; - rolldice(player); - } - - else if (player == 0) { /* fresh start, roll the dice */ - barcube(); - zoo: debug("Tossing for first turn..."); - wipedice(); - rolldice(ME); - myval = dice[0]; - rolldice(YU); - yrval = dice[0]; - if (myval == yrval) { - if (tone) beep(); - off_cursor(); - gotoxy(37,11); puts("[___]"); sleep(3); - startcubevalue *= 2; - if (startcubevalue > 8) startcubevalue = 8; - doubles.cube = startcubevalue; - gotoxy(37,11); - if (doubles.cube < 16) printf("[ %d ]",doubles.cube); - else printf("[%03d]",doubles.cube); - if (startcubevalue < 9) { - msg("Double the cube!"); - sleep(20); - } - goto zoo; - } - else if (myval < yrval) player = YU; - else player = ME; - dice[0] = max(myval,yrval); dice[1] = min(myval,yrval); - } - /* otherwise, continue with last dice rolled as play is resumed */ - -} /* end: whofirst */ - - -getmove() { -static int i, ch, temp, happy; - - cantuse = ERROR; /* important for human player in tellmove */ - movesleft = 2; - if (dice[0] == dice[1]) movesleft += 2; - temp = movesleft; - - getlist(); saveboard(); lookforit = TRUE; - - if ( nomove() ) { - debug("All "); - if (player == ME) puts("my"); else puts("your"); - puts(" moves are blocked!"); - if (player == YU) sleep(20); - return; - } - - - if (player == ME) { - /* handle doubles as two consecutive, independent moves */ - setchat("I move"); debug(chatter); - if (movesleft == 4) myturns = 2; else myturns = 1; - clrpend(); - while (myturns > 0) { - cantuse = ERROR; - movesleft = 2; - while (movesleft > 0) { getlist(); mymove(); } - myturns--; - } - strcat(chatter,"\008."); debug(chatter); - } - else { /* allow the human to take back a bad board position */ - happy = FALSE; - while (!happy) { - while (movesleft > 0) { getlist(); yrmove(); } - msg("All ok? Y/N "); - do { - ch = getkey(); - } while (ch != 'N' && (ch != 'Y' && ch != '\n')); - if ( ch == 'N' ) { - msg("Ok, as it was..."); - restoreboard(); - update(); - movesleft = temp; - cantuse = ERROR; - } - else happy = TRUE; - debug(""); - } - } - -} /* end: getmove */ - - - -taketurns() { - - while (TRUE) { /* NO EXIT! Only a Win or player ESC can exit */ - - getmove(); - player = other(player); - if ( player == ME ) { - if ( endgame() ) { - if (topstone(ME) < 6 && cubeval()) idouble(); - else if ( mytotal() < (yrtotal() - 8) ) { - idouble(); - } - } - else if ( bearoff() ) idouble(); - } - rolldice (player); - } - -} /* end: taketurns */ - - - - - -/*=============================================*/ -/* Y O U R M O V E */ -/*=============================================*/ - -tellmove() { /* show what the player's current dice are */ -int k,n; - - n = movesleft; - debug("You "); - if (!expert) { puts(token2); puts(" "); } - puts("have "); - while (n--) { - if (dice[0] == dice[1]) k = dice[0]; /* doubles? */ - - else if (cantuse == 1) k = dice[0]; - else if (cantuse == 0) k = dice[1]; - else if (n == 1) k = dice[1]; /* 2 of 2? */ - else k = dice[0]; /* 1 of 2? */ - - printf("[%d] ",k); - } - puts("left"); - if (expert) puts("."); else puts(", moving from high to low."); - -} /* end: tellmove */ - - - -yrmove() { - - if ( nomove() ) { - debug("You have no more moves in this line of play."); - movesleft = 0; - return; - } - else { -loo: tellmove(); - if (!getyrmove()) { - hint(); - goto loo; - } - debug(""); - } - -} /* end: yrmove */ - - - -hint() { - if (!expert) { - debug("HELP, BAR and HOME are useful words in this game."); - sleep(10); - } -} /* end: hint */ - - - -nomove() { -int i,j; - for (i = 0; i < 2; i++) - for (j = 0; j < 28; j++) - if (list[i][j] != ERROR) return (FALSE); - return (TRUE); -} /* end: nomove */ - - - -getyrmove() { -int fpoint, tpoint; - - - firstmove = FALSE; /* I got it, I got it! */ - - msg("Move from? "); - fpoint = getpt(YRBAR,YRHOME); - if ( fpoint == ERROR || - (list[0][fpoint] == ERROR && list[1][fpoint] == ERROR)) { - return (FALSE); - } - puts(" To? "); - tpoint = getpt(YRBAR,YRHOME); - if ( tpoint == ERROR || - (list[0][fpoint] != tpoint && list[1][fpoint] != tpoint)) { - return (FALSE); - } - - movestone( fpoint, tpoint ); - if (movesleft < 2) { - if (list[0][fpoint] == tpoint) cantuse = 0; - else cantuse = 1; - } - return (TRUE); - -} /* end: getyrmove */ - - - -/*====== Functions That Make The Selected Move ======*/ - - -setchat( p ) char *p; { - strcpy(chatter,p); -} /* end: setchat */ - - - -putdice( f,t) int f,t; { -static char q[15]; - if (t == MYHOME) sprintf(q," %d to Home,",25 - f); - else if (f == MYBAR) sprintf(q," Bar to %d,",25 - t); - else sprintf(q," %d to %d,",25 - f, 25 - t); - strcat(chatter,q); - debug(chatter); /* avoid using save_cursor() */ -} /* end: putdice */ - - - -lurch( f, t, zlist ) int f, t, zlist; { - movestone( f, t ); /* move the stone */ - putdice(f,t); /* tell user, the action is a bit fast */ - if (movesleft < 2) cantuse = zlist; -} /* end: lurch */ - - - -/*****************************/ -/* must LINK to GAMEPLAN.REL */ -/*****************************/ - - - -/*========================================================================== - - GETLIST -- Find the possible moves for any particular throw of the dice - -===========================================================================*/ - - -checkpips( whichlist, ptimon, pips, tops ) -int whichlist, ptimon, pips, tops; { -static int j,k; - - if ( !ptimon ) { - j = whosebar(player); /* 0 if you, 25 if me */ - k = abs(j - pips); - } - else if (player == ME) { - j = ptimon; - k = j - pips; - if (k < 1) k = MYHOME; - } - else { - j = 25 - ptimon; - k = j + pips; - if (k > 24) k = YRHOME; - } - - if (point[j].stones > 0 && point[j].owner == player) { - - /* no move to a blocked point */ - if (point[k].owner != player && point[k].stones > 1) - return; - - /* no move home if i can't bear off yet */ - if (k == whosehome(player) && cantbearoff(j,pips,tops)) - return; - - /* no other move is allowed if i'm on the bar */ - if (tops == 25 && j != whosebar(player)) - return; - - /* the move is legal (but maybe not optimal) */ - list [whichlist] [j] = k; - } - -} /* end: checkpips */ - - - -build( whichlist, pips ) int whichlist, pips; { -int i, tops; - - if (whichlist == cantuse) return; - tops = topstone(player); - for (i = 0; i < 25; i++) checkpips( whichlist, i, pips, tops ); - -} /* end: build */ - - - -getlist() { /* find all legal moves using these dice */ -static int i, j; - - for (i = 0; i < 2; i++) /* initialize the lists */ - for (j = 0; j < 28; j++) - list [i] [j] = ERROR; - - build( 0, dice[0] ); /* usually the low die */ - build( 1, dice[1] ); /* usually the high die */ - -} /* end: getlist */ - - - -/*========================================================================== - - EVALUATE UTILITIES -- Functions for legal and/or best play, telling who's - who, who's ahead, who won, etc. etc. - -============================================================================*/ - - - -mytotal() { -int i, cnt; - - cnt = 0; - for (i = 0; i < 26; i++) { - if (point[i].owner == ME) cnt += point[i].stones * i; - } - if (show) { - gotoxy(0,3); printf("%03d",cnt); - } - return (cnt); - -} /* end: mytotal */ - - -yrtotal() { -int i, cnt; - - cnt = 0; - for (i = 0; i < 26; i++) { - if (point[i].owner == YU) cnt += point[i].stones * (25 - i); - } - if (show) { - gotoxy(0,19); printf("%03d",cnt); - } - return (cnt); - -} /* end: yrtotal */ - - - -topstone( who ) int who; { -static int i,j; - - if (point[ whosebar( who ) ].stones > 0) i = 25; - else { - i = 24; - while (i > 0) { - if (who == ME) j = i; else j = 25 - i; - if (point[j].stones > 0 && - point[j].owner == who) return (i); - --i; - } - } - return (i); /* return normalized value, 1 - 25, 0 is home */ - -} /* end: topstone */ - - - -cantbearoff( mypt, pips, tops ) int mypt, pips, tops; { - - /* My destination is Home, but can I do it??? */ - if (mypt > 6) mypt = 25 - mypt; /* normalize inner table */ - - /* I can't bear off if there's anybody still not in my inner table */ - if (tops > 6) return (TRUE); - - /* If I'm the highest blot in my own table, I CAN bear off */ - if (tops == mypt) return (FALSE); - - /* If I'm NOT high, I have to have an exact roll to get away with it */ - return ( (mypt != pips) ); - -} /* end: cantbearoff */ - - - -whosebar( who ) int who; { - return ( (who == ME? MYBAR: YRBAR) ); -} - - - -whosehome( who ) int who; { - return ( (who == YU? YRHOME: MYHOME) ); -} - - - -checkwin() { - if (mytotal() == 0) winner(ME, topstone(YU)); - if (yrtotal() == 0) winner(YU, topstone(ME)); -} /* end: checkwin */ - - -other( color ) int color; { - - if (color == ME) return (YU); else return (ME); - -} /* end: otherplayer */ - - - - -winner( who, high ) int who, high; { -int gammon; char ch; - - if (tone) beep(); - if (point[ whosehome( other(who) )].stones > 0) gammon = 1; - else gammon = 2; /* nothing off is a gammon! */ - if (high == 0) gammon = 1; /* someone doubled */ - else if (high > 18) gammon = 3; /* backgammon! */ - - - debug(""); - if (who == ME) puts("I"); else puts("You"); puts(" win"); - switch (gammon) { - case 1: { puts("!"); break; } - case 2: { puts(" a Gammon!"); break; } - case 3: { puts(" a Backgammon!"); break; } - } - gammon *= doubles.cube; - switch (who) { - case ME: { myscore += gammon; break; } - case YU: { yrscore += gammon; break; } - } - putscore(); - msg("Hit ESC to resume play"); - loo: ch = getc(0); if (ch != 27) goto loo; - player = 0; - reverse(); deciding = FALSE; jumpjack(); - -} /* end: winner */ - - -putscore() { - gotoxy(39,0); blanks(39); gotoxy(53,0); - printf("SCORE: You %d, Me %d",yrscore,myscore); -} /* end: putscore */ - - - - -/*======================================================================== - - REVERSE Command - allow player to take the opponent's viewpoint of the - board layout, mirror the board. Returns board layout - to the arranged position as seen from opposite side. - -==========================================================================*/ - -reverse() { -int cnt1, cnt2, cnt3, cnt4; - - off_cursor(); - cnt1 = point[MYHOME].stones; /* save counts for erase */ - cnt2 = point[YRHOME].stones; - cnt3 = point[MYBAR].stones; - cnt4 = point[YRBAR].stones; - - putstone( MYHOME, 0, 0); /* erase old trays before update */ - putstone( YRHOME, 0, 0); - - halfswap(1); halfswap(13); - - gotoxy(0,11); puts(" "); /* erase HOME message */ - gotoxy(75,11); puts(" "); - if (point[1].x < 40) { - point[MYHOME].x = point[YRHOME].x = 0; - } - else { - point[MYHOME].x = point[YRHOME].x = 75; - } - - point[MYHOME].owner = point[MYBAR].owner = ME; /* restore counts */ - point[YRHOME].owner = point[YRBAR].owner = YU; - point[MYHOME].stones = cnt1; - point[YRHOME].stones = cnt2; - point[MYBAR].stones = cnt3; - point[YRBAR].stones = cnt4; - -} /* end: reverse */ - - -#asm - DB 'Gammon IV concept & text graphic rendition by David C. Oshel',0 - DB 'MidSummer''s Day, June 21, 1985',0 - DB 'To Whomever Destroys This Notice -- Nothing Shall Happen, Forever',0 -#endasm - - -halfswap( n ) int n; { -static int i, j, k, o; - - o = n + 6; - for (i = n; i < o; i++) { - j = ((o * 2) - 1) - i; - k = point[i].x; - point[i].cx = point[i].x = point[j].x; - point[j].cx = point[j].x = k; - } - -} /* end: halfswap */ - - - - - -getkey() { -int ch; - ch = getc(0); /* keybounce? */ - while ( (ch = toupper(getc(0))) == 0 ) acg(); return (ch); -} /* end: getkey */ - - -wipedice() { -static char *s = " "; - - off_cursor(); - gotoxy(47,11); puts(s); /* erase dice roll messages */ - gotoxy(12,11); puts(s); - -} /* end: wipedice */ - - - -update() { -int i, x, c; - - for (i = 1; i < 25; i++) { - gotoxy(point[i].cx,point[i].cy); - printf("%2d",25 - i); - } - if (doubles.whosecube == YU) yrcube(doubles.cube); - else if (doubles.whosecube == ME) mycube(doubles.cube); - else barcube(); - for (i = 0; i < 28; i++) { - x = point[i].stones; - c = point[i].owner; - putstone(i,x,c); - } - if (point[1].x < 40) x = 0; else x = 75; - gotoxy(x,11); puts("HOME"); - - putscore(); mytotal(); yrtotal(); - -} /* end: update */ - - -dissemble() { - - clr_screen(); - -puts("You are a passenger in the \"Orion\" bound for STAR WELL, a slightly disreputable\n"); -puts("planetoid in the Flammarion Rift, where you have a scheduled layover of several\n"); -puts("hours. You enter the Casino there, desperately bored. Your attention is \n"); -puts("immediately drawn to an unusual trio. Your instinct for good company (they \n"); -puts("are playing Backgammon) leads you easily into a round of introductions:\n"); -puts("\n"); -puts("LOUISA PARINI -- A young woman who gives you the uncomfortable feeling that she\n"); -puts("is even younger than she looks. In fact, she is the offspring of a clan of\n"); -puts("noted interstellar jewel thieves and con artists, on her way to a famous\n"); -puts("girl's finishing school on Nashua. She has larceny in her soul, but she is on\n"); -puts("holiday. Do not underestimate her. (But you will, of course. You must.)\n"); -puts("\n"); -puts("ANTHONY VILLIERS -- A mysterious young fop with impeccable manners, and (you\n"); -puts("notice) an even more impeccable dueling saber at his side. There is something\n"); -puts("between Louisa and him. His conversation is light, witty and just slightly\n"); -puts("cynical, but you are not wrong to conclude that this is someone you can trust.\n"); -puts("\n"); -puts("TORVE THE TROG -- This blue-eyed, golden-furred entity is a member of the most\n"); -puts("dangerous and unpredictable race in the galaxy (aside from humans). You are \n"); -puts("amazed that this one is allowed to travel. (In fact, Torve's papers were forged\n"); -puts("by a member of Louisa's family and procured for him by Villiers). Torve is\n"); -puts("lost in some inner rapture, emitting soft \"Thurb\"-like noises.\n"); -puts("\n(Hit any key to continue)"); -getkey(); -puts("\015You suggest a friendly game of backgammon, at small stakes, and your\n"); -puts("companions agree instantly. Who will be your opponent? (L, V, or T) "); - -} /* end: dissemble */ - - -/*====================================================================== - - ARRANGE Command: Move stones around in the playing area. Play will - commence with this final arrangement. Notice, this - command allows for cheating because the line input - function traps Ctrl-C and executes jumpjack(). Player - returns to the command line with the game frozen, may - re-arrange as desired, then resume play. The Ctrl-C - trap will increment play level by 1. The sufficiently - stupid player will not notice, and so may lose anyway. - Trap implemented in MYLIB2.C, not here. - -========================================================================*/ - - -arrange() { /* whoever calls arrange() must also call update() next */ - -/* any vars here MUST be STATIC */ - -#asm - MOV B,H ;set up to exit this function by saving caller's - LXI H,0 ;stack pointer for use in deeply-nested scope - DAD SP ;WARNING: this function must not use dynamic variables - SHLD _fool ;CAUTION: risky business if called with parameters?? - MOV H,B ;HL is restored on general principles, BC is trashed -#endasm - - moveabout(); - -} /* end: arrange */ - - - -moveabout() { - - player = -1; /* flag to ask who moves first */ - if (!expert) - debug("Type BAR or HOME, or the Number of a Point."); - - while ( TRUE ) { /* exit via jumpjack() by typing Control-C */ - mytotal(); - yrtotal(); - revise(); - } - -} /* end: moveabout */ - - - -getpt(b,h) int b,h; { -static char ans[6], *p; int x, d1, d2, look, try; - - on_cursor(); - gets(ans,5); - p = ans; - while (*p) *p = toupper(*p++); /* capitalize string */ - off_cursor(); - - if (!helpdisabled && ((index(ans,"HEL") != -1) || - (index(ans,"?") != -1))) { - x = ERROR; - msg(""); - if (point[ whosebar(player) ].stones > 0) { - puts("You're on the Bar, so let's move that one! BAR "); - x = b; - } - else { - puts("Are you "); - if (cantuse != 0 && cantuse != 1) puts("REALLY "); - puts("blocked? Try moving From "); - look = 24; - while (look > 0) { - try = list[0][look]; - if (try == ERROR) try = list[1][look]; - if ( try != ERROR ) { - printf("%d To ",25-look); - if (try == YRHOME) printf("HOME"); - else printf("%d",25-try); - look = 0; - } - look--; - } - sleep(40); - } - } - else if (index(ans,"B") != -1) x = b; - else if (index(ans,"H") != -1) x = h; - else { - x = atoi( ans ); - if (x < 1 || x > 24) x = ERROR; - else x = 25 - x; /* translate human to computer view */ - } - return (x); - -} /* end: getpt */ - - -whoseit(p,a,b) char *p; int a,b; { -int ch; - - if (point[a].stones > 0 && point[b].stones > 0) { - debug("Whose "); puts(p); puts("? 1 = "); - puts(token1); - puts(" 2 = "); puts(token2); puts(" "); - loo: ch = getkey(); - if (!(ch == '1' || ch == '2')) goto loo; - - debug("From "); - if (ch == '1') { ch = a; puts(token1); } - else { puts(token2); ch = b; } - puts("'s "); puts(p); - return ( ch ); - } - else if (point[a].stones > 0) return (a); - else if (point[b].stones > 0) return (b); - else return (ERROR); - -} /* end: whoseit */ - - - -revise() { - do { - setchat("Move a Stone From? "); - msg(chatter); - } - while ( !delightful() ); - -} /* end: revise */ - - -delightful() { -static int from, to, fcnt, tcnt, fcolor, tcolor; - - from = getpt(MYBAR,MYHOME); - - sprintf(buzzard,"%d",abs(25 - from)); - - if (from == MYBAR) { - from = whoseit("bar",MYBAR,YRBAR); - strcpy(buzzard,"BAR"); - } - - if (from == MYHOME) { - from = whoseit("home",MYHOME,YRHOME); - strcpy(buzzard,"HOME"); - } - - if (from == ERROR) { - debug("Type Control-C to quit."); - return( FALSE ); - } - - /*-----------------------------------------------------*/ - /* establish the color of the stones on the from point */ - /*-----------------------------------------------------*/ - fcolor = point[from].owner; - - /*--------------------------------------------------*/ - /* establish the number of stones on the from point */ - /*--------------------------------------------------*/ - fcnt = point[from].stones; - - if (fcnt == 0) { - debug("What's the point?"); - return(FALSE); - } - - strcat(chatter,buzzard); /* this avoids use of save_cursor() */ - strcat(chatter," To? "); - msg(chatter); - - to = getpt(MYBAR,MYHOME); - - sprintf(buzzard,"%d",abs(25 - to)); - - - if (to == MYBAR) { - if (fcolor == YU) to = YRBAR; - strcpy(buzzard,"BAR"); - } - - if (to == MYHOME) { - if (fcolor == YU) to = YRHOME; - strcpy(buzzard,"HOME"); - } - - if (to == ERROR) { - debug("Type Control-C to quit."); - return(FALSE); - } - - if (from == to) { - debug("Quite easily done!"); - return(FALSE); - } - - strcat(chatter,buzzard); - - /*---------------------------------------------------*/ - /* establish the color of the stones on the to point */ - /*---------------------------------------------------*/ - tcolor = point[to].owner; - - /*------------------------------------------------*/ - /* establish the number of stones on the to point */ - /*------------------------------------------------*/ - tcnt = point[to].stones; - - if (fcolor == tcolor || tcolor == 0) { - msg(chatter); - --fcnt; - ++tcnt; - putstone(from, fcnt, fcolor); /* one less */ - putstone(to, tcnt, fcolor); /* one more */ - debug(""); - return (TRUE); - } - else { - debug("Evict the other stone"); - if (tcnt > 1) puts("s"); - puts(" first!"); - return (FALSE); - } - -} /* end: delightful */ - - -/*========================================================================== - - INITIALIZATION and NEWBOARD commands -- start of a new game, or cold - -===========================================================================*/ - - -wipeout() { -static int i; - - player = 0; - barcube(); - for (i = 0; i < 28; i++) { - point[i].stones = point[i].owner = 0; - } - update(); - -} /* end: wipeout */ - - -setup() { -static int i, j, k, copyright; - - myscore = yrscore = player = dice[0] = dice[1] = 0; - kaypro = swapped = tswap = expert = helpdisabled = yrdice = FALSE; - show = moremsgline = tone = TRUE; - - init_lib(); - OFFinterrupt(); /* enable jumpjack() on ctl-c */ - crtinit(); /* Kaypro video mode on (2-byte graphics) */ - off_cursor(); - token1 = getAtkn(); - token2 = getBtkn(); - copyright = backtalk[ MYLEVEL + 1 ]; - draw_board( copyright ); - - for (i = 0; i < 28; i++) { - point[i].stones = point[i].owner = 0; - point[i].x = point[i].y = point[i].lastx = point[i].lasty = 0; - point[i].cx = point[i].cy = 0; - } - - k = 68; - for (i = 1; i < 13; i++ ) { /* establish xy coords for the points */ - j = 25 - i; - point[i].cx = point[j].cx = point[i].x = point[j].x = k; - k -= 5; - point[i].y = 4; - point[j].y = 18; - point[i].cy = 2; - point[j].cy = 20; - if (k == 38) k -= 5; /* skip over bar */ - } - - point[MYBAR].x = point[YRBAR].x = 38; - point[MYHOME].x = point[YRHOME].x = 75; - - point[MYBAR].y = point[MYHOME].y = 5; - point[YRBAR].y = point[YRHOME].y = 17; - -} /* end: setup */ - - - -newboard() { -static int i; - - startcubevalue = 1; - wipedice(); wipeout(); - - putstone( MYHOME, 15, ME ); - putstone( YRHOME, 15, YU ); - - putstone( YRHOME, 13, YU ); - putstone( 1, 2, YU ); - - putstone( YRHOME, 8, YU ); - putstone( 12, 5, YU ); - - putstone( YRHOME, 5, YU ); - putstone( 17, 3, YU ); - - putstone( YRHOME, 0, 0 ); - putstone( 19, 5, YU ); - - putstone( MYHOME, 10, ME ); - putstone( 6, 5, ME ); - - putstone( MYHOME, 7, ME ); - putstone( 8, 3, ME ); - - putstone( MYHOME, 2, ME ); - putstone( 13, 5, ME ); - - putstone( MYHOME, 0, 0 ); - putstone( 24, 2, ME ); - -} /* end: newboard */ - - -draw_board( c ) char *c; { -static int line; -static char *m = " ", *picture[] = { -"The Peelgrunt Game of GAMMON IV%s\n\n\n", -":=================================o=================================:\n", -":: .. \\/ .. \\/ .. \\/ ||| .. \\/ .. \\/ .. \\/ ::\n", -":: ||| ::\n", -":: /\\ .. /\\ .. /\\ .. ||| /\\ .. /\\ .. /\\ .. ::\n" -}; - - clr_screen(); - off_cursor(); - msg( c ); - off_cursor(); - gotoxy(0,0); - puts(m); printf(picture[0],bgversion); - puts(m); puts(picture[1]); - for (line = 0; line < 6; line++) { - puts(m); puts(picture[2]); - } - puts(m); puts(picture[3]); - puts(m); puts(picture[3]); - puts(m); puts(picture[3]); - for (line = 0; line < 6; line++) { - puts(m); puts(picture[4]); - } - puts(m); puts(picture[1]); - -} /* end: draw_board */ - - -/*========================================================================= - - DICE Commands: How to roll the dice - -===========================================================================*/ - - -peek() { - if (yrdice) return; /* you know your own dice, probably...? */ - if (expert) debug(""); - else debug("The Dice will Rattle until you Roll. Now on "); - getdice(); - printf("[%d] [%d] ...",dice[0],dice[1]); -} /* end: peek */ - - -getonedie() { - return ( (abs(acg()) % 6) + 1 ); -} /* end: getonedie */ - - -fixup() { /* ensure that the low die is in dice[0] */ -int d,e; - if (player == 0) return; /* whofirst? don't mess with the odds */ - d = min(dice[0],dice[1]); - e = max(dice[0],dice[1]); - dice[0] = d; - dice[1] = e; -} /* end: fixup */ - - -getdice() { -int ch; - - /* if it's MY dice we're using, generate random dice... */ - if (!yrdice) { - dice[0] = getonedie(); - acg(); /* bounce a little for luck */ - dice[1] = getonedie(); - fixup(); - return; - } - - /* but if it's YOUR dice, then ask about the roll... */ -zoo: msg("<> "); - if (player == ME) puts("My"); else puts("Your"); - puts(" roll: "); - if (!expert) puts("\008\008, using your dice: "); - puts(" First? "); -loo: while ( (ch = getc(0)) == 0 ); /* don't bother acg */ - if (ch == 3) haltgame(); - ch -= '0'; - if (ch < 1 || ch > 6) goto loo; - putc( ch + '0',0); - dice[0] = ch; - - puts(" Second? "); - while ( (ch = getc(0)) == 0 ); - if (ch == 3) haltgame(); - ch -= '0'; - if (ch < 1 || ch > 6) goto zoo; - putc( ch + '0',0); - dice[1] = ch; - - puts(" All Ok? "); -roo: while ( (ch = toupper(getc(0))) == 0 ); /* don't bother acg */ - if (ch == 3) haltgame(); - if (ch != 'N' && ch != 'Y') goto zoo; - fixup(); - -} /* end: getdice */ - - - -haltgame() { - player = -1; /* if play resumes, ask whose roll it is */ - hint(); - jumpjack(); - -} /* end: haltgame */ - - - -rolldice( who ) int who; { -int waiting; - - setchat("Your Turn: "); - if (!expert) { - if (!yrdice) strcat(chatter," P(eek,"); - strcat(chatter," D(ouble, Q(uit, or to Roll "); - } - if (player == YU) { /* not executed if player == 0, i.e., whofirst */ - waiting = TRUE; - while (waiting) { - msg(chatter); - switch ( getkey() ) { - /* bailout is Ctrl-C instead of ESCape */ - case 3 : { haltgame(); break; } - case 'P': { peek(); break; } - case 'D': { udouble(); break; } - case 'Q': { winner(ME,topstone(YU)); break; } - default : waiting = FALSE; - } } - off_cursor(); debug(""); msg(""); - } - highroller(who); - -} /* end: rolldice */ - -highroller( who ) int who; { /* parameter is not redundant */ -static int y = 11; -static int xme, xyu; - - /* get the values for two dice, either yours or mine */ - - getdice(); - - /* display the values of the dice in the board area */ - - off_cursor(); - xme = 47; xyu = 12; /* decide which half to show the values in */ - if (point[1].x > 40) { - xme = 12; - xyu = 47; - } - if (player) { - gotoxy(xyu,y); blanks(18); /* erase, if not whofirst */ - gotoxy(xme,y); blanks(18); - } - if (who == ME) { - gotoxy(xme,y); puts("My"); - } - else { - gotoxy(xyu,y); puts("Your"); - } - printf(" Roll> [%d] ",dice[0]); - if (player) printf("[%d] ",dice[1]); /* whofirst doesn't show this */ - -} /* end: highroller */ - - - - - -/*======================================================================== - - MAJOR UTILITIES -- Miscellaneous functions sans which the game will not - proceed so well as otherwise.......... - -========================================================================*/ - -jumpjack() { /* Much too simple-minded LONGJUMP. (But it IS simple!) - CAUTION: C/80 has no idea what's going on here! - The in-line assembly which sets _fool MUST NOT be in - a function which uses dynamic variables, or the stack - will be disrupted. See arrange() and play() herein. */ -#asm - LHLD _fool ;Retrieve old stack status... - SPHL ;...diddle stack pointer - RET ;...and execute the ad hoc jump back to outer loop - -_fool: DS 2 ;stack pointer is saved by doit(), read and used here - -#endasm -} /* end: jumpjack */ - - - -acg() { /* additive congruential generator for pseudo-random numbers */ -static int arg[] = { - 4292, 60, 4947, 3972, 4489, - 1917, 3916, 7579, 3048, 6856, - 1832, 7589, 1798, 4954, 2880, - 5142, 5187, 3045, 1529, 3110, - 4333, 167, 5556, 7237, 5906, - 5419, 6632, 5833, 3760, 1081, - 1434, 80, 6212, 344, 7303, - 3044, 7675, 5420, 457, 3434, - 2657, 700, 6777, 4436, 620, - 2129, 629, 3550, 1639, 4546, - 1220, 6469, 862, 3280, 4664 - }; -static int rp1 = 0, rp2 = 32; - - rp1++; - rp2++; - rp1 %= 55; - rp2 %= 55; - arg[rp1] ^= arg[rp2]; - return ( arg[rp1] ); - -} /* end: acg */ - -finishup() { - crtexit(); on_cursor(); /* restore for user */ - exit(); -} - -saveboard() { -int i; - for (i = 0; i < 28; i++) { - bdsave[i].stones = point[i].stones; - bdsave[i].owner = point[i].owner; - } -} /* end: saveboard */ - -restoreboard() { -int i; - for (i = 0; i < 28; i++) { - point[i].stones = bdsave[i].stones; - point[i].owner = bdsave[i].owner; - } -} /* end: restoreboard */ - - -getAtkn() { - if (kaypro) return( get5tkn() ); - else return( get1tkn() ); -} -getBtkn() { - if (kaypro) return( get6tkn() ); - else return( get2tkn() ); -} -getCtkn() { - if (kaypro) return( get7tkn() ); - else return( get3tkn() ); -} -getDtkn() { - if (kaypro) return( get8tkn() ); - else return( get4tkn() ); -} - -swaptokens() { -char *temp; - - swapped ^= TRUE; - if (swapped) { - temp = token1; - token1 = token2; - token2 = temp; - } - else { - tswap ^= TRUE; - if (tswap) { - token1 = getCtkn(); - token2 = getDtkn(); - } - else { - token1 = getAtkn(); - token2 = getBtkn(); - } - } - -} /* end: swaptokens */ - - -blanks( n ) int n; { - while (n--) putc(' ',0); -} /* end: blanks */ - - -msg(p) char *p; { - on_cursor(); - gotoxy(5,23); blanks(74); - gotoxy(5,23); puts(p); -} - -debug(p) char *p; { - on_cursor(); - gotoxy(5,22); blanks(74); - gotoxy(5,22); puts(p); return(FALSE); -} - - -nxtyp(i) int i; { - if (i > 9) return ( i - 1 ); else return ( i + 1 ); -} - - -isbar(p) int p; { - return (( p == MYBAR ) || ( p == YRBAR )); -} - -ishome(p) int p; { - return (( p == MYHOME ) || ( p == YRHOME )); -} - - -putstone( pt, cnt, color ) int pt, cnt, color; { -int i, xp, yp, slack; -char *background, *token; - - - if (cnt < 1) { /* empty point has neither stones nor owner */ - cnt = 0; - color = 0; - } - - point[pt].stones = cnt; /* number of stones on this point */ - point[pt].owner = color; /* and whose they are */ - - /* stack stones 5 high in the home tray, 6 high on the points */ - if (isbar(pt) || ishome(pt)) slack = 5; else slack = 6; - - /* locate the base address of the point for animation */ - xp = point[pt].x; - yp = point[pt].y; - - - /* decide on the background pattern to be used for empty places */ - if (pt > 12) background = "/\\ "; - else background = "\\/ "; - - if (point[1].x < 40) { - if ((pt % 2) == 1) background = ".. "; - } - else if ((pt % 2) == 0) background = ".. "; - - if (ishome(pt)) background = " "; - if (isbar(pt)) background = "||| "; - - /* get the token pattern to be used */ - if (color == ME) { - token = token1; - } - else { - token = token2; - } - - /* draw the entire point with token and background patterns */ - off_cursor(); - - /* first erase all blots from this point (draw the background) */ - for (i = 0; i < slack; i++) { - gotoxy(xp,yp); - puts(background); /* string has point's width */ - point[pt].lastx = 0; /* future, not implemented */ - point[pt].lasty = 0; - yp = nxtyp(yp); - } - - /* now draw all the blots there are on this point onto the point */ - for (i = 0; i < cnt; i++) { - xp = point[pt].x + (i / slack); - if ((i % slack) == 0) yp = point[pt].y; - gotoxy(xp, yp); - puts(token); - point[pt].lastx = xp; /* future, not implemented */ - point[pt].lasty = yp; - yp = nxtyp(yp); - } - -} /* end: putstone */ - - - -hitblot( from, color ) int from, color; { -static int barpt, addone; - - if (tone) beep(); - barpt = whosebar( color ); - putstone(from, 0, 0); - addone = point[barpt].stones + 1; - putstone( barpt, addone, color ); - -} /* end: hitblot */ - - - -movestone( from, to) int from, to; { -static int opponent, subone, addone; - - - opponent = other( player ); - if (point[to].owner == opponent) hitblot(to, opponent); - - subone = point[from].stones - 1; - addone = point[to].stones + 1; - - putstone(from, subone, player); - putstone(to, addone, player); - - --movesleft; - checkwin(); /* never but NEVER let a win go unnoticed! */ - -} /* end: movestone */ - - - -/*======================================================================== - - CUBE Commands -- commands related to the cube, doubling, etc. - -=========================================================================*/ - -notyrcube() { - gotoxy(75,19); blanks(5); - gotoxy(75,20); blanks(5); -} /* end: notyrcube */ - - -notmycube() { - gotoxy(75,2); blanks(5); - gotoxy(75,3); blanks(5); -} /* end: notmycube */ - - -barcube() { - /* startcubevalue is normally 1, but it may have doubled */ - /* if the opening rolloff for first turn came up doubles */ - doubles.cube = startcubevalue; - doubles.whosecube = 0; - notmycube(); notyrcube(); - gotoxy(37,11); - if (startcubevalue == 1) puts("[BAR]"); - else if (doubles.cube < 16) printf("[ %d ]",doubles.cube); - else printf("[%03d]",doubles.cube); -} /* end: barcube */ - - - -notbarcube() { - gotoxy(37,11); puts(" BAR "); -} /* end: notbarcube */ - - -mycube(value) int value; { - notbarcube(); gotoxy(75,2); puts("CUBE"); - gotoxy(75,3); - sprintf(buzzard,"[%d]",value); - printf("%-5s",buzzard); - doubles.whosecube = ME; - -} /* end: mycube */ - - - -yrcube(value) int value; { - notbarcube; gotoxy(75,19); puts("CUBE"); - gotoxy(75,20); sprintf(buzzard,"[%d]",value); - printf("%-5s",buzzard); - doubles.whosecube = YU; - -} /* end: yrcube */ - - -idouble() { -static int ch; - - if (doubles.whosecube == YU) return; /* not mine, can't double! */ - if (doubles.cube > 256) return; /* maximum, don't consider it */ - notbarcube(); - if (tone) beep(); - debug("I double. Will you accept the cube "); - printf("at %d points? ",doubles.cube * 2); - loo: while ((ch = getc(0)) == 0); - if (toupper(ch) == 'Y') { - notmycube(); - doubles.cube *= 2; - yrcube(doubles.cube); - off_cursor(); - } - else if (toupper(ch) == 'N') winner(ME,0); - else goto loo; - -} /* end: idouble() */ - - - - -backgame() { -int max, barred, count, i; - if (topstone(YU) < 12 && topstone(ME) > 18) { - if (mytotal() < yrtotal() + 4) return (TRUE); - max = barred = count = 0; - i = 24; - while (i > 18) { - if (point[i].owner == ME) { - max = i; - if (point[i].stones > 1) barred++; - count += point[i].stones; - } - i--; - } - return ((max < topstone(YU) + 1) && (barred > 1 && count < 7)); - } - else return ( mytotal() < yrtotal() + 24 ); - -} /* end: backgame */ - - - -cubeval() { -int ineed, yuneed, yrtop, mytop; - - if (endgame()) { - - /* calculate the number of dice that are required to end */ - /* the game, with appropriate fudge factors for position */ - - yrtop = topstone(YU); - mytop = topstone(ME); - - ineed = 15 - point[MYHOME].stones; - yuneed = 15 - point[YRHOME].stones; - - if (yrtop < 4 && yuneed < 3) return (FALSE); /* obvious */ - - /* topstones still running? use a different method */ - if (mytop > 6 || yrtop > 6) { - ineed = 2 * (mytotal() / 8) + 1; /* number of dice */ - yuneed = 2 * (yrtotal() / 8) + 1; - } - - /* count the stones on point 6 twice, they're losers */ - yuneed += point[6].stones; - ineed += point[6].stones; - - /* you doubled, so you have the roll */ - yuneed -= 2; - - /* odd number left? */ - if (ineed % 2) ineed++; - if (yuneed % 2) yuneed++; - - /* is the one point empty? */ - if (ineed > 4 && mytop > 3 && point[24].stones == 0) ineed++; - if (yuneed > 4 && yrtop > 3 && point[ 1].stones == 0) yuneed++; - - if (mytop < yrtop && ineed < yuneed) return (TRUE); - if (yrtop < 5 && yuneed < ineed) return (FALSE); - return ( yuneed >= ineed ); - } - else return ( backgame() ); - -} /* end: cubeval */ - - - -testcube() { - - if (cubeval()) { - debug("I accept the cube."); - notyrcube(); - doubles.cube *= 2; - mycube(doubles.cube); - } - else winner(YU,0); - -} /* end: testcube */ - - - -udouble() { - - if (doubles.whosecube == ME) { - if (tone) beep(); - debug("It's MY cube, dummy!"); - } - else testcube(); - -} /* end: udouble */ - - -#include "mylib2.c" - - \ No newline at end of file diff --git a/Original/backgmmn.com b/Original/backgmmn.com deleted file mode 100644 index fffa1720ead894aac9ef5b4d126ed55e33ae60f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30976 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 M{6Bvt{=dop2f`6scK`qY diff --git a/Original/backgmmn.sub b/Original/backgmmn.sub deleted file mode 100644 index acb857c..0000000 --- a/Original/backgmmn.sub +++ /dev/null @@ -1,14 +0,0 @@ -era *.bak -era *.mac -era backgmmn.rel -era gameplan.rel -era backgmmn.com -b:c -m backgmmn -b:m80 =backgmmn -era backgmmn.mac -b:c -m gameplan -b:m80 =gameplan -era gameplan.mac -b:l80 backgmmn,gameplan,stdlib/s,clibrary/s,backgmmn/n/e -backgmmn - \ No newline at end of file diff --git a/Original/gameplan.c b/Original/gameplan.c deleted file mode 100644 index 5d5b93a..0000000 --- a/Original/gameplan.c +++ /dev/null @@ -1,866 +0,0 @@ - -/* Gammon IV, by David C. Oshel, Ames, Iowa */ - -/*--------------------------------------------------------------------*/ -/* GAMEPLAN.C -- separately compiled module, contains the tactics and */ -/* strategy for making the computer's move in Gammon IV */ -/* BACKGMMN.REL calls MyMove(), MyMove() calls topstone */ -/* and movestone and a few others. Uses the globals in */ -/* GAMEPLAN.HDR quite heavily. Bgversion declared here */ -/*--------------------------------------------------------------------*/ - -#include "gameplan.hdr" /* contains external, global declarations */ - -/*-------------------------------------------------------------------------*/ -/* */ -/* Bgversion is an external reference in the main module. Use this string */ -/* to take credit for a decent gameplaying algorithm if you find one! */ -/* */ -char *bgversion = ".20 -April 1, 1986- by David C. Oshel"; - /*....v....1....v....2....v....3....v...*/ - /* just 38 characters for version info! */ -/* */ -/*-------------------------------------------------------------------------*/ - - -/*=============================================*/ -/* M Y M O V E */ -/*=============================================*/ - - -naked() { /* am I leaving too many blots? */ -static int i, clink; - i = 24; clink = 0; - while (i) { - if (point[i].stones == 1 && point[i].owner == ME) clink++; - i--; - } - return (clink > 2); -} /* end: naked */ - - -yourfolly() { /* look for lotsa blots in your inner table */ -static int i, clink; - i = 18; clink = 0; - while (i < 25) { - if (point[i].owner == YU && point[i].stones == 1) - clink++; - i++; - } - return (clink >= 3); -} /* end: yourfolly */ - - -goodboard() { /* look for four made points near my inner table */ -static int i, clank, clink; - i = 9; clank = 0; - while (i > 3) { - if (point[i].owner == ME && point[i].stones > 1) clank++; - i--; - } - if (clank > 4) return (TRUE); /* bar is nearly blocked */ - - i = 6; clank = clink = 0; - while (i) { - if (point[i].owner != ME) - ; - else if (point[i].stones == 1) clink++; else clank++; - i--; - } - return (clank > 3 && clink < 2); -} /* end: goodboard */ - - -bearoff() { - return (topstone(ME) < 7); -} /* end: bearoff */ - - -scanahead( from ) int from; { -static int count; - - count = 0; - while (--from > 0) { - ++count; - if ( point[ from ].owner == YU ) return (count); - } - return (7); - -} /* end: scanahead */ - - -endgame() { /* Is no strategy required from here on in? */ - return ( (25 - topstone(YU)) > topstone(ME) ); -} /* end: endgame */ - - -/*------------------------------------------------------------*/ -/* MATCHUP */ -/* */ -/* 2-stone functions that force the choice of the next move. */ -/* These are the HEART and SOUL of this backgammon algorithm! */ -/*------------------------------------------------------------*/ - -setpend( from, to ) int from, to; { - pending.fr = from; - pending.to = to; - pending.flag = TRUE; -} /* end: setpend */ - - -clrpend() { - pending.flag = FALSE; -} /* end: clrpend */ - - -natural(f1,t1,f2,t2) int f1,t1,f2,t2; { - clrpend(); - if (point[t2].stones == 1 && t1 == f2) setpend(f2,t2); - return (pending.flag); -} /* end: natural */ - - -matchup( test4 ) int (* test4)(); { -static int i, j, ti, tj; - - if ( pending.flag ) return (FALSE); /* this is probably redundant */ - - for (i = 1; i < 26; i++) { - ti = list[0][i]; - if ( ti == ERROR ) goto zoo; - for (j = 1; j < 26; j++) { - tj = list[1][j]; - if ( tj == ERROR ) goto voo; - if ( (* test4)( i, ti, j, tj ) ) { - lurch( i, ti, 0); - return (TRUE); - } - voo: ; - } - zoo: ; - } - return (FALSE); - -} /* end: matchup */ - - -matchhi( test4 ) int (* test4)(); { -static int i, j, ti, tj; - - if ( pending.flag ) return (FALSE); /* this is probably redundant */ - - for (i = 1; i < 26; i++) { - ti = list[1][i]; - if ( ti == ERROR ) goto zoo; - for (j = 1; j < 26; j++) { - tj = list[0][j]; - if ( tj == ERROR ) goto voo; - if ( (* test4)( i, ti, j, tj ) ) { - lurch( i, ti, 1); - return (TRUE); - } - voo: ; - } - zoo: ; - } - return (FALSE); - -} /* end: matchhi */ - - - -/*--------------------------------------------------------*/ -/* CLOCKWISE and COUNTERCLOCK */ -/* */ -/* the rest of these are single-stone decisions based on */ -/* rules of thumb, board-scanning functions */ -/*--------------------------------------------------------*/ - -plainstupid( from ) int from; { /* don't break a safe point */ - return (from < 13 && (point[from].stones == 2 && scanahead(from) < 7)); -} /* end: plainstupid */ - - -unwise( innertablept ) int innertablept; { - /* if it's a hit, just for god's sake don't put him on the bar!! */ - if ( innertablept < 7 ) { - if (point[ innertablept ].owner == YU || - point[ YRBAR ].stones > 0) - return (TRUE); - } - return(FALSE); -} /* end: unwise */ - - - -covermine( from, to ) int from, to; { - if ( from < 8 ) return(FALSE); - return ( (point[ to ].stones == 1) && (point[ to ].owner == ME) ); -} /* end: covermine */ - - -idareyou( from, to ) int from, to; { - if (unwise( to )) return (FALSE); - if ( (point[ from ].stones != 2) - && (point[ to ].stones < 2) - && (scanahead( to ) > 6) ) return ( TRUE ); - else return (FALSE); -} /* end: idareyou */ - - -hitandrun( from, to ) int from, to; { - return ( point[ to ].owner == YU ); -} /* end: hitandrun */ - - -dbuild( from, to ) int from, to; { -static int diceleft; - diceleft = (myturns? 2 + movesleft: movesleft); - if (diceleft > 1) { - /* can't possibly be only one stone on from point */ - /* or kamikaze would have covered it on last move */ - return ( point[to].stones == 0 ); - } - return (FALSE); -} /* end: dbuild */ - - -kamikaze( from, to ) int from, to; { -/* cover my distant blot, or razzle-dazzle 'em with the long doubles hit */ -static int j, k, diceleft; - - k = from; - j = from - to; - diceleft = myturns * movesleft; /* NB: 2*2 == 2+2, "fourtunately" */ - while ( diceleft-- ) { /* predicting where doubles land is easy! */ - k -= j; - if (k < 1) return (FALSE); /* out of bounds */ - if ( point[ k ].stones == 0 ) continue; /* simplify */ - if ( point[ k ].stones == 1 ) /* found my blot or yours? */ - return (TRUE); - else if ( point[k].owner == YU ) /* found your blockade? */ - return (FALSE); - else continue; /* found my safe point, so ignore it */ - } - return (FALSE); - -} /* end: kamikaze */ - - -hittite( from, to ) int from, to; { - return (hitandrun(from,to) && to > 9); -} /* end: hittite */ - - -safehit( from, to ) int from, to; { - return (hittite(from,to) && idareyou(from,to)); -} /* end: safehit */ - - -foolsdemise( from, to ) int from, to; { - /* annihilate orphaned blots in enemy's inner, my outer table */ - return (to > 17 && point[to].owner == YU); -} /* end: foolsdemise */ - - -landonme( from, to ) int from, to; { - if ( plainstupid(from) ) return (FALSE); - if ( loneranger(from,to) ) { - if (from < 19 && to > 6) return(TRUE); - } - else return ( point[ to ].owner == ME && point[to].stones < 4); -} /* end: landonme */ - - - -/* these evaluations have meaning only in the endgame */ - - -nobackgammon( from, to ) int from, to; { /* endgame */ - return (from > 19); -} /* end: nobackgammon */ - - -crosstable( from, to ) int from, to; { - /* always move a table ahead if possible, in the endgame */ - if (from < 7) return (FALSE); - if (from > 18 && to <= 18) return (TRUE); - if (from > 12 && to <= 12) return (TRUE); - if (from > 6 && to <= 6) return (TRUE); - return (FALSE); -} /* end: crosstable */ - - -fiftytworule( from, to ) int from, to; { /* endgame */ -static int p; - if (from < 7) return (FALSE); /* not in inner table! */ - p = from % 6; - if (p == 0) return (TRUE); /* improve the six */ - if (p != 5) return ( (to % 6) < 3 ); /* best improve under five */ -} /* end: fiftytworule */ - - - - -/* these evaluations are universally applicable, last resort moves */ - - -gohome( from, to ) int from, to; { /* always go home if you can */ - return (to == MYHOME); -} /* end: gohome */ - - -scatter( from, to ) int from, to; { /* scatter, esp. in the endgame */ - if (plainstupid(from) || unwise(to)) return (FALSE); - return ( point[ from ].stones > 1 && point[ to ].stones == 0 ); -} /* end: scatter */ - - -runnerup( from, to ) int from, to; { - if (from < 10 || from > 18) return (FALSE); - return (TRUE); -} /* end: runnerup */ - - -loneranger( from, to ) int from, to; { - return( point[ from ].stones == 1 ); -} /* end: loneranger */ - - -run( dummy1, dummy2 ) int dummy1, dummy2; { /* MUST move something! */ - return (TRUE); -} /* end: run */ - - - - - -/* clockwise and counterclock make a 1-stone choice on rules of thumb */ - - -counterclock( test ) int (* test)(); { -static int i,j; - - for (i = 0; i < 2; i++) { - for (j = 1; j < 25; j++) { - if ( list[i][j] == ERROR ) continue; - if ( (* test)( j, list[i][j] ) ) { - lurch( j, list[i][j], i); - return ( TRUE ); - } } } - return (FALSE); - -} /* end: counterclock */ - - -clockwise( test ) int (* test)(); { -static int i,j; - - for (i = 0; i < 2; i++) { - for (j = 25; j > 0; j--) { - if ( list[i][j] == ERROR ) continue; - if ( (* test)( j, list[i][j] ) ) { - lurch( j, list[i][j], i); - return ( TRUE ); - } } } - return (FALSE); - -} /* end: clockwise */ - - - - - -/*-------------------------------------------*/ -/* Make Prime */ -/*-------------------------------------------*/ - -static int prmchk; - - -buildprime( f1,t1,f2,t2 ) int f1,t1,f2,t2; { - clrpend(); - /* check for the doubles bug */ - if ((dice[0] == dice[1]) && (point[f1].stones < 2)) return(FALSE); - - /* look for the combination */ - if ( t1 == prmchk && t2 == prmchk) setpend(f2,t2); - - /* stick like glue to a made point, but doubles may move forward */ - if (dice[0] != dice[1]) { - if ((f2 < 8) && (point[f2].stones == 2)) clrpend(); - if ((f1 < 8) && (point[f1].stones == 2)) clrpend(); - } - - return(pending.flag); - -} /* end: buildprime */ - - -makeprime() { -static int i, tab[] = { ERROR,1,2,3,20,22,24,9,4,6,8,5,7 }; - i = 12; - while (i) { - prmchk = tab[i]; - i--; - if ( point[ prmchk ].stones > 1 ) continue; - else if ( matchup( buildprime ) ) return(TRUE); - } - return(FALSE); -} /* end: makeprime */ - - -coverprime( from, to ) int from, to; { - return (((to == prmchk) && - (point[prmchk].owner == ME)) && - (point[from].stones != 2)); -} /* coverprime */ - - -cleanup() { -static int i, tab[] = { ERROR,1,2,3,20,22,24,9,4,6,8,5,7 }; - i = 12; - while (i) { - prmchk = tab[i]; - i--; - if ( point[ prmchk ].stones != 1 ) continue; - else if ( counterclock( coverprime ) ) return(TRUE); - } - return(FALSE); -} /* end: cleanup */ - - -/*-------------------------------------*/ -/* Walking Prime */ -/*-------------------------------------*/ - -swivelhips( from, to ) int from, to; { - return ( from > prmchk ); -} /* end: swivelhips */ - - -slink( from, to ) int from, to; { - return( (from > prmchk) && (point[to].stones == 1) ); -} /* end: slink */ - - -weasel() { - if ( clockwise( slink ) ) - return(TRUE); - if ( counterclock( swivelhips ) ) - return(TRUE); - if ( clockwise( run ) ) - return(TRUE); -} /* end: weasel */ - -ihaveprime( from ) int from; { -static int i, to, ez; - ez = 0; - for (i = 0; i < 6; i++) { - to = from - i; - if ((point[to].owner == ME) && (point[to].stones > 1)) ez++; - } - return (ez > 4); -} /* end: ihaveprime */ - - -walkingprime() { -/* looks for the walking prime anywhere in the front tables */ -/* then tries to bring up a runner from behind the prime, */ -/* ensuring that a back stone WILL move before a front one */ -static int i; - i = 12; - while (i > 5) { - if ( ihaveprime(i) ) { - prmchk = i; - if ( weasel() ) return (TRUE); - } - i--; - } - return(FALSE); -} /* end: walkingprime */ - - -/*---------- Book Moves ----------*/ -/* only valid if my move is first */ -/*--------------------------------*/ - -zip(a,b,c,d) int a,b,c,d; { - lurch(a,b,0); - lurch(c,d,0); - movesleft = 0; return( TRUE ); -} /* end: zip */ - - -zoom( a,b,c,d,e,f,g,h ) int a,b,c,d,e,f,g,h; { - myturns = 0; zip(a,b,c,d); zip(e,f,g,h); return( TRUE ); -} /* end: zoom */ - - -book() { -int a,b; - if (!firstmove) return (FALSE); - firstmove = FALSE; - a = min(dice[0],dice[1]); - b = max(dice[0],dice[1]); - switch (level) { - case 0: { return ( book0(a,b) ); break; } - case 1: { return ( book1(a,b) ); break; } - case 2: { return ( book2(a,b) ); break; } - } -} -book0( a,b ) int a, b; { - switch (a) { - case 1: { switch (b) { - case 1: return ( zoom(8,7,8,7,6,5,6,5) ); - case 2: return ( zip(24,23,13,11) ); - case 3: return ( zip(8,5,6,5) ); - case 4: return ( zip(24,23,13,9) ); - case 5: return ( zip(24,23,13,8) ); - case 6: return ( zip(13,7,8,7) ); - } - break; } - case 2: { switch (b) { - case 2: return ( zoom(6,4,6,4,13,11,13,11) ); - case 3: return ( zip(13,11,13,10) ); - case 4: return ( zip(8,4,6,4) ); - case 5: return ( zip(13,8,13,11) ); - case 6: return ( zip(24,18,13,11) ); - } - break; } - case 3: { switch (b) { - case 3: return ( zoom(13,10,13,10,10,7,10,7) ); - case 4: return ( zip(13,10,13,9) ); - case 5: return ( zip(13,10,13,8) ); - case 6: return ( zip(24,18,13,10) ); - } - break; } - case 4: { switch (b) { - case 4: return ( zoom(13,9,13,9,24,20,24,20) ); - case 5: return ( zip(13,8,13,9) ); - case 6: return ( zip(24,18,18,14) ); - } - break; } - case 5: { switch (b) { - case 5: return ( zoom(13,8,13,8,8,3,8,3) ); - case 6: return ( zip(24,18,18,13) ); - } - break; } - case 6: { return ( zoom(13,7,13,7,24,18,24,18) ); - break; } - } - -} /* end: book0 */ -book1( a,b ) int a, b; { /* mostly follows Becker */ - switch (a) { - case 1: { switch (b) { - case 1: return ( zoom(8,7,8,7,6,5,6,5) ); - case 2: return ( zip(13,11,6,5) ); - case 3: return ( zip(8,5,6,5) ); - case 4: return ( zip(13,9,6,5) ); - case 5: return ( zip(13,8,6,5) ); - case 6: return ( zip(13,7,8,7) ); - } - break; } - case 2: { switch (b) { - case 2: return ( zoom(6,4,6,4,13,11,13,11) ); - case 3: return ( zip(13,11,13,10) ); - case 4: return ( zip(8,4,6,4) ); - case 5: return ( zip(13,8,13,11) ); - case 6: return ( zip(13,7,7,5) ); - } - break; } - case 3: { switch (b) { - case 3: return ( zoom(13,10,13,10,8,5,8,5) ); - case 4: return ( zip(13,10,13,9) ); - case 5: return ( zip(13,8,8,5) ); - case 6: return ( zip(13,7,13,10) ); - } - break; } - case 4: { switch (b) { - case 4: return ( zoom(13,9,13,9,9,5,9,5) ); - case 5: return ( zip(13,8,13,9) ); - case 6: return ( zip(13,7,13,9) ); - } - break; } - case 5: { switch (b) { - case 5: return ( zoom(13,8,13,8,8,3,8,3) ); - case 6: return ( zip(13,7,13,8) ); - } - break; } - case 6: { return ( zoom(13,7,13,7,24,18,24,18) ); - break; } - } - -} /* end: book1 */ -book2( a,b ) int a, b; { /* mostly follows Becker */ - switch (a) { - case 1: { switch (b) { - case 1: return ( zoom(8,7,8,7,6,5,6,5) ); - case 2: return ( zip(13,11,24,23) ); - case 3: return ( zip(8,5,6,5) ); - case 4: return ( zip(13,9,24,23) ); - case 5: return ( zip(13,8,24,23) ); - case 6: return ( zip(13,7,8,7) ); - } - break; } - case 2: { switch (b) { - case 2: return ( zoom(6,4,6,4,24,23,24,23) ); - case 3: return ( zip(13,11,13,10) ); - case 4: return ( zip(8,4,6,4) ); - case 5: return ( zip(13,8,13,11) ); - case 6: return ( zip(13,7,13,11) ); - } - break; } - case 3: { switch (b) { - case 3: return ( zoom(13,10,13,10,10,7,10,7) ); - case 4: return ( zip(13,10,13,9) ); - case 5: return ( zip(13,8,8,5) ); - case 6: return ( zip(13,7,13,10) ); - } - break; } - case 4: { switch (b) { - case 4: return ( zoom(13,9,13,9,9,5,9,5) ); - case 5: return ( zip(13,8,13,9) ); - case 6: return ( zip(13,7,13,9) ); - } - break; } - case 5: { switch (b) { - case 5: return ( zoom(13,8,13,8,8,3,8,3) ); - case 6: return ( zip(13,7,13,8) ); - } - break; } - case 6: { return ( zoom(13,7,13,7,24,18,24,18) ); - break; } - } - -} /* end: book2 */ - - -/*====== MyMove ======*/ - -torve() { - if ( makeprime() ) { /* this will use doubles, if it can */ - return; - } - else if ( walkingprime() ) { /* i have six prime points, so run!!! */ - return; - } - else if ( dice[0] == dice[1] ) { /* this is too easy! */ - if ( counterclock( kamikaze ) ) - return; - if ( counterclock( dbuild ) ) /* claim new turf */ - return; - if ( clockwise( run ) ) - return; - } - else if ( cleanup() ) { /* cover my single blot on prime points */ - return; - } - else if ( bearoff() ) { /* I'm ready, but you're in the back game! */ - if ( counterclock( gohome ) ) - return; - if ( clockwise( run ) ) - return; - } - else { - if ( clockwise( hitandrun ) ) - return; - if ( matchup( natural ) ) - return; - if ( clockwise( landonme ) ) - return; - if ( counterclock( runnerup ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } - -} /* end: torve */ - - - -villiers() { - if ( makeprime() ) { /* this will use doubles, if it can */ - return; - } - else if ( walkingprime() ) { /* i have six prime points, so run!!! */ - return; - } - else if ( dice[0] == dice[1] ) { /* this is too easy! */ - if ( counterclock( kamikaze ) ) - return; - if ( counterclock( dbuild ) ) /* claim new turf */ - return; - if ( clockwise( run ) ) - return; - } - else if ( cleanup() ) { /* cover my single blot on prime points */ - return; - } - else if ( bearoff() ) { /* I'm ready, but you're in the back game! */ - if ( counterclock( gohome ) ) - return; - if ( clockwise( run ) ) - return; - } - else { - if ( clockwise( foolsdemise ) ) - return; - if ( clockwise( idareyou ) ) - return; - if ( counterclock( covermine ) ) - return; - if ( matchup( natural ) ) - return; - if ( clockwise( landonme ) ) - return; - if ( clockwise( runnerup ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } - -} /* end: villiers */ - - - -louisa() { - if ( makeprime() ) { /* this will use doubles, if it can */ - return; - } - else if ( walkingprime() ) { /* i have six prime points, so run!!! */ - return; - } - else if ( dice[0] == dice[1] ) { /* this is too easy! */ - if ( counterclock( kamikaze ) ) - return; - if ( counterclock( dbuild ) ) /* claim new turf */ - return; - if ( clockwise( run ) ) - return; - } - else if ( cleanup() ) { /* cover my single blot on prime points */ - return; - } - else if ( bearoff() ) { /* I'm ready, but you're in the back game! */ - if ( counterclock( gohome ) ) - return; - if ( clockwise( run ) ) - return; - } - else if ( (!naked() && goodboard()) || yourfolly() ) { - if ( clockwise( hitandrun ) ) - return; - if ( matchup( natural ) ) - return; - if ( clockwise( landonme ) ) - return; - if ( counterclock( runnerup ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } - else { - if ( clockwise( foolsdemise ) ) - return; - if ( clockwise( idareyou ) ) - return; - if ( counterclock( covermine ) ) - return; - if ( matchup( natural ) ) - return; - if ( clockwise( landonme ) ) - return; - if ( clockwise( runnerup ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } -} /* end: louisa */ - - -mymove() { -int i, d; - - if ( nomove() ) { - if (lookforit && (dice[0] != dice[1])) { - lookforit = FALSE; - puts("\008... "); - switch (level) { - case 0: { puts("Blocked!"); break; } - case 1: { puts("Well, no!"); break; } - case 2: { puts("Thurb!"); break; } - } - sleep(10); - restoreboard(); - update(); - - /* put the high die in list zero */ - d = dice[0]; dice[0] = dice[1]; dice[1] = d; - - cantuse = ERROR; movesleft = 2; myturns = 1; - switch (level) { - case 0: { setchat("I move"); break; } - case 1: { setchat("Let's try"); break; } - case 2: { setchat("Move is"); break; } - } - debug(chatter); - prmchk = 12; - weasel(); - /* the rules say, use both dice if you can, or */ - /* the highest if one or the other but not both */ - } - else { - lookforit = TRUE; - strcat(chatter," and now I'm blocked "); - myturns = movesleft = 0; - } } - else if ( book() ) { - return; - } - else if ( pending.flag ) { - lurch( pending.fr, pending.to, 1 ); - clrpend(); - } - else if ( endgame() ) { /* very solid tactics here!! */ - if ( clockwise( gohome ) ) - return; - if ( clockwise( nobackgammon ) ) /* no excuse! */ - return; - if ( clockwise( crosstable ) ) - return; - if ( clockwise( fiftytworule ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } - else if ( point[ MYBAR ].stones > 0 ) { /* I'm on the bar! */ - if ( clockwise( hitandrun ) ) /* wreak havoc, please */ - return; - if ( clockwise( run ) ) /* note: uses low die first */ - return; - } - else switch (level) { - case 0: { villiers(); break; } - case 1: { louisa(); break; } - case 2: { torve(); break; } - } - - -} /* end: mymove */ - -/*------------------------------*/ -/* end of the GAMEPLAN.C module */ -/*------------------------------*/ - \ No newline at end of file diff --git a/Original/gameplan.hdr b/Original/gameplan.hdr deleted file mode 100644 index 49f8c27..0000000 --- a/Original/gameplan.hdr +++ /dev/null @@ -1,42 +0,0 @@ -/* GAMEPLAN.HDR */ - -/*================================================================*/ -/* change nothing in this file */ -/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ - -#define TRUE 1 -#define FALSE 0 -#define ME 1 -#define YU 2 -#define YRBAR 0 -#define MYBAR 25 -#define YRHOME 26 -#define MYHOME 27 -#define ERROR 999 -#define MYLEVEL 2 - -extern int list[2][28]; /* two dice, two lists */ - -extern struct board { - int stones, /* number of stones on that point */ - owner, /* and whose they are */ - x,y, /* x and y coordinates of point base */ - lastx,lasty, /* last location drawn on this point */ - cx,cy; /* coordinates for column numbers */ - } - point[28], bdsave[28]; /* 24 points, plus 2 bars, 2 homes */ - -extern struct { int cube, whosecube; } doubles; - -extern struct { int fr,to,flag; } pending; - -extern int level, dice[2], myscore, yrscore, player, movesleft, cantuse, - myturns, swapped, tswap, deciding, expert, tone, show, moremsgline, - firstmove, helpdisabled, yrdice, lookforit, startcubevalue; - -extern char *chatter[80]; - -/*----------------------------------------------*/ -/* end of header -- change NOTHING in this file */ -/*----------------------------------------------*/ - \ No newline at end of file diff --git a/Original/mylib2.c b/Original/mylib2.c deleted file mode 100644 index 4082da3..0000000 --- a/Original/mylib2.c +++ /dev/null @@ -1,541 +0,0 @@ -/* -MYLIB2.C - -These routines are CONDITIONALLY compiled; i.e., only as needed. - ----------------------------------------------------------------------- -Incorporates special mods used by my Backgammon game, BACKGMMN.C etc. ----------------------------------------------------------------------- - -A set of common I/O functions that seem to turn up a lot in my programs, -including terminal functions for Kaypro 10, 4'84, 2X etc. - -Uses Software Toolworks' C/80 3.1 compiler. Place #include "mylib2.c" at the -end of your source file for correct CONDITIONAL COMPILATION. - -David C. Oshel -1219 Harding Ave. -Ames, Iowa 50010 - -Last modified: March 25, 1986 - ------------------------------------------------------------------------------ -** WARNING ** These routines use direct console IO, bdos function 6! - - YOU MUST CALL INIT_LIB() BEFORE USING THESE ROUTINES! - - ======= UTILITIES ======= - - * init_lib() - CALL THIS FIRST, OR THE RESULT WILL BE VERY STRANGE! - * - * puts(p) - unformatted print, e.g., puts("Hello, sailor!\n"); - * gets(p,max) - printable input only, no prompt character - * - * ask(p) - demand Yes or No response to question p - * random() - effective random 16-bit integer IFF gets() is used - * sleep(n) - sleep n/10ths of a second, roughly (from C80.LIB) - * rollup() - roll up 23 lines of screen - * ONscript() - printer echo ON for output via puts, chrout - * OFFscript() - printer echo OFF for output via puts, chrout - * ONinterrupt() - Ctl-C, Ctl-B cause program exit - * OFFinterrupt() - Ctl-C, Ctl-B cause comedy - * hide_input(p,max) - like gets, but used when entering passwords - * chrout(c) - if scripting, echo output also to LST: - * putscreen(p) - like puts, but always and only to screen - - - ======= KAYPRO 10 TERMINAL/VIDEO FUNCTIONS ======= - - * gotoxy(x,y) - 0,0 is top left, horz <= 79 precedes vert <= 24, - * where 0,24 is on the 25th, status, line. - * beep() - terminal bell - * home() - home cursor, do not clear screen - * clr_screen() - home and clear - * - * shadow_box(h,v,x1,y1,x2,y2) - like box, but with shadow, calls box - * box(tlx,tly,brx,bry) - draw a line box, coords: topleft XY, bottomright XY - * note that box calls ldraw(x1,y1,x2,y2), below - * - * clr_lend() - clear from cursor to end of line - * clr_send() - clear from cursor to end of screen - * rev_vid(), - * nor_vid() - reverse field - * dim_vid(), - * bri_vid() - low/high intensity - * on_blink(), - * off_blink() - blinking chars - * ul_start(), - * ul_stop() - start/stop underline - * save_cursor(), - * retn_cursor() - remember/restore current cursor location - * ins_line(), - * del_line() - insert/delete screen text line - * on_cursor(), - * off_cursor() - hide/show cursor - * vm_on(), - * vm_off() - "Video Mode" commands - * pixel(x,y) - draw pixel at x,y (video coords, x <= 159, y <= 99) - * no_pixel(x,y) - erase pixel at x,y - * ldraw(x1,y1,x2,y2) - draw/ erase graphics line, see discussion for box - * lwipe(x1,y1,x2,y2) - range for video coordinates as for pixel -*/ - - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - - -/* hide this here so's not to worry about it elsewhere */ -/* "printf.c" collides with one of these, can't remember which */ -/* puts() takes longer to write, but executes faster */ -extern char Cmode, IOpread[4], IOpwrit[4], IOpeof[4]; - -/* make these known only to what follows */ -static int MYbstout, MYscrtp, MYretnirp; /* odd names mark semi-private */ -static unsigned RNDloc; /* effective random location, bumped by gets() */ - /* and scrambled when the LCG random() is called */ - /* makes a decent algorithm for interactive games */ - - -#ifneed init_lib -init_lib() { - - MYretnirp = fopen("LST:","w"); - OFFscript(); - ONinterrupt(); - Cmode = 0; - IOpread[0] = 6; IOpwrit[0] = 6; - -} /* end: init_lib */ -#endif - - - - -#ifneed random -random() { /* depends on effective random location spun by gets() */ - - RNDloc = 2053 * RNDloc + 13849; - return (RNDloc); -} -#endif - - - -#ifneed ONscript -ONscript() { - - MYscrtp = TRUE; - -} -#endif -#ifneed OFFscript -OFFscript() { - - MYscrtp = FALSE; - -} -#endif - - -#ifneed ONinterrupt -ONinterrupt() { - - MYbstout = TRUE; - -} -#endif -#ifneed OFFinterrupt -OFFinterrupt() { - - MYbstout = FALSE; - -} -#endif - - -#ifneed ask -ask(p) char *p; { - -char ch, resp[2]; - -loo: puts(p); - gets(resp,1); - ch = toupper( *resp ); - if ( !( ch == 'Y' || ch == 'N' )) { - puts("Please answer the question, Yes or No.\n"); - goto loo; - } - return (ch == 'Y'); - -} /* end: ask */ -#endif - - -#ifneed rollup -rollup() { - -int i; - - for (i=0; i<23; i++) puts("\n"); - -} /* end: rollup */ -#endif - - -#ifneed sleep -sleep( n ) int n; { /* sleep for n/10 seconds, 0 <= n < 256 */ - - n; /* get n into HL */ -#asm - MOV B,L ;delay B/10ths of a second -__DL0: MVI A,100 ;100 milliseconds, 1/10 second -__DL1: MVI C,249 ;1 millisecond per unit of A at 4 MHz -__DL2: DCR C ;Leventhal, Z80 Assembly Language Programming - JNZ __DL2 - DCR A - JNZ __DL1 - DCR B - JNZ __DL0 ;on exit, HL has FALSE if n was 0, else TRUE -#endasm -} /* end: sleep */ -#endif - - -/*========================================*/ -/* GETS(p, maxinput) */ -/* Local getline function with special *---* WARNING: */ -/* input handling, 1 <= len <= maxinput *---* Execute INIT_LIB() first !! */ -/* Updates effective random, RNDloc, */ -/* Forces input from CONSOLE only! */ -/*========================================*/ - -#ifneed gets -gets(p,maxinput) char *p; int maxinput; { - -/* This function depends on BDOS Function #6. Init_lib() sets Cmode=0 and - IOpread[0]=6 and IOpwrit[0]=6 (courtesy of and peculiar to C/80 3.1) - YOU must ensure that the target string is long enough to collect the - entire maximum input allowed and specified, INCLUDING FINAL NULL! */ - -static int len; -static char ch; - - len = -1; - if (maxinput < 1 || maxinput > 127) maxinput = 79; - - /*--------------------------------*/ - /* SPECIAL ROUTINE FOR BACKGAMMON */ - /*--------------------------------*/ - -loo: while ( !(ch = getc(0)) ) acg(); /* keep the game lively */ - - if (len < 0) len = 0; /* don't destroy prompt by backing up */ - if (ch == '\n') { /* end of line? don't store newline */ - *p = '\0'; /* mark it with a B for baby and me */ - /* chrout('\n'); */ /* but DON'T echo newline */ - return ( len ); /* <--- HERE IS THE FUNCTION EXIT! */ - } - else if (ch == '\b' || ch == 0x7F) { /* backspace? rubout? */ - if (len--) { /* where's the prompt? */ - puts("\008 \008"); /* we're ok, echo erase */ - p--; /* delete from string */ - } - } - - /*--------------------------------*/ - /* SPECIAL ROUTINE FOR BACKGAMMON */ - /*--------------------------------*/ - - else if (ch == '\003') { /* user bailout key is Ctrl-C, not ESC */ - if (MYbstout) exit(); - else { - haltgame(); /* sets whofirst flag and does jumpjack() */ - } - } - - else if (ch == '\025' || ch == '\030') { /* Ctl-U, Ctl-X */ - while (len--) { - p--; - puts("\008 \008"); - } - } - else if (len == maxinput) { /* test specials before testing len */ - chrout('\007'); - } - else if (ch > 31 && ch < 127) { /* printable char? */ - chrout(ch); /* yes, echo it */ - *p++ = ch; /* collect it */ - len++; /* keep track of it */ - } - else { /* control chars? */ - chrout('\007'); - } - goto loo; - -} /* end: gets */ -#endif - - - - -#ifneed hide_input -hide_input(s,len) char *s; int len; { - -/* receive at most len chars in s buffer, - terminate string with zero, - but echo each char with 1, 2, or 3 meaningless dots */ - -char ch; int num; - - if ((len < 1) || (len > 127)) len = 127; - num = 0; - for (;;) { /* forever */ - while ((ch = getc(0)) == 0) /* bdos 6 does not wait, so we do */ - ; - if ((ch == '\r') || (ch == '\n') || (num++ > len)) { - /* not sure what the CR key actually is to bdos 6 & C/80 */ - *s++ = '\0'; - return; /* this way out */ - } - if ((num % 2) == 0) putc('.',0); /* deception, illusion */ - if ((num % 5) == 0) putc('.',0); - putc('.',0); - *s++ = ch; - } - -} /* end: hide_input */ -#endif - - - - -/*------------------------ kpro stuff -------------------------*/ - -#ifneed shadow_box -/* like box, but with horizontal & vertical displacement for shadow */ -shadow_box(h,v,x1,y1,x2,y2) int h,v,x1,y1,x2,y2; -{ - box(x1+h,y1+v,x2+h,y2+v); /* draw the shadow */ - box(x1,y1,x2,y2); /* draw the box */ - ldraw(x1+h,y1+v,x1,y1); /* draw the corners */ - ldraw(x2+h,y2+v,x2,y2); - ldraw(x2+h,y1+v,x2,y1); - ldraw(x1+h,y2+v,x1,y2); -} -#endif - - -#ifneed box -/* parameters are topleft X,Y and bottomright X,Y - X ranges from 0 to 159, Y ranges from 0 to 99, top left is 0,0 - */ -box(x1,y1,x2,y2) int x1,y1,x2,y2; { - ldraw(x1,y1,x1,y2); - ldraw(x1,y2,x2,y2); /* appears to draw the box anticlockwise */ - ldraw(x2,y1,x2,y2); - ldraw(x1,y1,x2,y1); -} -#endif - - - -#ifneed gotoxy -gotoxy (xpos,ypos) int xpos,ypos; { /* 0,0 is top left corner */ - putscreen("\033="); - putc(ypos+' ',0); - putc(xpos+' ',0); - } -#endif - - -#ifneed beep -beep() { putc(7,0); } /* send bell character */ -#endif - -#ifneed home -home() { putc(30,0); } /* home cursor to top left */ -#endif - -#ifneed clr_screen -clr_screen() { putc(26,0); } /* home and erase screen */ -#endif - - -#ifneed clr_lend -clr_lend() { putc(24,0); } /* clear to end of line */ -#endif - -#ifneed clr_send -clr_send() { putc(23,0); } /* clear to end of screen */ -#endif - - - -#ifneed rev_vid -rev_vid() { putscreen ("\033B0"); } /* reverse background */ -#endif - -#ifneed nor_vid -nor_vid() { putscreen ("\033C0"); } -#endif - - - -#ifneed dim_vid -dim_vid() { putscreen ("\033B1"); } /* low intensity */ -#endif - -#ifneed bri_vid -bri_vid() { putscreen ("\033C1"); } -#endif - - - -#ifneed on_blink -on_blink() { putscreen ("\033B2"); } /* blinking characters */ -#endif - -#ifneed off_blink -off_blink() { putscreen ("\033C2"); } -#endif - - - -#ifneed ul_start -ul_start() { putscreen ("\033B3"); } /* underline */ -#endif - -#ifneed ul_stop -ul_stop() { putscreen ("\033C3"); } -#endif - - -#ifneed save_cursor -save_cursor() { putscreen ("\033B6"); } /* remember cursor position */ -#endif -#ifneed retn_cursor -retn_cursor() { putscreen ("\033C6"); } /* return to remembered pos */ -#endif - - -#ifneed on_status -on_status() { putscreen ("\033B7"); } /* status line preservation on */ -#endif -#ifneed off_status -off_status() { putscreen ("\033C7"); } -#endif - - -#ifneed ins_line -ins_line() { /* insert text line */ - putscreen("\033R"); - } -#endif -#ifneed del_line -del_line() { /* delete text line */ - putscreen("\033E"); - } -#endif - - -#ifneed on_cursor -on_cursor() { putscreen ("\033B4"); } /* (in)visible cursor */ -#endif -#ifneed off_cursor -off_cursor() { putscreen ("\033C4"); } -#endif - - - -/* Video Mode ON/OFF: video WORD, 8 bit video if 15 and 7 are both high */ -/* VM-ON 10000001 11111111 VM-OFF */ -/* ^video ^x^video */ -/* otherwise, video BYTE, high bit 7 interprets bits 0-6 as screen dots */ -/* 11111111 */ -/* ^video */ -/* e.g., */ -/* Non-VideoMode VideoMode */ -/* xx 1 11:0 where % is 1 01:0 1 11:0 xx */ -/* xx 3 11 2 the video 3 00 2 3 11 2 xx */ -/* xx 5 11 4 flag bit, 5 00 4 5 11 4 xx */ -/* x 7:%1 6 x is pixel 7:%0 6 7:%1 6 xx */ -/* ^ ^ ^ */ -/* to set the pixels, first do a gotoxy to character screen position */ -/* this mode is faster than Pixel ON/OFF if values are drawn from table */ -#ifneed vm_on -vm_on() { putscreen ("\033B5"); } /* video mode on */ -#endif -#ifneed vm_off -vm_off() { putscreen ("\033C5"); } -#endif - - -#ifneed pixel -pixel(x,y) int x,y; { /* x <= 159, y <= 99 */ - putscreen("\033*"); - putc(y+' ',0); putc(x+' ',0); -} -#endif - -#ifneed no_pixel -no_pixel(x,y) int x,y; { /* x <= 159, y <= 99 */ - putscreen("\033 "); - putc(y+' ',0); putc(x+' ',0); -} -#endif - - -#ifneed ldraw -/* use x1 <= x2, y1 <= y2, order is significant (Kaypro bug?) */ -ldraw(x1,y1,x2,y2) int x1,x2,y1,y2; { /* x <= 159, y <= 99 */ - putscreen("\033L"); - putc(y1+' ',0); putc(x1+' ',0); - putc(y2+' ',0); putc(x2+' ',0); -} -#endif - - -#ifneed lwipe -lwipe(x1,y1,x2,y2) int x1,x2,y1,y2; { /* x <= 159, y <= 99 */ - putscreen("\033D"); - putc(y1+' ',0); putc(x1+' ',0); - putc(y2+' ',0); putc(x2+' ',0); -} -#endif - - -#ifneed putscreen -putscreen(p) char *p; { - - while (*p) putc(*p++,0); - -} /* end: putscreen */ -#endif - - -#ifneed puts -puts(p) char *p; { - - while (*p) chrout(*p++); - -} /* end: puts */ -#endif - - -#ifneed chrout -chrout(c) char c; { /* SPECIAL FOR SCRIPT OPTION WITH LST: */ - - putc(c,0); - if ( MYscrtp ) putc(c,MYretnirp); - -} /* end: chrout */ -#endif - -/* end: MYLIB.C */ - - \ No newline at end of file diff --git a/Original/read.me b/Original/read.me deleted file mode 100644 index 148039f..0000000 --- a/Original/read.me +++ /dev/null @@ -1,56 +0,0 @@ - -GAMNIV20.LBR ------------- -Gammon IV, Version 2.0, April 1, 1986. Full-screen backgammon for CP/M. - -This is the April Fool's Day (1986) edition of Gammon IV, the first major -update in many months. - -BACKGMMN.COM is the compiled and ready-to-run object file. It requires -either an ADM-3A compatible terminal ("old" Kaypro) or a screen with video -characteristics exactly like the Kaypro 2X, 4'84 or 10. However, this -version has the same CRT Module as formerly, including a clearly-marked user -patch area for non-Kaypro terminals. - -Improvements for Version 2.0 include: - -a) Several bugs and poltergeists, especially in the Arrange command, have - been completely exorcised. No bugs have been found in the Play command - for months; but, as before, Gammon IV will not invariably recognize a - forced move, either in your play or in its own. Gammon IV knows and - obeys all other official rules of backgammon. - -b) There are no "hidden" commands anymore. All commands are now shown in - the command lines, including X(pert and G(raphic. The G(raphic command - turns on the Kaypro video-able display. - -c) Input error handling now documents the BAR, HOME and HELP commands, so - first-time players do not need to read anything else in order to play - the game successfully. The X(pert mode dispenses with these messages, - so X(pert actually does mean expert, now! - -d) The "break" command is Control-C again, instead of ESCAPE. It was - all too easy to hit ESC instead of 1 on the Kaypro keyboard, leading to - an inadvertently paused game. - -e) The sanction against cheating (your opponent became Torve) has been - removed. - -f) If the cube is doubled during the opening rolloff to see who goes - first, and the cube value reaches 8, additional pairs on the dice - have no further effect. The cube's opening value will not go above 8. - -The computer's three styles of play have not been changed. Judging from the -feedback I've received, Gammon IV plays acceptably well at the current -levels. All information needed to re-compile the program is included in the -BACKGMMN.C file, including the details of C/80 3.1 configuration. The -compile and link steps are governed by BACKGMMN.SUB. - -This program is in the public domain, so distribute it freely. - -Enjoy! - -David C. Oshel -1219 Harding Ave. -Ames, Iowa 50010 - \ No newline at end of file diff --git a/backgmmn.c b/backgmmn.c deleted file mode 100644 index d3a49ac..0000000 --- a/backgmmn.c +++ /dev/null @@ -1,1968 +0,0 @@ -/* backgmmn.c */ - -/*************************************************************************** - - GAMMON IV, Version 2 - VT100 version by Anna Christina Nass - - Author: David C. Oshel - 1219 Harding Avenue - Ames, Iowa 50010 - - Date: March 26, 1986 - - Gammon IV is probably the best backgammon game currently available for - CP/M. I wrote it because I was disgusted with the price and dullness - of all other programs which allegedly play backgammon on CP/M systems. - - This program has THREE DIFFERENT PLAYING STYLES, any one of which can - consistently beat a novice player, and occasionally beat a good player. - In all three levels, the computer's strategy can even seem brilliant; - there is nothing routine about it. - - This is a public domain program. Feel free to distribute or improve it. - Credit to the original author (me) will be appreciated, but is not - strictly required since the copyright owners are abnormally mild- - mannered (and extremely distant; see Acknowledgments, below.) - - Acknowledgments: - - The opening dialogue, in which you chose your computer opponent, - is freely adapted from Alexei Panshin's long out-of-print, and - now classic, "Star Well" travelogues. Scholars of computer history - will recognize many allusions to this same opus in various passages - of Mike Goetz's 550-point Adventure (especially in the Ice Caverns!). - - The Xochitl Sodality, which owns the copyright on Gammon IV, is a - philanthropic society first publicized by Panshin. Persons who wish - to obtain information on site licensing for Gammon IV should contact - the Monist Association imaginary properties secretary at the following - address: - Monist Association I.P.S. - c/o Xochitl Sodality - Semichastny House - Delbalso, Nash. Emp. - - - Special Instructions: - - This version uses VT100-compatible ANSI escape sequences which work - on a RC2014 computer with Marco Maccaferri's VT100 VGA terminal module. - - This program requires the Software Toolworks' C/80 v3.1 compiler - for CP/M 2.2. C/80 has a configuration program. C/80 must be - configured as follows, or else this program WILL NOT compile: - - Symbol table size: 512 - String constant table: 3200 - Dump constants after each routine: YES - Macro table size: 500 - Switch table size: 128 - Structure table size: 200 - Merge duplicate string constants: YES -NB: Assembler: C/80's AS - Initialize arrays to zero: < 256 BYES ONLY - Generate ROMable code in Macro-80: YES - Screen size: 24 (doesn't matter) - Generate slightly larger, faster code: NO - Sign extension on char to int conversion: YES - Device for library files: A: (your choice) - - Compilation: - -NB: Microsoft's MACRO-80 assembler and LINK-80 linker are required, - and are specified in the (-m) compiler switch! This is a moderately - complex compile, so the procedure is directed by batch SUBMIT files. - Distribute files as follows: - - On Drive A: - - BACKGMMN.C, BACKGMMN.SUB, CLIBRARY.REL, GAMEPLAN.C, - GAMEPLAN.HDR, MYLIB2.C, PRINTF.C, STDLIB.REL, SUBMIT.COM - - On Drive B: - - C.COM, L80.COM, M80.COM, WS.COM, WSMSGS.OVR, WSOVLY1.OVR - - Then, SUBMIT BACKGMMN to compile, assemble & link the game. You will - need about 180k of free space on Drive A. - - You must pay strict attention to the Special Instructions above, - regarding C/80 configuration. - - - Absent Files: - - M80.COM and L80.COM are from Microsoft, and are not part - of this distribution. C.COM, STDLIB.REL, CLIBRARY.REL and - PRINTF.C are from Software Toolworks, and are not part of - this distribution either. SUBMIT.COM is a CP/M transient - command; it came with your computer when you bought it. - - - Notes: - - Gammon IV is impossible to implement in any C which does not allow - functions to be passed as parameters to another function -- K & R must - be followed on this point! - - THIS CODE ASSUMES INTEL 8080 CPU. Inline code simulates an old, - archaic version of SetJump() and LongJump(), which are not features - of C/80 3.1. Use of inline code means you need 8080 compatibility. - - By isolating the game-playing algorithm into a separately compiled - module, I have allowed for the possibility that someone else may come - up with significant improvements in strategy, AND BE GIVEN CREDIT FOR - THEM, without having to re-design primitive parts of the program. - - The single exception to this rule is the code which decides when the - computer will offer, accept or reject the doubling cube; that is - considered primitive, even though the cube is a major factor in human - strategies when playing for blood or money. Gammon IV always plays - for the simple fun of aggravating humans, so cube tactics are neither - daring nor profound. Gammon IV does not bluff with the cube; if it - offers the cube, it is almost sure to win. - -*****************************************************************************/ - -#define TRUE 1 -#define FALSE 0 -#define ME 1 -#define YU 2 -#define YRBAR 0 -#define MYBAR 25 -#define YRHOME 26 -#define MYHOME 27 -#define ERROR 999 /* anything well out of range */ -#define MYLEVEL 2 - -/* put CRT stuff first so version differences won't affect it */ -#asm -; -; Note: Assumes assembly by M80.COM -; -; *========================= CRT Module =========================* -; * * -; * User Patch Area: ALL DB STRINGS MUST TERMINATE WITH A NULL * -; * * -; * The tokens TK1..TK4 comprise two sets each of playing tokens * -; * for the computer & human player. 24 bytes are reserved for * -; * EACH token, so that users may turn on video enhancements. * -; * * -; * Command Strings must terminate with 0, and the 0 byte CANNOT * -; * be sent to the console. 0 is INCLUDED in the reserved area. * -; * * -; * GAMMON IV no longer uses any console command function not * -; * specifically mentioned here. In particular, the clear-to- * -; * end-of-line function is now handled in a more general way. * -; *==============================================================* -; -; * REQUIRED * -; reserve 24 bytes apiece for the players' tokens (must terminate with 0) -; - DB 'USER PATCH AREA ' - DB 'ALL STRINGS MUST HAVE ZERO TERMINATOR->' - DB 'TOKEN1:' -TK1: DB 27,'[','3','1','m' ; computer's token, () - DB '(',')' - DB 27,'[','0','m' - DB 0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 'TOKEN2:' -TK2: DB 27,'[','3','4','m' ; player's token, [] - DB '[',']' - DB 27,'[','0','m' - DB 0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 'TOKEN3:' -TK3: DB 27,'[','3','1','m' ; computer's alternate token - DB 174,175 - DB 27,'[','0','m' - DB 0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 'TOKEN4:' -TK4: DB 27,'[','3','4','m' ; player's alternate token - DB 222,221 - DB 27,'[','0','m' - DB 0,0,0,0,0,0,0,0,0,0,0,0,0 -; -;---------------------------------------------------------------------------- -; -; * Optional * - DB 'CURSON:' -CURSON: DB 0,0,0,0,0,0,0,0 ; cursor ON (show cursor) - DB 'CURSOF:' -CURSOF: DB 0,0,0,0,0,0,0,0 ; cursor OFF (hide cursor) -;---------------------------------------------------------------------------- - DB '<-END USER PATCH AREA' -;---------------------------------------------------------------------------- -; LOF LG -#endasm - -get1tkn() { -#asm - LXI H,TK1 ;load string pointer for token 1 -#endasm -} - -get2tkn() { -#asm - LXI H,TK2 ;load string pointer for token 2 -#endasm -} - -get3tkn() { -#asm - LXI H,TK3 ;load string pointer for token 3 -#endasm -} - -get4tkn() { -#asm - LXI H,TK4 ;load string pointer for token 4 -#endasm -} - -getcof() { -#asm - LXI H,CURSOF -#endasm -} - -getcon() { -#asm - LXI H,CURSON -#endasm -} - -gotoxy(x,y) int x,y; { - /* this outputs the VT100 Escape sequence for cursor positioning */ - char s[7]; - putc( 27, 0 ); putc( '[', 0 ); - puts( itoa(y+1,s) ); - putc( ';', 0 ); - puts( itoa(x+1,s) ); - putc( 'H', 0 ); -} /* end: gotoxy */ - -clr_screen() { - putc( 27, 0 ); puts( "[2J" ); - putc( 27, 0 ); putc( 'H', 0); -} /* standard */ - -on_cursor() { - puts ( getcon() ); -} /* optional "hide cursor" command */ - -off_cursor() { - puts ( getcof() ); -} /* optional "show cursor" command */ - -#include "printf.c" - -extern char *bgversion; - -char *backtalk[] = { - "VILLIERS: At your service!", - "LOUISA: Delighted!", - "TORVE: Is interesting line of occurrence. Thurb!", - "Copyright (c) 1985 by The Xochitl Sodality Wonders & Marvels Committee", - }; - -int list[2][28]; /* two dice, two lists */ - -struct board { - int stones, /* number of stones on that point */ - owner, /* and whose they are */ - x,y, /* x and y coordinates of point base */ - lastx,lasty, /* last location drawn on this point */ - cx,cy; /* coordinates for column numbers */ - } - point[28], bdsave[28]; /* 24 points, plus 2 bars, 2 homes */ - - -struct { int cube, whosecube; } doubles; - - -struct { int fr,to,flag; } pending; - - -int level, dice[2], myscore, yrscore, player, movesleft, cantuse, myturns, - swapped, tswap, deciding, expert, tone, show, moremsgline, - firstmove, helpdisabled, yrdice, lookforit, startcubevalue; - -char *token1, *token2, chatter[80], buzzard[8]; - -/*====================================================================== - - OPPONENT -- A little scenario, in which to select level of play - -========================================================================*/ - - -char *chooseplayer() { -int ch; char *q; - - dissemble(); -loo: ch = getkey(); - switch (ch) { - case 'A': - case 'V': { level = 0; break; } - case 'L': - case 'P': { level = 1; break; } - case 'T': { level = 2; break; } - default: goto loo; - } - q = backtalk[ level ]; - clr_screen(); draw_board(q); - return(q); - -} /* end: chooseplayer */ - -/*==================================================================== - MAIN -======================================================================*/ - -main() { -static int ch; -static char *p1 = "P(lay, R(everse, S(wap, A(rrange, N(ew, Q(uit ", - *p2 = "U(se %s dice, O(pponent, X(pert, B(eep, C(ount, Z(ero ", - *myline; - - level = MYLEVEL + 1; /* fetch copyright notice */ - setup(); - hint(); - - while (TRUE) { - moremsgline = FALSE; /* show first command line on entry */ - debug(""); /* erase messages */ - myline = backtalk[ level ]; /* did level change? */ - msg( myline ); - firstmove = TRUE; - newboard(); /* note, sets starting cube value to 1 */ - - deciding = TRUE; - while (deciding) { - - /* display command line */ - - off_cursor(); - if (show) { mytotal(); yrtotal(); } - else { gotoxy(0,3); puts(" "); gotoxy(0,19); puts(" "); } - if (tone) beep(); - if (expert) msg("Your pleasure? "); - else { - msg("Select: "); - if (moremsgline) printf(p2,(yrdice? "my": "your")); - else printf(p1); - } - - /* get response and do it */ - - - ch = getkey(); - switch (ch) { - case 'Q': { /* quit play, exit to CP/M */ - finishup(); - break; - } - case 'A': { /* arrange stones (or cheat?) */ - /* play is suspended, so don't use the long */ - /* messages that assist game play */ - helpdisabled = TRUE; - arrange(); - update(); - debug(""); - break; - } - case 'R': { /* mirror board image */ - reverse(); - update(); - break; - } - case 'C': { /* show mytotal, yrtotal counts */ - show ^= TRUE; - break; - } - case 'S': { /* SWAP Command - exchange stones */ - swaptokens(); - update(); - break; - } - case 'B': { /* kill the beep */ - tone ^= TRUE; break; - } - case 'X': /* expert mode toggle(s) */ - case 27 : { - expert ^= TRUE; - break; - } - case 'D': { /* use my dice or your dice? */ - case 'U': - yrdice ^= TRUE; - break; - } - case 'O': { /* change opponents and skill level */ - myline = chooseplayer(); - deciding = FALSE; - break; - } - case 'P': { /* play the game as board is arranged */ - helpdisabled = FALSE; - if (level > MYLEVEL ) { - myline = chooseplayer(); - update(); - } - play(); - break; - } - case 'N': { /* abandon game without quitting */ - deciding = FALSE; player = 0; - break; - } - case 'Z': { /* zero the score */ - myscore = yrscore = 0; putscore(); - break; - } - default: { moremsgline ^= TRUE; break; } - }} - } -} /* end: main */ - -/*======================================================================= - - PLAY Command - this is the command that initiates the 2-player game - -=========================================================================*/ - -play() { - -/* any vars here MUST be STATIC */ - -#asm - MOV B,H ;set up to exit this function by saving caller's - LXI H,0 ;stack pointer for use in deeply-nested scope - DAD SP ;WARNING: this function must not use dynamic variables - SHLD _fool ;CAUTION: risky business if called with parameters?? - MOV H,B ;HL is restored on general principles, BC is trashed -#endasm - - whofirst(); - taketurns(); - -} /* end: play */ - - - -whofirst() { -int ch, myval, yrval; - - if (yrdice || (player < 0)) { /* board has been re-arranged */ - msg("Is it my "); puts(token1); - puts(" turn or your "); puts(token2); - puts(" turn? "); - loo: ch = toupper(getc(0)); - if (!(ch == 'M' || ch == 'Y')) goto loo; - if (ch == 'M') player = YU; /* player says Me, of course! */ - else player = ME; - rolldice(player); - } - - else if (player == 0) { /* fresh start, roll the dice */ - barcube(); - zoo: debug("Tossing for first turn..."); - wipedice(); - rolldice(ME); - myval = dice[0]; - rolldice(YU); - yrval = dice[0]; - if (myval == yrval) { - if (tone) beep(); - off_cursor(); - gotoxy(37,11); puts("[___]"); sleep(3); - startcubevalue *= 2; - if (startcubevalue > 8) startcubevalue = 8; - doubles.cube = startcubevalue; - gotoxy(37,11); - if (doubles.cube < 16) printf("[ %d ]",doubles.cube); - else printf("[%03d]",doubles.cube); - if (startcubevalue < 9) { - msg("Double the cube!"); - sleep(20); - } - goto zoo; - } - else if (myval < yrval) player = YU; - else player = ME; - dice[0] = max(myval,yrval); dice[1] = min(myval,yrval); - } - /* otherwise, continue with last dice rolled as play is resumed */ - -} /* end: whofirst */ - - -getmove() { -static int i, ch, temp, happy; - - cantuse = ERROR; /* important for human player in tellmove */ - movesleft = 2; - if (dice[0] == dice[1]) movesleft += 2; - temp = movesleft; - - getlist(); saveboard(); lookforit = TRUE; - - if ( nomove() ) { - debug("All "); - if (player == ME) puts("my"); else puts("your"); - puts(" moves are blocked!"); - if (player == YU) sleep(20); - return; - } - - - if (player == ME) { - /* handle doubles as two consecutive, independent moves */ - setchat("I move"); debug(chatter); - if (movesleft == 4) myturns = 2; else myturns = 1; - clrpend(); - while (myturns > 0) { - cantuse = ERROR; - movesleft = 2; - while (movesleft > 0) { getlist(); mymove(); } - myturns--; - } - strcat(chatter,"\008."); debug(chatter); - } - else { /* allow the human to take back a bad board position */ - happy = FALSE; - while (!happy) { - while (movesleft > 0) { getlist(); yrmove(); } - msg("All ok? Y/N "); - do { - ch = getkey(); - } while (ch != 'N' && (ch != 'Y' && ch != '\n')); - if ( ch == 'N' ) { - msg("Ok, as it was..."); - restoreboard(); - update(); - movesleft = temp; - cantuse = ERROR; - } - else happy = TRUE; - debug(""); - } - } - -} /* end: getmove */ - -taketurns() { - - while (TRUE) { /* NO EXIT! Only a Win or player ESC can exit */ - - getmove(); - player = other(player); - if ( player == ME ) { - if ( endgame() ) { - if (topstone(ME) < 6 && cubeval()) idouble(); - else if ( mytotal() < (yrtotal() - 8) ) { - idouble(); - } - } - else if ( bearoff() ) idouble(); - } - rolldice (player); - } - -} /* end: taketurns */ - -/*=============================================*/ -/* Y O U R M O V E */ -/*=============================================*/ - -tellmove() { /* show what the player's current dice are */ -int k,n; - - n = movesleft; - debug("You "); - if (!expert) { puts(token2); puts(" "); } - puts("have "); - while (n--) { - if (dice[0] == dice[1]) k = dice[0]; /* doubles? */ - - else if (cantuse == 1) k = dice[0]; - else if (cantuse == 0) k = dice[1]; - else if (n == 1) k = dice[1]; /* 2 of 2? */ - else k = dice[0]; /* 1 of 2? */ - - printf("[%d] ",k); - } - puts("left"); - if (expert) puts("."); else puts(", moving from high to low."); - -} /* end: tellmove */ - - - -yrmove() { - - if ( nomove() ) { - debug("You have no more moves in this line of play."); - movesleft = 0; - return; - } - else { -loo: tellmove(); - if (!getyrmove()) { - hint(); - goto loo; - } - debug(""); - } - -} /* end: yrmove */ - - - -hint() { - if (!expert) { - debug("HELP, BAR and HOME are useful words in this game."); - sleep(10); - } -} /* end: hint */ - - - -nomove() { -int i,j; - for (i = 0; i < 2; i++) - for (j = 0; j < 28; j++) - if (list[i][j] != ERROR) return (FALSE); - return (TRUE); -} /* end: nomove */ - - - -getyrmove() { -int fpoint, tpoint; - - - firstmove = FALSE; /* I got it, I got it! */ - - msg("Move from? "); - fpoint = getpt(YRBAR,YRHOME); - if ( fpoint == ERROR || - (list[0][fpoint] == ERROR && list[1][fpoint] == ERROR)) { - return (FALSE); - } - puts(" To? "); - tpoint = getpt(YRBAR,YRHOME); - if ( tpoint == ERROR || - (list[0][fpoint] != tpoint && list[1][fpoint] != tpoint)) { - return (FALSE); - } - - movestone( fpoint, tpoint ); - if (movesleft < 2) { - if (list[0][fpoint] == tpoint) cantuse = 0; - else cantuse = 1; - } - return (TRUE); - -} /* end: getyrmove */ - - - -/*====== Functions That Make The Selected Move ======*/ - - -setchat( p ) char *p; { - strcpy(chatter,p); -} /* end: setchat */ - - - -putdice( f,t) int f,t; { -static char q[15]; - if (t == MYHOME) sprintf(q," %d to Home,",25 - f); - else if (f == MYBAR) sprintf(q," Bar to %d,",25 - t); - else sprintf(q," %d to %d,",25 - f, 25 - t); - strcat(chatter,q); - debug(chatter); /* avoid using save_cursor() */ -} /* end: putdice */ - - - -lurch( f, t, zlist ) int f, t, zlist; { - movestone( f, t ); /* move the stone */ - putdice(f,t); /* tell user, the action is a bit fast */ - if (movesleft < 2) cantuse = zlist; -} /* end: lurch */ - - - -/*****************************/ -/* must LINK to GAMEPLAN.REL */ -/*****************************/ - - - -/*========================================================================== - - GETLIST -- Find the possible moves for any particular throw of the dice - -===========================================================================*/ - - -checkpips( whichlist, ptimon, pips, tops ) -int whichlist, ptimon, pips, tops; { -static int j,k; - - if ( !ptimon ) { - j = whosebar(player); /* 0 if you, 25 if me */ - k = abs(j - pips); - } - else if (player == ME) { - j = ptimon; - k = j - pips; - if (k < 1) k = MYHOME; - } - else { - j = 25 - ptimon; - k = j + pips; - if (k > 24) k = YRHOME; - } - - if (point[j].stones > 0 && point[j].owner == player) { - - /* no move to a blocked point */ - if (point[k].owner != player && point[k].stones > 1) - return; - - /* no move home if i can't bear off yet */ - if (k == whosehome(player) && cantbearoff(j,pips,tops)) - return; - - /* no other move is allowed if i'm on the bar */ - if (tops == 25 && j != whosebar(player)) - return; - - /* the move is legal (but maybe not optimal) */ - list [whichlist] [j] = k; - } - -} /* end: checkpips */ - - - -build( whichlist, pips ) int whichlist, pips; { -int i, tops; - - if (whichlist == cantuse) return; - tops = topstone(player); - for (i = 0; i < 25; i++) checkpips( whichlist, i, pips, tops ); - -} /* end: build */ - - - -getlist() { /* find all legal moves using these dice */ -static int i, j; - - for (i = 0; i < 2; i++) /* initialize the lists */ - for (j = 0; j < 28; j++) - list [i] [j] = ERROR; - - build( 0, dice[0] ); /* usually the low die */ - build( 1, dice[1] ); /* usually the high die */ - -} /* end: getlist */ - - - -/*========================================================================== - - EVALUATE UTILITIES -- Functions for legal and/or best play, telling who's - who, who's ahead, who won, etc. etc. - -============================================================================*/ - - - -mytotal() { -int i, cnt; - - cnt = 0; - for (i = 0; i < 26; i++) { - if (point[i].owner == ME) cnt += point[i].stones * i; - } - if (show) { - gotoxy(0,3); printf("%03d",cnt); - } - return (cnt); - -} /* end: mytotal */ - - -yrtotal() { -int i, cnt; - - cnt = 0; - for (i = 0; i < 26; i++) { - if (point[i].owner == YU) cnt += point[i].stones * (25 - i); - } - if (show) { - gotoxy(0,19); printf("%03d",cnt); - } - return (cnt); - -} /* end: yrtotal */ - - - -topstone( who ) int who; { -static int i,j; - - if (point[ whosebar( who ) ].stones > 0) i = 25; - else { - i = 24; - while (i > 0) { - if (who == ME) j = i; else j = 25 - i; - if (point[j].stones > 0 && - point[j].owner == who) return (i); - --i; - } - } - return (i); /* return normalized value, 1 - 25, 0 is home */ - -} /* end: topstone */ - - - -cantbearoff( mypt, pips, tops ) int mypt, pips, tops; { - - /* My destination is Home, but can I do it??? */ - if (mypt > 6) mypt = 25 - mypt; /* normalize inner table */ - - /* I can't bear off if there's anybody still not in my inner table */ - if (tops > 6) return (TRUE); - - /* If I'm the highest blot in my own table, I CAN bear off */ - if (tops == mypt) return (FALSE); - - /* If I'm NOT high, I have to have an exact roll to get away with it */ - return ( (mypt != pips) ); - -} /* end: cantbearoff */ - - - -whosebar( who ) int who; { - return ( (who == ME? MYBAR: YRBAR) ); -} - - - -whosehome( who ) int who; { - return ( (who == YU? YRHOME: MYHOME) ); -} - - - -checkwin() { - if (mytotal() == 0) winner(ME, topstone(YU)); - if (yrtotal() == 0) winner(YU, topstone(ME)); -} /* end: checkwin */ - - -other( color ) int color; { - - if (color == ME) return (YU); else return (ME); - -} /* end: otherplayer */ - - - - -winner( who, high ) int who, high; { -int gammon; char ch; - - if (tone) beep(); - if (point[ whosehome( other(who) )].stones > 0) gammon = 1; - else gammon = 2; /* nothing off is a gammon! */ - if (high == 0) gammon = 1; /* someone doubled */ - else if (high > 18) gammon = 3; /* backgammon! */ - - - debug(""); - if (who == ME) puts("I"); else puts("You"); puts(" win"); - switch (gammon) { - case 1: { puts("!"); break; } - case 2: { puts(" a Gammon!"); break; } - case 3: { puts(" a Backgammon!"); break; } - } - gammon *= doubles.cube; - switch (who) { - case ME: { myscore += gammon; break; } - case YU: { yrscore += gammon; break; } - } - putscore(); - msg("Hit ESC to resume play"); - loo: ch = getc(0); if (ch != 27) goto loo; - player = 0; - reverse(); deciding = FALSE; jumpjack(); - -} /* end: winner */ - - -putscore() { - gotoxy(39,0); blanks(39); gotoxy(53,0); - printf("SCORE: You %d, Me %d",yrscore,myscore); -} /* end: putscore */ - - - - -/*======================================================================== - - REVERSE Command - allow player to take the opponent's viewpoint of the - board layout, mirror the board. Returns board layout - to the arranged position as seen from opposite side. - -==========================================================================*/ - -reverse() { -int cnt1, cnt2, cnt3, cnt4; - - off_cursor(); - cnt1 = point[MYHOME].stones; /* save counts for erase */ - cnt2 = point[YRHOME].stones; - cnt3 = point[MYBAR].stones; - cnt4 = point[YRBAR].stones; - - putstone( MYHOME, 0, 0); /* erase old trays before update */ - putstone( YRHOME, 0, 0); - - halfswap(1); halfswap(13); - - gotoxy(0,11); puts(" "); /* erase HOME message */ - gotoxy(75,11); puts(" "); - if (point[1].x < 40) { - point[MYHOME].x = point[YRHOME].x = 0; - } - else { - point[MYHOME].x = point[YRHOME].x = 75; - } - - point[MYHOME].owner = point[MYBAR].owner = ME; /* restore counts */ - point[YRHOME].owner = point[YRBAR].owner = YU; - point[MYHOME].stones = cnt1; - point[YRHOME].stones = cnt2; - point[MYBAR].stones = cnt3; - point[YRBAR].stones = cnt4; - -} /* end: reverse */ - - -#asm - DB 'Gammon IV concept & text graphic rendition by David C. Oshel',0 - DB 'MidSummer''s Day, June 21, 1985',0 - DB 'To Whomever Destroys This Notice -- Nothing Shall Happen, Forever',0 -#endasm - - -halfswap( n ) int n; { -static int i, j, k, o; - - o = n + 6; - for (i = n; i < o; i++) { - j = ((o * 2) - 1) - i; - k = point[i].x; - point[i].cx = point[i].x = point[j].x; - point[j].cx = point[j].x = k; - } - -} /* end: halfswap */ - - - - - -getkey() { -int ch; - ch = getc(0); /* keybounce? */ - while ( (ch = toupper(getc(0))) == 0 ) acg(); return (ch); -} /* end: getkey */ - - -wipedice() { -static char *s = " "; - - off_cursor(); - gotoxy(47,11); puts(s); /* erase dice roll messages */ - gotoxy(12,11); puts(s); - -} /* end: wipedice */ - - - -update() { -int i, x, c; - - for (i = 1; i < 25; i++) { - gotoxy(point[i].cx,point[i].cy); - printf("%2d",25 - i); - } - if (doubles.whosecube == YU) yrcube(doubles.cube); - else if (doubles.whosecube == ME) mycube(doubles.cube); - else barcube(); - for (i = 0; i < 28; i++) { - x = point[i].stones; - c = point[i].owner; - putstone(i,x,c); - } - if (point[1].x < 40) x = 0; else x = 75; - gotoxy(x,11); puts("HOME"); - - putscore(); mytotal(); yrtotal(); - -} /* end: update */ - - -dissemble() { - -clr_screen(); - -puts("You are a passenger in the \"Orion\" bound for STAR WELL, a slightly disreputable\n"); -puts("planetoid in the Flammarion Rift, where you have a scheduled layover of several\n"); -puts("hours. You enter the Casino there, desperately bored. Your attention is \n"); -puts("immediately drawn to an unusual trio. Your instinct for good company (they \n"); -puts("are playing Backgammon) leads you easily into a round of introductions:\n"); -puts("\n"); -puts("LOUISA PARINI -- A young woman who gives you the uncomfortable feeling that she\n"); -puts("is even younger than she looks. In fact, she is the offspring of a clan of\n"); -puts("noted interstellar jewel thieves and con artists, on her way to a famous\n"); -puts("girl's finishing school on Nashua. She has larceny in her soul, but she is on\n"); -puts("holiday. Do not underestimate her. (But you will, of course. You must.)\n"); -puts("\n"); -puts("ANTHONY VILLIERS -- A mysterious young fop with impeccable manners, and (you\n"); -puts("notice) an even more impeccable dueling saber at his side. There is something\n"); -puts("between Louisa and him. His conversation is light, witty and just slightly\n"); -puts("cynical, but you are not wrong to conclude that this is someone you can trust.\n"); -puts("\n"); -puts("TORVE THE TROG -- This blue-eyed, golden-furred entity is a member of the most\n"); -puts("dangerous and unpredictable race in the galaxy (aside from humans). You are \n"); -puts("amazed that this one is allowed to travel. (In fact, Torve's papers were forged\n"); -puts("by a member of Louisa's family and procured for him by Villiers). Torve is\n"); -puts("lost in some inner rapture, emitting soft \"Thurb\"-like noises.\n"); -puts("\n(Hit any key to continue)"); -getkey(); -puts("\015You suggest a friendly game of backgammon, at small stakes, and your\n"); -puts("companions agree instantly. Who will be your opponent? (L, V, or T) "); - -} /* end: dissemble */ - - -/*====================================================================== - - ARRANGE Command: Move stones around in the playing area. Play will - commence with this final arrangement. Notice, this - command allows for cheating because the line input - function traps Ctrl-C and executes jumpjack(). Player - returns to the command line with the game frozen, may - re-arrange as desired, then resume play. The Ctrl-C - trap will increment play level by 1. The sufficiently - stupid player will not notice, and so may lose anyway. - Trap implemented in MYLIB2.C, not here. - -========================================================================*/ - - -arrange() { /* whoever calls arrange() must also call update() next */ - -/* any vars here MUST be STATIC */ - -#asm - MOV B,H ;set up to exit this function by saving caller's - LXI H,0 ;stack pointer for use in deeply-nested scope - DAD SP ;WARNING: this function must not use dynamic variables - SHLD _fool ;CAUTION: risky business if called with parameters?? - MOV H,B ;HL is restored on general principles, BC is trashed -#endasm - - moveabout(); - -} /* end: arrange */ - - - -moveabout() { - - player = -1; /* flag to ask who moves first */ - if (!expert) - debug("Type BAR or HOME, or the Number of a Point."); - - while ( TRUE ) { /* exit via jumpjack() by typing Control-C */ - mytotal(); - yrtotal(); - revise(); - } - -} /* end: moveabout */ - - - -getpt(b,h) int b,h; { -static char ans[6], *p; int x, d1, d2, look, try; - - on_cursor(); - gets(ans,5); - p = ans; - while (*p) *p = toupper(*p++); /* capitalize string */ - off_cursor(); - - if (!helpdisabled && ((index(ans,"HEL") != -1) || - (index(ans,"?") != -1))) { - x = ERROR; - msg(""); - if (point[ whosebar(player) ].stones > 0) { - puts("You're on the Bar, so let's move that one! BAR "); - x = b; - } - else { - puts("Are you "); - if (cantuse != 0 && cantuse != 1) puts("REALLY "); - puts("blocked? Try moving From "); - look = 24; - while (look > 0) { - try = list[0][look]; - if (try == ERROR) try = list[1][look]; - if ( try != ERROR ) { - printf("%d To ",25-look); - if (try == YRHOME) printf("HOME"); - else printf("%d",25-try); - look = 0; - } - look--; - } - sleep(40); - } - } - else if (index(ans,"B") != -1) x = b; - else if (index(ans,"H") != -1) x = h; - else { - x = atoi( ans ); - if (x < 1 || x > 24) x = ERROR; - else x = 25 - x; /* translate human to computer view */ - } - return (x); - -} /* end: getpt */ - - -whoseit(p,a,b) char *p; int a,b; { -int ch; - - if (point[a].stones > 0 && point[b].stones > 0) { - debug("Whose "); puts(p); puts("? 1 = "); - puts(token1); - puts(" 2 = "); puts(token2); puts(" "); - loo: ch = getkey(); - if (!(ch == '1' || ch == '2')) goto loo; - - debug("From "); - if (ch == '1') { ch = a; puts(token1); } - else { puts(token2); ch = b; } - puts("'s "); puts(p); - return ( ch ); - } - else if (point[a].stones > 0) return (a); - else if (point[b].stones > 0) return (b); - else return (ERROR); - -} /* end: whoseit */ - - - -revise() { - do { - setchat("Move a Stone From? "); - msg(chatter); - } - while ( !delightful() ); - -} /* end: revise */ - - -delightful() { -static int from, to, fcnt, tcnt, fcolor, tcolor; - - from = getpt(MYBAR,MYHOME); - - sprintf(buzzard,"%d",abs(25 - from)); - - if (from == MYBAR) { - from = whoseit("bar",MYBAR,YRBAR); - strcpy(buzzard,"BAR"); - } - - if (from == MYHOME) { - from = whoseit("home",MYHOME,YRHOME); - strcpy(buzzard,"HOME"); - } - - if (from == ERROR) { - debug("Type Control-C to quit."); - return( FALSE ); - } - - /*-----------------------------------------------------*/ - /* establish the color of the stones on the from point */ - /*-----------------------------------------------------*/ - fcolor = point[from].owner; - - /*--------------------------------------------------*/ - /* establish the number of stones on the from point */ - /*--------------------------------------------------*/ - fcnt = point[from].stones; - - if (fcnt == 0) { - debug("What's the point?"); - return(FALSE); - } - - strcat(chatter,buzzard); /* this avoids use of save_cursor() */ - strcat(chatter," To? "); - msg(chatter); - - to = getpt(MYBAR,MYHOME); - - sprintf(buzzard,"%d",abs(25 - to)); - - - if (to == MYBAR) { - if (fcolor == YU) to = YRBAR; - strcpy(buzzard,"BAR"); - } - - if (to == MYHOME) { - if (fcolor == YU) to = YRHOME; - strcpy(buzzard,"HOME"); - } - - if (to == ERROR) { - debug("Type Control-C to quit."); - return(FALSE); - } - - if (from == to) { - debug("Quite easily done!"); - return(FALSE); - } - - strcat(chatter,buzzard); - - /*---------------------------------------------------*/ - /* establish the color of the stones on the to point */ - /*---------------------------------------------------*/ - tcolor = point[to].owner; - - /*------------------------------------------------*/ - /* establish the number of stones on the to point */ - /*------------------------------------------------*/ - tcnt = point[to].stones; - - if (fcolor == tcolor || tcolor == 0) { - msg(chatter); - --fcnt; - ++tcnt; - putstone(from, fcnt, fcolor); /* one less */ - putstone(to, tcnt, fcolor); /* one more */ - debug(""); - return (TRUE); - } - else { - debug("Evict the other stone"); - if (tcnt > 1) puts("s"); - puts(" first!"); - return (FALSE); - } - -} /* end: delightful */ - - -/*========================================================================== - - INITIALIZATION and NEWBOARD commands -- start of a new game, or cold - -===========================================================================*/ - - -wipeout() { -static int i; - - player = 0; - barcube(); - for (i = 0; i < 28; i++) { - point[i].stones = point[i].owner = 0; - } - update(); - -} /* end: wipeout */ - - -setup() { -static int i, j, k, copyright; - - myscore = yrscore = player = dice[0] = dice[1] = 0; - swapped = tswap = expert = helpdisabled = yrdice = tone = FALSE; - show = moremsgline = TRUE; - - init_lib(); - OFFinterrupt(); /* enable jumpjack() on ctl-c */ - off_cursor(); - token1 = get1tkn(); - token2 = get2tkn(); - copyright = backtalk[ MYLEVEL + 1 ]; - draw_board( copyright ); - - for (i = 0; i < 28; i++) { - point[i].stones = point[i].owner = 0; - point[i].x = point[i].y = point[i].lastx = point[i].lasty = 0; - point[i].cx = point[i].cy = 0; - } - - k = 68; - for (i = 1; i < 13; i++ ) { /* establish xy coords for the points */ - j = 25 - i; - point[i].cx = point[j].cx = point[i].x = point[j].x = k; - k -= 5; - point[i].y = 4; - point[j].y = 18; - point[i].cy = 2; - point[j].cy = 20; - if (k == 38) k -= 5; /* skip over bar */ - } - - point[MYBAR].x = point[YRBAR].x = 38; - point[MYHOME].x = point[YRHOME].x = 75; - - point[MYBAR].y = point[MYHOME].y = 5; - point[YRBAR].y = point[YRHOME].y = 17; - -} /* end: setup */ - - - -newboard() { -static int i; - - startcubevalue = 1; - wipedice(); wipeout(); - - putstone( MYHOME, 15, ME ); - putstone( YRHOME, 15, YU ); - - putstone( YRHOME, 13, YU ); - putstone( 1, 2, YU ); - - putstone( YRHOME, 8, YU ); - putstone( 12, 5, YU ); - - putstone( YRHOME, 5, YU ); - putstone( 17, 3, YU ); - - putstone( YRHOME, 0, 0 ); - putstone( 19, 5, YU ); - - putstone( MYHOME, 10, ME ); - putstone( 6, 5, ME ); - - putstone( MYHOME, 7, ME ); - putstone( 8, 3, ME ); - - putstone( MYHOME, 2, ME ); - putstone( 13, 5, ME ); - - putstone( MYHOME, 0, 0 ); - putstone( 24, 2, ME ); - -} /* end: newboard */ - - -draw_board( c ) char *c; { -static int line; -static char *m = " ", *picture[] = { -"The Peelgrunt Game of GAMMON IV%s\n\n\n", -":=================================o=================================:\n", -":: .. \\/ .. \\/ .. \\/ ||| .. \\/ .. \\/ .. \\/ ::\n", -":: ||| ::\n", -":: /\\ .. /\\ .. /\\ .. ||| /\\ .. /\\ .. /\\ .. ::\n" -}; - - clr_screen(); - off_cursor(); - msg( c ); - off_cursor(); - gotoxy(0,0); - puts(m); printf(picture[0],bgversion); - puts(m); puts(picture[1]); - for (line = 0; line < 6; line++) { - puts(m); puts(picture[2]); - } - puts(m); puts(picture[3]); - puts(m); puts(picture[3]); - puts(m); puts(picture[3]); - for (line = 0; line < 6; line++) { - puts(m); puts(picture[4]); - } - puts(m); puts(picture[1]); - -} /* end: draw_board */ - - -/*========================================================================= - - DICE Commands: How to roll the dice - -===========================================================================*/ - - -peek() { - if (yrdice) return; /* you know your own dice, probably...? */ - if (expert) debug(""); - else debug("The Dice will Rattle until you Roll. Now on "); - getdice(); - printf("[%d] [%d] ...",dice[0],dice[1]); -} /* end: peek */ - - -getonedie() { - return ( (abs(acg()) % 6) + 1 ); -} /* end: getonedie */ - - -fixup() { /* ensure that the low die is in dice[0] */ -int d,e; - if (player == 0) return; /* whofirst? don't mess with the odds */ - d = min(dice[0],dice[1]); - e = max(dice[0],dice[1]); - dice[0] = d; - dice[1] = e; -} /* end: fixup */ - - -getdice() { -int ch; - - /* if it's MY dice we're using, generate random dice... */ - if (!yrdice) { - dice[0] = getonedie(); - acg(); /* bounce a little for luck */ - dice[1] = getonedie(); - fixup(); - return; - } - - /* but if it's YOUR dice, then ask about the roll... */ -zoo: msg("<> "); - if (player == ME) puts("My"); else puts("Your"); - puts(" roll: "); - if (!expert) puts("\008\008, using your dice: "); - puts(" First? "); -loo: while ( (ch = getc(0)) == 0 ); /* don't bother acg */ - if (ch == 3) haltgame(); - ch -= '0'; - if (ch < 1 || ch > 6) goto loo; - putc( ch + '0',0); - dice[0] = ch; - - puts(" Second? "); - while ( (ch = getc(0)) == 0 ); - if (ch == 3) haltgame(); - ch -= '0'; - if (ch < 1 || ch > 6) goto zoo; - putc( ch + '0',0); - dice[1] = ch; - - puts(" All Ok? "); -roo: while ( (ch = toupper(getc(0))) == 0 ); /* don't bother acg */ - if (ch == 3) haltgame(); - if (ch != 'N' && ch != 'Y') goto zoo; - fixup(); - -} /* end: getdice */ - - - -haltgame() { - player = -1; /* if play resumes, ask whose roll it is */ - hint(); - jumpjack(); - -} /* end: haltgame */ - - - -rolldice( who ) int who; { -int waiting; - - setchat("Your Turn: "); - if (!expert) { - if (!yrdice) strcat(chatter," P(eek,"); - strcat(chatter," D(ouble, Q(uit, or to Roll "); - } - if (player == YU) { /* not executed if player == 0, i.e., whofirst */ - waiting = TRUE; - while (waiting) { - msg(chatter); - switch ( getkey() ) { - /* bailout is Ctrl-C instead of ESCape */ - case 3 : { haltgame(); break; } - case 'P': { peek(); break; } - case 'D': { udouble(); break; } - case 'Q': { winner(ME,topstone(YU)); break; } - default : waiting = FALSE; - } } - off_cursor(); debug(""); msg(""); - } - highroller(who); - -} /* end: rolldice */ - -highroller( who ) int who; { /* parameter is not redundant */ -static int y = 11; -static int xme, xyu; - - /* get the values for two dice, either yours or mine */ - - getdice(); - - /* display the values of the dice in the board area */ - - off_cursor(); - xme = 47; xyu = 12; /* decide which half to show the values in */ - if (point[1].x > 40) { - xme = 12; - xyu = 47; - } - if (player) { - gotoxy(xyu,y); blanks(18); /* erase, if not whofirst */ - gotoxy(xme,y); blanks(18); - } - if (who == ME) { - gotoxy(xme,y); puts("My"); - } - else { - gotoxy(xyu,y); puts("Your"); - } - printf(" Roll> [%d] ",dice[0]); - if (player) printf("[%d] ",dice[1]); /* whofirst doesn't show this */ - -} /* end: highroller */ - - - - - -/*======================================================================== - - MAJOR UTILITIES -- Miscellaneous functions sans which the game will not - proceed so well as otherwise.......... - -========================================================================*/ - -jumpjack() { /* Much too simple-minded LONGJUMP. (But it IS simple!) - CAUTION: C/80 has no idea what's going on here! - The in-line assembly which sets _fool MUST NOT be in - a function which uses dynamic variables, or the stack - will be disrupted. See arrange() and play() herein. */ -#asm - LHLD _fool ;Retrieve old stack status... - SPHL ;...diddle stack pointer - RET ;...and execute the ad hoc jump back to outer loop - -_fool: DS 2 ;stack pointer is saved by doit(), read and used here - -#endasm -} /* end: jumpjack */ - - - -acg() { /* additive congruential generator for pseudo-random numbers */ -static int arg[] = { - 4292, 60, 4947, 3972, 4489, - 1917, 3916, 7579, 3048, 6856, - 1832, 7589, 1798, 4954, 2880, - 5142, 5187, 3045, 1529, 3110, - 4333, 167, 5556, 7237, 5906, - 5419, 6632, 5833, 3760, 1081, - 1434, 80, 6212, 344, 7303, - 3044, 7675, 5420, 457, 3434, - 2657, 700, 6777, 4436, 620, - 2129, 629, 3550, 1639, 4546, - 1220, 6469, 862, 3280, 4664 - }; -static int rp1 = 0, rp2 = 32; - - rp1++; - rp2++; - rp1 %= 55; - rp2 %= 55; - arg[rp1] ^= arg[rp2]; - return ( arg[rp1] ); - -} /* end: acg */ - -finishup() { - on_cursor(); /* restore for user */ - exit(); -} - -saveboard() { -int i; - for (i = 0; i < 28; i++) { - bdsave[i].stones = point[i].stones; - bdsave[i].owner = point[i].owner; - } -} /* end: saveboard */ - -restoreboard() { -int i; - for (i = 0; i < 28; i++) { - point[i].stones = bdsave[i].stones; - point[i].owner = bdsave[i].owner; - } -} /* end: restoreboard */ - - -swaptokens() { -char *temp; - - swapped ^= TRUE; - if (swapped) { - temp = token1; - token1 = token2; - token2 = temp; - } - else { - tswap ^= TRUE; - if (tswap) { - token1 = get3tkn(); - token2 = get4tkn(); - } - else { - token1 = get1tkn(); - token2 = get2tkn(); - } - } - -} /* end: swaptokens */ - - -blanks( n ) int n; { - while (n--) putc(' ',0); -} /* end: blanks */ - - -msg(p) char *p; { - on_cursor(); - gotoxy(5,23); blanks(74); - gotoxy(5,23); puts(p); -} - -debug(p) char *p; { - on_cursor(); - gotoxy(5,22); blanks(74); - gotoxy(5,22); puts(p); return(FALSE); -} - - -nxtyp(i) int i; { - if (i > 9) return ( i - 1 ); else return ( i + 1 ); -} - - -isbar(p) int p; { - return (( p == MYBAR ) || ( p == YRBAR )); -} - -ishome(p) int p; { - return (( p == MYHOME ) || ( p == YRHOME )); -} - - -putstone( pt, cnt, color ) int pt, cnt, color; { -int i, xp, yp, slack; -char *background, *token; - - - if (cnt < 1) { /* empty point has neither stones nor owner */ - cnt = 0; - color = 0; - } - - point[pt].stones = cnt; /* number of stones on this point */ - point[pt].owner = color; /* and whose they are */ - - /* stack stones 5 high in the home tray, 6 high on the points */ - if (isbar(pt) || ishome(pt)) slack = 5; else slack = 6; - - /* locate the base address of the point for animation */ - xp = point[pt].x; - yp = point[pt].y; - - - /* decide on the background pattern to be used for empty places */ - if (pt > 12) background = "/\\ "; - else background = "\\/ "; - - if (point[1].x < 40) { - if ((pt % 2) == 1) background = ".. "; - } - else if ((pt % 2) == 0) background = ".. "; - - if (ishome(pt)) background = " "; - if (isbar(pt)) background = "||| "; - - /* get the token pattern to be used */ - if (color == ME) { - token = token1; - } - else { - token = token2; - } - - /* draw the entire point with token and background patterns */ - off_cursor(); - - /* first erase all blots from this point (draw the background) */ - for (i = 0; i < slack; i++) { - gotoxy(xp,yp); - puts(background); /* string has point's width */ - point[pt].lastx = 0; /* future, not implemented */ - point[pt].lasty = 0; - yp = nxtyp(yp); - } - - /* now draw all the blots there are on this point onto the point */ - for (i = 0; i < cnt; i++) { - xp = point[pt].x + (i / slack); - if ((i % slack) == 0) yp = point[pt].y; - gotoxy(xp, yp); - puts(token); - point[pt].lastx = xp; /* future, not implemented */ - point[pt].lasty = yp; - yp = nxtyp(yp); - } - -} /* end: putstone */ - - - -hitblot( from, color ) int from, color; { -static int barpt, addone; - - if (tone) beep(); - barpt = whosebar( color ); - putstone(from, 0, 0); - addone = point[barpt].stones + 1; - putstone( barpt, addone, color ); - -} /* end: hitblot */ - - - -movestone( from, to) int from, to; { -static int opponent, subone, addone; - - - opponent = other( player ); - if (point[to].owner == opponent) hitblot(to, opponent); - - subone = point[from].stones - 1; - addone = point[to].stones + 1; - - putstone(from, subone, player); - putstone(to, addone, player); - - --movesleft; - checkwin(); /* never but NEVER let a win go unnoticed! */ - -} /* end: movestone */ - - - -/*======================================================================== - - CUBE Commands -- commands related to the cube, doubling, etc. - -=========================================================================*/ - -notyrcube() { - gotoxy(75,19); blanks(5); - gotoxy(75,20); blanks(5); -} /* end: notyrcube */ - - -notmycube() { - gotoxy(75,2); blanks(5); - gotoxy(75,3); blanks(5); -} /* end: notmycube */ - - -barcube() { - /* startcubevalue is normally 1, but it may have doubled */ - /* if the opening rolloff for first turn came up doubles */ - doubles.cube = startcubevalue; - doubles.whosecube = 0; - notmycube(); notyrcube(); - gotoxy(37,11); - if (startcubevalue == 1) puts("[BAR]"); - else if (doubles.cube < 16) printf("[ %d ]",doubles.cube); - else printf("[%03d]",doubles.cube); -} /* end: barcube */ - - - -notbarcube() { - gotoxy(37,11); puts(" BAR "); -} /* end: notbarcube */ - - -mycube(value) int value; { - notbarcube(); gotoxy(75,2); puts("CUBE"); - gotoxy(75,3); - sprintf(buzzard,"[%d]",value); - printf("%-5s",buzzard); - doubles.whosecube = ME; - -} /* end: mycube */ - - - -yrcube(value) int value; { - notbarcube; gotoxy(75,19); puts("CUBE"); - gotoxy(75,20); sprintf(buzzard,"[%d]",value); - printf("%-5s",buzzard); - doubles.whosecube = YU; - -} /* end: yrcube */ - - -idouble() { -static int ch; - - if (doubles.whosecube == YU) return; /* not mine, can't double! */ - if (doubles.cube > 256) return; /* maximum, don't consider it */ - notbarcube(); - if (tone) beep(); - debug("I double. Will you accept the cube "); - printf("at %d points? ",doubles.cube * 2); - loo: while ((ch = getc(0)) == 0); - if (toupper(ch) == 'Y') { - notmycube(); - doubles.cube *= 2; - yrcube(doubles.cube); - off_cursor(); - } - else if (toupper(ch) == 'N') winner(ME,0); - else goto loo; - -} /* end: idouble() */ - - - - -backgame() { -int max, barred, count, i; - if (topstone(YU) < 12 && topstone(ME) > 18) { - if (mytotal() < yrtotal() + 4) return (TRUE); - max = barred = count = 0; - i = 24; - while (i > 18) { - if (point[i].owner == ME) { - max = i; - if (point[i].stones > 1) barred++; - count += point[i].stones; - } - i--; - } - return ((max < topstone(YU) + 1) && (barred > 1 && count < 7)); - } - else return ( mytotal() < yrtotal() + 24 ); - -} /* end: backgame */ - - - -cubeval() { -int ineed, yuneed, yrtop, mytop; - - if (endgame()) { - - /* calculate the number of dice that are required to end */ - /* the game, with appropriate fudge factors for position */ - - yrtop = topstone(YU); - mytop = topstone(ME); - - ineed = 15 - point[MYHOME].stones; - yuneed = 15 - point[YRHOME].stones; - - if (yrtop < 4 && yuneed < 3) return (FALSE); /* obvious */ - - /* topstones still running? use a different method */ - if (mytop > 6 || yrtop > 6) { - ineed = 2 * (mytotal() / 8) + 1; /* number of dice */ - yuneed = 2 * (yrtotal() / 8) + 1; - } - - /* count the stones on point 6 twice, they're losers */ - yuneed += point[6].stones; - ineed += point[6].stones; - - /* you doubled, so you have the roll */ - yuneed -= 2; - - /* odd number left? */ - if (ineed % 2) ineed++; - if (yuneed % 2) yuneed++; - - /* is the one point empty? */ - if (ineed > 4 && mytop > 3 && point[24].stones == 0) ineed++; - if (yuneed > 4 && yrtop > 3 && point[ 1].stones == 0) yuneed++; - - if (mytop < yrtop && ineed < yuneed) return (TRUE); - if (yrtop < 5 && yuneed < ineed) return (FALSE); - return ( yuneed >= ineed ); - } - else return ( backgame() ); - -} /* end: cubeval */ - - - -testcube() { - - if (cubeval()) { - debug("I accept the cube."); - notyrcube(); - doubles.cube *= 2; - mycube(doubles.cube); - } - else winner(YU,0); - -} /* end: testcube */ - - - -udouble() { - - if (doubles.whosecube == ME) { - if (tone) beep(); - debug("It's MY cube, dummy!"); - } - else testcube(); - -} /* end: udouble */ - - -#include "mylib2.c" - diff --git a/backgmmn.com b/backgmmn.com deleted file mode 100644 index c474be16427e7131cc08f1b62e52fe71007dbba2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30592 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 KghE&5|Nj6?Hu+Zo diff --git a/bgclean.sub b/bgclean.sub deleted file mode 100644 index 0172b3f..0000000 --- a/bgclean.sub +++ /dev/null @@ -1,8 +0,0 @@ -era *.bak -era *.mac -era backgmmn.rel -era gameplan.rel -era backgmmn.com -era backgmmn.mac -era gameplan.mac - diff --git a/bgmake.sub b/bgmake.sub deleted file mode 100644 index b8b595a..0000000 --- a/bgmake.sub +++ /dev/null @@ -1,13 +0,0 @@ -era *.bak -era *.mac -era backgmmn.rel -era gameplan.rel -era backgmmn.com -c -m backgmmn -m80 =backgmmn -era backgmmn.mac -c -m gameplan -m80 =gameplan -era gameplan.mac -l80 backgmmn,gameplan,stdlib/s,clibrary/s,backgmmn/n/e - diff --git a/gameplan.c b/gameplan.c deleted file mode 100644 index 5d5b93a..0000000 --- a/gameplan.c +++ /dev/null @@ -1,866 +0,0 @@ - -/* Gammon IV, by David C. Oshel, Ames, Iowa */ - -/*--------------------------------------------------------------------*/ -/* GAMEPLAN.C -- separately compiled module, contains the tactics and */ -/* strategy for making the computer's move in Gammon IV */ -/* BACKGMMN.REL calls MyMove(), MyMove() calls topstone */ -/* and movestone and a few others. Uses the globals in */ -/* GAMEPLAN.HDR quite heavily. Bgversion declared here */ -/*--------------------------------------------------------------------*/ - -#include "gameplan.hdr" /* contains external, global declarations */ - -/*-------------------------------------------------------------------------*/ -/* */ -/* Bgversion is an external reference in the main module. Use this string */ -/* to take credit for a decent gameplaying algorithm if you find one! */ -/* */ -char *bgversion = ".20 -April 1, 1986- by David C. Oshel"; - /*....v....1....v....2....v....3....v...*/ - /* just 38 characters for version info! */ -/* */ -/*-------------------------------------------------------------------------*/ - - -/*=============================================*/ -/* M Y M O V E */ -/*=============================================*/ - - -naked() { /* am I leaving too many blots? */ -static int i, clink; - i = 24; clink = 0; - while (i) { - if (point[i].stones == 1 && point[i].owner == ME) clink++; - i--; - } - return (clink > 2); -} /* end: naked */ - - -yourfolly() { /* look for lotsa blots in your inner table */ -static int i, clink; - i = 18; clink = 0; - while (i < 25) { - if (point[i].owner == YU && point[i].stones == 1) - clink++; - i++; - } - return (clink >= 3); -} /* end: yourfolly */ - - -goodboard() { /* look for four made points near my inner table */ -static int i, clank, clink; - i = 9; clank = 0; - while (i > 3) { - if (point[i].owner == ME && point[i].stones > 1) clank++; - i--; - } - if (clank > 4) return (TRUE); /* bar is nearly blocked */ - - i = 6; clank = clink = 0; - while (i) { - if (point[i].owner != ME) - ; - else if (point[i].stones == 1) clink++; else clank++; - i--; - } - return (clank > 3 && clink < 2); -} /* end: goodboard */ - - -bearoff() { - return (topstone(ME) < 7); -} /* end: bearoff */ - - -scanahead( from ) int from; { -static int count; - - count = 0; - while (--from > 0) { - ++count; - if ( point[ from ].owner == YU ) return (count); - } - return (7); - -} /* end: scanahead */ - - -endgame() { /* Is no strategy required from here on in? */ - return ( (25 - topstone(YU)) > topstone(ME) ); -} /* end: endgame */ - - -/*------------------------------------------------------------*/ -/* MATCHUP */ -/* */ -/* 2-stone functions that force the choice of the next move. */ -/* These are the HEART and SOUL of this backgammon algorithm! */ -/*------------------------------------------------------------*/ - -setpend( from, to ) int from, to; { - pending.fr = from; - pending.to = to; - pending.flag = TRUE; -} /* end: setpend */ - - -clrpend() { - pending.flag = FALSE; -} /* end: clrpend */ - - -natural(f1,t1,f2,t2) int f1,t1,f2,t2; { - clrpend(); - if (point[t2].stones == 1 && t1 == f2) setpend(f2,t2); - return (pending.flag); -} /* end: natural */ - - -matchup( test4 ) int (* test4)(); { -static int i, j, ti, tj; - - if ( pending.flag ) return (FALSE); /* this is probably redundant */ - - for (i = 1; i < 26; i++) { - ti = list[0][i]; - if ( ti == ERROR ) goto zoo; - for (j = 1; j < 26; j++) { - tj = list[1][j]; - if ( tj == ERROR ) goto voo; - if ( (* test4)( i, ti, j, tj ) ) { - lurch( i, ti, 0); - return (TRUE); - } - voo: ; - } - zoo: ; - } - return (FALSE); - -} /* end: matchup */ - - -matchhi( test4 ) int (* test4)(); { -static int i, j, ti, tj; - - if ( pending.flag ) return (FALSE); /* this is probably redundant */ - - for (i = 1; i < 26; i++) { - ti = list[1][i]; - if ( ti == ERROR ) goto zoo; - for (j = 1; j < 26; j++) { - tj = list[0][j]; - if ( tj == ERROR ) goto voo; - if ( (* test4)( i, ti, j, tj ) ) { - lurch( i, ti, 1); - return (TRUE); - } - voo: ; - } - zoo: ; - } - return (FALSE); - -} /* end: matchhi */ - - - -/*--------------------------------------------------------*/ -/* CLOCKWISE and COUNTERCLOCK */ -/* */ -/* the rest of these are single-stone decisions based on */ -/* rules of thumb, board-scanning functions */ -/*--------------------------------------------------------*/ - -plainstupid( from ) int from; { /* don't break a safe point */ - return (from < 13 && (point[from].stones == 2 && scanahead(from) < 7)); -} /* end: plainstupid */ - - -unwise( innertablept ) int innertablept; { - /* if it's a hit, just for god's sake don't put him on the bar!! */ - if ( innertablept < 7 ) { - if (point[ innertablept ].owner == YU || - point[ YRBAR ].stones > 0) - return (TRUE); - } - return(FALSE); -} /* end: unwise */ - - - -covermine( from, to ) int from, to; { - if ( from < 8 ) return(FALSE); - return ( (point[ to ].stones == 1) && (point[ to ].owner == ME) ); -} /* end: covermine */ - - -idareyou( from, to ) int from, to; { - if (unwise( to )) return (FALSE); - if ( (point[ from ].stones != 2) - && (point[ to ].stones < 2) - && (scanahead( to ) > 6) ) return ( TRUE ); - else return (FALSE); -} /* end: idareyou */ - - -hitandrun( from, to ) int from, to; { - return ( point[ to ].owner == YU ); -} /* end: hitandrun */ - - -dbuild( from, to ) int from, to; { -static int diceleft; - diceleft = (myturns? 2 + movesleft: movesleft); - if (diceleft > 1) { - /* can't possibly be only one stone on from point */ - /* or kamikaze would have covered it on last move */ - return ( point[to].stones == 0 ); - } - return (FALSE); -} /* end: dbuild */ - - -kamikaze( from, to ) int from, to; { -/* cover my distant blot, or razzle-dazzle 'em with the long doubles hit */ -static int j, k, diceleft; - - k = from; - j = from - to; - diceleft = myturns * movesleft; /* NB: 2*2 == 2+2, "fourtunately" */ - while ( diceleft-- ) { /* predicting where doubles land is easy! */ - k -= j; - if (k < 1) return (FALSE); /* out of bounds */ - if ( point[ k ].stones == 0 ) continue; /* simplify */ - if ( point[ k ].stones == 1 ) /* found my blot or yours? */ - return (TRUE); - else if ( point[k].owner == YU ) /* found your blockade? */ - return (FALSE); - else continue; /* found my safe point, so ignore it */ - } - return (FALSE); - -} /* end: kamikaze */ - - -hittite( from, to ) int from, to; { - return (hitandrun(from,to) && to > 9); -} /* end: hittite */ - - -safehit( from, to ) int from, to; { - return (hittite(from,to) && idareyou(from,to)); -} /* end: safehit */ - - -foolsdemise( from, to ) int from, to; { - /* annihilate orphaned blots in enemy's inner, my outer table */ - return (to > 17 && point[to].owner == YU); -} /* end: foolsdemise */ - - -landonme( from, to ) int from, to; { - if ( plainstupid(from) ) return (FALSE); - if ( loneranger(from,to) ) { - if (from < 19 && to > 6) return(TRUE); - } - else return ( point[ to ].owner == ME && point[to].stones < 4); -} /* end: landonme */ - - - -/* these evaluations have meaning only in the endgame */ - - -nobackgammon( from, to ) int from, to; { /* endgame */ - return (from > 19); -} /* end: nobackgammon */ - - -crosstable( from, to ) int from, to; { - /* always move a table ahead if possible, in the endgame */ - if (from < 7) return (FALSE); - if (from > 18 && to <= 18) return (TRUE); - if (from > 12 && to <= 12) return (TRUE); - if (from > 6 && to <= 6) return (TRUE); - return (FALSE); -} /* end: crosstable */ - - -fiftytworule( from, to ) int from, to; { /* endgame */ -static int p; - if (from < 7) return (FALSE); /* not in inner table! */ - p = from % 6; - if (p == 0) return (TRUE); /* improve the six */ - if (p != 5) return ( (to % 6) < 3 ); /* best improve under five */ -} /* end: fiftytworule */ - - - - -/* these evaluations are universally applicable, last resort moves */ - - -gohome( from, to ) int from, to; { /* always go home if you can */ - return (to == MYHOME); -} /* end: gohome */ - - -scatter( from, to ) int from, to; { /* scatter, esp. in the endgame */ - if (plainstupid(from) || unwise(to)) return (FALSE); - return ( point[ from ].stones > 1 && point[ to ].stones == 0 ); -} /* end: scatter */ - - -runnerup( from, to ) int from, to; { - if (from < 10 || from > 18) return (FALSE); - return (TRUE); -} /* end: runnerup */ - - -loneranger( from, to ) int from, to; { - return( point[ from ].stones == 1 ); -} /* end: loneranger */ - - -run( dummy1, dummy2 ) int dummy1, dummy2; { /* MUST move something! */ - return (TRUE); -} /* end: run */ - - - - - -/* clockwise and counterclock make a 1-stone choice on rules of thumb */ - - -counterclock( test ) int (* test)(); { -static int i,j; - - for (i = 0; i < 2; i++) { - for (j = 1; j < 25; j++) { - if ( list[i][j] == ERROR ) continue; - if ( (* test)( j, list[i][j] ) ) { - lurch( j, list[i][j], i); - return ( TRUE ); - } } } - return (FALSE); - -} /* end: counterclock */ - - -clockwise( test ) int (* test)(); { -static int i,j; - - for (i = 0; i < 2; i++) { - for (j = 25; j > 0; j--) { - if ( list[i][j] == ERROR ) continue; - if ( (* test)( j, list[i][j] ) ) { - lurch( j, list[i][j], i); - return ( TRUE ); - } } } - return (FALSE); - -} /* end: clockwise */ - - - - - -/*-------------------------------------------*/ -/* Make Prime */ -/*-------------------------------------------*/ - -static int prmchk; - - -buildprime( f1,t1,f2,t2 ) int f1,t1,f2,t2; { - clrpend(); - /* check for the doubles bug */ - if ((dice[0] == dice[1]) && (point[f1].stones < 2)) return(FALSE); - - /* look for the combination */ - if ( t1 == prmchk && t2 == prmchk) setpend(f2,t2); - - /* stick like glue to a made point, but doubles may move forward */ - if (dice[0] != dice[1]) { - if ((f2 < 8) && (point[f2].stones == 2)) clrpend(); - if ((f1 < 8) && (point[f1].stones == 2)) clrpend(); - } - - return(pending.flag); - -} /* end: buildprime */ - - -makeprime() { -static int i, tab[] = { ERROR,1,2,3,20,22,24,9,4,6,8,5,7 }; - i = 12; - while (i) { - prmchk = tab[i]; - i--; - if ( point[ prmchk ].stones > 1 ) continue; - else if ( matchup( buildprime ) ) return(TRUE); - } - return(FALSE); -} /* end: makeprime */ - - -coverprime( from, to ) int from, to; { - return (((to == prmchk) && - (point[prmchk].owner == ME)) && - (point[from].stones != 2)); -} /* coverprime */ - - -cleanup() { -static int i, tab[] = { ERROR,1,2,3,20,22,24,9,4,6,8,5,7 }; - i = 12; - while (i) { - prmchk = tab[i]; - i--; - if ( point[ prmchk ].stones != 1 ) continue; - else if ( counterclock( coverprime ) ) return(TRUE); - } - return(FALSE); -} /* end: cleanup */ - - -/*-------------------------------------*/ -/* Walking Prime */ -/*-------------------------------------*/ - -swivelhips( from, to ) int from, to; { - return ( from > prmchk ); -} /* end: swivelhips */ - - -slink( from, to ) int from, to; { - return( (from > prmchk) && (point[to].stones == 1) ); -} /* end: slink */ - - -weasel() { - if ( clockwise( slink ) ) - return(TRUE); - if ( counterclock( swivelhips ) ) - return(TRUE); - if ( clockwise( run ) ) - return(TRUE); -} /* end: weasel */ - -ihaveprime( from ) int from; { -static int i, to, ez; - ez = 0; - for (i = 0; i < 6; i++) { - to = from - i; - if ((point[to].owner == ME) && (point[to].stones > 1)) ez++; - } - return (ez > 4); -} /* end: ihaveprime */ - - -walkingprime() { -/* looks for the walking prime anywhere in the front tables */ -/* then tries to bring up a runner from behind the prime, */ -/* ensuring that a back stone WILL move before a front one */ -static int i; - i = 12; - while (i > 5) { - if ( ihaveprime(i) ) { - prmchk = i; - if ( weasel() ) return (TRUE); - } - i--; - } - return(FALSE); -} /* end: walkingprime */ - - -/*---------- Book Moves ----------*/ -/* only valid if my move is first */ -/*--------------------------------*/ - -zip(a,b,c,d) int a,b,c,d; { - lurch(a,b,0); - lurch(c,d,0); - movesleft = 0; return( TRUE ); -} /* end: zip */ - - -zoom( a,b,c,d,e,f,g,h ) int a,b,c,d,e,f,g,h; { - myturns = 0; zip(a,b,c,d); zip(e,f,g,h); return( TRUE ); -} /* end: zoom */ - - -book() { -int a,b; - if (!firstmove) return (FALSE); - firstmove = FALSE; - a = min(dice[0],dice[1]); - b = max(dice[0],dice[1]); - switch (level) { - case 0: { return ( book0(a,b) ); break; } - case 1: { return ( book1(a,b) ); break; } - case 2: { return ( book2(a,b) ); break; } - } -} -book0( a,b ) int a, b; { - switch (a) { - case 1: { switch (b) { - case 1: return ( zoom(8,7,8,7,6,5,6,5) ); - case 2: return ( zip(24,23,13,11) ); - case 3: return ( zip(8,5,6,5) ); - case 4: return ( zip(24,23,13,9) ); - case 5: return ( zip(24,23,13,8) ); - case 6: return ( zip(13,7,8,7) ); - } - break; } - case 2: { switch (b) { - case 2: return ( zoom(6,4,6,4,13,11,13,11) ); - case 3: return ( zip(13,11,13,10) ); - case 4: return ( zip(8,4,6,4) ); - case 5: return ( zip(13,8,13,11) ); - case 6: return ( zip(24,18,13,11) ); - } - break; } - case 3: { switch (b) { - case 3: return ( zoom(13,10,13,10,10,7,10,7) ); - case 4: return ( zip(13,10,13,9) ); - case 5: return ( zip(13,10,13,8) ); - case 6: return ( zip(24,18,13,10) ); - } - break; } - case 4: { switch (b) { - case 4: return ( zoom(13,9,13,9,24,20,24,20) ); - case 5: return ( zip(13,8,13,9) ); - case 6: return ( zip(24,18,18,14) ); - } - break; } - case 5: { switch (b) { - case 5: return ( zoom(13,8,13,8,8,3,8,3) ); - case 6: return ( zip(24,18,18,13) ); - } - break; } - case 6: { return ( zoom(13,7,13,7,24,18,24,18) ); - break; } - } - -} /* end: book0 */ -book1( a,b ) int a, b; { /* mostly follows Becker */ - switch (a) { - case 1: { switch (b) { - case 1: return ( zoom(8,7,8,7,6,5,6,5) ); - case 2: return ( zip(13,11,6,5) ); - case 3: return ( zip(8,5,6,5) ); - case 4: return ( zip(13,9,6,5) ); - case 5: return ( zip(13,8,6,5) ); - case 6: return ( zip(13,7,8,7) ); - } - break; } - case 2: { switch (b) { - case 2: return ( zoom(6,4,6,4,13,11,13,11) ); - case 3: return ( zip(13,11,13,10) ); - case 4: return ( zip(8,4,6,4) ); - case 5: return ( zip(13,8,13,11) ); - case 6: return ( zip(13,7,7,5) ); - } - break; } - case 3: { switch (b) { - case 3: return ( zoom(13,10,13,10,8,5,8,5) ); - case 4: return ( zip(13,10,13,9) ); - case 5: return ( zip(13,8,8,5) ); - case 6: return ( zip(13,7,13,10) ); - } - break; } - case 4: { switch (b) { - case 4: return ( zoom(13,9,13,9,9,5,9,5) ); - case 5: return ( zip(13,8,13,9) ); - case 6: return ( zip(13,7,13,9) ); - } - break; } - case 5: { switch (b) { - case 5: return ( zoom(13,8,13,8,8,3,8,3) ); - case 6: return ( zip(13,7,13,8) ); - } - break; } - case 6: { return ( zoom(13,7,13,7,24,18,24,18) ); - break; } - } - -} /* end: book1 */ -book2( a,b ) int a, b; { /* mostly follows Becker */ - switch (a) { - case 1: { switch (b) { - case 1: return ( zoom(8,7,8,7,6,5,6,5) ); - case 2: return ( zip(13,11,24,23) ); - case 3: return ( zip(8,5,6,5) ); - case 4: return ( zip(13,9,24,23) ); - case 5: return ( zip(13,8,24,23) ); - case 6: return ( zip(13,7,8,7) ); - } - break; } - case 2: { switch (b) { - case 2: return ( zoom(6,4,6,4,24,23,24,23) ); - case 3: return ( zip(13,11,13,10) ); - case 4: return ( zip(8,4,6,4) ); - case 5: return ( zip(13,8,13,11) ); - case 6: return ( zip(13,7,13,11) ); - } - break; } - case 3: { switch (b) { - case 3: return ( zoom(13,10,13,10,10,7,10,7) ); - case 4: return ( zip(13,10,13,9) ); - case 5: return ( zip(13,8,8,5) ); - case 6: return ( zip(13,7,13,10) ); - } - break; } - case 4: { switch (b) { - case 4: return ( zoom(13,9,13,9,9,5,9,5) ); - case 5: return ( zip(13,8,13,9) ); - case 6: return ( zip(13,7,13,9) ); - } - break; } - case 5: { switch (b) { - case 5: return ( zoom(13,8,13,8,8,3,8,3) ); - case 6: return ( zip(13,7,13,8) ); - } - break; } - case 6: { return ( zoom(13,7,13,7,24,18,24,18) ); - break; } - } - -} /* end: book2 */ - - -/*====== MyMove ======*/ - -torve() { - if ( makeprime() ) { /* this will use doubles, if it can */ - return; - } - else if ( walkingprime() ) { /* i have six prime points, so run!!! */ - return; - } - else if ( dice[0] == dice[1] ) { /* this is too easy! */ - if ( counterclock( kamikaze ) ) - return; - if ( counterclock( dbuild ) ) /* claim new turf */ - return; - if ( clockwise( run ) ) - return; - } - else if ( cleanup() ) { /* cover my single blot on prime points */ - return; - } - else if ( bearoff() ) { /* I'm ready, but you're in the back game! */ - if ( counterclock( gohome ) ) - return; - if ( clockwise( run ) ) - return; - } - else { - if ( clockwise( hitandrun ) ) - return; - if ( matchup( natural ) ) - return; - if ( clockwise( landonme ) ) - return; - if ( counterclock( runnerup ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } - -} /* end: torve */ - - - -villiers() { - if ( makeprime() ) { /* this will use doubles, if it can */ - return; - } - else if ( walkingprime() ) { /* i have six prime points, so run!!! */ - return; - } - else if ( dice[0] == dice[1] ) { /* this is too easy! */ - if ( counterclock( kamikaze ) ) - return; - if ( counterclock( dbuild ) ) /* claim new turf */ - return; - if ( clockwise( run ) ) - return; - } - else if ( cleanup() ) { /* cover my single blot on prime points */ - return; - } - else if ( bearoff() ) { /* I'm ready, but you're in the back game! */ - if ( counterclock( gohome ) ) - return; - if ( clockwise( run ) ) - return; - } - else { - if ( clockwise( foolsdemise ) ) - return; - if ( clockwise( idareyou ) ) - return; - if ( counterclock( covermine ) ) - return; - if ( matchup( natural ) ) - return; - if ( clockwise( landonme ) ) - return; - if ( clockwise( runnerup ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } - -} /* end: villiers */ - - - -louisa() { - if ( makeprime() ) { /* this will use doubles, if it can */ - return; - } - else if ( walkingprime() ) { /* i have six prime points, so run!!! */ - return; - } - else if ( dice[0] == dice[1] ) { /* this is too easy! */ - if ( counterclock( kamikaze ) ) - return; - if ( counterclock( dbuild ) ) /* claim new turf */ - return; - if ( clockwise( run ) ) - return; - } - else if ( cleanup() ) { /* cover my single blot on prime points */ - return; - } - else if ( bearoff() ) { /* I'm ready, but you're in the back game! */ - if ( counterclock( gohome ) ) - return; - if ( clockwise( run ) ) - return; - } - else if ( (!naked() && goodboard()) || yourfolly() ) { - if ( clockwise( hitandrun ) ) - return; - if ( matchup( natural ) ) - return; - if ( clockwise( landonme ) ) - return; - if ( counterclock( runnerup ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } - else { - if ( clockwise( foolsdemise ) ) - return; - if ( clockwise( idareyou ) ) - return; - if ( counterclock( covermine ) ) - return; - if ( matchup( natural ) ) - return; - if ( clockwise( landonme ) ) - return; - if ( clockwise( runnerup ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } -} /* end: louisa */ - - -mymove() { -int i, d; - - if ( nomove() ) { - if (lookforit && (dice[0] != dice[1])) { - lookforit = FALSE; - puts("\008... "); - switch (level) { - case 0: { puts("Blocked!"); break; } - case 1: { puts("Well, no!"); break; } - case 2: { puts("Thurb!"); break; } - } - sleep(10); - restoreboard(); - update(); - - /* put the high die in list zero */ - d = dice[0]; dice[0] = dice[1]; dice[1] = d; - - cantuse = ERROR; movesleft = 2; myturns = 1; - switch (level) { - case 0: { setchat("I move"); break; } - case 1: { setchat("Let's try"); break; } - case 2: { setchat("Move is"); break; } - } - debug(chatter); - prmchk = 12; - weasel(); - /* the rules say, use both dice if you can, or */ - /* the highest if one or the other but not both */ - } - else { - lookforit = TRUE; - strcat(chatter," and now I'm blocked "); - myturns = movesleft = 0; - } } - else if ( book() ) { - return; - } - else if ( pending.flag ) { - lurch( pending.fr, pending.to, 1 ); - clrpend(); - } - else if ( endgame() ) { /* very solid tactics here!! */ - if ( clockwise( gohome ) ) - return; - if ( clockwise( nobackgammon ) ) /* no excuse! */ - return; - if ( clockwise( crosstable ) ) - return; - if ( clockwise( fiftytworule ) ) - return; - if ( clockwise( scatter ) ) - return; - if ( clockwise( run ) ) - return; - } - else if ( point[ MYBAR ].stones > 0 ) { /* I'm on the bar! */ - if ( clockwise( hitandrun ) ) /* wreak havoc, please */ - return; - if ( clockwise( run ) ) /* note: uses low die first */ - return; - } - else switch (level) { - case 0: { villiers(); break; } - case 1: { louisa(); break; } - case 2: { torve(); break; } - } - - -} /* end: mymove */ - -/*------------------------------*/ -/* end of the GAMEPLAN.C module */ -/*------------------------------*/ - \ No newline at end of file diff --git a/gameplan.hdr b/gameplan.hdr deleted file mode 100644 index 49f8c27..0000000 --- a/gameplan.hdr +++ /dev/null @@ -1,42 +0,0 @@ -/* GAMEPLAN.HDR */ - -/*================================================================*/ -/* change nothing in this file */ -/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ - -#define TRUE 1 -#define FALSE 0 -#define ME 1 -#define YU 2 -#define YRBAR 0 -#define MYBAR 25 -#define YRHOME 26 -#define MYHOME 27 -#define ERROR 999 -#define MYLEVEL 2 - -extern int list[2][28]; /* two dice, two lists */ - -extern struct board { - int stones, /* number of stones on that point */ - owner, /* and whose they are */ - x,y, /* x and y coordinates of point base */ - lastx,lasty, /* last location drawn on this point */ - cx,cy; /* coordinates for column numbers */ - } - point[28], bdsave[28]; /* 24 points, plus 2 bars, 2 homes */ - -extern struct { int cube, whosecube; } doubles; - -extern struct { int fr,to,flag; } pending; - -extern int level, dice[2], myscore, yrscore, player, movesleft, cantuse, - myturns, swapped, tswap, deciding, expert, tone, show, moremsgline, - firstmove, helpdisabled, yrdice, lookforit, startcubevalue; - -extern char *chatter[80]; - -/*----------------------------------------------*/ -/* end of header -- change NOTHING in this file */ -/*----------------------------------------------*/ - \ No newline at end of file diff --git a/mylib2.c b/mylib2.c deleted file mode 100644 index 4082da3..0000000 --- a/mylib2.c +++ /dev/null @@ -1,541 +0,0 @@ -/* -MYLIB2.C - -These routines are CONDITIONALLY compiled; i.e., only as needed. - ----------------------------------------------------------------------- -Incorporates special mods used by my Backgammon game, BACKGMMN.C etc. ----------------------------------------------------------------------- - -A set of common I/O functions that seem to turn up a lot in my programs, -including terminal functions for Kaypro 10, 4'84, 2X etc. - -Uses Software Toolworks' C/80 3.1 compiler. Place #include "mylib2.c" at the -end of your source file for correct CONDITIONAL COMPILATION. - -David C. Oshel -1219 Harding Ave. -Ames, Iowa 50010 - -Last modified: March 25, 1986 - ------------------------------------------------------------------------------ -** WARNING ** These routines use direct console IO, bdos function 6! - - YOU MUST CALL INIT_LIB() BEFORE USING THESE ROUTINES! - - ======= UTILITIES ======= - - * init_lib() - CALL THIS FIRST, OR THE RESULT WILL BE VERY STRANGE! - * - * puts(p) - unformatted print, e.g., puts("Hello, sailor!\n"); - * gets(p,max) - printable input only, no prompt character - * - * ask(p) - demand Yes or No response to question p - * random() - effective random 16-bit integer IFF gets() is used - * sleep(n) - sleep n/10ths of a second, roughly (from C80.LIB) - * rollup() - roll up 23 lines of screen - * ONscript() - printer echo ON for output via puts, chrout - * OFFscript() - printer echo OFF for output via puts, chrout - * ONinterrupt() - Ctl-C, Ctl-B cause program exit - * OFFinterrupt() - Ctl-C, Ctl-B cause comedy - * hide_input(p,max) - like gets, but used when entering passwords - * chrout(c) - if scripting, echo output also to LST: - * putscreen(p) - like puts, but always and only to screen - - - ======= KAYPRO 10 TERMINAL/VIDEO FUNCTIONS ======= - - * gotoxy(x,y) - 0,0 is top left, horz <= 79 precedes vert <= 24, - * where 0,24 is on the 25th, status, line. - * beep() - terminal bell - * home() - home cursor, do not clear screen - * clr_screen() - home and clear - * - * shadow_box(h,v,x1,y1,x2,y2) - like box, but with shadow, calls box - * box(tlx,tly,brx,bry) - draw a line box, coords: topleft XY, bottomright XY - * note that box calls ldraw(x1,y1,x2,y2), below - * - * clr_lend() - clear from cursor to end of line - * clr_send() - clear from cursor to end of screen - * rev_vid(), - * nor_vid() - reverse field - * dim_vid(), - * bri_vid() - low/high intensity - * on_blink(), - * off_blink() - blinking chars - * ul_start(), - * ul_stop() - start/stop underline - * save_cursor(), - * retn_cursor() - remember/restore current cursor location - * ins_line(), - * del_line() - insert/delete screen text line - * on_cursor(), - * off_cursor() - hide/show cursor - * vm_on(), - * vm_off() - "Video Mode" commands - * pixel(x,y) - draw pixel at x,y (video coords, x <= 159, y <= 99) - * no_pixel(x,y) - erase pixel at x,y - * ldraw(x1,y1,x2,y2) - draw/ erase graphics line, see discussion for box - * lwipe(x1,y1,x2,y2) - range for video coordinates as for pixel -*/ - - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - - -/* hide this here so's not to worry about it elsewhere */ -/* "printf.c" collides with one of these, can't remember which */ -/* puts() takes longer to write, but executes faster */ -extern char Cmode, IOpread[4], IOpwrit[4], IOpeof[4]; - -/* make these known only to what follows */ -static int MYbstout, MYscrtp, MYretnirp; /* odd names mark semi-private */ -static unsigned RNDloc; /* effective random location, bumped by gets() */ - /* and scrambled when the LCG random() is called */ - /* makes a decent algorithm for interactive games */ - - -#ifneed init_lib -init_lib() { - - MYretnirp = fopen("LST:","w"); - OFFscript(); - ONinterrupt(); - Cmode = 0; - IOpread[0] = 6; IOpwrit[0] = 6; - -} /* end: init_lib */ -#endif - - - - -#ifneed random -random() { /* depends on effective random location spun by gets() */ - - RNDloc = 2053 * RNDloc + 13849; - return (RNDloc); -} -#endif - - - -#ifneed ONscript -ONscript() { - - MYscrtp = TRUE; - -} -#endif -#ifneed OFFscript -OFFscript() { - - MYscrtp = FALSE; - -} -#endif - - -#ifneed ONinterrupt -ONinterrupt() { - - MYbstout = TRUE; - -} -#endif -#ifneed OFFinterrupt -OFFinterrupt() { - - MYbstout = FALSE; - -} -#endif - - -#ifneed ask -ask(p) char *p; { - -char ch, resp[2]; - -loo: puts(p); - gets(resp,1); - ch = toupper( *resp ); - if ( !( ch == 'Y' || ch == 'N' )) { - puts("Please answer the question, Yes or No.\n"); - goto loo; - } - return (ch == 'Y'); - -} /* end: ask */ -#endif - - -#ifneed rollup -rollup() { - -int i; - - for (i=0; i<23; i++) puts("\n"); - -} /* end: rollup */ -#endif - - -#ifneed sleep -sleep( n ) int n; { /* sleep for n/10 seconds, 0 <= n < 256 */ - - n; /* get n into HL */ -#asm - MOV B,L ;delay B/10ths of a second -__DL0: MVI A,100 ;100 milliseconds, 1/10 second -__DL1: MVI C,249 ;1 millisecond per unit of A at 4 MHz -__DL2: DCR C ;Leventhal, Z80 Assembly Language Programming - JNZ __DL2 - DCR A - JNZ __DL1 - DCR B - JNZ __DL0 ;on exit, HL has FALSE if n was 0, else TRUE -#endasm -} /* end: sleep */ -#endif - - -/*========================================*/ -/* GETS(p, maxinput) */ -/* Local getline function with special *---* WARNING: */ -/* input handling, 1 <= len <= maxinput *---* Execute INIT_LIB() first !! */ -/* Updates effective random, RNDloc, */ -/* Forces input from CONSOLE only! */ -/*========================================*/ - -#ifneed gets -gets(p,maxinput) char *p; int maxinput; { - -/* This function depends on BDOS Function #6. Init_lib() sets Cmode=0 and - IOpread[0]=6 and IOpwrit[0]=6 (courtesy of and peculiar to C/80 3.1) - YOU must ensure that the target string is long enough to collect the - entire maximum input allowed and specified, INCLUDING FINAL NULL! */ - -static int len; -static char ch; - - len = -1; - if (maxinput < 1 || maxinput > 127) maxinput = 79; - - /*--------------------------------*/ - /* SPECIAL ROUTINE FOR BACKGAMMON */ - /*--------------------------------*/ - -loo: while ( !(ch = getc(0)) ) acg(); /* keep the game lively */ - - if (len < 0) len = 0; /* don't destroy prompt by backing up */ - if (ch == '\n') { /* end of line? don't store newline */ - *p = '\0'; /* mark it with a B for baby and me */ - /* chrout('\n'); */ /* but DON'T echo newline */ - return ( len ); /* <--- HERE IS THE FUNCTION EXIT! */ - } - else if (ch == '\b' || ch == 0x7F) { /* backspace? rubout? */ - if (len--) { /* where's the prompt? */ - puts("\008 \008"); /* we're ok, echo erase */ - p--; /* delete from string */ - } - } - - /*--------------------------------*/ - /* SPECIAL ROUTINE FOR BACKGAMMON */ - /*--------------------------------*/ - - else if (ch == '\003') { /* user bailout key is Ctrl-C, not ESC */ - if (MYbstout) exit(); - else { - haltgame(); /* sets whofirst flag and does jumpjack() */ - } - } - - else if (ch == '\025' || ch == '\030') { /* Ctl-U, Ctl-X */ - while (len--) { - p--; - puts("\008 \008"); - } - } - else if (len == maxinput) { /* test specials before testing len */ - chrout('\007'); - } - else if (ch > 31 && ch < 127) { /* printable char? */ - chrout(ch); /* yes, echo it */ - *p++ = ch; /* collect it */ - len++; /* keep track of it */ - } - else { /* control chars? */ - chrout('\007'); - } - goto loo; - -} /* end: gets */ -#endif - - - - -#ifneed hide_input -hide_input(s,len) char *s; int len; { - -/* receive at most len chars in s buffer, - terminate string with zero, - but echo each char with 1, 2, or 3 meaningless dots */ - -char ch; int num; - - if ((len < 1) || (len > 127)) len = 127; - num = 0; - for (;;) { /* forever */ - while ((ch = getc(0)) == 0) /* bdos 6 does not wait, so we do */ - ; - if ((ch == '\r') || (ch == '\n') || (num++ > len)) { - /* not sure what the CR key actually is to bdos 6 & C/80 */ - *s++ = '\0'; - return; /* this way out */ - } - if ((num % 2) == 0) putc('.',0); /* deception, illusion */ - if ((num % 5) == 0) putc('.',0); - putc('.',0); - *s++ = ch; - } - -} /* end: hide_input */ -#endif - - - - -/*------------------------ kpro stuff -------------------------*/ - -#ifneed shadow_box -/* like box, but with horizontal & vertical displacement for shadow */ -shadow_box(h,v,x1,y1,x2,y2) int h,v,x1,y1,x2,y2; -{ - box(x1+h,y1+v,x2+h,y2+v); /* draw the shadow */ - box(x1,y1,x2,y2); /* draw the box */ - ldraw(x1+h,y1+v,x1,y1); /* draw the corners */ - ldraw(x2+h,y2+v,x2,y2); - ldraw(x2+h,y1+v,x2,y1); - ldraw(x1+h,y2+v,x1,y2); -} -#endif - - -#ifneed box -/* parameters are topleft X,Y and bottomright X,Y - X ranges from 0 to 159, Y ranges from 0 to 99, top left is 0,0 - */ -box(x1,y1,x2,y2) int x1,y1,x2,y2; { - ldraw(x1,y1,x1,y2); - ldraw(x1,y2,x2,y2); /* appears to draw the box anticlockwise */ - ldraw(x2,y1,x2,y2); - ldraw(x1,y1,x2,y1); -} -#endif - - - -#ifneed gotoxy -gotoxy (xpos,ypos) int xpos,ypos; { /* 0,0 is top left corner */ - putscreen("\033="); - putc(ypos+' ',0); - putc(xpos+' ',0); - } -#endif - - -#ifneed beep -beep() { putc(7,0); } /* send bell character */ -#endif - -#ifneed home -home() { putc(30,0); } /* home cursor to top left */ -#endif - -#ifneed clr_screen -clr_screen() { putc(26,0); } /* home and erase screen */ -#endif - - -#ifneed clr_lend -clr_lend() { putc(24,0); } /* clear to end of line */ -#endif - -#ifneed clr_send -clr_send() { putc(23,0); } /* clear to end of screen */ -#endif - - - -#ifneed rev_vid -rev_vid() { putscreen ("\033B0"); } /* reverse background */ -#endif - -#ifneed nor_vid -nor_vid() { putscreen ("\033C0"); } -#endif - - - -#ifneed dim_vid -dim_vid() { putscreen ("\033B1"); } /* low intensity */ -#endif - -#ifneed bri_vid -bri_vid() { putscreen ("\033C1"); } -#endif - - - -#ifneed on_blink -on_blink() { putscreen ("\033B2"); } /* blinking characters */ -#endif - -#ifneed off_blink -off_blink() { putscreen ("\033C2"); } -#endif - - - -#ifneed ul_start -ul_start() { putscreen ("\033B3"); } /* underline */ -#endif - -#ifneed ul_stop -ul_stop() { putscreen ("\033C3"); } -#endif - - -#ifneed save_cursor -save_cursor() { putscreen ("\033B6"); } /* remember cursor position */ -#endif -#ifneed retn_cursor -retn_cursor() { putscreen ("\033C6"); } /* return to remembered pos */ -#endif - - -#ifneed on_status -on_status() { putscreen ("\033B7"); } /* status line preservation on */ -#endif -#ifneed off_status -off_status() { putscreen ("\033C7"); } -#endif - - -#ifneed ins_line -ins_line() { /* insert text line */ - putscreen("\033R"); - } -#endif -#ifneed del_line -del_line() { /* delete text line */ - putscreen("\033E"); - } -#endif - - -#ifneed on_cursor -on_cursor() { putscreen ("\033B4"); } /* (in)visible cursor */ -#endif -#ifneed off_cursor -off_cursor() { putscreen ("\033C4"); } -#endif - - - -/* Video Mode ON/OFF: video WORD, 8 bit video if 15 and 7 are both high */ -/* VM-ON 10000001 11111111 VM-OFF */ -/* ^video ^x^video */ -/* otherwise, video BYTE, high bit 7 interprets bits 0-6 as screen dots */ -/* 11111111 */ -/* ^video */ -/* e.g., */ -/* Non-VideoMode VideoMode */ -/* xx 1 11:0 where % is 1 01:0 1 11:0 xx */ -/* xx 3 11 2 the video 3 00 2 3 11 2 xx */ -/* xx 5 11 4 flag bit, 5 00 4 5 11 4 xx */ -/* x 7:%1 6 x is pixel 7:%0 6 7:%1 6 xx */ -/* ^ ^ ^ */ -/* to set the pixels, first do a gotoxy to character screen position */ -/* this mode is faster than Pixel ON/OFF if values are drawn from table */ -#ifneed vm_on -vm_on() { putscreen ("\033B5"); } /* video mode on */ -#endif -#ifneed vm_off -vm_off() { putscreen ("\033C5"); } -#endif - - -#ifneed pixel -pixel(x,y) int x,y; { /* x <= 159, y <= 99 */ - putscreen("\033*"); - putc(y+' ',0); putc(x+' ',0); -} -#endif - -#ifneed no_pixel -no_pixel(x,y) int x,y; { /* x <= 159, y <= 99 */ - putscreen("\033 "); - putc(y+' ',0); putc(x+' ',0); -} -#endif - - -#ifneed ldraw -/* use x1 <= x2, y1 <= y2, order is significant (Kaypro bug?) */ -ldraw(x1,y1,x2,y2) int x1,x2,y1,y2; { /* x <= 159, y <= 99 */ - putscreen("\033L"); - putc(y1+' ',0); putc(x1+' ',0); - putc(y2+' ',0); putc(x2+' ',0); -} -#endif - - -#ifneed lwipe -lwipe(x1,y1,x2,y2) int x1,x2,y1,y2; { /* x <= 159, y <= 99 */ - putscreen("\033D"); - putc(y1+' ',0); putc(x1+' ',0); - putc(y2+' ',0); putc(x2+' ',0); -} -#endif - - -#ifneed putscreen -putscreen(p) char *p; { - - while (*p) putc(*p++,0); - -} /* end: putscreen */ -#endif - - -#ifneed puts -puts(p) char *p; { - - while (*p) chrout(*p++); - -} /* end: puts */ -#endif - - -#ifneed chrout -chrout(c) char c; { /* SPECIAL FOR SCRIPT OPTION WITH LST: */ - - putc(c,0); - if ( MYscrtp ) putc(c,MYretnirp); - -} /* end: chrout */ -#endif - -/* end: MYLIB.C */ - - \ No newline at end of file