/// <summary> /// fügt den Code für das Spielfeld inkl. deren Basis-Werte hinzu /// </summary> /// <param name="csFile">Cs-Datei, wo der Code hinzugefügt werden soll</param> /// <param name="field">Spielfeld, welches dargestellt werden soll</param> public static void AddLevelBasics(CsFile csFile, SokowahnField field) { var fChars = new char[field.width * field.height]; #region # // --- static readonly char[] FieldData = ... --- csFile.Write("const int FieldWidth = " + field.width + ";"); csFile.Write("const int FieldHeight = " + field.height + ";"); csFile.Write("const int FieldCount = FieldWidth * FieldHeight;"); csFile.Write(); csFile.Write("static readonly char[] FieldData =", f => { var zeile = new StringBuilder(); for (int y = 0; y < field.height; y++) { zeile.Clear(); zeile.Append("/* " + (y * field.width).ToString("N0").PadLeft(((field.height - 1) * field.width).ToString("N0").Length) + " */ "); for (int x = 0; x < field.width; x++) { char c = field.fieldData[x + y * field.width]; fChars[x + y * field.width] = c; if (c != '#') c = ' '; zeile.Append('\'').Append(c).Append("',"); } if (y == field.height - 1) zeile.Remove(zeile.Length - 1, 1); f.Write(zeile.ToString()); } }); csFile.WriteV(";\r\n\r\n"); #endregion #region # // --- static readonly ushort[] TargetPosis --- var targetFields = fChars.Select((c, i) => new { c, i }).Where(f => f.c == '.' || f.c == '*').Select(f => (ushort)f.i).ToArray(); csFile.Write("static readonly ushort[] TargetPosis = { " + string.Join(", ", targetFields) + " };"); csFile.Write(); #endregion #region # // --- static readonly ushort[] BoxPosis --- csFile.Write("static readonly ushort[] BoxPosis = { " + string.Join(", ", targetFields.Select(x => fChars.Length - 1)) + " };"); csFile.Write(); #endregion #region # // --- TxtView --- csFile.Write("static string TxtViewP(int playerPos = -1) { return SokoTools.TxtView(FieldData, FieldWidth, TargetPosis, playerPos); }"); csFile.Write("static string TxtView { get { return TxtViewP(); } }"); csFile.Write(); #endregion }
/// <summary> /// fügt Informationen über das Spielfeld als Kommentare im Quellcode hinzu /// </summary> /// <param name="csFile">Cs-Datei, wo der Code hinzugefügt werden soll</param> /// <param name="field">Spielfeld, welches dargestellt werden soll</param> /// <param name="headLine">Überschrift, welche über dem Level verwendet werden soll</param> public static void AddLevelComments(CsFile csFile, SokowahnField field, string headLine) { int commentWidth = Math.Max(field.width + 2, 35); commentWidth = (commentWidth + 1) / 2 * 2 + field.width % 2; string levelId = field.GetLevelId(); string emptyLine = " *" + new string(' ', commentWidth - 2) + "*"; csFile.Write("/" + new string('*', commentWidth)); csFile.Write(emptyLine); csFile.Write((" * " + new string(' ', (commentWidth - 14 - headLine.Length) / 2) + "--- " + headLine + " ---").PadRight(commentWidth, ' ') + "*"); csFile.Write(emptyLine); csFile.Write(" " + new string('*', commentWidth)); csFile.Write(emptyLine); csFile.Write((" * Level-Hash: " + levelId.Remove(0, levelId.LastIndexOf('_') + 1)).PadRight(commentWidth, ' ') + "*"); csFile.Write(emptyLine); csFile.Write((" * Size : " + field.width + " x " + field.height + " (" + (field.width * field.height).ToString("N0") + ")").PadRight(commentWidth, ' ') + "*"); csFile.Write((" * Boxes : " + field.boxesCount).PadRight(commentWidth, ' ') + "*"); csFile.Write(emptyLine); string centerChars = new string(' ', (commentWidth - field.width - 2) / 2); csFile.Write(field.ToString().Replace("\r", "").Split('\n').Select(x => " *" + centerChars + x + centerChars + "*")); csFile.Write(emptyLine); csFile.Write(" " + new string('*', commentWidth) + "/"); }
/// <summary> /// erstellt ein vollständiges Hashbuilder-Projekt und kompiliert dieses /// </summary> /// <param name="field">Spielfeld, welches als Grundlage dient</param> /// <param name="solutionPath">Pfad zum Ordner, wo die Projektmappe erstellt werden soll</param> public static void CreateProject(SokowahnField field, string solutionPath) { var scanner = new SokowahnField(field); Console.WriteLine(scanner.ToString()); Console.WriteLine(); string levelId = scanner.GetLevelId(); var solutionGuid = CsProject.NewGuid("S" + levelId); var projectGuid = CsProject.NewGuid("P" + levelId); string projectName = "Sokowahn_HashBuilder_" + levelId; var csFile = new CsFile(); csFile.Write(); csFile.Write(); GenLevelTools.AddLevelComments(csFile, scanner, "Hash Builder Alpha"); csFile.Write(); csFile.Write(); #region # // --- using *.* --- csFile.Write("#region # using *.*"); csFile.Write(); csFile.Write("using System;"); csFile.Write("using System.Linq;"); csFile.Write("using System.Collections.Generic;"); csFile.Write("using System.Diagnostics;"); csFile.Write(); csFile.Write("// ReSharper disable UnusedMember.Local"); csFile.Write(); csFile.Write("#endregion"); csFile.Write(); csFile.Write(); #endregion #region # // --- Program.cs --- csFile.Write("namespace " + projectName, ns => { ns.Write("static unsafe class Program", cl => { GenLevelTools.AddLevelBasics(cl, scanner); GenLevelTools.AddBoxFunctions(cl); #region # // --- static int ScanTopLeftPos(int startPos) --- cl.Write("static readonly int[] PlayerDirections = { -1, +1, -FieldWidth, +FieldWidth };"); cl.Write(); cl.Write("static readonly int[] ScanTmp = new int[FieldCount];"); cl.Write(); cl.Write("static int ScanTopLeftPosIntern(int* next, bool* scanned, char* fd)", sc => { sc.Write("int bestPos = int.MaxValue;"); sc.Write("int nextPos = 1;"); sc.Write("while (nextPos > 0)", wh => { wh.Write("int checkPos = next[--nextPos];"); wh.Write("if (checkPos < bestPos) bestPos = checkPos;"); wh.Write("scanned[checkPos] = true;"); wh.Write("if (!scanned[checkPos - 1] && fd[checkPos - 1] == ' ') next[nextPos++] = checkPos - 1;"); wh.Write("if (!scanned[checkPos + 1] && fd[checkPos + 1] == ' ') next[nextPos++] = checkPos + 1;"); wh.Write("if (!scanned[checkPos - FieldWidth] && fd[checkPos - FieldWidth] == ' ') next[nextPos++] = checkPos - FieldWidth;"); wh.Write("if (!scanned[checkPos + FieldWidth] && fd[checkPos + FieldWidth] == ' ') next[nextPos++] = checkPos + FieldWidth;"); }); sc.Write("return bestPos;"); }); cl.Write(); cl.Write("static int ScanTopLeftPos(int startPos)", sc => { sc.Write("fixed (int* next = ScanTmp) fixed (char* fd = FieldData)", f => { f.Write("bool* scanned = stackalloc bool[FieldCount];"); f.Write("*next = startPos;"); f.Write("return ScanTopLeftPosIntern(next, scanned, fd);"); }); }); cl.Write(); #endregion #region # // --- static int ScanReverseMoves(int startPlayerPos, ushort[] output) --- cl.Write("static int ScanReverseMoves(int startPlayerPos, ushort[] output, int boxesCount)", sc => { sc.Write("int outputLen = 0;"); sc.Write(); sc.Write("bool* scannedFields = stackalloc bool[FieldCount];"); sc.Write("ushort* scanTodo = stackalloc ushort[FieldCount];"); sc.Write(); sc.Write("int scanTodoPos = 0;"); sc.Write("int scanTodoLen = 0;"); sc.Write(); sc.Write("scanTodo[scanTodoLen++] = (ushort)startPlayerPos;"); sc.Write("scannedFields[startPlayerPos] = true;"); sc.Write(); sc.Write("while (scanTodoPos < scanTodoLen)", wh => { wh.Write("ushort scan = scanTodo[scanTodoPos++];"); wh.Write(); wh.Write("#region # // --- links (zurück nach rechts) ---"); wh.Write("switch (FieldData[scan - 1])", sw => { sw.Write("case '#': break;"); sw.Write("case ' ': if (!scannedFields[scan - 1]) { scannedFields[scan - 1] = true; scanTodo[scanTodoLen++] = (ushort)(scan - 1); } break;"); sw.Write("default:", bx => { bx.Write("if (FieldData[scan + 1] != ' ') break;"); bx.Write(); bx.Write("MoveBox((ushort)(scan - 1), scan);"); bx.Write(); bx.Write("for (int i = 0; i < boxesCount; i++) output[outputLen + i] = BoxPosis[i];"); bx.Write("output[outputLen + boxesCount] = (ushort)(scan + 1);"); bx.Write("outputLen += boxesCount + 1;"); bx.Write(); bx.Write("MoveBox(scan, (ushort)(scan - 1));"); }); sw.Write("break;"); }); wh.Write("#endregion"); wh.Write(); wh.Write("#region # // --- rechts (zurück nach links) ---"); wh.Write("switch (FieldData[scan + 1])", sw => { sw.Write("case '#': break;"); sw.Write("case ' ': if (!scannedFields[scan + 1]) { scannedFields[scan + 1] = true; scanTodo[scanTodoLen++] = (ushort)(scan + 1); } break;"); sw.Write("default:", bx => { bx.Write("if (FieldData[scan - 1] != ' ') break;"); bx.Write(); bx.Write("MoveBox((ushort)(scan + 1), scan);"); bx.Write(); bx.Write("for (int i = 0; i < boxesCount; i++) output[outputLen + i] = BoxPosis[i];"); bx.Write("output[outputLen + boxesCount] = (ushort)(scan - 1);"); bx.Write("outputLen += boxesCount + 1;"); bx.Write(); bx.Write("MoveBox(scan, (ushort)(scan + 1));"); }); sw.Write("break;"); }); wh.Write("#endregion"); wh.Write(); wh.Write("#region # // --- oben (zurück nach unten) ---"); wh.Write("switch (FieldData[scan - FieldWidth])", sw => { sw.Write("case '#': break;"); sw.Write("case ' ': if (!scannedFields[scan - FieldWidth]) { scannedFields[scan - FieldWidth] = true; scanTodo[scanTodoLen++] = (ushort)(scan - FieldWidth); } break;"); sw.Write("default:", bx => { bx.Write("if (FieldData[scan + FieldWidth] != ' ') break;"); bx.Write(); bx.Write("MoveBox((ushort)(scan - FieldWidth), scan);"); bx.Write(); bx.Write("for (int i = 0; i < boxesCount; i++) output[outputLen + i] = BoxPosis[i];"); bx.Write("output[outputLen + boxesCount] = (ushort)(scan + FieldWidth);"); bx.Write("outputLen += boxesCount + 1;"); bx.Write(); bx.Write("MoveBox(scan, (ushort)(scan - FieldWidth));"); }); sw.Write("break;"); }); wh.Write("#endregion"); wh.Write(); wh.Write("#region # // --- unten (zurück nach oben) ---"); wh.Write("switch (FieldData[scan + FieldWidth])", sw => { sw.Write("case '#': break;"); sw.Write("case ' ': if (!scannedFields[scan + FieldWidth]) { scannedFields[scan + FieldWidth] = true; scanTodo[scanTodoLen++] = (ushort)(scan + FieldWidth); } break;"); sw.Write("default:", bx => { bx.Write("if (FieldData[scan - FieldWidth] != ' ') break;"); bx.Write(); bx.Write("MoveBox((ushort)(scan + FieldWidth), scan);"); bx.Write(); bx.Write("for (int i = 0; i < boxesCount; i++) output[outputLen + i] = BoxPosis[i];"); bx.Write("output[outputLen + boxesCount] = (ushort)(scan - FieldWidth);"); bx.Write("outputLen += boxesCount + 1;"); bx.Write(); bx.Write("MoveBox(scan, (ushort)(scan + FieldWidth));"); }); sw.Write("break;"); }); wh.Write("#endregion"); wh.Write(); }); sc.Write(); sc.Write("return outputLen;"); }); cl.Write(); #endregion #region # // --- static void Main() --- cl.Write("static void Main()", main => { main.Write("for (int boxesCount = 1; boxesCount <= TargetPosis.Length; boxesCount++)", bx => { bx.Write("int stateLen = boxesCount + 1;"); bx.Write("var todoBuf = new ushort[16777216 / (stateLen + 1) * (stateLen + 1)];"); bx.Write("int todoLen = 0;"); bx.Write("var stopWatch = Stopwatch.StartNew();"); bx.Write(); #region # // --- Suche End-Varianten --- bx.Write("#region # // --- search all finish-positions -> put into \"todoBuf\" ---", sc => { sc.Write("var checkDuplicates = new HashSet<ulong>();"); sc.Write(); sc.Write("foreach (var boxesVariant in SokoTools.FieldBoxesVariants(TargetPosis.Length, boxesCount).Select(v => v.Select(f => TargetPosis[f]).ToArray()))", fe => { fe.Write("foreach (var box in boxesVariant) FieldData[box] = '$';"); fe.Write(); fe.Write("ulong boxCrc = SokoTools.CrcCompute(SokoTools.CrcStart, boxesVariant, 0, boxesVariant.Length);"); fe.Write(); fe.Write("foreach (var box in boxesVariant)", feb => { feb.Write("foreach (int playerDir in PlayerDirections)", febs => { febs.Write("int playerPos = box - playerDir;"); febs.Write("if (FieldData[playerPos] != ' ') continue;"); febs.Write("if (FieldData[playerPos - playerDir] != ' ') continue;"); febs.Write(); febs.Write("ulong crc = SokoTools.CrcCompute(boxCrc, playerPos);"); febs.Write("if (checkDuplicates.Contains(crc)) continue;"); febs.Write("checkDuplicates.Add(crc);"); febs.Write(); febs.Write("int topPlayerPos = ScanTopLeftPos(playerPos);"); febs.Write(); febs.Write("if (topPlayerPos != playerPos)", febst => { febst.Write("crc = SokoTools.CrcCompute(boxCrc, topPlayerPos);"); febst.Write("if (checkDuplicates.Contains(crc)) continue;"); febst.Write("checkDuplicates.Add(crc);"); }); febs.Write(); febs.Write("todoBuf[todoLen++] = 0;"); febs.Write("for(int i = 0; i < boxesVariant.Length; i++) todoBuf[todoLen + i] = boxesVariant[i];"); febs.Write("todoBuf[todoLen + boxesVariant.Length] = (ushort)topPlayerPos;"); febs.Write("todoLen += stateLen;"); }); }); fe.Write(); fe.Write("foreach (var box in boxesVariant) FieldData[box] = ' ';"); }); }); bx.Write("#endregion"); bx.Write(); #endregion #region # // --- Durchsuche Rückwärts alle Möglichkeiten --- bx.Write("#region # // --- search all possible positions (bruteforce-reverse) ---", sc => { sc.Write("var hash = new DictionaryFastCrc<ushort>();"); sc.Write("var nextBuf = new ushort[stateLen * boxesCount * 4];"); sc.Write(); sc.Write("int todoPos = 0;"); sc.Write("while (todoPos < todoLen)", wh => { wh.Write("ushort depth = todoBuf[todoPos++];"); wh.Write("ulong crc = SetBoxes(todoBuf, todoPos, boxesCount);"); wh.Write("int playerPos = ScanTopLeftPos(todoBuf[todoPos + boxesCount]);"); wh.Write("crc = SokoTools.CrcCompute(crc, playerPos);"); wh.Write(); wh.Write("if (hash.ContainsKey(crc))", skip => { skip.Write("todoPos += stateLen;"); skip.Write("continue;"); }); wh.Write(); wh.Write("hash.Add(crc, depth);"); wh.Write("if ((hash.Count & 0xffff) == 0) Console.WriteLine(\"[\" + boxesCount + \"] (\" + depth + \") \" + ((todoLen - todoPos) / (stateLen + 1)).ToString(\"N0\") + \" / \" + hash.Count.ToString(\"N0\"));"); wh.Write(); wh.Write("depth++;"); wh.Write("int nextLength = ScanReverseMoves(playerPos, nextBuf, boxesCount);"); wh.Write("for (int next = 0; next < nextLength; next += stateLen)", f => { f.Write("todoBuf[todoLen++] = depth;"); f.Write("for (int i = 0; i < stateLen; i++) todoBuf[todoLen++] = nextBuf[next + i];"); }); wh.Write(); wh.Write("todoPos += stateLen;"); wh.Write("if (todoBuf.Length - todoLen < nextLength * 2)", arr => { arr.Write("Array.Copy(todoBuf, todoPos, todoBuf, 0, todoLen - todoPos);"); arr.Write("todoLen -= todoPos;"); arr.Write("todoPos = 0;"); }); }); sc.Write("stopWatch.Stop();"); sc.Write("Console.WriteLine();"); sc.Write("Console.ForegroundColor = ConsoleColor.Yellow;"); sc.Write("Console.WriteLine(\"[\" + boxesCount + \"] ok. Hash: \" + hash.Count.ToString(\"N0\") + \" (\" + stopWatch.ElapsedMilliseconds.ToString(\"N0\") + \" ms)\");"); sc.Write("Console.ForegroundColor = ConsoleColor.Gray;"); sc.Write("Console.WriteLine();"); }); bx.Write("#endregion"); #endregion }); }); #endregion }); }); csFile.SaveToFile(solutionPath + "Program.cs"); #endregion var csSokoTools = GenStaticTools.GenSokoTools(projectName); csSokoTools.SaveToFile(solutionPath + "SokoTools.cs"); var csDictFast = GenStaticTools.GenDictionaryFastCrc(projectName); csDictFast.SaveToFile(solutionPath + "DictionaryFastCrc.cs"); var projectFile = CsProject.CreateCsProjectFile(projectGuid, projectName, new[] { "System" }, new[] { "Program.cs", "SokoTools.cs", "DictionaryFastCrc.cs" }); projectFile.SaveToFile(solutionPath + projectName + ".csproj"); var solutionFile = CsProject.CreateSolutionFile(solutionGuid, projectGuid, "Sokowahn", projectName + ".csproj"); solutionFile.SaveToFile(solutionPath + projectName + ".sln"); CsCompiler.Compile(solutionPath + projectName + ".sln"); }
/// <summary> /// fügt Methoden hinzu um die Kisten auf dem Spielfeld zu beeinflussen /// </summary> /// <param name="csFile">Cs-Datei, wo der Code hinzugefügt werden soll</param> public static void AddBoxFunctions(CsFile csFile) { // --- static ulong SetBoxes(ushort[] buf, int offset, int boxesCount) --- csFile.Write("static ulong SetBoxes(ushort[] buf, int offset, int boxesCount)", sb => { sb.Write("for (int i = 0; i < boxesCount; i++) FieldData[BoxPosis[i]] = ' ';"); sb.Write(); sb.Write("ulong crc = SokoTools.CrcStart;"); sb.Write("for (int i = 0; i < boxesCount; i++)", f => { f.Write("ushort pos = buf[offset + i];"); f.Write("crc = SokoTools.CrcCompute(crc, pos);"); f.Write("BoxPosis[i] = pos;"); f.Write("FieldData[pos] = (char)(i + '0');"); }); sb.Write("return crc;"); }); csFile.Write(); // --- static void MoveBox(ushort oldPos, ushort newPos) --- csFile.Write("static void MoveBox(ushort oldPos, ushort newPos)", mb => { mb.Write("int index = FieldData[oldPos] - '0';"); mb.Write("FieldData[oldPos] = ' ';"); mb.Write("FieldData[newPos] = (char)(index + '0');"); mb.Write("BoxPosis[index] = newPos;"); mb.Write(); mb.Write("if (newPos < oldPos)", f => { f.Write("while (index > 0 && newPos < BoxPosis[index - 1])", wh => { wh.Write("BoxPosis[index] = BoxPosis[index - 1];"); wh.Write("FieldData[BoxPosis[index]] = (char)(index + '0');"); wh.Write("index--;"); wh.Write("BoxPosis[index] = newPos;"); wh.Write("FieldData[BoxPosis[index]] = (char)(index + '0');"); }); }); mb.Write("else", f => { f.Write("while (index < BoxPosis.Length - 1 && newPos > BoxPosis[index + 1])", wh => { wh.Write("BoxPosis[index] = BoxPosis[index + 1];"); wh.Write("FieldData[BoxPosis[index]] = (char)(index + '0');"); wh.Write("index++;"); wh.Write("BoxPosis[index] = newPos;"); wh.Write("FieldData[BoxPosis[index]] = (char)(index + '0');"); }); }); }); csFile.Write(); }
/// <summary> /// erstellt eine einfach Projektmappen-Datei /// </summary> /// <param name="solutionGuid">GUID der Projektmappe</param> /// <param name="projectGuid">GUID des Projektes</param> /// <param name="projectName">Name des Projektes</param> /// <param name="projectFile">Dateiname des Projektes</param> /// <returns>fertig erstellte Projektmappen-Datei</returns> public static CsFile CreateSolutionFile(Guid solutionGuid, Guid projectGuid, string projectName, string projectFile) { var sol = new CsFile(true); sol.Write("Microsoft Visual Studio Solution File, Format Version 12.00"); sol.Write("# Visual Studio 2013"); sol.Write("VisualStudioVersion = 12.0.31101.0"); sol.Write("MinimumVisualStudioVersion = 10.0.40219.1"); sol.Write("Project('{" + solutionGuid.ToString().ToUpperInvariant() + "}') = '" + projectName + "', '" + projectFile + "', '{" + projectGuid.ToString().ToUpperInvariant() + "}'"); sol.Write("EndProject"); sol.Write("Global"); { sol.Write("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); { sol.Write("\t\tDebug|Any CPU = Debug|Any CPU"); sol.Write("\t\tRelease|Any CPU = Release|Any CPU"); } sol.Write("\tEndGlobalSection"); sol.Write("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); { sol.Write("\t\t{" + projectGuid.ToString().ToUpperInvariant() + "}.Debug|Any CPU.ActiveCfg = Debug|Any CPU"); sol.Write("\t\t{" + projectGuid.ToString().ToUpperInvariant() + "}.Debug|Any CPU.Build.0 = Debug|Any CPU"); sol.Write("\t\t{" + projectGuid.ToString().ToUpperInvariant() + "}.Release|Any CPU.ActiveCfg = Release|Any CPU"); sol.Write("\t\t{" + projectGuid.ToString().ToUpperInvariant() + "}.Release|Any CPU.Build.0 = Release|Any CPU"); } sol.Write("\tEndGlobalSection"); sol.Write("\tGlobalSection(SolutionProperties) = preSolution"); { sol.Write("\t\tHideSolutionNode = FALSE"); } sol.Write("\tEndGlobalSection"); } sol.Write("EndGlobal"); return sol; }
/// <summary> /// erstellt eine einfache Visual Studio Projekt-Datei (Konsolenzeilen Programm) /// </summary> /// <param name="projectGuid">GUID des Projektes</param> /// <param name="projectName">Name des Projektes (Assembly-Name)</param> /// <param name="references">Liste mit erforderlichen Verweisen</param> /// <param name="compileFiles">Liste der compilierbaren Dateien, welche zum Projekt gehören</param> /// <returns>fertig erstellte Projekt-Datei</returns> public static CsFile CreateCsProjectFile(Guid projectGuid, string projectName, IEnumerable<string> references, IEnumerable<string> compileFiles) { var prj = new CsFile(true); prj.Write("<?xml version='1.0' encoding='utf-8'?>"); prj.WriteX("Project ToolsVersion='12.0' DefaultTargets='Build' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'", p => { p.WriteX("Import Project='$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props' Condition='Exists(´$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props´)'"); p.WriteX("PropertyGroup", x => { x.WriteXv("Configuration Condition=' ´$(Configuration)´ == ´´ '", "Debug"); x.WriteXv("Platform Condition=' ´$(Platform)´ == ´´ '", "AnyCPU"); x.WriteXv("ProjectGuid", "{" + projectGuid.ToString().ToUpperInvariant() + "}"); x.WriteXv("OutputType", "Exe"); x.WriteXv("AppDesignerFolder", "Properties"); x.WriteXv("RootNamespace", projectName); x.WriteXv("AssemblyName", projectName); x.WriteXv("TargetFrameworkVersion", "v4.5"); x.WriteXv("FileAlignment", "512"); }); p.WriteX("PropertyGroup Condition=' ´$(Configuration)|$(Platform)´ == ´Debug|AnyCPU´ '", x => { x.WriteXv("PlatformTarget", "AnyCPU"); x.WriteXv("DebugSymbols", "true"); x.WriteXv("DebugType", "full"); x.WriteXv("Optimize", "false"); x.WriteXv("OutputPath", "bin\\Debug\\"); x.WriteXv("DefineConstants", "DEBUG;TRACE"); x.WriteXv("ErrorReport", "prompt"); x.WriteXv("WarningLevel", "4"); x.WriteXv("Prefer32Bit", "false"); x.WriteXv("AllowUnsafeBlocks", "true"); }); p.WriteX("PropertyGroup Condition=' ´$(Configuration)|$(Platform)´ == ´Release|AnyCPU´ '", x => { x.WriteXv("PlatformTarget", "AnyCPU"); x.WriteXv("DebugType", "pdbonly"); x.WriteXv("Optimize", "true"); x.WriteXv("OutputPath", "bin\\Release\\"); x.WriteXv("DefineConstants", "TRACE"); x.WriteXv("ErrorReport", "prompt"); x.WriteXv("WarningLevel", "4"); x.WriteXv("Prefer32Bit", "false"); x.WriteXv("AllowUnsafeBlocks", "true"); }); p.WriteX("ItemGroup", x => { foreach (var r in references) { x.WriteX("Reference Include='" + r + "'"); } }); p.WriteX("ItemGroup", x => { foreach (var file in compileFiles) { x.WriteX("Compile Include='" + file + "'"); } }); p.WriteX("Import Project='$(MSBuildToolsPath)\\Microsoft.CSharp.targets'"); }); return prj; }