package controls;
import interfaces.IBotBehavior;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
import static views.Constants.DECK_COUNT;
public class BotIntelligence implements IBotBehavior {
TurnBot turnBot;
public BotIntelligence(TurnBot turnBot) {
this.turnBot = turnBot;
}
/**
* 未確定の数字を列挙する
*/
List<Integer> calculateCandidate() {
//候補の初期化
List<Integer> candidates = new ArrayList<Integer>();
for (int i = 0; i < DECK_COUNT; i++) candidates.add(i);
candidates.removeAll(turnBot.getOpponentHands().stream().map(x -> x.getKey()).collect(Collectors.toList()));
candidates.removeAll(turnBot.getMyHands().stream().filter(x -> x.getValue()).map(x -> x.getKey()).collect(Collectors.toList()));
return candidates;
}
/**
* 相手の手札に対して、候補となる数字を割り当てる
*
* @return 候補のリスト
*/
List<int[]> assignCandidateNumberEachHand() {
List<Map.Entry<Integer, Boolean>> myHands = turnBot.getMyHands();
List<int[]> result = new ArrayList<int[]>();
for (Map.Entry<Integer, Boolean> card : myHands) {//ユーザーの手札を左から見ていく
int index = myHands.indexOf(card);//左からindex番目に
List<Integer> candidateList = calculateCandidate();//確認するカード
if (card.getValue()) {
candidateList.clear();
} else { //裏の場合
//そのカードから右隣のカードを確認していく
for (int i = 0; i < myHands.size() - index - 1; i++) {
//今確認していっているカード
Map.Entry<Integer, Boolean> currentCard = myHands.get(i + index + 1);
if (currentCard.getValue()) {//確認しているカードが表なら、(YES)
candidateList.removeIf(x -> x > currentCard.getKey());//その確認したカードの数字より大きい数字を除外する。
for (int j = 1; j < i; j++) {//そして、その確認したカードよりjだけ小さいそのカードからj番目の数字を除外する。
candidateList.remove(candidateList.size() - 1);
}
break;
}
}
//そのカードから左隣のカードを確認していく
for (int i = 1; i <= index; i++) {
//今確認していっているカード
Map.Entry<Integer, Boolean> currentCard = myHands.get(index - i);
if (currentCard.getValue()) {//表があれば、それより小さい数字を候補から削除する
candidateList.removeIf(x -> x < currentCard.getKey());
}
}
}
String s = (card.getValue() ? "+" : "-") + card.getKey() + ":[";
for (int i : candidateList) s += i + " ";
s += "]\n";
System.out.println(s);
result.add(candidateList.stream().mapToInt(x -> x).toArray());
}
return result;
}
//公開されていないカードのインデックスを選ぶ(カードにかかれている番号ではない)
@Override
public int selectAttacker() {
List<Map.Entry<Integer, Boolean>> botHands = turnBot.getOpponentHands();
for (Map.Entry<Integer, Boolean> i : botHands) {//小さいものから選択
if (!i.getValue()) return botHands.indexOf(i);
}
return 0;
}
@Override
public int selectTarget() {
List<int[]> candidate = assignCandidateNumberEachHand();
int result = 0;
int min = DECK_COUNT;
for (int[] i : candidate) {
if (i.length < min && i.length != 0) {
result = candidate.indexOf(i);
min = i.length;
}
}
return result;
}
@Override
public int declareNumber(int target) {
int[] array = assignCandidateNumberEachHand().get(target);
return array[new Random().nextInt(array.length)];
}
}