Moved Backgammon to this repository
This commit is contained in:
parent
54fe73b528
commit
9008c67a38
62
Backgammon/Compiler/Compiling.md
Normal file
62
Backgammon/Compiler/Compiling.md
Normal file
@ -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
|
||||||
|
|
8
Backgammon/Compiler/bgclean.sub
Normal file
8
Backgammon/Compiler/bgclean.sub
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
era *.bak
|
||||||
|
era *.mac
|
||||||
|
era backgmmn.rel
|
||||||
|
era gameplan.rel
|
||||||
|
era backgmmn.com
|
||||||
|
era backgmmn.mac
|
||||||
|
era gameplan.mac
|
||||||
|
|
13
Backgammon/Compiler/bgmake.sub
Normal file
13
Backgammon/Compiler/bgmake.sub
Normal file
@ -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
|
||||||
|
|
BIN
Backgammon/Compiler/c80v31.zip
Normal file
BIN
Backgammon/Compiler/c80v31.zip
Normal file
Binary file not shown.
BIN
Backgammon/Compiler/l80.com
Normal file
BIN
Backgammon/Compiler/l80.com
Normal file
Binary file not shown.
BIN
Backgammon/Compiler/m80.com
Normal file
BIN
Backgammon/Compiler/m80.com
Normal file
Binary file not shown.
2278
Backgammon/Original/backgmmn.c
Normal file
2278
Backgammon/Original/backgmmn.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Backgammon/Original/backgmmn.com
Normal file
BIN
Backgammon/Original/backgmmn.com
Normal file
Binary file not shown.
BIN
Backgammon/Original/backgmmn.lbr
Normal file
BIN
Backgammon/Original/backgmmn.lbr
Normal file
Binary file not shown.
14
Backgammon/Original/backgmmn.sub
Normal file
14
Backgammon/Original/backgmmn.sub
Normal file
@ -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
|
||||||
|
|
866
Backgammon/Original/gameplan.c
Normal file
866
Backgammon/Original/gameplan.c
Normal file
@ -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 */
|
||||||
|
/*------------------------------*/
|
||||||
|
|
42
Backgammon/Original/gameplan.hdr
Normal file
42
Backgammon/Original/gameplan.hdr
Normal file
@ -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 */
|
||||||
|
/*----------------------------------------------*/
|
||||||
|
|
541
Backgammon/Original/mylib2.c
Normal file
541
Backgammon/Original/mylib2.c
Normal file
@ -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 */
|
||||||
|
|
||||||
|
|
56
Backgammon/Original/read.me
Normal file
56
Backgammon/Original/read.me
Normal file
@ -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
|
||||||
|
|
51
Backgammon/README.md
Normal file
51
Backgammon/README.md
Normal file
@ -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ß <acn@acn.wtf>
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
1968
Backgammon/backgmmn.c
Normal file
1968
Backgammon/backgmmn.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Backgammon/backgmmn.com
Normal file
BIN
Backgammon/backgmmn.com
Normal file
Binary file not shown.
866
Backgammon/gameplan.c
Normal file
866
Backgammon/gameplan.c
Normal file
@ -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 */
|
||||||
|
/*------------------------------*/
|
||||||
|
|
42
Backgammon/gameplan.hdr
Normal file
42
Backgammon/gameplan.hdr
Normal file
@ -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 */
|
||||||
|
/*----------------------------------------------*/
|
||||||
|
|
541
Backgammon/mylib2.c
Normal file
541
Backgammon/mylib2.c
Normal file
@ -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 */
|
||||||
|
|
||||||
|
|
@ -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
|
Whenever possible, I will provide working binaries (i.e. .COM files) and also the
|
||||||
sources or original files that I found online.
|
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
|
## Games in this repository
|
||||||
|
|
||||||
* [2048](2048/)
|
* [2048](2048/)
|
||||||
@ -34,6 +28,7 @@ See this repository: https://git.imzadi.de/acn/backgammon-vt100
|
|||||||
* [Robot Chase](RobotChase/)
|
* [Robot Chase](RobotChase/)
|
||||||
* [MazezaM](MazezaM/)
|
* [MazezaM](MazezaM/)
|
||||||
* [Pac](Pac/)
|
* [Pac](Pac/)
|
||||||
|
* [Backgammon](Backgammon/)
|
||||||
|
|
||||||
## More Games on the Interwebs
|
## More Games on the Interwebs
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user