diff --git a/src/storm/builder/ChoiceInformationBuilder.cpp b/src/storm/builder/ChoiceInformationBuilder.cpp
deleted file mode 100644
index 6578fe590..000000000
--- a/src/storm/builder/ChoiceInformationBuilder.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "storm/builder/ChoiceInformationBuilder.h"
-
-namespace storm {
-    namespace builder {
-         
-        void ChoiceInformationBuilder::addLabel(std::string const& label, uint_fast64_t choiceIndex) {
-            storm::storage::BitVector& labeledChoices = labels[label];
-            labeledChoices.grow(choiceIndex + 1);
-            labeledChoices.set(choiceIndex, true);
-        }
-        
-        void ChoiceInformationBuilder::addOriginData(boost::any const& originData, uint_fast64_t choiceIndex) {
-            if (dataOfOrigins.size() != choiceIndex) {
-                dataOfOrigins.resize(choiceIndex);
-            }
-            dataOfOrigins.push_back(originData);
-        }
-        
-        boost::optional<storm::models::sparse::ChoiceLabeling> ChoiceInformationBuilder::buildChoiceLabeling(uint_fast64_t totalNumberOfChoices) {
-            if (labels.empty()) {
-                return boost::none;
-            } else {
-                storm::models::sparse::ChoiceLabeling result(totalNumberOfChoices);
-                for (auto& label : labels) {
-                    label.second.resize(totalNumberOfChoices, false);
-                    result.addLabel(label.first, std::move(label.second));
-                }
-                return result;
-            }
-        }
-            
-        std::vector<boost::any> ChoiceInformationBuilder::buildDataOfChoiceOrigins(uint_fast64_t totalNumberOfChoices) {
-            dataOfOrigins.resize(totalNumberOfChoices);
-            return std::move(dataOfOrigins);
-        }
-        
-    }
-}
diff --git a/src/storm/builder/ChoiceInformationBuilder.h b/src/storm/builder/ChoiceInformationBuilder.h
deleted file mode 100644
index 8dbe8721a..000000000
--- a/src/storm/builder/ChoiceInformationBuilder.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-#include <boost/any.hpp>
-
-#include "storm/models/sparse/ChoiceLabeling.h"
-#include "storm/storage/BitVector.h"
-#include "storm/storage/sparse/PrismChoiceOrigins.h"
-#include "storm/storage/prism/Program.h"
-
-
-namespace storm {
-    namespace builder {
-        
-        /*!
-         * This class collects information regarding the choices
-         */
-        class ChoiceInformationBuilder {
-        public:
-            
-            ChoiceInformationBuilder() = default;
-
-            void addLabel(std::string const& label, uint_fast64_t choiceIndex);
-            
-            void addOriginData(boost::any const& originData, uint_fast64_t choiceIndex);
-            
-            boost::optional<storm::models::sparse::ChoiceLabeling> buildChoiceLabeling(uint_fast64_t totalNumberOfChoices);
-            
-            std::vector<boost::any> buildDataOfChoiceOrigins(uint_fast64_t totalNumberOfChoices);
-            
-        private:
-            std::unordered_map<std::string, storm::storage::BitVector> labels;
-            std::vector<boost::any> dataOfOrigins;
-        };
-    }
-}
-    
diff --git a/src/storm/builder/ExplicitModelBuilder.cpp b/src/storm/builder/ExplicitModelBuilder.cpp
index 10e0c8927..b80825d1d 100644
--- a/src/storm/builder/ExplicitModelBuilder.cpp
+++ b/src/storm/builder/ExplicitModelBuilder.cpp
@@ -4,7 +4,7 @@
 
 
 #include "storm/builder/RewardModelBuilder.h"
-#include "storm/builder/ChoiceInformationBuilder.h"
+#include "storm/builder/StateAndChoiceInformationBuilder.h"
 
 #include "storm/exceptions/AbortException.h"
 #include "storm/exceptions/WrongFormatException.h"
@@ -120,18 +120,11 @@ namespace storm {
         }
 
         template <typename ValueType, typename RewardModelType, typename StateType>
-        void ExplicitModelBuilder<ValueType, RewardModelType, StateType>::buildMatrices(storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, std::vector<RewardModelBuilder<typename RewardModelType::ValueType>>& rewardModelBuilders, ChoiceInformationBuilder& choiceInformationBuilder, boost::optional<storm::storage::BitVector>& markovianStates, boost::optional<std::vector<uint_fast32_t>> playerActionIndices, boost::optional<storm::storage::sparse::StateValuationsBuilder>& stateValuationsBuilder) {
+        void ExplicitModelBuilder<ValueType, RewardModelType, StateType>::buildMatrices(storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, std::vector<RewardModelBuilder<typename RewardModelType::ValueType>>& rewardModelBuilders, StateAndChoiceInformationBuilder& stateAndChoiceInformationBuilder) {
 
-            // Create markovian states bit vector, if required.
-            if (generator->getModelType() == storm::generator::ModelType::MA) {
-                // The bit vector will be resized when the correct size is known.
-                markovianStates = storm::storage::BitVector(1000);
-            }
-
-            // Create the player indices vector, if required.
-            if (generator->getModelType() == storm::generator::ModelType::SMG) {
-                playerActionIndices = std::vector<uint_fast32_t>{};
-                playerActionIndices.get().reserve(1000);
+            // Initialize building state valuations (if necessary)
+            if (stateAndChoiceInformationBuilder.isBuildStateValuations()) {
+                stateAndChoiceInformationBuilder.stateValuationsBuilder() = generator->initializeStateValuationsBuilder();
             }
 
             // Create a callback for the next-state generator to enable it to request the index of states.
@@ -175,8 +168,8 @@ namespace storm {
                 }
 
                 generator->load(currentState);
-                if (stateValuationsBuilder) {
-                    generator->addStateValuation(currentIndex, stateValuationsBuilder.get());
+                if (stateAndChoiceInformationBuilder.isBuildStateValuations()) {
+                    generator->addStateValuation(currentIndex, stateAndChoiceInformationBuilder.stateValuationsBuilder());
                 }
                 storm::generator::StateBehavior<ValueType, StateType> behavior = generator->expand(stateToIdCallback);
 
@@ -188,11 +181,6 @@ namespace storm {
                             this->stateStorage.deadlockStateIndices.push_back(currentIndex);
                         }
 
-                        if (markovianStates) {
-                            markovianStates.get().grow(currentRowGroup + 1, false);
-                            markovianStates.get().set(currentRowGroup);
-                        }
-
                         if (!generator->isDeterministicModel()) {
                             transitionMatrixBuilder.newRowGroup(currentRow);
                         }
@@ -208,11 +196,14 @@ namespace storm {
                                 rewardModelBuilder.addStateActionReward(storm::utility::zero<ValueType>());
                             }
                         }
-
-                        if (playerActionIndices) {
-                            // TODO change this to storm::utility::infinity<ValueType>() ?
-                            playerActionIndices.get().push_back(-1);
+                        
+                        // This state shall be Markovian (to not introduce Zeno behavior)
+                        if (stateAndChoiceInformationBuilder.isBuildMarkovianStates()) {
+                            stateAndChoiceInformationBuilder.addMarkovianState(currentRowGroup);
                         }
+                        // Other state-based information does not need to be treated, in particular:
+                        // * StateValuations have already been set above
+                        // * The associated player shall be the "default" player, i.e. INVALID_PLAYER_INDEX
 
                         ++currentRow;
                         ++currentRowGroup;
@@ -235,22 +226,26 @@ namespace storm {
                     }
 
                     // Now add all choices.
+                    bool firstChoiceOfState = true;
                     for (auto const& choice : behavior) {
 
                         // add the generated choice information
-                        if (choice.hasLabels()) {
+                        if (stateAndChoiceInformationBuilder.isBuildChoiceLabels() && choice.hasLabels()) {
                             for (auto const& label : choice.getLabels()) {
-                                choiceInformationBuilder.addLabel(label, currentRow);
+                                stateAndChoiceInformationBuilder.addChoiceLabel(label, currentRow);
                             }
                         }
-                        if (choice.hasOriginData()) {
-                            choiceInformationBuilder.addOriginData(choice.getOriginData(), currentRow);
+                        if (stateAndChoiceInformationBuilder.isBuildChoiceOrigins() && choice.hasOriginData()) {
+                            stateAndChoiceInformationBuilder.addChoiceOriginData(choice.getOriginData(), currentRow);
                         }
-
-                        // If we keep track of the Markovian choices, store whether the current one is Markovian.
-                        if (markovianStates && choice.isMarkovian()) {
-                            markovianStates.get().grow(currentRowGroup + 1, false);
-                            markovianStates.get().set(currentRowGroup);
+                        if (stateAndChoiceInformationBuilder.isBuildStatePlayerIndications() && choice.hasPlayerIndex()) {
+                            STORM_LOG_ASSERT(firstChoiceOfState || stateAndChoiceInformationBuilder.hasStatePlayerIndicationBeenSet(choice.getPlayerIndex(), currentRowGroup), "There is a state where different players have an enabled choice."); // Should have been detected in generator, already
+                            if (firstChoiceOfState) {
+                                stateAndChoiceInformationBuilder.addStatePlayerIndication(choice.getPlayerIndex(), currentRowGroup);
+                            }
+                        }
+                        if (stateAndChoiceInformationBuilder.isBuildMarkovianStates() &&  choice.isMarkovian()) {
+                            stateAndChoiceInformationBuilder.addMarkovianState(currentRowGroup);
                         }
 
                         // Add the probabilistic behavior to the matrix.
@@ -267,11 +262,9 @@ namespace storm {
                             ++choiceRewardIt;
                         }
                         ++currentRow;
+                        firstChoiceOfState = false;
                     }
 
-                    if (playerActionIndices) {
-                        playerActionIndices.get().push_back(behavior.getChoices().at(0).getPlayerIndex());
-                    }
                     ++currentRowGroup;
                 }
 
@@ -298,15 +291,6 @@ namespace storm {
                 }
             }
 
-            if (markovianStates) {
-                // Since we now know the correct size, cut the bit vector to the correct length.
-                markovianStates->resize(currentRowGroup, false);
-            }
-
-            if (playerActionIndices) {
-                playerActionIndices.get().shrink_to_fit();
-            }
-
             // If the exploration order was not breadth-first, we need to fix the entries in the matrix according to
             // (reversed) mapping of row groups to indices.
             if (options.explorationOrder != ExplorationOrder::Bfs) {
@@ -348,39 +332,48 @@ namespace storm {
             for (uint64_t i = 0; i < generator->getNumberOfRewardModels(); ++i) {
                 rewardModelBuilders.emplace_back(generator->getRewardModelInformation(i));
             }
-            ChoiceInformationBuilder choiceInformationBuilder;
-            boost::optional<storm::storage::BitVector> markovianStates;
-            boost::optional<std::vector<uint_fast32_t>> playerActionIndices;
-
-            // If we need to build state valuations, initialize them now.
-            boost::optional<storm::storage::sparse::StateValuationsBuilder> stateValuationsBuilder;
-            if (generator->getOptions().isBuildStateValuationsSet()) {
-                stateValuationsBuilder = generator->initializeStateValuationsBuilder();
-            }
-
-            buildMatrices(transitionMatrixBuilder, rewardModelBuilders, choiceInformationBuilder, markovianStates, playerActionIndices, stateValuationsBuilder);
-
+            StateAndChoiceInformationBuilder stateAndChoiceInformationBuilder;
+            stateAndChoiceInformationBuilder.setBuildChoiceLabels(generator->getOptions().isBuildChoiceLabelsSet());
+            stateAndChoiceInformationBuilder.setBuildChoiceOrigins(generator->getOptions().isBuildChoiceOriginsSet());
+            stateAndChoiceInformationBuilder.setBuildStatePlayerIndications(generator->getModelType() == storm::generator::ModelType::SMG);
+            stateAndChoiceInformationBuilder.setBuildMarkovianStates(generator->getModelType() == storm::generator::ModelType::MA);
+            stateAndChoiceInformationBuilder.setBuildStateValuations(generator->getOptions().isBuildStateValuationsSet());
+
+            buildMatrices(transitionMatrixBuilder, rewardModelBuilders, stateAndChoiceInformationBuilder);
+            
             // Initialize the model components with the obtained information.
-            storm::storage::sparse::ModelComponents<ValueType, RewardModelType> modelComponents(transitionMatrixBuilder.build(0, transitionMatrixBuilder.getCurrentRowGroupCount()), buildStateLabeling(), std::unordered_map<std::string, RewardModelType>(), !generator->isDiscreteTimeModel(), std::move(markovianStates), /* player1Matrix = */ boost::none, std::move(playerActionIndices));
+            storm::storage::sparse::ModelComponents<ValueType, RewardModelType> modelComponents(transitionMatrixBuilder.build(0, transitionMatrixBuilder.getCurrentRowGroupCount()), buildStateLabeling(), std::unordered_map<std::string, RewardModelType>(), !generator->isDiscreteTimeModel());
+
+            uint_fast64_t numStates = modelComponents.transitionMatrix.getColumnCount();
+            uint_fast64_t numChoices = modelComponents.transitionMatrix.getRowCount();
 
             // Now finalize all reward models.
             for (auto& rewardModelBuilder : rewardModelBuilders) {
-                modelComponents.rewardModels.emplace(rewardModelBuilder.getName(), rewardModelBuilder.build(modelComponents.transitionMatrix.getRowCount(), modelComponents.transitionMatrix.getColumnCount(), modelComponents.transitionMatrix.getRowGroupCount()));
+                modelComponents.rewardModels.emplace(rewardModelBuilder.getName(), rewardModelBuilder.build(numChoices, modelComponents.transitionMatrix.getColumnCount(), numStates));
+            }
+            // Build the player assignment
+            if (stateAndChoiceInformationBuilder.isBuildStatePlayerIndications()) {
+                modelComponents.statePlayerIndications = stateAndChoiceInformationBuilder.buildStatePlayerIndications(numStates);
+                modelComponents.playerNameToIndexMap = generator->getPlayerNameToIndexMap();
+            }
+            // Build Markovian states
+            if (stateAndChoiceInformationBuilder.isBuildMarkovianStates()) {
+                modelComponents.markovianStates = stateAndChoiceInformationBuilder.buildMarkovianStates(numStates);
             }
             // Build the choice labeling
-            modelComponents.choiceLabeling = choiceInformationBuilder.buildChoiceLabeling(modelComponents.transitionMatrix.getRowCount());
-
+            if (stateAndChoiceInformationBuilder.isBuildChoiceLabels()) {
+                modelComponents.choiceLabeling = stateAndChoiceInformationBuilder.buildChoiceLabeling(numChoices);
+            }
             // If requested, build the state valuations and choice origins
-            if (stateValuationsBuilder) {
-                modelComponents.stateValuations = stateValuationsBuilder->build(modelComponents.transitionMatrix.getRowGroupCount());
+            if (stateAndChoiceInformationBuilder.isBuildStateValuations()) {
+                modelComponents.stateValuations = stateAndChoiceInformationBuilder.stateValuationsBuilder().build(numStates);
             }
-            if (generator->getOptions().isBuildChoiceOriginsSet()) {
-                auto originData = choiceInformationBuilder.buildDataOfChoiceOrigins(modelComponents.transitionMatrix.getRowCount());
+            if (stateAndChoiceInformationBuilder.isBuildChoiceOrigins()) {
+                auto originData = stateAndChoiceInformationBuilder.buildDataOfChoiceOrigins(numChoices);
                 modelComponents.choiceOrigins = generator->generateChoiceOrigins(originData);
             }
             if (generator->isPartiallyObservable()) {
-                std::vector<uint32_t> classes;
-                classes.resize(stateStorage.getNumberOfStates());
+                std::vector<uint32_t> classes(stateStorage.getNumberOfStates());
                 std::unordered_map<uint32_t, std::vector<std::pair<std::vector<std::string>, uint32_t>>> observationActions;
                 for (auto const& bitVectorIndexPair : stateStorage.stateToId) {
                     uint32_t varObservation = generator->observabilityClass(bitVectorIndexPair.first);
diff --git a/src/storm/builder/ExplicitModelBuilder.h b/src/storm/builder/ExplicitModelBuilder.h
index af068b3fa..f33b37ba3 100644
--- a/src/storm/builder/ExplicitModelBuilder.h
+++ b/src/storm/builder/ExplicitModelBuilder.h
@@ -43,7 +43,7 @@ namespace storm {
         
         // Forward-declare classes.
         template <typename ValueType> class RewardModelBuilder;
-        class ChoiceInformationBuilder;
+        class StateAndChoiceInformationBuilder;
 
         template<typename StateType>
         class ExplicitStateLookup {
@@ -127,11 +127,9 @@ namespace storm {
              *
              * @param transitionMatrixBuilder The builder of the transition matrix.
              * @param rewardModelBuilders The builders for the selected reward models.
-             * @param choiceInformationBuilder The builder for the requested information of the choices
-             * @param markovianChoices is set to a bit vector storing whether a choice is Markovian (is only set if the model type requires this information).
-             * @param stateValuationsBuilder if not boost::none, we insert valuations for the corresponding states
+             * @param stateAndChoiceInformationBuilder The builder for the requested information of the individual states and choices
              */
-            void buildMatrices(storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, std::vector<RewardModelBuilder<typename RewardModelType::ValueType>>& rewardModelBuilders, ChoiceInformationBuilder& choiceInformationBuilder, boost::optional<storm::storage::BitVector>& markovianChoices, boost::optional<std::vector<uint_fast32_t>> playerActionIndices, boost::optional<storm::storage::sparse::StateValuationsBuilder>& stateValuationsBuilder);
+            void buildMatrices(storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, std::vector<RewardModelBuilder<typename RewardModelType::ValueType>>& rewardModelBuilders, StateAndChoiceInformationBuilder& stateAndChoiceInformationBuilder);
 
             /*!
              * Explores the state space of the given program and returns the components of the model as a result.
diff --git a/src/storm/builder/StateAndChoiceInformationBuilder.cpp b/src/storm/builder/StateAndChoiceInformationBuilder.cpp
new file mode 100644
index 000000000..13d21624a
--- /dev/null
+++ b/src/storm/builder/StateAndChoiceInformationBuilder.cpp
@@ -0,0 +1,121 @@
+#include "storm/builder/StateAndChoiceInformationBuilder.h"
+
+namespace storm {
+    namespace builder {
+
+        StateAndChoiceInformationBuilder::StateAndChoiceInformationBuilder() : _buildChoiceLabels(false), _buildChoiceOrigins(false), _buildStatePlayerIndications(false), _buildMarkovianStates(false), _buildStateValuations(false) {
+            // Intentionally left empty
+        }
+
+        void StateAndChoiceInformationBuilder::setBuildChoiceLabels(bool value) {
+            _buildChoiceLabels = value;
+        }
+
+        bool StateAndChoiceInformationBuilder::isBuildChoiceLabels() const {
+            return _buildChoiceLabels;
+        }
+
+        void StateAndChoiceInformationBuilder::addChoiceLabel(std::string const& label, uint_fast64_t choiceIndex) {
+            STORM_LOG_ASSERT(_buildChoiceLabels, "Building ChoiceLabels was not enabled.");
+            storm::storage::BitVector& labeledChoices = _choiceLabels[label];
+            labeledChoices.grow(choiceIndex + 1, false);
+            labeledChoices.set(choiceIndex, true);
+        }
+
+        storm::models::sparse::ChoiceLabeling StateAndChoiceInformationBuilder::buildChoiceLabeling(uint_fast64_t totalNumberOfChoices) {
+            storm::models::sparse::ChoiceLabeling result(totalNumberOfChoices);
+            for (auto& label : _choiceLabels) {
+                label.second.resize(totalNumberOfChoices, false);
+                result.addLabel(label.first, std::move(label.second));
+            }
+            return result;
+        }
+
+        void StateAndChoiceInformationBuilder::setBuildChoiceOrigins(bool value) {
+            _buildChoiceOrigins = value;
+        }
+
+        bool StateAndChoiceInformationBuilder::isBuildChoiceOrigins() const {
+            return _buildChoiceOrigins;
+        }
+
+        void StateAndChoiceInformationBuilder::addChoiceOriginData(boost::any const& originData, uint_fast64_t choiceIndex) {
+            STORM_LOG_ASSERT(_buildChoiceOrigins, "Building ChoiceOrigins was not enabled.");
+            STORM_LOG_ASSERT(_dataOfChoiceOrigins.size() <= choiceIndex, "Unexpected choice index. Apparently, the choice indices are provided in an incorrect order.");
+            if (_dataOfChoiceOrigins.size() != choiceIndex) {
+                _dataOfChoiceOrigins.resize(choiceIndex);
+            }
+            _dataOfChoiceOrigins.push_back(originData);
+        }
+
+        std::vector<boost::any> StateAndChoiceInformationBuilder::buildDataOfChoiceOrigins(uint_fast64_t totalNumberOfChoices) {
+            STORM_LOG_ASSERT(_buildChoiceOrigins, "Building ChoiceOrigins was not enabled.");
+            _dataOfChoiceOrigins.resize(totalNumberOfChoices);
+            _dataOfChoiceOrigins.shrink_to_fit();
+            return std::move(_dataOfChoiceOrigins);
+        }
+
+        void StateAndChoiceInformationBuilder::setBuildStatePlayerIndications(bool value) {
+            _buildStatePlayerIndications = value;
+        }
+
+        bool StateAndChoiceInformationBuilder::isBuildStatePlayerIndications() const {
+            return _buildStatePlayerIndications;
+        }
+
+        void StateAndChoiceInformationBuilder::addStatePlayerIndication(storm::storage::PlayerIndex player, uint_fast64_t stateIndex) {
+            STORM_LOG_ASSERT(_buildStatePlayerIndications, "Building StatePlayerIndications was not enabled.");
+            STORM_LOG_ASSERT(_statePlayerIndications.size() <= stateIndex, "Unexpected choice index. Apparently, the choice indices are provided in an incorrect order.");
+            if (_statePlayerIndications.size() != stateIndex) {
+                _statePlayerIndications.resize(stateIndex, storm::storage::INVALID_PLAYER_INDEX);
+            }
+            _statePlayerIndications.push_back(player);
+        }
+
+        bool StateAndChoiceInformationBuilder::hasStatePlayerIndicationBeenSet(storm::storage::PlayerIndex expectedPlayer, uint_fast64_t stateIndex) const {
+            STORM_LOG_ASSERT(_buildStatePlayerIndications, "Building StatePlayerIndications was not enabled.");
+            return (stateIndex < _statePlayerIndications.size()) && (_statePlayerIndications[stateIndex] == expectedPlayer);
+        }
+
+        std::vector<storm::storage::PlayerIndex> StateAndChoiceInformationBuilder::buildStatePlayerIndications(uint_fast64_t totalNumberOfStates) {
+            STORM_LOG_ASSERT(_buildStatePlayerIndications, "Building StatePlayerIndications was not enabled.");
+            _statePlayerIndications.resize(totalNumberOfStates, storm::storage::INVALID_PLAYER_INDEX);
+            _statePlayerIndications.shrink_to_fit();
+            return std::move(_statePlayerIndications);
+        }
+
+        void StateAndChoiceInformationBuilder::setBuildMarkovianStates(bool value) {
+            _buildMarkovianStates = value;
+        }
+
+        bool StateAndChoiceInformationBuilder::isBuildMarkovianStates() const {
+            return _buildMarkovianStates;
+        }
+
+        void StateAndChoiceInformationBuilder::addMarkovianState(uint_fast64_t markovianStateIndex) {
+            STORM_LOG_ASSERT(_buildMarkovianStates, "Building MarkovianStates was not enabled.");
+            _markovianStates.grow(markovianStateIndex + 1, false);
+            _markovianStates.set(markovianStateIndex, true);
+        }
+
+        storm::storage::BitVector StateAndChoiceInformationBuilder::buildMarkovianStates(uint_fast64_t totalNumberOfStates) {
+            STORM_LOG_ASSERT(_buildMarkovianStates, "Building MarkovianStates was not enabled.");
+            _markovianStates.resize(totalNumberOfStates, false);
+            return _markovianStates;
+        }
+
+        void StateAndChoiceInformationBuilder::setBuildStateValuations(bool value) {
+            _buildStateValuations = value;
+        }
+
+        bool StateAndChoiceInformationBuilder::isBuildStateValuations() const {
+            return _buildStateValuations;
+        }
+
+        storm::storage::sparse::StateValuationsBuilder& StateAndChoiceInformationBuilder::stateValuationsBuilder() {
+            STORM_LOG_ASSERT(_buildStateValuations, "Building StateValuations was not enabled.");
+            return _stateValuationsBuilder;
+        }
+
+    }
+}
diff --git a/src/storm/builder/StateAndChoiceInformationBuilder.h b/src/storm/builder/StateAndChoiceInformationBuilder.h
new file mode 100644
index 000000000..413dcd50f
--- /dev/null
+++ b/src/storm/builder/StateAndChoiceInformationBuilder.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+#include <boost/any.hpp>
+
+#include "storm/models/sparse/ChoiceLabeling.h"
+#include "storm/storage/BitVector.h"
+#include "storm/storage/PlayerIndex.h"
+#include "storm/storage/sparse/PrismChoiceOrigins.h"
+#include "storm/storage/prism/Program.h"
+#include "storm/storage/sparse/StateValuations.h"
+
+
+namespace storm {
+    namespace builder {
+        
+        /*!
+         * This class collects information regarding the states and choices during model building.
+         * It is expected that the provided indices are in ascending order
+         */
+        class StateAndChoiceInformationBuilder {
+        public:
+            
+            StateAndChoiceInformationBuilder();
+
+            void setBuildChoiceLabels(bool value);
+            bool isBuildChoiceLabels() const;
+            void addChoiceLabel(std::string const& label, uint_fast64_t choiceIndex);
+            storm::models::sparse::ChoiceLabeling buildChoiceLabeling(uint_fast64_t totalNumberOfChoices);
+
+            void setBuildChoiceOrigins(bool value);
+            bool isBuildChoiceOrigins() const;
+            void addChoiceOriginData(boost::any const& originData, uint_fast64_t choiceIndex);
+            std::vector<boost::any> buildDataOfChoiceOrigins(uint_fast64_t totalNumberOfChoices);
+            
+            void setBuildStatePlayerIndications(bool value);
+            bool isBuildStatePlayerIndications() const;
+            /*!
+             * @note: skipped choiceIndices get assigned the invalid player index.
+             */
+            void addStatePlayerIndication(storm::storage::PlayerIndex player, uint_fast64_t stateIndex);
+            bool hasStatePlayerIndicationBeenSet(storm::storage::PlayerIndex expectedPlayer, uint_fast64_t stateIndex) const;
+            std::vector<storm::storage::PlayerIndex> buildStatePlayerIndications(uint_fast64_t totalNumberOfStates);
+            
+            void setBuildMarkovianStates(bool value);
+            bool isBuildMarkovianStates() const;
+            void addMarkovianState(uint_fast64_t markovianStateIndex);
+            storm::storage::BitVector buildMarkovianStates(uint_fast64_t  totalNumberOfStates);
+            
+            void setBuildStateValuations(bool value);
+            bool isBuildStateValuations() const;
+            storm::storage::sparse::StateValuationsBuilder& stateValuationsBuilder();
+            
+        private:
+            bool _buildChoiceLabels;
+            std::unordered_map<std::string, storm::storage::BitVector> _choiceLabels;
+            
+            bool _buildChoiceOrigins;
+            std::vector<boost::any> _dataOfChoiceOrigins;
+            
+            bool _buildStatePlayerIndications;
+            std::vector<storm::storage::PlayerIndex> _statePlayerIndications;
+            
+            bool _buildMarkovianStates;
+            storm::storage::BitVector _markovianStates;
+            
+            bool _buildStateValuations;
+            storm::storage::sparse::StateValuationsBuilder _stateValuationsBuilder;
+        };
+    }
+}
+    
diff --git a/src/storm/generator/Choice.cpp b/src/storm/generator/Choice.cpp
index fc1d41999..a0efb04f9 100644
--- a/src/storm/generator/Choice.cpp
+++ b/src/storm/generator/Choice.cpp
@@ -3,7 +3,6 @@
 #include "storm/adapters/RationalFunctionAdapter.h"
 
 #include "storm/utility/constants.h"
-#include "storm/builder/ChoiceInformationBuilder.h"
 
 #include "storm/utility/macros.h"
 #include "storm/exceptions/InvalidOperationException.h"
diff --git a/src/storm/generator/NextStateGenerator.cpp b/src/storm/generator/NextStateGenerator.cpp
index b68380935..4112920e4 100644
--- a/src/storm/generator/NextStateGenerator.cpp
+++ b/src/storm/generator/NextStateGenerator.cpp
@@ -278,6 +278,11 @@ namespace storm {
             return classId;
         }
 
+        template<typename ValueType, typename StateType>
+        std::map<std::string, storm::storage::PlayerIndex> NextStateGenerator<ValueType, StateType>::getPlayerNameToIndexMap() const {
+            STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Generating player mappings is not supported for this model input format");
+        }
+        
         template<typename ValueType, typename StateType>
         void NextStateGenerator<ValueType, StateType>::remapStateIds(std::function<StateType(StateType const&)> const& remapping) {
             if (overlappingGuardStates != boost::none) {
diff --git a/src/storm/generator/NextStateGenerator.h b/src/storm/generator/NextStateGenerator.h
index 671158870..eee62412d 100644
--- a/src/storm/generator/NextStateGenerator.h
+++ b/src/storm/generator/NextStateGenerator.h
@@ -11,6 +11,7 @@
 #include "storm/storage/expressions/ExpressionEvaluator.h"
 #include "storm/storage/sparse/ChoiceOrigins.h"
 #include "storm/storage/sparse/StateValuations.h"
+#include "storm/storage/PlayerIndex.h"
 
 #include "storm/builder/BuilderOptions.h"
 #include "storm/builder/RewardModelInformation.h"
@@ -74,6 +75,8 @@ namespace storm {
             std::string stateToString(CompressedState const& state) const;
 
             uint32_t observabilityClass(CompressedState const& state) const;
+            
+            virtual std::map<std::string, storm::storage::PlayerIndex> getPlayerNameToIndexMap() const;
 
             virtual storm::models::sparse::StateLabeling label(storm::storage::sparse::StateStorage<StateType> const& stateStorage, std::vector<StateType> const& initialStateIndices = {}, std::vector<StateType> const& deadlockStateIndices = {}) = 0;
 
diff --git a/src/storm/generator/PrismNextStateGenerator.cpp b/src/storm/generator/PrismNextStateGenerator.cpp
index ecf7e792d..ead36e763 100644
--- a/src/storm/generator/PrismNextStateGenerator.cpp
+++ b/src/storm/generator/PrismNextStateGenerator.cpp
@@ -734,6 +734,11 @@ namespace storm {
             }
         }
 
+        template<typename ValueType, typename StateType>
+        std::map<std::string, storm::storage::PlayerIndex> PrismNextStateGenerator<ValueType, StateType>::getPlayerNameToIndexMap() const {
+            return program.getPlayerNameToIndexMapping();
+        }
+
         template<typename ValueType, typename StateType>
         storm::models::sparse::StateLabeling PrismNextStateGenerator<ValueType, StateType>::label(storm::storage::sparse::StateStorage<StateType> const& stateStorage, std::vector<StateType> const& initialStateIndices, std::vector<StateType> const& deadlockStateIndices) {
             // Gather a vector of labels and their expressions.
diff --git a/src/storm/generator/PrismNextStateGenerator.h b/src/storm/generator/PrismNextStateGenerator.h
index 4e1901134..e8a7a81ff 100644
--- a/src/storm/generator/PrismNextStateGenerator.h
+++ b/src/storm/generator/PrismNextStateGenerator.h
@@ -4,7 +4,6 @@
 #include "storm/generator/NextStateGenerator.h"
 
 #include "storm/storage/prism/Program.h"
-#include "storm/storage/PlayerIndex.h"
 #include "storm/storage/BoostTypes.h"
 
 namespace storm {
@@ -43,7 +42,8 @@ namespace storm {
 
             virtual std::size_t getNumberOfRewardModels() const override;
             virtual storm::builder::RewardModelInformation getRewardModelInformation(uint64_t const& index) const override;
-            
+            virtual std::map<std::string, storm::storage::PlayerIndex> getPlayerNameToIndexMap() const override;
+
             virtual storm::models::sparse::StateLabeling label(storm::storage::sparse::StateStorage<StateType> const& stateStorage, std::vector<StateType> const& initialStateIndices = {}, std::vector<StateType> const& deadlockStateIndices = {}) override;
 
             virtual std::shared_ptr<storm::storage::sparse::ChoiceOrigins> generateChoiceOrigins(std::vector<boost::any>& dataForChoiceOrigins) const override;
diff --git a/src/storm/storage/sparse/ModelComponents.h b/src/storm/storage/sparse/ModelComponents.h
index 29ae3d14b..1011efbd7 100644
--- a/src/storm/storage/sparse/ModelComponents.h
+++ b/src/storm/storage/sparse/ModelComponents.h
@@ -13,6 +13,7 @@
 #include "storm/storage/sparse/ChoiceOrigins.h"
 #include "storm/storage/SparseMatrix.h"
 #include "storm/storage/BitVector.h"
+#include "storm/storage/PlayerIndex.h"
 #include "storm/models/sparse/StandardRewardModel.h"
 
 #include "storm/utility/macros.h"
@@ -30,9 +31,8 @@ namespace storm {
                                 std::unordered_map<std::string, RewardModelType> const& rewardModels =  std::unordered_map<std::string, RewardModelType>(),
                                 bool rateTransitions = false,
                                 boost::optional<storm::storage::BitVector> const& markovianStates = boost::none,
-                                boost::optional<storm::storage::SparseMatrix<storm::storage::sparse::state_type>> const& player1Matrix = boost::none,
-                                boost::optional<std::vector<uint_fast32_t>> const& playerActionIndices = boost::none)
-                        : transitionMatrix(transitionMatrix), stateLabeling(stateLabeling), rewardModels(rewardModels), rateTransitions(rateTransitions), markovianStates(markovianStates), player1Matrix(player1Matrix), playerActionIndices(playerActionIndices) {
+                                boost::optional<storm::storage::SparseMatrix<storm::storage::sparse::state_type>> const& player1Matrix = boost::none)
+                        : transitionMatrix(transitionMatrix), stateLabeling(stateLabeling), rewardModels(rewardModels), rateTransitions(rateTransitions), markovianStates(markovianStates), player1Matrix(player1Matrix) {
                     // Intentionally left empty
                 }
 
@@ -41,15 +41,12 @@ namespace storm {
                                 std::unordered_map<std::string, RewardModelType>&& rewardModels =  std::unordered_map<std::string, RewardModelType>(),
                                 bool rateTransitions = false,
                                 boost::optional<storm::storage::BitVector>&& markovianStates = boost::none,
-                                boost::optional<storm::storage::SparseMatrix<storm::storage::sparse::state_type>>&& player1Matrix = boost::none,
-                                boost::optional<std::vector<uint_fast32_t>>&& playerActionIndices = boost::none)
-                        : transitionMatrix(std::move(transitionMatrix)), stateLabeling(std::move(stateLabeling)), rewardModels(std::move(rewardModels)), rateTransitions(rateTransitions), markovianStates(std::move(markovianStates)), player1Matrix(std::move(player1Matrix)), playerActionIndices(std::move(playerActionIndices)) {
+                                boost::optional<storm::storage::SparseMatrix<storm::storage::sparse::state_type>>&& player1Matrix = boost::none)
+                        : transitionMatrix(std::move(transitionMatrix)), stateLabeling(std::move(stateLabeling)), rewardModels(std::move(rewardModels)), rateTransitions(rateTransitions), markovianStates(std::move(markovianStates)), player1Matrix(std::move(player1Matrix)) {
                     // Intentionally left empty
                 }
 
 
-
-
                 // General components (applicable for all model types):
 
                 // The transition matrix.
@@ -68,7 +65,6 @@ namespace storm {
                 // POMDP specific components
                 // The POMDP observations
                 boost::optional<std::vector<uint32_t>> observabilityClasses;
-
                 boost::optional<storm::storage::sparse::StateValuations> observationValuations;
 
                 // Continuous time specific components (CTMCs, Markov Automata):
@@ -84,8 +80,10 @@ namespace storm {
                 boost::optional<storm::storage::SparseMatrix<storm::storage::sparse::state_type>> player1Matrix;
 
                 // Stochastic multiplayer game specific components:
-                // The vector mapping state choices to players
-                boost::optional<std::vector<uint_fast32_t>> playerActionIndices;
+                // The vector mapping states to player indices.
+                boost::optional<std::vector<storm::storage::PlayerIndex>> statePlayerIndications;
+                // A mapping of player names to player indices.
+                boost::optional<std::map<std::string, storm::storage::PlayerIndex>> playerNameToIndexMap;
             };
         }
     }