Path: utzoo!mnetor!uunet!husc6!cmcl2!brl-adm!umd5!purdue!i.cc.purdue.edu!j.cc.purdue.edu!ahh From: ahh@j.cc.purdue.edu (Brent L. Woods) Newsgroups: comp.sources.amiga Subject: hearts--card game of the same name. 1 of 1. Message-ID: <6658@j.cc.purdue.edu> Date: 13 Mar 88 02:33:23 GMT Organization: Co-Moderators Unlimited. Lines: 883 Keywords: tested, shar archive, part 1 of 1. Approved: ahh@j.cc.purdue.edu (Brent Woods) Program Name: hearts Submitted By: griggs%cory.Berkeley.EDU@ucbvax.berkeley.edu (Ted Griggs) Summary: A program that allows you to play the card game "hearts" with three computer opponents. Poster Boy: Brent Woods (ahh@j.cc.purdue.edu) Tested. Shar archive. Part 1 of 1. NOTES: This program came to us, for the most part, without documentation. However, I believe that the only skills one needs to play the game is a knowledge of how to play hearts. The program appears to run just fine, but I can't attest to how closely it plays since I don't know how to play hearts. I'm from Indiana; I learned eucre instead. :-) The following shar file contains some comments from the author, a makefile for Manx, and the source code itself. It compiled under Manx 3.4a without any problems. Brent Woods, Co-Moderator, comp.{sources,binaries}.amiga USENET: ...!j.cc.purdue.edu!ahh ARPANET: ahh@j.cc.purdue.edu BITNET: PODUM@PURCCVM PHONE: +1 (317) 743-8421 USNAIL: 320 Brown St., #406 / West Lafayette, IN 47906 ================================================================ # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # author # Makefile # hearts.c # This archive created: Sat Mar 12 20:56:03 1988 # By: Brent L. Woods (Co-Moderators Unlimited.) cat << \SHAR_EOF > author Here is a small program I wrote one Saturday afternoon a while back. For those of you familiar with the card game "Hearts," this program lets you play against 3 computer players (who also compete among themselves). Alas there are no comments since all I really wanted was to quickly write the code. Likewise, the user interface is not wonderful either - all commands must be typed in uppercase, and when it asks for a letter it really wants a letter, not just a return. Otherwise, the logic gives the program a bit above the average skill level. It plays an interesting game, and, I think, that will provide some entertainment for Hearts enthusiasists. Also, in order to really "win" you should beat all 3 computer players. To compile under MANX: cc hearts.c ln hearts.o -lc -lm Simple. It also compiles under Lattice. SHAR_EOF cat << \SHAR_EOF > Makefile CFLAGS = +pCD -Damiga SOURCES=hearts.c OBJECTS=hearts.o all: $(OBJECTS) ln -o hearts $(OBJECTS) -lcl32 -lml32 .c.o: $(SOURCES) cc $(CFLAGS) $*.c SHAR_EOF cat << \SHAR_EOF > hearts.c #include "stdio.h" #include "exec/types.h" #include "intuition/intuition.h" #define INTSIZ 4 #define LEAD 0 #define FOLLOW 1 #define INTUITION_REV 29 #define HUMAN 3 #define SPADES 2 #define SPQUEEN 36 #define SPKING 37 #define SPACE 38 #define HEARTS 3 #define RUN 26 #define CLUBS 0 #define DIAMONDS 1 #define CLS (char)(0x0c) #define CSI (char)(0x9b) struct IntuitionBase *IntuitionBase, *OpenLibrary(); int ok=TRUE; int start,first,taker,deck[52],out[52],trick[4],score[4],hscr[4]; int hand[4][13]; int outc[4][4]; int dump[4][4]; int pass[4][3]; int outi,outt,outp,outh,seed,turn; ULONG seconds,micros; int wt[53] = { 0, 0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,13,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1, }; char cardname[13]= { '2','3','4','5','6','7','8','9','T','J','Q','K','A', }; char suitname[4]= { 'C','D','S','H', }; int who[4][4]= { {3,1,2,0}, {0,2,3,0}, {1,3,0,0}, {2,0,1,0}, }; scrnx[4]={10,35,60,35,}; scrny[4]={9,3,9,15,}; char dirstr[4][8]= { {"left"}, {"right"}, {"across"}, {"hold"}, }; double rnd() { double num; seed=((25173*seed)+13849) % 20000; if (seed<0) seed=-seed; num=(double)((double)(seed)/20000.0); return(num); } Shuffle(deck) int deck[52]; { int i1,i2,i3,i; for(i=0;i<2000;i++) { i1=(int)(rnd()*52.0); i2=(int)(rnd()*52.0); i3=deck[i1]; deck[i1]=deck[i2]; deck[i2]=i3; } } SortHand(pl) int pl; { int i,j,k; for(i=0;i<13;i++) for(j=i;j<13;j++) if(hand[pl][j]=c)&&(out[i]=c)&&(hand[pl][i]=c)&&(hand[pl][i]card)) card=hand[pl][i]; return(card); } PickLow(pl,suit) int pl,suit; { int c,i,cmax,card=999; c=suit*13; cmax=c+13; for(i=0;i<13;i++) if((hand[pl][i]>=c)&&(hand[pl][i]=c)&&(hand[pl][i]card)) card=hand[pl][i]; return(card); } HighOut(pl,suit) int pl,suit; { int c,i,plr,card=-1; c=suit*13; for(i=0;i<13;i++) for(plr=0;plr<4;plr++) if((hand[plr][i]>=c)&&(hand[plr][i]card)&& (plr!=pl)) card=hand[plr][i]; return(card); } CardsLeft(pl) int pl; { int i,n=0; for(i=0;i<13;i++) if(hand[pl][i]!=-1)n++; return(n); } Desperate(pl) int pl; { int i; for(i=0;i<13;i++) if((hand[pl][i]!=SPQUEEN)&&(hand[pl][i]!=-1))return(hand[pl][i]); return(SPQUEEN); } NumberVoid(pl,suit) int pl,suit; { int i,vd=0; for(i=0;i<4;i++) if((i!=pl)&&(outc[i][suit]))vd++; return(vd); } SafestSuit(pl) int pl; { int i,s=999; for(i=0;i<4;i++) if((SuitPlayed(i)<=s)&&(i!=SPADES)&&(SuitHand(pl,i)>0))s=i; return(s); } BestLead(pl) int pl; { int i; for(i=0;i<4;i++) { if(i!=SPADES) { if(((i==HEARTS)&&(outh))||(i!=HEARTS)) { if(SuitHand(pl,i)!=0) { if((SuitPlayed(i)+SuitHand(pl,i)==12)&&(PickLow(pl,i)HighOut(i))&&(NumberVoid(pl,i)>=2))i=999; if((i!=999)&&(((i==HEARTS)&&(outh))||(i!=HEARTS))) { return(PickHigh(pl,i)); } for(i=0;i<4;i++) if((PickLow(pl,i)=13-SuitPlayed(i))&& (SuitHand(pl,i)+SuitPlayed(i)!=13)&& (((i==HEARTS)&&(outh))||(i!=HEARTS))) { return (PickUnder(pl,i,HighOut(pl,i))); } i=VoidSuit(pl); if((CardsLeft(pl)>1)&&(i!=SPQUEEN)&&(i!=SPACE)&&(i!=SPKING)) return(i); return(Desperate(pl)); } MustFollow(pl) int pl; { int suit; suit=trick[0]/13; if((SuitHand(pl,suit)==0))return(FALSE); return(TRUE); } HandWeight() { int i,w=0; for(i=0;i=c)&&(trick[i]card))card=trick[i]; return(card); } BestFollow(pl) int pl; { int suit,i; suit=trick[0]/13; if(suit==SPADES) { if(((HighTrick()==SPACE)||(HighTrick()==SPKING)) &&(HaveCard(pl,SPQUEEN))) return(SPQUEEN); if((HighTrick()==SPACE)&&(HaveCard(pl,SPKING))) return(SPKING); if((outt==3)&&(PickHigh(pl,SPADES)>SPQUEEN)&& (HighTrick()!=SPQUEEN))return(PickHigh(pl,SPADES)); if(PickUnder(pl,SPADES,SPQUEEN)!=-1)return(PickUnder(pl,SPADES,SPQUEEN)); } if((suit==HEARTS)&&(outp==HighCarder(first))&& (PickHigh(pl,HEARTS)=w) { if(wt[hand[pl][i]+1]>w) { card=hand[pl][i]; w=wt[hand[pl][i]+1]; } else { c=hand[pl][i] % 13; if(c>=card%13) card=hand[pl][i]; } } return(card); } SafeHeart(pl) int pl; { int c; c=PickHigh(pl,HEARTS)%13; if(SuitHand(pl,HEARTS)-1>13-c) return(PickUnder(pl,HEARTS,PickHigh(pl,HEARTS))); return(-1); } VoidSuit(pl) int pl; { int i,suit=999; for(i=0;i<4;i++) if((SuitHand(pl,i)0)&& (SuitPlayed(i)+SuitHand(pl,i)!=13)) if((i!=SPADES)||((i==SPADES)&&(HaveCard(pl,SPQUEEN)==FALSE)))suit=i; if(suit!=999)return(PickHigh(pl,suit)); for(i=3;i>-1;i--) if(SuitHand(pl,i)>0)return(PickLow(pl,i)); return(-1); } BestDump(pl) int pl; { int i; if(outi<4) { i=VoidSuit(pl); if(i!=SPQUEEN) return(i); else for(i=0;i<4;i++) if((SuitHand(pl,i)>0)&&(PickHigh(pl,i)!=SPQUEEN)) return(PickHigh(pl,i)); } if(HaveCard(pl,SPQUEEN))return(SPQUEEN); if((outp!=HighCarder(first))&&(SuitHand(pl,HEARTS)!=0)&& (outp!=999)) return(HighWeight(pl)); if((HaveCard(pl,SPKING))&&(SuitHand(pl,SPADES)<5))return(SPKING); if((HaveCard(pl,SPACE))&&(SuitHand(pl,SPADES)<5))return(SPACE); if((outp<0)&&(HighWeight(pl)!=-1)&&(SuitHand(pl,HEARTS)!=0)) return(HighWeight(pl)); if((SuitHand(pl,HEARTS)!=0)&&(SafeHeart(pl)!=-1))return(SafeHeart(pl)); return(VoidSuit(pl)); } RemoveCard(pl,card) int pl,card; { int i; for(i=0;i<13;i++) if(hand[pl][i]==card)hand[pl][i]=-1; } PlayCard(pl,card) int pl,card; { trick[outt]=card; if(card/13!=trick[0]/13)outc[pl][trick[0]/13]=TRUE; dump[pl][card/13]++; outt++; RemoveCard(pl,card); } HumanCard() { int i,play; char str[8]; do { printf("%c%d%c%d%c",CSI,scrny[HUMAN]+6,';',scrnx[HUMAN]-6,'H'); printf(" Your play: "); scanf("%s",str); printf("%c%d%c%d%c",CSI,scrny[HUMAN]+6,';',scrnx[HUMAN]-6,'H'); printf(" "); if(str[0]=='/') for(i=0;i<4;i++) { DisplayHand(i); } play=ParseCard(str); } while(play==-1); return(play); } DoPlayer(pl,type) int pl,type; { int play; if(pl==HUMAN)DisplayHand(pl); if((outi==0)&&(type==LEAD)) { play=0; } else { if (pl==HUMAN) { play=HumanCard(); } else { if (type==LEAD) { if (SpadeSafe(pl)) { if(PickHigh(pl,SPADES)=c)&&(trick[i]card)) { card=trick[i]; h=i; } c=start; for(i=0;i0)outh=TRUE; for(i=0;i<4;i++) if((HandWeight()>0)&&(outp!=pl)) if(outp==999) outp=pl; else outp=-1; } ScoreHand() { int i,ii; for(i=0;i<4;i++) if(hscr[i]==RUN) { for(ii=0;ii<4;ii++) if(i!=ii)score[ii]+=RUN; } else { score[i]+=hscr[i]; } for(i=0;i<4;i++) { printf("%c%d%c%d%c",CSI,scrny[i],';',scrnx[i],'H'); printf("Player %d score: %d\n",i,score[i]); } for(i=0;i<4;i++) if(score[i]>99)exit(TRUE); } PassCard(pl) int pl; { if(SpadeSafe(pl)==FALSE)return(PickHigh(pl,SPADES)); if((pass[pl][0]