package com.mbelsky.controller;
import com.mbelsky.model.Card;
import com.mbelsky.model.player.*;
import com.mbelsky.view.DialogWindow;
import java.util.ArrayList;
import java.util.List;
/**
* User: mbelsky
* Date: 05.10.13
* Time: 21:04
*/
public class GameController {
private static final int PLAYERS_COUNT = 4;
private static final int MAX_VALID_SCORE = 21;
private final DialogWindow dialogWindow = new DialogWindow();
private final List<Player> players = new ArrayList<Player>( PLAYERS_COUNT);
private Dealer dealer;
private int bank;
public void play() {
int playersCount = 0;
do {
final String answer = dialogWindow.getAnswer( "How many humans want to play in the game(enter positive integer)?\n");
try {
playersCount = Integer.parseInt( answer);
} catch (NumberFormatException ignored) {
dialogWindow.print( "Incorrect value. Please retry.");
}
}while ( playersCount <= 0 );
initPlayers( playersCount);
Boolean play;
do {
startRound();
do {
final String answer = dialogWindow.getAnswer( "Start next round (enter 'y'(yes) or 'n'(no))?\n");
if ( "y".equals( answer) ) {
play = true;
} else if ( "n".equals( answer) ) {
play = false;
} else {
dialogWindow.print( "Incorrect answer. Please retry.");
play = null;
}
}while ( null == play );
}while ( play );
}
private void initPlayers(final int playersCount) {
players.clear();
for (int i = 0; i < playersCount; i++) {
players.add( new Human( dialogWindow));
}
players.add( new QuietBot( dialogWindow));
players.add( new GamblerBot( dialogWindow));
players.add( (dealer = new Dealer( dialogWindow)) );
}
private void startRound() {
dealer.refreshCardDesks();
doBet();
dialogWindow.print( String.format("Bank: %d\n", bank));
dealsCards();
showPlayersCards();
final List<Player> winners = searchPlayersWithBJ();
if ( 0 == winners.size() ) {
dealsAdditionalCards();
winners.addAll( searchWinners());
}
showWinners( winners);
throwCards();
}
private void doBet() {
bank = 0;
for (final Player player : players)
bank += player.getBet();
}
private void dealsCards() {
for(final Player player : players ) {
for(int i = 0; i < 2; i++)
player.fetchCard( dealer.getCard());
if ( !canPlay( player) ) { // players cards: Ace & Ace
player.useAce();
}
}
}
private void dealsAdditionalCards() {
for (final Player player : players) {
if ( player == dealer ) {
dealer.setSecondCardShowed( true);
}
showPlayerCards( player);
dialogWindow.print( String.format( "Deals additional cards for %s\n", player.getName()));
boolean firstRun = true;
while ( true ) {
if ( MAX_VALID_SCORE == player.getScore()
|| (!canPlay( player) && !player.useAce()) ) {
showPlayerCards( player);
showPlayerScore( player);
break;
} else if ( !firstRun ) {
showPlayerCards( player);
dialogWindow.print( "");
}
dialogWindow.print(String.format("%s: card? (enter 'y'(yes) or 'n'(no))", dealer.getName()));
if ( player.hitMe() ) {
player.fetchCard( dealer.getCard());
}
else {
showPlayerScore( player);
break;
}
firstRun = false;
}
}
}
private void showPlayerScore(final Player player) {
dialogWindow.print( String.format( "%s score: %d\n", player.getName(), player.getScore()));
}
private boolean canPlay(final Player player) {
return !( MAX_VALID_SCORE < player.getScore() );
}
private List<Player> searchPlayersWithBJ() {
final List<Player> playersWithBJ = new ArrayList<Player>( players.size());
for (final Player player : players) {
final boolean haveAce = player.haveAce();
if ( !haveAce )
continue;
searchImage:
for (final Card card : player.getCards()) {
switch ( card.getName() ) {
case TEN:
case JACK:
case QUEEN:
case KING: {
playersWithBJ.add( player);
break searchImage;
}
}
}
}
if ( playersWithBJ.contains( dealer) && playersWithBJ.size() > 1 ) {
playersWithBJ.remove( dealer);
}
return playersWithBJ;
}
private List<Player> searchWinners() {
final List<Player> winners = new ArrayList<Player>( players.size());
final List<Integer> playersScoreList = new ArrayList<Integer>( players.size());
for (final Player player : players) {
playersScoreList.add( player.getScore());
}
int maxScore = 0;
for (int i = 0; i < playersScoreList.size(); i++) {
final int score = playersScoreList.get( i);
if ( MAX_VALID_SCORE < score )
continue;
if ( score > maxScore ) {
maxScore = score;
winners.clear();
}
if ( score == maxScore ) {
winners.add( players.get( i));
}
}
return winners;
}
private void showPlayersCards() {
for (final Player player : players) {
showPlayerCards(player);
}
dialogWindow.print( "");
}
private void showPlayerCards(final Player player) {
final List<Card> cards = player.getCards();
final StringBuilder stringBuilder = new StringBuilder( player.getName());
stringBuilder.append( " cards: ");
if ( player == dealer ) {
for (int i = 0; i < cards.size(); i++ ) {
final Card card = cards.get( i);
if ( 1 == i && !dealer.isSecondCardShowed() ) {
stringBuilder.append( "Unknown card");
break;
} else {
stringBuilder.append( card)
.append( " ");
}
}
} else {
for (final Card card : cards)
stringBuilder.append( card)
.append( " ");
}
if ( player != dealer || dealer.isSecondCardShowed() ) {
stringBuilder.append( String.format( "(%d)", player.getScore()));
}
dialogWindow.print( stringBuilder.toString());
}
private void showWinners(final List<Player> winners) {
final int winnersCount = winners.size();
if ( 0 == winnersCount ) {
dialogWindow.print( "No winners.\n");
return;
}
final int prize = bank / winnersCount;
for (final Player winner : winners) {
dialogWindow.print( String.format("%s win a prize %d", winner.getName(), prize));
}
dialogWindow.print( "");
}
private void throwCards() {
for (final Player player : players)
player.throwCards();
}
}