using System;
using System.Collections.Generic;
using System.Linq;
using CardGame;
using Daifugou;
///
/// 出せる限り必ずカードを出すおバカAI。
///
public class SampleShortsitedAi : IArtificialIntelligence
{
#region IArtificialIntelligence メンバ
public IEnumerable Play(IEnumerable hand, IEnumerable table, int rank, Suit suit, Mode mode, bool revolution, History history)
{
if (revolution && rank != Card.RankOfJoker)
{
rank = 14 - rank;
}
if (hand == null || hand.Count() == 0)
return null;
int count = table.Count();
// 初手はとりあえず一番弱いのを出しとく。
if (mode.Match(Mode.First))
{
var min = hand.Min(x => Game.Rank(x, revolution));
return hand.Where(x => Game.Rank(x, revolution) == min);
}
if (mode.Match(Mode.Normal))
{
if(mode.Match(Mode.SuitBound))
{
return hand.MinCard(x => Game.Rank(x, revolution) > rank && x.Suit == suit, revolution);
}
else
{
return hand.MinCard(x => Game.Rank(x, revolution) > rank, revolution);
}
}
if(mode.Match(Mode.Multiple))
{
for (int i = rank + 1; i <= 13; i++)
{
// 出せる
var c = hand.Where(x => Game.Rank(x, revolution) == i);
if (c.Count() >= count)
return c.Take(count);
// Joker含めれば出せる
if (c.Count() + 1 == count && hand.FirstOrDefault(x => x.Suit == Suit.Joker) != null)
return c.Concat(hand.Where(x => x.Suit == Suit.Joker).Take(count));
}
}
if (mode.Match(Mode.SequenceBound))
return null; //todo また未対応
if (mode.Match(Mode.Sequence))
{
if (mode.Match(Mode.SuitBound))
return hand.Sequence(rank, revolution, count, suit);
else
return hand.Sequence(rank, revolution, count);
}
return null;
}
#endregion
}
static class CardsExtesions
{
///
/// cardsの中から、条件predを満たす最少ランクのカードを返す。
///
/// 対象となる札。
/// 条件。
/// 条件を満たす最少ランクのカード。
public static IEnumerable MinCard(this IEnumerable cards, Func pred, bool revolution)
{
cards = cards.Where(pred);
if (cards == null || cards.Count() == 0)
return null;
int min = int.MaxValue;
Card minCard = cards.First();
foreach (var c in cards)
{
var rank = Game.Rank(c, revolution);
if (min > rank)
{
min = rank;
minCard = c;
}
}
return new[] { minCard };
}
public static IEnumerable Sequence(this IEnumerable cards, int rank, bool revolution, int count, Suit suit)
{
int jokers = cards.Count(x => x.Suit == Suit.Joker);
return cards.Sequence(rank, revolution, count, suit, jokers);
}
public static IEnumerable Sequence(this IEnumerable cards, int rank, bool revolution, int count, Suit suit, int jokers)
{
var c = cards.Where(x => Game.Rank(x, revolution) > rank && (x.Suit == suit));
if (c.Count() < count)
return null;
var cc = c.OrderBy(x => Game.Rank(x, revolution)).ToArray();
for (int i = 0; i <= cc.Length - count; i++)
{
var ccc = cc.Skip(i).Take(count);
if (Game.IsSequence(ccc) != 0)
{
return ccc;
}
}
if (jokers == 0)
return null;
for (int i = 0; i <= cc.Length - count; i++)
{
var ccc = cc.Skip(i).Take(count - 1).Concat(new[] { new Card(Suit.Joker, 1) });
if (Game.IsSequence(ccc) != 0)
{
return ccc;
}
}
return null;
}
public static IEnumerable Sequence(this IEnumerable cards, int rank, bool revolution, int count)
{
var ss = new[] { Suit.Club, Suit.Spade, Suit.Heart, Suit.Diamond };
int jokers = cards.Count(x => x.Suit == Suit.Joker);
foreach (var s in ss)
{
var c = cards.Sequence(rank, revolution, count, s, jokers);
if (c != null)
return c;
}
return null;
}
}