{"id":13419298,"url":"https://github.com/leethomason/MicroPather","last_synced_at":"2025-03-15T05:30:43.990Z","repository":{"id":145307978,"uuid":"7027603","full_name":"leethomason/MicroPather","owner":"leethomason","description":"MicroPather is a path finder and A* solver (astar or a-star) written in platform independent C++ that can be easily integrated into existing code. MicroPather focuses on being a path finding engine for video games but is a generic A* solver.","archived":false,"fork":false,"pushed_at":"2022-11-06T21:17:34.000Z","size":89,"stargazers_count":324,"open_issues_count":6,"forks_count":71,"subscribers_count":30,"default_branch":"master","last_synced_at":"2024-07-31T22:46:49.663Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leethomason.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2012-12-06T01:04:58.000Z","updated_at":"2024-07-18T19:16:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"6adc3e0a-c781-4b71-966f-a847c0fa30f2","html_url":"https://github.com/leethomason/MicroPather","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leethomason%2FMicroPather","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leethomason%2FMicroPather/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leethomason%2FMicroPather/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leethomason%2FMicroPather/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leethomason","download_url":"https://codeload.github.com/leethomason/MicroPather/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243690113,"owners_count":20331726,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T22:01:14.008Z","updated_at":"2025-03-15T05:30:43.700Z","avatar_url":"https://github.com/leethomason.png","language":"C++","readme":"MicroPather\r\n===========\r\n\r\nMicroPather is a path finder and A* solver (astar or a-star) written in platform \r\nindependent C++ that can be easily integrated into existing code. MicroPather \r\nfocuses on being a path finding engine for video games but is a generic A* solver. \r\nMicroPather is open source, with a license suitable for open source or commercial \r\nuse.\r\n\r\nThe goals of MicroPather are:\r\n* Easy integration into games and other software\r\n* Easy to use and simple interface\r\n* Fast enough\r\n\r\nDemo\r\n----\r\n\r\nMicroPather comes with a demo application - dungeon.cpp - to show off pathing. \r\nIt's ASCII art dungeon exploring at its finest.\r\n\r\nThe demo shows an ASCII art dungeon. You can move around by typing a new location, and it will \r\nprint the path to that location. In the screen shot above, the path starts in \r\nthe upper left corner, and steps to the 'i' at about the middle of \r\nthe screen avoiding ASCII walls on the way. The numbers show the path from 0 \r\nto 9 then back to 0.\r\n\r\nYou can even open and close the doors to change possible paths. 'd' at the command prompt.\r\n\r\nA Windows Visual C++ 2010 project file and a Linux Makefile are provided. Building it \r\nfor another environment is trivial: just compile dungeon.cpp, micropather.h, and \r\nmicropather.cpp to a command line app in your environment.\r\n\r\nAbout A*\r\n--------\r\nIn video games, the pathfinding problem comes up in many modern games. What \r\nis the shortest distance from point A to point B? Humans are good at that problem \r\n- you pathfind naturally almost every time you move - but tricky to express \r\nas a computer algorithm. A* is the workhorse technique to solve pathing. It \r\nis directed, meaning that it is optimized to find a solution quickly rather \r\nthan by brute force, but it will never fail to find a solution if there is one.\r\n\r\nA* is much more universal that just pathfinding. A* and MicroPather could be \r\nused to find the solution to general state problems, for example it could be \r\nused to solve for a rubiks cube puzzle.\r\n\r\nTerminology\r\n-----------\r\n\r\nThe *Graph* is the search space. For the pathfinding problem, \r\nthis is your Map. It can be any kind of map: squares like the dungeon example, \r\npolygonal, 3D, hexagons, etc.\r\n\r\nIn pathfinding, a *State* is just a position on the Map. In \r\nthe demo, the player starts at State (0,0). Adjacent states are very important, \r\nas you might image. If something is at state (1,1) in the dungeon example, \r\nit has 8 adjacent states (0,1), (2,1) etc. it can move to. Why State instead \r\nof location or node? The terminology comes from the more general application. \r\nThe states of a cube puzzle aren't locations, for example.\r\n\r\nStates are separated by *Cost*. For simple pathfinding in \r\nthe dungeon, the *Cost* is simply distance. The cost from state \r\n(0,0) to (1,0) is 1.0, and the cost from (0,0) to (1,1) is sqrt(2), about \r\n1.4. *Cost* is challenging and interesting because it can be \r\ndistance, time, or difficulty.\r\n* using distance as the cost will give the shortest length path\r\n* using traversal time as the cost will give the fastest path\r\n* using difficulty as the cost will give the easiest path\r\netc.\r\n\r\nMore info: http://www-cs-students.stanford.edu/~amitp/gameprog.html#paths\r\n\r\nIntegrating MicroPather Into Your Code\r\n--------------------------------------\r\nNothing could by simpler! Or at least that's the goal. More importantly, none \r\nof your game data structures need to change to use MicroPather. The steps, in \r\nbrief, are:\r\n\r\n1. Include MicroPather files\u003c/p\u003e\r\n2. Implement the Graph interface\u003c/p\u003e\r\n3. Call the Solver\u003c/p\u003e\r\n\r\n*Include files*\r\n\r\nThere are only 2 files for micropather: micropather.cpp and micropather.h. \r\nSo there's no build, no make, just add the 2 files to your project. That's it. \r\nThey are standard C++ and don't require exceptions or RTTI. (I know, a bunch \r\nof you like exceptions and RTTI. But it does make it less portable and slightly \r\nslower to use them.)\r\n\r\nAssuming you build a debug version of your project with _DEBUG or DEBUG (and \r\neveryone does) MicroPather will run extra checking in these modes.\r\n\r\n*Implement Graph Interface*\r\n\r\nYou have some class called Game, or Map, or World, that organizes and stores \r\nyour game map. This object (we'll call it Map) needs to inherit from the abstract \r\nclass Graph:\r\n\r\n\tclass Map : public Graph\r\n\r\nGraph is pure abstract, so your map class won't be changed by it (except for \r\npossibly gaining a vtable), or have strange conflicts.\r\nBefore getting to the methods of Graph, lets think states, as in:\r\n\r\n\tvoid Foo( void* state )\r\n\t\r\nThe state pointer is provided by you, the game programmer. What it is? It is \r\na unique id for a state. For something like a 3D terrain map, like Lilith3D \r\nuses, the states are pointers to a map structure, a 'QuadNode' in \r\nthis case. So the state would simply be:\r\n\r\n\tvoid* state = (void*) quadNode;\r\n\t\r\nOn the other hand, the Dungeon example doesn't have an object per map location, \r\njust an x and y. It then uses:\r\n\r\n\tvoid* state = (void*)( y * MAPX + x );\r\n\t\r\nThe state can be anything you want, as long as it is unique and you can convert \r\nto it and from it.\r\n\r\nNow, the methods of Graph.\r\n\r\n\t/**\r\n\t\tReturn the least possible cost between 2 states. For example, if your pathfinding \r\n\t\tis based on distance, this is simply the straight distance between 2 points on the \r\n\t\tmap. If you pathfinding is based on minimum time, it is the minimal travel time \r\n\t\tbetween 2 points given the best possible terrain.\r\n\t*/\r\n\tvirtual float LeastCostEstimate( void* stateStart, void* stateEnd ) = 0;\r\n\r\n\t/** \r\n\t\tReturn the exact cost from the given state to all its neighboring states. This\r\n\t\tmay be called multiple times, or cached by the solver. It *must* return the same\r\n\t\texact values for every call to MicroPather::Solve(). It should generally be a simple,\r\n\t\tfast function with no callbacks into the pather.\r\n\t*/\t\r\n\tvirtual void AdjacentCost( void* state, MP_VECTOR\u003c micropather::StateCost \u003e *adjacent ) = 0;\r\n\r\n\t/**\r\n\t\tThis function is only used in DEBUG mode - it dumps output to stdout. Since void* \r\n\t\taren't really human readable, normally you print out some concise info (like \"(1,2)\") \r\n\t\twithout an ending newline.\r\n\t*/\r\n\tvirtual void  PrintStateInfo( void* state ) = 0;\r\n\r\n*Call the Solver*\r\n\r\n\tMicroPather* pather = new MicroPather( myGraph );\t// Although you really should set the default params for your game.\r\n\t\r\n\tmicropather::MPVector\u003c void* \u003e path;\r\n\tfloat totalCost = 0;\r\n\tint result = pather-\u003eSolve( startState, endState, \u0026path, \u0026totalCost );\r\n\r\nThat's it. Given the start state and the end state, the sequence of states \r\nfrom start to end will be written to the vector.\r\n\r\nMicroPather does a lot of caching. You want to create one and keep in around.\r\nIt will cache lots of information about your graph, and get faster as it is \r\ncalled. However, for caching to work, the connections between states and the \r\ncosts of those connections must stay the same. (Else the cache information will \r\nbe invalid.) If costs between connections does change, be sure to call Reset().\r\n\r\n\tpather-\u003eReset();\r\n\r\nReset() is a fast call if it doesn't need to do anything.\r\n\r\nFuture Improvements and Social Coding\r\n-------------------------------------\r\n\r\nI really like getting patches, improvements, and performance enhancements. \r\nSome guidelines:\r\n* Pull requests are the best way to send a change.\r\n* The \"ease of use\" goal is important to this project. It can be sped up by\r\n  deeper integration into the client code (all states must subclass the State\r\n  object, for example) but that dramatically reduces usability.\r\n\r\nThanks for checking out MicroPather!\r\n\r\nLee Thomason\r\n ","funding_links":[],"categories":["TODO scan for Android support in followings","AI"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleethomason%2FMicroPather","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleethomason%2FMicroPather","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleethomason%2FMicroPather/lists"}