fsm/builder/parallelepiped.hpp

Go to the documentation of this file.
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 SourceForge.net. Use the Table of Contents for navigation.