annotate enigma/machine.cpp @ 16:280facb82b80

Add the ability to change ring settings at the machine level.
author Brian Neal <bgneal@gmail.com>
date Sat, 07 Jul 2012 11:42:31 -0500
parents 919b7a0d1802
children
rev   line source
bgneal@4 1 // Copyright (C) 2012 by Brian Neal.
bgneal@4 2 // This file is part of Cpp-Enigma, the Enigma Machine simulation.
bgneal@4 3 // Cpp-Enigma is released under the MIT License (see License.txt).
bgneal@4 4 //
bgneal@4 5 // machine.cpp - The implementation file for the main Enigma machine class.
bgneal@4 6
bgneal@4 7 #include <cstddef>
bgneal@8 8 #include <sstream>
bgneal@4 9 #include "machine.h"
bgneal@4 10 #include "rotor.h"
bgneal@4 11 #include "rotor_factory.h"
bgneal@4 12
bgneal@4 13 using namespace enigma;
bgneal@4 14
bgneal@4 15 ////////////////////////////////////////////////////////////////////////////////
bgneal@4 16
bgneal@4 17 enigma_machine::enigma_machine(
bgneal@11 18 const rotor_vector& rv,
bgneal@14 19 const rotor& reflector,
bgneal@4 20 const plugboard& pb)
bgneal@13 21 : rotors(),
bgneal@11 22 pb(pb)
bgneal@4 23 {
bgneal@14 24 rotors.push_back(reflector);
bgneal@13 25 for (const auto& r : rv)
bgneal@13 26 {
bgneal@13 27 rotors.push_back(*r);
bgneal@13 28 }
bgneal@4 29 rotor_count_check();
bgneal@4 30 }
bgneal@4 31
bgneal@4 32 ////////////////////////////////////////////////////////////////////////////////
bgneal@4 33
bgneal@4 34 enigma_machine::enigma_machine(
bgneal@11 35 const rotor_vector& rv,
bgneal@14 36 const rotor& reflector)
bgneal@13 37 : rotors(),
bgneal@11 38 pb()
bgneal@4 39 {
bgneal@14 40 rotors.push_back(reflector);
bgneal@13 41 for (const auto& r : rv)
bgneal@13 42 {
bgneal@13 43 rotors.push_back(*r);
bgneal@13 44 }
bgneal@4 45 rotor_count_check();
bgneal@4 46 }
bgneal@4 47
bgneal@4 48 ////////////////////////////////////////////////////////////////////////////////
bgneal@4 49
bgneal@4 50 enigma_machine::enigma_machine(
bgneal@4 51 const std::vector<std::string>& rotor_types,
bgneal@4 52 const std::vector<int>& ring_settings,
bgneal@4 53 const std::string& reflector_name,
bgneal@4 54 const std::string& plugboard_settings)
bgneal@4 55 : rotors(),
bgneal@11 56 pb(plugboard_settings)
bgneal@4 57 {
bgneal@13 58 const auto ukw(create_reflector(reflector_name.c_str()));
bgneal@13 59 rotors.push_back(*ukw);
bgneal@4 60 for (const auto& name : rotor_types)
bgneal@4 61 {
bgneal@13 62 const auto r(create_rotor(name.c_str()));
bgneal@13 63 rotors.push_back(*r);
bgneal@4 64 }
bgneal@4 65 rotor_count_check();
bgneal@4 66
bgneal@4 67 // if ring settings are supplied, there has to be one for each rotor
bgneal@4 68 if (!ring_settings.empty())
bgneal@4 69 {
bgneal@13 70 if (rotors.size() - 1 != ring_settings.size())
bgneal@4 71 {
bgneal@4 72 throw enigma_machine_error("rotor/ring setting count mismatch");
bgneal@4 73 }
bgneal@4 74
bgneal@13 75 for (std::size_t i = 1; i < rotors.size(); ++i)
bgneal@4 76 {
bgneal@13 77 rotors[i].set_ring_setting(ring_settings[i - 1]);
bgneal@4 78 }
bgneal@4 79 }
bgneal@4 80 }
bgneal@4 81
bgneal@4 82 ////////////////////////////////////////////////////////////////////////////////
bgneal@4 83
bgneal@4 84 void enigma_machine::rotor_count_check()
bgneal@4 85 {
bgneal@13 86 // the first rotor is actually the reflector; so we should have a total
bgneal@13 87 // of 4 or 5 rotors
bgneal@13 88 if (rotors.size() != 4 && rotors.size() != 5)
bgneal@4 89 {
bgneal@4 90 throw enigma_machine_error("rotor count");
bgneal@4 91 }
bgneal@4 92
bgneal@13 93 if (rotors.size() == 4)
bgneal@4 94 {
bgneal@13 95 r_rotor = &rotors[3];
bgneal@13 96 m_rotor = &rotors[2];
bgneal@13 97 l_rotor = &rotors[1];
bgneal@4 98 }
bgneal@4 99 else
bgneal@4 100 {
bgneal@13 101 r_rotor = &rotors[4];
bgneal@13 102 m_rotor = &rotors[3];
bgneal@13 103 l_rotor = &rotors[2];
bgneal@4 104 }
bgneal@4 105 }
bgneal@8 106
bgneal@8 107 ////////////////////////////////////////////////////////////////////////////////
bgneal@8 108
bgneal@8 109 std::string enigma_machine::str(bool army) const
bgneal@8 110 {
bgneal@8 111 std::ostringstream os;
bgneal@8 112
bgneal@13 113 os << rotors[0].name() << ' ';
bgneal@8 114
bgneal@13 115 for (std::size_t i = 1; i < rotors.size(); ++i)
bgneal@8 116 {
bgneal@13 117 os << rotors[i].name() << '/' << rotors[i].get_ring_setting() << ' ';
bgneal@8 118 }
bgneal@8 119
bgneal@8 120 os << get_display() << ' ' << (army ? pb.army_str() : pb.navy_str());
bgneal@8 121
bgneal@8 122 return os.str();
bgneal@8 123 }
bgneal@8 124