00001 00028 #ifndef MSMAZES_CORE_PATTERN_BASE_HPP 00029 #define MSMAZES_CORE_PATTERN_BASE_HPP 00030 00031 #include <vector> // std::vector 00032 #include <boost/utility.hpp> // boost::tie 00033 #include <boost/property_map.hpp> // boost::property_map and boost::get 00034 #include <boost/graph/graph_traits.hpp> // boost::graph_traits 00035 #include <boost/graph/graph_selectors.hpp> // boost::vecS and boost::listS 00036 #include <boost/graph/adjacency_list.hpp> // boost::adjacency_list and friends 00037 00609 namespace msmazes { 00610 00612 00632 struct BasicCellEqualityPolicy 00633 { 00661 template <typename Cell> 00662 bool operator()(const Cell& c1, const Cell& c2) const 00663 { 00664 return c1 == c2; 00665 } 00666 }; 00667 00669 00756 template < 00757 #ifndef MSMAZES_DOX 00758 typename EdgeDirectedSelector 00759 , typename CellType 00760 , typename CellEqualityPolicyType 00761 , typename DirectionType 00762 , typename CellContainer = std::vector<CellType> 00763 #endif /* MSMAZES_DOX */ 00764 > 00765 class BasePattern 00766 { 00767 public: 00772 #ifdef MSMAZES_DOX 00773 typedef implementation_defined Cell; 00774 #else 00775 typedef CellType 00776 Cell; 00777 #endif /* MSMAZES_DOX */ 00778 00784 #ifdef MSMAZES_DOX 00785 typedef implementation_defined CellEqualityPolicy; 00786 #else 00787 typedef CellEqualityPolicyType 00788 CellEqualityPolicy; 00789 #endif /* MSMAZES_DOX */ 00790 00796 #ifdef MSMAZES_DOX 00797 typedef implementation_defined Graph; 00798 #else 00799 typedef boost::adjacency_list<boost::listS,boost::vecS,EdgeDirectedSelector> 00800 Graph; 00801 #endif /* MSMAZES_DOX */ 00802 00808 #ifdef MSMAZES_DOX 00809 typedef implementation_defined CellIndex; 00810 #else 00811 typedef typename boost::graph_traits<Graph>::vertices_size_type 00812 CellIndex; 00813 #endif /* MSMAZES_DOX */ 00814 00820 #ifdef MSMAZES_DOX 00821 typedef implementation_defined EdgeDirectedCategory; 00822 #else 00823 typedef typename boost::graph_traits<Graph>::directed_category 00824 EdgeDirectedCategory; 00825 #endif /* MSMAZES_DOX */ 00826 00832 #ifdef MSMAZES_DOX 00833 typedef implementation_defined Direction; 00834 #else 00835 typedef DirectionType 00836 Direction; 00837 #endif /* MSMAZES_DOX */ 00838 00839 private: 00840 Graph _graph; 00841 CellContainer _cell; 00842 00843 BasePattern(const BasePattern& copy) 00844 { 00845 } 00846 00847 protected: 00849 00855 BasePattern() : _graph(), _cell() 00856 { 00857 } 00858 00859 public: 00861 00864 virtual ~BasePattern() 00865 { 00866 } 00867 00868 private: 00869 template < 00870 typename PatternFormer 00871 , typename ArgumentPack 00872 > 00873 void 00874 _initializeEdges( 00875 const PatternFormer& pattern_former 00876 , const ArgumentPack& p 00877 , boost::undirected_tag 00878 ) 00879 { 00880 typename boost::graph_traits<Graph>::vertex_descriptor u; 00881 CellIndex i = boost::num_vertices(_graph); 00882 CellIndex j; 00883 00884 while (i > 0) 00885 { 00886 u = boost::vertex(--i, _graph); 00887 boost::clear_vertex(u, _graph); 00888 Cell& u_loc = _cell[i]; 00889 j = boost::num_vertices(_graph); 00890 00891 while (--j > i) 00892 { 00893 Cell& v_loc = _cell[j]; 00894 00895 if ( 00896 PatternFormer::isLegalEdge(u_loc, v_loc, p) 00897 || PatternFormer::isLegalEdge(v_loc, u_loc, p) 00898 ) 00899 { 00900 boost::add_edge(u, boost::vertex(j, _graph), _graph); 00901 } 00902 } 00903 } 00904 } 00905 00906 template < 00907 typename PatternFormer 00908 , typename ArgumentPack 00909 > 00910 void 00911 _initializeEdges( 00912 const PatternFormer& pattern_former 00913 , const ArgumentPack& p 00914 , boost::directed_tag 00915 ) 00916 { 00917 typename boost::graph_traits<Graph>::vertex_descriptor u, v; 00918 CellIndex i = boost::num_vertices(_graph); 00919 CellIndex j; 00920 00921 while (i > 0) 00922 { 00923 u = boost::vertex(--i, _graph); 00924 boost::clear_vertex(u, _graph); 00925 Cell& u_loc = _cell[i]; 00926 j = boost::num_vertices(_graph); 00927 00928 while (--j > i) 00929 { 00930 v = boost::vertex(j, _graph); 00931 Cell& v_loc = _cell[j]; 00932 00933 if (PatternFormer::isLegalEdge(u_loc, v_loc, p)) 00934 { 00935 boost::add_edge(u, v, _graph); 00936 } 00937 00938 if (PatternFormer::isLegalEdge(v_loc, u_loc, p)) 00939 { 00940 boost::add_edge(v, u, _graph); 00941 } 00942 } 00943 } 00944 } 00945 00946 protected: 00975 template < 00976 typename PatternFormer 00977 , typename ArgumentPack 00978 > 00979 void 00980 initializeWithPatternFormer( 00981 const PatternFormer& pattern_former 00982 , const ArgumentPack& p 00983 ) 00984 { 00985 const CellIndex volume = PatternFormer::countCells(p); 00986 00987 while (boost::num_vertices(_graph) < volume) 00988 { 00989 boost::add_vertex(_graph); 00990 } 00991 00992 typename boost::graph_traits<Graph>::vertex_descriptor vertex; 00993 CellIndex vertex_count = boost::num_vertices(_graph); 00994 00995 while (vertex_count > volume) 00996 { 00997 vertex = boost::vertex(--vertex_count, _graph); 00998 boost::clear_vertex(vertex, _graph); 00999 boost::remove_vertex(vertex, _graph); 01000 } 01001 01002 _cell.resize(volume); 01003 PatternFormer::makeCells(_cell.begin(), p); 01004 _initializeEdges(pattern_former, p, EdgeDirectedCategory()); 01005 } 01006 01007 public: 01014 inline const Graph& getGraph() const 01015 { 01016 return _graph; 01017 } 01018 01024 inline CellIndex getCellCount() const 01025 { 01026 return boost::num_vertices(_graph); 01027 } 01028 01034 inline const Cell& getCell(const CellIndex index) const 01035 { 01036 return _cell[index]; 01037 } 01038 01044 virtual const Cell& getEntranceCell() const = 0; 01045 01052 virtual const Cell& getSourceCell() const = 0; 01053 01060 virtual const Cell& getTargetCell() const = 0; 01061 01067 virtual const Cell& getExitCell() const = 0; 01068 01069 protected: 01075 virtual Direction 01076 getEdgeDirectionDerived( 01077 const Cell& source 01078 , const Cell& target 01079 ) const 01080 { 01081 return Direction(); 01082 } 01083 01084 public: 01091 Direction 01092 getEdgeDirection( 01093 const CellIndex source_index 01094 , const CellIndex target_index 01095 ) const 01096 { 01097 return 01098 (source_index == target_index) 01099 ? getEdgeDirectionDerived( 01100 getEntranceCell() 01101 , getCell(target_index) 01102 ) 01103 : (target_index == getCellCount()) 01104 ? getEdgeDirectionDerived( 01105 getCell(source_index) 01106 , getExitCell() 01107 ) 01108 : getEdgeDirectionDerived( 01109 getCell(source_index) 01110 , getCell(target_index) 01111 ); 01112 } 01113 }; 01114 } // namespace msmazes 01115 01116 #endif /* MSMAZES_CORE_PATTERN_BASE_HPP */
Multi-State Mazes in C++ is hosted by . Use the Table of Contents for navigation.