PROGRAM Cribbage; (* TURBO PASCAL 1.0 Morrow Micro Decision MD-2 David C. Oshel, Jan 15, 1984, 1219 Harding Ave, Ames, Iowa 50010 Modified under Turbo Pascal 2.0 6-Jan-85 Alan D. Hull, 42489 Castle Ct., Canton, MI. 48188 *) { Modification history: 1/6/85 Added Delete key as a valid video erase in data entries. Commented out the Inline exit code; replaced with Halt. Added instructions } { TITLE PAGE: (':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'); (':: Adapted from "Cribbage" in APPLE PASCAL GAMES, by Douglas Hergert ::'); (':: and Joseph T. Kalash, pages 301-349. Sybex, 1981. ::'); (':: ::'); (':: January 8, 1984 d.c.o. ::'); (':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'); } Label 1; Const decksize = 52; dealsize = 6; scribsize = 6; playsize = 4; ranksize = 13; winpoints = 121; Type charset = set of char; str80 = string[80]; suitype = (hearts,diamonds,clubs,spades); ranktype = 0..ranksize; card = record rank: ranktype; suit: suitype end; handtype = array[1..dealsize] of card; {Typed} Const alpha:charset = [' '..'}']; Var deck: array[1..decksize] of card; comp, human, crib: handtype; common: card; i, hscore, cscore: integer; ch: char; xplayx: integer; { Note: The following information is left in this source code for historical purposes. Under version 2.0 of Turbo, just use a Halt command. } (* This is the code for simulating an Exit with TURBO Pascal 1.0 --> Include this instead of Exit(Procname) in the procedure which actually invokes the exit: inline($2A/save/ { LD HL,(save) ; EXIT PROC } $F9); { LD SP,HL } goto procend; --> Include this as the FIRST instruction in the Procedure you wish to eventually exit from: inline($21/0/0/ { LD HL,0000h ; MARK PROC } $39/ { ADD HL,SP } $22/save); { LD (save),HL } David C. Oshel, 15 January 1984, Ames, Iowa *) procedure list_instructions; VAR instructions: text; buffer : string[80]; filename : string[14]; ok : boolean; Procedure get_file( var ok: boolean); begin filename := 'CRIBBAGE.INS'; assign (instructions, filename); {$I-} reset (instructions) {$I+} ; ok := (Ioresult = 0); if not ok then begin writeln (chr(7),chr(7),'Can''t find file ', filename); delay (3000); end; end; procedure print_instructions; VAR ch: char; i: 1..24; begin while NOT Eof(instructions) do begin ClrScr; for i := 1 to 22 do begin readln (instructions, buffer); writeln (buffer); end; writeln; if NOT Eof(instructions) then begin write ('Press any key to continue...'); read (kbd, ch); writeln; end else begin write ('Press any key to resume play.'); read (kbd, ch); writeln; ClrScr; end; end; {while} close (instructions); end; begin {list_instructions} get_file(ok); if ok then print_instructions; end; function getchar:char; var ch,cr,bs,del: char; goodset: charset; bailout: boolean; begin cr:=chr(13); bs:=chr(8); del:=chr(127); goodset:=alpha+[cr,bs,del]; repeat read(kbd,ch); ch:=upcase(ch); bailout:=(ch=chr(3)) or (ch=chr(27)); if eoln then ch:=cr until bailout or (ch in goodset); getchar:=ch; if bailout then halt { v2.0 updated exit } (* inline($2A/xplayx/ { LD HL,(xplayx) ;EXIT PROC } $F9) { LD SP,HL } *) end; {getchar} procedure getln(VAR s:str80); var ch: char; done: boolean; begin done:=false; s:=''; repeat ch:=getchar; if (* bailout or *) (ch=chr(13)) then begin done:=true; writeln end else if ((ch=chr(8)) or (ch=chr(127))) then begin if length(s) > 0 then begin write(chr(8),' ',chr(8)); s:=copy(s,1,length(s)-1) end else s:='' end else begin s:=concat(s,ch); if ch in alpha then write(ch) end until done; end; {getln} procedure addpoints(who:boolean; amount:integer); var winner: boolean; begin if who then begin hscore:=hscore+amount; writeln('You''ve pegged ',hscore,' points.'); winner := (hscore >= winpoints) end else begin cscore:=cscore+amount; writeln('I''ve pegged ',cscore,' points.'); winner := (cscore >= winpoints) end; if winner then halt; inline($2A/xplayx/ { LD HL,(xplayx) ;EXIT PROC } $F9) { LD SP,HL } end; {addpoints} {$I Cribbage.PS2} function getelement:integer; label retry; var irank,isuit: char; rank: ranktype; suit: suitype; which: integer; index: 1..dealsize; many: -5..4; procedure getcard(VAR rankchar:char; VAR suitchar:char); var ch: char; s: str80; i: integer; begin repeat write('__',chr(8),chr(8)); getln(s); rankchar:=' '; suitchar:=' '; for i:=1 to length(s) do begin ch:=s[i]; if (ch in ['A','2'..'9','T','J','Q','K']) then rankchar:=ch; if (ch in ['S','H','D','C']) then suitchar:=ch end; if (rankchar=' ') or (suitchar=' ') then begin writeln(s,'?'); writeln('Suits = S,H,D,C (Spades,Hearts,Diamonds,Clubs)'); writeln('Ranks = A,2,3,4,5,6,7,8,9,T,J,Q,K (Ace is A, 10 is T!)'); writeln('Example: 8D (eight of Diamonds) or TH (ten of Hearts)'); writeln; write('Try again from the start. Which card? ') end until (rankchar<>' ') and (suitchar<>' '); writeln('{{{ ',rankchar,suitchar,' }}}'); end; {getcard} begin retry: getcard(irank,isuit); case irank of 'A': rank:=1; '2','3','4','5','6','7','8','9': rank:=ord(irank)-ord('0'); 'T': rank:=10; 'J': rank:=11; 'Q': rank:=12; 'K': rank:=13 end; {case} case isuit of 'S': suit := spades; 'H': suit := hearts; 'D': suit := diamonds; 'C': suit := clubs end; {case} many:=0; which:=0; for index:=1 to dealsize do begin if human[index].rank = rank then begin many:=many+1; if many>0 then which:=index; if isuit<>' ' then if human[index].suit = suit then many:=-5 end end; if many=0 then begin writeln('What?! No such card exists.'); write('Which card? '); goto retry end; if many>1 then begin writeln('There is more than one ',irank); write('Please be more specific: '); goto retry end; if (many=1) or (many<0) then getelement:=which; end; {getelement} procedure tocrib; var cardnum: 1..dealsize; numgone: 0..1; begin for numgone:=0 to 1 do begin write('Throw which card? [ '); for cardnum:=1 to (dealsize-numgone) do showcard(human[cardnum]); write(' ] '); cardnum:=getelement; crib[numgone+1]:=human[cardnum]; while cardnum <= (dealsize-1) do begin human[cardnum]:=human[cardnum+1]; cardnum:=cardnum+1 end; human[cardnum].rank:=0 end; end; {tocrib} procedure sort(n:integer; var hand:handtype); var touched: boolean; index: 1..dealsize; tmp: card; begin repeat touched:=false; for index:=1 to (n-1) do if hand[index].rank > hand[index+1].rank then begin tmp:=hand[index]; hand[index]:=hand[index+1]; hand[index+1]:=tmp; touched:=true end until not touched; end; {sort} {$I Cribbage.PS3} procedure compcrib; type bestrec = record points: integer; first, second: 1..dealsize end; var tmp: handtype; best: bestrec; i,j,points: integer; function compscore:integer; var index,points: integer; num: 1..dealsize; begin num:=1; for index:=1 to (i-1) do begin tmp[num]:=comp[index]; num:=num+1 end; for index:=(i+1) to (j-1) do begin tmp[num]:=comp[index]; num:=num+1 end; for index:=(j+1) to dealsize do begin tmp[num]:=comp[index]; num:=num+1 end; tmp[5].rank:=0; compscore:=score(tmp); end; {function compscore} begin {compcrib} best.points:=-1; sort(6,comp); for i:=1 to (dealsize-1) do for j:=i+1 to dealsize do begin points:=compscore; if points > best.points then begin best.points:=points; best.first:=i; best.second:=j end end; j:=1; for i:=1 to (best.first-1) do begin tmp[j]:=comp[i]; j:=j+1 end; for i:=(best.first+1) to (best.second-1) do begin tmp[j]:=comp[i]; j:=j+1 end; for i:=(best.second+1) to dealsize do begin tmp[j]:=comp[i]; j:=j+1 end; crib[3]:=comp[best.first]; crib[4]:=comp[best.second]; for i:=1 to playsize do comp[i]:=tmp[i]; end; {compcrib} procedure count(who: boolean); var oldhuman: array[1..4] of card; curcount: integer; humcant, compcant: boolean; cnthand: array[1..8] of card; last: 0..2; cntnum: 1..8; lastcnt: integer; humleft, comleft: 0..playsize; i: -1..playsize; points: integer; function countscore(newcard: card):integer; var return: integer; matched, index: 0..8; begin return:=0; matched:=0; cnthand[cntnum]:=newcard; if cnthand[cntnum].rank > 10 then curcount:=curcount+10 else curcount:=curcount+cnthand[cntnum].rank; if cntnum=1 then begin cntnum:=cntnum+1; countscore:=0 end else begin if (curcount=15) or (curcount=31) then return:=2; index:=cntnum; while index >= 2 do begin if cnthand[index].rank=cnthand[index-1].rank then matched:=matched+1 else index:=1; index:=index-1 end; case matched of 0: ; 1: return:=return+2; 2: return:=return+6; 3: return:=return+12 end; {case} matched:=0; index:=cntnum; while index >= 2 do begin if cnthand[index].rank=(cnthand[index-1].rank -1) then matched:=matched+1 else index:=1; index:=index-1 end; cntnum:=cntnum+1; if matched > 2 then return:=return+matched+1; countscore:=return end; end; {countscore} function humplay:integer; var i,j: integer; begin if human[1].rank > 10 then i:=10 else i:=human[1].rank; if (humleft <= 0) or ((i+curcount) > 31) then begin humcant:=true; humplay:=-1 end else begin last:=1; humcant:=false; if human[2].rank > 10 then i:=10 else i:=human[2].rank; if (humleft=1) or ((i+curcount) > 31) then humplay:=1 else begin j:=0; while j=0 do begin write('Play which card? [ '); for i:=1 to playsize do if human[i].rank <> 0 then showcard(human[i]); write(' ] '); i:=getelement; if human[i].rank > 10 then j:=10 else j:=human[i].rank; if (j+curcount) > 31 then begin writeln('Sorry, that''s more than 31'); j:=0 end end; humplay:=i end end end; {humplay} function complay:integer; var index: 1..playsize; points, best: integer; tmp: 0..10; return: 1..playsize; begin best:=-1; if comp[1].rank > 10 then tmp:=10 else tmp:=comp[1].rank; if (comleft=0) or ((tmp+curcount) > 31) then begin compcant:=true; complay:=-1 end else begin compcant:=false; last:=2; for index:=1 to comleft do begin if comp[index].rank>10 then tmp:=10 else tmp:=comp[index].rank; if (tmp<>0) and ((tmp+curcount) <= 31) then begin points:=countscore(comp[index]); cntnum:=cntnum-1; curcount:=curcount-tmp; if points>best then begin best:=points; return:=index end end end; complay:=return end; end; {complay} begin {count -- at last!} humleft:=playsize; comleft:=playsize; humcant:=false; compcant:=false; last:=0; cntnum:=1; if common.rank=11 then begin if who then begin writeln('I get a point for Nobs!'); addpoints(false,1); end else begin writeln('YOU get a point for Nobs!!'); addpoints(true,1); end end; for curcount:=1 to playsize do oldhuman[curcount]:=human[curcount]; curcount:=0; while (humleft > 0) or (comleft > 0) do begin if who then begin who:=false; i:=humplay; if i>0 then begin write('You played a '); showcard(human[i]); writeln('.'); points:=countscore(human[i]); if points>0 then begin writeln('You got ',points,' points'); addpoints(true,points); end; while i<=(playsize-1) do begin human[i]:=human[i+1]; i:=i+1 end; human[humleft].rank:=0; humleft:=humleft-1 end end; if not who then begin who:=true; i:=complay; if i>0 then begin write('I play a '); showcard(comp[i]); writeln('.'); points:=countscore(comp[i]); if points>0 then begin writeln('I got ',points,' points.'); addpoints(false,points); end; while i <= (playsize-1) do begin comp[i]:=comp[i+1]; i:=i+1 end; comp[comleft].rank:=0; comleft:=comleft-1 end end; if lastcnt<>curcount then writeln('Total is ',curcount,'.'); lastcnt:=curcount; if (humcant and compcant) or ((humleft=0) and (comleft=0)) then begin case last of 0: ; 1: begin writeln('You got a point for last card.'); addpoints(true,1); who:=false end; 2: begin writeln('I got a point for last card.'); addpoints(false,1); who:=true end end; {case} writeln; writeln('Total is now 0.'); writeln; humcant:=false; compcant:=false; last:=0; cntnum:=1; curcount:=0 end; end; for curcount:=1 to playsize do human[curcount]:=oldhuman[curcount]; end; {count} procedure play(who: boolean); var cpoints, hpoints, crbpnts: integer; user:str80; usernum,code: integer; procedure check(num: integer; question: str80); begin repeat write(question); getln(user); val(user,usernum,code); if code<>0 then writeln(user,'??') else writeln; until code=0; if usernum<>num then begin writeln('Unless there''s a bug in my program, you should have taken ',num,' points!'); writeln('I get ',abs(num-usernum),', regardless!'); addpoints(false,abs(num-usernum)); if usernum>num then usernum:=num end; if (usernum > 0) then addpoints(true,usernum); writeln; end; {check} begin {play} inline($21/0/0/ { LD HL,0000h ; MARK PROC } $39/ { ADD HL,SP ; FOR EXIT } $22/xplayx); { LD (xplayx),HL } repeat { forever -- we get out by simulating an Exit(Play) } shuffle; deal; if who then writeln('It''s my crib.') else writeln('It''s your crib.'); sort(6,human); tocrib; compcrib; sort(4,crib); if who then begin repeat write('Cut which card [1-40] ? '); getln(user); val(user,usernum,code); if code<>0 then writeln(user,'??') else writeln until (code=0) and (usernum in [1..40]); common:=deck[usernum+12] end else begin common:=deck[13+random(40)] end; write('The UPCARD is '); showcard(common); writeln; cpoints:=score(comp); hpoints:=score(human); crbpnts:=score(crib); writeln; count(who); writeln; if who then begin write('[ '); for usernum:=1 to playsize do showcard(human[usernum]); write(' ] [ '); showcard(common); writeln(' ]'); check(hpoints,'How many points you got? '); writeln('I''ve got ',cpoints,' points in my hand'); addpoints(false,cpoints); writeln('I have ',crbpnts,' points in my crib'); addpoints(false,crbpnts); end else begin writeln('I''ve got ',cpoints,' in my hand'); addpoints(false,cpoints); writeln; write('[ '); for usernum := 1 to playsize do showcard(human[usernum]); write(' ] [ '); showcard(common); writeln(' ]'); check(hpoints,'How many points in YOUR hand? '); writeln; write('[ '); for usernum:=1 to playsize do showcard(crib[usernum]); write(' ] [ '); showcard(common); writeln(' ]'); check(crbpnts,'How much in the crib? '); end; who:=not who until false end; {play} BEGIN {MAIN} 1: lowvideo; clrscr; writeln(':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'); writeln(':: W E L C O M E TO K I D D I E K R I B B A G E ! ::'); writeln(':: ::'); writeln(':: Adapted from "Cribbage" in APPLE PASCAL GAMES, by Douglas Hergert ::'); writeln(':: and Joseph T. Kalash, pages 301-349. Sybex, 1981. ::'); writeln(':: ::'); writeln(':: TURBO Pascal 1.0, Copyright 1983 by Borland Intl. 1/17/84 DCO ::'); writeln(':: Updated for Turbo Pascal 2.0 1/06/85 ADH ::'); writeln(':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'); writeln; writeln('It''s you against me, kid! Whoever pegs 121 points first wins!'); writeln; write('Do you want instructions? '); read(kbd,ch); writeln(ch); if NOT (ch in ['n','N']) then list_instructions; randomize; makedeck; hscore:=0; cscore:=0; play(random(2)=0); writeln; if cscore>hscore then writeln('Ho Ho!! I peg out and win this game!') else writeln('You pegged out and won the game! Congratulations!'); writeln; writeln; writeln; write('Do you want another game? '); read(kbd,ch); writeln(ch); if ch in ['n','N'] then writeln('OK, see you later!') else goto 1 END.