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@4
|
18 rotor_vector rv,
|
bgneal@4
|
19 std::unique_ptr<rotor> reflector,
|
bgneal@4
|
20 const plugboard& pb)
|
bgneal@4
|
21 : rotors(std::move(rv)),
|
bgneal@4
|
22 reflector(std::move(reflector)),
|
bgneal@4
|
23 pb(pb),
|
bgneal@4
|
24 r_rotor(0),
|
bgneal@4
|
25 m_rotor(0),
|
bgneal@4
|
26 l_rotor(0)
|
bgneal@4
|
27 {
|
bgneal@4
|
28 rotor_count_check();
|
bgneal@4
|
29 }
|
bgneal@4
|
30
|
bgneal@4
|
31 ////////////////////////////////////////////////////////////////////////////////
|
bgneal@4
|
32
|
bgneal@4
|
33 enigma_machine::enigma_machine(
|
bgneal@4
|
34 rotor_vector rv,
|
bgneal@4
|
35 std::unique_ptr<rotor> reflector)
|
bgneal@4
|
36 : rotors(std::move(rv)),
|
bgneal@4
|
37 reflector(std::move(reflector)),
|
bgneal@4
|
38 pb(),
|
bgneal@4
|
39 r_rotor(0),
|
bgneal@4
|
40 m_rotor(0),
|
bgneal@4
|
41 l_rotor(0)
|
bgneal@4
|
42 {
|
bgneal@4
|
43 rotor_count_check();
|
bgneal@4
|
44 }
|
bgneal@4
|
45
|
bgneal@4
|
46 ////////////////////////////////////////////////////////////////////////////////
|
bgneal@4
|
47
|
bgneal@4
|
48 enigma_machine::enigma_machine(
|
bgneal@4
|
49 const std::vector<std::string>& rotor_types,
|
bgneal@4
|
50 const std::vector<int>& ring_settings,
|
bgneal@4
|
51 const std::string& reflector_name,
|
bgneal@4
|
52 const std::string& plugboard_settings)
|
bgneal@4
|
53 : rotors(),
|
bgneal@4
|
54 reflector(create_reflector(reflector_name.c_str())),
|
bgneal@4
|
55 pb(plugboard_settings),
|
bgneal@4
|
56 r_rotor(0),
|
bgneal@4
|
57 m_rotor(0),
|
bgneal@4
|
58 l_rotor(0)
|
bgneal@4
|
59 {
|
bgneal@4
|
60 for (const auto& name : rotor_types)
|
bgneal@4
|
61 {
|
bgneal@4
|
62 rotors.push_back(create_rotor(name.c_str()));
|
bgneal@4
|
63 }
|
bgneal@4
|
64 rotor_count_check();
|
bgneal@4
|
65
|
bgneal@4
|
66 // if ring settings are supplied, there has to be one for each rotor
|
bgneal@4
|
67 if (!ring_settings.empty())
|
bgneal@4
|
68 {
|
bgneal@4
|
69 if (rotors.size() != ring_settings.size())
|
bgneal@4
|
70 {
|
bgneal@4
|
71 throw enigma_machine_error("rotor/ring setting count mismatch");
|
bgneal@4
|
72 }
|
bgneal@4
|
73
|
bgneal@4
|
74 for (std::size_t i = 0; i < rotors.size(); ++i)
|
bgneal@4
|
75 {
|
bgneal@4
|
76 rotors[i]->set_ring_setting(ring_settings[i]);
|
bgneal@4
|
77 }
|
bgneal@4
|
78 }
|
bgneal@4
|
79 }
|
bgneal@4
|
80
|
bgneal@4
|
81 ////////////////////////////////////////////////////////////////////////////////
|
bgneal@4
|
82
|
bgneal@4
|
83 void enigma_machine::rotor_count_check()
|
bgneal@4
|
84 {
|
bgneal@4
|
85 if (rotors.size() != 3 && rotors.size() != 4)
|
bgneal@4
|
86 {
|
bgneal@4
|
87 throw enigma_machine_error("rotor count");
|
bgneal@4
|
88 }
|
bgneal@4
|
89
|
bgneal@4
|
90 if (rotors.size() == 3)
|
bgneal@4
|
91 {
|
bgneal@4
|
92 r_rotor = rotors[2].get();
|
bgneal@4
|
93 m_rotor = rotors[1].get();
|
bgneal@4
|
94 l_rotor = rotors[0].get();
|
bgneal@4
|
95 }
|
bgneal@4
|
96 else
|
bgneal@4
|
97 {
|
bgneal@4
|
98 r_rotor = rotors[3].get();
|
bgneal@4
|
99 m_rotor = rotors[2].get();
|
bgneal@4
|
100 l_rotor = rotors[1].get();
|
bgneal@4
|
101 }
|
bgneal@4
|
102 }
|
bgneal@8
|
103
|
bgneal@8
|
104 ////////////////////////////////////////////////////////////////////////////////
|
bgneal@8
|
105
|
bgneal@8
|
106 std::string enigma_machine::str(bool army) const
|
bgneal@8
|
107 {
|
bgneal@8
|
108 std::ostringstream os;
|
bgneal@8
|
109
|
bgneal@8
|
110 os << reflector->name() << ' ';
|
bgneal@8
|
111
|
bgneal@8
|
112 for (const auto& r : rotors)
|
bgneal@8
|
113 {
|
bgneal@8
|
114 os << r->name() << '/' << r->get_ring_setting() << ' ';
|
bgneal@8
|
115 }
|
bgneal@8
|
116
|
bgneal@8
|
117 os << get_display() << ' ' << (army ? pb.army_str() : pb.navy_str());
|
bgneal@8
|
118
|
bgneal@8
|
119 return os.str();
|
bgneal@8
|
120 }
|
bgneal@8
|
121
|