Poke is a really simple incomplete-information game. It's like "Poker", but simpler. At the start of every round, each player is dealt a hand. To simplify things, a hand is a uniformly distributed random number between 0 and 1. Each player only knows their own hand. The player that wins the round is the one whose hand has the greatest value.
Every turn, all the players who are still in the round make a bet that they're the player with the best hand. Each player has to decide whether or not to match the largest bet. If they match it, that amount is added to the pot from their account. If they choose not to match it, they drop out of the round. Even if they had the best hand, they can't win once they drop out, and they lose everything they had in the pot. At the end of the round, the player with the best hand out of those that haven't dropped wins. (Each player knows how many turns are gonna be in the round since the start of the round).
The winner is the one that makes the most money after a large number of rounds (hundreds, or thousands). In order to compete, write a struct that inherits from this "player" class:
class player
{
private:
double _hand;
game* _owner = 0;
public:
//You must provide
bool set_new_owner(game* current, game* new_owner) {
if(current == _owner) { _owner = new_owner; return true; }
return false;
}
bool set_new_hand(game* current, double new_hand) {
if(current == _owner) { _hand = new_hand; return true; }
return false;
}
double hand() const { return _hand; }
virtual double bet(const round_info&) = 0;
virtual bool take_bet(const round_info&) = 0;
virtual std::string name() { return typeid(*this).name(); }
virtual ~player() {}
};
All you need to do is specialize the "bet" function (which determines how much your player bets each turn), and the "take_bet" function (which determines whether or not to take the bet. Here are some examples:
struct grog : player
{
//Always bets the minimum amount
double bet(const round_info&) { return 1.0; }
//Takes any bet
bool take_bet(const round_info&) { return true; }
string name() { return "Grog"; }
};
struct bob : player
{
//Bet the minimum amount
double bet(const round_info&) { return 1.0; }
//Only take bets when you have a good hand
bool take_bet(const round_info&) { return hand() > 0.95; }
string name() { return "Bob"; }
};
struct james : player
{
//Raise the bet a lot if you have a *really* good hand
double bet(const round_info&) {
if(hand() > 0.99) return 1000.0;
else return 1.0;
}
//Only take bets when you have a *really* good hand
bool take_bet(const round_info&) { return hand() > 0.99; }
string name() { return "James"; }
};
struct rainman : player
{
//Play it safe
double bet(const round_info&) { return 1.0; }
bool take_bet(const round_info& r)
{
double cost = r.current_max_bet();
double winnings = r.winnings() + r.current_max_bet() * r.n_active_players();
int players = r.n_players();
double hand = this->hand();
double p_win = pow(hand,players - 1);
double p_loss = 1 - p_win;
double gain = -(cost * p_loss) + p_win * winnings;
if(gain > 0) return true;
return false;
}
string name() { return "Rainman"; }
};
If all four people are playing, then over a few thousand games, James will be the winner and Rainman will do worse than anyone but Grog. But if only Bob, Grog, and Rainman are playing, Rainman will clean the floor with the other players (and win tons of money).
Edit: Here is the code for round_info
and for the class that will manage the game. https://github.com/Artifexian/PokeGame
Edit 2: If you submit something not in C++, I can try to translate it into C++ for you. If you want me to, I will edit your answer and append my translated version.
Edit 3: I will work to write a wrapper for non-c++ languages. Your solution must include 2 functions: something to determine how much to bet (which should return a floating point value), and something to determine whether or not to stay in the round (which should return true or false). Contact me about your preferring input format. I will write something to translate "round_info" into text. The data provided as text will be the same data provided to everyone else. It will include:
- The current turn number
- The maximum number of turns (when the round ends)
- The number of players
- The number of players who haven't dropped out
- The history of what each player has bet
- A list of which players haven't dropped out
- The size of the pot
- The current maximum bet amount (what you have to put down to stay in the game)
- Your hand
Edit 4: Any bets made by players will be clipped to be between 1 and 10^6