# Go Fish/Unicon

This is a two player version of Go Fish with a 9 card deal out where the human player always goes first. It is assumed that everyone will know what cards are booked out and what cards are fished. The computer acts as arbitrator so there is no way to lie, cheat, or steal.

Also, this program uses a simplified deck (no suits but four of each card) similar to some children's specialty decks.

The computer strategy relies on the following facts and public knowledge which are kept for each player in the player's public field. Public is a table by rank. A value of -1 indicates unknown state, any other value is the known number of cards.

• a. Public counts can be adjusted when a player makes a book.
• b. If the opponent asks for a card an unknown can be changed to a 1 as they have at least one card of this rank.
• c. When one or more cards are surrendered during fishing , the public counts of both players can be adjusted accordingly.
• d. A card drawn requires that counts of 0 be set to unknown unless the cards were booked out.

Strategy:

• (i) Request any known cases of 3 of a kind first.
• (ii) Request from other known cards second. The request should be in proportion to what you do not hold in your hand. That is if you have 1 J, you should have 3 chances of requesting it.
• (iii) Guess. This should also be in inverse proportion to what you hold in your hand.
` link printf,strings global GF                                                   # global game staterecord GFgame(ranks,suits,dealt,booked,deck,HP,AI)          # game recordrecord GFplayer(name,score,ask,hand,public)                 # player record       procedure main()                                #: 2 player go-fish human vs. AI   GF := GFgame("23456789TJQKA", 4, 9, "")            # game parameters   GF.deck := scramble(repl(GF.ranks,GF.suits))       # shuffled deck   GF.HP   := GFplayer("Human"   ,0,HPaskAI,"",table(-1))    # Human player   GF.AI   := GFplayer("Computer",0,AIaskHP,"",table(-1))    # Computer player   every 1 to GF.dealt do DrawCard(GF.HP) & DrawCard(GF.AI)  # Deal cards    printf("Go fish.\nYou vs. the computer - your turn first:\n")    while PlayerTurn(GF.HP,GF.AI) & PlayerTurn(GF.AI,GF.HP)   # play until done   printf("Final score:  Computer=%d, Human=%d - %s wins.\n",          GF.AI.score,GF.HP.score,          if GF.HP.score > GF.AI.score then GF.HP.name else GF.AI.name)end procedure PlayerTurn(player,opponent)           #: Player's turn                        if *GF.booked < *GF.ranks then {                   # play until done      ifbook(player)                                  # made a book ?         while PlayerFishes(player,opponent)             # fish while successful      return                                          # signal continue      }end procedure PlayerFishes(player,opponent)         #: player fishes for a card   if 0 < strcnt(r := player.ask(),player.hand) then {# ask - any in hand?       player.public[r] <:= 1                          # either way - at least one      opponent.public[r] := 0                         # either way -none      if k := 0 < strcnt(r,opponent.hand) then {      # opponent has k > 0 r's?           printf("Yes, there was %d %s('s)\n",k,r)         opponent.hand := deletec(opponent.hand,r)    # move from opponent         player.hand ||:= repl(r,k)                   # to player         player.public[r] +:= k                       # k more in hand            if *opponent.hand = 0 then DrawCard(opponent)# hand empty ?                  ifbook(player)                               # made a book ?          if *player.hand > 0 then return              # signal success if cards left         }      else {         printf("No, %s has no %s's - %s draws a card\n",opponent.name,r,player.name)          DrawCard(player)                             # draw from deck         ifbook(player)                               # made a book ?         }      }   else      printf("%s is out of cards\n",player.name)   #   end procedure ifbook(player)                        #: determine if a book made   every r := !GF.ranks do       if strcnt(r,player.hand) = GF.suits then {      # yes          printf("%s made a book of %s's\n",player.name,r)         player.hand := deletec(player.hand,r)        # remove trick from hand         player.public[r] := 0                        # no longer in hand         player.score +:= 1                           # score 1         GF.booked ||:= r                             # book trick         if *player.hand = 0 then DrawCard(player)    # draw if hand empty                  return         }end procedure DrawCard(player)                      #: draw a card from the deck   if player.hand ||:= r := GF.deck[1] then {         # card if any to player      GF.deck[1] := ""                                # and out of deck      every r := !GF.ranks do                         # 0's back to uncertainty          if player.public[r] = 0 & not find(r,GF.booked) then             player.public[r] := -1      return        }end   procedure GFstrategy(player,opponent)           #: Request Strategy   every (knowns := "") ||:= key(opponent.public)   knowns := string(knowns**player.hand)              # we know we can win   ask    := ""              every r := !knowns do      if opponent.public[r] = GF.suits -1 then        # we can make a trick         return r      else          ask ||:= repl(r,0 < opponent.public[r])      # weighted knowns           if *ask > 0 then       return ?ask                                     # random choice by weight    every (guess := "") ||:=               repl(c := !cset(player.hand),GF.suits-strcnt(c,player.hand))   every ( z := '') ++:= (0 = opponent.public[r := !GF.ranks],r)     guess := deletec(guess,z)   if *guess = 0 then guess := (z ** player.hand)[1]  # make fruitless guess   return ?guessend procedure AIaskHP()                             #: AI asks for a card   if r := \GFstrategy(GF.AI,GF.HP) then {            # use strategy         printf("Computer: Do you have any %s's?\n",r)      return r      }end procedure HPaskAI()                             #: Human asks for a card   repeat {      printf("Your hand : %s\nYour turn : ", csort(GF.HP.hand))       if find(r := map(read(),&lcase,&ucase),GF.ranks) then         if *r = 1 & 0 < strcnt(r,GF.HP.hand) then break         else             printf("Try again, you must have at least one %i in your hand\n",r)       else          printf("Invalid rank %i, must be one of %i\n",r,GF.ranks)       }   printf("You: Does the computer have any %s's?\n",r)   return rend`
Sample Game:
```Go fish.
You vs. the computer - your turn first:
You: Does the computer have any K's?
Yes, there was 2 K('s)
You: Does the computer have any J's?
Yes, there was 1 J('s)
You: Does the computer have any A's?
No, Computer has no A's - Human draws a card
Computer: Do you have any 3's?
Yes, there was 1 3('s)
Computer: Do you have any 5's?
No, Human has no 5's - Computer draws a card
You: Does the computer have any 4's?
Yes, there was 2 4('s)
You: Does the computer have any 6's?
Yes, there was 2 6('s)
You: Does the computer have any 8's?
No, Computer has no 8's - Human draws a card
Computer: Do you have any 3's?
No, Human has no 3's - Computer draws a card
You: Does the computer have any Q's?
No, Computer has no Q's - Human draws a card
Computer: Do you have any 3's?
No, Human has no 3's - Computer draws a card
You: Does the computer have any K's?
No, Computer has no K's - Human draws a card
Computer: Do you have any 3's?
No, Human has no 3's - Computer draws a card
You: Does the computer have any T's?
Yes, there was 1 T('s)
You: Does the computer have any J's?
No, Computer has no J's - Human draws a card
Computer: Do you have any 2's?
No, Human has no 2's - Computer draws a card
You: Does the computer have any A's?
No, Computer has no A's - Human draws a card
Computer: Do you have any J's?
Yes, there was 2 J('s)
Computer: Do you have any 7's?
No, Human has no 7's - Computer draws a card
You: Does the computer have any 4's?
Yes, there was 1 4('s)
Human made a book of 4's
You: Does the computer have any 6's?
No, Computer has no 6's - Human draws a card
Computer: Do you have any 5's?
No, Human has no 5's - Computer draws a card
You: Does the computer have any 8's?
No, Computer has no 8's - Human draws a card
Computer: Do you have any 2's?
Yes, there was 1 2('s)
Computer: Do you have any 3's?
Yes, there was 1 3('s)
Computer: Do you have any 7's?
No, Human has no 7's - Computer draws a card
You: Does the computer have any T's?
No, Computer has no T's - Human draws a card
Human made a book of 6's
Computer: Do you have any 7's?
No, Human has no 7's - Computer draws a card
You: Does the computer have any Q's?
No, Computer has no Q's - Human draws a card
Computer: Do you have any 8's?
Yes, there was 3 8('s)
Computer made a book of 8's
Computer: Do you have any J's?
Yes, there was 1 J('s)
Computer made a book of J's
Computer: Do you have any 9's?
No, Human has no 9's - Computer draws a card
You: Does the computer have any A's?
No, Computer has no A's - Human draws a card
Computer: Do you have any 7's?
Yes, there was 1 7('s)
Computer: Do you have any 9's?
No, Human has no 9's - Computer draws a card
You: Does the computer have any K's?
No, Computer has no K's - Human draws a card
Computer: Do you have any T's?
Yes, there was 2 T('s)
Computer: Do you have any 9's?
Yes, there was 1 9('s)
Computer: Do you have any 2's?
No, Human has no 2's - Computer draws a card
You: Does the computer have any 5's?
Yes, there was 2 5('s)
You: Does the computer have any Q's?
Yes, there was 1 Q('s)
You: Does the computer have any K's?
No, Computer has no K's - Human draws a card
Computer: Do you have any 2's?
No, Human has no 2's - Computer draws a card
You: Does the computer have any T's?
Yes, there was 3 T('s)
Human made a book of T's
You: Does the computer have any 5's?
No, Computer has no 5's - Human draws a card
Computer: Do you have any Q's?
Yes, there was 3 Q('s)
Computer made a book of Q's
Computer: Do you have any 7's?
No, Human has no 7's - Computer draws a card
You: Does the computer have any 2's?
Yes, there was 3 2('s)
Human made a book of 2's
You: Does the computer have any 5's?
No, Computer has no 5's - Human draws a card
Computer: Do you have any A's?
Yes, there was 3 A('s)
Computer made a book of A's
Computer: Do you have any 7's?
No, Human has no 7's - Computer draws a card
You: Does the computer have any 3's?
Yes, there was 3 3('s)
Human made a book of 3's
You: Does the computer have any K's?
No, Computer has no K's - Human draws a card
Human made a book of 5's
Computer: Do you have any 7's?
No, Human has no 7's - Computer draws a card
Computer made a book of 9's