00001 00027 #ifndef MSMAZES_CORE_FSM_BUILDER_PARALLELEPIPED_HPP 00028 #define MSMAZES_CORE_FSM_BUILDER_PARALLELEPIPED_HPP 00029 00030 #define MSMAZES_CORE_FSM_ARITY 13 00031 00032 // BOOST_PP_LESS 00033 #include <boost/preprocessor/comparison/less.hpp> 00034 // boost::is_same 00035 #include <boost/type_traits/is_same.hpp> 00036 // boost::remove_const 00037 #include <boost/type_traits/remove_const.hpp> 00038 // boost::remove_reference 00039 #include <boost/type_traits/remove_reference.hpp> 00040 // boost::mpl::apply1 00041 #include <boost/mpl/apply.hpp> 00042 // sgdk::Pi 00043 #include <swiss_gd_knife/zref/pi.hpp> 00044 // sgdk::Tangent 00045 #include <swiss_gd_knife/zref/tangent.hpp> 00046 // sgdk::ZeroChecker 00047 #include <swiss_gd_knife/math/zero_checker.hpp> 00048 // sgdk::PositiveRotation 00049 #include <swiss_gd_knife/math/geom/compass.hpp> 00050 // Boost.Parameter keyword objects used by the Core FSM Layer 00051 #include <msmazes/core/fsm/keywords.hpp> 00052 00053 #if BOOST_PP_LESS(BOOST_PARAMETER_MAX_ARITY, MSMAZES_CORE_FSM_ARITY) 00054 #error Set BOOST_PARAMETER_MAX_ARITY to 13 or higher. 00055 #endif 00056 00057 // msmazes::FSMInputMakerTraits 00058 #include <msmazes/core/fsm/input/traits_maker.hpp> 00059 // msmazes::FSMBuilder 00060 #include <msmazes/core/fsm/builder.hpp> 00061 // msmazes::MazeMakerTraits 00062 #include <msmazes/core/maze/traits_maker.hpp> 00063 // msmazes::NoNegativeTurnWalkthroughMazePolicy 00064 #include <msmazes/core/maze/maker_walkthrough.hpp> 00065 // MSMAZES_CORE_PATTERN_TESSELATION_FORMER_TYPE 00066 #include <msmazes/core/pattern/tesselation_former_type.hpp> 00067 // msmazes::Parallelepiped 00068 #include <msmazes/core/pattern/parallelepiped.hpp> 00069 00070 namespace msmazes { 00071 namespace _parallelepiped_builder { 00072 00077 template < 00078 typename Pattern 00079 > 00080 struct ArgumentValidationPolicy 00081 { 00082 private: 00083 typedef typename Pattern::Cell Cell; 00084 typedef typename Pattern::Coordinate Coordinate; 00085 00086 template < 00087 typename MazeMaker 00088 , typename FSMInputMaker 00089 , typename MazePolicy 00090 , typename ArgumentPack 00091 > 00092 static bool 00093 _areValidArgumentsByTesselation( 00094 const MazeMaker& maze_maker 00095 , const FSMInputMaker& input_maker 00096 , const MazePolicy& policy 00097 , const ArgumentPack& p 00098 , const msmazes::_detail::OrthogonalParallelepipedTag& tag 00099 ) 00100 { 00101 typedef typename FSMInputMakerTraits< 00102 FSMInputMaker 00103 >::RequiresSingleLayer 00104 FSMInputMakerRequiresSingleLayer; 00105 00106 const Cell& entrance = p[init_entrance_cell_arg]; 00107 const Cell& exit = p[init_exit_cell_arg]; 00108 const Cell& min = p[init_cell_minimum_arg]; 00109 const Cell& max = p[init_cell_maximum_arg]; 00110 const Cell& inc = p[init_cell_increment_arg]; 00111 00112 if (FSMInputMakerRequiresSingleLayer::value) 00113 { 00114 sgdk::ZeroChecker<Coordinate> zero_checker(inc[2] - 0.00001); 00115 00116 if ( 00117 !zero_checker.isZero(max[2] - min[2]) 00118 || !zero_checker.isZero(exit[2] - entrance[2]) 00119 || !zero_checker.isZero(exit[2] - min[2]) 00120 ) 00121 { 00122 return false; 00123 } 00124 } 00125 00126 if ( 00127 boost::is_same< 00128 MazePolicy 00129 , NoNegativeTurnWalkthroughMazePolicy 00130 >::value 00131 ) 00132 { 00133 const Coordinate end_x_maximum = max[0] - inc[0]; 00134 const Coordinate end_x_minimum = min[0] + inc[0]; 00135 const Coordinate end_y_maximum = max[1] - inc[1]; 00136 const Coordinate end_y_minimum = min[1] + inc[1]; 00137 const Coordinate start_x = entrance[0]; 00138 const Coordinate start_y = entrance[1]; 00139 const Coordinate end_x = exit[0]; 00140 const Coordinate end_y = exit[1]; 00141 00142 return 00143 ( 00144 (start_x >= end_x_minimum) && (start_x <= end_x_maximum) 00145 || (start_y >= end_y_minimum) && (start_y <= end_y_maximum) 00146 ) 00147 && ( 00148 (end_x >= end_x_minimum) && (end_x <= end_x_maximum) 00149 || (end_y >= end_y_minimum) && (end_y <= end_y_maximum) 00150 ); 00151 } 00152 00153 return true; 00154 } 00155 00156 template < 00157 typename MazeMaker 00158 , typename FSMInputMaker 00159 , typename MazePolicy 00160 , typename ArgumentPack 00161 > 00162 static bool 00163 _areValidArgumentsByTesselation( 00164 const MazeMaker& maze_maker 00165 , const FSMInputMaker& input_maker 00166 , const MazePolicy& policy 00167 , const ArgumentPack& p 00168 , const msmazes::_detail::Upsilon2DParallelepipedTag& tag 00169 ) 00170 { 00171 typedef typename FSMInputMakerTraits< 00172 FSMInputMaker 00173 >::RequiresSingleLayer 00174 FSMInputMakerRequiresSingleLayer; 00175 00176 const Cell& entrance 00177 = p[init_entrance_cell_arg]; 00178 const Cell& exit 00179 = p[init_exit_cell_arg]; 00180 const Cell& min 00181 = p[init_cell_minimum_arg]; 00182 const Cell& max 00183 = p[init_cell_maximum_arg]; 00184 const Coordinate inc 00185 = p[init_cell_increment_arg].getOctagonSquareCellCenterDistance(); 00186 00187 if (FSMInputMakerRequiresSingleLayer::value) 00188 { 00189 sgdk::ZeroChecker<Coordinate> zero_checker(inc - 0.00001); 00190 00191 if ( 00192 !zero_checker.isZero(max[2] - min[2]) 00193 || !zero_checker.isZero(exit[2] - entrance[2]) 00194 || !zero_checker.isZero(exit[2] - min[2]) 00195 ) 00196 { 00197 return false; 00198 } 00199 } 00200 00201 if ( 00202 boost::is_same< 00203 MazePolicy 00204 , NoNegativeTurnWalkthroughMazePolicy 00205 >::value 00206 ) 00207 { 00208 const Coordinate end_x_maximum = max[0] - inc; 00209 const Coordinate end_x_minimum = min[0] + inc; 00210 const Coordinate end_y_maximum = max[1] - inc; 00211 const Coordinate end_y_minimum = min[1] + inc; 00212 const Coordinate start_x = entrance[0]; 00213 const Coordinate start_y = entrance[1]; 00214 const Coordinate end_x = exit[0]; 00215 const Coordinate end_y = exit[1]; 00216 00217 return 00218 ( 00219 (start_x >= end_x_minimum) && (start_x <= end_x_maximum) 00220 || (start_y >= end_y_minimum) && (start_y <= end_y_maximum) 00221 ) 00222 && ( 00223 (end_x >= end_x_minimum) && (end_x <= end_x_maximum) 00224 || (end_y >= end_y_minimum) && (end_y <= end_y_maximum) 00225 ); 00226 } 00227 00228 return true; 00229 } 00230 00231 template < 00232 typename MazeMaker 00233 , typename FSMInputMaker 00234 , typename MazePolicy 00235 , typename ArgumentPack 00236 > 00237 static bool 00238 _areValidArgumentsByTesselation( 00239 const MazeMaker& maze_maker 00240 , const FSMInputMaker& input_maker 00241 , const MazePolicy& policy 00242 , const ArgumentPack& p 00243 , const msmazes::_detail::CubicGridParallelepipedTag& tag 00244 ) 00245 { 00246 typedef typename FSMInputMakerTraits< 00247 FSMInputMaker 00248 >::RequiresSingleLayer 00249 FSMInputMakerRequiresSingleLayer; 00250 00251 const Cell& entrance = p[init_entrance_cell_arg]; 00252 const Cell& exit = p[init_exit_cell_arg]; 00253 const Cell& min = p[init_cell_minimum_arg]; 00254 const Cell& max = p[init_cell_maximum_arg]; 00255 const Coordinate inc = p[init_cell_increment_arg]; 00256 00257 if (FSMInputMakerRequiresSingleLayer::value) 00258 { 00259 sgdk::ZeroChecker<Coordinate> zero_checker(inc - 0.00001); 00260 00261 if ( 00262 !zero_checker.isZero(max[2] - min[2]) 00263 || !zero_checker.isZero(exit[2] - entrance[2]) 00264 || !zero_checker.isZero(exit[2] - min[2]) 00265 ) 00266 { 00267 return false; 00268 } 00269 } 00270 00271 if ( 00272 boost::is_same< 00273 MazePolicy 00274 , NoNegativeTurnWalkthroughMazePolicy 00275 >::value 00276 ) 00277 { 00278 const Coordinate end_x_maximum = max[0] - inc; 00279 const Coordinate end_x_minimum = min[0] + inc; 00280 const Coordinate end_y_maximum = max[1] - inc; 00281 const Coordinate end_y_minimum = min[1] + inc; 00282 const Coordinate start_x = entrance[0]; 00283 const Coordinate start_y = entrance[1]; 00284 const Coordinate end_x = exit[0]; 00285 const Coordinate end_y = exit[1]; 00286 00287 return 00288 ( 00289 (start_x >= end_x_minimum) && (start_x <= end_x_maximum) 00290 || (start_y >= end_y_minimum) && (start_y <= end_y_maximum) 00291 ) 00292 && ( 00293 (end_x >= end_x_minimum) && (end_x <= end_x_maximum) 00294 || (end_y >= end_y_minimum) && (end_y <= end_y_maximum) 00295 ); 00296 } 00297 00298 return true; 00299 } 00300 00301 public: 00302 template < 00303 typename MazeMaker 00304 , typename FSMInputMaker 00305 , typename MazePolicy 00306 , typename ArgumentPack 00307 > 00308 static bool 00309 areValidArguments( 00310 const MazeMaker& maze_maker 00311 , const FSMInputMaker& input_maker 00312 , const MazePolicy& policy 00313 , const ArgumentPack& p 00314 ) 00315 { 00316 typedef MSMAZES_CORE_PATTERN_TESSELATION_FORMER_TYPE( 00317 ArgumentPack 00318 , Pattern 00319 ) 00320 TesselationFormer; 00321 00322 return 00323 _areValidArgumentsByTesselation( 00324 maze_maker 00325 , input_maker 00326 , policy 00327 , p 00328 , typename TesselationFormer::tag() 00329 ); 00330 } 00331 }; 00332 00337 struct parameters 00338 : boost::parameter::parameters< 00339 boost::parameter::required< 00340 keyword_tag::rng_engine_arg 00341 > 00342 , boost::parameter::required< 00343 keyword_tag::maze_maker_arg 00344 > 00345 , boost::parameter::required< 00346 keyword_tag::fsm_input_maker_arg 00347 > 00348 , boost::parameter::required< 00349 keyword_tag::init_tesselation_selector_arg 00350 > 00351 , boost::parameter::required< 00352 keyword_tag::init_cell_minimum_arg 00353 > 00354 , boost::parameter::required< 00355 keyword_tag::init_cell_maximum_arg 00356 > 00357 , boost::parameter::required< 00358 keyword_tag::init_cell_increment_arg 00359 > 00360 , boost::parameter::required< 00361 keyword_tag::init_entrance_cell_arg 00362 > 00363 , boost::parameter::required< 00364 keyword_tag::init_exit_cell_arg 00365 > 00366 , boost::parameter::optional< 00367 keyword_tag::maze_policy_arg 00368 > 00369 , boost::parameter::optional< 00370 keyword_tag::init_zero_direction_arg 00371 > 00372 , boost::parameter::optional< 00373 keyword_tag::init_positive_rotation_arg 00374 > 00375 , boost::parameter::optional< 00376 keyword_tag::init_zero_tolerance_arg 00377 > 00378 > 00379 { 00380 }; 00381 } // namespace _parallelepiped_builder 00382 00384 00516 template < 00517 #ifndef MSMAZES_DOX 00518 typename DirectionType = unsigned int 00519 , typename DirectionChangeType = int 00520 , typename CellContainerSelector = boost::vecS 00521 , typename PiConstant = sgdk::Pi 00522 , typename TangentFunction = sgdk::Tangent 00523 #endif /* MSMAZES_DOX */ 00524 > 00525 class ParallelepipedFSMBuilder 00526 #ifndef MSMAZES_DOX 00527 : public FSMBuilder< 00528 Parallelepiped< 00529 DirectionType 00530 , DirectionChangeType 00531 , CellContainerSelector 00532 , PiConstant 00533 , TangentFunction 00534 > 00535 , _parallelepiped_builder::ArgumentValidationPolicy< 00536 Parallelepiped< 00537 DirectionType 00538 , DirectionChangeType 00539 , CellContainerSelector 00540 , PiConstant 00541 , TangentFunction 00542 > 00543 > 00544 > 00545 #endif /* MSMAZES_DOX */ 00546 { 00547 #ifndef MSMAZES_DOX 00548 private: 00549 typedef FSMBuilder< 00550 Parallelepiped< 00551 DirectionType 00552 , DirectionChangeType 00553 , CellContainerSelector 00554 , PiConstant 00555 , TangentFunction 00556 > 00557 , _parallelepiped_builder::ArgumentValidationPolicy< 00558 Parallelepiped< 00559 DirectionType 00560 , DirectionChangeType 00561 , CellContainerSelector 00562 , PiConstant 00563 , TangentFunction 00564 > 00565 > 00566 > 00567 ParentBuilder; 00568 #endif /* MSMAZES_DOX */ 00569 00570 public: 00576 #ifdef MSMAZES_DOX 00577 typedef implementation_defined StateIndex; 00578 #else 00579 typedef typename ParentBuilder::StateIndex 00580 StateIndex; 00581 #endif /* MSMAZES_DOX */ 00582 00588 #ifdef MSMAZES_DOX 00589 typedef implementation_defined InputIndex; 00590 #else 00591 typedef typename ParentBuilder::InputIndex 00592 InputIndex; 00593 #endif /* MSMAZES_DOX */ 00594 00600 #ifdef MSMAZES_DOX 00601 typedef implementation_defined MazeGraph; 00602 #else 00603 typedef typename ParentBuilder::MazeGraph 00604 MazeGraph; 00605 #endif /* MSMAZES_DOX */ 00606 00612 #ifdef MSMAZES_DOX 00613 typedef implementation_defined Pattern; 00614 #else 00615 typedef typename ParentBuilder::Pattern 00616 Pattern; 00617 #endif /* MSMAZES_DOX */ 00618 00624 #ifdef MSMAZES_DOX 00625 typedef implementation_defined Cell; 00626 #else 00627 typedef typename ParentBuilder::Cell 00628 Cell; 00629 #endif /* MSMAZES_DOX */ 00630 00637 #ifdef MSMAZES_DOX 00638 typedef implementation_defined Direction; 00639 #else 00640 typedef typename ParentBuilder::Direction 00641 Direction; 00642 #endif /* MSMAZES_DOX */ 00643 00650 #ifdef MSMAZES_DOX 00651 typedef implementation_defined ArgumentValidationPolicy; 00652 #else 00653 typedef typename ParentBuilder::ArgumentValidationPolicy 00654 ArgumentValidationPolicy; 00655 #endif /* MSMAZES_DOX */ 00656 00657 private: 00658 ParallelepipedFSMBuilder(const ParallelepipedFSMBuilder& copy) 00659 { 00660 } 00661 00662 public: 00664 00668 ParallelepipedFSMBuilder() 00669 : ParentBuilder() 00670 { 00671 } 00672 00674 00677 virtual ~ParallelepipedFSMBuilder() 00678 { 00679 } 00680 00681 #ifdef MSMAZES_DOX 00682 00846 template < 00847 typename RNGEngine 00848 , typename MazeMaker 00849 , typename FSMInputMaker 00850 , typename TesselationSelector 00851 , typename Increment 00852 , typename MazePolicy 00853 > 00854 bool initialize( 00855 RNGEngine& rng_engine_arg 00856 , const MazeMaker& maze_maker_arg 00857 , const FSMInputMaker& fsm_input_maker_arg 00858 , const TesselationSelector& init_tesselation_selector_arg 00859 , const Cell& init_cell_minimum_arg 00860 , const Cell& init_cell_maximum_arg 00861 , Increment init_cell_increment_arg 00862 , const Cell& init_entrance_cell_arg 00863 , const Cell& init_exit_cell_arg 00864 , const MazePolicy& maze_policy_arg 00865 , const sgdk::ZeroDirection& init_zero_direction_arg 00866 , const sgdk::PositiveRotation& init_positive_rotation_arg 00867 , const typename Pattern::Coordinate init_zero_tolerance_arg 00868 ); 00869 00876 template <typename Params> 00877 bool initialize_with_named_params(Params& p) 00878 #else 00879 BOOST_PARAMETER_MEMFUN( 00880 bool 00881 , initialize 00882 , 8 00883 , MSMAZES_CORE_FSM_ARITY 00884 , _parallelepiped_builder::parameters 00885 ) 00886 #endif /* MSMAZES_DOX */ 00887 { 00888 typedef typename boost::remove_const< 00889 typename boost::remove_reference< 00890 typename boost::parameter::binding< 00891 Params 00892 , keyword_tag::rng_engine_arg 00893 >::type 00894 >::type 00895 >::type 00896 RNGEngine; 00897 typedef typename boost::remove_const< 00898 typename boost::remove_reference< 00899 typename boost::parameter::binding< 00900 Params 00901 , keyword_tag::maze_maker_arg 00902 >::type 00903 >::type 00904 >::type 00905 MazeMaker; 00906 00907 RNGEngine& rng_engine = p[rng_engine_arg]; 00908 00909 return 00910 ParentBuilder::initialize( 00911 rng_engine 00912 , p[maze_maker_arg] 00913 , p[fsm_input_maker_arg] 00914 , p[ 00915 maze_policy_arg 00916 | typename MazeMakerTraits<MazeMaker>::DefaultPolicy() 00917 ] 00918 , ( 00919 init_tesselation_selector_arg 00920 = p[init_tesselation_selector_arg] 00921 , init_zero_tolerance_arg 00922 = p[init_zero_tolerance_arg | 0.00001] 00923 , init_zero_direction_arg 00924 = p[ 00925 init_zero_direction_arg 00926 | sgdk::ZeroDirection::POSITIVE_Y_AXIS 00927 ] 00928 , init_positive_rotation_arg 00929 = p[ 00930 init_positive_rotation_arg 00931 | sgdk::PositiveRotation::CLOCKWISE 00932 ] 00933 , init_cell_minimum_arg = p[init_cell_minimum_arg] 00934 , init_cell_maximum_arg = p[init_cell_maximum_arg] 00935 , init_cell_increment_arg = p[init_cell_increment_arg] 00936 , init_entrance_cell_arg = p[init_entrance_cell_arg] 00937 , init_exit_cell_arg = p[init_exit_cell_arg] 00938 ) 00939 ); 00940 } 00941 00947 inline const Pattern& getPattern() const 00948 { 00949 return ParentBuilder::getPattern(); 00950 } 00951 00957 inline const MazeGraph& getMazeGraph() const 00958 { 00959 return ParentBuilder::getMazeGraph(); 00960 } 00961 00967 inline bool isReady() const 00968 { 00969 return ParentBuilder::isReady(); 00970 } 00971 00978 template <typename TransitionFunction> 00979 void 00980 buildTransitionFunction( 00981 TransitionFunction& transition_function 00982 ) const 00983 { 00984 ParentBuilder::buildTransitionFunction(transition_function); 00985 } 00986 00992 inline StateIndex getSourceState() const 00993 { 00994 return ParentBuilder::getSourceState(); 00995 } 00996 01002 inline StateIndex getTargetState() const 01003 { 01004 return ParentBuilder::getTargetState(); 01005 } 01006 01013 bool hasSolutionFromState(const StateIndex source_state) const 01014 { 01015 return ParentBuilder::hasSolutionFromState(source_state); 01016 } 01017 01023 InputIndex getCorrectInput(const StateIndex source_state) const 01024 { 01025 return ParentBuilder::getCorrectInput(source_state); 01026 } 01027 01033 const Cell& getStateCell(const StateIndex state) const 01034 { 01035 return ParentBuilder::getStateCell(state); 01036 } 01037 01044 Direction getStateDirection(const StateIndex state) const 01045 { 01046 return ParentBuilder::getStateDirection(state); 01047 } 01048 }; 01049 } // namespace msmazes 01050 01051 #undef MSMAZES_CORE_FSM_ARITY 01052 01053 #endif /* MSMAZES_CORE_FSM_BUILDER_PARALLELEPIPED_HPP */
Multi-State Mazes in C++ is hosted by . Use the Table of Contents for navigation.