DomSim

Option Explicit

' DomSim, a simulation of the game Dominion.
'
' --- Copyright (C) 2010, Michael Waddell. ------------------------------------------
'
'    This program is free software: you can redistribute it and/or modify
'    it under the terms of the GNU General Public License as published by
'    the Free Software Foundation, either version 3 of the License, or
'    (at your option) any later version.
'
'    This program is distributed in the hope that it will be useful,
'    but WITHOUT ANY WARRANTY; without even the implied warranty of
'    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'    GNU General Public License for more details.
'
'    You should have received a copy of the GNU General Public License
'    along with this program.  If not, see <http://www.gnu.org/licenses/>.
'
' --- Usage notes ------------------------------------------------------------------
'
' In general, a "c" prefix means "count", as in the number of something.
' A "k" prefix means "constant". ("C" was already taken.)
' An "i" prefix means integer, an "s" prefix means string.
'
' Most of my arrays are 1-based. Each has a corresponding count variable to indicate
'  how many items are in the array. The strategies (players) is 0-based, so cPlayers
'  is actually 1 less than the number of players. I apologize. I'd fix that, but the
'  real fix is to use a language with robust data structures.
' Victory points are stored as multiples of ten, because I handle ties by adding an
'  additional point to each player who has had fewer turns than the max. It's a hack.

Dim cPlayers As Integer
Dim cTurns As Integer
Dim cDepletedSupplyPiles As Integer

Dim Supply(1 To 100) As Integer
Dim DrawPile(0 To 5, 1 To 300) As Integer
Dim Hand(0 To 5, 1 To 100) As Integer
Dim InPlay(0 To 5, 1 To 100) As Integer
Dim DiscardPile(0 To 5, 1 To 300) As Integer

Dim cDrawPile(0 To 5) As Integer
Dim cDiscardPile(0 To 5) As Integer
Dim cInPlay(0 To 5) As Integer
Dim cHand(0 To 5) As Integer

Dim iCurrentPlayer As Integer
Dim iVict(0 To 5) As Integer
Dim iInt(0 To 5) As Integer
Dim cActions As Integer
Dim iActionMoney As Integer
Dim iLastPurchased As Integer
Dim iCopperSmithery As Integer

Const kCurse = 1
Const kEstate = 2
Const kDuchy = 3
Const kProvince = 4
Const kColony = 5
Const kCopper = 6
Const kSilver = 7
Const kGold = 8
Const kPlatinum = 9
Const kExplorer = 10
Const kScout = 11
Const kSmithy = 12
Const kWitch = 13
Const kTreasureMap = 14
Const kIsland = 15
Const kLaboratory = 16
Const kMoat = 17
Const kWorkshop = 18
Const kMilitia = 19
Const kCutpurse = 20
Const kBureaucrat = 21
Const kMoneylender = 22
Const kSpy = 23
Const kMine = 24
Const kAdventurer = 25
Const kMonument = 26
Const kSeahag = 27
Const kThief = 28
Const kGreatHall = 29
Const kTreasury = 30
Const kCountingHouse = 31
Const kVenture = 32
Const kRabble = 33
Const kHarem = 34
Const kMountebank = 35
Const kCouncilRoom = 36
Const kLibrary = 37
Const kMarket = 38
Const kTradingPost = 39
Const kFeast = 40
Const kCoppersmith = 41
Const kIronworks = 42
Const kSmugglers = 43
Const kPearlDiver = 44
Const kBank = 45
Const kPeddler = 46
Const kChapel = 47
'

Sub DominionLoop()
  Randomize Timer
  
  Dim i As Integer
  Dim iRuns As Integer
  Dim iWins(-1 To 5) As Integer
  Dim Percent(-1 To 5) As Single
  Dim sThisWin As String
  Dim Strats(0 To 5) As String
  Dim iFirstPlayer As Integer
  Dim iNumPlayers As Integer
  
  Strats(0) = "Monument"
  Strats(1) = "Smithy"
  Strats(2) = "TB"
  Strats(3) = "Moat"
  iRuns = 9000
  iFirstPlayer = 0
  
  For i = 1 To iRuns
    Select Case iFirstPlayer
    Case 0
      sThisWin = PlayOneGame(Strats(0), Strats(1), Strats(2), Strats(3))
    Case 1
      sThisWin = PlayOneGame(Strats(1), Strats(2), Strats(3), Strats(0))
    Case 2
      sThisWin = PlayOneGame(Strats(2), Strats(3), Strats(0), Strats(1))
    Case 3
      sThisWin = PlayOneGame(Strats(3), Strats(0), Strats(1), Strats(2))
    End Select
    
    Select Case sThisWin
    Case Strats(0)
      iWins(0) = iWins(0) + 1
    Case Strats(1)
      iWins(1) = iWins(1) + 1
    Case Strats(2)
      iWins(2) = iWins(2) + 1
    Case Strats(3)
      iWins(3) = iWins(3) + 1
    Case Else
      iWins(-1) = iWins(-1) + 1
    End Select
    
    iFirstPlayer = (iFirstPlayer + 1) Mod 4
  Next i
  
  For i = -1 To 5
    Percent(i) = 100 * (iWins(i) / iRuns)
  Next i
  
  MsgBox iRuns & " runs." & vbCrLf & _
    "Player 0: " & Percent(0) & vbCrLf & _
    "Player 1: " & Percent(1) & vbCrLf & _
    "Player 2: " & Percent(2) & vbCrLf & _
    "Player 3: " & Percent(3) & vbCrLf & _
    "Player 4: " & Percent(4) & vbCrLf & _
    "Player 5: " & Percent(5) & vbCrLf & _
    "Ties: " & Percent(-1)
End Sub
       
Sub SetUpGame()
  Dim i As Integer
  
  cTurns = 0
  cDepletedSupplyPiles = 0
  
  Select Case cPlayers
  Case 1
    Supply(kCurse) = 10
    Supply(kEstate) = 8
    Supply(kDuchy) = 8
    Supply(kProvince) = 8
    Supply(kColony) = 8
    Supply(kIsland) = 8
    Supply(kGreatHall) = 8
    Supply(kHarem) = 8
    Supply(kCopper) = 60
    Supply(kSilver) = 40
    Supply(kGold) = 30
  Case 2
    Supply(kCurse) = 20
    Supply(kEstate) = 12
    Supply(kDuchy) = 12
    Supply(kProvince) = 12
    Supply(kColony) = 12
    Supply(kIsland) = 12
    Supply(kGreatHall) = 12
    Supply(kHarem) = 12
    Supply(kCopper) = 60
    Supply(kSilver) = 40
    Supply(kGold) = 30
  Case 3
    Supply(kCurse) = 30
    Supply(kEstate) = 12
    Supply(kDuchy) = 12
    Supply(kProvince) = 12
    Supply(kColony) = 12
    Supply(kIsland) = 12
    Supply(kGreatHall) = 12
    Supply(kHarem) = 12
    Supply(kCopper) = 60
    Supply(kSilver) = 40
    Supply(kGold) = 30
  Case 4
    Supply(kCurse) = 40
    Supply(kEstate) = 12
    Supply(kDuchy) = 12
    Supply(kProvince) = 15
    Supply(kColony) = 12
    Supply(kIsland) = 12
    Supply(kGreatHall) = 12
    Supply(kHarem) = 12
    Supply(kCopper) = 120
    Supply(kSilver) = 80
    Supply(kGold) = 60
  Case 5
    Supply(kCurse) = 50
    Supply(kEstate) = 12
    Supply(kDuchy) = 12
    Supply(kProvince) = 18
    Supply(kColony) = 12
    Supply(kIsland) = 12
    Supply(kGreatHall) = 12
    Supply(kHarem) = 12
    Supply(kCopper) = 120
    Supply(kSilver) = 80
    Supply(kGold) = 60
  End Select
  
  Supply(kWitch) = 10
  Supply(kScout) = 10
  Supply(kSmithy) = 10
  Supply(kLaboratory) = 10
  Supply(kMoat) = 10
  Supply(kWorkshop) = 10
  Supply(kMilitia) = 10
  Supply(kCutpurse) = 10
  Supply(kMoneylender) = 10
  Supply(kBureaucrat) = 10
  Supply(kSpy) = 10
  Supply(kMine) = 10
  Supply(kAdventurer) = 10
  Supply(kMonument) = 10
  Supply(kSeahag) = 10
  Supply(kThief) = 10
  Supply(kTreasureMap) = 10
  Supply(kExplorer) = 10
  Supply(kTreasury) = 10
  Supply(kCountingHouse) = 10
  Supply(kVenture) = 10
  Supply(kRabble) = 10
  Supply(kMountebank) = 10
  Supply(kCouncilRoom) = 10
  Supply(kLibrary) = 10
  Supply(kMarket) = 10
  Supply(kTradingPost) = 10
  Supply(kFeast) = 10
  Supply(kCoppersmith) = 10
  Supply(kIronworks) = 10
  Supply(kSmugglers) = 10
  Supply(kPearlDiver) = 10
  Supply(kBank) = 10
  Supply(kPeddler) = 10
  Supply(kChapel) = 10
  
  For i = 0 To cPlayers
    cDrawPile(i) = 0
    cHand(i) = 0
    cInPlay(i) = 0
    cDiscardPile(i) = 10
    DiscardPile(i, 1) = kEstate
    DiscardPile(i, 2) = kEstate
    DiscardPile(i, 3) = kEstate
    DiscardPile(i, 4) = kCopper
    DiscardPile(i, 5) = kCopper
    DiscardPile(i, 6) = kCopper
    DiscardPile(i, 7) = kCopper
    DiscardPile(i, 8) = kCopper
    DiscardPile(i, 9) = kCopper
    DiscardPile(i, 10) = kCopper
    Supply(kCopper) = Supply(kCopper) - 7
    iVict(i) = 30
    iInt(i) = 0
    Call Draw(i, 5)
  Next i
End Sub
       
Function PlayOneGame(ParamArray Strategies() As Variant) As String
  Dim i As Integer
  
  cPlayers = UBound(Strategies)
  Call SetUpGame
  
  Do
    cTurns = cTurns + 1

    For iCurrentPlayer = 0 To cPlayers
      iActionMoney = 0
      iCopperSmithery = 0
      Call ActionPhase(Strategies(iCurrentPlayer))
      Call BuyPhase(Strategies(iCurrentPlayer))
      Call CleanupPhase
      
      ' Did someone win?
      If Supply(kColony) = 0 Or Supply(kProvince) = 0 _
          Or (cDepletedSupplyPiles >= 3 And cPlayers < 4) _
          Or cDepletedSupplyPiles >= 4 Then
        For i = 0 To cPlayers
          If i > iCurrentPlayer Then
            iVict(i) = iVict(i) + 1
          End If
        Next i
        
        Exit Do
      End If
    Next iCurrentPlayer
  Loop
    
  ' Game over. Who won?
  PlayOneGame = "tie"
  If iVict(0) > Max(iVict(1), iVict(2), iVict(3), iVict(4), iVict(5)) Then
    PlayOneGame = Strategies(0)
  ElseIf iVict(1) > Max(iVict(0), iVict(2), iVict(3), iVict(4), iVict(5)) Then
    PlayOneGame = Strategies(1)
  ElseIf iVict(2) > Max(iVict(0), iVict(1), iVict(3), iVict(4), iVict(5)) Then
    PlayOneGame = Strategies(2)
  ElseIf iVict(3) > Max(iVict(0), iVict(1), iVict(2), iVict(4), iVict(5)) Then
    PlayOneGame = Strategies(3)
  ElseIf iVict(4) > Max(iVict(0), iVict(1), iVict(2), iVict(3), iVict(5)) Then
    PlayOneGame = Strategies(4)
  ElseIf iVict(5) > Max(iVict(0), iVict(1), iVict(2), iVict(3), iVict(4)) Then
    PlayOneGame = Strategies(5)
  End If
End Function

Function MoneyVal(ByVal iCard As Integer) As Integer
  Dim i As Integer
  
  Select Case iCard
  Case kCopper
    MoneyVal = 1
    For i = 1 To iCopperSmithery
      MoneyVal = MoneyVal + 1
    Next i
  Case kSilver
    MoneyVal = 2
  Case kGold
    MoneyVal = 3
  Case kPlatinum
    MoneyVal = 4
'  Case kVenture
'    PlayVenture
'    MoneyVal = 1
  Case kHarem
    MoneyVal = 2
  Case kBank
    ' Figure this out QQQ
  Case Else
    MoneyVal = 0
  End Select
End Function

Function IsVictoryCard(ByVal iCard As Integer) As Boolean
  Select Case iCard
  Case kEstate, kDuchy, kProvince, kColony, kIsland, kGreatHall, kHarem
    IsVictoryCard = True
  Case Else
    IsVictoryCard = False
  End Select
End Function

Function IsActionCard(ByVal iCard As Integer) As Boolean
  Select Case iCard
  Case kCurse, kEstate, kDuchy, kProvince, kColony, kIsland, kGreatHall, kHarem, kCopper, kSilver, kGold, kPlatinum, kVenture, kBank
    IsActionCard = False
  Case Else
    IsActionCard = True
  End Select
End Function

Function Cost(ByVal iCard As Integer) As Integer
  Select Case iCard
  Case kCurse, kCopper, 0
    Cost = 0
  Case kEstate, kPearlDiver, kMoat, kChapel
    Cost = 2
  Case kSilver, kSmugglers, kWorkshop, kGreatHall
    Cost = 3
  Case kSmithy, kIronworks, kCoppersmith, kFeast, kMoneylender, kSpy, kThief, kBureaucrat, kMilitia, kScout, kTreasureMap, kIsland, kCutpurse, kSeahag, kMonument
    Cost = 4
  Case kDuchy, kMine, kTradingPost, kMarket, kLibrary, kCouncilRoom, kMountebank, kCountingHouse, kRabble, kVenture, kTreasury, kExplorer, kLaboratory, kWitch
    Cost = 5
  Case kGold, kHarem, kAdventurer
    Cost = 6
  Case kBank
    Cost = 7
  Case kProvince, kPeddler
    Cost = 8
  Case kPlatinum
    Cost = 9
  Case kColony
    Cost = 11
  End Select
End Function

Sub Shuffle(ByVal iThisPlayer As Integer)
  Dim x As Integer
  Dim Temp(1 To 10) As Integer
  Dim cTemp As Integer
  Dim i As Integer
  
  'Set aside the drawpile
  cTemp = 0
  For i = 1 To cDrawPile(iThisPlayer)
    Temp(i) = DrawPile(iThisPlayer, cDrawPile(iThisPlayer))
    cDrawPile(iThisPlayer) = cDrawPile(iThisPlayer) - 1
    cTemp = cTemp + 1
  Next i
  
  'Shuffle in the discard
  Do While cDiscardPile(iThisPlayer) > 0
    x = Int(cDiscardPile(iThisPlayer) * Rnd + 1)
    cDrawPile(iThisPlayer) = cDrawPile(iThisPlayer) + 1
    DrawPile(iThisPlayer, cDrawPile(iThisPlayer)) = DiscardPile(iThisPlayer, x)
    DiscardPile(iThisPlayer, x) = DiscardPile(iThisPlayer, cDiscardPile(iThisPlayer))
    cDiscardPile(iThisPlayer) = cDiscardPile(iThisPlayer) - 1
  Loop
  
  'Put the set-aside cards on top.
  For i = 1 To cTemp
    cDrawPile(iThisPlayer) = cDrawPile(iThisPlayer) + 1
    DrawPile(iThisPlayer, cDrawPile(iThisPlayer)) = Temp(i)
  Next i
End Sub

Sub Draw(ByVal iThisPlayer As Integer, ByVal iCards As Integer)
  Dim i As Integer
  
  If cDrawPile(iThisPlayer) < iCards Then Shuffle iThisPlayer
  
  For i = 1 To Min(iCards, cDrawPile(iThisPlayer))
    cHand(iThisPlayer) = cHand(iThisPlayer) + 1
    Hand(iThisPlayer, cHand(iThisPlayer)) = DrawPile(iThisPlayer, cDrawPile(iThisPlayer))
    cDrawPile(iThisPlayer) = cDrawPile(iThisPlayer) - 1
  Next
End Sub

Sub Gain(ByVal iThisPlayer As Integer, ByVal iCard As Integer, Optional ByVal sTo As String)
  If UCase(sTo) = "DECK" Then
    cDrawPile(iThisPlayer) = cDrawPile(iThisPlayer) + 1
    DrawPile(iThisPlayer, cDrawPile(iThisPlayer)) = iCard
  ElseIf UCase(sTo) = "HAND" Then
    cHand(iThisPlayer) = cHand(iThisPlayer) + 1
    Hand(iThisPlayer, cHand(iThisPlayer)) = iCard
  Else
    cDiscardPile(iThisPlayer) = cDiscardPile(iThisPlayer) + 1
    DiscardPile(iThisPlayer, cDiscardPile(iThisPlayer)) = iCard
  End If
  
  Desupply iCard
  
  Select Case iCard
  Case kCurse
    iVict(iThisPlayer) = iVict(iThisPlayer) - 10
  Case kEstate
    iVict(iThisPlayer) = iVict(iThisPlayer) + 10
  Case kDuchy
    iVict(iThisPlayer) = iVict(iThisPlayer) + 30
  Case kProvince
    iVict(iThisPlayer) = iVict(iThisPlayer) + 60
  Case kColony
    iVict(iThisPlayer) = iVict(iThisPlayer) + 100
  Case kIsland
    iVict(iThisPlayer) = iVict(iThisPlayer) + 20
  Case kGreatHall
    iVict(iThisPlayer) = iVict(iThisPlayer) + 10
  Case kHarem
    iVict(iThisPlayer) = iVict(iThisPlayer) + 20
  End Select
End Sub

Sub CleanupPhase()
  Dim i As Integer
  
  ' Hand -> Discard
  For i = 1 To cHand(iCurrentPlayer)
    cDiscardPile(iCurrentPlayer) = cDiscardPile(iCurrentPlayer) + 1
    DiscardPile(iCurrentPlayer, cDiscardPile(iCurrentPlayer)) = Hand(iCurrentPlayer, i)
    cHand(iCurrentPlayer) = cHand(iCurrentPlayer) - 1
  Next
  
  ' InPlay -> Discard
  For i = 1 To cInPlay(iCurrentPlayer)
    'Treasury is special
    If InPlay(iCurrentPlayer, i) = kTreasury And Not IsVictoryCard(iLastPurchased) Then
      cDrawPile(iCurrentPlayer) = cDrawPile(iCurrentPlayer) + 1
      DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer)) = InPlay(iCurrentPlayer, i)
      cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
    Else
      cDiscardPile(iCurrentPlayer) = cDiscardPile(iCurrentPlayer) + 1
      DiscardPile(iCurrentPlayer, cDiscardPile(iCurrentPlayer)) = InPlay(iCurrentPlayer, i)
      cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
    End If
  Next
  
  Call Draw(iCurrentPlayer, 5)
End Sub

Function PlayAction(ByVal sCard As Integer) As Boolean
  If PutIntoPlay(sCard) Then
    PlayAction = True
    cActions = cActions - 1
  Else
    PlayAction = False
  End If
End Function

Function PutIntoPlay(ByVal sCard As Integer) As Boolean
  Dim iFoundItAt As Integer
  Dim i As Integer
  
  iFoundItAt = 0
  For i = 1 To cHand(iCurrentPlayer)
    If Hand(iCurrentPlayer, i) = sCard Then
      iFoundItAt = i
    End If
  Next i
  
  If iFoundItAt > 0 Then
    'Put it in play
    cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) + 1
    InPlay(iCurrentPlayer, cInPlay(iCurrentPlayer)) = Hand(iCurrentPlayer, iFoundItAt)
      
    '...and out of hand
    Hand(iCurrentPlayer, iFoundItAt) = Hand(iCurrentPlayer, cHand(iCurrentPlayer))
    cHand(iCurrentPlayer) = cHand(iCurrentPlayer) - 1
    
    PutIntoPlay = True
  Else
    PutIntoPlay = False
  End If
End Function

Function HasInHand(ByVal iThisPlayer As Integer, ByVal iCard As Integer) As Integer
  Dim i As Integer

  HasInHand = 0
  For i = 1 To cHand(iThisPlayer)
    If Hand(iThisPlayer, i) = iCard Then
      HasInHand = i
    End If
  Next i
End Function

Function DiscardThis(ByVal iThisPlayer As Integer, ByVal iCard As Integer) As Boolean
  Dim i As Integer
  
  DiscardThis = False
  For i = 1 To cHand(iThisPlayer)
    If Hand(iThisPlayer, i) = iCard Then
      DiscardThis = True
      cDiscardPile(iThisPlayer) = cDiscardPile(iThisPlayer) + 1
      DiscardPile(iThisPlayer, cDiscardPile(iThisPlayer)) = Hand(iThisPlayer, i)
      Hand(iThisPlayer, i) = Hand(iThisPlayer, cHand(iThisPlayer))
      cHand(iThisPlayer) = cHand(iThisPlayer) - 1
      Exit For
    End If
  Next i
End Function

Function PutThisOnDeck(ByVal iThisPlayer As Integer, ByVal cTarget As Integer) As Boolean
  Dim i As Integer
  
  PutThisOnDeck = False
  For i = 1 To cHand(iThisPlayer)
    If Hand(iThisPlayer, i) = cTarget Then
      PutThisOnDeck = True
      cDrawPile(iThisPlayer) = cDrawPile(iThisPlayer) + 1
      DrawPile(iThisPlayer, cDrawPile(iThisPlayer)) = Hand(iThisPlayer, i)
      Hand(iThisPlayer, i) = Hand(iThisPlayer, cHand(iThisPlayer))
      cHand(iThisPlayer) = cHand(iThisPlayer) - 1
      Exit For
    End If
  Next i
End Function

Function TrashThis(ByVal iThisPlayer As Integer, ByVal cTarget As Integer) As Boolean
  Dim i As Integer
  
  TrashThis = False
  For i = 1 To cHand(iThisPlayer)
    If Hand(iThisPlayer, i) = cTarget Then
      TrashThis = True
      Hand(iThisPlayer, i) = Hand(iThisPlayer, cHand(iThisPlayer))
      cHand(iThisPlayer) = cHand(iThisPlayer) - 1
      Exit For
    End If
  Next i
End Function

Sub PlayMine()
  Dim i As Integer
  
  'Look for silver
  If Supply(kGold) > 0 Then
    For i = 1 To cHand(iCurrentPlayer)
      If Hand(iCurrentPlayer, i) = kSilver Then
        Hand(iCurrentPlayer, i) = kGold
        Desupply kGold
        Exit Sub
      End If
    Next
  End If
  
  'Look for copper
  If Supply(kSilver) > 0 Then
    For i = 1 To cHand(iCurrentPlayer)
      If Hand(iCurrentPlayer, i) = kCopper Then
        Hand(iCurrentPlayer, i) = kSilver
        Desupply kSilver
        Exit Sub
      End If
    Next
  End If
End Sub

Sub PlayScout()
  Dim i As Integer
  Dim Temp(1 To 4) As Integer
  
  If cDrawPile(iCurrentPlayer) < 4 Then Shuffle iCurrentPlayer
  For i = 1 To 4
    Temp(i) = DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer))
    cDrawPile(iCurrentPlayer) = cDrawPile(iCurrentPlayer) - 1
  Next i
  For i = 1 To 4
    If IsVictoryCard(Temp(i)) Then
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) + 1
      Hand(iCurrentPlayer, cHand(iCurrentPlayer)) = Temp(i)
    Else
      cDrawPile(iCurrentPlayer) = cDrawPile(iCurrentPlayer) + 1
      DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer)) = Temp(i)
    End If
  Next i
  
  cActions = cActions + 1
End Sub

Sub PlayIsland()
  Dim i As Integer
  Dim iChosen As Integer
  
  iChosen = HasInHand(iCurrentPlayer, kEstate)
  If iChosen = 0 Then iChosen = HasInHand(iCurrentPlayer, kDuchy)
  If iChosen = 0 Then iChosen = HasInHand(iCurrentPlayer, kProvince)
  If iChosen = 0 Then iChosen = HasInHand(iCurrentPlayer, kColony)
  If iChosen = 0 Then iChosen = HasInHand(iCurrentPlayer, kCurse)
  If iChosen = 0 Then iChosen = HasInHand(iCurrentPlayer, kGreatHall)
  If iChosen = 0 Then iChosen = HasInHand(iCurrentPlayer, kIsland)
  If iChosen = 0 Then iChosen = HasInHand(iCurrentPlayer, kCopper)
  
  If iChosen > 0 Then
    'Island goes away
    cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
    
    'Chosen card goes away
    Hand(iCurrentPlayer, iChosen) = Hand(iCurrentPlayer, cHand(iCurrentPlayer))
    cHand(iCurrentPlayer) = cHand(iCurrentPlayer) - 1
  End If
End Sub

Sub PlayCountingHouse()
  Dim i As Integer
  
  For i = cDiscardPile(iCurrentPlayer) To 1 Step -1
    If DiscardPile(iCurrentPlayer, i) = kCopper Then
      DiscardPile(iCurrentPlayer, i) = DiscardPile(iCurrentPlayer, cDiscardPile(iCurrentPlayer))
      cDiscardPile(iCurrentPlayer) = cDiscardPile(iCurrentPlayer) - 1
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) + 1
      Hand(iCurrentPlayer, cHand(iCurrentPlayer)) = kCopper
    End If
  Next i
End Sub

Sub PlayIronworksForIslands()
  If Supply(kIsland) > 0 Then
    Gain iCurrentPlayer, kIsland
    cActions = cActions + 1
    Draw iCurrentPlayer, 1
  ElseIf Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
    Gain iCurrentPlayer, kEstate
    Draw iCurrentPlayer, 1
  ElseIf Supply(kSilver) > 0 Then
    Gain iCurrentPlayer, kSilver
    iActionMoney = iActionMoney + 1
  End If
End Sub

Sub PlayIronworks()
  ' For TB
  If Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
    Gain iCurrentPlayer, kEstate
    Draw iCurrentPlayer, 1
  ElseIf Supply(kSilver) > 0 Then
    Gain iCurrentPlayer, kSilver
    iActionMoney = iActionMoney + 1
  End If
  
'  ' For Islands
'  If Supply(kIsland) > 0 Then
'    Gain iCurrentPlayer, kIsland
'    cActions = cActions + 1
'    Draw iCurrentPlayer, 1
'  ElseIf Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
'    Gain iCurrentPlayer, kEstate
'    Draw iCurrentPlayer, 1
'  ElseIf Supply(kSilver) > 0 Then
'    Gain iCurrentPlayer, kSilver
'    iActionMoney = iActionMoney + 1
'  End If
End Sub

Sub PlayWorkshop()
  If Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
    Gain iCurrentPlayer, kEstate
'  Now put in any available 4-cost kingdom cards...
'  ElseIf Supply(kIsland) > 0 Then
'    DiscardPile(iCurrentPlayer, cDiscardPile(iCurrentPlayer)) = kIsland
'    iVict(iCurrentPlayer) = iVict(iCurrentPlayer) + 20
'    Desupply kIsland
  ElseIf Supply(kSilver) > 0 Then
    Gain iCurrentPlayer, kSilver
  End If
End Sub

Sub PlayFeast()
  If Supply(kProvince) <= 3 + cPlayers And Supply(kDuchy) > 0 Then
    Gain iCurrentPlayer, kDuchy
    cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
  ElseIf Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
    Gain iCurrentPlayer, kEstate
    cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
  ' Pick a $5 card to Feast for.
  ElseIf Supply(kWitch) > 0 Then
    Gain iCurrentPlayer, kWitch
    cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
  ElseIf Supply(kSilver) > 0 Then
    Gain iCurrentPlayer, kSilver
    cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
  End If
End Sub

Sub PlaySpy()
  Dim i As Integer
  
  Draw iCurrentPlayer, 1
  
  For i = 0 To cPlayers
    If cDrawPile(i) < 1 Then Shuffle i
    If i <> iCurrentPlayer Then
      If HasInHand(i, kMoat) = 0 Then
        If IsVictoryCard(DrawPile(i, cDrawPile(i))) _
            Or DrawPile(i, cDrawPile(i)) = kCurse _
            Or (DrawPile(i, cDrawPile(i)) = kCopper And cTurns >= 9) Then
          'Nothing
        Else
          cDiscardPile(i) = cDiscardPile(i) + 1
          DiscardPile(i, cDiscardPile(i)) = DrawPile(i, cDrawPile(i))
          cDrawPile(i) = cDrawPile(i) - 1
        End If
      End If
    Else
      'You
      If IsVictoryCard(DrawPile(i, cDrawPile(i))) _
          Or DrawPile(i, cDrawPile(i)) = kCurse _
          Or (DrawPile(i, cDrawPile(i)) = kCopper And cTurns >= 9) Then
        cDiscardPile(i) = cDiscardPile(i) + 1
        DiscardPile(i, cDiscardPile(i)) = DrawPile(i, cDrawPile(i))
        cDrawPile(i) = cDrawPile(i) - 1
      End If
    End If
  Next i
  
  cActions = cActions + 1
End Sub

Sub PlayMarket()
  iActionMoney = iActionMoney + 1
  Draw iCurrentPlayer, 1
  cActions = cActions + 1
End Sub
          
Sub PlayRabble()
  Dim i As Integer
  Dim j As Integer
  Dim Temp(1 To 3) As Integer
  Dim cTemp As Integer
  
  ' +3 Cards
  Draw iCurrentPlayer, 3
  
  ' Each other player...
  For i = 0 To cPlayers
    If i <> iCurrentPlayer Then
      If HasInHand(i, kMoat) = 0 Then
      
        ' ...reveal the top 3 cards of his deck,...
        If cDrawPile(i) < 3 Then Shuffle i
        cTemp = 0
        For j = 1 To Min(3, cDrawPile(i))
          cTemp = cTemp + 1
          Temp(cTemp) = DrawPile(i, cDrawPile(i))
          cDrawPile(i) = cDrawPile(i) - 1
        Next j
        
        For j = 1 To cTemp
          If IsActionCard(Temp(j)) Or MoneyVal(Temp(j)) > 0 Then
            ' ...discards the revealed Actions and Treasures,...
            cDiscardPile(i) = cDiscardPile(i) + 1
            DiscardPile(i, cDiscardPile(i)) = Temp(j)
          Else
            ' ...and puts the rest back on top...
            cDrawPile(i) = cDrawPile(i) + 1
            DrawPile(i, cDrawPile(i)) = Temp(j)
          End If
        Next j
      End If
    End If
  Next i
End Sub

Sub PlayVenture()
  Dim i As Integer
  Dim Temp(1 To 100) As Integer
  Dim cTemp As Integer
  Dim bFoundTreasure As Boolean

  bFoundTreasure = False
  cTemp = 0

  Do While Not bFoundTreasure
    If cDrawPile(iCurrentPlayer) < 1 Then Shuffle iCurrentPlayer
    If cDrawPile(iCurrentPlayer) < 1 Then Exit Sub
    
    If MoneyVal(DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer))) > 0 Then
      bFoundTreasure = True
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) + 1
      Hand(iCurrentPlayer, cHand(iCurrentPlayer)) = DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer))
      cDrawPile(iCurrentPlayer) = cDrawPile(iCurrentPlayer) - 1
    Else
      cTemp = cTemp + 1
      Temp(cTemp) = DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer))
      cDrawPile(iCurrentPlayer) = cDrawPile(iCurrentPlayer) - 1
    End If
  Loop
  
  For i = 1 To cTemp
    cDiscardPile(iCurrentPlayer) = cDiscardPile(iCurrentPlayer) + 1
    DiscardPile(iCurrentPlayer, cDiscardPile(iCurrentPlayer)) = Temp(i)
  Next i
End Sub

Sub PlayMoneylender()
  If TrashThis(iCurrentPlayer, kCopper) Then
    iActionMoney = iActionMoney + 3
  End If
End Sub

Sub PlayTreasureMap()
  If iInt(iCurrentPlayer) < 100 Then
    If PutIntoPlay(kTreasureMap) Then
      cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 2
      Gain iCurrentPlayer, kGold, "Deck"
      Gain iCurrentPlayer, kGold, "Deck"
      Gain iCurrentPlayer, kGold, "Deck"
      Gain iCurrentPlayer, kGold, "Deck"
      iInt(iCurrentPlayer) = 100
    Else
      'Leave it "in play", so we don't try again, but don't actually play it.
      cActions = cActions + 1
    End If
  Else
    'Trash itself
    cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
  End If
End Sub

Sub PlayWitch()
  Dim i As Integer
  
  Draw iCurrentPlayer, 2
  
  For i = 0 To cPlayers
    If i <> iCurrentPlayer Then
      If Supply(kCurse) > 0 Then
        If HasInHand(i, kMoat) = 0 Then
          Gain i, kCurse
        End If
      End If
    End If
  Next i
End Sub

Sub PlayCouncilRoom()
  Dim i As Integer
  
  ' +4 Cards
  Draw iCurrentPlayer, 4
  
  ' Each other player draws a card.
  For i = 0 To cPlayers
    If i <> iCurrentPlayer Then
      Draw i, 1
    End If
  Next i
End Sub

Sub PlayThief()
  Dim i As Integer
  Dim Temp(1 To 2) As Integer
  
  For i = 0 To cPlayers
    If i <> iCurrentPlayer Then
      If HasInHand(i, kMoat) = 0 Then
      
        'Reveal 2 cards
        If cDrawPile(i) < 2 Then Shuffle i
        
        If cDrawPile(i) > 0 Then
          If cDrawPile(i) >= 2 Then
            Temp(1) = DrawPile(i, cDrawPile(i))
            cDrawPile(i) = cDrawPile(i) - 1
            Temp(2) = DrawPile(i, cDrawPile(i))
            cDrawPile(i) = cDrawPile(i) - 1
            
            'Discard the lesser
            If MoneyVal(Temp(1)) > MoneyVal(Temp(2)) Then
              cDiscardPile(i) = cDiscardPile(i) + 1
              DiscardPile(i, cDiscardPile(i)) = Temp(2)
            Else
              cDiscardPile(i) = cDiscardPile(i) + 1
              DiscardPile(i, cDiscardPile(i)) = Temp(1)
              Temp(1) = Temp(2)
            End If
          Else 'If cDrawPile(i) = 1 Then
            Temp(1) = DrawPile(i, cDrawPile(i))
            cDrawPile(i) = cDrawPile(i) - 1
          End If
                
          'If the greater is treasure, the take or trash it.
          If MoneyVal(Temp(1)) >= 1 Then
            'treasure
            If Temp(1) = kCopper Then
              'Trash it, i.e., do nothing.
            Else
              'Gain it.
              cDiscardPile(iCurrentPlayer) = cDiscardPile(iCurrentPlayer) + 1
              DiscardPile(iCurrentPlayer, cDiscardPile(iCurrentPlayer)) = Temp(1)
            End If
          Else
            'Discard it.
            cDiscardPile(i) = cDiscardPile(i) + 1
            DiscardPile(i, cDiscardPile(i)) = Temp(1)
          End If
        End If
      End If
    End If
  Next i
End Sub

Sub PlayExplorer()
  If HasInHand(iCurrentPlayer, kProvince) > 0 And Supply(kGold) > 0 Then
    Gain iCurrentPlayer, kGold
  ElseIf Supply(kSilver) > 0 Then
    Gain iCurrentPlayer, kSilver
  End If
End Sub

Sub PlaySeahag()
  Dim i As Integer
  
  For i = 0 To cPlayers
    If i <> iCurrentPlayer Then
      If HasInHand(i, kMoat) = 0 Then
        If cDrawPile(i) < 1 Then Shuffle i
        
        If cDrawPile(i) >= 1 Then
          cDiscardPile(i) = cDiscardPile(i) + 1
          DiscardPile(i, cDiscardPile(i)) = DrawPile(i, cDrawPile(i))
          cDrawPile(i) = cDrawPile(i) - 1
        End If
        
        If Supply(kCurse) > 0 Then
          Gain i, kCurse, "Deck"
        End If
      End If
    End If
  Next i
End Sub

Sub PlayMountebank()
  Dim i As Integer
  
  ' "+2 coin"
  iActionMoney = iActionMoney + 2
    
  ' "Each other player..."
  For i = 0 To cPlayers
    If i <> iCurrentPlayer Then
      If HasInHand(i, kMoat) = 0 Then
        
        ' "...may discard a Curse."
        If DiscardThis(i, kCurse) Then
          ' Do nothing
        Else
          ' "If he doesn't, he gains a Curse..."
          If Supply(kCurse) > 0 Then
            Gain i, kCurse
          End If
          
          ' "...and a Copper."
          If Supply(kCopper) > 0 Then
            Gain i, kCopper
          End If
        End If
      End If
    End If
  Next i
  
End Sub

Sub PlayCutpurse()
  Dim i As Integer
  iActionMoney = iActionMoney + 2
  
  For i = 0 To cPlayers
    If i <> iCurrentPlayer Then
      If HasInHand(i, kMoat) = 0 Then
        If DiscardThis(i, kCopper) Then
          'Nothing, either way. Just discard it.
        End If
      End If
    End If
  Next i
End Sub

Sub PlayAdventurer()
  Dim i As Integer
  Dim Temp(1 To 100) As Integer
  Dim cTemp As Integer
  Dim cTreasures As Integer
  
  cTreasures = 0
  cTemp = 0
  
  ' "Reveal cards from your deck until you reveal 2 Treasure cards...."
  Do While cTreasures < 2
    'Look at a card
    If cDrawPile(iCurrentPlayer) < 1 Then Shuffle iCurrentPlayer
    
    If MoneyVal(DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer))) >= 1 Then
      'Treasure
      ' "...Put those into your hand..."
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) + 1
      Hand(iCurrentPlayer, cHand(iCurrentPlayer)) = DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer))
      cDrawPile(iCurrentPlayer) = cDrawPile(iCurrentPlayer) - 1
      cTreasures = cTreasures + 1
    Else
      'Not treasure
      cTemp = cTemp + 1
      Temp(cTemp) = DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer))
      cDrawPile(iCurrentPlayer) = cDrawPile(iCurrentPlayer) - 1
    End If
  Loop
  
  ' "...and discard the other revealed cards."
  For i = 1 To cTemp
    cDiscardPile(iCurrentPlayer) = cDiscardPile(iCurrentPlayer) + 1
    DiscardPile(iCurrentPlayer, cDiscardPile(iCurrentPlayer)) = Temp(i)
  Next i
End Sub

Sub PlayTradingPost()
  Dim bIfYouDo As Boolean
  bIfYouDo = False
  
  ' "Trash 2 cards from your hand...."
  If PutIntoPlay(kCurse) Then
    ' Trash {--}, {-c}, {-s}, {-e}
    If PutIntoPlay(kCurse) Then
      bIfYouDo = True
    ElseIf PutIntoPlay(kEstate) Then
      bIfYouDo = True
    ElseIf PutIntoPlay(kCopper) Then
      bIfYouDo = True
    ElseIf PutIntoPlay(kSilver) Then
      bIfYouDo = True
    ElseIf Supply(kProvince) <= 3 + cPlayers And PutIntoPlay(kGold) Then
      bIfYouDo = True
    Else
      'Take the curse out of play
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) + 1
      Hand(iCurrentPlayer, cHand(iCurrentPlayer)) = InPlay(iCurrentPlayer, cInPlay(iCurrentPlayer))
      cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
    End If
  ElseIf Supply(kProvince) > 3 + cPlayers And PutIntoPlay(kEstate) Then
    ' If you don't yet want estates...
    ' Trash {ee}, or {ce}, or {se}
    If PutIntoPlay(kEstate) Then
      bIfYouDo = True
    ElseIf PutIntoPlay(kCopper) Then
      bIfYouDo = True
    ElseIf PutIntoPlay(kSilver) Then
      bIfYouDo = True
    Else
      'Take the estate out of play
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) + 1
      Hand(iCurrentPlayer, cHand(iCurrentPlayer)) = InPlay(iCurrentPlayer, cInPlay(iCurrentPlayer))
      cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
    End If
  ElseIf PutIntoPlay(kCopper) Then
    ' Trash {cc}
    If PutIntoPlay(kCopper) Then
      bIfYouDo = True
    Else
      'Take the copper out of play
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) + 1
      Hand(iCurrentPlayer, cHand(iCurrentPlayer)) = InPlay(iCurrentPlayer, cInPlay(iCurrentPlayer))
      cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 1
    End If
  End If
  
  ' "If you do, gain a silver card; put it into your hand."
  If bIfYouDo Then
    cInPlay(iCurrentPlayer) = cInPlay(iCurrentPlayer) - 2
    
    If Supply(kSilver) > 0 Then
      Gain iCurrentPlayer, kSilver
    End If
  End If
End Sub

Sub PlayLibrary()
  Dim Temp(1 To 100) As Integer
  Dim cTemp As Integer
  Dim i As Integer
  
  ' Draw until you have 7 cards in hand.
  Do While cHand(iCurrentPlayer) < 7
    Draw iCurrentPlayer, 1
    
    ' You may set aside any Action cards drawn this way, as you draw them;
    If IsActionCard(Hand(iCurrentPlayer, cHand(iCurrentPlayer))) Then
      cTemp = cTemp + 1
      Temp(cTemp) = Hand(iCurrentPlayer, cHand(iCurrentPlayer))
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) - 1
    End If
  Loop
  
  ' Discard the set aside cards after you finish drawing.
  For i = 1 To cTemp
    cDiscardPile(iCurrentPlayer) = cDiscardPile(iCurrentPlayer) + 1
    DiscardPile(iCurrentPlayer, cDiscardPile(iCurrentPlayer)) = Temp(i)
  Next i
End Sub

Sub PlayMoat()
  Draw iCurrentPlayer, 2
End Sub

Sub PlaySmithy()
  Draw iCurrentPlayer, 3
End Sub

Sub PlayGreatHall()
  Draw iCurrentPlayer, 1
  cActions = cActions + 1
End Sub

Sub PlayBureaucrat()
  Dim i As Integer

  'Gain silver
  If Supply(kSilver) > 0 Then
    Gain iCurrentPlayer, kSilver, "Deck"
  End If
  
  'Make them all put victory cards on their decks
  For i = 0 To cPlayers
    If i <> iCurrentPlayer Then
      If HasInHand(i, kMoat) = 0 Then
        If PutThisOnDeck(i, kEstate) Then
          'Nothing. You're done
        ElseIf PutThisOnDeck(i, kDuchy) Then
          'Nothing. You're done
        ElseIf PutThisOnDeck(i, kProvince) Then
          'Nothing. You're done
        ElseIf PutThisOnDeck(i, kColony) Then
          'Nothing. You're done
        ElseIf PutThisOnDeck(i, kGreatHall) Then
          'Nothing. You're done
        ElseIf PutThisOnDeck(i, kIsland) Then
          'Nothing. You're done
        End If
      End If
    End If
  Next i
End Sub

Sub PlayChapel()
  Dim i As Integer
  Dim iTrashed As Integer
  Dim iHand As Integer
  
  ' How much money do I have?
  iHand = iActionMoney
  i = 1
  Do While i <= cHand(iCurrentPlayer)
    iHand = iHand + MoneyVal(Hand(iCurrentPlayer, i))
    i = i + 1
  Loop
  
  ' Trash up to 4 cards from your hand.
  iTrashed = 0
  
  For i = cHand(iCurrentPlayer) To 1 Step -1
    If Hand(iCurrentPlayer, i) = kCurse Then
      Hand(iCurrentPlayer, i) = Hand(iCurrentPlayer, cHand(iCurrentPlayer))
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) - 1
      iTrashed = iTrashed + 1
    ElseIf Supply(kProvince) > 3 + cPlayers And Hand(iCurrentPlayer, i) = kEstate Then
      Hand(iCurrentPlayer, i) = Hand(iCurrentPlayer, cHand(iCurrentPlayer))
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) - 1
      iTrashed = iTrashed + 1
    ElseIf Supply(kProvince) > 3 + cPlayers And Hand(iCurrentPlayer, i) = kCopper Then
      If iHand = 1 Or iHand = 2 Or iHand = 4 Or iHand = 5 Or iHand = 7 Or iHand = 9 Then
        Hand(iCurrentPlayer, i) = Hand(iCurrentPlayer, cHand(iCurrentPlayer))
        cHand(iCurrentPlayer) = cHand(iCurrentPlayer) - 1
        iTrashed = iTrashed + 1
        iHand = iHand - 1
      End If
    ElseIf Hand(iCurrentPlayer, i) = kChapel Then
      Hand(iCurrentPlayer, i) = Hand(iCurrentPlayer, cHand(iCurrentPlayer))
      cHand(iCurrentPlayer) = cHand(iCurrentPlayer) - 1
      iTrashed = iTrashed + 1
    End If
    
    If iTrashed >= 4 Then Exit For
  Next i
End Sub

Sub PlayCoppersmith()
  iCopperSmithery = iCopperSmithery + 1
End Sub

Sub PlayTreasury()
  Draw iCurrentPlayer, 1
  iActionMoney = iActionMoney + 1
  cActions = cActions + 1
End Sub

Sub PlayPearlDiver()
  Dim bPutItOnTop As Boolean
  Dim iPearl As Integer
  Dim i As Integer
  
  ' +1 Card, +1 Action
  Draw iCurrentPlayer, 1
  cActions = cActions + 1
  
  ' Look at the bottom card of your deck.
  If cDrawPile(iCurrentPlayer) < 1 Then Shuffle iCurrentPlayer
  
  If cDrawPile(iCurrentPlayer) >= 2 Then
    iPearl = DrawPile(iCurrentPlayer, 1)
    Select Case iPearl
    Case kEstate, kDuchy, kProvince, kColony, kCurse
      bPutItOnTop = False
    Case kCopper
      If cTurns > 9 Then
        bPutItOnTop = False
      Else
        bPutItOnTop = True
      End If
    Case Else
      bPutItOnTop = True
    End Select
    
    ' You may put it on top.
    If bPutItOnTop Then
      For i = 2 To cDrawPile(iCurrentPlayer)
        DrawPile(iCurrentPlayer, i - 1) = DrawPile(iCurrentPlayer, i)
      Next i
      DrawPile(iCurrentPlayer, cDrawPile(iCurrentPlayer)) = iPearl
    End If
  End If
End Sub

Sub PlayLaboratory()
  Draw iCurrentPlayer, 2
  cActions = cActions + 1
End Sub

Sub PlaySmugglers()
  If Cost(iLastPurchased) <= 6 And Supply(iLastPurchased) >= 1 And iLastPurchased <> kSmugglers Then
    Gain iCurrentPlayer, iLastPurchased
    If iLastPurchased = kSmugglers Then
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    End If
  End If
End Sub

Sub PlayMonument()
  iActionMoney = iActionMoney + 2
  iVict(iCurrentPlayer) = iVict(iCurrentPlayer) + 10
End Sub

Sub ActionPhase(ByVal Strat As String)
  cActions = 1
  
  Do While cActions > 0
    ' ====== Play action-replacers first ==========================
    If PlayAction(kSpy) Then
      Call PlaySpy
    ElseIf PlayAction(kPearlDiver) Then
      Call PlayPearlDiver
    ElseIf PlayAction(kLaboratory) Then
      Call PlayLaboratory
    ElseIf PlayAction(kMarket) Then
      Call PlayMarket
    ElseIf PlayAction(kTreasury) Then
      Call PlayTreasury
    ElseIf PlayAction(kScout) Then
      Call PlayScout
    ElseIf PlayAction(kGreatHall) Then
      Call PlayGreatHall
      
    ' ====== Play non-action-replacers second =========================
    ElseIf PlayAction(kSmugglers) Then
      Call PlaySmugglers
    ElseIf PlayAction(kFeast) Then
      Call PlayFeast
    ElseIf PlayAction(kTreasureMap) Then
      Call PlayTreasureMap
    ElseIf PlayAction(kCoppersmith) Then
      Call PlayCoppersmith
    ElseIf PlayAction(kBureaucrat) Then
      Call PlayBureaucrat
    ElseIf PlayAction(kRabble) Then
      Call PlayRabble
    ElseIf PlayAction(kAdventurer) Then
      Call PlayAdventurer
    ElseIf PlayAction(kMountebank) Then
      Call PlayMountebank
    ElseIf PlayAction(kCountingHouse) Then
      Call PlayCountingHouse
    ElseIf PlayAction(kChapel) Then
      Call PlayChapel
    ElseIf PlayAction(kMine) Then
      Call PlayMine
    ElseIf PlayAction(kCouncilRoom) Then
      Call PlayCouncilRoom
    ElseIf PlayAction(kLibrary) Then
      Call PlayLibrary
    ElseIf PlayAction(kWitch) Then
      Call PlayWitch
    ElseIf PlayAction(kSeahag) Then
      Call PlaySeahag
    ElseIf PlayAction(kSmithy) Then
      Call PlaySmithy
    ElseIf PlayAction(kMonument) Then
      Call PlayMonument
    ElseIf PlayAction(kIsland) Then
      Call PlayIsland
    ElseIf PlayAction(kWorkshop) Then
      Call PlayWorkshop
    ElseIf PlayAction(kCutpurse) Then
      Call PlayCutpurse
    ElseIf PlayAction(kThief) Then
      Call PlayThief
    ElseIf PlayAction(kExplorer) Then
      Call PlayExplorer
    ElseIf PlayAction(kIronworks) Then
      Call PlayIronworks
    ElseIf PlayAction(kTradingPost) Then
      Call PlayTradingPost
    ElseIf PlayAction(kMoat) Then
      Call PlayMoat
    ElseIf PlayAction(kMoneylender) Then
      Call PlayMoneylender
    Else
      ' No action cards in hand, even though you have actions left
      Exit Do
    End If
  Loop
End Sub

Sub Desupply(ByVal iCard As Integer)
  Supply(iCard) = Supply(iCard) - 1
  If Supply(iCard) < 1 Then
    cDepletedSupplyPiles = cDepletedSupplyPiles + 1
  End If
End Sub

Sub Buy(ByVal iCard As Integer)
  Call Gain(iCurrentPlayer, iCard)
  iLastPurchased = iCard
End Sub

Sub BuyPhase(ByVal Strat As String)
  Dim iHand As Integer
  Dim i As Integer
  
  ' How much treasure do you have?
  iHand = iActionMoney
  i = 1
  Do While i <= cHand(iCurrentPlayer)
    iHand = iHand + MoneyVal(Hand(iCurrentPlayer, i))
    i = i + 1
  Loop
  
  ' What to buy?
  Select Case Strat
    
  Case "TB"
    ' Ideal Non-Prosperity TreasureBot:
    ' Always buy provinces.
    ' Buy duchies when there are 8 or fewer provinces left (with 4 players)
    ' Buy estates when there are 6 or fewer provinces left (with 4 players)
    ' Otherwise, buy the best treasure you can.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "TB2"
  ' Duplicate, for testing.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "ProsTB"
    ' Ideal Prosperity TreasureBot:
    ' Always buy colonies.
    ' Buy provinces when [colonies/provinces] is down to 10.
    ' Buy duchies when [colonies/provinces] is down to 10 (with 4 players)
    ' Buy estates when [colonies/provinces] is down to 5 (with 4 players)
    ' Otherwise, buy the best treasure you can.
    If iHand >= 11 Then
      Buy kColony
    ElseIf iHand >= 8 And (Supply(kColony) <= 10 Or Supply(kProvince) <= 10) Then
      Buy kProvince
    ElseIf iHand >= 9 And Supply(kPlatinum) > 0 Then
      Buy kPlatinum
    ElseIf iHand >= 5 And (Supply(kColony) <= 10 Or Supply(kProvince) <= 10) And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And (Supply(kColony) <= 5 Or Supply(kProvince) <= 5) And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  Case "CouncilRoom"
    ' Buy Council Room 1 time at $5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kCouncilRoom) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kCouncilRoom
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Market"
    ' Always buy Market at $5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kMarket) > 0 Then
      Buy kMarket
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Chapel"
  ' Buy chapel 1 time at $2-$5
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 2 And Supply(kChapel) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kChapel
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    End If
    
  Case "TradingPost"
    ' Buy Trading Post 1 time at $5-$7.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 5 And Supply(kTradingPost) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kTradingPost
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Harem"
    ' Always buy Harem at $6-$7.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kHarem) > 0 Then
      Buy kHarem
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "GreatHall"
    ' Buy GreatHall at $3-$5 starting at turn 10
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 3 And Supply(kGreatHall) > 0 And cTurns > 9 Then
      Buy kGreatHall
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Explorer"
    ' Buy Explorer 2 times at $5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kExplorer) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kExplorer
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Adventurer"
    ' Buy adventurer 1 time at $6-$7.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kAdventurer) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kAdventurer
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Library"
    ' Buy library 2 times at $5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kLibrary) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kLibrary
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Mountebank"
    ' Buy Mountebank always at $5 and once at $6-$7 (if you have none).
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 5 And Supply(kMountebank) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kMountebank
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kMountebank) > 0 Then
      Buy kMountebank
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "MountebankMoat"
    ' Buy Mountebank always at $5 and once at $6-$7 (if you have none).
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 5 And Supply(kMountebank) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kMountebank
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kMountebank) > 0 Then
      Buy kMountebank
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf iHand >= 2 And Supply(kMoat) > 0 Then
      Buy kMoat
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Mine"
    ' Buy a Mine 1 time at $5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kMine) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kMine
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Thief"
    ' Buy 3 thieves.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kThief) > 0 And iInt(iCurrentPlayer) < 3 Then
      Buy kThief
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Smugglers"
    ' Buy this action 1 time at $3.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSmugglers) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kSmugglers
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Treasury"
    ' Always buy this at $5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kTreasury) > 0 Then
      Buy kTreasury
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "PearlDiver"
    ' Always buy Pearl Diver at $2.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    End If
  
  Case "CountingHouse"
    ' Buy Counting House 2 times at $5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kCountingHouse) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kCountingHouse
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Rabble"
    ' Buy Rabble 2 times at $5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kRabble) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kRabble
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "RabbleMoat"
    ' Buy Rabble 2 times at $5. +Moat
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand = 5 And Supply(kRabble) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kRabble
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf iHand >= 2 And Supply(kMoat) > 0 Then
      Buy kMoat
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Seahag"
    ' Buy 2 seahags.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kSeahag) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kSeahag
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "SeahagMoat"
    ' Like seahag and moat together.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kSeahag) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kSeahag
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf iHand >= 2 And Supply(kMoat) > 0 Then
      Buy kMoat
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
      
  Case "Moat"
    'Buy a Moat for 2, and Moat for 3-5 if you don't yet have one.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kMoat) > 0 And iInt(iCurrentPlayer) = 0 Then
      Buy kMoat
      iInt(iCurrentPlayer) = 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf iHand >= 2 And Supply(kMoat) > 0 Then
      Buy kMoat
      iInt(iCurrentPlayer) = 1
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  Case "TreasureMap"
    ' Buy up to 4 Treasure Maps (or until they trigger)
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kTreasureMap) > 0 And iInt(iCurrentPlayer) < 4 Then
      Buy kTreasureMap
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Monument"
    ' Buy 2 Monuments.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kMonument) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kMonument
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  Case "Bureaucrat"
    ' Buy 1 Bureaucrat.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kBureaucrat) > 0 And iInt(iCurrentPlayer) = 0 Then
      Buy kBureaucrat
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
        
  Case "BureaucratMoat"
    ' Like Bureaucrat and Moat.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kBureaucrat) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kBureaucrat
      If iInt(iCurrentPlayer) = 1 Then iInt(iCurrentPlayer) = 3 Else iInt(iCurrentPlayer) = 2
    ElseIf iHand >= 3 And Supply(kMoat) > 0 And (iInt(iCurrentPlayer) = 0 Or iInt(iCurrentPlayer) = 2) Then
      Buy kMoat
      If iInt(iCurrentPlayer) >= 2 Then iInt(iCurrentPlayer) = 3 Else iInt(iCurrentPlayer) = 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf iHand >= 2 And Supply(kMoat) > 0 Then
      Buy kMoat
      If iInt(iCurrentPlayer) >= 2 Then iInt(iCurrentPlayer) = 3 Else iInt(iCurrentPlayer) = 1
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Moneylender"
    ' Buy 1 moneylender.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kMoneylender) > 0 And iInt(iCurrentPlayer) = 0 Then
      Buy kMoneylender
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  Case "Coppersmith"
    ' Buy this action 1 time at $4.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 4 And Supply(kCoppersmith) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kCoppersmith
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Workshop"
    ' Buy a single workshop.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kWorkshop) > 0 And iInt(iCurrentPlayer) = 0 Then
      Buy kWorkshop
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  Case "Smithy"
    ' Buy a single smithy.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kSmithy) > 0 And iInt(iCurrentPlayer) = 0 Then
      Buy kSmithy
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  Case "Cutpurse"
    ' Buy buy 2 cutpurses.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kCutpurse) > 0 And iInt(iCurrentPlayer) < 2 Then
      Buy kCutpurse
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  Case "Ironworks"
    ' Buy Ironworks 1 time at $4-$5.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 4 And Supply(kIronworks) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kIronworks
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Island"
    ' Buy an island for $4-$5 every chance you get.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 4 And Supply(kIsland) > 0 Then
      Buy kIsland
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
'    ElseIf Supply(kCopper) > 0 Then
'      Buy kCopper
    End If
    
  Case "Scout"
    ' Buy a scout after each gold is bought.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kScout) > 0 And iInt(iCurrentPlayer) > 0 Then
      Buy kScout
      iInt(iCurrentPlayer) = -10
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  Case "Spy"
    ' Buy a spy for $4-$5 1 time.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand >= 4 And Supply(kSpy) > 0 And iInt(iCurrentPlayer) = 0 Then
      Buy kSpy
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
        
  Case "WitchMoat"
    ' Buy a Witch with $5, a Moat for $2, and Moat for $3-$4 if you don't yet have one.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf (iHand = 5) And Supply(kWitch) > 0 Then
      Buy kWitch
    ElseIf iHand >= 3 And Supply(kMoat) > 0 And iInt(iCurrentPlayer) = 0 Then
      Buy kMoat
      iInt(iCurrentPlayer) = 1
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf iHand >= 2 And Supply(kMoat) > 0 Then
      Buy kMoat
      iInt(iCurrentPlayer) = 1
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Witch"
    ' Buy a Witch with $5 always.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf (iHand = 5) And Supply(kWitch) > 0 Then
      Buy kWitch
    ElseIf iHand >= 3 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "FeastWitch"
    ' Buy a Witch with $5 always. Buy a Feast for $4 once.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf (iHand >= 5) And Supply(kWitch) > 0 Then
      Buy kWitch
    ElseIf (iHand >= 4) And Supply(kFeast) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kFeast
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "FeastWitchMoat"
    ' Buy a Witch with $5 always. Buy a Feast for $4 once.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf (iHand >= 5) And Supply(kWitch) > 0 Then
      Buy kWitch
    ElseIf (iHand >= 4) And Supply(kFeast) > 0 And iInt(iCurrentPlayer) < 1 Then
      Buy kFeast
      iInt(iCurrentPlayer) = iInt(iCurrentPlayer) + 1
    ElseIf iHand >= 3 Then
      Buy kSilver
    ElseIf iHand >= 2 And Supply(kMoat) > 0 Then
      Buy kMoat
      iInt(iCurrentPlayer) = 1
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
  
  Case "Laboratory"
    ' Buy a lab with $5 every chance you get.
    If iHand >= 8 Then
      Buy kProvince
    ElseIf iHand >= 5 And Supply(kProvince) <= 5 + cPlayers And Supply(kDuchy) > 0 Then
      Buy kDuchy
    ElseIf iHand >= 6 And Supply(kGold) > 0 Then
      Buy kGold
    ElseIf iHand >= 2 And Supply(kProvince) <= 3 + cPlayers And Supply(kEstate) > 0 Then
      Buy kEstate
    ElseIf iHand = 5 And Supply(kLaboratory) > 0 Then
      Buy kLaboratory
    ElseIf iHand >= 3 And Supply(kSilver) > 0 Then
      Buy kSilver
    ElseIf Supply(kCopper) > 0 Then
      Buy kCopper
    End If
    
  End Select
End Sub

' I can't believe Visual Basic doesn't have these built in!
Function Max(ParamArray TheValues() As Variant) As Integer
  Dim intLoop As Integer
  Dim varCurrentMax As Integer
  varCurrentMax = TheValues(LBound(TheValues))
  For intLoop = LBound(TheValues) + 1 To UBound(TheValues)
    If TheValues(intLoop) > varCurrentMax Then
      varCurrentMax = TheValues(intLoop)
    End If
  Next intLoop
  Max = varCurrentMax
End Function

Function Min(ParamArray TheValues() As Variant) As Integer
  Dim intLoop As Integer
  Dim varCurrentMin As Integer
  varCurrentMin = TheValues(LBound(TheValues))
  For intLoop = LBound(TheValues) + 1 To UBound(TheValues)
    If TheValues(intLoop) < varCurrentMin Then
      varCurrentMin = TheValues(intLoop)
    End If
  Next intLoop
  Min = varCurrentMin
End Function

Comments