From 9008c67a3850c082dc62abc2fc378fec1d88f895 Mon Sep 17 00:00:00 2001 From: acn Date: Wed, 1 Jul 2020 15:28:08 +0200 Subject: [PATCH] Moved Backgammon to this repository --- Backgammon/Compiler/Compiling.md | 62 + Backgammon/Compiler/bgclean.sub | 8 + Backgammon/Compiler/bgmake.sub | 13 + Backgammon/Compiler/c80v31.zip | Bin 0 -> 88632 bytes Backgammon/Compiler/l80.com | Bin 0 -> 10752 bytes Backgammon/Compiler/m80.com | Bin 0 -> 20096 bytes Backgammon/Original/backgmmn.c | 2278 ++++++++++++++++++++++++++++++ Backgammon/Original/backgmmn.com | Bin 0 -> 30976 bytes Backgammon/Original/backgmmn.lbr | Bin 0 -> 69888 bytes Backgammon/Original/backgmmn.sub | 14 + Backgammon/Original/gameplan.c | 866 ++++++++++++ Backgammon/Original/gameplan.hdr | 42 + Backgammon/Original/mylib2.c | 541 +++++++ Backgammon/Original/read.me | 56 + Backgammon/README.md | 51 + Backgammon/backgmmn.c | 1968 ++++++++++++++++++++++++++ Backgammon/backgmmn.com | Bin 0 -> 30592 bytes Backgammon/gameplan.c | 866 ++++++++++++ Backgammon/gameplan.hdr | 42 + Backgammon/mylib2.c | 541 +++++++ README.md | 7 +- 21 files changed, 7349 insertions(+), 6 deletions(-) create mode 100644 Backgammon/Compiler/Compiling.md create mode 100644 Backgammon/Compiler/bgclean.sub create mode 100644 Backgammon/Compiler/bgmake.sub create mode 100644 Backgammon/Compiler/c80v31.zip create mode 100644 Backgammon/Compiler/l80.com create mode 100644 Backgammon/Compiler/m80.com create mode 100644 Backgammon/Original/backgmmn.c create mode 100644 Backgammon/Original/backgmmn.com create mode 100644 Backgammon/Original/backgmmn.lbr create mode 100644 Backgammon/Original/backgmmn.sub create mode 100644 Backgammon/Original/gameplan.c create mode 100644 Backgammon/Original/gameplan.hdr create mode 100644 Backgammon/Original/mylib2.c create mode 100644 Backgammon/Original/read.me create mode 100644 Backgammon/README.md create mode 100644 Backgammon/backgmmn.c create mode 100644 Backgammon/backgmmn.com create mode 100644 Backgammon/gameplan.c create mode 100644 Backgammon/gameplan.hdr create mode 100644 Backgammon/mylib2.c diff --git a/Backgammon/Compiler/Compiling.md b/Backgammon/Compiler/Compiling.md new file mode 100644 index 0000000..da5f0c9 --- /dev/null +++ b/Backgammon/Compiler/Compiling.md @@ -0,0 +1,62 @@ +# 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 also 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/Backgammon/Compiler/bgclean.sub b/Backgammon/Compiler/bgclean.sub new file mode 100644 index 0000000..0172b3f --- /dev/null +++ b/Backgammon/Compiler/bgclean.sub @@ -0,0 +1,8 @@ +era *.bak +era *.mac +era backgmmn.rel +era gameplan.rel +era backgmmn.com +era backgmmn.mac +era gameplan.mac + diff --git a/Backgammon/Compiler/bgmake.sub b/Backgammon/Compiler/bgmake.sub new file mode 100644 index 0000000..b8b595a --- /dev/null +++ b/Backgammon/Compiler/bgmake.sub @@ -0,0 +1,13 @@ +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/Backgammon/Compiler/c80v31.zip b/Backgammon/Compiler/c80v31.zip new file mode 100644 index 0000000000000000000000000000000000000000..e43d1fc8501dd40af715ea2b26acc01425542f91 GIT binary patch literal 88632 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 literal 0 HcmV?d00001 diff --git a/Backgammon/Compiler/l80.com b/Backgammon/Compiler/l80.com new file mode 100644 index 0000000000000000000000000000000000000000..264e3b54d7cc172d1deac73f6cf3854e91ac5373 GIT binary patch literal 10752 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 X$6@~$`6Js1`A_ literal 0 HcmV?d00001 diff --git a/Backgammon/Compiler/m80.com b/Backgammon/Compiler/m80.com new file mode 100644 index 0000000000000000000000000000000000000000..d54606572457565559674a8d67d7ded4b80f78ae GIT binary patch literal 20096 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' + 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/Backgammon/Original/backgmmn.com b/Backgammon/Original/backgmmn.com new file mode 100644 index 0000000000000000000000000000000000000000..fffa1720ead894aac9ef5b4d126ed55e33ae60f1 GIT binary patch literal 30976 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 M{6Bvt{=dop2f`6scK`qY literal 0 HcmV?d00001 diff --git a/Backgammon/Original/backgmmn.sub b/Backgammon/Original/backgmmn.sub new file mode 100644 index 0000000..acb857c --- /dev/null +++ b/Backgammon/Original/backgmmn.sub @@ -0,0 +1,14 @@ +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/Backgammon/Original/gameplan.c b/Backgammon/Original/gameplan.c new file mode 100644 index 0000000..5d5b93a --- /dev/null +++ b/Backgammon/Original/gameplan.c @@ -0,0 +1,866 @@ + +/* 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/Backgammon/Original/gameplan.hdr b/Backgammon/Original/gameplan.hdr new file mode 100644 index 0000000..49f8c27 --- /dev/null +++ b/Backgammon/Original/gameplan.hdr @@ -0,0 +1,42 @@ +/* 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/Backgammon/Original/mylib2.c b/Backgammon/Original/mylib2.c new file mode 100644 index 0000000..4082da3 --- /dev/null +++ b/Backgammon/Original/mylib2.c @@ -0,0 +1,541 @@ +/* +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/Backgammon/Original/read.me b/Backgammon/Original/read.me new file mode 100644 index 0000000..148039f --- /dev/null +++ b/Backgammon/Original/read.me @@ -0,0 +1,56 @@ + +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/Backgammon/README.md b/Backgammon/README.md new file mode 100644 index 0000000..af00ada --- /dev/null +++ b/Backgammon/README.md @@ -0,0 +1,51 @@ +# Gammon IV (VT100 ANSI edition) + +By: + David C. Oshel + 1219 Harding Ave. + Ames, Iowa 50010 + +This is a patched version of "Gammon IV, Version 2.0, April 1, 1986", a full-screen backgammon for CP/M. + +I patched the game to use VT100 compatible escape sequences (including ANSI color). + +Therefore, I removed most of the "user patch area" and hardcoded the VT100 sequences in the C code, +replaced the asm code of gotoxy() with C code and removed the Kaypro graphics routines +(and the "G(raphics" command) as it is not needed for my VT100 version. + +``BACKGMMN.COM`` is the compiled and ready-to-run game. + +Have fun playing! + +Anna Christina Naß + +## Compiling the game + +See [Compiler/Compiling.md](Compiler/Compiling.md) for information on compiling the game on CP/M. + +## From the original Version 2.0 READ.ME: + +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. + +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 + diff --git a/Backgammon/backgmmn.c b/Backgammon/backgmmn.c new file mode 100644 index 0000000..d3a49ac --- /dev/null +++ b/Backgammon/backgmmn.c @@ -0,0 +1,1968 @@ +/* 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/Backgammon/backgmmn.com b/Backgammon/backgmmn.com new file mode 100644 index 0000000000000000000000000000000000000000..c474be16427e7131cc08f1b62e52fe71007dbba2 GIT binary patch literal 30592 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 KghE&5|Nj6?Hu+Zo literal 0 HcmV?d00001 diff --git a/Backgammon/gameplan.c b/Backgammon/gameplan.c new file mode 100644 index 0000000..5d5b93a --- /dev/null +++ b/Backgammon/gameplan.c @@ -0,0 +1,866 @@ + +/* 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/Backgammon/gameplan.hdr b/Backgammon/gameplan.hdr new file mode 100644 index 0000000..49f8c27 --- /dev/null +++ b/Backgammon/gameplan.hdr @@ -0,0 +1,42 @@ +/* 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/Backgammon/mylib2.c b/Backgammon/mylib2.c new file mode 100644 index 0000000..4082da3 --- /dev/null +++ b/Backgammon/mylib2.c @@ -0,0 +1,541 @@ +/* +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/README.md b/README.md index 3b2b5da..978732d 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,6 @@ These games use VT100 either per default or were adopted to using them. Whenever possible, I will provide working binaries (i.e. .COM files) and also the sources or original files that I found online. -## Backgammon - -by David C. Oshel; C/asm sources available; I've adopted the code to VT100. - -See this repository: https://git.imzadi.de/acn/backgammon-vt100 - ## Games in this repository * [2048](2048/) @@ -34,6 +28,7 @@ See this repository: https://git.imzadi.de/acn/backgammon-vt100 * [Robot Chase](RobotChase/) * [MazezaM](MazezaM/) * [Pac](Pac/) +* [Backgammon](Backgammon/) ## More Games on the Interwebs