⚠️ Warning: This is a draft ⚠️
This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.
If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.
{{collection|Go Fish}} [[Category:AutoHotkey]] {{works with|AutoHotkey L}} Unicode Easily expanded to multiple players, any combination of human and AI.
#NoEnv
SetBatchLines -1
#SingleInstance Force
Global Suits:={1:"♣",2:"♦",3:"♠",4:"♥"}
Global Pips:={13:"A",1:"2",2:"3",3:"4",4:"5",5:"6",6:"7",7:"8",8:"9",9:"T",10:"J",11:"Q",12:"K"}
Deck:=new Deck
Deck.Shuffle()
Player1:=new Human
Player0:=new AI
i:=!i ; current player
o:=!i ; current opponent
While (Player%i%.Archive() || Player1.Hand.HasCards() || Player0.Hand.HasCards())
{
If (!Player%i%.Hand.HasCards()) ; if hand is empty,
Player%i%.Hand.Draw() ; draw 1
pip := Player%i%.Choose(o) ; player's request
If pip not in % Player%i%.Pips() ; if invalid,
Continue ; try again
If (Player%i%.Take(pip, o)) ; if received what requested from opponent,
Continue ; go again
If (Player%i%.Hand.Draw().Pip = pip) ; if obtained what requested from pond,
Continue ; go again
i:=!i ; current player
o:=!i ; current opponent
}
Msgbox % "Human: " Player1.Book.Show()
. "`nAI: " Player0.Book.Show()
. "`nWinner: " (Player1.Book.HasCards() > Player0.Book.HasCards() ? "Human" : "AI")
Return ;--------------------------------------------------------------------------------
class Card
{
__New(Pip, Suit) {
this.Pip:=Pip, this.Suit:=Suit
}
Show() {
Return this.Pip . this.Suit
}
}
class Cards
{
Cards:=[]
HasCards() {
Return this.Cards.MaxIndex()
}
Shuffle() { ; Knuth Shuffle from http://rosettacode.org/wiki/Knuth_Shuffle#AutoHotkey
Loop % this.HasCards()-1 {
Random, i, A_Index, this.HasCards() ; swap item 1,2... with a random item to the right of it
temp := this.Cards[i], this.Cards[i] := this.Cards[A_Index], this.Cards[A_Index] := temp
}
}
Show(Sort=0) {
For i, Card in this.Cards
s .= Card.Show() ","
s:=SubStr(s,1,-1)
If Sort
Sort, s, D,
Return s
}
}
class Deck extends Cards
{
__New() {
For i, Pip in Pips
For j, Suit in Suits
this.Cards.Insert(new Card(Pip,Suit))
}
}
class Hand extends Cards
{
lastDraw := ""
__New() {
this.Draw(9)
}
Draw(n=1) {
Loop, %n%
If (Deck.HasCards())
this.Cards.Insert(temp:=Deck.Cards.Remove(1)) ; to deal from bottom, use Remove()
lastDraw := temp.Pip ","
Return temp.Pip
}
}
class Player
{
Hand := new Hand
Book := new Cards
oRequests := "" ; log pips requested by opponent here
Pip() {
For i, Card in this.Hand.Cards
s .= Card.Pip ","
s:=SubStr(s,1,-1)
Sort, s, D,
Return s
}
Pips() {
s := this.Pip()
Sort, s, UD,
Return s
}
Take(Pip, o) {
Player%o%.oRequests := Pip "," Player%o%.oRequests
For i, Card in Player%o%.Hand.Cards
If (Card.Pip = Pip)
this.Hand.Cards.Insert(Card)
, toremove .= i ","
toremove:=SubStr(toremove,1,-1)
Sort, toremove, RND, ; must remove in reverse order
Loop, Parse, toremove, `, ; so as not to mess up loop
Player%o%.Hand.Cards.Remove(A_LoopField)
Return toremove ? 1 : 0
}
Archive() {
s := this.Pip()
Loop, Parse, s, `,
{
If (A_LoopField = previous)
count++
Else
count := 1
If (count = Suits.MaxIndex()) ; normally 4
{
toarchive := A_LoopField
Break
}
previous := A_LoopField
}
If (toarchive)
{
For i, Card in this.Hand.Cards
If (Card.Pip = toarchive)
this.Book.Cards.Insert(Card)
, toremove .= i ","
toremove:=SubStr(toremove,1,-1)
Sort, toremove, RND, ; must remove in reverse order
Loop, Parse, toremove, `, ; so as not to mess up loop
this.Hand.Cards.Remove(A_LoopField)
}
Return 0
}
}
class Human extends Player
{
Choose(o) {
InputBox, Pip, Enter a rank to request from opponent.
, % "Your cards: " this.Hand.Show(1)
. "`nYour books: " this.Book.Show(1)
. "`nAI's books: " Player%o%.Book.Show(1)
. "`nEnter rank: " this.Pips()
, , 900
Return Pip
}
}
class AI extends Player
{
Choose(o) {
Static Pip ; last asked
s := this.Pip()
Loop, Parse, s, `,
{
If (A_LoopField = previous)
count++
Else
count := 1
Random, rand, 0, 2
If (count > oldcount - rand//2 && count < Suits.MaxIndex())
oldcount := count
, IHaveMostOf := A_LoopField
previous := A_LoopField
}
ChoicePrefs := this.oRequests . this.Hand.lastDraw . IHaveMostOf . "," . s
this.Hand.lastDraw := ""
Loop, Parse, ChoicePrefs, `,
If A_LoopField in % this.Pips()
If (A_LoopField != Pip) ; don't repeat last asked
{
Pip := A_LoopField
Break
}
Msgbox, , Opponent requests a rank from you.
, % "Your cards: " Player%o%.Hand.Show(1)
. "`nYour books: " Player%o%.Book.Show(1)
. "`nAI's books: " this.Book.Show(1)
. "`n`n`nRequested rank: " Pip
Return Pip
}
}