Skip to content

Instantly share code, notes, and snippets.

@aloisdg
Last active June 9, 2022 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aloisdg/82861d3e20b2f1c42a69dd9a1eeda5e8 to your computer and use it in GitHub Desktop.
Save aloisdg/82861d3e20b2f1c42a69dd9a1eeda5e8 to your computer and use it in GitHub Desktop.
Kata 7 Wonders Sciences

Kata 7 Wonders Sciences

Scientific Structures are a set collecting aspect to the game of 7 Wonders. Throughout the game you, as the player, will occasionally come across one of three types of Scientific Structure. They could have a Gear on them, a Compass on them, or a Tablet. There are 8 of each card in the game, spread across the ages, and you get points for collecting them in different ways.

Although there are 8 of each of the three types of card, it is impossible to collect all 8 in the base game (although not with the Leaders expansion). This is because there are 24 Scientific Structures and the maximum number of cards you can have in the game is 18.

Step 1

Firstly, you get squared points for each multiple of an icon you have. For instance, if you have 1 gear, you will get 12 points. If you have 2 gears then you get 22 points. If you have 3 gears then you will get 32 points. You get the idea.

Given Joker Then
Tablet, Tablet 0 4
Tablet, Tablet, Gear 0 5
Step 2

Secondly, you get 7 points for each set of icons you have. A set is one gear, one compass, and one tablet.

Given Joker Then
Tablet, Tablet 0 4
Tablet, Tablet, Gear 0 5
Tablet, Tablet, Gear, Compass 0 13
Step 3

Thirdly, you can get the Science Guild. This card will count as any single type of Scientific Structure. The type will always be the most impactful one you can get. The guild is a joker.

Given Joker Then
Tablet, Tablet 0 4
Tablet, Tablet, Gear 0 5
Tablet, Tablet, Gear, Compass 0 13
Tablet, Tablet, Gear 1 13
Step 4

Finally, you can have another joker from your Wonder. This wonder will count as any single type of Scientific Structure. The type will always be the most impactful one you can get.

Given Joker Then
Tablet, Tablet 0 4
Tablet, Tablet, Gear 0 5
Tablet, Tablet, Gear, Compass 0 13
Tablet, Tablet, Gear 1 13
Tablet, Tablet 2 16
Spoiler
public static void Main()
{
	Console.WriteLine(Score(new List<Science>{Science.Tablet, Science.Tablet, Science.Gear}, 0) == 5);
	Console.WriteLine(Score(new List<Science>{Science.Tablet, Science.Tablet, Science.Gear, Science.Compass}, 0) == 13);
	Console.WriteLine(Score(new List<Science>{Science.Tablet, Science.Tablet, Science.Gear},1) == 13);
	Console.WriteLine(Score(new List<Science>{Science.Tablet, Science.Tablet, Science.Tablet}, 1) == 16);
	Console.WriteLine(Score(new List<Science>{Science.Tablet, Science.Tablet, Science.Gear}, 2) == 18);
	Console.WriteLine(Score(new List<Science>{Science.Tablet, Science.Tablet, Science.Tablet}, 2) == 25);
}

public enum Science
{
	Tablet,
	Gear,
	Compass
}

static readonly Science[] scienceTypes = (Science[])Enum.GetValues(typeof(Science));

static public int Score(IList<Science> sciences, int jokers)
{
	return jokers switch
	{
		0 => ScoreWithoutJoker(sciences),
		1 => scienceTypes.Max(s => ScoreWithoutJoker(sciences.Append(s))),
		2 => scienceTypes.Max(w => scienceTypes.Max(s => ScoreWithoutJoker(sciences.Append(s).Append(w)))),
		_ => throw new ArgumentOutOfRangeException(nameof(jokers), $"Not expected count: {jokers}")
	};
}

static public int ScoreWithoutJoker(IEnumerable<Science> sciences)
{
	var groups = sciences.GroupBy(x => x).Select(v => v.Count()).ToArray();
	var squaresSum = groups.Sum(count => (int)Math.Pow(count, 2));
	var bonus = groups.Length < 3 ? 0 : groups.Min() * 7;
	return squaresSum + bonus;
}

This algo bruteforces the result. Since this is a card game with a small number of value to bruteforce to, it should be quite fast. An heuritic to speed up the process would be to skip lower or equals square.

Try it Online

source:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment