home *** CD-ROM | disk | FTP | other *** search
- /* AUTOTURN.C
- * This contains the functions for the program to decide what to do
- */
-
- #include <proto/all.h>
- #include <stdlib.h>
- #include <math.h>
- #include <intuition/intuition.h>
- #include <string.h>
- #include "defns.h"
- #include "externs.h"
-
-
- VOID autoturn(cp,np,pp)
- struct playerinfo *cp,*np,*pp;
- {
- register USHORT i,n,p,takefup,cc=cp->nchld,gtemp;
- register struct condset *s;
- char buf[3];
- /* deselect fup,fdp*/
- gtemp = RemoveGList(wind,&stdgad[FUPG],2);
- RefreshGList(&stdgad[FUPG],wind,NULL,2);
- stdgad[FUPG].Flags &= ~SELECTED;
- stdgad[FDPG].Flags &= ~SELECTED;
- TXTOUT(180,21,1,0,cp->name);
- TXTOUT(MESX,MESY,7,0,"... is thinking ...");
- cp->hand[0] = fup[fuptc]; /*test how well next card from fup integrates with other cards*/
- buildsets(cp);
- for(i=0;i<=ncs;i++) score(&cs[i],cp); /*initial scores for sets*/
- n=mutexcl(cp); /*generate non-mutually exclusive combination of submissible sets*/
- if(!n) /*fup card not very useful, and not submissible*/
- { /*try fdp card instead*/
- TXTOUT(MESX,MESY,7,0,"Takes the facedown card. ");
- takefup=0;
- maintainmem(cp,pp,np,fup[fuptc],GONEPAST);
- maintainmem(cp,pp,np,fup[fuptc],CURRPLRDROPD);
- cp->hand[0]=NEXTFDP;
- cp->mem[CARD2(cp->hand[0])] |= CURRPLRHOLDS;
- buildsets(cp);
- for(i=0;i<=ncs;i++) score(&cs[i],cp);
- mutexcl(cp);
- }
- else
- {
- takefup=1;
- TXTOUT(MESX,MESY,7,0,"Takes the faceup card. ");
- NEXTFUP; /*fup card will be used so remove it from pack*/
- maintainmem(cp,pp,np,cp->hand[0],CURRPLRHOLDS);
- }
- for(p=3;p;p--)
- {
- for(n=0;n<=ncs;n++) if(selcs[n].ns) /*some cards in set*/
- {
- s=&selcs[n];
- if((p==3 && s->ns==3 || p==2) && s->type&SUB) autosubset(s,cp); /*submit set*/
- else if(p==1 && s->type&ADD) autoaddset(s,cp); /*add to set*/
- }
- }
- /*now drop card with lowest score*/
- for(i=0,p=60000,n=500;i<=cp->nchld;i++)
- if(!ISNUL(cp->hand[i]) && (cdsc[i]<p || n==500) && (i!=0 || !takefup)) p=cdsc[n=i]; /*new lowest*/
- PUTFUP(cp->hand[n]);
- DRAWFUP;
- maintainmem(cp,pp,np,cp->hand[n],CURRPLRDROPD);
- cp->hand[n]=nulcard;
- if(!ISNUL(cp->hand[0]))
- { /*copy selected card to body of hand*/
- for(i=1;i<=cp->nchld && !ISNUL(cp->hand[i]);i++);
- cp->hand[i]=cp->hand[0];
- }
- compacthand(cp->hand,&cp->nchld);
- REMHAND(cp);
- if(cp->viewcard) disphand(cp); else hidecards(cp);
- cc-=cp->nchld;
- if(cc)
- {
- sortdispset();
- stci_d(buf,cc);
- TXTOUT(MESX+25*8,MESY,7,0,buf);
- TXTOUT(MESX+27*8,MESY,7,0,"submitted - Hit continue");
- }
- else
- {
- TXTOUT(MESX+25*8,MESY,7,0,"None submitted - Hit continue");
- }
- if(!contplay) WAITCONT;
- AddGList(wind,&stdgad[FUPG],gtemp,2,NULL);
- TXTOUT(MESX,MESY,7,0," ");
- TXTOUT(180,21,1,0," ");
- }
-
- VOID autosubset(struct condset *s,struct playerinfo *p)
- {
- register struct card *t=s->set;
- register USHORT i,d,n,samesuit=1,samenum=1;
- for(i=0,n=0;i<=p->nchld;i++) if(!ISNUL(p->hand[i])) n++;
- d=s->ns;
- if(d==n+1)
- {/* ensure at least one card will be left when finished*/
- for(i=0;i<=d;i++) if(CDEQU(p->hand[i],t[d])) s->uc&=~(1<<i);
- d--;
- }
- for(i=2;i<=d;i++)
- { /*final check on validity of set*/
- if(t[i-1].n!=t[i].n) samenum=0;
- if(t[i-1].s!=t[i].s) samesuit=0;
- }
- if(d<3 || !(samesuit || samenum)) return; /*rejected submission attempt*/
- if(samesuit)
- { /*check set is continuous*/
- for(i=2;i<=d;i++)
- if((t[i-1].n!=t[i].n-1) && !(t[i-1].n==KING && t[i].n==ACE)) return; /*rejected*/
- }
- n=s->uc<<1;
- for(i=0;i<=p->nchld;i++) if((n>>=1)&1) p->hand[i]=nulcard; /*this card about to be submitted*/
- for(i=0;i<=5 && fupset[i]->ncard;i++); /*find empty set*/
- fupset[i]->ncard=d;
- if(samesuit) for(n=1;n<=d;n++)
- {
- fupset[i]->cards[n+t[1].n-1]=t[n];
- maintainmem(NULL,NULL,NULL,t[n],INFUPSET);
- }
- else for(n=1;n<=d;n++)
- {
- fupset[i]->cards[n]=t[n];
- maintainmem(NULL,NULL,NULL,t[n],INFUPSET);
- }
- s->ns=s->nd=0; /*remove all cards from set*/
- }
-
- VOID autoaddset(struct condset *s,struct playerinfo *p)
- {
- register struct card *fsc,*phc;
- register USHORT *fsn,phn,i,j,f,l,used;
- fsc=fupset[s->addtoset]->cards;
- fsn=&fupset[s->addtoset]->ncard;
- phc=p->hand;
- phn=p->nchld;
- for(f=1;ISNUL(fsc[f]);f++); /*find first card of set*/
- l=f+(*fsn)-1;
- if(fsc[f].s==fsc[f+1].s && s->type&SUITSET) /*same suit*/
- {
- if(s->type&TOSTART)
- {
- if(s->set[1].n==fsc[f].n-1 && s->set[1].s==fsc[f].s)
- {
- for(i=0,used=1;i<=phn;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
- {
- phc[i]=nulcard;
- used=0; /*card has not already been used*/
- }
- if(!used)
- {
- fsc[--f]=s->set[1];
- maintainmem(NULL,NULL,NULL,s->set[1],INFUPSET);
- (*fsn)++;
- for(j=1;j<=s->nd;j++) if(s->dep[j].n==fsc[f].n-1 && s->dep[j].s==fsc[f].s)
- {
- for(i=0,used=1;i<=phn;i++) if(CDEQU(s->dep[j],phc[i]) && !ISNUL(s->dep[j]))
- {
- phc[i]=nulcard;
- used=0; /*card not already used*/
- }
- if(!used)
- {
- fsc[--f]=s->dep[j];
- maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
- (*fsn)++;
- }
- else
- {/*exit function - no more additions possible*/
- s->nd=s->ns=0;
- return;
- }
- }
- }
- else
- {/*exit function - no more additions possible*/
- s->nd=s->ns=0;
- return;
- }
- }
- }
- else if(s->type&TOEND)
- {
- if(((s->set[1].n==fsc[l].n+1 && s->set[1].n!=2) || (fsc[l].n==KING && s->set[1].n==ACE))
- && s->set[1].s==fsc[l].s)
- {
- for(i=0,used=1;i<=phn;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
- {
- phc[i]=nulcard;
- used=0; /*card not already used*/
- }
- if(!used)
- {
- fsc[++l]=s->set[1];
- maintainmem(NULL,NULL,NULL,s->set[1],INFUPSET);
- (*fsn)++;
- for(j=1;j<=s->nd;j++) if(((s->dep[j].n==fsc[l].n+1 && s->dep[j].n!=2) || (fsc[l].n==KING && s->dep[j].n==ACE))
- && s->dep[j].s==fsc[l].s)
- {
- for(i=0,used=1;i<=phn;i++) if(CDEQU(s->dep[j],phc[i]) && !ISNUL(s->dep[j]))
- {
- phc[i]=nulcard;
- used=0; /*card not already used*/
- }
- if(!used)
- {
- fsc[++l]=s->dep[j];
- maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
- (*fsn)++;
- }
- else
- {/*exit function - no more additions possible*/
- s->nd=s->ns=0;
- return;
- }
- }
- }
- else
- {/*exit function - no more additions possible*/
- s->nd=s->ns=0;
- return;
- }
- }
- }
- }
- else if(fsc[f].n==fsc[f+1].n && s->set[1].n==fsc[f].n && s->type&NUMSET && *fsn==3)
- {
- for(i=0,used=1;i<=phn && used;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
- {
- phc[i]=nulcard;
- used=0; /*card not already used*/
- fsc[++l]=s->set[1];
- maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
- (*fsn)++;
- }
- }
- s->ns=s->nd=0; /*remove all cards from set*/
- }
-
-
-
- VOID buildsets(struct playerinfo *p)
- {
- register USHORT i,n,nchld=p->nchld,s;
- register struct card *h=p->hand;
- USHORT nconc,setfound; /*next condensed set, number of consecutive cards*/
- for(i=0;i<=3;i++)
- { /*initialise arrays*/
- for(n=0;n<=15;n++) ss[i].c[n] = nulcard;
- ss[i].nc=0;
- }
- for(i=0;i<=32;i++)
- {
- cs[i].type = NOTSET;
- cs[i].ns = cs[i].nd = cs[i].score = cs[i].ig = cs[i].addtoset = cs[i].uc= 0;
- for(n=0;n<=8;n++) cs[i].set[n]=cs[i].dep[n]=nulcard;
- }
- for(i=0;i<=13;i++) ns[i].nc=0;
-
- for(i=0;i<=nchld;i++)
- { /*separate hand into sets*/
- ns[h[i].n].c[++ns[h[i].n].nc]=h[i]; /*add card to numset*/
- ss[h[i].s].c[h[i].n]=h[i]; /*add card to suit set*/
- if(h[i].n==ACE) ss[h[i].s].c[14]=h[i];
- ss[h[i].s].nc++;
- }
- /*card ss[s].c[n] has suit s and number n.*/
- ncs=0;
- for(i=0;i<=3;i++)
- if(ss[i].nc)
- { /*convert suit set to condensed form*/
- nconc=setfound=0;
- for(n=1;n<=15;n++)
- { /*look for submissible sets*/
- if(!ISNUL(ss[i].c[n])) nconc++;
- else
- {
- if(nconc>=3)
- { /*submissible set*/
- if(setfound) ncs++; /*current set already has submissible subset*/
- while(nconc) cs[ncs].set[++cs[ncs].ns]=ss[i].c[n-nconc--];
- setfound=1; /*current record now has a submissible set*/
- cs[ncs].type = SUITSET | SUB;
- }
- else
- {
- if((cs[ncs].nd || cs[ncs].ns) &&
- (n-nconc)-max(cs[ncs].dep[cs[ncs].nd].n,cs[ncs].set[cs[ncs].ns].n)>=(p->nchld<4?p->nchld:4))
- {
- ncs++;
- setfound=0; /*no set in current record*/
- }
- while(nconc) cs[ncs].dep[++cs[ncs].nd]=ss[i].c[n-nconc--];
- cs[ncs].type = SUITSET | SUB;
- }
- }
- }
- if(cs[ncs].ns || cs[ncs].nd) cs[ncs++].type = SUITSET | SUB;
- else cs[ncs].ns=cs[ncs].nd=0;
- }
- cs[ncs].type = NOTSET;
-
- /*detect cards which can be added to existing suitsets*/
- for(i=0;i<=3;i++)
- {
- if(ss[i].nc) /*check some cards in set*/
- {
- for(n=1;n<=14;n++)
- {
- if(!ISNUL(ss[i].c[n]))
- {
- setfound=0;
- for(s=0;s<=5 && !setfound && fupset[s]->ncard;s++)
- {
- if(ISNUL(fupset[s]->cards[n]))
- {
- if(fupset[s]->cards[n-1].n==n-1 && !ISNUL(fupset[s]->cards[n-1])
- && fupset[s]->cards[n-1].s==i && fupset[s]->cards[n-2].s==i)
- { /*can add after set s*/
- if(cs[ncs].type!=NOTSET) ncs++; /*current set already used*/
- else cs[ncs].ns=cs[ncs].nd=0; /*current set no good - throw it away*/
- cs[ncs].set[++cs[ncs].ns]=ss[i].c[n];
- cs[ncs].addtoset=s;
- cs[ncs].type = ADD | SUITSET | TOEND;
- setfound=1;
- }
- else if(fupset[s]->cards[n+1].n==n+1 && fupset[s]->cards[n+1].s==i && fupset[s]->cards[n+2].s==i)
- { /*can add before set s*/
- if(cs[ncs].type!=NOTSET || (cs[ncs].nd && cs[ncs].dep[1].s!=ss[i].c[n].s)) ncs++;
- cs[ncs].set[++cs[ncs].ns]=ss[i].c[n];
- cs[ncs].addtoset=s;
- cs[ncs].type= ADD | SUITSET | TOSTART;
- setfound=1;
- ncs++; /*move to new set*/
- }
- }
- }
- if(!setfound)
- { /*add to dependants*/
- if((cs[ncs].ns || cs[ncs].nd)
- && ((n-max(cs[ncs].set[cs[ncs].ns].n,cs[ncs].dep[cs[ncs].nd].n))>=4)
- || (ss[i].c[n].s!=(cs[ncs].ns==0?cs[ncs].dep[1].s:cs[ncs].set[1].s)))
- { /*start new set*/
- if(cs[ncs].type!=NOTSET) ncs++;
- else cs[ncs].ns=cs[ncs].nd=0;
- }
- cs[ncs].dep[++cs[ncs].nd]=ss[i].c[n];
- }
- }
- }
- }
- }
- if(cs[ncs].ns) ncs++;
- else cs[ncs].nd=0;
-
- /*copy numsets to condensed sets*/
- for(i=1;i<=13;i++)
- {
- if(ns[i].nc==1)
- { /*can card be added to existing set*/
- setfound=0;
- for(s=0;s<=5 && !setfound && fupset[s]->ncard;s++)
- if(fupset[s]->cards[1].n==ns[i].c[1].n && fupset[s]->cards[2].n==ns[i].c[1].n)
- { /*can add card this set*/
- cs[ncs].addtoset=s;
- cs[ncs].set[++cs[ncs].ns]=ns[i].c[1];
- cs[ncs++].type= ADD | NUMSET;
- setfound=1;
- }
- if(!setfound)
- {
- cs[ncs].dep[++cs[ncs].nd]=ns[i].c[1];
- cs[ncs++].type = SUB | NUMSET;
- }
- }
- else if(ns[i].nc==2)
- {
- cs[ncs].dep[1]=ns[i].c[1];
- cs[ncs].dep[2]=ns[i].c[2];
- cs[ncs].type = NUMSET | SUB;
- cs[ncs++].nd=2;
- }
- else if(ns[i].nc>=3)
- {
- for(n=1;n<=ns[i].nc;n++) cs[ncs].set[n]=ns[i].c[n];
- cs[ncs].type = NUMSET | SUB;
- cs[ncs++].ns=ns[i].nc;
- }
- }
- for(i=0;i<=ncs;i++)
- for(n=1;n<=cs[i].ns;n++)
- for(s=setfound=0;s<=nchld && !setfound;s++) if(setfound=CDEQU(cs[i].set[n],h[s])) cs[i].uc|=(1<<s);
- }
-
- VOID score(struct condset *c,struct playerinfo *p)
- {
- register USHORT i,n,j,last,m,s;
- USHORT gap,next;
- struct card t[5];
- c->score = 0;
- if(c->type&NUMSET)
- {
- for(n=1;n<=c->ns;n++) c->score+=(c->set[n].n*8+(n>1?1100:0))+300;
- for(n=1;n<=c->nd;n++) c->score+=((15-c->dep[n].n)*4+(n>1?1300:0));
- for(n=1;n<=4;n++) t[n]=nulcard;
- if(c->nd)
- {
- s=c->dep[1].n;
- for(n=1;n<=c->nd;n++) t[c->dep[n].s]=c->dep[n];
- }
- else
- {
- s=c->set[1].n;
- for(n=1;n<=c->ns;n++) t[c->set[n].s]=c->set[n];
- }
- for(n=1;n<=4;n++) if(ISNUL(t[n]))
- {
- m=p->mem[CARD(s,n)];
- if(!(m&INFUPSET))
- {
- c->score+=100+15-s;
- if(!(m&NEXTPLRHOLDS)) c->score+=70;
- if(!(m&PREVPLRHOLDS)) c->score+=40;
- if(!(m&GONEPAST)) c->score+=100;
- if(m&(NEXTPLRDROPD | PREVPLRDROPD)) c->score+=100;
- }
- }
- else c->score+=(16-t[n].n)*4;
- }
- else /*score suitset*/
- {
- if(ISNUL(c->set[1])) last=c->dep[1].n;
- else if(ISNUL(c->dep[1])) last=c->set[1].n;
- else last=min(c->dep[1].n,c->set[1].n);
- if(c->type&SUB)
- {
- c->score+=c->ns*500+c->nd*100;
- for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
- {
- if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
- {
- if(c->set[i].n==ACE && i>1) c->score+=(last==KING?1200:(7-(13-last))*130)+15*9+100;
- else if(c->set[i].n!=last)
- c->score+=(c->set[i].n-last==1?1200:(6-(c->set[i].n-last-1))*100)+c->set[i].n*9+100;
- else c->score+=(15-last)*9+100;
- last=c->set[i++].n;
- }
- else
- {
- if(c->dep[n].n==ACE && n>1) c->score+=(last==KING?1200:(6-(13-last))*110)+15*5+80;
- else if(c->dep[n].n!=last)
- c->score+=(c->dep[n].n-last==1?1200:(6-(c->dep[n].n-last-1))*90)+(15-c->dep[n].n)*5+80;
- else c->score+=(15-last)*5+80;
- last=c->dep[n++].n;
- }
- }
- }
- else if(c->type&ADD)
- {
- for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
- {
- if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
- {
- if(c->set[i].n==ACE && i>1) next = 14;
- else next=c->set[i].n;
- if(last!=c->set[i].n)
- c->score+=(next-last==1?1200:(7-(next-last-1))*100)+c->set[i].n*9+100;
- else c->score+=(15-last)*9+100;
- last=c->set[i++].n;
- }
- else
- {
- if(c->dep[n].n==ACE && i>1) next = 14;
- else next=c->dep[n].n;
- if(next-last==1) c->score+=1200+c->dep[n].n*8+80;
- else if(last!=next) c->score+=(6-(next-last-1))*90+c->dep[n].n*5+80;
- else c->score+=(15-last)*5+80;
- last=c->dep[n++].n;
- }
- }
- }
-
- if(!ISNUL(c->set[1])) s=c->set[1].s;
- else s=c->dep[1].s;
- if(ISNUL(c->set[1])) last=c->dep[1].n;
- else if(ISNUL(c->dep[1])) last=c->set[1].n;
- else last=min(c->dep[1].n,c->set[1].n);
- for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
- {
- if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
- {
- gap=c->set[i].n-last-1;
- next=c->set[i++].n;
- }
- else
- {
- gap=c->dep[n].n-last-1;
- next=c->dep[n++].n;
- }
- for(j=last+1;j<next;j++)
- {
- m=p->mem[CARD(s,n)];
- if(!(m&INFUPSET))
- {
- c->score+=90/gap+15-s;
- if(!(m&NEXTPLRHOLDS)) c->score+=70/gap;
- if(!(m&PREVPLRHOLDS)) c->score+=70/gap;
- if(!(m&GONEPAST)) c->score+=90/gap;
- if(m&(NEXTPLRDROPD | PREVPLRDROPD)) c->score+=90/gap;
- }
- last=next;
- }
- }
- }
- if(c->type&SUB && p->nchld<=2) c->score=0; /*less than useless*/
- if(c->type&ADD && p->nchld<=2) c->score+=15000; /*ensure high score for addable sets when submission is impossible*/
- if(c->type&NUMSET && c->nd==2) c->score+=500;
- c->score+=c->ns*600;
- }
-
- USHORT mutexcl(struct playerinfo *p)
- {
- register USHORT i,j,k,w,x;
- long l;
- struct card c,*s;
- USHORT bias, /*toward 1:numset, 2:suitset 3:set with higher score*/
- pass, /*number of passes to be made with different biases*/
- nxsts, /*next start set*/
- psperbias, /*number of passes to be made for each bias at different start sets*/
- best=0,pn,chng,currst,pm,sc,cdscs[53];
- if(p->level==1)
- {/*easiest level*/
- bias=1; pass=1; nxsts=0; psperbias=1;
- }
- else if(p->level==1)
- {/*best level*/
- bias=1; pass=3; nxsts=0; psperbias=ncs;
- }
- else if(p->level<=5)
- {/*fairly easy*/
- l=rand();
- bias=1;
- pass=1;
- if((nxsts=l&31)>ncs) nxsts=ncs;
- if((psperbias=(l>>5&31)+1)>ncs>>1 && ncs!=1) psperbias=ncs>>1;
- }
- else
- {/*fairly good play*/
- l=rand();
- bias=1;
- pass=3;
- if((nxsts=l&31)>ncs) nxsts=ncs;
- if((psperbias=(l>>5&31)+1)>ncs) psperbias=ncs;
- }
-
- while(pass--)
- {
- for(currst=nxsts,pn=psperbias,chng=1;pn && chng;pn--)
- {
- chng=0; /*change made flag*/
- for(i=0;i<=ncs;i++) testcs[i]=cs[i];
- for(i=currst,pm=0;!pm || i!=currst;i=i>=ncs?0:i+1)
- {
- pm=1;
- for(j=(i>=ncs?0:i+1);j!=i;j=j>=ncs?0:j+1)
- {
- if(w=testcs[i].uc&testcs[j].uc)
- {/*collision between sets*/
- w<<=1;k=0;
- while(w)
- {
- while(!((w>>=1)&1) && w) k++;
- c=p->hand[k]; /*card causing collision*/
- if(w && ((bias==1 && testcs[i].type&NUMSET && testcs[j].type&SUITSET)
- || (bias==2 && testcs[i].score >= testcs[j].score)
- || (bias==3 && testcs[i].score < testcs[j].score)))
- { /*reduce set i*/
- chng=1;
- for(x=1;!CDEQU(testcs[i].set[x],c) && x<=testcs[i].ns;x++);
- testcs[i].set[x]=nulcard;
- if(c.n==ACE && testcs[i].set[testcs[i].ns].n==ACE) testcs[i].set[testcs[i].ns]=nulcard;
- compacthand(testcs[i].set,&testcs[i].ns);
- checksets(&testcs[i],p);
- score(&testcs[i],p);
- }
- else if(w)
- { /*reduce set j*/
- chng=1;
- for(x=1;!CDEQU(testcs[j].set[x],c) && x<=testcs[j].ns;x++);
- testcs[j].set[x]=nulcard;
- if(c.n==ACE && testcs[j].set[testcs[j].ns].n==ACE) testcs[j].set[testcs[j].ns]=nulcard;
- compacthand(testcs[j].set,&testcs[j].ns);
- checksets(&testcs[j],p);
- score(&testcs[j],p);
- }
- }
- }
- }
- }
- for(j=0,sc=0;j<=ncs;j++) sc+=testcs[j].score;
- if(sc>best)
- { /*new best set*/
- best=sc;
- for(j=0;j<=ncs;j++) selcs[j]=testcs[j];
- }
- if(currst==ncs) currst=0; else currst++;
- if(bias==3) bias=1; else bias++;
- }
- }
-
- for(j=0;j<=p->nchld;j++) cdscs[CARD2(p->hand[j])]=0; /*zeroise scores of player cards*/
- /* The section below prevents the autoplayer being left with just two
- * cards, which cannot be submitted (min 3), and meaning it must wait
- * for cards to arrive which can be added to existing sets, which the
- * other players will also be looking out for.
- * NB. this will only reduce submissions by one card, and only where
- * permissible.
- */
- /*work out number of cards to be submitted by this combination of sets*/
- for(i=0,w=0;i<=ncs;i++) if(selcs[i].type&ADD)
- {
- w++; /*at least one card can be submitted*/
- for(j=1,x=selcs[i].set[1].n;j<=selcs[i].nd;j++) if(x+1==selcs[i].dep[j].n || x-1==selcs[i].dep[j].n)
- {
- w++; x=selcs[i].dep[j].n;
- }
- }
- else if(selcs[i].type&SUB) w+=selcs[i].ns;
- if(p->nchld-w==2) /*retain one further card to enable later submissions*/
- {
- for(i=0,w=0;i<=ncs && !w;i++) if(selcs[i].type&SUB && selcs[i].ns>=4)
- {/*prevent submission of one of the cards of the set*/
- for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
- selcs[i].dep[1]=selcs[i].set[selcs[i].ns--];
- selcs[i].nd++;
- w=1; /*finished*/
- cdscs[CARD2(selcs[i].dep[1])]+=20000; /*ensure this card retained*/
- }
- else if(selcs[i].type&ADD)
- {
- if(selcs[i].type&NUMSET || (selcs[i].type&SUITSET
- && selcs[i].set[1].n!=selcs[i].dep[1].n-1 && selcs[i].set[1].n!=selcs[i].dep[1].n+1))
- {/* only one addable card - remove it to the dep list*/
- for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
- selcs[i].dep[1]=selcs[i].set[1];
- selcs[i].set[1]=nulcard;
- selcs[i].ns--; selcs[i].nd++;
- selcs[i].type&= ~ADD;
- selcs[i].type|= SUB;
- w=1;
- cdscs[CARD2(selcs[i].dep[1])]+=20000; /*ensure this card retained*/
- }
- else
- {/* reduce number of addable cards of this set to just one*/
- for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
- selcs[i].dep[1]=nulcard;
- selcs[i].nd++;
- cdscs[CARD2(selcs[i].dep[2])]+=20000; /*ensure this card retained*/
- w=1;
- }
- }
- }
-
- /*generate card scores here*/
- for(i=0;i<=ncs;i++)
- {
- if(selcs[i].type&SUITSET)
- {
- if(selcs[i].ns)
- {
- for(j=1;j<=selcs[i].ns;j++) cdscs[CARD2(selcs[i].set[j])]+=selcs[i].score;
- for(j=1;j<=selcs[i].nd;j++)
- {
- w=selcs[i].dep[j-1].n;x=selcs[i].dep[j].n;
- k=selcs[i].dep[j+1].n;
- if(selcs[i].dep[j].n<selcs[i].set[1].n)
- cdscs[CARD2(selcs[i].dep[j])]+=(selcs[i].score*j)/22 +
- ((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/30 +
- ((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/30;
-
- else cdscs[CARD2(selcs[i].dep[j])]+=(selcs[i].score*(9-j))/22 +
- ((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/30 +
- ((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/30;
- }
- }
- else /*no submissible cards*/
- {
- for(j=1;j<=selcs[i].nd;j++)
- {
- w=selcs[i].dep[j-1].n;x=selcs[i].dep[j].n;
- k=selcs[i].dep[j+1].n;
- cdscs[CARD2(selcs[i].dep[j])]+=selcs[i].score +
- ((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/12 +
- ((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/12;
- }
- }
- }
- else /*numset*/
- {
- for(j=1;j<=selcs[i].ns;j++) cdscs[CARD2(selcs[i].set[j])]+=selcs[i].score*(j==4?(1/2):1);
- for(j=1;j<=selcs[i].nd;j++) cdscs[CARD2(selcs[i].dep[j])]+=selcs[i].score*(j==4?(1/2):1);
- }
- }
-
- for(j=0;j<=p->nchld;j++) cdsc[j]=cdscs[CARD2(p->hand[j])];
- l=rand();
- if(p->level==1) return (USHORT)(l&1);
- else if(p->level<=9)
- {
- if(p->level<(l%11)+1) return (USHORT)(l&256);
- }
-
- /* the next loop checks to see if any cards can be added to an existing
- * set after the acquisition of one further card, a facility which was
- * overlooked in the original program design
- */
- for(i=0;i<=p->nchld;i++)
- {
- for(j=0;j<5 && fupset[j]->ncard;j++)
- {
- s=fupset[j]->cards;
- for(k=1;k<=13 && ISNUL(s[k]);k++);
- w=k+fupset[j]->ncard-1; /*last card*/
- if(s[k].s==s[k+1].s && s[k].s==p->hand[i].s) /*suitset*/
- {
- x=p->hand[i].n;
- if(x==s[k].n-2 && !(p->mem[CARD(x+1,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
- if(x==s[w].n+2 && !(p->mem[CARD(x-1,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
- if(x==ACE && s[w].n==QUEEN && !(p->mem[CARD(KING,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
- }
- }
- }
-
- if(p->nchld==1)
- {
- for(i=0;i<=ncs;i++) if(selcs[i].type&ADD && CDEQU(selcs[i].set[1],p->hand[0])) return 1;
- return 0; /* last card not addable, so recommend to ignore it*/
- }
-
- /* the section below causes the last selected card to be dropped if it
- * only belongs to one set of two cards, and the other member is about
- * to be dropped
- */
- j=cdsc[k=0];
- for(i=1;i<=p->nchld;i++) if(cdsc[i]<j) j=cdsc[k=i];
- if(k!=0 && cdsc[0]>1690 /* || cdsc[0]>2200*/) return 1; /*keep last selected card*/
- else
- {
- for(i=w=x=0;i<=ncs;i++)
- {
- for(j=1;j<=selcs[i].nd;j++) if(CDEQU(selcs[i].dep[j],p->hand[0]) && selcs[i].nd==2 && !selcs[i].ns)
- {
- w++;
- x=i;
- }
- }
- if(w==1)
- {
- if(CDEQU(selcs[x].dep[1],p->hand[0])) j=2; else j=1;
- for(i=0;i<=p->nchld;i++) if(CDEQU(p->hand[i],selcs[x].dep[j]) && i==k) return 0; /*drop card*/
- }
- }
-
- for(j=0;j<=ncs;j++) if(selcs[j].uc&1) return 1; /* last chosen card being submitted in set*/
- return 0; /*last selected card not being submitted in a set,
- and not within two of an adjacent card*/
- }
-
-
- VOID checksets(struct condset *c,struct playerinfo *p)
- { /*reconstruct reduced set*/
- register USHORT i,n=0,nconc,setfound;
- struct card t[16];
- for(i=0;i<=15;i++) t[i]=nulcard;
- if(c->type&SUITSET && c->type&SUB)
- {
- for(i=1;i<=c->ns;i++) if(c->set[i].n==ACE && i>1) t[14]=c->set[i];
- else t[c->set[i].n]=c->set[i];
- for(i=1;i<=c->nd;i++) if(c->dep[i].n==ACE && i>1) t[14]=c->dep[i];
- else t[c->dep[i].n]=c->dep[i];
- n=c->nd+c->ns;
- nconc=0;
- c->nd=c->ns=0;
- for(i=1;i<=15;i++)
- {
- if(!ISNUL(t[i])) nconc++;
- else
- {
- if(nconc>=3) while(nconc) c->set[++c->ns]=t[i-nconc--];
- else while(nconc) c->dep[++c->nd]=t[i-nconc--];
- }
- }
- }
- else if(c->type&NUMSET && c->type&SUB)
- {
- if(c->ns==2 || c->ns==1) for(c->nd=0;c->ns;)c->dep[++c->nd]=c->set[c->ns--];
- }
- if(!(c->ns || c->nd)) c->type=NOTSET; /*no cards in this set*/
- else for(n=1,c->uc=0;n<=c->ns;n++)
- for(i=setfound=0;i<=p->nchld && !setfound;i++) if(setfound=CDEQU(c->set[n],p->hand[i])) c->uc|=(1<<i);
-
- }
-