mirror of
				https://github.com/bensuperpc/astar.git
				synced 2025-10-30 21:36:23 +01:00 
			
		
		
		
	
							
								
								
									
										259
									
								
								.clang-format
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										259
									
								
								.clang-format
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,259 @@ | ||||
| --- | ||||
| Language:        Cpp | ||||
| # BasedOnStyle:  Chromium | ||||
| AccessModifierOffset: -1 | ||||
| AlignAfterOpenBracket: Align | ||||
| AlignArrayOfStructures: None | ||||
| AlignConsecutiveAssignments: | ||||
|   Enabled:         false | ||||
|   AcrossEmptyLines: false | ||||
|   AcrossComments:  false | ||||
|   AlignCompound:   false | ||||
|   PadOperators:    true | ||||
| AlignConsecutiveBitFields: | ||||
|   Enabled:         false | ||||
|   AcrossEmptyLines: false | ||||
|   AcrossComments:  false | ||||
|   AlignCompound:   false | ||||
|   PadOperators:    false | ||||
| AlignConsecutiveDeclarations: | ||||
|   Enabled:         false | ||||
|   AcrossEmptyLines: false | ||||
|   AcrossComments:  false | ||||
|   AlignCompound:   false | ||||
|   PadOperators:    false | ||||
| AlignConsecutiveMacros: | ||||
|   Enabled:         false | ||||
|   AcrossEmptyLines: false | ||||
|   AcrossComments:  false | ||||
|   AlignCompound:   false | ||||
|   PadOperators:    false | ||||
| AlignEscapedNewlines: Left | ||||
| AlignOperands:   Align | ||||
| AlignTrailingComments: | ||||
|   Kind:            Always | ||||
|   OverEmptyLines:  0 | ||||
| AllowAllArgumentsOnNextLine: true | ||||
| AllowAllParametersOfDeclarationOnNextLine: false | ||||
| AllowShortBlocksOnASingleLine: Never | ||||
| AllowShortCaseLabelsOnASingleLine: false | ||||
| AllowShortEnumsOnASingleLine: true | ||||
| AllowShortFunctionsOnASingleLine: Inline | ||||
| AllowShortIfStatementsOnASingleLine: Never | ||||
| AllowShortLambdasOnASingleLine: All | ||||
| AllowShortLoopsOnASingleLine: false | ||||
| AlwaysBreakAfterDefinitionReturnType: None | ||||
| AlwaysBreakAfterReturnType: None | ||||
| AlwaysBreakBeforeMultilineStrings: true | ||||
| AlwaysBreakTemplateDeclarations: Yes | ||||
| AttributeMacros: | ||||
|   - __capability | ||||
| BinPackArguments: true | ||||
| BinPackParameters: false | ||||
| BitFieldColonSpacing: Both | ||||
| BraceWrapping: | ||||
|   AfterCaseLabel:  false | ||||
|   AfterClass:      false | ||||
|   AfterControlStatement: Never | ||||
|   AfterEnum:       false | ||||
|   AfterExternBlock: false | ||||
|   AfterFunction:   false | ||||
|   AfterNamespace:  false | ||||
|   AfterObjCDeclaration: false | ||||
|   AfterStruct:     false | ||||
|   AfterUnion:      false | ||||
|   BeforeCatch:     false | ||||
|   BeforeElse:      false | ||||
|   BeforeLambdaBody: false | ||||
|   BeforeWhile:     false | ||||
|   IndentBraces:    false | ||||
|   SplitEmptyFunction: true | ||||
|   SplitEmptyRecord: true | ||||
|   SplitEmptyNamespace: true | ||||
| BreakAfterAttributes: Never | ||||
| BreakAfterJavaFieldAnnotations: false | ||||
| BreakArrays:     true | ||||
| BreakBeforeBinaryOperators: None | ||||
| BreakBeforeConceptDeclarations: Always | ||||
| BreakBeforeBraces: Attach | ||||
| BreakBeforeInlineASMColon: OnlyMultiline | ||||
| BreakBeforeTernaryOperators: true | ||||
| BreakConstructorInitializers: BeforeColon | ||||
| BreakInheritanceList: BeforeColon | ||||
| BreakStringLiterals: true | ||||
| ColumnLimit:     144 | ||||
| CommentPragmas:  '^ IWYU pragma:' | ||||
| CompactNamespaces: false | ||||
| ConstructorInitializerIndentWidth: 4 | ||||
| ContinuationIndentWidth: 4 | ||||
| Cpp11BracedListStyle: true | ||||
| DerivePointerAlignment: false | ||||
| DisableFormat:   false | ||||
| EmptyLineAfterAccessModifier: Never | ||||
| EmptyLineBeforeAccessModifier: LogicalBlock | ||||
| ExperimentalAutoDetectBinPacking: false | ||||
| FixNamespaceComments: true | ||||
| ForEachMacros: | ||||
|   - foreach | ||||
|   - Q_FOREACH | ||||
|   - BOOST_FOREACH | ||||
| IfMacros: | ||||
|   - KJ_IF_MAYBE | ||||
| IncludeBlocks:   Preserve | ||||
| IncludeCategories: | ||||
|   - Regex:           '^<ext/.*\.h>' | ||||
|     Priority:        2 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
|   - Regex:           '^<.*\.h>' | ||||
|     Priority:        1 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
|   - Regex:           '^<.*' | ||||
|     Priority:        2 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
|   - Regex:           '.*' | ||||
|     Priority:        3 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
| IncludeIsMainRegex: '([-_](test|unittest))?$' | ||||
| IncludeIsMainSourceRegex: '' | ||||
| IndentAccessModifiers: false | ||||
| IndentCaseBlocks: false | ||||
| IndentCaseLabels: true | ||||
| IndentExternBlock: AfterExternBlock | ||||
| IndentGotoLabels: true | ||||
| IndentPPDirectives: None | ||||
| IndentRequiresClause: true | ||||
| IndentWidth:     4 | ||||
| IndentWrappedFunctionNames: false | ||||
| InsertBraces:    false | ||||
| InsertNewlineAtEOF: false | ||||
| InsertTrailingCommas: None | ||||
| IntegerLiteralSeparator: | ||||
|   Binary:          0 | ||||
|   BinaryMinDigits: 0 | ||||
|   Decimal:         0 | ||||
|   DecimalMinDigits: 0 | ||||
|   Hex:             0 | ||||
|   HexMinDigits:    0 | ||||
| JavaScriptQuotes: Leave | ||||
| JavaScriptWrapImports: true | ||||
| KeepEmptyLinesAtTheStartOfBlocks: false | ||||
| LambdaBodyIndentation: Signature | ||||
| LineEnding:      DeriveLF | ||||
| MacroBlockBegin: '' | ||||
| MacroBlockEnd:   '' | ||||
| MaxEmptyLinesToKeep: 1 | ||||
| NamespaceIndentation: None | ||||
| ObjCBinPackProtocolList: Never | ||||
| ObjCBlockIndentWidth: 2 | ||||
| ObjCBreakBeforeNestedBlockParam: true | ||||
| ObjCSpaceAfterProperty: false | ||||
| ObjCSpaceBeforeProtocolList: true | ||||
| PackConstructorInitializers: NextLine | ||||
| PenaltyBreakAssignment: 2 | ||||
| PenaltyBreakBeforeFirstCallParameter: 1 | ||||
| PenaltyBreakComment: 300 | ||||
| PenaltyBreakFirstLessLess: 120 | ||||
| PenaltyBreakOpenParenthesis: 0 | ||||
| PenaltyBreakString: 1000 | ||||
| PenaltyBreakTemplateDeclaration: 10 | ||||
| PenaltyExcessCharacter: 1000000 | ||||
| PenaltyIndentedWhitespace: 0 | ||||
| PenaltyReturnTypeOnItsOwnLine: 200 | ||||
| PointerAlignment: Left | ||||
| PPIndentWidth:   -1 | ||||
| QualifierAlignment: Leave | ||||
| RawStringFormats: | ||||
|   - Language:        Cpp | ||||
|     Delimiters: | ||||
|       - cc | ||||
|       - CC | ||||
|       - cpp | ||||
|       - Cpp | ||||
|       - CPP | ||||
|       - 'c++' | ||||
|       - 'C++' | ||||
|     CanonicalDelimiter: '' | ||||
|     BasedOnStyle:    google | ||||
|   - Language:        TextProto | ||||
|     Delimiters: | ||||
|       - pb | ||||
|       - PB | ||||
|       - proto | ||||
|       - PROTO | ||||
|     EnclosingFunctions: | ||||
|       - EqualsProto | ||||
|       - EquivToProto | ||||
|       - PARSE_PARTIAL_TEXT_PROTO | ||||
|       - PARSE_TEST_PROTO | ||||
|       - PARSE_TEXT_PROTO | ||||
|       - ParseTextOrDie | ||||
|       - ParseTextProtoOrDie | ||||
|       - ParseTestProto | ||||
|       - ParsePartialTestProto | ||||
|     CanonicalDelimiter: pb | ||||
|     BasedOnStyle:    google | ||||
| ReferenceAlignment: Pointer | ||||
| ReflowComments:  true | ||||
| RemoveBracesLLVM: false | ||||
| RemoveSemicolon: false | ||||
| RequiresClausePosition: OwnLine | ||||
| RequiresExpressionIndentation: OuterScope | ||||
| SeparateDefinitionBlocks: Leave | ||||
| ShortNamespaceLines: 1 | ||||
| SortIncludes:    CaseSensitive | ||||
| SortJavaStaticImport: Before | ||||
| SortUsingDeclarations: LexicographicNumeric | ||||
| SpaceAfterCStyleCast: false | ||||
| SpaceAfterLogicalNot: false | ||||
| SpaceAfterTemplateKeyword: true | ||||
| SpaceAroundPointerQualifiers: Default | ||||
| SpaceBeforeAssignmentOperators: true | ||||
| SpaceBeforeCaseColon: false | ||||
| SpaceBeforeCpp11BracedList: false | ||||
| SpaceBeforeCtorInitializerColon: true | ||||
| SpaceBeforeInheritanceColon: true | ||||
| SpaceBeforeParens: ControlStatements | ||||
| SpaceBeforeParensOptions: | ||||
|   AfterControlStatements: true | ||||
|   AfterForeachMacros: true | ||||
|   AfterFunctionDefinitionName: false | ||||
|   AfterFunctionDeclarationName: false | ||||
|   AfterIfMacros:   true | ||||
|   AfterOverloadedOperator: false | ||||
|   AfterRequiresInClause: false | ||||
|   AfterRequiresInExpression: false | ||||
|   BeforeNonEmptyParentheses: false | ||||
| SpaceBeforeRangeBasedForLoopColon: true | ||||
| SpaceBeforeSquareBrackets: false | ||||
| SpaceInEmptyBlock: false | ||||
| SpaceInEmptyParentheses: false | ||||
| SpacesBeforeTrailingComments: 2 | ||||
| SpacesInAngles:  Never | ||||
| SpacesInConditionalStatement: false | ||||
| SpacesInContainerLiterals: true | ||||
| SpacesInCStyleCastParentheses: false | ||||
| SpacesInLineCommentPrefix: | ||||
|   Minimum:         1 | ||||
|   Maximum:         -1 | ||||
| SpacesInParentheses: false | ||||
| SpacesInSquareBrackets: false | ||||
| Standard:        Auto | ||||
| StatementAttributeLikeMacros: | ||||
|   - Q_EMIT | ||||
| StatementMacros: | ||||
|   - Q_UNUSED | ||||
|   - QT_REQUIRE_VERSION | ||||
| TabWidth:        8 | ||||
| UseTab:          Never | ||||
| WhitespaceSensitiveMacros: | ||||
|   - BOOST_PP_STRINGIZE | ||||
|   - CF_SWIFT_NAME | ||||
|   - NS_SWIFT_NAME | ||||
|   - PP_STRINGIZE | ||||
|   - STRINGIZE | ||||
| ... | ||||
|  | ||||
							
								
								
									
										155
									
								
								.clang-tidy
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								.clang-tidy
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| --- | ||||
| # Enable ALL the things! Except not really | ||||
| # misc-non-private-member-variables-in-classes: the options don't do anything | ||||
| # modernize-use-nodiscard: too aggressive, attribute is situationally useful | ||||
| Checks: "*,\ | ||||
|   -google-readability-todo,\ | ||||
|   -altera-*,\ | ||||
|   -fuchsia-*,\ | ||||
|   fuchsia-multiple-inheritance,\ | ||||
|   -llvm-header-guard,\ | ||||
|   -llvm-include-order,\ | ||||
|   -llvmlibc-*,\ | ||||
|   -modernize-use-nodiscard,\ | ||||
|   -misc-non-private-member-variables-in-classes" | ||||
| WarningsAsErrors: '' | ||||
| CheckOptions: | ||||
|   - key: 'bugprone-argument-comment.StrictMode' | ||||
|     value: 'true' | ||||
| # Prefer using enum classes with 2 values for parameters instead of bools | ||||
|   - key: 'bugprone-argument-comment.CommentBoolLiterals' | ||||
|     value: 'true' | ||||
|   - key: 'bugprone-misplaced-widening-cast.CheckImplicitCasts' | ||||
|     value: 'true' | ||||
|   - key: 'bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression' | ||||
|     value: 'true' | ||||
|   - key: 'bugprone-suspicious-string-compare.WarnOnLogicalNotComparison' | ||||
|     value: 'true' | ||||
|   - key: 'readability-simplify-boolean-expr.ChainedConditionalReturn' | ||||
|     value: 'true' | ||||
|   - key: 'readability-simplify-boolean-expr.ChainedConditionalAssignment' | ||||
|     value: 'true' | ||||
|   - key: 'readability-uniqueptr-delete-release.PreferResetCall' | ||||
|     value: 'true' | ||||
|   - key: 'cppcoreguidelines-init-variables.MathHeader' | ||||
|     value: '<cmath>' | ||||
|   - key: 'cppcoreguidelines-narrowing-conversions.PedanticMode' | ||||
|     value: 'true' | ||||
|   - key: 'readability-else-after-return.WarnOnUnfixable' | ||||
|     value: 'true' | ||||
|   - key: 'readability-else-after-return.WarnOnConditionVariables' | ||||
|     value: 'true' | ||||
|   - key: 'readability-inconsistent-declaration-parameter-name.Strict' | ||||
|     value: 'true' | ||||
|   - key: 'readability-qualified-auto.AddConstToQualified' | ||||
|     value: 'true' | ||||
|   - key: 'readability-redundant-access-specifiers.CheckFirstDeclaration' | ||||
|     value: 'true' | ||||
| # These seem to be the most common identifier styles | ||||
|   - key: 'readability-identifier-naming.AbstractClassCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ClassCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ClassConstantCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ClassMemberCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ClassMethodCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ConstantCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ConstantMemberCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ConstantParameterCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ConstantPointerParameterCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ConstexprFunctionCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ConstexprMethodCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ConstexprVariableCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.EnumCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.EnumConstantCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.FunctionCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.GlobalConstantCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.GlobalConstantPointerCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.GlobalFunctionCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.GlobalPointerCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.GlobalVariableCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.InlineNamespaceCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.LocalConstantCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.LocalConstantPointerCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.LocalPointerCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.LocalVariableCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.MacroDefinitionCase' | ||||
|     value: 'UPPER_CASE' | ||||
|   - key: 'readability-identifier-naming.MemberCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.MethodCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.NamespaceCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ParameterCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ParameterPackCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.PointerParameterCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.PrivateMemberCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.PrivateMemberPrefix' | ||||
|     value: 'm_' | ||||
|   - key: 'readability-identifier-naming.PrivateMethodCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ProtectedMemberCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ProtectedMemberPrefix' | ||||
|     value: 'm_' | ||||
|   - key: 'readability-identifier-naming.ProtectedMethodCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.PublicMemberCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.PublicMethodCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ScopedEnumConstantCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.StaticConstantCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.StaticVariableCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.StructCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.TemplateParameterCase' | ||||
|     value: 'CamelCase' | ||||
|   - key: 'readability-identifier-naming.TemplateTemplateParameterCase' | ||||
|     value: 'CamelCase' | ||||
|   - key: 'readability-identifier-naming.TypeAliasCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.TypedefCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.TypeTemplateParameterCase' | ||||
|     value: 'CamelCase' | ||||
|   - key: 'readability-identifier-naming.UnionCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.ValueTemplateParameterCase' | ||||
|     value: 'CamelCase' | ||||
|   - key: 'readability-identifier-naming.VariableCase' | ||||
|     value: 'lower_case' | ||||
|   - key: 'readability-identifier-naming.VirtualMethodCase' | ||||
|     value: 'lower_case' | ||||
| ... | ||||
							
								
								
									
										6
									
								
								.codespellrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.codespellrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| [codespell] | ||||
| builtin = clear,rare,en-GB_to_en-US,names,informal,code | ||||
| check-filenames = | ||||
| check-hidden = | ||||
| skip = */.git,*/build,*/prefix | ||||
| quiet-level = 2 | ||||
							
								
								
									
										185
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										185
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,185 @@ | ||||
| name: Continuous Integration | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|     - master | ||||
|     - main | ||||
|     - develop | ||||
|  | ||||
|   pull_request: | ||||
|     branches: | ||||
|     - master | ||||
|     - main | ||||
|     - develop | ||||
|  | ||||
| jobs: | ||||
|   lint: | ||||
|     runs-on: ubuntu-22.04 | ||||
|  | ||||
|     steps: | ||||
|     - uses: actions/checkout@v3 | ||||
|  | ||||
|     - uses: actions/setup-python@v4 | ||||
|       with: { python-version: "3.8" } | ||||
|  | ||||
|     - name: Install codespell | ||||
|       run: pip3 install codespell | ||||
|  | ||||
|     - name: Lint | ||||
|       if: always() | ||||
|       run: cmake -D FORMAT_COMMAND=clang-format-14 -P cmake/lint.cmake | ||||
|  | ||||
|     - name: Spell check | ||||
|       if: always() | ||||
|       run: cmake -P cmake/spell.cmake | ||||
|  | ||||
|   coverage: | ||||
|     needs: [lint] | ||||
|  | ||||
|     runs-on: ubuntu-22.04 | ||||
|  | ||||
|     # To enable coverage, delete the last line from the conditional below and | ||||
|     # edit the "<name>" placeholder to your GitHub name. | ||||
|     # If you do not wish to use codecov, then simply delete this job from the | ||||
|     # workflow. | ||||
|     if: github.repository_owner == 'bensuperpc' | ||||
|       && false | ||||
|  | ||||
|     steps: | ||||
|     - uses: actions/checkout@v3 | ||||
|  | ||||
|     - name: Install LCov | ||||
|       run: sudo apt-get update -q | ||||
|         && sudo apt-get install lcov -q -y | ||||
|  | ||||
|     - name: Configure | ||||
|       run: cmake --preset=ci-coverage | ||||
|  | ||||
|     - name: Build | ||||
|       run: cmake --build build/coverage -j 2 | ||||
|  | ||||
|     - name: Test | ||||
|       working-directory: build/coverage | ||||
|       run: ctest --output-on-failure --no-tests=error -j 2 | ||||
|  | ||||
|     - name: Process coverage info | ||||
|       run: cmake --build build/coverage -t coverage | ||||
|  | ||||
|     - name: Submit to codecov.io | ||||
|       uses: codecov/codecov-action@v3 | ||||
|       with: | ||||
|         file: build/coverage/coverage.info | ||||
|  | ||||
|   sanitize: | ||||
|     needs: [lint] | ||||
|  | ||||
|     runs-on: ubuntu-22.04 | ||||
|  | ||||
|     env: { CXX: clang++-14 } | ||||
|  | ||||
|     steps: | ||||
|     - uses: actions/checkout@v3 | ||||
|  | ||||
|     - name: Configure | ||||
|       run: cmake --preset=ci-sanitize | ||||
|  | ||||
|     - name: Build | ||||
|       run: cmake --build build/sanitize -j 2 | ||||
|  | ||||
|     - name: Test | ||||
|       working-directory: build/sanitize | ||||
|       env: | ||||
|         ASAN_OPTIONS: "strict_string_checks=1:\ | ||||
|           detect_stack_use_after_return=1:\ | ||||
|           check_initialization_order=1:\ | ||||
|           strict_init_order=1:\ | ||||
|           detect_leaks=1" | ||||
|         UBSAN_OPTIONS: print_stacktrace=1 | ||||
|       run: ctest --output-on-failure --no-tests=error -j 2 | ||||
|  | ||||
|   test: | ||||
|     needs: [lint] | ||||
|  | ||||
|     strategy: | ||||
|       matrix: | ||||
|         os: [macos-12, ubuntu-22.04, windows-2022] | ||||
|  | ||||
|     runs-on: ${{ matrix.os }} | ||||
|  | ||||
|     steps: | ||||
|     - uses: actions/checkout@v3 | ||||
|  | ||||
|     - name: Install static analyzers | ||||
|       if: matrix.os == 'ubuntu-22.04' | ||||
|       run: >- | ||||
|         sudo apt-get install clang-tidy-14 cppcheck -y -q | ||||
|  | ||||
|         sudo update-alternatives --install | ||||
|         /usr/bin/clang-tidy clang-tidy | ||||
|         /usr/bin/clang-tidy-14 140 | ||||
|  | ||||
|     - name: Setup MultiToolTask | ||||
|       if: matrix.os == 'windows-2022' | ||||
|       run: | | ||||
|         Add-Content "$env:GITHUB_ENV" 'UseMultiToolTask=true' | ||||
|         Add-Content "$env:GITHUB_ENV" 'EnforceProcessCountAcrossBuilds=true' | ||||
|  | ||||
|     - name: Configure | ||||
|       shell: pwsh | ||||
|       run: cmake "--preset=ci-$("${{ matrix.os }}".split("-")[0])" | ||||
|  | ||||
|     - name: Build | ||||
|       run: cmake --build build --config Release -j 2 | ||||
|  | ||||
|     - name: Install | ||||
|       run: cmake --install build --config Release --prefix prefix | ||||
|  | ||||
|     - name: Test | ||||
|       working-directory: build | ||||
|       run: ctest --output-on-failure --no-tests=error -C Release -j 2 | ||||
|  | ||||
|   docs: | ||||
|     # Deploy docs only when builds succeed | ||||
|     needs: [sanitize, test] | ||||
|  | ||||
|     runs-on: ubuntu-22.04 | ||||
|  | ||||
|     # To enable, first you have to create an orphaned gh-pages branch: | ||||
|     # | ||||
|     #    git switch --orphan gh-pages | ||||
|     #    git commit --allow-empty -m "Initial commit" | ||||
|     #    git push -u origin gh-pages | ||||
|     # | ||||
|     # Edit the <name> placeholder below to your GitHub name, so this action | ||||
|     # runs only in your repository and no one else's fork. After these, delete | ||||
|     # this comment and the last line in the conditional below. | ||||
|     # If you do not wish to use GitHub Pages for deploying documentation, then | ||||
|     # simply delete this job similarly to the coverage one. | ||||
|     if: github.ref == 'refs/heads/master' | ||||
|       && github.event_name == 'push' | ||||
|       && github.repository_owner == 'bensuperpc' | ||||
|       && false | ||||
|  | ||||
|     steps: | ||||
|     - uses: actions/checkout@v3 | ||||
|  | ||||
|     - uses: actions/setup-python@v4 | ||||
|       with: { python-version: "3.8" } | ||||
|  | ||||
|     - name: Install m.css dependencies | ||||
|       run: pip3 install jinja2 Pygments | ||||
|  | ||||
|     - name: Install Doxygen | ||||
|       run: sudo apt-get update -q | ||||
|         && sudo apt-get install doxygen -q -y | ||||
|  | ||||
|     - name: Build docs | ||||
|       run: cmake "-DPROJECT_SOURCE_DIR=$PWD" "-DPROJECT_BINARY_DIR=$PWD/build" | ||||
|         -P cmake/docs-ci.cmake | ||||
|  | ||||
|     - name: Deploy docs | ||||
|       uses: peaceiris/actions-gh-pages@v3 | ||||
|       with: | ||||
|         github_token: ${{ secrets.GITHUB_TOKEN }} | ||||
|         publish_dir: build/docs/html | ||||
							
								
								
									
										11
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| **/.DS_Store | ||||
| .idea/ | ||||
| .vs/ | ||||
| .vscode/ | ||||
| build/ | ||||
| cmake-build-*/ | ||||
| prefix/ | ||||
| .clangd | ||||
| CMakeLists.txt.user | ||||
| compile_commands.json | ||||
| venv/* | ||||
							
								
								
									
										103
									
								
								BUILDING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								BUILDING.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| # Building with CMake | ||||
|  | ||||
| ## Build | ||||
|  | ||||
| This project doesn't require any special command-line flags to build to keep | ||||
| things simple. | ||||
|  | ||||
| ### Building with Make | ||||
|  | ||||
| You can use the Makefile provided in the root of the project to easily build multiple presets: | ||||
|      | ||||
| ```sh | ||||
| make base # Build the base preset | ||||
| ``` | ||||
|  | ||||
| ```sh | ||||
| make debug # Build the debug preset | ||||
| ``` | ||||
|  | ||||
| ### Building with CMake | ||||
|  | ||||
| Here are the steps for building in release mode with a single-configuration | ||||
| generator, like the Unix Makefiles one: | ||||
|  | ||||
| ```sh | ||||
| cmake -S . -B build -D CMAKE_BUILD_TYPE=Release | ||||
| cmake --build build | ||||
| ``` | ||||
|  | ||||
| Here are the steps for building in release mode with a multi-configuration | ||||
| generator, like the Visual Studio ones: | ||||
|  | ||||
| ```sh | ||||
| cmake -S . -B build | ||||
| cmake --build build --config Release | ||||
| ``` | ||||
|  | ||||
| ### Building with MSVC | ||||
|  | ||||
| Note that MSVC by default is not standards compliant and you need to pass some | ||||
| flags to make it behave properly. See the `flags-windows` preset in the | ||||
| [CMakePresets.json](CMakePresets.json) file for the flags and with what | ||||
| variable to provide them to CMake during configuration. | ||||
|  | ||||
| ### Building on Apple Silicon | ||||
|  | ||||
| CMake supports building on Apple Silicon properly since 3.20.1. Make sure you | ||||
| have the [latest version][1] installed. | ||||
|  | ||||
| ## Install | ||||
|  | ||||
| This project doesn't require any special command-line flags to install to keep | ||||
| things simple. As a prerequisite, the project has to be built with the above | ||||
| commands already. | ||||
|  | ||||
| The below commands require at least CMake 3.15 to run, because that is the | ||||
| version in which [Install a Project][2] was added. | ||||
|  | ||||
| Here is the command for installing the release mode artifacts with a | ||||
| single-configuration generator, like the Unix Makefiles one: | ||||
|  | ||||
| ```sh | ||||
| cmake --install build | ||||
| ``` | ||||
|  | ||||
| Here is the command for installing the release mode artifacts with a | ||||
| multi-configuration generator, like the Visual Studio ones: | ||||
|  | ||||
| ```sh | ||||
| cmake --install build --config Release | ||||
| ``` | ||||
|  | ||||
| ### CMake package | ||||
|  | ||||
| This project exports a CMake package to be used with the [`find_package`][3] | ||||
| command of CMake: | ||||
|  | ||||
| * Package name: `astar` | ||||
| * Target name: `astar::astar` | ||||
|  | ||||
| Example usage: | ||||
|  | ||||
| ```cmake | ||||
| find_package(astar REQUIRED) | ||||
| # Declare the imported target as a build requirement using PRIVATE, where | ||||
| # project_target is a target created in the consuming project | ||||
| target_link_libraries( | ||||
|     project_target PRIVATE | ||||
|     astar::astar | ||||
| ) | ||||
| ``` | ||||
|  | ||||
| ### Note to packagers | ||||
|  | ||||
| The `CMAKE_INSTALL_INCLUDEDIR` is set to a path other than just `include` if | ||||
| the project is configured as a top level project to avoid indirectly including | ||||
| other libraries when installed to a common prefix. Please review the | ||||
| [install-rules.cmake](cmake/install-rules.cmake) file for the full set of | ||||
| install rules. | ||||
|  | ||||
| [1]: https://cmake.org/download/ | ||||
| [2]: https://cmake.org/cmake/help/latest/manual/cmake.1.html#install-a-project | ||||
| [3]: https://cmake.org/cmake/help/latest/command/find_package.html | ||||
							
								
								
									
										60
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
|  | ||||
| include(cmake/prelude.cmake) | ||||
|  | ||||
| project( | ||||
|     astar | ||||
|     VERSION 0.1.0 | ||||
|     DESCRIPTION "astar" | ||||
|     HOMEPAGE_URL "bensuperpc.org" | ||||
|     LANGUAGES NONE | ||||
| ) | ||||
|  | ||||
| include(cmake/project-is-top-level.cmake) | ||||
| include(cmake/variables.cmake) | ||||
|  | ||||
| # ---- Declare library ---- | ||||
|  | ||||
| add_library(astar_astar INTERFACE) | ||||
| add_library(astar::astar ALIAS astar_astar) | ||||
|  | ||||
| set_property( | ||||
|     TARGET astar_astar PROPERTY | ||||
|     EXPORT_NAME astar | ||||
| ) | ||||
|  | ||||
| target_include_directories( | ||||
|     astar_astar ${warning_guard} | ||||
|     INTERFACE | ||||
|     "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" | ||||
| ) | ||||
|  | ||||
| target_compile_features(astar_astar INTERFACE cxx_std_20) | ||||
|  | ||||
| # ---- Install rules ---- | ||||
|  | ||||
| if(NOT CMAKE_SKIP_INSTALL_RULES) | ||||
|   include(cmake/install-rules.cmake) | ||||
| endif() | ||||
|  | ||||
| # ---- Examples ---- | ||||
|  | ||||
| if(PROJECT_IS_TOP_LEVEL) | ||||
|   option(BUILD_EXAMPLES "Build examples tree." "${astar_DEVELOPER_MODE}") | ||||
|   if(BUILD_EXAMPLES) | ||||
|     add_subdirectory(example) | ||||
|   endif() | ||||
| endif() | ||||
|  | ||||
| # ---- Developer mode ---- | ||||
|  | ||||
| if(NOT astar_DEVELOPER_MODE) | ||||
|   return() | ||||
| elseif(NOT PROJECT_IS_TOP_LEVEL) | ||||
|   message( | ||||
|       AUTHOR_WARNING | ||||
|       "Developer mode is intended for developers of astar" | ||||
|   ) | ||||
| endif() | ||||
|  | ||||
| include(cmake/dev-mode.cmake) | ||||
							
								
								
									
										247
									
								
								CMakePresets.json
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										247
									
								
								CMakePresets.json
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| { | ||||
|   "version": 2, | ||||
|   "cmakeMinimumRequired": { | ||||
|     "major": 3, | ||||
|     "minor": 14, | ||||
|     "patch": 0 | ||||
|   }, | ||||
|   "configurePresets": [ | ||||
|     { | ||||
|       "name": "cmake-pedantic", | ||||
|       "hidden": true, | ||||
|       "warnings": { | ||||
|         "dev": true, | ||||
|         "deprecated": true, | ||||
|         "uninitialized": true, | ||||
|         "unusedCli": true, | ||||
|         "systemVars": false | ||||
|       }, | ||||
|       "errors": { | ||||
|         "dev": false, | ||||
|         "deprecated": false | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "dev-mode", | ||||
|       "hidden": true, | ||||
|       "inherits": "cmake-pedantic", | ||||
|       "cacheVariables": { | ||||
|         "astar_DEVELOPER_MODE": "ON" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "cppcheck", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CXX_CPPCHECK": "cppcheck;--inline-suppr", | ||||
|         "CMAKE_C_CPPCHECK": "cppcheck;--inline-suppr" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "clang-tidy", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CXX_CLANG_TIDY": "clang-tidy;--header-filter=^${sourceDir}/", | ||||
|         "CMAKE_C_CLANG_TIDY": "clang-tidy;--header-filter=^${sourceDir}/" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-std", | ||||
|       "description": "This preset makes sure the project actually builds with at least the specified standard", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CXX_EXTENSIONS": "ON", | ||||
|         "CMAKE_CXX_STANDARD": "20", | ||||
|         "CMAKE_CXX_STANDARD_REQUIRED": "ON", | ||||
|         "CMAKE_C_EXTENSIONS": "ON", | ||||
|         "CMAKE_C_STANDARD": "17", | ||||
|         "CMAKE_C_STANDARD_REQUIRED": "ON" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "flags-gcc-clang", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CXX_FLAGS": "-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -pipe -fstack-protector-strong -fstack-clash-protection -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wdouble-promotion -Wimplicit-fallthrough -Wextra-semi -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast -Wformat-security", | ||||
|         "CMAKE_C_FLAGS": "-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -pipe -fstack-protector-strong -fstack-clash-protection -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wdouble-promotion -Wformat-security", | ||||
|         "CMAKE_EXE_LINKER_FLAGS": "-Wl,--allow-shlib-undefined,--as-needed,-z,noexecstack,-z,relro,-z,now", | ||||
|         "CMAKE_SHARED_LINKER_FLAGS": "-Wl,--allow-shlib-undefined,--as-needed,-z,noexecstack,-z,relro,-z,now" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "flags-appleclang", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CXX_FLAGS": "-pipe -fstack-protector-strong -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wdouble-promotion -Wimplicit-fallthrough -Wextra-semi -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast", | ||||
|         "CMAKE_C_FLAGS": "-pipe -fstack-protector-strong -Wall -Wextra -Wpedantic" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "flags-msvc", | ||||
|       "description": "Note that all the flags after /W4 are required for MSVC to conform to the language standard", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CXX_FLAGS": "/sdl /guard:cf /utf-8 /diagnostics:caret /w14165 /w44242 /w44254 /w44263 /w34265 /w34287 /w44296 /w44365 /w44388 /w44464 /w14545 /w14546 /w14547 /w14549 /w14555 /w34619 /w34640 /w24826 /w14905 /w14906 /w14928 /w45038 /W4 /permissive- /volatile:iso /Zc:inline /Zc:preprocessor /Zc:enumTypes /Zc:lambda /Zc:__cplusplus /Zc:externConstexpr /Zc:throwingNew /EHsc", | ||||
|         "CMAKE_EXE_LINKER_FLAGS": "/machine:x64 /guard:cf" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "flags-cuda", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CUDA_FLAGS": "--default-stream per-thread -Xfatbin=-compress-all -arch=all-major -Xcompiler=-Wall,-Wextra,-Wconversion,-Wsign-conversion,-Wcast-qual,-Wundef,-Wshadow,-Wunused,-Wnull-dereference,-Wdouble-promotion,-Wimplicit-fallthrough,-Wextra-semi,-Woverloaded-virtual,-Wnon-virtual-dtor,-Wformat-security", | ||||
|         "CMAKE_CUDA_ARCHITECTURES": "50;52;53;60;61;62;70;72;75;80;86;87;89;90", | ||||
|         "CUDA_PROPAGATE_HOST_FLAGS": "OFF", | ||||
|         "CMAKE_CUDA_SEPARABLE_COMPILATION": "ON" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "flags-debugger", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CXX_FLAGS": "-O0 -g3 -ggdb3 -Wall -Wextra -Wpedantic -pg", | ||||
|         "CMAKE_C_FLAGS": "-O0 -g3 -ggdb3 -Wall -Wextra -Wpedantic -pg" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-cuda", | ||||
|       "description": "This preset makes sure the project actually builds with at least the specified standard", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_CUDA_STANDARD": "17", | ||||
|         "CMAKE_CUDA_STANDARD_REQUIRED": "ON", | ||||
|         "CMAKE_CUDA_EXTENSIONS": "OFF" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-linux", | ||||
|       "generator": "Unix Makefiles", | ||||
|       "hidden": true, | ||||
|       "inherits": ["flags-gcc-clang", "ci-std", "ci-cuda", "flags-cuda"], | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Release" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-darwin", | ||||
|       "generator": "Unix Makefiles", | ||||
|       "hidden": true, | ||||
|       "inherits": ["flags-appleclang", "ci-std"], | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Release" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-base", | ||||
|       "generator": "Unix Makefiles", | ||||
|       "hidden": true, | ||||
|       "inherits": ["ci-std", "flags-gcc-clang", "dev-mode", "flags-cuda", "ci-cuda"] | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-win64", | ||||
|       "inherits": ["flags-msvc", "ci-std"], | ||||
|       "generator": "Visual Studio 17 2022", | ||||
|       "architecture": "x64", | ||||
|       "hidden": true | ||||
|     }, | ||||
|     { | ||||
|       "name": "coverage-linux", | ||||
|       "binaryDir": "${sourceDir}/build/coverage", | ||||
|       "inherits": "ci-linux", | ||||
|       "hidden": true, | ||||
|       "cacheVariables": { | ||||
|         "ENABLE_COVERAGE": "ON", | ||||
|         "CMAKE_BUILD_TYPE": "Coverage", | ||||
|         "CMAKE_CXX_FLAGS_COVERAGE": "-O0 -g3 --coverage -fkeep-inline-functions -fkeep-static-functions", | ||||
|         "CMAKE_EXE_LINKER_FLAGS_COVERAGE": "--coverage", | ||||
|         "CMAKE_SHARED_LINKER_FLAGS_COVERAGE": "--coverage" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-coverage", | ||||
|       "inherits": ["coverage-linux", "dev-mode"], | ||||
|       "cacheVariables": { | ||||
|         "COVERAGE_HTML_COMMAND": "" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-sanitize", | ||||
|       "binaryDir": "${sourceDir}/build/sanitize", | ||||
|       "inherits": ["ci-linux", "dev-mode"], | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Sanitize", | ||||
|         "CMAKE_CXX_FLAGS_SANITIZE": "-Og -U_FORTIFY_SOURCE -g3 -fsanitize=address,undefined,leak -fno-omit-frame-pointer -fno-common", | ||||
|         "CMAKE_C_FLAGS_SANITIZE": "-Og -U_FORTIFY_SOURCE -g3" | ||||
|       }, | ||||
|       "environment": { | ||||
|         "ASAN_OPTIONS": "strict_string_checks=1 detect_stack_use_after_return=1 check_initialization_order=1 strict_init_order=1 detect_leaks=1", | ||||
|         "UBSAN_OPTIONS": "print_stacktrace=1" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-build", | ||||
|       "binaryDir": "${sourceDir}/build", | ||||
|       "hidden": true | ||||
|     }, | ||||
|     { | ||||
|       "name": "base", | ||||
|       "binaryDir": "${sourceDir}/build/base", | ||||
|       "inherits": ["ci-base"], | ||||
|       "hidden": false, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Release" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "base-clang", | ||||
|       "binaryDir": "${sourceDir}/build/base-clang", | ||||
|       "inherits": ["ci-base"], | ||||
|       "hidden": false, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Release", | ||||
|         "CMAKE_C_COMPILER": "clang", | ||||
|         "CMAKE_CXX_COMPILER": "clang++" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "gprof", | ||||
|       "generator": "Unix Makefiles", | ||||
|       "binaryDir": "${sourceDir}/build/gprof", | ||||
|       "inherits": ["ci-std", "flags-debugger", "dev-mode"], | ||||
|       "hidden": false, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Release" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "debugger", | ||||
|       "generator": "Unix Makefiles", | ||||
|       "binaryDir": "${sourceDir}/build/debugger", | ||||
|       "inherits": ["ci-std", "flags-debugger", "dev-mode"], | ||||
|       "hidden": false, | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Debug" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "dev-common", | ||||
|       "hidden": true, | ||||
|       "inherits": ["dev-mode", "clang-tidy", "cppcheck"], | ||||
|       "cacheVariables": { | ||||
|         "BUILD_MCSS_DOCS": "ON" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-macos", | ||||
|       "inherits": ["ci-build", "ci-darwin", "dev-mode"] | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-ubuntu", | ||||
|       "inherits": ["ci-build", "ci-linux", "dev-common"] | ||||
|     }, | ||||
|     { | ||||
|       "name": "ci-windows", | ||||
|       "inherits": ["ci-build", "ci-win64", "dev-mode"] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										69
									
								
								CMakeUserPresets.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								CMakeUserPresets.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| { | ||||
|   "version": 2, | ||||
|   "cmakeMinimumRequired": { | ||||
|     "major": 3, | ||||
|     "minor": 14, | ||||
|     "patch": 0 | ||||
|   }, | ||||
|   "configurePresets": [ | ||||
|     { | ||||
|       "name": "dev-linux", | ||||
|       "binaryDir": "${sourceDir}/build/dev-linux", | ||||
|       "inherits": ["dev-common", "ci-linux"], | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Debug", | ||||
|         "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "dev-darwin", | ||||
|       "binaryDir": "${sourceDir}/build/dev-darwin", | ||||
|       "inherits": ["dev-common", "ci-darwin"], | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Debug", | ||||
|         "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "dev-win64", | ||||
|       "binaryDir": "${sourceDir}/build/dev-win64", | ||||
|       "inherits": ["dev-common", "ci-win64"], | ||||
|       "environment": { | ||||
|         "UseMultiToolTask": "true", | ||||
|         "EnforceProcessCountAcrossBuilds": "true" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "name": "dev", | ||||
|       "binaryDir": "${sourceDir}/build/dev", | ||||
|       "inherits": "dev-linux" | ||||
|     }, | ||||
|     { | ||||
|       "name": "dev-coverage", | ||||
|       "binaryDir": "${sourceDir}/build/coverage", | ||||
|       "inherits": ["dev-mode", "coverage-linux"] | ||||
|     } | ||||
|   ], | ||||
|   "buildPresets": [ | ||||
|     { | ||||
|       "name": "dev", | ||||
|       "configurePreset": "dev", | ||||
|       "configuration": "Debug", | ||||
|       "jobs": 16 | ||||
|     } | ||||
|   ], | ||||
|   "testPresets": [ | ||||
|     { | ||||
|       "name": "dev", | ||||
|       "configurePreset": "dev", | ||||
|       "configuration": "Debug", | ||||
|       "output": { | ||||
|         "outputOnFailure": true | ||||
|       }, | ||||
|       "execution": { | ||||
|         "jobs": 16, | ||||
|         "noTestsAction": "error" | ||||
|       } | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										5
									
								
								CODE_OF_CONDUCT.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								CODE_OF_CONDUCT.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| # Code of Conduct | ||||
|  | ||||
| * You will be judged by your contributions first, and your sense of humor | ||||
|   second. | ||||
| * Nobody owes you anything. | ||||
							
								
								
									
										19
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| # Contributing | ||||
|  | ||||
| <!-- | ||||
|     Short overview, rules, general guidelines, notes about pull requests and | ||||
|     style should go here. | ||||
| --> | ||||
|  | ||||
| ## Code of Conduct | ||||
|  | ||||
| Please see the [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) document. | ||||
|  | ||||
| ## Getting started | ||||
|  | ||||
| Helpful notes for developers can be found in the [`HACKING.md`](HACKING.md) | ||||
| document. | ||||
|  | ||||
| In addition to he above, if you use the presets file as instructed, then you | ||||
| should NOT check it into source control, just as the CMake documentation | ||||
| suggests. | ||||
							
								
								
									
										149
									
								
								HACKING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								HACKING.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| # Hacking | ||||
|  | ||||
| Here is some wisdom to help you build and test this project as a developer and | ||||
| potential contributor. | ||||
|  | ||||
| If you plan to contribute, please read the [CONTRIBUTING](CONTRIBUTING.md) | ||||
| guide. | ||||
|  | ||||
| ## Developer mode | ||||
|  | ||||
| Build system targets that are only useful for developers of this project are | ||||
| hidden if the `astar_DEVELOPER_MODE` option is disabled. Enabling this | ||||
| option makes tests and other developer targets and options available. Not | ||||
| enabling this option means that you are a consumer of this project and thus you | ||||
| have no need for these targets and options. | ||||
|  | ||||
| Developer mode is always set to on in CI workflows. | ||||
|  | ||||
| ### Presets | ||||
|  | ||||
| This project makes use of [presets][1] to simplify the process of configuring | ||||
| the project. As a developer, you are recommended to always have the [latest | ||||
| CMake version][2] installed to make use of the latest Quality-of-Life | ||||
| additions. | ||||
|  | ||||
| You have a few options to pass `astar_DEVELOPER_MODE` to the configure | ||||
| command, but this project prefers to use presets. | ||||
|  | ||||
| As a developer, you should create a `CMakeUserPresets.json` file at the root of | ||||
| the project: | ||||
|  | ||||
| ```json | ||||
| { | ||||
|   "version": 2, | ||||
|   "cmakeMinimumRequired": { | ||||
|     "major": 3, | ||||
|     "minor": 14, | ||||
|     "patch": 0 | ||||
|   }, | ||||
|   "configurePresets": [ | ||||
|     { | ||||
|       "name": "dev", | ||||
|       "binaryDir": "${sourceDir}/build/dev", | ||||
|       "inherits": ["dev-mode", "ci-<os>"], | ||||
|       "cacheVariables": { | ||||
|         "CMAKE_BUILD_TYPE": "Debug" | ||||
|       } | ||||
|     } | ||||
|   ], | ||||
|   "buildPresets": [ | ||||
|     { | ||||
|       "name": "dev", | ||||
|       "configurePreset": "dev", | ||||
|       "configuration": "Debug" | ||||
|     } | ||||
|   ], | ||||
|   "testPresets": [ | ||||
|     { | ||||
|       "name": "dev", | ||||
|       "configurePreset": "dev", | ||||
|       "configuration": "Debug", | ||||
|       "output": { | ||||
|         "outputOnFailure": true | ||||
|       } | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| ``` | ||||
|  | ||||
| You should replace `<os>` in your newly created presets file with the name of | ||||
| the operating system you have, which may be `win64`, `linux` or `darwin`. You | ||||
| can see what these correspond to in the | ||||
| [`CMakePresets.json`](CMakePresets.json) file. | ||||
|  | ||||
| `CMakeUserPresets.json` is also the perfect place in which you can put all | ||||
| sorts of things that you would otherwise want to pass to the configure command | ||||
| in the terminal. | ||||
|  | ||||
| > **Note** | ||||
| > Some editors are pretty greedy with how they open projects with presets. | ||||
| > Some just randomly pick a preset and start configuring without your consent, | ||||
| > which can be confusing. Make sure that your editor configures when you | ||||
| > actually want it to, for example in CLion you have to make sure only the | ||||
| > `dev-dev preset` has `Enable profile` ticked in | ||||
| > `File > Settings... > Build, Execution, Deployment > CMake` and in Visual | ||||
| > Studio you have to set the option `Never run configure step automatically` | ||||
| > in `Tools > Options > CMake` **prior to opening the project**, after which | ||||
| > you can manually configure using `Project > Configure Cache`. | ||||
|  | ||||
| ### Configure, build and test | ||||
|  | ||||
| If you followed the above instructions, then you can configure, build and test | ||||
| the project respectively with the following commands from the project root on | ||||
| any operating system with any build system: | ||||
|  | ||||
| ```sh | ||||
| cmake --preset=dev | ||||
| cmake --build --preset=dev | ||||
| ctest --preset=dev | ||||
| ``` | ||||
|  | ||||
| If you are using a compatible editor (e.g. VSCode) or IDE (e.g. CLion, VS), you | ||||
| will also be able to select the above created user presets for automatic | ||||
| integration. | ||||
|  | ||||
| Please note that both the build and test commands accept a `-j` flag to specify | ||||
| the number of jobs to use, which should ideally be specified to the number of | ||||
| threads your CPU has. You may also want to add that to your preset using the | ||||
| `jobs` property, see the [presets documentation][1] for more details. | ||||
|  | ||||
| ### Developer mode targets | ||||
|  | ||||
| These are targets you may invoke using the build command from above, with an | ||||
| additional `-t <target>` flag: | ||||
|  | ||||
| #### `coverage` | ||||
|  | ||||
| Available if `ENABLE_COVERAGE` is enabled. This target processes the output of | ||||
| the previously run tests when built with coverage configuration. The commands | ||||
| this target runs can be found in the `COVERAGE_TRACE_COMMAND` and | ||||
| `COVERAGE_HTML_COMMAND` cache variables. The trace command produces an info | ||||
| file by default, which can be submitted to services with CI integration. The | ||||
| HTML command uses the trace command's output to generate an HTML document to | ||||
| `<binary-dir>/coverage_html` by default. | ||||
|  | ||||
| #### `docs` | ||||
|  | ||||
| Available if `BUILD_MCSS_DOCS` is enabled. Builds to documentation using | ||||
| Doxygen and m.css. The output will go to `<binary-dir>/docs` by default | ||||
| (customizable using `DOXYGEN_OUTPUT_DIRECTORY`). | ||||
|  | ||||
| #### `format-check` and `format-fix` | ||||
|  | ||||
| These targets run the clang-format tool on the codebase to check errors and to | ||||
| fix them respectively. Customization available using the `FORMAT_PATTERNS` and | ||||
| `FORMAT_COMMAND` cache variables. | ||||
|  | ||||
| #### `run-examples` | ||||
|  | ||||
| Runs all the examples created by the `add_example` command. | ||||
|  | ||||
| #### `spell-check` and `spell-fix` | ||||
|  | ||||
| These targets run the codespell tool on the codebase to check errors and to fix | ||||
| them respectively. Customization available using the `SPELL_COMMAND` cache | ||||
| variable. | ||||
|  | ||||
| [1]: https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html | ||||
| [2]: https://cmake.org/download/ | ||||
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| MIT License | ||||
|  | ||||
| Copyright (c) 2024 Bensuperpc | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
							
								
								
									
										162
									
								
								Makefile
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										162
									
								
								Makefile
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| #////////////////////////////////////////////////////////////// | ||||
| #//   ____                                                   // | ||||
| #//  | __ )  ___ _ __  ___ _   _ _ __   ___ _ __ _ __   ___  // | ||||
| #//  |  _ \ / _ \ '_ \/ __| | | | '_ \ / _ \ '__| '_ \ / __| // | ||||
| #//  | |_) |  __/ | | \__ \ |_| | |_) |  __/ |  | |_) | (__  // | ||||
| #//  |____/ \___|_| |_|___/\__,_| .__/ \___|_|  | .__/ \___| // | ||||
| #//                             |_|             |_|          // | ||||
| #////////////////////////////////////////////////////////////// | ||||
| #//                                                          // | ||||
| #//  sandbox, 2023                               // | ||||
| #//  Created: 04, June, 2021                                 // | ||||
| #//  Modified: 18, November, 2023                            // | ||||
| #//  file: -                                                 // | ||||
| #//  -                                                       // | ||||
| #//  Source:                                                 // | ||||
| #//  OS: ALL                                                 // | ||||
| #//  CPU: ALL                                                // | ||||
| #//                                                          // | ||||
| #////////////////////////////////////////////////////////////// | ||||
|  | ||||
| PROJECT_NAME := world_of_blocks | ||||
|  | ||||
| PARALLEL := 1 | ||||
|  | ||||
| GENERATOR := Ninja | ||||
| PROJECT_ROOT := . | ||||
|  | ||||
| CTEST_TIMEOUT := 1500 | ||||
| CTEST_OPTIONS := --output-on-failure --timeout $(CTEST_TIMEOUT) --parallel $(PARALLEL) --verbose | ||||
|  | ||||
| # LANG := en | ||||
| # LANG=$(LANG) | ||||
| # -Werror=float-equal | ||||
|  | ||||
| .PHONY: build | ||||
| build: base | ||||
|  | ||||
| .PHONY: all | ||||
| all: release debug minsizerel coverage relwithdebinfo minsizerel relwithdebinfo release-clang \ | ||||
| 	debug-clang base base-clang sanitize sanitize-clang gprof $(DOCKCROSS_IMAGE) docker valgrind gdb | ||||
|  | ||||
| .PHONY: base | ||||
| base: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=$@ | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: base-clang | ||||
| base-clang: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=$@ | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: release | ||||
| release: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=base -DCMAKE_BUILD_TYPE=Release | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: release-clang | ||||
| release-clang: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=base -DCMAKE_BUILD_TYPE=Release \ | ||||
| 	-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: debug | ||||
| debug: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=dev -DCMAKE_BUILD_TYPE=Debug | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: debug-clang | ||||
| debug-clang: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=dev -DCMAKE_BUILD_TYPE=Debug \ | ||||
| 	-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: coverage | ||||
| coverage: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=dev-coverage -DCMAKE_BUILD_TYPE=Coverage | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
| 	cmake --build build/$@ --target $@ | ||||
|  | ||||
| .PHONY: sanitize | ||||
| sanitize: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=ci-sanitize | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| sanitize-clang: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=ci-sanitize \ | ||||
| 	-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: minsizerel | ||||
| minsizerel: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=dev -DCMAKE_BUILD_TYPE=MinSizeRel | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: relwithdebinfo | ||||
| relwithdebinfo: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=dev -DCMAKE_BUILD_TYPE=RelWithDebInfo | ||||
| 	cmake --build build/$@ | ||||
| 	ctest $(CTEST_OPTIONS) --test-dir build/$@ | ||||
|  | ||||
| .PHONY: gprof | ||||
| gprof: | ||||
| 	cmake --preset=$@ -G $(GENERATOR) | ||||
| 	cmake --build build/$@ | ||||
| 	@echo "Run executable and after gprof <exe> gmon.out | less" | ||||
|  | ||||
| .PHONY: perf | ||||
| perf: | ||||
| 	cmake --preset=base -G $(GENERATOR) | ||||
| 	cmake --build build/base | ||||
| 	perf record --all-user -e branch-misses ./build/base/bin/$(PROJECT_NAME) | ||||
|  | ||||
| .PHONY: graph | ||||
| graph: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --graphviz=build/$@/graph.dot | ||||
| 	cmake --build build/base | ||||
| 	dot -Tpng -o build/$@/graph.png build/$@/graph.dot | ||||
|  | ||||
| .PHONY: valgrind | ||||
| valgrind: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=debugger | ||||
| 	cmake --build build/$@ | ||||
| 	valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=build/$@/valgrind.log ./build/$@/bin/$(PROJECT_NAME) | ||||
|  | ||||
| .PHONY: gdb | ||||
| gdb: | ||||
| 	cmake -B build/$@ -S $(PROJECT_ROOT) -G $(GENERATOR) --preset=debugger | ||||
| 	cmake --build build/$@ | ||||
| 	gdb build/$@/bin/$(PROJECT_NAME) | ||||
|  | ||||
| .PHONY: lint | ||||
| lint: | ||||
| 	cmake -D FORMAT_COMMAND=clang-format -P cmake/lint.cmake | ||||
| 	cmake -P cmake/spell.cmake | ||||
|  | ||||
| .PHONY: format | ||||
| format: | ||||
| 	time find . -regex '.*\.\(cpp\|cxx\|hpp\|hxx\|c\|h\|cu\|cuh\|cuhpp\|tpp\)' -not -path '*/build/*' -not -path '.git/*' | parallel clang-format -style=file -i {} \; | ||||
|  | ||||
| .PHONY: cloc | ||||
| cloc: | ||||
| 	cloc --fullpath --not-match-d="(build|.git)" --not-match-f="(.git)" . | ||||
|  | ||||
| .PHONY: update | ||||
| update: | ||||
| # 	git submodule update --recursive --remote --force --rebase | ||||
| 	git submodule update --init --recursive | ||||
| 	git pull --recurse-submodules --all --progress | ||||
|  | ||||
| .PHONY: clear | ||||
| clear: | ||||
| 	rm -rf build/* | ||||
							
								
								
									
										207
									
								
								README.md
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										207
									
								
								README.md
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| # astar | ||||
|  | ||||
| Fast and easy to use header only 2D astar algorithm library in C++20. | ||||
|  | ||||
| I made it for learning how the astar algorithm works, try to make the fastest, tested and configurable as possible for my needs (future games and works). | ||||
|  | ||||
| # How does it work | ||||
|  | ||||
| It is an [astar algorithm](https://en.wikipedia.org/wiki/A*_search_algorithm), the main idea is to find the shortest path between two points in a grid/map. | ||||
|  | ||||
| # Screenshots | ||||
|  | ||||
|  | ||||
|  | ||||
| # Features | ||||
|  | ||||
| * [x] Header-only library C++20 | ||||
| * [x] Support 2D map | ||||
| * [ ] Support 3D map | ||||
| * [x] Configurable heuristic function and movement cost | ||||
| * [x] Configurable (diagonal and more) movement | ||||
| * [x] Debug mode in template argument and lambda function | ||||
| * [x] Support direct access and not access to the map | ||||
| * [x] Unit tests and benchmarks | ||||
|  | ||||
| # How to use it | ||||
|  | ||||
| This project is a header-only library and easy to use, just copy the `include/astar` folder in your project and include the `astar/astar.hpp` header or via CMake FetchContent_Declare. | ||||
|  | ||||
| Now you can use the `Astar::Astar` class to find the shortest path between two points in a grid. | ||||
|  | ||||
| ```cpp | ||||
| #include <astar/astar.hpp> | ||||
| #include <iostream> | ||||
|  | ||||
| auto main() -> int { | ||||
|     // Create the template class with optional a type (e.g. uint32_t) and a boolean  | ||||
|     // if you want enable debug mode (AStar::AStar<uint32_t, true>) | ||||
|     AStar::AStar pathFinder; | ||||
|  | ||||
|     // Define the map size (width, height) | ||||
|     pathFinder.setWorldSize({10, 10}); | ||||
|  | ||||
|     // Set the heuristic function (manhattan, euclidean, octagonal etc...), it is optional, default is euclidean | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::manhattan); | ||||
|  | ||||
|     // if you want to enable diagonal movement, it is optional, default is false | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     // Add a obstacle point (5, 5) and (5, 6) | ||||
|     pathFinder.addObstacle({5, 5}); | ||||
|     pathFinder.addObstacle({5, 6}); | ||||
|  | ||||
|     // Find the path from (0, 0) to (9, 9) | ||||
|     auto path = pathFinder.findPath({0, 0}, {9, 9}); | ||||
|  | ||||
|     // Print the path | ||||
|     for (auto& p : path) { | ||||
|         std::cout << p.x << " " << p.y << std::endl; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### Alternative version (direct access to the map) | ||||
|  | ||||
| You can use the alternative version of the library if you want astar have direct access to the map, this version is faster than the non-direct access version. | ||||
|  | ||||
| ```cpp | ||||
| #include <astar/astar.hpp> | ||||
| #include <iostream> | ||||
|  | ||||
| auto main() -> int { | ||||
|     // Create the template class with optional a type (e.g. uint32_t) and a boolean | ||||
|     // if you want enable debug mode (AStar::AStar<uint32_t, true>) | ||||
|     AStar::AStarFast pathFinder; | ||||
|  | ||||
|     // Set the heuristic function (manhattan, euclidean, octagonal etc...), it is optional, default is euclidean | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::manhattan); | ||||
|  | ||||
|     // if you want to enable diagonal movement, it is optional, default is false | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     // Create world 9x9 filled with 0 | ||||
|     std::vector<uint32_t> world(9 * 9, 0); | ||||
|  | ||||
|     // set lambda function to check if is an obstacle (value == 1) | ||||
|     auto isObstacle = [](uint32_t value) -> bool { return value == 1; }; | ||||
|     pathFinder.setObstacle(isObstacle); | ||||
|  | ||||
|     // Add a obstacle point (5, 5) and (5, 6) | ||||
|     world[5 + 5 * 9] = 1; | ||||
|     world[5 + 6 * 9] = 1; | ||||
|  | ||||
|     // Find the path from (0, 0) to (9, 9), it it equal to 0, then the path is not found | ||||
|     // This version of findPath() is faster due direct access to the world | ||||
|     auto path = pathFinder.findPath({0, 0}, {9, 9}, world, {9, 9}); | ||||
|  | ||||
|     // Print the path | ||||
|     for (auto& p : path) { | ||||
|         std::cout << p.x << " " << p.y << std::endl; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### Debug mode | ||||
|  | ||||
| You can enable the debug mode to call a lambda function when new node is visiting by the algorithm and when new node is added to the open list. | ||||
|  | ||||
| ```cpp | ||||
| #include <iostream> | ||||
|  | ||||
| #include <astar/astar.hpp> | ||||
|  | ||||
| auto main() -> int { | ||||
|     // Enable debug mode with template argument, this helps avoid performance issues on non-debug classes | ||||
|     AStar::AStar<uint32_t, true> pathFinder; | ||||
|  | ||||
|     // Set lambda function to debug current node | ||||
|     std::function<void(const AStar::Node<uint32_t>* node)> debugCurrentNode = [](const AStar::Node<uint32_t>* node) { | ||||
|         std::cout << "Current node: " << node->pos.x << ", " << node->pos.y << std::endl; | ||||
|     }; | ||||
|     pathFinder.setDebugCurrentNode(debugCurrentNode); | ||||
|  | ||||
|     // Set lambda function to debug open node | ||||
|     std::function<void(const AStar::Node<uint32_t>* node)> debugOpenNode = [](const AStar::Node<uint32_t>* node) { | ||||
|         std::cout << "Add to open list: " << node->pos.x << ", " << node->pos.y << std::endl; | ||||
|     }; | ||||
|     pathFinder.setDebugOpenNode(debugOpenNode); | ||||
|  | ||||
|     // Define the map size (width, height) | ||||
|     pathFinder.setWorldSize({10, 10}); | ||||
|  | ||||
|     // Set the heuristic function (manhattan, euclidean, octagonal etc...), it is optional, default is euclidean | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::manhattan); | ||||
|  | ||||
|     // if you want to enable diagonal movement, it is optional, default is false | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     // Add a obstacle point (5, 5) and (5, 6) | ||||
|     pathFinder.addObstacle({5, 5}); | ||||
|     pathFinder.addObstacle({5, 6}); | ||||
|  | ||||
|     // Find the path from (0, 0) to (9, 9) | ||||
|     auto path = pathFinder.findPath({0, 0}, {9, 9}); | ||||
|  | ||||
|     // Print the path | ||||
|     for (auto& p : path) { | ||||
|         std::cout << p.x << " " << p.y << std::endl; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| # Building and installing | ||||
|  | ||||
| See the [BUILDING](BUILDING.md) document. | ||||
|  | ||||
| # Contributing | ||||
|  | ||||
| See the [CONTRIBUTING](CONTRIBUTING.md) document. | ||||
|  | ||||
| # Sources, references and ideas | ||||
|  | ||||
| You can find here the sources, references, libs and ideas that I have used to make this library. | ||||
|  | ||||
| ## Astar | ||||
|  | ||||
| Sources and references that I have used to make this library. | ||||
|  | ||||
| * [Wikipedia A* search algorithm](https://en.wikipedia.org/wiki/A*_search_algorithm) | ||||
| * [A* Pathfinding](https://www.youtube.com/watch?v=-L-WgKMFuhE) | ||||
| * [AStar](https://github.com/yatima1460/AStar) | ||||
| * [Introduction to A*](https://theory.stanford.edu/~amitp/GameProgramming/AStarComparison.html) | ||||
| * [Easy A* (star) Pathfinding](https://medium.com/@nicholas.w.swift/easy-a-star-pathfinding-7e6689c7f7b2) | ||||
| * [a-star](https://www.ce.unipr.it/people/medici/a-star.html)$ | ||||
| * [A* Search Algorithm](https://yuminlee2.medium.com/a-search-algorithm-42c1a13fcf9f) | ||||
|  | ||||
| ## Bench others astar implementations | ||||
|  | ||||
| The list of others astar implementations that I have benchmarked to compare the performance of my implementation. | ||||
|  | ||||
| * [A* Search Algorithm](https://www.geeksforgeeks.org/a-search-algorithm/) | ||||
| * [a-star](https://github.com/daancode/a-star) | ||||
| * [A-Star-Search-Algorithm](https://github.com/lychengrex/A-Star-Search-Algorithm) | ||||
| * [Pathfinding](https://github.com/Gerard097/Pathfinding) | ||||
|  | ||||
| ## Libraries | ||||
|  | ||||
| Libraries used in this project. | ||||
|  | ||||
| * [cmake-init](https://github.com/friendlyanon/cmake-init) | ||||
| * [google test](https://github.com/google/googletest) | ||||
| * [google benchmark](https://github.com/google/benchmark) | ||||
| * [Raylib](https://github.com/raysan5/raylib) | ||||
|  | ||||
| # Others | ||||
|  | ||||
| * [Benchmark visualization](https://int-i.github.io/python/2021-11-07/matplotlib-google-benchmark-visualization/) | ||||
|  | ||||
| # Licensing | ||||
|  | ||||
| [LICENSE](LICENSE) | ||||
							
								
								
									
										33
									
								
								cmake/coverage.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								cmake/coverage.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| # ---- Variables ---- | ||||
|  | ||||
| # We use variables separate from what CTest uses, because those have | ||||
| # customization issues | ||||
| set( | ||||
|     COVERAGE_TRACE_COMMAND | ||||
|     lcov -c -q | ||||
|     -o "${PROJECT_BINARY_DIR}/coverage.info" | ||||
|     -d "${PROJECT_BINARY_DIR}" | ||||
|     --include "${PROJECT_SOURCE_DIR}/*" | ||||
|     CACHE STRING | ||||
|     "; separated command to generate a trace for the 'coverage' target" | ||||
| ) | ||||
|  | ||||
| set( | ||||
|     COVERAGE_HTML_COMMAND | ||||
|     genhtml --legend -f -q | ||||
|     "${PROJECT_BINARY_DIR}/coverage.info" | ||||
|     -p "${PROJECT_SOURCE_DIR}" | ||||
|     -o "${PROJECT_BINARY_DIR}/coverage_html" | ||||
|     CACHE STRING | ||||
|     "; separated command to generate an HTML report for the 'coverage' target" | ||||
| ) | ||||
|  | ||||
| # ---- Coverage target ---- | ||||
|  | ||||
| add_custom_target( | ||||
|     coverage | ||||
|     COMMAND ${COVERAGE_TRACE_COMMAND} | ||||
|     COMMAND ${COVERAGE_HTML_COMMAND} | ||||
|     COMMENT "Generating coverage report" | ||||
|     VERBATIM | ||||
| ) | ||||
							
								
								
									
										21
									
								
								cmake/dev-mode.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								cmake/dev-mode.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| include(cmake/folders.cmake) | ||||
|  | ||||
| include(CTest) | ||||
| if(BUILD_TESTING) | ||||
|   add_subdirectory(test) | ||||
| endif() | ||||
|  | ||||
| option(BUILD_MCSS_DOCS "Build documentation using Doxygen and m.css" OFF) | ||||
| if(BUILD_MCSS_DOCS) | ||||
|   include(cmake/docs.cmake) | ||||
| endif() | ||||
|  | ||||
| option(ENABLE_COVERAGE "Enable coverage support separate from CTest's" OFF) | ||||
| if(ENABLE_COVERAGE) | ||||
|   include(cmake/coverage.cmake) | ||||
| endif() | ||||
|  | ||||
| include(cmake/lint-targets.cmake) | ||||
| include(cmake/spell-targets.cmake) | ||||
|  | ||||
| add_folders(Project) | ||||
							
								
								
									
										112
									
								
								cmake/docs-ci.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								cmake/docs-ci.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
|  | ||||
| foreach(var IN ITEMS PROJECT_BINARY_DIR PROJECT_SOURCE_DIR) | ||||
|   if(NOT DEFINED "${var}") | ||||
|     message(FATAL_ERROR "${var} must be defined") | ||||
|   endif() | ||||
| endforeach() | ||||
| set(bin "${PROJECT_BINARY_DIR}") | ||||
| set(src "${PROJECT_SOURCE_DIR}") | ||||
|  | ||||
| # ---- Dependencies ---- | ||||
|  | ||||
| set(mcss_SOURCE_DIR "${bin}/docs/.ci") | ||||
| if(NOT IS_DIRECTORY "${mcss_SOURCE_DIR}") | ||||
|   file(MAKE_DIRECTORY "${mcss_SOURCE_DIR}") | ||||
|   file( | ||||
|       DOWNLOAD | ||||
|       https://github.com/friendlyanon/m.css/releases/download/release-1/mcss.zip | ||||
|       "${mcss_SOURCE_DIR}/mcss.zip" | ||||
|       STATUS status | ||||
|       EXPECTED_MD5 00cd2757ebafb9bcba7f5d399b3bec7f | ||||
|   ) | ||||
|   if(NOT status MATCHES "^0;") | ||||
|     message(FATAL_ERROR "Download failed with ${status}") | ||||
|   endif() | ||||
|   execute_process( | ||||
|       COMMAND "${CMAKE_COMMAND}" -E tar xf mcss.zip | ||||
|       WORKING_DIRECTORY "${mcss_SOURCE_DIR}" | ||||
|       RESULT_VARIABLE result | ||||
|   ) | ||||
|   if(NOT result EQUAL "0") | ||||
|     message(FATAL_ERROR "Extraction failed with ${result}") | ||||
|   endif() | ||||
|   file(REMOVE "${mcss_SOURCE_DIR}/mcss.zip") | ||||
| endif() | ||||
|  | ||||
| find_program(Python3_EXECUTABLE NAMES python3 python) | ||||
| if(NOT Python3_EXECUTABLE) | ||||
|   message(FATAL_ERROR "Python executable was not found") | ||||
| endif() | ||||
|  | ||||
| # ---- Process project() call in CMakeLists.txt ---- | ||||
|  | ||||
| file(READ "${src}/CMakeLists.txt" content) | ||||
|  | ||||
| string(FIND "${content}" "project(" index) | ||||
| if(index EQUAL "-1") | ||||
|   message(FATAL_ERROR "Could not find \"project(\"") | ||||
| endif() | ||||
| string(SUBSTRING "${content}" "${index}" -1 content) | ||||
|  | ||||
| string(FIND "${content}" "\n)\n" index) | ||||
| if(index EQUAL "-1") | ||||
|   message(FATAL_ERROR "Could not find \"\\n)\\n\"") | ||||
| endif() | ||||
| string(SUBSTRING "${content}" 0 "${index}" content) | ||||
|  | ||||
| file(WRITE "${bin}/docs-ci.project.cmake" "docs_${content}\n)\n") | ||||
|  | ||||
| macro(list_pop_front list out) | ||||
|   list(GET "${list}" 0 "${out}") | ||||
|   list(REMOVE_AT "${list}" 0) | ||||
| endmacro() | ||||
|  | ||||
| function(docs_project name) | ||||
|   cmake_parse_arguments(PARSE_ARGV 1 "" "" "VERSION;DESCRIPTION;HOMEPAGE_URL" LANGUAGES) | ||||
|   set(PROJECT_NAME "${name}" PARENT_SCOPE) | ||||
|   if(DEFINED _VERSION) | ||||
|     set(PROJECT_VERSION "${_VERSION}" PARENT_SCOPE) | ||||
|     string(REGEX MATCH "^[0-9]+(\\.[0-9]+)*" versions "${_VERSION}") | ||||
|     string(REPLACE . ";" versions "${versions}") | ||||
|     set(suffixes MAJOR MINOR PATCH TWEAK) | ||||
|     while(NOT versions STREQUAL "" AND NOT suffixes STREQUAL "") | ||||
|       list_pop_front(versions version) | ||||
|       list_pop_front(suffixes suffix) | ||||
|       set("PROJECT_VERSION_${suffix}" "${version}" PARENT_SCOPE) | ||||
|     endwhile() | ||||
|   endif() | ||||
|   if(DEFINED _DESCRIPTION) | ||||
|     set(PROJECT_DESCRIPTION "${_DESCRIPTION}" PARENT_SCOPE) | ||||
|   endif() | ||||
|   if(DEFINED _HOMEPAGE_URL) | ||||
|     set(PROJECT_HOMEPAGE_URL "${_HOMEPAGE_URL}" PARENT_SCOPE) | ||||
|   endif() | ||||
| endfunction() | ||||
|  | ||||
| include("${bin}/docs-ci.project.cmake") | ||||
|  | ||||
| # ---- Generate docs ---- | ||||
|  | ||||
| if(NOT DEFINED DOXYGEN_OUTPUT_DIRECTORY) | ||||
|   set(DOXYGEN_OUTPUT_DIRECTORY "${bin}/docs") | ||||
| endif() | ||||
| set(out "${DOXYGEN_OUTPUT_DIRECTORY}") | ||||
|  | ||||
| foreach(file IN ITEMS Doxyfile conf.py) | ||||
|   configure_file("${src}/docs/${file}.in" "${bin}/docs/${file}" @ONLY) | ||||
| endforeach() | ||||
|  | ||||
| set(mcss_script "${mcss_SOURCE_DIR}/documentation/doxygen.py") | ||||
| set(config "${bin}/docs/conf.py") | ||||
|  | ||||
| file(REMOVE_RECURSE "${out}/html" "${out}/xml") | ||||
|  | ||||
| execute_process( | ||||
|     COMMAND "${Python3_EXECUTABLE}" "${mcss_script}" "${config}" | ||||
|     WORKING_DIRECTORY "${bin}/docs" | ||||
|     RESULT_VARIABLE result | ||||
| ) | ||||
| if(NOT result EQUAL "0") | ||||
|   message(FATAL_ERROR "m.css returned with ${result}") | ||||
| endif() | ||||
							
								
								
									
										46
									
								
								cmake/docs.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								cmake/docs.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| # ---- Dependencies ---- | ||||
|  | ||||
| set(extract_timestamps "") | ||||
| if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24") | ||||
|   set(extract_timestamps DOWNLOAD_EXTRACT_TIMESTAMP YES) | ||||
| endif() | ||||
|  | ||||
| include(FetchContent) | ||||
| FetchContent_Declare( | ||||
|     mcss URL | ||||
|     https://github.com/friendlyanon/m.css/releases/download/release-1/mcss.zip | ||||
|     URL_MD5 00cd2757ebafb9bcba7f5d399b3bec7f | ||||
|     SOURCE_DIR "${PROJECT_BINARY_DIR}/mcss" | ||||
|     UPDATE_DISCONNECTED YES | ||||
|     ${extract_timestamps} | ||||
| ) | ||||
| FetchContent_MakeAvailable(mcss) | ||||
|  | ||||
| find_package(Python3 3.6 REQUIRED) | ||||
|  | ||||
| # ---- Declare documentation target ---- | ||||
|  | ||||
| set( | ||||
|     DOXYGEN_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/docs" | ||||
|     CACHE PATH "Path for the generated Doxygen documentation" | ||||
| ) | ||||
|  | ||||
| set(working_dir "${PROJECT_BINARY_DIR}/docs") | ||||
|  | ||||
| foreach(file IN ITEMS Doxyfile conf.py) | ||||
|   configure_file("docs/${file}.in" "${working_dir}/${file}" @ONLY) | ||||
| endforeach() | ||||
|  | ||||
| set(mcss_script "${mcss_SOURCE_DIR}/documentation/doxygen.py") | ||||
| set(config "${working_dir}/conf.py") | ||||
|  | ||||
| add_custom_target( | ||||
|     docs | ||||
|     COMMAND "${CMAKE_COMMAND}" -E remove_directory | ||||
|     "${DOXYGEN_OUTPUT_DIRECTORY}/html" | ||||
|     "${DOXYGEN_OUTPUT_DIRECTORY}/xml" | ||||
|     COMMAND "${Python3_EXECUTABLE}" "${mcss_script}" "${config}" | ||||
|     COMMENT "Building documentation using Doxygen and m.css" | ||||
|     WORKING_DIRECTORY "${working_dir}" | ||||
|     VERBATIM | ||||
| ) | ||||
							
								
								
									
										21
									
								
								cmake/folders.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								cmake/folders.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| set_property(GLOBAL PROPERTY USE_FOLDERS YES) | ||||
|  | ||||
| # Call this function at the end of a directory scope to assign a folder to | ||||
| # targets created in that directory. Utility targets will be assigned to the | ||||
| # UtilityTargets folder, otherwise to the ${name}Targets folder. If a target | ||||
| # already has a folder assigned, then that target will be skipped. | ||||
| function(add_folders name) | ||||
|   get_property(targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS) | ||||
|   foreach(target IN LISTS targets) | ||||
|     get_property(folder TARGET "${target}" PROPERTY FOLDER) | ||||
|     if(DEFINED folder) | ||||
|       continue() | ||||
|     endif() | ||||
|     set(folder Utility) | ||||
|     get_property(type TARGET "${target}" PROPERTY TYPE) | ||||
|     if(NOT type STREQUAL "UTILITY") | ||||
|       set(folder "${name}") | ||||
|     endif() | ||||
|     set_property(TARGET "${target}" PROPERTY FOLDER "${folder}Targets") | ||||
|   endforeach() | ||||
| endfunction() | ||||
							
								
								
									
										1
									
								
								cmake/install-config.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								cmake/install-config.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| include("${CMAKE_CURRENT_LIST_DIR}/astarTargets.cmake") | ||||
							
								
								
									
										66
									
								
								cmake/install-rules.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								cmake/install-rules.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| if(PROJECT_IS_TOP_LEVEL) | ||||
|   set( | ||||
|       CMAKE_INSTALL_INCLUDEDIR "include/astar-${PROJECT_VERSION}" | ||||
|       CACHE STRING "" | ||||
|   ) | ||||
|   set_property(CACHE CMAKE_INSTALL_INCLUDEDIR PROPERTY TYPE PATH) | ||||
| endif() | ||||
|  | ||||
| # Project is configured with no languages, so tell GNUInstallDirs the lib dir | ||||
| set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "") | ||||
|  | ||||
| include(CMakePackageConfigHelpers) | ||||
| include(GNUInstallDirs) | ||||
|  | ||||
| # find_package(<package>) call for consumers to find this project | ||||
| set(package astar) | ||||
|  | ||||
| install( | ||||
|     DIRECTORY include/ | ||||
|     DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" | ||||
|     COMPONENT astar_Development | ||||
| ) | ||||
|  | ||||
| install( | ||||
|     TARGETS astar_astar | ||||
|     EXPORT astarTargets | ||||
|     INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" | ||||
| ) | ||||
|  | ||||
| write_basic_package_version_file( | ||||
|     "${package}ConfigVersion.cmake" | ||||
|     COMPATIBILITY SameMajorVersion | ||||
|     ARCH_INDEPENDENT | ||||
| ) | ||||
|  | ||||
| # Allow package maintainers to freely override the path for the configs | ||||
| set( | ||||
|     astar_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${package}" | ||||
|     CACHE STRING "CMake package config location relative to the install prefix" | ||||
| ) | ||||
| set_property(CACHE astar_INSTALL_CMAKEDIR PROPERTY TYPE PATH) | ||||
| mark_as_advanced(astar_INSTALL_CMAKEDIR) | ||||
|  | ||||
| install( | ||||
|     FILES cmake/install-config.cmake | ||||
|     DESTINATION "${astar_INSTALL_CMAKEDIR}" | ||||
|     RENAME "${package}Config.cmake" | ||||
|     COMPONENT astar_Development | ||||
| ) | ||||
|  | ||||
| install( | ||||
|     FILES "${PROJECT_BINARY_DIR}/${package}ConfigVersion.cmake" | ||||
|     DESTINATION "${astar_INSTALL_CMAKEDIR}" | ||||
|     COMPONENT astar_Development | ||||
| ) | ||||
|  | ||||
| install( | ||||
|     EXPORT astarTargets | ||||
|     NAMESPACE astar:: | ||||
|     DESTINATION "${astar_INSTALL_CMAKEDIR}" | ||||
|     COMPONENT astar_Development | ||||
| ) | ||||
|  | ||||
| if(PROJECT_IS_TOP_LEVEL) | ||||
|   include(CPack) | ||||
| endif() | ||||
							
								
								
									
										13
									
								
								cmake/lib/backward-cpp.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								cmake/lib/backward-cpp.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| FetchContent_Declare( | ||||
|   backward-cpp | ||||
|   GIT_REPOSITORY https://github.com/bombela/backward-cpp.git | ||||
|   GIT_TAG 0ddfadc4b0f5c53e63259fe804ee595e6f01f4df) # 23-10-2022 | ||||
|  | ||||
| FetchContent_MakeAvailable(backward-cpp) | ||||
|  | ||||
| # TODO: target_include_directories instead of include_directories | ||||
| include_directories(${backward-cpp_SOURCE_DIR}) | ||||
							
								
								
									
										70
									
								
								cmake/lib/benchmark.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										70
									
								
								cmake/lib/benchmark.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| find_package(benchmark QUIET) | ||||
|  | ||||
| if (NOT benchmark_FOUND) | ||||
|     message(STATUS "benchmark not found on system, downloading...") | ||||
|     include(FetchContent) | ||||
|  | ||||
|     set(CMAKE_CXX_CLANG_TIDY_TMP "${CMAKE_CXX_CLANG_TIDY}") | ||||
|     set(CMAKE_CXX_CLANG_TIDY "") | ||||
|  | ||||
|     FetchContent_Declare( | ||||
|         googlebenchmark | ||||
|         GIT_REPOSITORY https://github.com/google/benchmark.git | ||||
|         GIT_TAG ca8d0f7b613ac915cd6b161ab01b7be449d1e1cd | ||||
|         #GIT_SHALLOW TRUE | ||||
|         ) # 12-10-2023 | ||||
|  | ||||
|     # Disable tests on google benchmark | ||||
|     set(BENCHMARK_ENABLE_TESTING | ||||
|         OFF | ||||
|         CACHE BOOL "" FORCE) | ||||
|     set(BENCHMARK_ENABLE_WERROR | ||||
|         OFF | ||||
|         CACHE BOOL "" FORCE) | ||||
|     set(BENCHMARK_FORCE_WERROR | ||||
|         OFF | ||||
|         CACHE BOOL "" FORCE) | ||||
|  | ||||
|     set(BENCHMARK_ENABLE_INSTALL | ||||
|         OFF | ||||
|         CACHE BOOL "" FORCE) | ||||
|  | ||||
|     set(BENCHMARK_DOWNLOAD_DEPENDENCIES | ||||
|         ON | ||||
|         CACHE BOOL "" FORCE) | ||||
|  | ||||
|     set(BENCHMARK_CXX_LINKER_FLAGS | ||||
|         "" | ||||
|         CACHE STRING "" FORCE) | ||||
|  | ||||
|     set(BENCHMARK_CXX_LIBRARIES | ||||
|         "" | ||||
|         CACHE STRING "" FORCE) | ||||
|  | ||||
|     set(BENCHMARK_CXX_FLAGS | ||||
|         "" | ||||
|         CACHE STRING "" FORCE) | ||||
|  | ||||
|     set(CMAKE_CXX_FLAGS_COVERAGE | ||||
|         "" | ||||
|         CACHE STRING "" FORCE) | ||||
|  | ||||
|     set(CMAKE_REQUIRED_FLAGS | ||||
|         "" | ||||
|         CACHE STRING "" FORCE) | ||||
|  | ||||
|     FetchContent_MakeAvailable(googlebenchmark) | ||||
|     # Lib: benchmark::benchmark benchmark::benchmark_main | ||||
|  | ||||
|     set(CMAKE_CXX_CLANG_TIDY "${CMAKE_CXX_CLANG_TIDY_TMP}") | ||||
|  | ||||
|     set_target_properties(benchmark | ||||
|         PROPERTIES | ||||
|         RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|         LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|         ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|         PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|     ) | ||||
| endif() | ||||
							
								
								
									
										22
									
								
								cmake/lib/boost.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								cmake/lib/boost.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| if(NOT DEFINED BOOST_INCLUDE_LIBRARIES) | ||||
|   set(BOOST_INCLUDE_LIBRARIES system) | ||||
| endif() | ||||
|  | ||||
|  | ||||
| if(NOT DEFINED BOOST_ENABLE_CMAKE) | ||||
|   set(BOOST_ENABLE_CMAKE ON) | ||||
| endif() | ||||
|  | ||||
|  | ||||
| FetchContent_Declare( | ||||
|   Boost | ||||
|   GIT_REPOSITORY https://github.com/boostorg/boost.git | ||||
|   GIT_TAG boost-1.81.0 | ||||
|   #GIT_SHALLOW TRUE | ||||
| ) | ||||
| FetchContent_MakeAvailable(Boost) | ||||
|  | ||||
							
								
								
									
										15
									
								
								cmake/lib/drogon.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								cmake/lib/drogon.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
|  | ||||
|  | ||||
| # https://github.com/drogonframework/drogon/issues/1288#issuecomment-1163902139 | ||||
| FetchContent_Declare(drogon | ||||
|     GIT_REPOSITORY https://github.com/drogonframework/drogon.git | ||||
|     GIT_TAG v1.8.4  # 08-04-2023 | ||||
| ) | ||||
|  | ||||
| # Reset CXX_FLAGS to avoid warnings from drogon | ||||
| set(CMAKE_CXX_FLAGS_OLD "${CMAKE_CXX_FLAGS}") | ||||
| set(CMAKE_CXX_FLAGS "-std=c++17 -O3") | ||||
|  | ||||
| FetchContent_MakeAvailable(drogon) | ||||
|  | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_OLD}") | ||||
							
								
								
									
										11
									
								
								cmake/lib/fast_noise2.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								cmake/lib/fast_noise2.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| set(FASTNOISE2_NOISETOOL OFF CACHE BOOL "Build Noise Tool" FORCE) | ||||
|  | ||||
| FetchContent_Declare(FastNoise2 | ||||
|     GIT_REPOSITORY https://github.com/Auburn/FastNoise2.git | ||||
|     GIT_TAG 0928ca22cd4cfd50e9b17cec4fe9d867b59c3943 # 2023-06-07 | ||||
| ) | ||||
| FetchContent_MakeAvailable(FastNoise2) | ||||
							
								
								
									
										32
									
								
								cmake/lib/gtest.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								cmake/lib/gtest.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| find_package(GTest QUIET) | ||||
|  | ||||
| if (NOT GTEST_FOUND) | ||||
|     message(STATUS "GTest not found on system, downloading...") | ||||
|     include(FetchContent) | ||||
|  | ||||
|     FetchContent_Declare( | ||||
|     googletest | ||||
|     GIT_REPOSITORY https://github.com/google/googletest.git | ||||
|     GIT_TAG 2dd1c131950043a8ad5ab0d2dda0e0970596586a) # 12-10-2023 | ||||
|  | ||||
|     # Disable tests on gtest | ||||
|     set(gtest_build_tests | ||||
|         OFF | ||||
|         CACHE BOOL "" FORCE) | ||||
|     set(gtest_build_samples | ||||
|         OFF | ||||
|         CACHE BOOL "" FORCE) | ||||
|  | ||||
|     FetchContent_MakeAvailable(googletest) | ||||
|     # Lib: gtest gtest_main | ||||
|  | ||||
|     set_target_properties(gtest | ||||
|         PROPERTIES | ||||
|         RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|         LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|         ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|         PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|     ) | ||||
| endif() | ||||
							
								
								
									
										31
									
								
								cmake/lib/json.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								cmake/lib/json.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| find_package(nlohmann_json QUIET) | ||||
|  | ||||
| if (NOT nlohmann_json_FOUND) | ||||
|     message(STATUS "nlohmann_json not found on system, downloading...") | ||||
|     include(FetchContent) | ||||
|  | ||||
|     #set(CMAKE_MODULE_PATH | ||||
|     #    "" | ||||
|     #    CACHE STRING "" FORCE) | ||||
|  | ||||
|     #set(NLOHMANN_JSON_SYSTEM_INCLUDE | ||||
|     #    "" | ||||
|     #    CACHE STRING "" FORCE) | ||||
|  | ||||
|     FetchContent_Declare(nlohmann_json | ||||
|         GIT_REPOSITORY https://github.com/nlohmann/json.git | ||||
|         GIT_TAG f56c6e2e30241b9245161a86ae9fecf6543bf411 # 2023-11-26 | ||||
|     ) | ||||
|     FetchContent_MakeAvailable(nlohmann_json) | ||||
|     # nlohmann_json::nlohmann_json | ||||
|     set_target_properties(nlohmann_json | ||||
|         PROPERTIES | ||||
|         RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|         LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|         ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|         PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|     ) | ||||
|     include_directories(${nlohmann_json_SOURCE_DIR}/include) | ||||
| endif() | ||||
							
								
								
									
										42
									
								
								cmake/lib/opencv.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								cmake/lib/opencv.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
| set(OpenCV_DIR ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|  | ||||
| find_package(OpenCV QUIET) | ||||
|  | ||||
| if (NOT OpenCV_FOUND) | ||||
|     #set(OpenCV_STATIC ON) | ||||
|     set(BUILD_EXAMPLES CACHE BOOL OFF) | ||||
|     set(BUILD_DOCS CACHE BOOL OFF) | ||||
|     set(BUILD_TESTS CACHE BOOL OFF) | ||||
|     set(BUILD_PERF_TESTS CACHE BOOL OFF) | ||||
|     #set(BUILD_PACKAGE CACHE BOOL OFF) | ||||
|  | ||||
|  | ||||
|     set(BUILD_opencv_apps CACHE BOOL OFF) | ||||
|  | ||||
|     FetchContent_Declare( | ||||
|         OpenCV | ||||
|         GIT_REPOSITORY https://github.com/opencv/opencv.git | ||||
|         GIT_TAG        4.7.0 | ||||
|         #GIT_SHALLOW    TRUE | ||||
|         GIT_PROGRESS TRUE | ||||
|     ) | ||||
|     FetchContent_MakeAvailable(OpenCV) | ||||
|     #set(OpenCV_DIR ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|     #include_directories(${OpenCV_INCLUDE_DIRS}) | ||||
|     #message(FATAL_ERROR "OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}") | ||||
|     #find_package(OpenCV REQUIRED) | ||||
|  | ||||
|     #include_directories(${OpenCV_INCLUDE_DIRS}) | ||||
|     #target_include_directories("${NAME}" PRIVATE | ||||
|     #${OPENCV_CONFIG_FILE_INCLUDE_DIR} | ||||
|     #${OPENCV_MODULE_opencv_core_LOCATION}/include | ||||
|     #${OPENCV_MODULE_opencv_highgui_LOCATION}/include | ||||
|     #) | ||||
|     #target_link_libraries("${NAME}" PRIVATE opencv_core opencv_highgui) | ||||
|     #target_link_libraries("${NAME}" PRIVATE ${OpenCV_LIBS}) | ||||
|     #opencv_add_module() | ||||
|      | ||||
| endif() | ||||
							
								
								
									
										6
									
								
								cmake/lib/openmp.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								cmake/lib/openmp.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| find_package(OpenMP) | ||||
| if(OpenMP_CXX_FOUND) | ||||
|     # message("OpenMP found") | ||||
| endif() | ||||
							
								
								
									
										14
									
								
								cmake/lib/perlin_noise.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								cmake/lib/perlin_noise.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| FetchContent_Declare(perlin_noise | ||||
|     GIT_REPOSITORY https://github.com/Reputeless/PerlinNoise.git | ||||
|     GIT_TAG bdf39fe92b2a585cdef485bcec2bca8ab5614095 # 2022-12-30 | ||||
|     CONFIGURE_COMMAND "" | ||||
|     BUILD_COMMAND "" | ||||
|     INSTALL_COMMAND "" | ||||
|     TEST_COMMAND "" | ||||
| ) | ||||
| FetchContent_MakeAvailable(perlin_noise) | ||||
| include_directories("${perlin_noise_SOURCE_DIR}") | ||||
							
								
								
									
										18
									
								
								cmake/lib/pybind11.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								cmake/lib/pybind11.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| cmake_minimum_required(VERSION 3.15) | ||||
|  | ||||
| find_package(Python 3.8 COMPONENTS Interpreter Development REQUIRED) | ||||
| find_package(pybind11) | ||||
| # add_subdirectory(pybind11) | ||||
|  | ||||
| if (NOT pybind11_FOUND) | ||||
| 	include(FetchContent) | ||||
| 	FetchContent_Declare( | ||||
| 		pybind11 | ||||
| 		GIT_REPOSITORY https://github.com/pybind/pybind11.git | ||||
| 		GIT_TAG v2.10.3 | ||||
| 		GIT_SHALLOW TRUE | ||||
| 	) | ||||
| 	FetchContent_MakeAvailable(pybind11) | ||||
| endif() | ||||
|  | ||||
| #pybind11_add_module(${PROJECT_NAME} main.cpp) | ||||
							
								
								
									
										17
									
								
								cmake/lib/raygui.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								cmake/lib/raygui.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| set(BUILD_RAYLIB_CPP_EXAMPLES OFF CACHE BOOL "" FORCE) | ||||
|  | ||||
| find_package(raygui QUIET) | ||||
|  | ||||
| if (NOT raygui_FOUND) | ||||
|     FetchContent_Declare(raygui | ||||
|         GIT_REPOSITORY https://github.com/raysan5/raygui.git | ||||
|         GIT_TAG 4.0 | ||||
|     ) | ||||
|     FetchContent_MakeAvailable(raygui) | ||||
|     include_directories(${raygui_SOURCE_DIR}) | ||||
|     include_directories(${raygui_SOURCE_DIR}/src) | ||||
| endif() | ||||
							
								
								
									
										13
									
								
								cmake/lib/raylib-cpp.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										13
									
								
								cmake/lib/raylib-cpp.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| #find_package(raylib_cpp QUIET) | ||||
|  | ||||
| if (NOT raylib_cpp_FOUND) | ||||
|     FetchContent_Declare(raylib_cpp | ||||
|         GIT_REPOSITORY https://github.com/RobLoach/raylib-cpp.git | ||||
|         GIT_TAG v5.0.0 # 08-12-2023 | ||||
|     ) | ||||
|     FetchContent_MakeAvailable(raylib_cpp) | ||||
| endif() | ||||
							
								
								
									
										47
									
								
								cmake/lib/raylib.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										47
									
								
								cmake/lib/raylib.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| find_package(raylib QUIET) | ||||
|  | ||||
| if (NOT raylib_FOUND AND NOT FETCHCONTENT_FULLY_DISCONNECTED) | ||||
|     message(STATUS "raylib not found on system, downloading...") | ||||
|  | ||||
|     include(FetchContent) | ||||
|  | ||||
|     if(NOT DEFINED BUILD_EXAMPLES) | ||||
|         set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) | ||||
|     endif() | ||||
|  | ||||
|     if(NOT DEFINED BUILD_GAMES) | ||||
|         set(BUILD_GAMES    OFF CACHE BOOL "" FORCE) | ||||
|     endif() | ||||
|  | ||||
|     if(NOT DEFINED INCLUDE_EVERYTHING) | ||||
|         set(INCLUDE_EVERYTHING ON CACHE BOOL "" FORCE) | ||||
|     endif() | ||||
|  | ||||
|     if(NOT DEFINED OPENGL_VERSION) | ||||
|         #set(OPENGL_VERSION OFF CACHE STRING "4.3" FORCE) | ||||
|     endif() | ||||
|  | ||||
|     #set (CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/install CACHE PATH "default install path" FORCE) | ||||
|     #set (CMAKE_INSTALL_LIBDIR ${CMAKE_BINARY_DIR}/lib CACHE PATH "default install path" FORCE) | ||||
|  | ||||
|     #message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}") | ||||
|     FetchContent_Declare(raylib | ||||
|         GIT_REPOSITORY https://github.com/raysan5/raylib.git | ||||
|         GIT_TAG 5.0  # 08-12-2023 | ||||
|     ) | ||||
|     FetchContent_MakeAvailable(raylib) | ||||
|  | ||||
|     set_target_properties(raylib | ||||
|         PROPERTIES | ||||
|         RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|         LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|         ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|         PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|     ) | ||||
|  | ||||
|     set(raylib_FOUND TRUE) | ||||
| else() | ||||
|     find_package(raylib 5.0.0 REQUIRED) | ||||
| endif() | ||||
							
								
								
									
										11
									
								
								cmake/lib/spdlog.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								cmake/lib/spdlog.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| FetchContent_Declare( | ||||
|     spdlog | ||||
|     GIT_REPOSITORY https://github.com/gabime/spdlog.git | ||||
|     GIT_TAG 7e635fca68d014934b4af8a1cf874f63989352b7) # 2023-07-09 | ||||
|  | ||||
| FetchContent_MakeAvailable(spdlog) | ||||
| include_directories("${spdlog_SOURCE_DIR}") | ||||
							
								
								
									
										14
									
								
								cmake/lib/threadpool.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								cmake/lib/threadpool.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| FetchContent_Declare(bs-thread-pool | ||||
|     GIT_REPOSITORY https://github.com/bshoshany/thread-pool.git | ||||
|     GIT_TAG 6790920f61ab3e928ddaea835ab6a803d467f41d # 2023-12-28 | ||||
|     CONFIGURE_COMMAND "" | ||||
|     BUILD_COMMAND "" | ||||
|     INSTALL_COMMAND "" | ||||
|     TEST_COMMAND "" | ||||
| ) | ||||
| FetchContent_MakeAvailable(bs-thread-pool) | ||||
| include_directories("${bs-thread-pool_SOURCE_DIR}/include") | ||||
							
								
								
									
										10
									
								
								cmake/lib/vector.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								cmake/lib/vector.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| FetchContent_Declare( | ||||
|   vector | ||||
|   GIT_REPOSITORY https://github.com/bensuperpc/vector.git | ||||
|   GIT_TAG 9febb9c84e7b73e6c621afd920dd3c8bb47a130c) # 2022-10-23 | ||||
|  | ||||
| FetchContent_MakeAvailable(vector) | ||||
							
								
								
									
										16
									
								
								cmake/lib/zlib.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								cmake/lib/zlib.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| cmake_minimum_required(VERSION 3.14.0) | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| find_package(zlib QUIET) | ||||
|  | ||||
| set(ZLIB_LIBRARY zlib) | ||||
|  | ||||
| if (NOT zlib_FOUND) | ||||
|     FetchContent_Declare( | ||||
|         zlib | ||||
|         GIT_REPOSITORY https://github.com/madler/zlib.git | ||||
|         GIT_TAG        v1.2.13 | ||||
|     ) | ||||
|     FetchContent_MakeAvailable(zlib) | ||||
| endif() | ||||
							
								
								
									
										34
									
								
								cmake/lint-targets.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								cmake/lint-targets.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| set( | ||||
|     FORMAT_PATTERNS | ||||
|     source/*.cpp source/*.hpp | ||||
|     include/*.hpp | ||||
|     test/*.cpp test/*.hpp | ||||
|     example/*.cpp example/*.hpp | ||||
|     CACHE STRING | ||||
|     "; separated patterns relative to the project source dir to format" | ||||
| ) | ||||
|  | ||||
| set(FORMAT_COMMAND clang-format CACHE STRING "Formatter to use") | ||||
|  | ||||
| add_custom_target( | ||||
|     format-check | ||||
|     COMMAND "${CMAKE_COMMAND}" | ||||
|     -D "FORMAT_COMMAND=${FORMAT_COMMAND}" | ||||
|     -D "PATTERNS=${FORMAT_PATTERNS}" | ||||
|     -P "${PROJECT_SOURCE_DIR}/cmake/lint.cmake" | ||||
|     WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" | ||||
|     COMMENT "Linting the code" | ||||
|     VERBATIM | ||||
| ) | ||||
|  | ||||
| add_custom_target( | ||||
|     format-fix | ||||
|     COMMAND "${CMAKE_COMMAND}" | ||||
|     -D "FORMAT_COMMAND=${FORMAT_COMMAND}" | ||||
|     -D "PATTERNS=${FORMAT_PATTERNS}" | ||||
|     -D FIX=YES | ||||
|     -P "${PROJECT_SOURCE_DIR}/cmake/lint.cmake" | ||||
|     WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" | ||||
|     COMMENT "Fixing the code" | ||||
|     VERBATIM | ||||
| ) | ||||
							
								
								
									
										52
									
								
								cmake/lint.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								cmake/lint.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
|  | ||||
| macro(default name) | ||||
|   if(NOT DEFINED "${name}") | ||||
|     set("${name}" "${ARGN}") | ||||
|   endif() | ||||
| endmacro() | ||||
|  | ||||
| default(FORMAT_COMMAND clang-format) | ||||
| default( | ||||
|     PATTERNS | ||||
|     source/*.cpp source/*.hpp | ||||
|     include/*.hpp | ||||
|     test/*.cpp test/*.hpp | ||||
|     example/*.cpp example/*.hpp | ||||
| ) | ||||
| default(FIX NO) | ||||
|  | ||||
| set(flag --output-replacements-xml) | ||||
| set(args OUTPUT_VARIABLE output) | ||||
| if(FIX) | ||||
|   set(flag -i) | ||||
|   set(args "") | ||||
| endif() | ||||
|  | ||||
| file(GLOB_RECURSE files ${PATTERNS}) | ||||
| set(badly_formatted "") | ||||
| set(output "") | ||||
| string(LENGTH "${CMAKE_SOURCE_DIR}/" path_prefix_length) | ||||
|  | ||||
| foreach(file IN LISTS files) | ||||
|   execute_process( | ||||
|       COMMAND "${FORMAT_COMMAND}" --style=file "${flag}" "${file}" | ||||
|       WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" | ||||
|       RESULT_VARIABLE result | ||||
|       ${args} | ||||
|   ) | ||||
|   if(NOT result EQUAL "0") | ||||
|     message(FATAL_ERROR "'${file}': formatter returned with ${result}") | ||||
|   endif() | ||||
|   if(NOT FIX AND output MATCHES "\n<replacement offset") | ||||
|     string(SUBSTRING "${file}" "${path_prefix_length}" -1 relative_file) | ||||
|     list(APPEND badly_formatted "${relative_file}") | ||||
|   endif() | ||||
|   set(output "") | ||||
| endforeach() | ||||
|  | ||||
| if(NOT badly_formatted STREQUAL "") | ||||
|   list(JOIN badly_formatted "\n" bad_list) | ||||
|   message("The following files are badly formatted:\n\n${bad_list}\n") | ||||
|   message(FATAL_ERROR "Run again with FIX=YES to fix these files.") | ||||
| endif() | ||||
							
								
								
									
										10
									
								
								cmake/prelude.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								cmake/prelude.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| # ---- In-source guard ---- | ||||
|  | ||||
| if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) | ||||
|   message( | ||||
|       FATAL_ERROR | ||||
|       "In-source builds are not supported. " | ||||
|       "Please read the BUILDING document before trying to build this project. " | ||||
|       "You may need to delete 'CMakeCache.txt' and 'CMakeFiles/' first." | ||||
|   ) | ||||
| endif() | ||||
							
								
								
									
										6
									
								
								cmake/project-is-top-level.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								cmake/project-is-top-level.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| # This variable is set by project() in CMake 3.21+ | ||||
| string( | ||||
|     COMPARE EQUAL | ||||
|     "${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}" | ||||
|     PROJECT_IS_TOP_LEVEL | ||||
| ) | ||||
							
								
								
									
										22
									
								
								cmake/spell-targets.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								cmake/spell-targets.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| set(SPELL_COMMAND codespell CACHE STRING "Spell checker to use") | ||||
|  | ||||
| add_custom_target( | ||||
|     spell-check | ||||
|     COMMAND "${CMAKE_COMMAND}" | ||||
|     -D "SPELL_COMMAND=${SPELL_COMMAND}" | ||||
|     -P "${PROJECT_SOURCE_DIR}/cmake/spell.cmake" | ||||
|     WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" | ||||
|     COMMENT "Checking spelling" | ||||
|     VERBATIM | ||||
| ) | ||||
|  | ||||
| add_custom_target( | ||||
|     spell-fix | ||||
|     COMMAND "${CMAKE_COMMAND}" | ||||
|     -D "SPELL_COMMAND=${SPELL_COMMAND}" | ||||
|     -D FIX=YES | ||||
|     -P "${PROJECT_SOURCE_DIR}/cmake/spell.cmake" | ||||
|     WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" | ||||
|     COMMENT "Fixing spelling errors" | ||||
|     VERBATIM | ||||
| ) | ||||
							
								
								
									
										31
									
								
								cmake/spell.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								cmake/spell.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
|  | ||||
| macro(default name) | ||||
|   if(NOT DEFINED "${name}") | ||||
|     set("${name}" "${ARGN}") | ||||
|   endif() | ||||
| endmacro() | ||||
|  | ||||
| default(SPELL_COMMAND codespell) | ||||
| default(FIX NO) | ||||
|  | ||||
| set(flag "") | ||||
| if(FIX) | ||||
|   set(flag -w) | ||||
| endif() | ||||
|  | ||||
| set(flag "${flag}" --ignore-words codespell.ignore-words.txt) | ||||
|  | ||||
| execute_process( | ||||
|     COMMAND "${SPELL_COMMAND}" ${flag} | ||||
|     WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" | ||||
|     RESULT_VARIABLE result | ||||
| ) | ||||
|  | ||||
| if(result EQUAL "65") | ||||
|   message(FATAL_ERROR "Run again with FIX=YES to fix these errors.") | ||||
| elseif(result EQUAL "64") | ||||
|   message(FATAL_ERROR "Spell checker printed the usage info. Bad arguments?") | ||||
| elseif(NOT result EQUAL "0") | ||||
|   message(FATAL_ERROR "Spell checker returned with ${result}") | ||||
| endif() | ||||
							
								
								
									
										9
									
								
								cmake/utile/ccache.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										9
									
								
								cmake/utile/ccache.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| find_program(CCACHE_PROGRAM ccache) | ||||
|  | ||||
| if(CCACHE_PROGRAM) | ||||
|     message(NOTICE "-- ccache is enabled (found here: ${CCACHE_PROGRAM})") | ||||
|     set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "\"${CCACHE_PROGRAM}\"") | ||||
|     set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "\"${CCACHE_PROGRAM}\"") | ||||
| else() | ||||
|     message(WARNING "-- ccache has not been found") | ||||
| endif() | ||||
							
								
								
									
										11
									
								
								cmake/utile/distcc.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								cmake/utile/distcc.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| find_program(DISTCC_PROGRAM distcc) | ||||
|  | ||||
| message(WARNING "distcc module is in beta.") | ||||
|  | ||||
| if(DISTCC_PROGRAM) | ||||
|     message(NOTICE "distcc is enabled (found here: ${DISTCC_PROGRAM})") | ||||
|     set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "\"${DISTCC_PROGRAM}\"") | ||||
|     set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "\"${DISTCC_PROGRAM}\"") | ||||
| else() | ||||
|     message(NOTICE "distcc has not been found") | ||||
| endif() | ||||
							
								
								
									
										11
									
								
								cmake/utile/lto.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								cmake/utile/lto.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| cmake_minimum_required(VERSION 3.9.0) | ||||
|  | ||||
| include(CheckIPOSupported) | ||||
| check_ipo_supported(RESULT supported OUTPUT error) | ||||
|  | ||||
| if(supported) | ||||
|     message(STATUS "IPO / LTO enabled") | ||||
|     set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) | ||||
| else() | ||||
|     message(STATUS "IPO / LTO not supported: <${error}>") | ||||
| endif() | ||||
							
								
								
									
										9
									
								
								cmake/utile/ninja_color.cmake
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										9
									
								
								cmake/utile/ninja_color.cmake
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,9 @@ | ||||
|  | ||||
| option (FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." TRUE) | ||||
| if (${FORCE_COLORED_OUTPUT}) | ||||
|   if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") | ||||
|     add_compile_options (-fdiagnostics-color=always) | ||||
|   elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") | ||||
|     add_compile_options (-fcolor-diagnostics) | ||||
|   endif () | ||||
| endif () | ||||
							
								
								
									
										28
									
								
								cmake/variables.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cmake/variables.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| # ---- Developer mode ---- | ||||
|  | ||||
| # Developer mode enables targets and code paths in the CMake scripts that are | ||||
| # only relevant for the developer(s) of astar | ||||
| # Targets necessary to build the project must be provided unconditionally, so | ||||
| # consumers can trivially build and package the project | ||||
| if(PROJECT_IS_TOP_LEVEL) | ||||
|   option(astar_DEVELOPER_MODE "Enable developer mode" OFF) | ||||
| endif() | ||||
|  | ||||
| # ---- Warning guard ---- | ||||
|  | ||||
| # target_include_directories with the SYSTEM modifier will request the compiler | ||||
| # to omit warnings from the provided paths, if the compiler supports that | ||||
| # This is to provide a user experience similar to find_package when | ||||
| # add_subdirectory or FetchContent is used to consume this project | ||||
| set(warning_guard "") | ||||
| if(NOT PROJECT_IS_TOP_LEVEL) | ||||
|   option( | ||||
|       astar_INCLUDES_WITH_SYSTEM | ||||
|       "Use SYSTEM modifier for astar's includes, disabling warnings" | ||||
|       ON | ||||
|   ) | ||||
|   mark_as_advanced(astar_INCLUDES_WITH_SYSTEM) | ||||
|   if(astar_INCLUDES_WITH_SYSTEM) | ||||
|     set(warning_guard SYSTEM) | ||||
|   endif() | ||||
| endif() | ||||
							
								
								
									
										1
									
								
								codespell.ignore-words.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								codespell.ignore-words.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
|   | ||||
							
								
								
									
										32
									
								
								docs/Doxyfile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								docs/Doxyfile.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| # Configuration for Doxygen for use with CMake | ||||
| # Only options that deviate from the default are included | ||||
| # To create a new Doxyfile containing all available options, call `doxygen -g` | ||||
|  | ||||
| # Get Project name and version from CMake | ||||
| PROJECT_NAME = "@PROJECT_NAME@" | ||||
| PROJECT_NUMBER = "@PROJECT_VERSION@" | ||||
|  | ||||
| # Add sources | ||||
| INPUT = "@PROJECT_SOURCE_DIR@/README.md" "@PROJECT_SOURCE_DIR@/include" "@PROJECT_SOURCE_DIR@/docs/pages" | ||||
| EXTRACT_ALL = YES | ||||
| RECURSIVE = YES | ||||
| OUTPUT_DIRECTORY = "@DOXYGEN_OUTPUT_DIRECTORY@" | ||||
|  | ||||
| # Use the README as a main page | ||||
| USE_MDFILE_AS_MAINPAGE = "@PROJECT_SOURCE_DIR@/README.md" | ||||
|  | ||||
| # set relative include paths | ||||
| FULL_PATH_NAMES = YES | ||||
| STRIP_FROM_PATH = "@PROJECT_SOURCE_DIR@/include" "@PROJECT_SOURCE_DIR@" | ||||
| STRIP_FROM_INC_PATH = | ||||
|  | ||||
| # We use m.css to generate the html documentation, so we only need XML output | ||||
| GENERATE_XML = YES | ||||
| GENERATE_HTML = NO | ||||
| GENERATE_LATEX = NO | ||||
| XML_PROGRAMLISTING = NO | ||||
| CREATE_SUBDIRS = NO | ||||
|  | ||||
| # Include all directories, files and namespaces in the documentation | ||||
| # Disable to include only explicitly documented objects | ||||
| M_SHOW_UNDOCUMENTED = YES | ||||
							
								
								
									
										6
									
								
								docs/conf.py.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								docs/conf.py.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| DOXYFILE = 'Doxyfile' | ||||
|  | ||||
| LINKS_NAVBAR1 = [ | ||||
|     (None, 'pages', [(None, 'about')]), | ||||
|     (None, 'namespaces', []), | ||||
| ] | ||||
							
								
								
									
										7
									
								
								docs/pages/about.dox
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								docs/pages/about.dox
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| /** | ||||
|  * @page about About | ||||
|  * @section about-doxygen Doxygen documentation | ||||
|  * This page is auto generated using | ||||
|  * <a href="https://www.doxygen.nl/">Doxygen</a>, making use of some useful | ||||
|  * <a href="https://www.doxygen.nl/manual/commands.html">special commands</a>. | ||||
|  */ | ||||
							
								
								
									
										27
									
								
								example/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								example/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
|  | ||||
| project(astarExamples CXX) | ||||
|  | ||||
| include(../cmake/project-is-top-level.cmake) | ||||
| include(../cmake/folders.cmake) | ||||
|  | ||||
| if(PROJECT_IS_TOP_LEVEL) | ||||
|   find_package(astar REQUIRED) | ||||
| endif() | ||||
|  | ||||
| add_custom_target(run-examples) | ||||
|  | ||||
| function(add_example NAME) | ||||
|   add_executable("${NAME}" "${NAME}.cpp") | ||||
|   target_link_libraries("${NAME}" PRIVATE astar::astar) | ||||
|   target_compile_features("${NAME}" PRIVATE cxx_std_20) | ||||
|   add_custom_target("run_${NAME}" COMMAND "${NAME}" VERBATIM) | ||||
|   add_dependencies("run_${NAME}" "${NAME}") | ||||
|   add_dependencies(run-examples "run_${NAME}") | ||||
| endfunction() | ||||
|  | ||||
| add_example(basic_example) | ||||
| add_example(debug_example) | ||||
| add_example(basic_fast_example) | ||||
|  | ||||
| add_folders(Example) | ||||
							
								
								
									
										31
									
								
								example/basic_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								example/basic_example.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| #include <astar/astar.hpp> | ||||
| #include <iostream> | ||||
|  | ||||
| auto main() -> int { | ||||
|     // Create the template class with optional a type (e.g. uint32_t) and a boolean | ||||
|     // if you want enable debug mode (AStar::AStar<uint32_t, true>) | ||||
|     AStar::AStar pathFinder; | ||||
|  | ||||
|     // Define the map size (width, height) | ||||
|     pathFinder.setWorldSize({10, 10}); | ||||
|  | ||||
|     // Set the heuristic function (manhattan, euclidean, octagonal etc...), it is optional, default is euclidean | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::manhattan); | ||||
|  | ||||
|     // if you want to enable diagonal movement, it is optional, default is false | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     // Add a obstacle point (5, 5) and (5, 6) | ||||
|     pathFinder.addObstacle({5, 5}); | ||||
|     pathFinder.addObstacle({5, 6}); | ||||
|  | ||||
|     // Find the path from (0, 0) to (9, 9), it it equal to 0, then the path is not found | ||||
|     auto path = pathFinder.findPath({0, 0}, {9, 9}); | ||||
|  | ||||
|     // Print the path | ||||
|     for (auto& p : path) { | ||||
|         std::cout << p.x << " " << p.y << std::endl; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										36
									
								
								example/basic_fast_example.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										36
									
								
								example/basic_fast_example.cpp
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| #include <astar/astar.hpp> | ||||
| #include <iostream> | ||||
|  | ||||
| auto main() -> int { | ||||
|     // Create the template class with optional a type (e.g. uint32_t) and a boolean | ||||
|     // if you want enable debug mode (AStar::AStar<uint32_t, true>) | ||||
|     AStar::AStarFast pathFinder; | ||||
|  | ||||
|     // Set the heuristic function (manhattan, euclidean, octagonal etc...), it is optional, default is euclidean | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::manhattan); | ||||
|  | ||||
|     // if you want to enable diagonal movement, it is optional, default is false | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     // Create world 9x9 filled with 0 | ||||
|     std::vector<uint32_t> world(9 * 9, 0); | ||||
|  | ||||
|     // set lambda function to check if is an obstacle (value == 1) | ||||
|     auto isObstacle = [](uint32_t value) -> bool { return value == 1; }; | ||||
|     pathFinder.setObstacle(isObstacle); | ||||
|  | ||||
|     // Add a obstacle point (5, 5) and (5, 6) | ||||
|     world[5 + 5 * 9] = 1; | ||||
|     world[5 + 6 * 9] = 1; | ||||
|  | ||||
|     // Find the path from (0, 0) to (9, 9), it it equal to 0, then the path is not found | ||||
|     // This version of findPath() is faster due direct access to the world | ||||
|     auto path = pathFinder.findPath({0, 0}, {9, 9}, world, {9, 9}); | ||||
|  | ||||
|     // Print the path | ||||
|     for (auto& p : path) { | ||||
|         std::cout << p.x << " " << p.y << std::endl; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										43
									
								
								example/debug_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								example/debug_example.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| #include <iostream> | ||||
|  | ||||
| #include <astar/astar.hpp> | ||||
|  | ||||
| auto main() -> int { | ||||
|     // Enable debug mode with template argument, this helps avoid performance issues on non-debug classes | ||||
|     AStar::AStar<uint32_t, true> pathFinder; | ||||
|  | ||||
|     // Set lambda function to debug current node | ||||
|     std::function<void(const AStar::Node<uint32_t>* node)> debugCurrentNode = [](const AStar::Node<uint32_t>* node) { | ||||
|         std::cout << "Current node: " << node->pos.x << ", " << node->pos.y << std::endl; | ||||
|     }; | ||||
|     pathFinder.setDebugCurrentNode(debugCurrentNode); | ||||
|  | ||||
|     // Set lambda function to debug open node | ||||
|     std::function<void(const AStar::Node<uint32_t>* node)> debugOpenNode = [](const AStar::Node<uint32_t>* node) { | ||||
|         std::cout << "Add to open list: " << node->pos.x << ", " << node->pos.y << std::endl; | ||||
|     }; | ||||
|     pathFinder.setDebugOpenNode(debugOpenNode); | ||||
|  | ||||
|     // Define the map size (width, height) | ||||
|     pathFinder.setWorldSize({10, 10}); | ||||
|  | ||||
|     // Set the heuristic function (manhattan, euclidean, octagonal etc...), it is optional, default is euclidean | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::manhattan); | ||||
|  | ||||
|     // if you want to enable diagonal movement, it is optional, default is false | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     // Add a obstacle point (5, 5) and (5, 6) | ||||
|     pathFinder.addObstacle({5, 5}); | ||||
|     pathFinder.addObstacle({5, 6}); | ||||
|  | ||||
|     // Find the path from (0, 0) to (9, 9) | ||||
|     auto path = pathFinder.findPath({0, 0}, {9, 9}); | ||||
|  | ||||
|     // Print the path | ||||
|     for (auto& p : path) { | ||||
|         std::cout << p.x << " " << p.y << std::endl; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										360
									
								
								include/astar/astar.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								include/astar/astar.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,360 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <cmath> | ||||
| #include <concepts> | ||||
| #include <cstdint> | ||||
| #include <functional> | ||||
| #include <iostream> | ||||
| #include <memory> | ||||
| #include <queue> | ||||
| #include <string> | ||||
| #include <unordered_map> | ||||
| #include <unordered_set> | ||||
| #include <vector> | ||||
|  | ||||
| template <typename T> | ||||
| concept ArithmeticType = std::is_arithmetic<T>::value; | ||||
|  | ||||
| template <typename T> | ||||
| concept IntegerType = std::is_integral<T>::value; | ||||
|  | ||||
| template <typename T> | ||||
| concept FloatingPointType = std::is_floating_point<T>::value; | ||||
|  | ||||
| namespace AStar { | ||||
|  | ||||
| template <IntegerType T = int32_t> | ||||
| class Vec2 { | ||||
|    public: | ||||
|     Vec2() = default; | ||||
|     Vec2(T x_, T y_) : x(x_), y(y_) {} | ||||
|  | ||||
|     bool operator==(const Vec2& pos) const noexcept { return (x == pos.x && y == pos.y); } | ||||
|     Vec2 operator=(const Vec2& pos) noexcept { | ||||
|         x = pos.x; | ||||
|         y = pos.y; | ||||
|         return *this; | ||||
|     } | ||||
|     Vec2 operator+(const Vec2& pos) noexcept { return {x + pos.x, y + pos.y}; } | ||||
|     Vec2 operator-(const Vec2& pos) noexcept { return {x - pos.x, y - pos.y}; } | ||||
|     Vec2 operator*(const Vec2& pos) noexcept { return {x * pos.x, y * pos.y}; } | ||||
|     Vec2 operator/(const Vec2& pos) noexcept { return {x / pos.x, y / pos.y}; } | ||||
|     struct hash { | ||||
|         size_t operator()(const Vec2& pos) const noexcept { return std::hash<size_t>()(pos.x ^ (pos.y << 4)); } | ||||
|     }; | ||||
|  | ||||
|     T x = 0; | ||||
|     T y = 0; | ||||
| }; | ||||
| typedef Vec2<int32_t> Vec2i; | ||||
|  | ||||
| template <IntegerType T = uint32_t> | ||||
| class Node { | ||||
|    public: | ||||
|     explicit Node() : pos(Vec2i(0, 0)), parentNode(nullptr) {} | ||||
|     explicit Node(const Vec2i& pos, Node* parent = nullptr) : pos(pos), parentNode(parent) {} | ||||
|     explicit Node(const Vec2i& pos, const T pathCost, const T heuristicCost, Node* parent = nullptr) | ||||
|         : pathCost(pathCost), heuristicCost(heuristicCost), pos(pos), parentNode(parent) {} | ||||
|     inline T getTotalCost() const noexcept { return pathCost + heuristicCost; } | ||||
|     struct hash { | ||||
|         size_t operator()(const Node* node) const noexcept { return std::hash<size_t>()(node->pos.x ^ (node->pos.y << 4)); } | ||||
|     }; | ||||
|  | ||||
|     T pathCost = 0; | ||||
|     T heuristicCost = 0; | ||||
|     Vec2i pos = {0, 0}; | ||||
|     Node* parentNode = nullptr; | ||||
| }; | ||||
|  | ||||
| namespace Heuristic { | ||||
| static inline Vec2i deltaVec(const Vec2i& source, const Vec2i& target) noexcept { | ||||
|     return {std::abs(source.x - target.x), std::abs(source.y - target.y)}; | ||||
| } | ||||
|  | ||||
| static inline uint32_t manhattan(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept { | ||||
|     auto delta = deltaVec(source, target); | ||||
|     return weight * (delta.x + delta.y); | ||||
| } | ||||
|  | ||||
| static inline uint32_t octagonal(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept { | ||||
|     auto delta = deltaVec(source, target); | ||||
|     return weight * (delta.x + delta.y) + (-6) * std::min(delta.x, delta.y); | ||||
| } | ||||
|  | ||||
| static inline uint32_t euclidean(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept { | ||||
|     auto delta = deltaVec(source, target); | ||||
|     return weight * static_cast<uint32_t>(std::sqrt(std::pow(delta.x, 2) + std::pow(delta.y, 2))); | ||||
| } | ||||
|  | ||||
| static inline uint32_t chebyshev(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept { | ||||
|     auto delta = deltaVec(source, target); | ||||
|     return weight * std::max(delta.x, delta.y); | ||||
| } | ||||
|  | ||||
| static inline uint32_t euclideanNoSQR(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept { | ||||
|     auto delta = deltaVec(source, target); | ||||
|     return weight * static_cast<uint32_t>(std::pow(delta.x, 2) + std::pow(delta.y, 2)); | ||||
| } | ||||
|  | ||||
| static constexpr uint32_t dijkstra([[maybe_unused]] const Vec2i& source, | ||||
|                                    [[maybe_unused]] const Vec2i& target, | ||||
|                                    const uint32_t weight = 0) noexcept { | ||||
|     return 0; | ||||
| } | ||||
| };  // namespace Heuristic | ||||
|  | ||||
| template <IntegerType T = uint32_t, bool enableDebug = false> | ||||
| class AStarVirtual { | ||||
|    public: | ||||
|     explicit AStarVirtual() | ||||
|         : _heuristicFunction(&Heuristic::euclidean), | ||||
|           _directionsCount(4), | ||||
|           _heuristicWeight(10), | ||||
|           _mouvemementCost(10), | ||||
|           _debugCurrentNode([](Node<T>*) {}), | ||||
|           _debugOpenNode([](Node<T>*) {}) { | ||||
|         _directions = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; | ||||
|     } | ||||
|     void setHeuristic(const std::function<uint32_t(Vec2i, Vec2i, uint32_t)>& heuristic) { | ||||
|         _heuristicFunction = std::bind(heuristic, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); | ||||
|     } | ||||
|     std::function<uint32_t(Vec2i, Vec2i, uint32_t)>& getHeuristic() noexcept { return _heuristicFunction; } | ||||
|  | ||||
|     void setHeuristicWeight(const uint32_t weight) noexcept { _heuristicWeight = weight; } | ||||
|     uint32_t getHeuristicWeight() const noexcept { return _heuristicWeight; } | ||||
|  | ||||
|     void setDiagonalMovement(const bool enableDiagonalMovement) noexcept { | ||||
|         _directionsCount = (enableDiagonalMovement ? _directions.size() : _directions.size() / 2); | ||||
|     } | ||||
|  | ||||
|     void setMouvemementCost(const size_t cost) noexcept { _mouvemementCost = cost; } | ||||
|     size_t getMouvemementCost() const noexcept { return _mouvemementCost; } | ||||
|  | ||||
|     void setCustomDirections(const std::vector<Vec2i>& directions) noexcept { | ||||
|         _directions = directions; | ||||
|         _directionsCount = static_cast<size_t>(directions.size()); | ||||
|     } | ||||
|  | ||||
|     std::vector<Vec2i>& getDirections() noexcept { return _directions; } | ||||
|  | ||||
|     void setDebugCurrentNode(const std::function<void(Node<T>*)>& debugCurrentNode) noexcept { _debugCurrentNode = debugCurrentNode; } | ||||
|     void setDebugOpenNode(const std::function<void(Node<T>*)>& debugOpenNode) noexcept { _debugOpenNode = debugOpenNode; } | ||||
|  | ||||
|    protected: | ||||
|     std::function<uint32_t(Vec2i, Vec2i, uint32_t)> _heuristicFunction; | ||||
|     std::vector<Vec2i> _directions; | ||||
|     size_t _directionsCount; | ||||
|     T _heuristicWeight; | ||||
|     size_t _mouvemementCost = 10; | ||||
|  | ||||
|     // Only used if enableDebug is true | ||||
|     std::function<void(Node<T>*)> _debugCurrentNode; | ||||
|     std::function<void(Node<T>*)> _debugOpenNode; | ||||
| }; | ||||
|  | ||||
| template <IntegerType T = uint32_t, bool enableDebug = false> | ||||
| class AStar final : public AStarVirtual<T, enableDebug> { | ||||
|    public: | ||||
|     explicit AStar() {} | ||||
|  | ||||
|     std::vector<Vec2i> findPath(const Vec2i source, const Vec2i& target) { | ||||
|         if (target.x < 0 || target.x >= _worldSize.x || target.y < 0 || target.y >= _worldSize.y) { | ||||
|             return {}; | ||||
|         } | ||||
|  | ||||
|         Node<T>* currentNode = nullptr; | ||||
|  | ||||
|         auto compareFn = [](const Node<T>* a, const Node<T>* b) { return a->getTotalCost() > b->getTotalCost(); }; | ||||
|         std::priority_queue<Node<T>*, std::vector<Node<T>*>, decltype(compareFn)> openNodeVecPQueue = | ||||
|             std::priority_queue<Node<T>*, std::vector<Node<T>*>, decltype(compareFn)>(compareFn); | ||||
|  | ||||
|         std::unordered_map<Vec2i, Node<T>*, Vec2i::hash> openNodeMap; | ||||
|         std::unordered_map<Vec2i, Node<T>*, Vec2i::hash> closedNodeMap; | ||||
|  | ||||
|         openNodeVecPQueue.push(new Node<T>(source)); | ||||
|         openNodeMap.insert({source, openNodeVecPQueue.top()}); | ||||
|  | ||||
|         while (!openNodeVecPQueue.empty()) { | ||||
|             currentNode = openNodeVecPQueue.top(); | ||||
|  | ||||
|             if constexpr (enableDebug) { | ||||
|                 AStarVirtual<T, enableDebug>::_debugCurrentNode(currentNode); | ||||
|             } | ||||
|  | ||||
|             if (currentNode->pos == target) { | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             openNodeVecPQueue.pop(); | ||||
|             openNodeMap.erase(currentNode->pos); | ||||
|             closedNodeMap.insert({currentNode->pos, currentNode}); | ||||
|  | ||||
|             for (size_t i = 0; i < AStarVirtual<T, enableDebug>::_directionsCount; ++i) { | ||||
|                 Vec2i newPos = currentNode->pos + AStarVirtual<T, enableDebug>::_directions[i]; | ||||
|  | ||||
|                 if (_obstacles.contains(newPos)) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (closedNodeMap.contains(newPos)) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (newPos.x < 0 || newPos.x >= _worldSize.x || newPos.y < 0 || newPos.y >= _worldSize.y) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 T nextCost = currentNode->pathCost + AStarVirtual<T, enableDebug>::_mouvemementCost; | ||||
|                 Node<T>* nextNode = openNodeMap.find(newPos) != openNodeMap.end() ? openNodeMap[newPos] : nullptr; | ||||
|  | ||||
|                 if (nextNode == nullptr) { | ||||
|                     nextNode = new Node<T>(newPos, currentNode); | ||||
|                     nextNode->pathCost = nextCost; | ||||
|                     nextNode->heuristicCost = static_cast<T>(AStarVirtual<T, enableDebug>::_heuristicFunction( | ||||
|                         nextNode->pos, target, AStarVirtual<T, enableDebug>::_heuristicWeight)); | ||||
|                     openNodeVecPQueue.push(nextNode); | ||||
|                     openNodeMap.insert({nextNode->pos, nextNode}); | ||||
|                 } else if (nextCost < nextNode->pathCost) { | ||||
|                     nextNode->parentNode = currentNode; | ||||
|                     nextNode->pathCost = nextCost; | ||||
|                 } | ||||
|  | ||||
|                 if constexpr (enableDebug) { | ||||
|                     AStarVirtual<T, enableDebug>::_debugOpenNode(nextNode); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         std::vector<Vec2i> path; | ||||
|  | ||||
|         if (currentNode->pos == target) [[likely]] { | ||||
|             path.reserve(currentNode->getTotalCost() / 10); | ||||
|             while (currentNode != nullptr) { | ||||
|                 path.push_back(currentNode->pos); | ||||
|                 currentNode = currentNode->parentNode; | ||||
|             } | ||||
|         } | ||||
|         for (auto& [key, value] : openNodeMap) { | ||||
|             delete value; | ||||
|         } | ||||
|  | ||||
|         for (auto& [key, value] : closedNodeMap) { | ||||
|             delete value; | ||||
|         } | ||||
|  | ||||
|         return path; | ||||
|     } | ||||
|  | ||||
|     void addObstacle(const Vec2i& pos) { _obstacles.insert(pos); } | ||||
|     void removeObstacle(const Vec2i& pos) { _obstacles.erase(pos); } | ||||
|     std::unordered_set<Vec2i, Vec2i::hash>& getObstacles() noexcept { return _obstacles; } | ||||
|  | ||||
|     void clear() { _obstacles.clear(); } | ||||
|     void setWorldSize(const Vec2i& worldSize_) noexcept { _worldSize = worldSize_; } | ||||
|  | ||||
|    private: | ||||
|     std::unordered_set<Vec2i, Vec2i::hash> _obstacles; | ||||
|     Vec2i _worldSize = {0, 0}; | ||||
| }; | ||||
|  | ||||
| // Fast AStar are faster than normal AStar but use more ram and direct access to the map | ||||
| template <IntegerType T = uint32_t, bool enableDebug = false, IntegerType U = uint32_t> | ||||
| class AStarFast final : public AStarVirtual<T, enableDebug> { | ||||
|    public: | ||||
|     explicit AStarFast() : _isObstacleFunction([](U value) { return value == 1; }) {} | ||||
|  | ||||
|     // Same as AStar::findPath() but use direct access to the map | ||||
|     std::vector<Vec2i> findPath(const Vec2i& source, const Vec2i& target, const std::vector<U>& map, const Vec2i& worldSize) { | ||||
|         if (target.x < 0 || target.x >= worldSize.x || target.y < 0 || target.y >= worldSize.y) { | ||||
|             return {}; | ||||
|         } | ||||
|  | ||||
|         Node<T>* currentNode = nullptr; | ||||
|  | ||||
|         auto compareFn = [](const Node<T>* a, const Node<T>* b) { return a->getTotalCost() > b->getTotalCost(); }; | ||||
|         std::priority_queue<Node<T>*, std::vector<Node<T>*>, decltype(compareFn)> openNodeVecPQueue = | ||||
|             std::priority_queue<Node<T>*, std::vector<Node<T>*>, decltype(compareFn)>(compareFn); | ||||
|         std::unordered_map<Vec2i, Node<T>*, Vec2i::hash> openNodeMap; | ||||
|         std::unordered_map<Vec2i, Node<T>*, Vec2i::hash> closedNodeMap; | ||||
|  | ||||
|         openNodeVecPQueue.push(new Node<T>(source)); | ||||
|         openNodeMap.insert({source, openNodeVecPQueue.top()}); | ||||
|  | ||||
|         while (!openNodeVecPQueue.empty()) { | ||||
|             currentNode = openNodeVecPQueue.top(); | ||||
|  | ||||
|             if constexpr (enableDebug) { | ||||
|                 AStarVirtual<T, enableDebug>::_debugCurrentNode(currentNode); | ||||
|             } | ||||
|  | ||||
|             if (currentNode->pos == target) { | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             openNodeVecPQueue.pop(); | ||||
|             openNodeMap.erase(currentNode->pos); | ||||
|             closedNodeMap.insert({currentNode->pos, currentNode}); | ||||
|  | ||||
|             for (size_t i = 0; i < AStarVirtual<T, enableDebug>::_directionsCount; ++i) { | ||||
|                 Vec2i newPos = currentNode->pos + AStarVirtual<T, enableDebug>::_directions[i]; | ||||
|  | ||||
|                 if (_isObstacleFunction(map[newPos.x + newPos.y * worldSize.x])) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (closedNodeMap.contains(newPos)) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (newPos.x < 0 || newPos.x >= worldSize.x || newPos.y < 0 || newPos.y >= worldSize.y) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 T nextCost = currentNode->pathCost + AStarVirtual<T, enableDebug>::_mouvemementCost; | ||||
|                 Node<T>* nextNode = openNodeMap.find(newPos) != openNodeMap.end() ? openNodeMap[newPos] : nullptr; | ||||
|                 if (nextNode == nullptr) { | ||||
|                     nextNode = new Node<T>(newPos, currentNode); | ||||
|                     nextNode->pathCost = nextCost; | ||||
|                     nextNode->heuristicCost = static_cast<T>(AStarVirtual<T, enableDebug>::_heuristicFunction( | ||||
|                         nextNode->pos, target, AStarVirtual<T, enableDebug>::_heuristicWeight)); | ||||
|                     openNodeVecPQueue.push(nextNode); | ||||
|                     openNodeMap.insert({nextNode->pos, nextNode}); | ||||
|                 } else if (nextCost < nextNode->pathCost) [[likely]] { | ||||
|                     nextNode->parentNode = currentNode; | ||||
|                     nextNode->pathCost = nextCost; | ||||
|                 } | ||||
|  | ||||
|                 if constexpr (enableDebug) { | ||||
|                     AStarVirtual<T, enableDebug>::_debugOpenNode(nextNode); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         std::vector<Vec2i> path; | ||||
|  | ||||
|         if (currentNode->pos == target) [[likely]] { | ||||
|             path.reserve(currentNode->getTotalCost() / 10); | ||||
|             while (currentNode != nullptr) { | ||||
|                 path.push_back(currentNode->pos); | ||||
|                 currentNode = currentNode->parentNode; | ||||
|             } | ||||
|         } | ||||
|         for (auto& [key, value] : openNodeMap) { | ||||
|             delete value; | ||||
|         } | ||||
|  | ||||
|         for (auto& [key, value] : closedNodeMap) { | ||||
|             delete value; | ||||
|         } | ||||
|  | ||||
|         return path; | ||||
|     } | ||||
|     void setObstacle(const std::function<bool(U)>& isObstacleFunction) noexcept { _isObstacleFunction = isObstacleFunction; } | ||||
|     std::function<bool(U)>& getObstacle() noexcept { return _isObstacleFunction; } | ||||
|  | ||||
|    private: | ||||
|     std::function<bool(U)> _isObstacleFunction; | ||||
| }; | ||||
|  | ||||
| }  // namespace AStar | ||||
							
								
								
									
										
											BIN
										
									
								
								resources/Screenshot_20240128_093812.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/Screenshot_20240128_093812.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 59 KiB | 
							
								
								
									
										82
									
								
								test/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								test/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
|  | ||||
| project(astarTests LANGUAGES C CXX) | ||||
|  | ||||
| include(../cmake/project-is-top-level.cmake) | ||||
| include(../cmake/folders.cmake) | ||||
|  | ||||
| # ---- Dependencies ---- | ||||
|  | ||||
| if(PROJECT_IS_TOP_LEVEL) | ||||
|   find_package(astar REQUIRED) | ||||
|   enable_testing() | ||||
| endif() | ||||
|  | ||||
|  | ||||
| function(test_bench_generator TEST_BENCH_NAME IS_TEST ADD_TO_TEST) | ||||
|   if (IS_TEST) | ||||
|     add_executable("${TEST_BENCH_NAME}" "source/test/${TEST_BENCH_NAME}.cpp" source/generator/generator.cpp source/generator/generator.hpp) | ||||
|   else() | ||||
|     add_executable("${TEST_BENCH_NAME}" "source/benchmark/${TEST_BENCH_NAME}.cpp" source/generator/generator.cpp source/generator/generator.hpp) | ||||
|   endif() | ||||
|  | ||||
|  | ||||
|   if (IS_TEST) | ||||
|     target_link_libraries("${TEST_BENCH_NAME}" PRIVATE gtest) | ||||
|   else() | ||||
|     target_link_libraries("${TEST_BENCH_NAME}" PRIVATE benchmark::benchmark) | ||||
|   endif() | ||||
|  | ||||
|   target_link_libraries("${TEST_BENCH_NAME}" PRIVATE astar::astar) | ||||
|   target_link_libraries("${TEST_BENCH_NAME}" PRIVATE raylib) | ||||
|   target_link_libraries("${TEST_BENCH_NAME}" PRIVATE FastNoise2) | ||||
|   #target_link_libraries("${TEST_BENCH_NAME}" PRIVATE spdlog::spdlog nlohmann_json::nlohmann_json) | ||||
|  | ||||
|   #if (OpenMP_FOUND OR OpenMP_CXX_FOUND) | ||||
|   #  target_link_libraries("${TEST_BENCH_NAME}" PRIVATE OpenMP::OpenMP_CXX) | ||||
|   #endif() | ||||
|  | ||||
|   set_target_properties("${TEST_BENCH_NAME}" | ||||
|     PROPERTIES | ||||
|     RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|     LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|     ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" | ||||
|     PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" | ||||
|   ) | ||||
|  | ||||
|   #if(NOT CMAKE_BUILD_TYPE MATCHES Debug AND NOT CMAKE_BUILD_TYPE MATCHES Coverage) | ||||
|   #  add_test(NAME "${TEST_BENCH_NAME}" COMMAND $<TARGET_FILE:${TEST_BENCH_NAME}>) | ||||
|   #elseif() | ||||
|   #  message(STATUS "Disable ${BENCH_NAME}, Performance benchmark test only run on Release/RelWithDebInfo/MinSizeRel") | ||||
|   #endif() | ||||
|  | ||||
|   if (ADD_TO_TEST) | ||||
|       add_test(NAME "${TEST_BENCH_NAME}" COMMAND $<TARGET_FILE:${TEST_BENCH_NAME}>) | ||||
|   endif() | ||||
|   target_compile_features("${TEST_BENCH_NAME}" PRIVATE cxx_std_20) | ||||
| endfunction() | ||||
|  | ||||
| # ---- Tests ---- | ||||
|  | ||||
| if(NOT WIN32) | ||||
|   include(../cmake/lib/gtest.cmake) | ||||
|   include(../cmake/lib/benchmark.cmake) | ||||
|   #include(../cmake/lib/openmp.cmake) | ||||
|   include(../cmake/lib/raygui.cmake) | ||||
|  | ||||
|   include(../cmake/lib/raylib.cmake) | ||||
|   include(../cmake/lib/fast_noise2.cmake) | ||||
|   #include(../cmake/lib/spdlog.cmake) | ||||
|   #include(../cmake/lib/json.cmake) | ||||
|   include(../cmake/utile/ccache.cmake) | ||||
|  | ||||
|   include_directories(source) | ||||
|  | ||||
|   test_bench_generator(astar_test true true) | ||||
|   test_bench_generator(astar_bench false true) | ||||
|   test_bench_generator(path_finder false false) | ||||
| endif() | ||||
|  | ||||
| # ---- End-of-file commands ---- | ||||
|  | ||||
| add_folders(Test) | ||||
							
								
								
									
										195
									
								
								test/source/benchmark/astar_bench.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								test/source/benchmark/astar_bench.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | ||||
| #include <array> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| #include <vector> | ||||
|  | ||||
| #include <benchmark/benchmark.h> | ||||
| #include "astar/astar.hpp" | ||||
| #include "generator/generator.hpp" | ||||
|  | ||||
| static constexpr int64_t multiplier = 4; | ||||
| static constexpr int64_t minRange = 16; | ||||
| static constexpr int64_t maxRange = 256; | ||||
| static constexpr int64_t minThreadRange = 1; | ||||
| static constexpr int64_t maxThreadRange = 1; | ||||
| static constexpr int64_t repetitions = 1; | ||||
|  | ||||
| static void DoSetup([[maybe_unused]] const benchmark::State& state) {} | ||||
|  | ||||
| static void DoTeardown([[maybe_unused]] const benchmark::State& state) {} | ||||
|  | ||||
| template <IntegerType T> | ||||
| static void astar_bench(benchmark::State& state) { | ||||
|     auto range = state.range(0); | ||||
|  | ||||
|     int mapWidth = range; | ||||
|     int mapHeight = range; | ||||
|  | ||||
|     float lacunarity = 1.6f; | ||||
|     float octaves = 6; | ||||
|     float gain = 3.5f; | ||||
|     float frequency = 1.7f; | ||||
|     float weightedStrength = 0.034f; | ||||
|     float multiplier = 118; | ||||
|  | ||||
|     Generator generator(-972960945); | ||||
|     benchmark::DoNotOptimize(generator); | ||||
|     generator.setLacunarity(lacunarity); | ||||
|     generator.setOctaves((uint32_t)octaves); | ||||
|     generator.setGain(gain); | ||||
|     generator.setFrequency(frequency); | ||||
|     generator.setWeightedStrength(weightedStrength); | ||||
|     generator.setMultiplier((uint32_t)multiplier); | ||||
|  | ||||
|     std::vector<uint32_t> heightmap = generator.generate2dMeightmap(0, 0, 0, mapWidth, 0, mapHeight); | ||||
|     benchmark::DoNotOptimize(heightmap); | ||||
|  | ||||
|     std::vector<uint8_t> blocks = std::vector<uint8_t>(mapWidth * mapHeight, 0); | ||||
|     benchmark::DoNotOptimize(blocks); | ||||
|  | ||||
|     AStar::AStar<T, false> pathFinder; | ||||
|     benchmark::DoNotOptimize(pathFinder); | ||||
|     pathFinder.setWorldSize({mapWidth, mapHeight}); | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::euclidean); | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     for (uint64_t x = 0; x < mapWidth; x++) { | ||||
|         for (uint64_t y = 0; y < mapHeight; y++) { | ||||
|             uint64_t index = x + y * mapWidth; | ||||
|             uint8_t value = static_cast<uint8_t>(heightmap[index]); | ||||
|  | ||||
|             if (value < 128) { | ||||
|                 blocks[index] = 0; | ||||
|             } else { | ||||
|                 blocks[index] = 1; | ||||
|                 pathFinder.addObstacle({static_cast<int32_t>(x), static_cast<int32_t>(y)}); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     blocks[0] = 0; | ||||
|     pathFinder.removeObstacle({0, 0}); | ||||
|     blocks[mapWidth * mapHeight - 1] = 0; | ||||
|     pathFinder.removeObstacle({mapWidth - 1, mapHeight - 1}); | ||||
|  | ||||
|     AStar::Vec2i source(0, 0); | ||||
|     AStar::Vec2i target(mapWidth - 1, mapHeight - 1); | ||||
|  | ||||
|     std::vector<AStar::Vec2i> path; | ||||
|     benchmark::DoNotOptimize(path); | ||||
|  | ||||
|     for (auto _ : state) { | ||||
|         path = pathFinder.findPath(source, target); | ||||
|         state.PauseTiming(); | ||||
|         if (path.size() == 0) { | ||||
|             state.SkipWithError("No path found"); | ||||
|         } | ||||
|         state.ResumeTiming(); | ||||
|  | ||||
|         benchmark::ClobberMemory(); | ||||
|     } | ||||
|     state.SetItemsProcessed(state.iterations()); | ||||
|     state.SetBytesProcessed(state.iterations() * sizeof(path)); | ||||
| } | ||||
|  | ||||
| BENCHMARK(astar_bench<uint32_t>) | ||||
|     ->Name("astar_bench<uint32_t>") | ||||
|     ->RangeMultiplier(multiplier) | ||||
|     ->Range(minRange, maxRange) | ||||
|     ->ThreadRange(minThreadRange, maxThreadRange) | ||||
|     ->Unit(benchmark::kNanosecond) | ||||
|     ->Setup(DoSetup) | ||||
|     ->Teardown(DoTeardown) | ||||
|     ->MeasureProcessCPUTime() | ||||
|     ->UseRealTime() | ||||
|     ->Repetitions(repetitions); | ||||
|  | ||||
| template <IntegerType T> | ||||
| static void astar_bench_fast(benchmark::State& state) { | ||||
|     auto range = state.range(0); | ||||
|  | ||||
|     int mapWidth = range; | ||||
|     int mapHeight = range; | ||||
|  | ||||
|     float lacunarity = 1.6f; | ||||
|     float octaves = 6; | ||||
|     float gain = 3.5f; | ||||
|     float frequency = 1.7f; | ||||
|     float weighted_strength = 0.034f; | ||||
|     float multiplier = 118; | ||||
|  | ||||
|     Generator generator(-972960945); | ||||
|     benchmark::DoNotOptimize(generator); | ||||
|     generator.setLacunarity(lacunarity); | ||||
|     generator.setOctaves((uint32_t)octaves); | ||||
|     generator.setGain(gain); | ||||
|     generator.setFrequency(frequency); | ||||
|     generator.setWeightedStrength(0.0f); | ||||
|     generator.setMultiplier((uint32_t)multiplier); | ||||
|  | ||||
|     std::vector<uint32_t> heightmap = generator.generate2dMeightmap(0, 0, 0, mapWidth, 0, mapHeight); | ||||
|     benchmark::DoNotOptimize(heightmap); | ||||
|  | ||||
|     std::vector<uint32_t> blocks = std::vector<uint32_t>(mapWidth * mapHeight, 0); | ||||
|     benchmark::DoNotOptimize(blocks); | ||||
|  | ||||
|     AStar::AStarFast<T, false, uint32_t> pathFinder; | ||||
|     benchmark::DoNotOptimize(pathFinder); | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::euclidean); | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     for (uint64_t x = 0; x < mapWidth; x++) { | ||||
|         for (uint64_t y = 0; y < mapHeight; y++) { | ||||
|             uint64_t index = x + y * mapWidth; | ||||
|             uint8_t value = static_cast<uint8_t>(heightmap[index]); | ||||
|  | ||||
|             if (value < 128) { | ||||
|                 blocks[index] = 0; | ||||
|             } else { | ||||
|                 blocks[index] = 1; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     blocks[0] = 0; | ||||
|     blocks[mapWidth * mapHeight - 1] = 0; | ||||
|  | ||||
|     AStar::Vec2i source(0, 0); | ||||
|     AStar::Vec2i target(mapWidth - 1, mapHeight - 1); | ||||
|  | ||||
|     std::vector<AStar::Vec2i> path; | ||||
|     benchmark::DoNotOptimize(path); | ||||
|  | ||||
|     for (auto _ : state) { | ||||
|         path = pathFinder.findPath(source, target, blocks, {mapWidth, mapHeight}); | ||||
|         state.PauseTiming(); | ||||
|         if (path.size() == 0) { | ||||
|             state.SkipWithError("No path found"); | ||||
|         } | ||||
|         state.ResumeTiming(); | ||||
|  | ||||
|         benchmark::ClobberMemory(); | ||||
|     } | ||||
|     state.SetItemsProcessed(state.iterations()); | ||||
|     state.SetBytesProcessed(state.iterations() * sizeof(path)); | ||||
| } | ||||
|  | ||||
| BENCHMARK(astar_bench_fast<uint32_t>) | ||||
|     ->Name("astar_bench_fast<uint32_t>") | ||||
|     ->RangeMultiplier(multiplier) | ||||
|     ->Range(minRange, maxRange) | ||||
|     ->ThreadRange(minThreadRange, maxThreadRange) | ||||
|     ->Unit(benchmark::kNanosecond) | ||||
|     ->Setup(DoSetup) | ||||
|     ->Teardown(DoTeardown) | ||||
|     ->MeasureProcessCPUTime() | ||||
|     ->UseRealTime() | ||||
|     ->Repetitions(repetitions); | ||||
|  | ||||
| // Run the benchmark | ||||
| // BENCHMARK_MAIN(); | ||||
|  | ||||
| int main(int argc, char** argv) { | ||||
|     ::benchmark::Initialize(&argc, argv); | ||||
|     ::benchmark::RunSpecifiedBenchmarks(); | ||||
| } | ||||
							
								
								
									
										258
									
								
								test/source/benchmark/path_finder.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								test/source/benchmark/path_finder.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,258 @@ | ||||
| #include <array>     // std::array | ||||
| #include <chrono>    // std::chrono::system_clock | ||||
| #include <cmath>     // std::abs | ||||
| #include <cstdint>   // std::uint32_t | ||||
| #include <iostream>  // std::cout, std::endl | ||||
| #include <map>       // std::map | ||||
| #include <memory>    // std::unique_ptr | ||||
| #include <random>    // std::random_device, std::mt19937, std::uniform_int_distribution | ||||
| #include <vector>    // std::vector | ||||
|  | ||||
| #include "astar/astar.hpp" | ||||
| #include "generator/generator.hpp" | ||||
|  | ||||
| #include "raylib.h" | ||||
|  | ||||
| #define RAYGUI_IMPLEMENTATION | ||||
| extern "C" { | ||||
| #include "src/raygui.h" | ||||
| } | ||||
|  | ||||
| auto main() -> int { | ||||
|     // Set log level for Raylib | ||||
|     SetTraceLogLevel(LOG_WARNING); | ||||
|  | ||||
|     const int screenWidth = 1920; | ||||
|     const int screenHeight = 1080; | ||||
|  | ||||
|     const int mapWidth = 192; | ||||
|     const int mapHeight = 108; | ||||
|  | ||||
|     const uint32_t targetFPS = 120; | ||||
|  | ||||
|     const uint32_t ImageUpdatePerSecond = 30; | ||||
|  | ||||
|     SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_MSAA_4X_HINT); | ||||
|     InitWindow(screenWidth, screenHeight, "Path finder by Bensuperpc"); | ||||
|  | ||||
|     SetTargetFPS(targetFPS); | ||||
|  | ||||
|     float lacunarity = 1.6f; | ||||
|     float octaves = 6; | ||||
|     float gain = 3.5f; | ||||
|     float frequency = 1.7f; | ||||
|     float weighted_strength = 0.034f; | ||||
|     float multiplier = 118; | ||||
|  | ||||
|     Generator generator_2(-972960945); | ||||
|     generator_2.setLacunarity(lacunarity); | ||||
|     generator_2.setOctaves((uint32_t)octaves); | ||||
|     generator_2.setGain(gain); | ||||
|     generator_2.setFrequency(frequency); | ||||
|     generator_2.setWeightedStrength(0.0f); | ||||
|     generator_2.setMultiplier((uint32_t)multiplier); | ||||
|  | ||||
|     AStar::AStar<uint32_t, false> pathFinder; | ||||
|     pathFinder.setWorldSize({mapWidth, mapHeight}); | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::manhattan); | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     size_t manhattanPathSize = 0; | ||||
|     size_t euclideanPathSize = 0; | ||||
|     size_t euclideanNoSQRPathSize = 0; | ||||
|     size_t octagonalPathSize = 0; | ||||
|     size_t chebyshevPathSize = 0; | ||||
|     size_t dijkstraPathSize = 0; | ||||
|  | ||||
|     std::vector<uint32_t> heightmap; | ||||
|  | ||||
|     heightmap = generator_2.generate2dMeightmap(0, 0, 0, mapWidth, 0, mapHeight); | ||||
|  | ||||
|     std::vector<uint8_t> blocks = std::vector<uint8_t>(mapWidth * mapHeight, 0); | ||||
|  | ||||
|     uint64_t framesCounter = 0; | ||||
|  | ||||
|     bool needUpdate = true; | ||||
|  | ||||
|     while (!WindowShouldClose()) { | ||||
|         framesCounter++; | ||||
|         if (IsKeyPressed(KEY_S)) { | ||||
|             const std::string filename = "screenshot_" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count()) + ".png"; | ||||
|             TakeScreenshot(filename.c_str()); | ||||
|         } | ||||
|         if (IsKeyPressed(KEY_R)) { | ||||
|             generator_2.randomizeSeed(); | ||||
|             needUpdate = true; | ||||
|         } | ||||
|  | ||||
|         if (framesCounter % (targetFPS / ImageUpdatePerSecond) == 0) { | ||||
|             if (needUpdate) { | ||||
|                 needUpdate = false; | ||||
|                 generator_2.setLacunarity(lacunarity); | ||||
|                 generator_2.setOctaves((uint32_t)octaves); | ||||
|                 generator_2.setGain(gain); | ||||
|                 generator_2.setFrequency(frequency); | ||||
|                 generator_2.setWeightedStrength(weighted_strength); | ||||
|                 generator_2.setMultiplier((uint32_t)multiplier); | ||||
|  | ||||
|                 pathFinder.clear(); | ||||
|  | ||||
|                 heightmap = generator_2.generate2dMeightmap(0, 0, 0, screenWidth, 0, screenHeight); | ||||
|  | ||||
|                 for (uint64_t x = 0; x < mapWidth; x++) { | ||||
|                     for (uint64_t y = 0; y < mapHeight; y++) { | ||||
|                         uint64_t index = x + y * mapWidth; | ||||
|                         uint8_t value = static_cast<uint8_t>(heightmap[index]); | ||||
|  | ||||
|                         if (value < 128) { | ||||
|                             blocks[index] = 0; | ||||
|                         } else { | ||||
|                             blocks[index] = 1; | ||||
|                             pathFinder.addObstacle({static_cast<int32_t>(x), static_cast<int32_t>(y)}); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 blocks[0] = 0; | ||||
|                 pathFinder.removeObstacle({0, 0}); | ||||
|                 blocks[mapWidth * mapHeight - 1] = 0; | ||||
|                 pathFinder.removeObstacle({mapWidth - 1, mapHeight - 1}); | ||||
|  | ||||
|                 pathFinder.setHeuristic(AStar::Heuristic::manhattan); | ||||
|                 auto start1 = std::chrono::high_resolution_clock::now(); | ||||
|                 auto path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}); | ||||
|                 auto stop1 = std::chrono::high_resolution_clock::now(); | ||||
|                 if (path.empty()) { | ||||
|                     std::cout << "Path not found" << std::endl; | ||||
|                 } | ||||
|                 auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(stop1 - start1); | ||||
|                 std::cout << "Path search: " << duration1.count() << " microseconds" << std::endl; | ||||
|  | ||||
|                 manhattanPathSize = path.size(); | ||||
|                 for (auto& i : path) { | ||||
|                     uint64_t index = i.x + i.y * mapWidth; | ||||
|                     blocks[index] = 2; | ||||
|                 } | ||||
|  | ||||
|                 pathFinder.setHeuristic(AStar::Heuristic::euclidean); | ||||
|                 path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}); | ||||
|                 euclideanPathSize = path.size(); | ||||
|  | ||||
|                 for (auto& i : path) { | ||||
|                     uint64_t index = i.x + i.y * mapWidth; | ||||
|                     blocks[index] = 3; | ||||
|                 } | ||||
|  | ||||
|                 pathFinder.setHeuristic(AStar::Heuristic::octagonal); | ||||
|                 path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}); | ||||
|                 octagonalPathSize = path.size(); | ||||
|  | ||||
|                 for (auto& i : path) { | ||||
|                     uint64_t index = i.x + i.y * mapWidth; | ||||
|                     blocks[index] = 4; | ||||
|                 } | ||||
|  | ||||
|                 pathFinder.setHeuristic(AStar::Heuristic::chebyshev); | ||||
|                 path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}); | ||||
|                 chebyshevPathSize = path.size(); | ||||
|  | ||||
|                 for (auto& i : path) { | ||||
|                     uint64_t index = i.x + i.y * mapWidth; | ||||
|                     blocks[index] = 5; | ||||
|                 } | ||||
|  | ||||
|                 pathFinder.setHeuristic(AStar::Heuristic::euclideanNoSQR); | ||||
|                 path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}); | ||||
|                 euclideanNoSQRPathSize = path.size(); | ||||
|  | ||||
|                 for (auto& i : path) { | ||||
|                     uint64_t index = i.x + i.y * mapWidth; | ||||
|                     blocks[index] = 6; | ||||
|                 } | ||||
|  | ||||
|                 pathFinder.setHeuristic(AStar::Heuristic::dijkstra); | ||||
|                 path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}); | ||||
|                 dijkstraPathSize = path.size(); | ||||
|  | ||||
|                 for (auto& i : path) { | ||||
|                     uint64_t index = i.x + i.y * mapWidth; | ||||
|                     blocks[index] = 7; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         ClearBackground(RAYWHITE); | ||||
|         BeginDrawing(); | ||||
|  | ||||
|         // Draw white if blocks[index] == 0 else black | ||||
|         int size = 10; | ||||
|         for (uint64_t x = 0; x < mapWidth; x++) { | ||||
|             for (uint64_t y = 0; y < mapHeight; y++) { | ||||
|                 uint64_t index = x + y * mapWidth; | ||||
|                 if (blocks[index] == 0) { | ||||
|                     DrawRectangle(static_cast<float>(x * size), static_cast<float>(y * size), size, size, WHITE); | ||||
|                 } else if (blocks[index] == 1) { | ||||
|                     DrawRectangle(static_cast<float>(x * size), static_cast<float>(y * size), size, size, BLACK); | ||||
|                 } else if (blocks[index] == 2) { | ||||
|                     DrawRectangle(static_cast<float>(x * size), static_cast<float>(y * size), size, size, RED); | ||||
|                 } else if (blocks[index] == 3) { | ||||
|                     DrawRectangle(static_cast<float>(x * size), static_cast<float>(y * size), size, size, GREEN); | ||||
|                 } else if (blocks[index] == 4) { | ||||
|                     DrawRectangle(static_cast<float>(x * size), static_cast<float>(y * size), size, size, BLUE); | ||||
|                 } else if (blocks[index] == 5) { | ||||
|                     DrawRectangle(static_cast<float>(x * size), static_cast<float>(y * size), size, size, YELLOW); | ||||
|                 } else if (blocks[index] == 6) { | ||||
|                     DrawRectangle(static_cast<float>(x * size), static_cast<float>(y * size), size, size, ORANGE); | ||||
|                 } else if (blocks[index] == 7) { | ||||
|                     DrawRectangle(static_cast<float>(x * size), static_cast<float>(y * size), size, size, PURPLE); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // display FPS | ||||
|         DrawRectangle(screenWidth - 90, 10, 80, 20, Fade(SKYBLUE, 0.95f)); | ||||
|         DrawText(TextFormat("FPS: %02d", GetFPS()), screenWidth - 80, 15, 15, DARKGRAY); | ||||
|  | ||||
|         DrawRectangle(0, 0, 275, 200, Fade(SKYBLUE, 0.95f)); | ||||
|         DrawRectangleLines(0, 0, 275, 200, BLUE); | ||||
|         GuiSlider((Rectangle){70, 10, 165, 20}, "Lacunarity", TextFormat("%2.3f", lacunarity), &lacunarity, -0.0f, 5.0f); | ||||
|         GuiSlider((Rectangle){70, 40, 165, 20}, "Octaves", TextFormat("%2.3f", octaves), &octaves, 1, 12); | ||||
|         GuiSlider((Rectangle){70, 70, 165, 20}, "Gain", TextFormat("%2.3f", gain), &gain, -0.0f, 16.0f); | ||||
|         GuiSlider((Rectangle){70, 100, 165, 20}, "Frequency", TextFormat("%2.3f", frequency), &frequency, -0.0f, 10.0f); | ||||
|         GuiSlider((Rectangle){70, 130, 165, 20}, "Weight", TextFormat("%2.3f", weighted_strength), &weighted_strength, -5.0f, 5.0f); | ||||
|         GuiSlider((Rectangle){70, 160, 165, 20}, "Multiplier", TextFormat("%2.3f", multiplier), &multiplier, 1, 512); | ||||
|  | ||||
|         // display info each color for each heuristic | ||||
|         DrawRectangle(0, 200, 275, 190, Fade(SKYBLUE, 0.95f)); | ||||
|         DrawRectangleLines(0, 200, 275, 190, BLUE); | ||||
|  | ||||
|         std::string manhattanText = "Manhattan: " + std::to_string(manhattanPathSize); | ||||
|         DrawRectangle(10, 210, 20, 20, RED); | ||||
|         DrawText(manhattanText.c_str(), 40, 210, 20, DARKGRAY); | ||||
|  | ||||
|         std::string euclideanText = "Euclidean: " + std::to_string(euclideanPathSize); | ||||
|         DrawRectangle(10, 240, 20, 20, GREEN); | ||||
|         DrawText(euclideanText.c_str(), 40, 240, 20, DARKGRAY); | ||||
|  | ||||
|         std::string octagonalText = "Octagonal: " + std::to_string(octagonalPathSize); | ||||
|         DrawRectangle(10, 270, 20, 20, BLUE); | ||||
|         DrawText(octagonalText.c_str(), 40, 270, 20, DARKGRAY); | ||||
|  | ||||
|         std::string chebyshevText = "Chebyshev: " + std::to_string(chebyshevPathSize); | ||||
|         DrawRectangle(10, 300, 20, 20, YELLOW); | ||||
|         DrawText(chebyshevText.c_str(), 40, 300, 20, DARKGRAY); | ||||
|  | ||||
|         std::string euclideanNoSQRText = "EuclideanNoSQR: " + std::to_string(euclideanNoSQRPathSize); | ||||
|         DrawRectangle(10, 330, 20, 20, ORANGE); | ||||
|         DrawText(euclideanNoSQRText.c_str(), 40, 330, 20, DARKGRAY); | ||||
|  | ||||
|         std::string dijkstraText = "Dijkstra: " + std::to_string(dijkstraPathSize); | ||||
|         DrawRectangle(10, 360, 20, 20, PURPLE); | ||||
|         DrawText(dijkstraText.c_str(), 40, 360, 20, DARKGRAY); | ||||
|  | ||||
|         EndDrawing(); | ||||
|     } | ||||
|  | ||||
|     CloseWindow(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										310
									
								
								test/source/generator/generator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								test/source/generator/generator.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,310 @@ | ||||
| #include <algorithm> | ||||
| #include <chrono> | ||||
| #include <filesystem> | ||||
| #include <iostream> | ||||
| #include <numeric> | ||||
| #include <random> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| #include <vector> | ||||
|  | ||||
| // #include <omp.h> | ||||
|  | ||||
| #include "generator.hpp" | ||||
|  | ||||
| Generator::Generator(int32_t _seed) : seed(_seed) { | ||||
|     fnSimplex = FastNoise::New<FastNoise::Perlin>(); | ||||
|     fnFractal = FastNoise::New<FastNoise::FractalFBm>(); | ||||
|  | ||||
|     fnFractal->SetSource(fnSimplex); | ||||
|     fnFractal->SetOctaveCount(octaves); | ||||
|     fnFractal->SetGain(gain); | ||||
|     fnFractal->SetLacunarity(lacunarity); | ||||
|     fnFractal->SetWeightedStrength(weighted_strength); | ||||
| } | ||||
|  | ||||
| Generator::Generator() { | ||||
|     fnSimplex = FastNoise::New<FastNoise::Perlin>(); | ||||
|     fnFractal = FastNoise::New<FastNoise::FractalFBm>(); | ||||
|  | ||||
|     fnFractal->SetSource(fnSimplex); | ||||
|     fnFractal->SetOctaveCount(octaves); | ||||
|     fnFractal->SetGain(gain); | ||||
|     fnFractal->SetLacunarity(lacunarity); | ||||
|     fnFractal->SetWeightedStrength(weighted_strength); | ||||
|  | ||||
|     randomizeSeed(); | ||||
| } | ||||
|  | ||||
| Generator::~Generator() {} | ||||
|  | ||||
| void Generator::reseed(int32_t _seed) { | ||||
|     this->seed = _seed; | ||||
| } | ||||
|  | ||||
| int32_t Generator::randomizeSeed() { | ||||
|     std::random_device rd; | ||||
|     std::mt19937_64 gen(rd()); | ||||
|     std::uniform_int_distribution<uint32_t> dis(std::numeric_limits<int32_t>::min(), std::numeric_limits<int32_t>::max()); | ||||
|     this->seed = dis(gen); | ||||
|  | ||||
|     return seed; | ||||
| } | ||||
|  | ||||
| uint32_t Generator::get_seed() const { | ||||
|     return seed; | ||||
| } | ||||
|  | ||||
| void Generator::setOctaves(uint32_t _octaves) { | ||||
|     this->octaves = _octaves; | ||||
|     fnFractal->SetOctaveCount(octaves); | ||||
| } | ||||
|  | ||||
| uint32_t Generator::getOctaves() const { | ||||
|     return octaves; | ||||
| } | ||||
|  | ||||
| void Generator::setLacunarity(float _lacunarity) { | ||||
|     this->lacunarity = _lacunarity; | ||||
|     fnFractal->SetLacunarity(lacunarity); | ||||
| } | ||||
|  | ||||
| float Generator::getLacunarity() const { | ||||
|     return lacunarity; | ||||
| } | ||||
|  | ||||
| void Generator::setGain(float _gain) { | ||||
|     this->gain = _gain; | ||||
|     fnFractal->SetGain(gain); | ||||
| } | ||||
|  | ||||
| float Generator::getGain() const { | ||||
|     return gain; | ||||
| } | ||||
|  | ||||
| void Generator::setFrequency(float _frequency) { | ||||
|     this->frequency = _frequency; | ||||
| } | ||||
|  | ||||
| float Generator::getFrequency() const { | ||||
|     return frequency; | ||||
| } | ||||
|  | ||||
| void Generator::setWeightedStrength(float _weighted_strength) { | ||||
|     this->weighted_strength = _weighted_strength; | ||||
|     fnFractal->SetWeightedStrength(weighted_strength); | ||||
| } | ||||
|  | ||||
| float Generator::getWeightedStrength() const { | ||||
|     return weighted_strength; | ||||
| } | ||||
|  | ||||
| void Generator::setMultiplier(uint32_t _multiplier) { | ||||
|     this->multiplier = _multiplier; | ||||
| } | ||||
|  | ||||
| uint32_t Generator::getMultiplier() const { | ||||
|     return multiplier; | ||||
| } | ||||
|  | ||||
| std::vector<uint32_t> Generator::generate2dMeightmap(const int32_t begin_x, | ||||
|                                                      [[maybe_unused]] const int32_t begin_y, | ||||
|                                                      const int32_t begin_z, | ||||
|                                                      const uint32_t size_x, | ||||
|                                                      [[maybe_unused]] const uint32_t size_y, | ||||
|                                                      const uint32_t size_z) { | ||||
|     constexpr bool debug = false; | ||||
|  | ||||
|     std::vector<uint32_t> heightmap(size_x * size_z); | ||||
|  | ||||
|     std::vector<float> noise_output(size_x * size_z); | ||||
|  | ||||
|     if (fnFractal.get() == nullptr) { | ||||
|         std::cout << "fnFractal is nullptr" << std::endl; | ||||
|         return heightmap; | ||||
|     } | ||||
|  | ||||
|     fnFractal->GenUniformGrid2D(noise_output.data(), begin_x, begin_z, size_x, size_z, frequency, seed); | ||||
|  | ||||
|     // Convert noise_output to heightmap | ||||
|     for (uint32_t i = 0; i < size_x * size_z; i++) { | ||||
|         heightmap[i] = static_cast<uint32_t>((noise_output[i] + 1.0) * multiplier); | ||||
|         if constexpr (debug) { | ||||
|             std::cout << "i: " << i << ", value: " << noise_output[i] << ", heightmap: " << heightmap[i] << std::endl; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if constexpr (debug) { | ||||
|         // cout max and min | ||||
|         auto minmax = std::minmax_element(heightmap.begin(), heightmap.end()); | ||||
|         std::cout << "min: " << static_cast<int32_t>(*minmax.first) << std::endl; | ||||
|         std::cout << "max: " << static_cast<int32_t>(*minmax.second) << std::endl; | ||||
|     } | ||||
|     return heightmap; | ||||
| } | ||||
|  | ||||
| std::vector<uint32_t> Generator::generate3dHeightmap(const int32_t begin_x, | ||||
|                                                      const int32_t begin_y, | ||||
|                                                      const int32_t begin_z, | ||||
|                                                      const uint32_t size_x, | ||||
|                                                      const uint32_t size_y, | ||||
|                                                      const uint32_t size_z) { | ||||
|     constexpr bool debug = false; | ||||
|  | ||||
|     std::vector<uint32_t> heightmap(size_x * size_y * size_z); | ||||
|  | ||||
|     std::vector<float> noise_output(size_x * size_y * size_z); | ||||
|  | ||||
|     if (fnFractal.get() == nullptr) { | ||||
|         std::cout << "fnFractal is nullptr" << std::endl; | ||||
|         return heightmap; | ||||
|     } | ||||
|  | ||||
|     fnFractal->GenUniformGrid3D(noise_output.data(), begin_x, begin_y, begin_z, size_x, size_y, size_z, frequency, seed); | ||||
|  | ||||
|     // Convert noise_output to heightmap | ||||
|     for (uint32_t i = 0; i < size_x * size_y * size_z; i++) { | ||||
|         heightmap[i] = static_cast<uint32_t>((noise_output[i] + 1.0) * multiplier); | ||||
|         if constexpr (debug) { | ||||
|             std::cout << "i: " << i << ", noise_output: " << noise_output[i] << ", heightmap: " << heightmap[i] << std::endl; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if constexpr (debug) { | ||||
|         // cout max and min | ||||
|         auto minmax = std::minmax_element(heightmap.begin(), heightmap.end()); | ||||
|         std::cout << "min: " << static_cast<int32_t>(*minmax.first) << std::endl; | ||||
|         std::cout << "max: " << static_cast<int32_t>(*minmax.second) << std::endl; | ||||
|     } | ||||
|  | ||||
|     return heightmap; | ||||
| } | ||||
|  | ||||
| /* | ||||
| std::unique_ptr<Chunk> Generator::generateChunk(const int32_t chunk_x, | ||||
|                                                 const int32_t chunk_y, | ||||
|                                                 const int32_t chunk_z, | ||||
|                                                 const bool generate_3d_terrain) { | ||||
|     const int32_t real_x = chunk_x * Chunk::chunk_size_x; | ||||
|     const int32_t real_y = chunk_y * Chunk::chunk_size_y; | ||||
|     const int32_t real_z = chunk_z * Chunk::chunk_size_z; | ||||
|  | ||||
|     std::vector<Block> blocks; | ||||
|  | ||||
|     std::unique_ptr<Chunk> _chunk = std::make_unique<Chunk>(); | ||||
|  | ||||
|     if (generate_3d_terrain) { | ||||
|         blocks = std::move(generate3d(real_x, real_y, real_z, Chunk::chunk_size_x, Chunk::chunk_size_y, Chunk::chunk_size_z)); | ||||
|     } else { | ||||
|         blocks = std::move(generate2d(real_x, real_y, real_z, Chunk::chunk_size_x, Chunk::chunk_size_y, Chunk::chunk_size_z)); | ||||
|     } | ||||
|  | ||||
|     _chunk->set_blocks(blocks); | ||||
|     _chunk->set_chuck_pos(chunk_x, chunk_y, chunk_z); | ||||
|  | ||||
|     return _chunk; | ||||
| } | ||||
|  | ||||
| [[nodiscard]] std::vector<std::unique_ptr<Chunk>> Generator::generateChunks(const int32_t begin_chunk_x, | ||||
|                                                                             const int32_t begin_chunk_y, | ||||
|                                                                             const int32_t begin_chunk_z, | ||||
|                                                                             const uint32_t size_x, | ||||
|                                                                             const uint32_t size_y, | ||||
|                                                                             const uint32_t size_z, | ||||
|                                                                             const bool generate_3d_terrain) { | ||||
|     constexpr bool debug = false; | ||||
|  | ||||
|     std::vector<std::unique_ptr<Chunk>> chunks; | ||||
|     chunks.reserve(size_x * size_y * size_z); | ||||
|  | ||||
| #pragma omp parallel for collapse(3) schedule(auto) | ||||
|     for (int32_t x = begin_chunk_x; x < begin_chunk_x + size_x; x++) { | ||||
|         for (int32_t z = begin_chunk_y; z < begin_chunk_y + size_z; z++) { | ||||
|             for (int32_t y = begin_chunk_z; y < begin_chunk_z + size_y; y++) { | ||||
|                 auto gen_chunk = generateChunk(x, y, z, generate_3d_terrain); | ||||
| #pragma omp critical | ||||
|                 chunks.emplace_back(std::move(gen_chunk)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return chunks; | ||||
| } | ||||
| std::vector<Block> Generator::generate2d(const int32_t begin_x, | ||||
|                                          const int32_t begin_y, | ||||
|                                          const int32_t begin_z, | ||||
|                                          const uint32_t size_x, | ||||
|                                          const uint32_t size_y, | ||||
|                                          const uint32_t size_z) { | ||||
|     constexpr bool debug = false; | ||||
|  | ||||
|     std::vector<uint32_t> heightmap; | ||||
|     std::vector<Block> blocks = std::vector<Block>(size_x * size_y * size_z, Block()); | ||||
|  | ||||
|     heightmap = std::move(generate2dMeightmap(begin_x, begin_y, begin_z, size_x, size_y, size_z)); | ||||
|  | ||||
|     // Generate blocks | ||||
|     for (uint32_t x = 0; x < size_x; x++) { | ||||
|         for (uint32_t z = 0; z < size_z; z++) { | ||||
|             // Noise value is divided by 4 to make it smaller and it is used as the height of the Block (z) | ||||
|             std::vector<Block>::size_type vec_index = math::convert_to_1d(x, z, size_x, size_z); | ||||
|  | ||||
|             uint32_t noise_value = heightmap[vec_index] / 4; | ||||
|  | ||||
|             for (uint32_t y = 0; y < size_y; y++) { | ||||
|                 // Calculate real y from begin_y | ||||
|                 vec_index = math::convert_to_1d(x, y, z, size_x, size_y, size_z); | ||||
|  | ||||
|                 if constexpr (debug) { | ||||
|                     std::cout << "x: " << x << ", z: " << z << ", y: " << y << " index: " << vec_index | ||||
|                               << ", noise: " << static_cast<int32_t>(noise_value) << std::endl; | ||||
|                 } | ||||
|  | ||||
|                 Block& current_block = blocks[vec_index]; | ||||
|  | ||||
|                 // If the noise value is greater than the current Block, make it air | ||||
|                 if (noise_value > 120) { | ||||
|                     current_block.block_type = block_type::stone; | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return blocks; | ||||
| } | ||||
|  | ||||
| std::vector<Block> Generator::generate3d(const int32_t begin_x, | ||||
|                                          const int32_t begin_y, | ||||
|                                          const int32_t begin_z, | ||||
|                                          const uint32_t size_x, | ||||
|                                          const uint32_t size_y, | ||||
|                                          const uint32_t size_z) { | ||||
|     constexpr bool debug = false; | ||||
|  | ||||
|     std::vector<Block> blocks = std::vector<Block>(size_x * size_y * size_z, Block()); | ||||
|  | ||||
|     std::vector<uint32_t> heightmap = generate3dHeightmap(begin_x, begin_y, begin_z, size_x, size_y, size_z); | ||||
|  | ||||
|     // Generate blocks | ||||
|     for (uint32_t x = 0; x < size_x; x++) { | ||||
|         for (uint32_t z = 0; z < size_z; z++) { | ||||
|             for (uint32_t y = 0; y < size_y; y++) { | ||||
|                 size_t vec_index = math::convert_to_1d(x, y, z, size_x, size_y, size_z); | ||||
|                 const uint32_t noise_value = heightmap[vec_index]; | ||||
|                 auto& current_block = blocks[vec_index]; | ||||
|  | ||||
|                 if constexpr (debug) { | ||||
|                     std::cout << "x: " << x << ", z: " << z << ", y: " << y << " index: " << vec_index | ||||
|                               << ", noise: " << static_cast<int32_t>(noise_value) << std::endl; | ||||
|                 } | ||||
|  | ||||
|                 if (noise_value > 120) { | ||||
|                     current_block.block_type = block_type::stone; | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return blocks; | ||||
| } | ||||
| */ | ||||
							
								
								
									
										115
									
								
								test/source/generator/generator.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								test/source/generator/generator.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| #ifndef WORLD_OF_CUBE_GENERATOR_HPP | ||||
| #define WORLD_OF_CUBE_GENERATOR_HPP | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <chrono> | ||||
| #include <filesystem> | ||||
| #include <iostream> | ||||
| #include <numeric> | ||||
| #include <random> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| #include <vector> | ||||
|  | ||||
| // #include <omp.h> | ||||
|  | ||||
| #ifndef FASTNOISE_HPP_INCLUDED | ||||
| #define FASTNOISE_HPP_INCLUDED | ||||
| #ifdef __GNUC__ | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| #ifdef __clang__ | ||||
| #pragma clang system_header | ||||
| #endif | ||||
| #include "FastNoise/FastNoise.h" | ||||
| #endif | ||||
|  | ||||
| class Generator { | ||||
|    public: | ||||
|     explicit Generator(int32_t _seed); | ||||
|  | ||||
|     explicit Generator(); | ||||
|  | ||||
|     ~Generator(); | ||||
|  | ||||
|     void reseed(int32_t _seed); | ||||
|  | ||||
|     int32_t randomizeSeed(); | ||||
|  | ||||
|     uint32_t get_seed() const; | ||||
|  | ||||
|     void setOctaves(uint32_t _octaves); | ||||
|  | ||||
|     uint32_t getOctaves() const; | ||||
|  | ||||
|     void setLacunarity(float _lacunarity); | ||||
|  | ||||
|     float getLacunarity() const; | ||||
|  | ||||
|     void setGain(float _gain); | ||||
|  | ||||
|     float getGain() const; | ||||
|  | ||||
|     void setFrequency(float _frequency); | ||||
|     float getFrequency() const; | ||||
|  | ||||
|     void setWeightedStrength(float _weighted_strength); | ||||
|     float getWeightedStrength() const; | ||||
|  | ||||
|     void setMultiplier(uint32_t _multiplier); | ||||
|  | ||||
|     uint32_t getMultiplier() const; | ||||
|  | ||||
|     std::vector<uint32_t> generate2dMeightmap(const int32_t begin_x, | ||||
|                                               [[maybe_unused]] const int32_t begin_y, | ||||
|                                               const int32_t begin_z, | ||||
|                                               const uint32_t size_x, | ||||
|                                               [[maybe_unused]] const uint32_t size_y, | ||||
|                                               const uint32_t size_z); | ||||
|  | ||||
|     std::vector<uint32_t> generate3dHeightmap(const int32_t begin_x, | ||||
|                                               const int32_t begin_y, | ||||
|                                               const int32_t begin_z, | ||||
|                                               const uint32_t size_x, | ||||
|                                               const uint32_t size_y, | ||||
|                                               const uint32_t size_z); | ||||
|     /* | ||||
|     std::unique_ptr<Chunk> generateChunk(const int32_t chunk_x, const int32_t chunk_y, const int32_t chunk_z, const bool generate_3d_terrain); | ||||
|  | ||||
|     [[nodiscard]] std::vector<std::unique_ptr<Chunk>> generateChunks(const int32_t begin_chunk_x, | ||||
|                                                                      const int32_t begin_chunk_y, | ||||
|                                                                      const int32_t begin_chunk_z, | ||||
|                                                                      const uint32_t size_x, | ||||
|                                                                      const uint32_t size_y, | ||||
|                                                                      const uint32_t size_z, | ||||
|                                                                      const bool generate_3d_terrain); | ||||
|  | ||||
|     std::vector<Block> generate2d(const int32_t begin_x, | ||||
|                                   const int32_t begin_y, | ||||
|                                   const int32_t begin_z, | ||||
|                                   const uint32_t size_x, | ||||
|                                   const uint32_t size_y, | ||||
|                                   const uint32_t size_z); | ||||
|  | ||||
|     std::vector<Block> generate3d(const int32_t begin_x, | ||||
|                                   const int32_t begin_y, | ||||
|                                   const int32_t begin_z, | ||||
|                                   const uint32_t size_x, | ||||
|                                   const uint32_t size_y, | ||||
|                                   const uint32_t size_z); | ||||
|     */ | ||||
|    private: | ||||
|     // default seed | ||||
|     int32_t seed = 404; | ||||
|     FastNoise::SmartNode<FastNoise::Perlin> fnSimplex; | ||||
|     FastNoise::SmartNode<FastNoise::FractalFBm> fnFractal; | ||||
|  | ||||
|     int32_t octaves = 6; | ||||
|     float lacunarity = 0.5f; | ||||
|     float gain = 3.5f; | ||||
|     float frequency = 0.4f; | ||||
|     float weighted_strength = 0.0f; | ||||
|     uint32_t multiplier = 128; | ||||
| }; | ||||
|  | ||||
| #endif  // WORLD_OF_CUBE_GENERATOR_HPP | ||||
							
								
								
									
										87
									
								
								test/source/test/astar_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								test/source/test/astar_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| #include "astar/astar.hpp" | ||||
|  | ||||
| #include "gtest/gtest.h" | ||||
|  | ||||
| TEST(AStar, basic_path_1) { | ||||
|     int mapWidth = 4; | ||||
|     int mapHeight = 4; | ||||
|     AStar::AStar pathFinder; | ||||
|     pathFinder.setWorldSize({mapWidth, mapWidth}); | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::euclidean); | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     AStar::Vec2i source(0, 0); | ||||
|     AStar::Vec2i target(mapWidth - 1, mapHeight - 1); | ||||
|  | ||||
|     std::cout << "AStar::AStar pathFinder;" << std::endl; | ||||
|     auto path = pathFinder.findPath(source, target); | ||||
|  | ||||
|     EXPECT_EQ(path.size(), 4); | ||||
|  | ||||
|     for (size_t i = 0; i < path.size(); i++) { | ||||
|         EXPECT_EQ(path[i].x, path.size() - i - 1); | ||||
|         EXPECT_EQ(path[i].y, path.size() - i - 1); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST(AStar, basic_path_2) { | ||||
|     int mapWidth = 10; | ||||
|     int mapHeight = 10; | ||||
|     AStar::AStar pathFinder; | ||||
|     pathFinder.setWorldSize({mapWidth, mapWidth}); | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::euclidean); | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     AStar::Vec2i source(0, 0); | ||||
|     AStar::Vec2i target(mapWidth - 1, mapHeight - 1); | ||||
|  | ||||
|     auto path = pathFinder.findPath(source, target); | ||||
|  | ||||
|     EXPECT_EQ(path.size(), 10); | ||||
|  | ||||
|     for (size_t i = 0; i < path.size(); i++) { | ||||
|         EXPECT_EQ(path[i].x, path.size() - i - 1); | ||||
|         EXPECT_EQ(path[i].y, path.size() - i - 1); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST(AStar, basic_diagonal_path_wrong_1) { | ||||
|     int mapWidth = 10; | ||||
|     int mapHeight = 10; | ||||
|     AStar::AStar pathFinder; | ||||
|     pathFinder.setWorldSize({mapWidth, mapHeight}); | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::euclidean); | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     AStar::Vec2i source(0, 0); | ||||
|     AStar::Vec2i target(19, 19); | ||||
|  | ||||
|     auto path = pathFinder.findPath(source, target); | ||||
|  | ||||
|     EXPECT_EQ(path.size(), 0); | ||||
| } | ||||
|  | ||||
| TEST(AStar, basic_diagonal_path_wrong_2) { | ||||
|     int mapWidth = 10; | ||||
|     int mapHeight = 10; | ||||
|     AStar::AStar pathFinder; | ||||
|     pathFinder.setWorldSize({mapWidth, mapHeight}); | ||||
|     pathFinder.setHeuristic(AStar::Heuristic::euclidean); | ||||
|     pathFinder.setDiagonalMovement(true); | ||||
|  | ||||
|     pathFinder.addObstacle({0, 1}); | ||||
|     pathFinder.addObstacle({1, 1}); | ||||
|     pathFinder.addObstacle({1, 0}); | ||||
|  | ||||
|     AStar::Vec2i source(0, 0); | ||||
|     AStar::Vec2i target(9, 9); | ||||
|  | ||||
|     auto path = pathFinder.findPath(source, target); | ||||
|  | ||||
|     EXPECT_EQ(path.size(), 0); | ||||
| } | ||||
|  | ||||
| auto main(int argc, char** argv) -> int { | ||||
|     ::testing::InitGoogleTest(&argc, argv); | ||||
|     return RUN_ALL_TESTS(); | ||||
| } | ||||
							
								
								
									
										91
									
								
								tools/graphic.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										91
									
								
								tools/graphic.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| # Based on work: https://int-i.github.io/python/2021-11-07/matplotlib-google-benchmark-visualization/ | ||||
| # Modified by: Bensuperpc | ||||
|  | ||||
| from argparse import ArgumentParser | ||||
| from itertools import groupby | ||||
| import json | ||||
| import operator | ||||
| import matplotlib.pyplot as plt | ||||
| import numpy as np | ||||
| import seaborn as sns | ||||
| import pandas as pd | ||||
|  | ||||
| # Extract the benchmark name from the benchmark name string | ||||
| def extract_label_from_benchmark(benchmark): | ||||
|     bench_full_name = benchmark['name'] | ||||
|     bench_name = bench_full_name.split('/')[0]  # Remove all after / | ||||
|     if (bench_name.startswith('BM_')):  # Remove if string start with BM_ | ||||
|         return bench_name[3:]  # Remove BM_ | ||||
|     else: | ||||
|         return bench_name | ||||
|  | ||||
| # Extract the benchmark size from the benchmark | ||||
| def extract_size_from_benchmark(benchmark): | ||||
|     bench_name = benchmark['name'] | ||||
|     return bench_name.split('/')[1]  # Remove all before / | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     # ./prog_name --benchmark_format=json --benchmark_out=result.json | ||||
|     parser = ArgumentParser() | ||||
|     parser.add_argument('path', help='benchmark result json file') | ||||
|     args = parser.parse_args() | ||||
|  | ||||
|     with open(args.path) as file: | ||||
|         benchmark_result = json.load(file) | ||||
|         benchmarks = benchmark_result['benchmarks'] | ||||
|         elapsed_times = groupby(benchmarks, extract_label_from_benchmark) | ||||
|  | ||||
|         data1 = None | ||||
|         data2 = None | ||||
|  | ||||
|         for key, group in elapsed_times: | ||||
|             benchmark = list(group) | ||||
|             x = list(map(extract_size_from_benchmark, benchmark)) | ||||
|             y1 = list(map(operator.itemgetter('bytes_per_second'), benchmark)) | ||||
|             y2 = list(map(operator.itemgetter('items_per_second'), benchmark)) | ||||
|  | ||||
|             if data1 is None: | ||||
|                 data1 = pd.DataFrame({'size': x, key: y1}) | ||||
|             else: | ||||
|                 data1[key] = y1 | ||||
|              | ||||
|             if data2 is None: | ||||
|                 data2 = pd.DataFrame({'size': x, key: y2}) | ||||
|             else: | ||||
|                 data2[key] = y2 | ||||
|  | ||||
|         df1 = pd.melt(data1, id_vars=['size'], var_name='Benchmark', value_name='bytes_per_second') | ||||
|         df1_max_indices = df1.groupby(['size', 'Benchmark'])['bytes_per_second'].transform(max) == df1['bytes_per_second'] | ||||
|         df1 = df1.loc[df1_max_indices] | ||||
|         df1.reset_index(drop=True, inplace=True) | ||||
|  | ||||
|  | ||||
|         df2 = pd.melt(data2, id_vars=['size'], var_name='Benchmark', value_name='items_per_second') | ||||
|         df2_max_indices = df2.groupby(['size', 'Benchmark'])['items_per_second'].transform(max) == df2['items_per_second'] | ||||
|         df2 = df2.loc[df2_max_indices] | ||||
|         df2.reset_index(drop=True, inplace=True) | ||||
|          | ||||
|         sns.set_theme() | ||||
|  | ||||
|         fig, ax = plt.subplots(2, 1) | ||||
|  | ||||
|         fig.set_size_inches(16, 9) | ||||
|         fig.set_dpi(96) | ||||
|  | ||||
|         sns.lineplot(data=df1, x='size', y='bytes_per_second', hue='Benchmark', ax=ax[0]) | ||||
|         sns.lineplot(data=df2, x='size', y='items_per_second', hue='Benchmark', ax=ax[1]) | ||||
|  | ||||
|         ax[0].set_title('Bytes per second') | ||||
|         ax[1].set_title('Items per second') | ||||
|  | ||||
|         ax[0].set_xlabel('Array size') | ||||
|         ax[1].set_xlabel('Array size') | ||||
|  | ||||
|         ax[0].set_ylabel('byte per second') | ||||
|         ax[1].set_ylabel('items per second') | ||||
|  | ||||
|         fig.tight_layout() | ||||
|  | ||||
|         plt.savefig('benchmark.png', bbox_inches='tight', dpi=300) | ||||
|  | ||||
|         plt.show() | ||||
		Reference in New Issue
	
	Block a user