public ITrade HandleTrade(IGameState state, ITrade offer, int proposingPlayerId)
{
// accept if convert extras to needed and opponent < 7 points
List<Resource> extras = new List<Resource>();
foreach (Resource r in Enum.GetValues(typeof(Resource)))
{
int extra = state.GetOwnResources().Count(res => res == r) - 1;
for (int i = 0; i < extra; i++) extras.Add(r);
}
// good offer?
var valid = offer.Give.Where(o => o.All(r => o.Count(cur => cur == r) <= extras.Count(e => e == r)));
if (valid.Count() == 0) return offer.Decline();
// take the one with least cards to give, and then by most duplicates
List<Resource> bestGive = valid.OrderBy(o => o.Count)
.ThenByDescending(o => state.GetOwnResources().Sum(r => state.GetOwnResources().Count(res => res == r)))
.First();
// find best "take" (cards we get) kind of the opposite of above
List<Resource> bestTake = offer.Take.OrderBy(o => o.Count)
.ThenBy(o => state.GetOwnResources().Sum(r => state.GetOwnResources().Count(res => res == r)))
.First();
return offer.Respond(bestGive, bestTake);
}