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