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 fffa172..0000000 Binary files a/Original/backgmmn.com and /dev/null differ diff --git a/Original/backgmmn.lbr b/Original/backgmmn.lbr deleted file mode 100644 index c0e9097..0000000 Binary files a/Original/backgmmn.lbr and /dev/null differ 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 c474be1..0000000 Binary files a/backgmmn.com and /dev/null differ 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