GoFish.jl is a Julia package for playing and simulating the card game Go Fish.
To install GoFish.jl, enter the following into the REPL:
] add https://github.com/itsdfish/GoFish.jl
You can play Go Fish interactively within the Julia REPL using the keyboard. Interactive play requires creating a dictionary of players, a game object, and passing both to the play function. The human player must be a Human
, but the other players can be any subtype of AbstractPlayer
. The following example shows how to play interactively through the REPL. In this example, your opponents are Bernice and Joy.
using GoFish
ids = (:you, :Bernice,:Joy)
types = (Human,Player,Player)
players = Dict(id => t(;id) for (t,id) in zip(types,ids))
game = PlayGame(;ids = ids)
play(game, players)
Simulating Go Fish requires a dictionary of players, and a game object. Players must be a subtype of AbstractPlayer
. If using heterogenous types, use a dictionary of type Dict{I,Union{T1,..}}
to improve performance. The following code is a minimum working example of a simulation.
using GoFish
ids = (:Penelope,:Manuel,:Beelzebub)
players = Dict(id => Player(;id) for id in ids)
game = Game(ids)
deal!(game, players)
simulate!(game, players)
The outcome of the simulation can be found with game.books
.
GoFish.jl allows you to create a player with custom behavior. The process involves creating a new subtype of AbstractPlayer
and defining a decision method and four optional methods for setup and tracking the exchange of cards.
At minimum the custom subtype requires a field id
and cards
. Additional fields can be included as needed.
mutable struct MyPlayer{T} <: AbstractPlayer
id::T
cards::Vector{Card}
end
The decision logic of the player is written in the method decide
. This method receives the player object, and a set of player ids. decide
must return a player id and a card value.
function decide(player::MyPlayer, ids)
# awesomeness goes here
return player_id,card_value
end
After the cards are delt, initial setup of the player can be optionally performed in the function setup!
, which is called once prior to the game begining. The arguments for setup
are the player and player ids.
function setup!(player::MyPlayer, ids)
# awesomeness goes here
return nothing
end
The player's representation of the game is optionally updated through three methods: process_exchange!
, process_go_fish!
, and process_books!
. The method process_exchange!
allows the player to observe and process an exchange of cards between the inquirer and the opponent.
function process_exchange!(player::MyPlayer, inquirer_id, opponent_id, value, cards)
# awesomeness goes here
return nothing
end
process_go_fish!
allows the player to observe and that a player received an unknown card after going fish. process_go_fish!
is also called when a player runs replinishes an empty hand.
function process_go_fish!(player::MyPlayer, inquirer_id, n_cards)
# awesomeness goes here
return nothing
end
Finally, process_books!
allows the player to track which cards are no longer in play. The argument book_map
is a dictionary that maps player id to a vector of cards
function process_books!(player::AbstractPlayer, book_map)
# awesomeness goes here
return nothing
end
Additional documentation for functions exported through the API can be called through the REPL with
? function_name