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@11
|
19 std::shared_ptr<rotor> reflector,
|
bgneal@4
|
20 const plugboard& pb)
|
bgneal@13
|
21 : rotors(),
|
bgneal@11
|
22 pb(pb)
|
bgneal@4
|
23 {
|
bgneal@13
|
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@11
|
36 std::shared_ptr<rotor> reflector)
|
bgneal@13
|
37 : rotors(),
|
bgneal@11
|
38 pb()
|
bgneal@4
|
39 {
|
bgneal@13
|
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
|