BS is a card game where the object of the game is to lose all of your cards.
A game consists of four players and a 52-card deck. Each player is randomly dealt 13 cards. Normally, cards are labeled 2 - 10, Ace, Jack, Queen, King, but for simplicity, the cards will be labeled with a number from 0 - 12 inclusive. Although the number of cards in a player's hand is public information, only the player knows what specific cards are in his hand.
The game goes as follows: the first player places as many cards labeled 0 as he wants to in the discard pile (note that he is not required to play all of his cards labeled 0, though usually it is in his best interest to do so). He must play at least one card. The second player plays as many cards as he wants to labeled 1, the third player plays 2, and so on. After 12, it resets to 0.
What happens if you don't have any of the cards that you are supposed to play? Remember, you must play at least one card -- in fact, you can play any cards you want! (Actually, even if you have the right card, you can lie and play a different card). However, someone can call you out and say, "BS!" If that someone is correct and you had lied, then you must take all the cards in the discard pile; as a reward, the player who called you out randomly places one of their cards in the discard pile. If the accuser is wrong, however, he must take all the cards in the discard pile. Note that you can't lie about the number of cards that you play.
More detailed info:
- At the beginning of the game, four random players are chosen to play. Since there will be at least 1000 games, each player will get a chance to play. The turn order is randomly decided at the beginning of the game
- If you return one correct card and one incorrect card, then it is considered lying (i.e. if you were supposed to give 2s, and you gave one 2 and one 1, then that's lying)
- If two or more players both say BS at the same time, then one is randomly chosen.
- Your score is the percent of games that you win.
- There is a maximum 1000 rounds, where one round is every player going once. Usually, someone wins before this. If no one wins, then it is counted towards the total number of games played, but no one wins.
Spec:
You should write a class which extends Player
. It will look like:
package players;
import java.util.ArrayList;
import java.util.List;
import controller.*;
public class Player1 extends Player {
@Override
protected List<Card> requestCards(int card, Controller controller) {
Card[] hand = getHand();
List<Card> ret = new ArrayList<Card>();
for (Card c : hand) {
if (c.getNumber() == card) {
ret.add(c);
}
}
if (ret.size() == 0) ret.add(hand[0]);
return ret;
}
@Override
protected boolean bs(Player player, int card, int numberOfCards, Controller controller) {
return numberOfCards >= 3;
}
protected void update(Controller controller) {
// This method gets called once at the end of every round
}
protected void initialize(Controller controller) {
// This method gets called once at the beginning once all the cards are dealt
}
public String toString() {
return "Player 1";
}
}
The method requestCards
is called when it is your turn. The argument card
is the card number that you are supposed to provide. You return a list of cards that you want to put in the discard pile. The player above checks to see if he has any cards of the requested card type; if not, he simply plays his first card and hopes no one checks.
The method bs
is called whenever someone else plays a card. The first argument is the player, the second - the card he was supposed to play, and the third - the number of that type of card that he claims that he has played. Return true
if you want to call "BS." In the code above, the player only calls "BS" when the other player claims to have 3 or more cards of the requested type.
The last argument for both methods is controller
, which is just the controller that controls the game. From the controller, you can get more public information, such as the number of cards in the discard pile or the list and turn order of the players.
The toString
method is optional.
Conroller on GitHub: https://github.com/prakol16/bs
If you want to post a non-java solution, you can use the interface provided in https://github.com/LegionMammal978/bs (credits to LegionMammal978) and I'll try to integrate it.
Scoreboard so far:
class players.PlayerConMan: 2660/4446 = 59.82905982905983%
class players.CalculatingLiar: 2525/4426 = 57.049254405784005%
class players.PlayerTruthy: 1653/4497 = 36.75783855903936%
class players.Player4: 1446/4425 = 32.67796610169491%
class players.Player1: 536/4382 = 12.23185759926974%
class players.Player3: 493/4425 = 11.141242937853107%
class players.Player2: 370/4451 = 8.312738710402156%
class players.LiePlayer: 317/4432 = 7.152527075812275%
class players.Hoarder: 0/4516 = 0.0%
PlayerConMan is winning, but CalculatingLiar is in a close second. These scores seem consistent -- they are fairly the same every time.
Controller.toString()
to public, as it returns the hands of all players and the discard pile. \$\endgroup\$