bgneal@4: // Copyright (C) 2012 by Brian Neal. bgneal@4: // This file is part of Cpp-Enigma, the Enigma Machine simulation. bgneal@4: // Cpp-Enigma is released under the MIT License (see License.txt). bgneal@4: // bgneal@4: // machine.cpp - The implementation file for the main Enigma machine class. bgneal@4: bgneal@4: #include bgneal@8: #include bgneal@4: #include "machine.h" bgneal@4: #include "rotor.h" bgneal@4: #include "rotor_factory.h" bgneal@4: bgneal@4: using namespace enigma; bgneal@4: bgneal@4: //////////////////////////////////////////////////////////////////////////////// bgneal@4: bgneal@4: enigma_machine::enigma_machine( bgneal@11: const rotor_vector& rv, bgneal@14: const rotor& reflector, bgneal@4: const plugboard& pb) bgneal@13: : rotors(), bgneal@11: pb(pb) bgneal@4: { bgneal@14: rotors.push_back(reflector); bgneal@13: for (const auto& r : rv) bgneal@13: { bgneal@13: rotors.push_back(*r); bgneal@13: } bgneal@4: rotor_count_check(); bgneal@4: } bgneal@4: bgneal@4: //////////////////////////////////////////////////////////////////////////////// bgneal@4: bgneal@4: enigma_machine::enigma_machine( bgneal@11: const rotor_vector& rv, bgneal@14: const rotor& reflector) bgneal@13: : rotors(), bgneal@11: pb() bgneal@4: { bgneal@14: rotors.push_back(reflector); bgneal@13: for (const auto& r : rv) bgneal@13: { bgneal@13: rotors.push_back(*r); bgneal@13: } bgneal@4: rotor_count_check(); bgneal@4: } bgneal@4: bgneal@4: //////////////////////////////////////////////////////////////////////////////// bgneal@4: bgneal@4: enigma_machine::enigma_machine( bgneal@4: const std::vector& rotor_types, bgneal@4: const std::vector& ring_settings, bgneal@4: const std::string& reflector_name, bgneal@4: const std::string& plugboard_settings) bgneal@4: : rotors(), bgneal@11: pb(plugboard_settings) bgneal@4: { bgneal@13: const auto ukw(create_reflector(reflector_name.c_str())); bgneal@13: rotors.push_back(*ukw); bgneal@4: for (const auto& name : rotor_types) bgneal@4: { bgneal@13: const auto r(create_rotor(name.c_str())); bgneal@13: rotors.push_back(*r); bgneal@4: } bgneal@4: rotor_count_check(); bgneal@4: bgneal@4: // if ring settings are supplied, there has to be one for each rotor bgneal@4: if (!ring_settings.empty()) bgneal@4: { bgneal@13: if (rotors.size() - 1 != ring_settings.size()) bgneal@4: { bgneal@4: throw enigma_machine_error("rotor/ring setting count mismatch"); bgneal@4: } bgneal@4: bgneal@13: for (std::size_t i = 1; i < rotors.size(); ++i) bgneal@4: { bgneal@13: rotors[i].set_ring_setting(ring_settings[i - 1]); bgneal@4: } bgneal@4: } bgneal@4: } bgneal@4: bgneal@4: //////////////////////////////////////////////////////////////////////////////// bgneal@4: bgneal@4: void enigma_machine::rotor_count_check() bgneal@4: { bgneal@13: // the first rotor is actually the reflector; so we should have a total bgneal@13: // of 4 or 5 rotors bgneal@13: if (rotors.size() != 4 && rotors.size() != 5) bgneal@4: { bgneal@4: throw enigma_machine_error("rotor count"); bgneal@4: } bgneal@4: bgneal@13: if (rotors.size() == 4) bgneal@4: { bgneal@13: r_rotor = &rotors[3]; bgneal@13: m_rotor = &rotors[2]; bgneal@13: l_rotor = &rotors[1]; bgneal@4: } bgneal@4: else bgneal@4: { bgneal@13: r_rotor = &rotors[4]; bgneal@13: m_rotor = &rotors[3]; bgneal@13: l_rotor = &rotors[2]; bgneal@4: } bgneal@4: } bgneal@8: bgneal@8: //////////////////////////////////////////////////////////////////////////////// bgneal@8: bgneal@8: std::string enigma_machine::str(bool army) const bgneal@8: { bgneal@8: std::ostringstream os; bgneal@8: bgneal@13: os << rotors[0].name() << ' '; bgneal@8: bgneal@13: for (std::size_t i = 1; i < rotors.size(); ++i) bgneal@8: { bgneal@13: os << rotors[i].name() << '/' << rotors[i].get_ring_setting() << ' '; bgneal@8: } bgneal@8: bgneal@8: os << get_display() << ' ' << (army ? pb.army_str() : pb.navy_str()); bgneal@8: bgneal@8: return os.str(); bgneal@8: } bgneal@8: