diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ea6865d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,95 @@ +# Rules in this file were initially inferred by Visual Studio IntelliCode from the RogueSharp codebase based on best match to current usage at 12/9/2018 +# You can modify the rules from these initially generated values to suit your own policies +# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference +[*.cs] + +#Core editorconfig formatting - indentation + +#use soft tabs (spaces) for indentation +indent_style = space +#use 3 spaces for indentation +indent_size = 3 +#remove whitespace characters preceding newline characters +trim_trailing_whitespace = true + +#Formatting - indentation options + +#do not indent switch labels +csharp_indent_switch_labels = false + +#Formatting - new line options + +#require braces to be on a new line for properties, control_blocks, methods, and types (also known as "Allman" style) +csharp_new_line_before_open_brace = properties, control_blocks, methods, types + +#Formatting - organize using options + +#sort System.* using directives alphabetically, and place them before other usings +dotnet_sort_system_directives_first = true + +#Formatting - spacing options + +#require a space between a cast and the value +csharp_space_after_cast = true +#require a space before the colon for bases or interfaces in a type declaration +csharp_space_after_colon_in_inheritance_clause = true +#require a space after a keyword in a control flow statement such as a for loop +csharp_space_after_keywords_in_control_flow_statements = true +#require a space before the colon for bases or interfaces in a type declaration +csharp_space_before_colon_in_inheritance_clause = true +#remove space within empty argument list parentheses +csharp_space_between_method_call_empty_parameter_list_parentheses = false +#remove space between method call name and opening parenthesis +csharp_space_between_method_call_name_and_opening_parenthesis = false +#place a space character after the opening parenthesis and before the closing parenthesis of a method call +csharp_space_between_method_call_parameter_list_parentheses = true +#remove space within empty parameter list parentheses for a method declaration +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +#do not place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. +csharp_space_between_method_declaration_parameter_list_parentheses = true + +#Formatting - wrapping options + +#leave code block on single line +csharp_preserve_single_line_blocks = true + +#Style - expression bodied member options + +#prefer block bodies for accessors +csharp_style_expression_bodied_accessors = false:suggestion +#prefer block bodies for constructors +csharp_style_expression_bodied_constructors = false:suggestion +#prefer block bodies for methods +csharp_style_expression_bodied_methods = false:suggestion +#prefer block bodies for operators +csharp_style_expression_bodied_operators = false:suggestion +#prefer block bodies for properties +csharp_style_expression_bodied_properties = false:suggestion + +#Style - expression level options + +#prefer out variables to be declared before the method call +csharp_style_inlined_variable_declaration = false:suggestion +#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_member_access = true:suggestion + +#Style - implicit and explicit types + +#prefer explicit type over var to declare variables with built-in system types such as int +csharp_style_var_for_built_in_types = false:suggestion +#prefer explicit type over var when the type is already mentioned on the right-hand side of a declaration +csharp_style_var_when_type_is_apparent = false:suggestion + +#Style - language keyword and framework type options + +#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion + +#Style - qualification options + +#prefer fields not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_field = false:suggestion +#prefer methods not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_method = false:suggestion +#prefer properties not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_property = false:suggestion diff --git a/LICENSE.txt b/LICENSE.txt index 9407b3c..bd0cbec 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ The MIT License (MIT) -Copyright (c) 2014 - 2017 Faron Bracy -https://bitbucket.org/FaronBracy/roguesharp +Copyright (c) 2014 - 2019 Faron Bracy +https://github.com/FaronBracy/RogueSharp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 479c607..f150e7e 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ [![Build status](https://ci.appveyor.com/api/projects/status/mx09mla59wsgrkkj?svg=true)](https://ci.appveyor.com/project/FaronBracy/roguesharp-20n28) [![Nuget](https://buildstats.info/nuget/roguesharp)](https://www.nuget.org/packages/RogueSharp) +[![Test status](https://img.shields.io/azure-devops/tests/dreamersdesign/RogueSharp/1.svg)](https://dreamersdesign.visualstudio.com/RogueSharp/_build/latest?definitionId=1) +[![Code coverage](https://img.shields.io/azure-devops/coverage/dreamersdesign/RogueSharp/1.svg)](https://dreamersdesign.visualstudio.com/RogueSharp/_build/latest?definitionId=1) + [![Build History](https://buildstats.info/appveyor/chart/FaronBracy/roguesharp-20n28)](https://ci.appveyor.com/project/FaronBracy/roguesharp-20n28/history) # What is RogueSharp? # @@ -103,7 +106,7 @@ A more interesting way to create a map is to use the `Map` class's static method The MIT License (MIT) -Copyright (c) 2014 - 2018 Faron Bracy +Copyright (c) 2014 - 2019 Faron Bracy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/RogueSharp.Test/Algorithms/DepthFirstPathsTest.cs b/RogueSharp.Test/Algorithms/DepthFirstPathsTest.cs new file mode 100644 index 0000000..fbef5f1 --- /dev/null +++ b/RogueSharp.Test/Algorithms/DepthFirstPathsTest.cs @@ -0,0 +1,74 @@ +using System; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RogueSharp.Algorithms; + +namespace RogueSharp.Test.Algorithms +{ + [TestClass] + public class DepthFirstPathsTest + { + [TestMethod] + public void Constructor_WhenGraphIsNull_WillThrowArgumentException() + { + Assert.ThrowsException( () => new DepthFirstPaths( null, 3 ) ); + } + + [TestMethod] + public void HasPathTo_WhenPathExistsBetweenVertices_WillReturnTrue() + { + Graph graph = new Graph( 5 ); + graph.AddEdge( 0, 1 ); + graph.AddEdge( 1, 2 ); + graph.AddEdge( 1, 4 ); + graph.AddEdge( 2, 3 ); + graph.AddEdge( 3, 4 ); + DepthFirstPaths paths = new DepthFirstPaths( graph, 3 ); + + Assert.IsTrue( paths.HasPathTo( 0 ) ); + } + + [TestMethod] + public void HasPathTo_WhenPathDoesNotExistBetweenVertices_WillReturnFalse() + { + Graph graph = new Graph( 5 ); + graph.AddEdge( 0, 1 ); + graph.AddEdge( 1, 2 ); + graph.AddEdge( 1, 4 ); + DepthFirstPaths paths = new DepthFirstPaths( graph, 0 ); + + Assert.IsFalse( paths.HasPathTo( 3 ) ); + } + + [TestMethod] + public void PathTo_WhenPathExistsBetweenVertices_WillReturnVerticesInPath() + { + Graph graph = new Graph( 5 ); + graph.AddEdge( 0, 1 ); + graph.AddEdge( 1, 2 ); + graph.AddEdge( 1, 4 ); + graph.AddEdge( 2, 3 ); + graph.AddEdge( 3, 4 ); + DepthFirstPaths paths = new DepthFirstPaths( graph, 3 ); + + int[] pathVertices = paths.PathTo( 0 ).ToArray(); + + Assert.AreEqual( pathVertices[0], 2 ); + Assert.AreEqual( pathVertices[1], 1 ); + Assert.AreEqual( pathVertices[2], 0 ); + Assert.AreEqual( pathVertices.Length, 3 ); + } + + [TestMethod] + public void PathTo_WhenPathDoesNotExistBetweenVertices_WillReturnNull() + { + Graph graph = new Graph( 5 ); + graph.AddEdge( 0, 1 ); + graph.AddEdge( 1, 2 ); + graph.AddEdge( 1, 4 ); + DepthFirstPaths paths = new DepthFirstPaths( graph, 0 ); + + Assert.IsNull( paths.PathTo( 3 ) ); + } + } +} diff --git a/RogueSharp.Test/Algorithms/DijkstraShortestPathTest.cs b/RogueSharp.Test/Algorithms/DijkstraShortestPathTest.cs new file mode 100644 index 0000000..8fbb5d5 --- /dev/null +++ b/RogueSharp.Test/Algorithms/DijkstraShortestPathTest.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RogueSharp.Algorithms; + +namespace RogueSharp.Test.Algorithms +{ + [TestClass] + public class DijkstraShortestPathTest + { + [TestMethod] + public void Constructor_WhenGraphIsNull_WillThrowArgumentNullException() + { + Assert.ThrowsException( () => new DijkstraShortestPath( null, 0 ) ); + } + + [TestMethod] + public void Constructor_WhenGraphHasEdgesWithNegativeWeights_WillThrowArgumentOutOfRangeException() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 2 ); + digraph.AddEdge( new DirectedEdge( 0, 1, -1.5 ) ); + + Assert.ThrowsException( () => new DijkstraShortestPath( digraph, 0 ) ); + } + + [TestMethod] + public void HasPathTo_WhenPathExistsBetween0And4_WillBeTrue() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + DijkstraShortestPath dijkstra = new DijkstraShortestPath( digraph, 0 ); + + Assert.IsTrue( dijkstra.HasPathTo( 4 ) ); + } + + [TestMethod] + public void HasPathTo_WhenPathDoesNotExistBetween4And0_WillBeFalse() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + DijkstraShortestPath dijkstra = new DijkstraShortestPath( digraph, 4 ); + + Assert.IsFalse( dijkstra.HasPathTo( 0 ) ); + } + + [TestMethod] + public void DistanceTo_WhenPathExistsBetween0And4_WillBeSumOfWeightsInPath() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + DijkstraShortestPath dijkstra = new DijkstraShortestPath( digraph, 0 ); + + Assert.AreEqual( 9, dijkstra.DistanceTo( 4 ) ); + } + + [TestMethod] + public void DistanceTo_WhenMultiplePathsExistBetween0And4_WillBeSumOfWeightsInShortestPath() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 1, 4, 4.75 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + DijkstraShortestPath dijkstra = new DijkstraShortestPath( digraph, 0 ); + + Assert.AreEqual( 7.25, dijkstra.DistanceTo( 4 ) ); + } + + [TestMethod] + public void DistanceTo_WhenNoPathExists_WillBePositiveInfinity() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 1, 4, 4.75 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + DijkstraShortestPath dijkstra = new DijkstraShortestPath( digraph, 4 ); + + Assert.AreEqual( double.PositiveInfinity, dijkstra.DistanceTo( 0 ) ); + } + + [TestMethod] + public void PathTo_WhenMultiplePathsExistBetween0And4_WillBeShortestPath() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 1, 4, 4.75 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + DijkstraShortestPath dijkstra = new DijkstraShortestPath( digraph, 0 ); + + DirectedEdge[] path = dijkstra.PathTo( 4 ).ToArray(); + + Assert.AreEqual( "From: 0, To: 1, Weight: 2.5", path[0].ToString() ); + Assert.AreEqual( "From: 1, To: 4, Weight: 4.75", path[1].ToString() ); + Assert.AreEqual( 2, path.Length ); + } + + [TestMethod] + public void PathTo_WhenNoPathExists_WillBeNull() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 1, 4, 4.75 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + DijkstraShortestPath dijkstra = new DijkstraShortestPath( digraph, 4 ); + + IEnumerable path = dijkstra.PathTo( 0 ); + + Assert.IsNull( path ); + } + + [TestMethod] + public void FindPath_WhenMultiplePathsExistBetween0And4_WillBeShortestPath() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 1, 4, 4.75 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + + DirectedEdge[] path = DijkstraShortestPath.FindPath( digraph, 0, 4 ).ToArray(); + + Assert.AreEqual( "From: 0, To: 1, Weight: 2.5", path[0].ToString() ); + Assert.AreEqual( "From: 1, To: 4, Weight: 4.75", path[1].ToString() ); + Assert.AreEqual( 2, path.Length ); + } + + [TestMethod] + public void FindPath_WhenNoPathExists_WillBeNull() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 1, 4, 4.75 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + + IEnumerable path = DijkstraShortestPath.FindPath( digraph, 4, 0 ); + + Assert.IsNull( path ); + } + + [TestMethod] + public void Check_WhenGivenValidGraph_WillBeTrue() + { + EdgeWeightedDigraph digraph = new EdgeWeightedDigraph( 5 ); + digraph.AddEdge( new DirectedEdge( 0, 1, 2.5 ) ); + digraph.AddEdge( new DirectedEdge( 1, 2, 3.25 ) ); + digraph.AddEdge( new DirectedEdge( 1, 4, 4.75 ) ); + digraph.AddEdge( new DirectedEdge( 2, 3, 1.25 ) ); + digraph.AddEdge( new DirectedEdge( 3, 4, 2 ) ); + DijkstraShortestPath dijkstra = new DijkstraShortestPath( digraph, 0 ); + + Assert.IsTrue( dijkstra.Check( digraph, 0 ) ); + } + } +} diff --git a/RogueSharp.Test/Algorithms/DirectedEdgeTest.cs b/RogueSharp.Test/Algorithms/DirectedEdgeTest.cs new file mode 100644 index 0000000..43463ac --- /dev/null +++ b/RogueSharp.Test/Algorithms/DirectedEdgeTest.cs @@ -0,0 +1,41 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RogueSharp.Algorithms; + +namespace RogueSharp.Test.Algorithms +{ + [TestClass] + public class DirectedEdgeTest + { + [TestMethod] + public void From_WhenCreatingDirectedEdgeFrom4To5_WillBe4() + { + DirectedEdge directedEdge = new DirectedEdge( 4, 5, 1.12 ); + + Assert.AreEqual( 4, directedEdge.From ); + } + + [TestMethod] + public void To_WhenCreatingDirectedEdgeFrom4To5_WillBe5() + { + DirectedEdge directedEdge = new DirectedEdge( 4, 5, 1.12 ); + + Assert.AreEqual( 5, directedEdge.To ); + } + + [TestMethod] + public void Weight_WhenCreatingDirectedEdgeWithWeight1Point12_WillBe1Point12() + { + DirectedEdge directedEdge = new DirectedEdge( 4, 5, 1.12 ); + + Assert.AreEqual( 1.12, directedEdge.Weight ); + } + + [TestMethod] + public void ToString_WhenCreatingDirectedEdgeFrom4To5WithWeight1Point12_WillBeExpectedString() + { + DirectedEdge directedEdge = new DirectedEdge( 4, 5, 1.12 ); + + Assert.AreEqual( "From: 4, To: 5, Weight: 1.12", directedEdge.ToString() ); + } + } +} diff --git a/RogueSharp.Test/Algorithms/EdgeWeightedDigraphTest.cs b/RogueSharp.Test/Algorithms/EdgeWeightedDigraphTest.cs new file mode 100644 index 0000000..7b573f6 --- /dev/null +++ b/RogueSharp.Test/Algorithms/EdgeWeightedDigraphTest.cs @@ -0,0 +1,140 @@ +using System; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RogueSharp.Algorithms; + +namespace RogueSharp.Test.Algorithms +{ + [TestClass] + public class EdgeWeightedDigraphTest + { + [TestMethod] + public void NumberOfVertices_WhenConstructingNewGraphWith5Vertices_WillBe5() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + + Assert.AreEqual( 5, graph.NumberOfVertices ); + } + + [TestMethod] + public void NumberOfEdges_WhenConstructingNewGraphWith5Vertices_WillBe0() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + + Assert.AreEqual( 0, graph.NumberOfEdges ); + } + + [TestMethod] + public void AddEdge_WhenGraphHad0Edges_WillNowHave1Edge() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + + graph.AddEdge( new DirectedEdge( 1, 2, 1.0 ) ); + + Assert.AreEqual( 1, graph.NumberOfEdges ); + } + + [TestMethod] + public void AddEdge_6TimesWhenGraphHad0Edges_WillNowHave6Edges() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + + graph.AddEdge( new DirectedEdge( 1, 2, 1.0 ) ); + graph.AddEdge( new DirectedEdge( 1, 3, 1.0 ) ); + graph.AddEdge( new DirectedEdge( 0, 2, 2.0 ) ); + graph.AddEdge( new DirectedEdge( 0, 4, 4.0 ) ); + graph.AddEdge( new DirectedEdge( 3, 4, 5.5 ) ); + graph.AddEdge( new DirectedEdge( 3, 0, 4.0 ) ); + + Assert.AreEqual( 6, graph.NumberOfEdges ); + } + + [TestMethod] + public void AddEdge_WhenEdgeToAddIsNull_WillThrowArgumentNullException() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + + Assert.ThrowsException( () => graph.AddEdge( null ) ); + } + + [TestMethod] + public void Adjacent_WhenVertexHasNoEdgesToOtherVertices_WillReturn0DirectedEdges() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + + Assert.AreEqual( 0, graph.Adjacent( 1 ).Count() ); + } + + [TestMethod] + public void Adjacent_WhenVertexHas3EdgesToOtherVertices_WillReturn3DirectedEdges() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + graph.AddEdge( new DirectedEdge( 1, 2, 1.0 ) ); + graph.AddEdge( new DirectedEdge( 1, 3, 1.5 ) ); + graph.AddEdge( new DirectedEdge( 1, 4, 1.0 ) ); + + DirectedEdge[] adjacent = graph.Adjacent( 1 ).ToArray(); + + Assert.AreEqual( 3, adjacent.Length ); + Assert.AreEqual( 2, adjacent[0].To ); + Assert.AreEqual( 3, adjacent[1].To ); + Assert.AreEqual( 4, adjacent[2].To ); + } + + [TestMethod] + public void Edges_WhenGraphHas6Edges_WillReturnAll6DirectedEdges() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + graph.AddEdge( new DirectedEdge( 0, 2, 2.0 ) ); + graph.AddEdge( new DirectedEdge( 0, 4, 4.0 ) ); + graph.AddEdge( new DirectedEdge( 1, 2, 1.0 ) ); + graph.AddEdge( new DirectedEdge( 1, 3, 1.0 ) ); + graph.AddEdge( new DirectedEdge( 3, 4, 5.5 ) ); + graph.AddEdge( new DirectedEdge( 3, 0, 4.0 ) ); + + DirectedEdge[] edges = graph.Edges().ToArray(); + + Assert.AreEqual( 6, edges.Length ); + Assert.AreEqual( "From: 0, To: 2, Weight: 2", edges[0].ToString() ); + Assert.AreEqual( "From: 0, To: 4, Weight: 4", edges[1].ToString() ); + Assert.AreEqual( "From: 1, To: 2, Weight: 1", edges[2].ToString() ); + Assert.AreEqual( "From: 1, To: 3, Weight: 1", edges[3].ToString() ); + Assert.AreEqual( "From: 3, To: 4, Weight: 5.5", edges[4].ToString() ); + Assert.AreEqual( "From: 3, To: 0, Weight: 4", edges[5].ToString() ); + } + + [TestMethod] + public void OutDegree_WhenVertexHas3EdgesToOtherVertices_WillBe3() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + graph.AddEdge( new DirectedEdge( 1, 2, 1.0 ) ); + graph.AddEdge( new DirectedEdge( 1, 3, 1.5 ) ); + graph.AddEdge( new DirectedEdge( 1, 4, 1.0 ) ); + + Assert.AreEqual( 3, graph.OutDegree( 1 ) ); + } + + [TestMethod] + public void ToString_WhenGraphHasMultipleVerticesAndEdges_WillReturnExceptedString() + { + EdgeWeightedDigraph graph = new EdgeWeightedDigraph( 5 ); + graph.AddEdge( new DirectedEdge( 0, 2, 2.0 ) ); + graph.AddEdge( new DirectedEdge( 0, 4, 4.0 ) ); + graph.AddEdge( new DirectedEdge( 1, 2, 1.0 ) ); + graph.AddEdge( new DirectedEdge( 1, 3, 1.0 ) ); + graph.AddEdge( new DirectedEdge( 2, 0, 3.75 ) ); + graph.AddEdge( new DirectedEdge( 3, 4, 5.5 ) ); + graph.AddEdge( new DirectedEdge( 3, 0, 4.0 ) ); + + string[] tokens = graph.ToString().Split( Environment.NewLine ); + + Assert.AreEqual( "5 vertices, 7 edges", tokens[0] ); + Assert.AreEqual( "0: 2 4", tokens[1] ); + Assert.AreEqual( "1: 2 3", tokens[2] ); + Assert.AreEqual( "2: 0", tokens[3] ); + Assert.AreEqual( "3: 4 0", tokens[4] ); + Assert.AreEqual( "4:", tokens[5] ); + Assert.AreEqual( 6, tokens.Length ); + } + } +} diff --git a/RogueSharp.Test/Algorithms/GraphTest.cs b/RogueSharp.Test/Algorithms/GraphTest.cs new file mode 100644 index 0000000..35969c9 --- /dev/null +++ b/RogueSharp.Test/Algorithms/GraphTest.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RogueSharp.Algorithms; + +namespace RogueSharp.Test.Algorithms +{ + [TestClass] + public class GraphTest + { + [TestMethod] + public void NumberOfVertices_AfterConstructingNewGraphWith10Vertices_WillBe10() + { + Graph graph = new Graph( 10 ); + + int numberOfVertices = graph.NumberOfVertices; + + Assert.AreEqual( 10, numberOfVertices ); + } + + [TestMethod] + public void NumberOfEdges_AfterConstructingNewGraphWith10Vertices_WillBe0() + { + Graph graph = new Graph( 10 ); + + int numberOfEdges = graph.NumberOfEdges; + + Assert.AreEqual( 0, numberOfEdges ); + } + + [TestMethod] + public void AddEdge_WhenGraphHasNoExistingEdges_GraphWillHave1Edge() + { + Graph graph = new Graph( 10 ); + + graph.AddEdge( 1, 2 ); + + int numberOfEdges = graph.NumberOfEdges; + Assert.AreEqual( 1, numberOfEdges ); + } + + [TestMethod] + public void Adjacent_When2EdgesExistBetweenVertices_WillReturnBothAdjacentVertices() + { + Graph graph = new Graph( 10 ); + graph.AddEdge( 1, 2 ); + graph.AddEdge( 1, 3 ); + + List adjacentVertices = graph.Adjacent( 1 ).ToList(); + + Assert.AreEqual( 2, adjacentVertices.Count ); + Assert.IsTrue( adjacentVertices.Contains( 2 ) ); + Assert.IsTrue( adjacentVertices.Contains( 3 ) ); + } + + [TestMethod] + public void ToString_WhenGraphHas5VerticesAnd4Edges_WillReturnExpectedStringRepresentationOfGraph() + { + Graph graph = new Graph( 5 ); + graph.AddEdge( 0, 1 ); + graph.AddEdge( 1, 2 ); + graph.AddEdge( 2, 3 ); + graph.AddEdge( 0, 4 ); + + string graphString = graph.ToString(); + + string[] tokens = graphString.Split( Environment.NewLine ); + Assert.AreEqual( "5 vertices, 4 edges", tokens[0] ); + Assert.AreEqual( "0: 1 4", tokens[1] ); + Assert.AreEqual( "1: 0 2", tokens[2] ); + Assert.AreEqual( "2: 1 3", tokens[3] ); + Assert.AreEqual( "3: 2", tokens[4] ); + Assert.AreEqual( "4: 0", tokens[5] ); + Assert.AreEqual( 6, tokens.Length ); + } + } +} diff --git a/RogueSharp.Test/Algorithms/IndexMinPriorityQueueTest.cs b/RogueSharp.Test/Algorithms/IndexMinPriorityQueueTest.cs new file mode 100644 index 0000000..df03597 --- /dev/null +++ b/RogueSharp.Test/Algorithms/IndexMinPriorityQueueTest.cs @@ -0,0 +1,140 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RogueSharp.Algorithms; + +namespace RogueSharp.Test.Algorithms +{ + [TestClass] + public class IndexMinPriorityQueueTest + { + [TestMethod] + public void IsEmpty_AfterConstructingNewQueue_WillBeTrue() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + + Assert.IsTrue( queue.IsEmpty() ); + } + + [TestMethod] + public void Size_AfterInserting1Key_WillBe1() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + + Assert.AreEqual( 1, queue.Size ); + } + + [TestMethod] + public void Contains_Index4AfterInsertingKeyAtIndex4_WillBeTrue() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + + Assert.IsTrue( queue.Contains( 4 ) ); + } + + [TestMethod] + public void MinIndex_WhenMultipleKeysAreInQueue_WillReturnIndexOfMinimumKey() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + queue.Insert( 3, 40.12 ); + queue.Insert( 7, 4.3 ); + queue.Insert( 2, 162.75 ); + + int minIndex = queue.MinIndex(); + + Assert.AreEqual( 7, minIndex ); + } + + [TestMethod] + public void MinKey_WhenMultipleKeysAreInQueue_WillReturnMinimumKey() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + queue.Insert( 3, 40.12 ); + queue.Insert( 7, 4.3 ); + queue.Insert( 2, 162.75 ); + + double minKey = queue.MinKey(); + + Assert.AreEqual( 4.3, minKey ); + } + + [TestMethod] + public void KeyAt_WhenIndexIsInQueue_WillReturnKeyAtIndex() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + queue.Insert( 3, 40.12 ); + queue.Insert( 7, 4.3 ); + queue.Insert( 2, 162.75 ); + + double keyAtIndex = queue.KeyAt( 3 ); + + Assert.AreEqual( 40.12, keyAtIndex ); + } + + [TestMethod] + public void ChangeKey_WhenIndexIsInQueue_WillChangeOldKeyToNewKey() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + queue.Insert( 3, 40.12 ); + queue.Insert( 7, 4.3 ); + queue.Insert( 2, 162.75 ); + double newKey = 5.54; + + queue.ChangeKey( 3, newKey ); + + double keyAtIndex = queue.KeyAt( 3 ); + Assert.AreEqual( newKey, keyAtIndex ); + } + + [TestMethod] + public void DecreaseKey_WhenIndexIsInQueue_WillChangeOldKeyToNewSmallerKey() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + queue.Insert( 3, 40.12 ); + queue.Insert( 7, 4.3 ); + queue.Insert( 2, 162.75 ); + double newKey = 5.54; + + queue.DecreaseKey( 3, newKey ); + + double keyAtIndex = queue.KeyAt( 3 ); + Assert.AreEqual( newKey, keyAtIndex ); + } + + [TestMethod] + public void IncreaseKey_WhenIndexIsInQueue_WillChangeOldKeyToNewBiggerKey() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + queue.Insert( 3, 40.12 ); + queue.Insert( 7, 4.3 ); + queue.Insert( 2, 162.75 ); + double newKey = 5.54; + + queue.IncreaseKey( 7, newKey ); + + double keyAtIndex = queue.KeyAt( 7 ); + Assert.AreEqual( newKey, keyAtIndex ); + } + + [TestMethod] + public void Delete_WhenIndexIsInQueue_WillRemoveKeyFromQueue() + { + IndexMinPriorityQueue queue = new IndexMinPriorityQueue( 10 ); + queue.Insert( 4, 12.5 ); + queue.Insert( 3, 40.12 ); + queue.Insert( 7, 4.3 ); + queue.Insert( 2, 162.75 ); + + queue.Delete( 7 ); + + double keyAtIndex = queue.KeyAt( 7 ); + Assert.AreEqual( default( double ), keyAtIndex ); + } + } +} diff --git a/RogueSharp.Test/Algorithms/UnionFindTest.cs b/RogueSharp.Test/Algorithms/UnionFindTest.cs new file mode 100644 index 0000000..62e1324 --- /dev/null +++ b/RogueSharp.Test/Algorithms/UnionFindTest.cs @@ -0,0 +1,98 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RogueSharp.Algorithms; + +namespace RogueSharp.Test.Algorithms +{ + [TestClass] + public class UnionFindTest + { + [TestMethod] + public void UnionFind_WhenConstructorIsCalledWithNegativeNumber_WillThrowArgumentException() + { + Assert.ThrowsException( () => new UnionFind( -1 ) ); + } + + [TestMethod] + public void Count_WhenConstructorIsCalledWith5IsolatedSets_WillBe5() + { + UnionFind unionFind = new UnionFind( 5 ); + + int count = unionFind.Count; + + Assert.AreEqual( 5, count ); + } + + [TestMethod] + public void Count_WhenUnionIsCalledOn2SetsOf5_WillBe4() + { + UnionFind unionFind = new UnionFind( 5 ); + unionFind.Union( 0, 1 ); + + int count = unionFind.Count; + + Assert.AreEqual( 4, count ); + } + + [TestMethod] + public void Union_WhenCalledWith3SetsOf1ComponentEach_WillUpdateCountTo2() + { + UnionFind unionFind = new UnionFind( 3 ); + + unionFind.Union( 1, 2 ); + + int count = unionFind.Count; + Assert.AreEqual( 2, count ); + } + + [TestMethod] + public void Connected_WhenEachSetHasOnly1Component_WillBeFalse() + { + UnionFind unionFind = new UnionFind( 3 ); + + bool isConnected = unionFind.Connected( 1, 2 ); + + Assert.IsFalse( isConnected ); + } + + [TestMethod] + public void Connected_WhenUnionIsCalledOnComponents_WillBeTrue() + { + UnionFind unionFind = new UnionFind( 3 ); + unionFind.Union( 1, 2 ); + + bool isConnected = unionFind.Connected( 1, 2 ); + + Assert.IsTrue( isConnected ); + } + + [TestMethod] + public void Find_WhenCalledForSet3And3SetsExist_WillThrowArgumentOutOfRangeException() + { + UnionFind unionFind = new UnionFind( 3 ); + + Assert.ThrowsException( () => unionFind.Find( 3 ) ); + } + + [TestMethod] + public void Find_WhenUnionHasNotBeenCalled_WillBeInOriginalSet() + { + UnionFind unionFind = new UnionFind( 3 ); + + int set = unionFind.Find( 2 ); + + Assert.AreEqual( 2, set ); + } + + [TestMethod] + public void Find_WhenUnionHasBeenCalled_WillBeInNewSet() + { + UnionFind unionFind = new UnionFind( 3 ); + unionFind.Union( 1, 2 ); + + int set = unionFind.Find( 2 ); + + Assert.AreEqual( 1, set ); + } + } +} diff --git a/RogueSharp.Test/RogueSharp.Test.csproj b/RogueSharp.Test/RogueSharp.Test.csproj index c6cbdab..5749b41 100644 --- a/RogueSharp.Test/RogueSharp.Test.csproj +++ b/RogueSharp.Test/RogueSharp.Test.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/RogueSharp.sln b/RogueSharp.sln index 5a3392b..267f2d8 100644 --- a/RogueSharp.sln +++ b/RogueSharp.sln @@ -7,7 +7,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RogueSharp.Test", "RogueSha EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EC8DBBC4-3542-4859-A2C7-BAE76D5FF83E}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig HowToBuildNugetPackage.txt = HowToBuildNugetPackage.txt + LICENSE.txt = LICENSE.txt + README.md = README.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RogueSharp", "RogueSharp\RogueSharp.csproj", "{B7127CF8-EF2D-44F3-B728-F3E505822F63}" diff --git a/RogueSharp/Algorithms/DepthFirstPaths.cs b/RogueSharp/Algorithms/DepthFirstPaths.cs index 517bb78..3ec4cf6 100644 --- a/RogueSharp/Algorithms/DepthFirstPaths.cs +++ b/RogueSharp/Algorithms/DepthFirstPaths.cs @@ -30,10 +30,10 @@ public DepthFirstPaths( Graph graph, int sourceVertex ) _sourceVertex = sourceVertex; _edgeTo = new int[graph.NumberOfVertices]; _marked = new bool[graph.NumberOfVertices]; - DepthFirstSeach( graph, sourceVertex ); + DepthFirstSearch( graph, sourceVertex ); } - private void DepthFirstSeach( Graph graph, int sourceVertex ) + private void DepthFirstSearch( Graph graph, int sourceVertex ) { _marked[sourceVertex] = true; foreach ( int vertex in graph.Adjacent( sourceVertex ) ) @@ -41,7 +41,7 @@ private void DepthFirstSeach( Graph graph, int sourceVertex ) if ( !_marked[vertex] ) { _edgeTo[vertex] = sourceVertex; - DepthFirstSeach( graph, vertex ); + DepthFirstSearch( graph, vertex ); } } } @@ -60,7 +60,7 @@ public bool HasPathTo( int destinationVertex ) /// Returns a path between the sourceVertex and the specified destinationVertex or null if no such path exists /// /// The destination vertex - /// An IEnumerable sequence of vertices representing the path between the sourceVertex and the specified destinationVertex or null if no such path exists + /// An IEnumerable sequence of vertices representing the path between the sourceVertex and the specified destinationVertex or null if no such path exists. The path will not include the source vertex public IEnumerable PathTo( int destinationVertex ) { if ( !HasPathTo( destinationVertex ) ) @@ -68,6 +68,7 @@ public IEnumerable PathTo( int destinationVertex ) return null; } var path = new Stack(); + // TODO: All methods that return paths should be consistent on whether or not they include the source and destination vertices in the path. for ( int x = destinationVertex; x != _sourceVertex; x = _edgeTo[x] ) { path.Push( x ); diff --git a/RogueSharp/Algorithms/DijkstraShortestPath.cs b/RogueSharp/Algorithms/DijkstraShortestPath.cs index b9c9a26..33a8722 100644 --- a/RogueSharp/Algorithms/DijkstraShortestPath.cs +++ b/RogueSharp/Algorithms/DijkstraShortestPath.cs @@ -33,6 +33,7 @@ private DijkstraShortestPath( EdgeWeightedDigraph graph, int sourceVertex, int? throw new ArgumentNullException( "graph", "EdgeWeightedDigraph cannot be null" ); } + // TODO: Consider optimizations for building in Release vs Debug foreach ( DirectedEdge edge in graph.Edges() ) { if ( edge.Weight < 0 ) @@ -69,11 +70,11 @@ private DijkstraShortestPath( EdgeWeightedDigraph graph, int sourceVertex, int? /// /// Returns an IEnumerable of DirectedEdges representing a shortest path from the specified sourceVertex to the specified destinationVertex - /// This is more efficent than creating a new DijkstraShorestPath instance and calling PathTo( destinationVertex ) when we only + /// This is more efficient than creating a new DijkstraShortestPath instance and calling PathTo( destinationVertex ) when we only /// want a single path from Source to Destination and don't want many paths from the source to multiple different destinations. /// /// The edge-weighted directed graph - /// The source vertext to find a shortest path from + /// The source vertex to find a shortest path from /// The destination vertex to find a shortest path to /// IEnumerable of DirectedEdges representing a shortest path from the sourceVertex to the specified destinationVertex public static IEnumerable FindPath( EdgeWeightedDigraph graph, int sourceVertex, int destinationVertex ) @@ -135,6 +136,7 @@ public IEnumerable PathTo( int destinationVertex ) var path = new Stack(); for ( DirectedEdge edge = _edgeTo[destinationVertex]; edge != null; edge = _edgeTo[edge.From] ) { + // TODO: yield return edge path.Push( edge ); } return path; diff --git a/RogueSharp/Algorithms/EdgeWeightedDigraph.cs b/RogueSharp/Algorithms/EdgeWeightedDigraph.cs index 73535e6..b423221 100644 --- a/RogueSharp/Algorithms/EdgeWeightedDigraph.cs +++ b/RogueSharp/Algorithms/EdgeWeightedDigraph.cs @@ -5,7 +5,7 @@ namespace RogueSharp.Algorithms { /// - /// The EdgeWeightedDigrpah class represents an edge-weighted directed graph of vertices named 0 through V-1, where each directed edge + /// The EdgeWeightedDigraph class represents an edge-weighted directed graph of vertices named 0 through V-1, where each directed edge /// is of type DirectedEdge and has real-valued weight. /// /// EdgeWeightedDigraph class from Princeton University's Java Algorithms @@ -51,6 +51,7 @@ public void AddEdge( DirectedEdge edge ) } _adjacent[edge.From].AddLast( edge ); + NumberOfEdges++; } /// @@ -80,9 +81,9 @@ public IEnumerable Edges() /// /// Returns the number of directed edges incident from the specified vertex - /// This is known as the outdegree of the vertex + /// This is known as the out-degree of the vertex /// - /// The vertex to find find the outdegree of + /// The vertex to find find the out-degree of /// The number of directed edges incident from the specified vertex public int OutDegree( int vertex ) { @@ -98,15 +99,18 @@ public int OutDegree( int vertex ) public override string ToString() { var formattedString = new StringBuilder(); - formattedString.AppendFormat( "{0} vertices, {1} edges {2}", NumberOfVertices, NumberOfEdges, Environment.NewLine ); + formattedString.AppendFormat( "{0} vertices, {1} edges{2}", NumberOfVertices, NumberOfEdges, Environment.NewLine ); for ( int v = 0; v < NumberOfVertices; v++ ) { - formattedString.AppendFormat( "{0}: ", v ); + formattedString.AppendFormat( "{0}:", v ); foreach ( DirectedEdge edge in _adjacent[v] ) { - formattedString.AppendFormat( "{0} ", edge.To ); + formattedString.AppendFormat( " {0}", edge.To ); + } + if ( v < NumberOfVertices - 1 ) + { + formattedString.AppendLine(); } - formattedString.AppendLine(); } return formattedString.ToString(); } diff --git a/RogueSharp/Algorithms/Graph.cs b/RogueSharp/Algorithms/Graph.cs index 79801a4..c2e357e 100644 --- a/RogueSharp/Algorithms/Graph.cs +++ b/RogueSharp/Algorithms/Graph.cs @@ -68,15 +68,18 @@ public IEnumerable Adjacent( int vertex ) public override string ToString() { var formattedString = new StringBuilder(); - formattedString.AppendFormat( "{0} vertices, {1} edges {2}", NumberOfVertices, NumberOfEdges, Environment.NewLine ); + formattedString.AppendFormat( "{0} vertices, {1} edges{2}", NumberOfVertices, NumberOfEdges, Environment.NewLine ); for ( int v = 0; v < NumberOfVertices; v++ ) { - formattedString.AppendFormat( "{0}: ", v ); + formattedString.AppendFormat( "{0}:", v ); foreach ( int vertex in _adjacent[v] ) { - formattedString.AppendFormat( "{0} ", vertex ); + formattedString.AppendFormat( " {0}", vertex ); + } + if ( v < NumberOfVertices - 1 ) + { + formattedString.AppendLine(); } - formattedString.AppendLine(); } return formattedString.ToString(); } diff --git a/RogueSharp/Cell.cs b/RogueSharp/Cell.cs index 9bc8159..f806bb1 100644 --- a/RogueSharp/Cell.cs +++ b/RogueSharp/Cell.cs @@ -91,7 +91,7 @@ public Cell( int x, int y, bool isTransparent, bool isWalkable, bool isInFov ) /// /// /// The explored property of a Cell can be used to track if the Cell has ever been in the field-of-view of a character controlled by the player - /// This property will not automatically be updated based on FOV calcuations or any other built-in functions of the RogueSharp library. + /// This property will not automatically be updated based on FOV calculations or any other built-in functions of the RogueSharp library. /// /// /// As the player moves characters around a Map, Cells will enter and exit the currently computed field-of-view @@ -109,7 +109,7 @@ public Cell( int x, int y, bool isTransparent, bool isWalkable, bool isInFov ) /// /// This call ignores field-of-view. If field-of-view is important use the ToString overload with a "true" parameter /// - /// A string represenation of the Cell using special symbols to denote Cell properties + /// A string representation of the Cell using special symbols to denote Cell properties public override string ToString() { return ToString( false ); @@ -123,7 +123,7 @@ public override string ToString() /// - `o`: `Cell` is transparent and in field-of-view (but not walkable) /// - `#`: `Cell` is in field-of-view (but not transparent or walkable) /// - /// True if field-of-view calculations will be used when creating the string represenation of the Cell. False otherwise + /// True if field-of-view calculations will be used when creating the string representation of the Cell. False otherwise /// A string representation of the Cell using special symbols to denote Cell properties public string ToString( bool useFov ) { diff --git a/RogueSharp/DiceNotation/DiceExpression.cs b/RogueSharp/DiceNotation/DiceExpression.cs index ddea23f..69a8300 100644 --- a/RogueSharp/DiceNotation/DiceExpression.cs +++ b/RogueSharp/DiceNotation/DiceExpression.cs @@ -73,7 +73,7 @@ public DiceExpression Dice( int multiplicity, int sides, int scalar ) /// The number of Dice /// The number of sides per Die /// The value to multiply the result of the Roll of these Dice by - /// Optional number of dice to choose out of the total rolled. The highest rolled Dice will be choosen. + /// Optional number of dice to choose out of the total rolled. The highest rolled Dice will be chosen. /// A DiceExpression representing the previous terms in this DiceExpression plus these newly added Dice public DiceExpression Dice( int multiplicity, int sides, int scalar, int? choose ) { diff --git a/RogueSharp/GoalMap.cs b/RogueSharp/GoalMap.cs index 34c7593..2c3b571 100644 --- a/RogueSharp/GoalMap.cs +++ b/RogueSharp/GoalMap.cs @@ -33,7 +33,7 @@ public GoalMap( IMap map ) } /// - /// Constructs a new instance of a GoalMap for the specified Map that will consider diagonal movments to be valid if allowDiagonalMovement is set to true. + /// Constructs a new instance of a GoalMap for the specified Map that will consider diagonal movements to be valid if allowDiagonalMovement is set to true. /// /// The Map that this GoalMap will be created for /// True if diagonal movements are allowed. False otherwise @@ -104,7 +104,7 @@ public void AddObstacle( int x, int y ) /// /// Add multiple obstacles from the specified enumeration of locations /// - /// An enumeration of points representing X, Y locations of Obstacles to avoid when pathfinding + /// An enumeration of points representing X, Y locations of Obstacles to avoid when path-finding public void AddObstacles( IEnumerable obstacles ) { if ( obstacles == null ) diff --git a/RogueSharp/ICell.cs b/RogueSharp/ICell.cs index 80dcc40..4be99a9 100644 --- a/RogueSharp/ICell.cs +++ b/RogueSharp/ICell.cs @@ -56,7 +56,7 @@ public interface ICell : IEquatable /// /// /// The explored property of a Cell can be used to track if the Cell has ever been in the field-of-view of a character controlled by the player - /// This property will not automatically be updated based on FOV calcuations or any other built-in functions of the RogueSharp library. + /// This property will not automatically be updated based on FOV calculations or any other built-in functions of the RogueSharp library. /// /// /// As the player moves characters around a Map, Cells will enter and exit the currently computed field-of-view diff --git a/RogueSharp/IGoalMap.cs b/RogueSharp/IGoalMap.cs index 1e43aef..6e9472a 100644 --- a/RogueSharp/IGoalMap.cs +++ b/RogueSharp/IGoalMap.cs @@ -8,7 +8,7 @@ namespace RogueSharp /// /// /// - /// Inspired by the article "The Incredible Power of Dijkstra Maps on roguebasin + /// Inspired by the article "The Incredible Power of Dijkstra Maps" on roguebasin public interface IGoalMap { /// @@ -41,7 +41,7 @@ public interface IGoalMap /// /// Add multiple obstacles from the specified enumeration of locations /// - /// An enumeration of points representing X, Y locations of Obstacles to avoid when pathfinding + /// An enumeration of points representing X, Y locations of Obstacles to avoid when path-finding void AddObstacles( IEnumerable obstacles ); /// diff --git a/RogueSharp/IMap.cs b/RogueSharp/IMap.cs index 69d74b8..fcb8e01 100644 --- a/RogueSharp/IMap.cs +++ b/RogueSharp/IMap.cs @@ -291,7 +291,7 @@ int Height /// - `o`: `Cell` is transparent and in field-of-view (but not walkable) /// - `#`: `Cell` is in field-of-view (but not transparent or walkable) /// - /// True if field-of-view calculations will be used when creating the string represenation of the Map. False otherwise + /// True if field-of-view calculations will be used when creating the string representation of the Map. False otherwise /// A string representation of the map using special symbols to denote Cell properties string ToString( bool useFov ); @@ -299,13 +299,13 @@ int Height /// Get a MapState POCO which represents this Map and can be easily serialized /// Use Restore with the MapState to get back a full Map /// - /// Mapstate POCO (Plain Old C# Object) which represents this Map and can be easily serialized + /// MapState POCO (Plain Old C# Object) which represents this Map and can be easily serialized MapState Save(); /// /// Restore the state of this Map from the specified MapState /// - /// Mapstate POCO (Plain Old C# Object) which represents this Map and can be easily serialized and deserialized + /// MapState POCO (Plain Old C# Object) which represents this Map and can be easily serialized and deserialized void Restore( MapState state ); /// @@ -383,7 +383,7 @@ public int Height /// /// An array of the Flags Enumeration of CellProperties for each Cell in the Map. - /// The index of the array corresponds to the location of the Cell within the Map using the forumla: index = ( y * Width ) + x + /// The index of the array corresponds to the location of the Cell within the Map using the formula: index = ( y * Width ) + x /// public CellProperties[] Cells { diff --git a/RogueSharp/Map.cs b/RogueSharp/Map.cs index 7e8cfd5..c44c400 100644 --- a/RogueSharp/Map.cs +++ b/RogueSharp/Map.cs @@ -677,7 +677,7 @@ public ICell GetCell( int x, int y ) /// - `o`: `Cell` is transparent and in field-of-view (but not walkable) /// - `#`: `Cell` is in field-of-view (but not transparent or walkable) /// - /// True if field-of-view calculations will be used when creating the string represenation of the Map. False otherwise + /// True if field-of-view calculations will be used when creating the string representation of the Map. False otherwise /// A string representation of the map using special symbols to denote Cell properties public string ToString( bool useFov ) { @@ -700,7 +700,7 @@ public string ToString( bool useFov ) /// Get a MapState POCO which represents this Map and can be easily serialized /// Use Restore with the MapState to get back a full Map /// - /// Mapstate POCO (Plain Old C# Object) which represents this Map and can be easily serialized + /// MapState POCO (Plain Old C# Object) which represents this Map and can be easily serialized public MapState Save() { var mapState = new MapState(); @@ -730,7 +730,7 @@ public MapState Save() /// /// Restore the state of this Map from the specified MapState /// - /// Mapstate POCO (Plain Old C# Object) which represents this Map and can be easily serialized and deserialized + /// MapState POCO (Plain Old C# Object) which represents this Map and can be easily serialized and deserialized /// Thrown on null map state public void Restore( MapState state ) { diff --git a/RogueSharp/MapCreation/CaveMapCreationStrategy.cs b/RogueSharp/MapCreation/CaveMapCreationStrategy.cs index 340d1b6..8f216cf 100644 --- a/RogueSharp/MapCreation/CaveMapCreationStrategy.cs +++ b/RogueSharp/MapCreation/CaveMapCreationStrategy.cs @@ -27,7 +27,7 @@ namespace RogueSharp.MapCreation /// The height of the Map to be created /// Recommend int between 40 and 60. Percent chance that a given cell will be a floor when randomizing all cells. /// Recommend int between 2 and 5. Number of times to execute the cellular automata algorithm. - /// Recommend int less than 4. The interation number to switch from the large area fill algorithm to a nearest neighbor algorithm + /// Recommend int less than 4. The iteration number to switch from the large area fill algorithm to a nearest neighbor algorithm /// A class implementing IRandom that will be used to generate pseudo-random numbers necessary to create the Map public CaveMapCreationStrategy( int width, int height, int fillProbability, int totalIterations, int cutoffOfBigAreaFill, IRandom random ) { @@ -47,7 +47,7 @@ public CaveMapCreationStrategy( int width, int height, int fillProbability, int /// The height of the Map to be created /// Recommend int between 40 and 60. Percent chance that a given cell will be a floor when randomizing all cells. /// Recommend int between 2 and 5. Number of times to execute the cellular automata algorithm. - /// Recommend int less than 4. The interation number to switch from the large area fill algorithm to a nearest neighbor algorithm + /// Recommend int less than 4. The iteration number to switch from the large area fill algorithm to a nearest neighbor algorithm /// Uses DotNetRandom as its RNG public CaveMapCreationStrategy( int width, int height, int fillProbability, int totalIterations, int cutoffOfBigAreaFill ) { @@ -282,7 +282,7 @@ public List GetMapSections() private MapSection Visit(ICell cell) { Stack stack = new Stack(new List()); - MapSection mapsection = new MapSection(); + MapSection mapSection = new MapSection(); stack.Push(cell); while ( stack.Count != 0 ) { @@ -291,7 +291,7 @@ private MapSection Visit(ICell cell) { continue; } - mapsection.AddCell( cell ); + mapSection.AddCell( cell ); _visited[cell.Y][cell.X] = true; foreach ( ICell neighbor in GetNeighbors(cell) ) { @@ -301,7 +301,7 @@ private MapSection Visit(ICell cell) } } } - return mapsection; + return mapSection; } private ICell GetCell( int x, int y ) diff --git a/RogueSharp/MapCreation/RandomRoomsMapCreationStrategy.cs b/RogueSharp/MapCreation/RandomRoomsMapCreationStrategy.cs index 4b1efd2..97dad41 100644 --- a/RogueSharp/MapCreation/RandomRoomsMapCreationStrategy.cs +++ b/RogueSharp/MapCreation/RandomRoomsMapCreationStrategy.cs @@ -62,7 +62,7 @@ public RandomRoomsMapCreationStrategy( int width, int height, int maxRooms, int /// The Map will be generated by trying to place rooms up to the maximum number specified in random locations around the Map. /// Each room will have a height and width between the minimum and maximum room size. /// If a room would be placed in such a way that it overlaps another room, it will not be placed. - /// Once all rooms have have been placed, or thrown out because they overlap, cooridors will be created between rooms in a random manner. + /// Once all rooms have have been placed, or thrown out because they overlap, corridors will be created between rooms in a random manner. /// /// An IMap of the specified type public T CreateMap() diff --git a/RogueSharp/Path.cs b/RogueSharp/Path.cs index b3a69db..7f8156e 100644 --- a/RogueSharp/Path.cs +++ b/RogueSharp/Path.cs @@ -65,7 +65,7 @@ public int Length } /// - /// The Cell represeting the step that is currently occupied in this Path + /// The Cell representing the step that is currently occupied in this Path /// public ICell CurrentStep { diff --git a/RogueSharp/Random/GaussianRandom.cs b/RogueSharp/Random/GaussianRandom.cs index 6b4a022..c5b61e1 100644 --- a/RogueSharp/Random/GaussianRandom.cs +++ b/RogueSharp/Random/GaussianRandom.cs @@ -18,7 +18,7 @@ public class GaussianRandom : IRandom private System.Random _random; private long _numberGenerated; private double _nextGaussian; - private bool _uselast = true; + private bool _useLast = true; /// /// Constructs a new Gaussian pseudo-random number generator @@ -120,7 +120,7 @@ public void Restore( RandomState state ) _random = new System.Random( _seed ); _numberGenerated = default( long ); _nextGaussian = default( double ); - _uselast = true; + _useLast = true; for ( long i = 0; i < state.NumberGenerated; i++ ) { Next( 1 ); @@ -128,9 +128,9 @@ public void Restore( RandomState state ) } private double BoxMuller() { - if ( _uselast ) + if ( _useLast ) { - _uselast = false; + _useLast = false; return _nextGaussian; } else @@ -147,7 +147,7 @@ private double BoxMuller() s = Math.Sqrt( ( -2.0 * Math.Log( s ) ) / s ); _nextGaussian = v2 * s; - _uselast = true; + _useLast = true; return v1 * s; } } diff --git a/RogueSharp/Random/IRandom.cs b/RogueSharp/Random/IRandom.cs index 127cf83..83bb38c 100644 --- a/RogueSharp/Random/IRandom.cs +++ b/RogueSharp/Random/IRandom.cs @@ -3,7 +3,7 @@ /// /// An Interface for pseudo-random number generators to implement. /// Useful when mocking out systems for tests, as the the random number generator can be swapped for - /// a mock implimentation that returns known and expected values + /// a mock implementation that returns known and expected values /// /// /// Pseudo-random number generators are devices that produces a sequence of numbers diff --git a/RogueSharp/RogueSharp.csproj b/RogueSharp/RogueSharp.csproj index b37f21c..085e341 100644 --- a/RogueSharp/RogueSharp.csproj +++ b/RogueSharp/RogueSharp.csproj @@ -2,10 +2,10 @@ netstandard1.0;net40 - 4.1.0 + 4.2.0 Faron Bracy - A .NET Standard class library for roguelike developers to provide utilities frequently used in roguelikes or 2D tile based games. Inspired by libtcod + A .NET Standard class library providing map generation, path-finding, and field-of-view utilities frequently used in roguelikes or 2D tile based games. Inspired by libtcod New features: * Optimized cave map generator (Thanks to James Neal) @@ -14,6 +14,7 @@ New features: * Diagonal paths can be found by using new constructors on GoalMap and PathFinder * Map.GetCellsInCircle and Map.GetBorderCellsInCircle to get cells within a circular radius Breaking changes: + * Bug fix (4.2.0) - EdgeWeightedDigraph updates NumberOfEdges property when new edge is added * Bug fix (4.1.0) - selecting border cells along edge of map no longer selects center cell * Point and Rectangle classes are now structs (Thanks to James Neal) * Updated all appropriate references to Cell with ICell (Thanks to Courtney Strachan) @@ -21,7 +22,7 @@ Breaking changes: * The Path returned from PathFinder.ShortestPath now includes the source cell in the returned Path * Map.GetCellsInArea was renamed to Map.GetCellsInSquare * Map.GetCellsInRadius was renamed to Map.GetCellsInDiamond - A .NET Standard class library for roguelike developers to provide utilities frequently used in roguelikes or 2D tile based games. Inspired by libtcod + A .NET Standard class library providing map generation, path-finding, and field-of-view utilities frequently used in roguelikes or 2D tile based games. Inspired by libtcod New features: * Optimized cave map generator (Thanks to James Neal) @@ -30,6 +31,7 @@ New features: * Diagonal paths can be found by using new constructors on GoalMap and PathFinder * Map.GetCellsInCircle and Map.GetBorderCellsInCircle to get cells within a circular radius Breaking changes: + * Bug fix (4.2.0) - EdgeWeightedDigraph updates NumberOfEdges property when new edge is added * Bug fix (4.1.0) - selecting border cells along edge of map no longer selects center cell * Point and Rectangle classes are now structs (Thanks to James Neal) * Updated all appropriate references to Cell with ICell (Thanks to Courtney Strachan) @@ -37,7 +39,7 @@ Breaking changes: * The Path returned from PathFinder.ShortestPath now includes the source cell in the returned Path * Map.GetCellsInArea was renamed to Map.GetCellsInSquare * Map.GetCellsInRadius was renamed to Map.GetCellsInDiamond - Copyright 2014-2018 Faron Bracy + Copyright 2014-2019 Faron Bracy https://github.com/FaronBracy/RogueSharp/blob/master/LICENSE.txt https://github.com/FaronBracy/RogueSharp https://github.com/FaronBracy/RogueSharp.git diff --git a/docs/RogueSharp.Algorithms/DepthFirstPaths.htm b/docs/RogueSharp.Algorithms/DepthFirstPaths.htm index a67c78c..40ae854 100644 --- a/docs/RogueSharp.Algorithms/DepthFirstPaths.htm +++ b/docs/RogueSharp.Algorithms/DepthFirstPaths.htm @@ -152,7 +152,7 @@
Returns
IEnumerable<int>
-
An IEnumerable sequence of vertices representing the path between the sourceVertex and the specified destinationVertex or null if no such path exists +
An IEnumerable sequence of vertices representing the path between the sourceVertex and the specified destinationVertex or null if no such path exists. The path will not include the source vertex
@@ -163,7 +163,7 @@
Returns