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