diff --git a/Codingame.csproj b/Codingame.csproj
new file mode 100644
index 0000000..1d22a36
--- /dev/null
+++ b/Codingame.csproj
@@ -0,0 +1,9 @@
+
+
+
+ Exe
+ net6.0
+ enable
+
+
+
diff --git a/Codingame.sln b/Codingame.sln
new file mode 100644
index 0000000..c985af2
--- /dev/null
+++ b/Codingame.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33122.133
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Codingame", "Codingame.csproj", "{4C43862B-37C5-4543-BD26-08875DC59CAC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4C43862B-37C5-4543-BD26-08875DC59CAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4C43862B-37C5-4543-BD26-08875DC59CAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4C43862B-37C5-4543-BD26-08875DC59CAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4C43862B-37C5-4543-BD26-08875DC59CAC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4EE8EC05-1729-4E48-AC79-5847801FFCA1}
+ EndGlobalSection
+EndGlobal
diff --git a/FallChallenge2022.cs b/FallChallenge2022.cs
new file mode 100644
index 0000000..fc28bc2
--- /dev/null
+++ b/FallChallenge2022.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Codingame {
+ public class FallChallenge2022 {
+ public static string ReadInput() => Console.ReadLine() ?? throw new InvalidProgramException("No input available!");
+
+ public static void Main(string[] args) {
+ string[] inputs;
+ inputs = ReadInput().Split(' ');
+ var width = int.Parse(inputs[0]);
+ var height = int.Parse(inputs[1]);
+ var state = new GameState(width, height, new FieldState[width, height]);
+
+ // game loop
+ while (true) {
+ inputs = ReadInput().Split(' ');
+ state.MyMatter = int.Parse(inputs[0]);
+ state.OppMatter = int.Parse(inputs[1]);
+ for (var i = 0; i < height; i++) for (var j = 0; j < width; j++) {
+ ref var field = ref state.Fields[j, i];
+ inputs = ReadInput().Split(' ');
+ field.ScrapAmount = int.Parse(inputs[0]);
+ field.Owner = (Owner)int.Parse(inputs[1]);
+ if (!Enum.IsDefined(field.Owner)) throw new InvalidProgramException("Invalid owner!");
+ field.Units = int.Parse(inputs[2]);
+ field.Recycler = int.Parse(inputs[3]) == 1;
+ field.CanBuild = int.Parse(inputs[4]) == 1;
+ field.CanSpawn = int.Parse(inputs[5]) == 1;
+ field.InRangeOfRecycler = int.Parse(inputs[6]) == 1;
+ }
+
+ // Write an action using Console.WriteLine()
+ // To debug: Console.Error.WriteLine("Debug messages...");
+
+ var commands = GetCommands(state).ToList() is { Count: > 0 } cmds ? cmds : Command.Empty;
+ Console.WriteLine(string.Join(';', commands.Select(i => i.GetCommandString())));
+ }
+ }
+
+ public static IEnumerable GetCommands(GameState state) {
+ var units = state.FindUnits();
+ var neutral = state.FindFields(Owner.Neutral);
+ var recyclers = state.FindFields(i => i.Recycler).Keys.ToList();
+ var possibleBuilds = state.PossibleRecyclerSpots(recyclers).OrderByDescending(i => i.Value).Take(1).ToList();
+ while (possibleBuilds.Count > 0) {
+ var possibleBuild = possibleBuilds.First();
+ if (state.MyMatter < GameState.RecyclerCost) break;
+ state.MyMatter -= GameState.RecyclerCost;
+ Console.Error.WriteLine($"Building recycler at {possibleBuild.Key} for {possibleBuild.Value} amount");
+ yield return new Build(possibleBuild.Key);
+ recyclers.Add(possibleBuild.Key);
+ possibleBuilds = state.PossibleRecyclerSpots(recyclers).OrderByDescending(i => i.Value).Take(1).ToList();
+ }
+ foreach (var (position, amount) in units) {
+ for (int i = 0; i < amount; i++) {
+ if (neutral.Count == 0) yield break;
+ var emptySpot = neutral.Keys.First();
+ if (!neutral.Remove(emptySpot, out var field)) throw new InvalidProgramException();
+ yield return new Move(1, position, emptySpot);
+ }
+ }
+ }
+ }
+
+ public abstract record class Command {
+ public virtual string GetCommandString() => $"{Name} {string.Join(' ', Args.Select(i => i.ToString()))}";
+ protected virtual IEnumerable