Mercurial > public > cpp-enigma
comparison enigma/plugboard.h @ 3:f4e25e6b76c3
Created plugboard class and tests.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 23 Jun 2012 23:28:17 -0500 |
parents | |
children | 232dbe7a3fe0 |
comparison
equal
deleted
inserted
replaced
2:713fa2a9ea9a | 3:f4e25e6b76c3 |
---|---|
1 #ifndef CPP_ENIGMA_PLUGBOARD_H | |
2 #define CPP_ENIGMA_PLUGBOARD_H | |
3 // Copyright (C) 2012 by Brian Neal. | |
4 // This file is part of Cpp-Enigma, the Enigma Machine simulation. | |
5 // Cpp-Enigma is released under the MIT License (see License.txt). | |
6 // | |
7 // plugboard.h - This file contains the plugboard class. | |
8 | |
9 #include <vector> | |
10 #include <utility> | |
11 #include <string> | |
12 #include <cstddef> | |
13 #include "enigma_types.h" | |
14 | |
15 namespace enigma | |
16 { | |
17 class plugboard_error : public enigma_error | |
18 { | |
19 public: | |
20 explicit plugboard_error(const std::string& what_arg) | |
21 : enigma_error(what_arg) | |
22 {} | |
23 }; | |
24 | |
25 // The plugboard allows the operator to swap letters before and after the | |
26 // entry wheel. This is accomplished by connecting cables between pairs of | |
27 // plugs that are marked with letters (Heer & Luftwaffe models) or numbers | |
28 // (Kriegsmarine). Ten cables were issued with each machine; thus up to 10 of | |
29 // these swappings could be used as part of a machine setup. | |
30 | |
31 // Each cable swaps both the input and output signals. Thus if A is connected | |
32 // to B, A crosses to B in the keyboard to entry wheel direction and also in | |
33 // the reverse entry wheel to lamp direction. | |
34 | |
35 class plugboard | |
36 { | |
37 public: | |
38 const static std::size_t max_pairs = 10; | |
39 | |
40 typedef std::vector<std::pair<int, int>> pair_vector; | |
41 | |
42 // Construct a plugboard with no connections: | |
43 plugboard(); | |
44 | |
45 // Construct from a vector of integer pairs that describe the | |
46 // connections. Each integer must be between [0-25], and the | |
47 // vector can have no more than max_pairs pairs. Each plug should | |
48 // be present at most once. A plugboard_error will be thrown if | |
49 // the pair_vector is invalid. | |
50 | |
51 explicit plugboard(const pair_vector& pairs); | |
52 | |
53 // Configure the plugboard according to a settings string as you may | |
54 // find on a key sheet. | |
55 // | |
56 // Two syntaxes are supported, the Heer/Luftwaffe and Kriegsmarine styles: | |
57 // | |
58 // In the Heer syntax, the settings are given as a string of | |
59 // alphabetic pairs. For example: 'PO ML IU KJ NH YT GB VF RE DC' | |
60 // | |
61 // In the Kriegsmarine syntax, the settings are given as a string of number | |
62 // pairs, separated by a '/'. Note that the numbering uses 1-26, inclusive. | |
63 // For example: '18/26 17/4 21/6 3/16 19/14 22/7 8/1 12/25 5/9 10/15' | |
64 // | |
65 // To specify no plugboard connections, settings can be an empty string. | |
66 // | |
67 // A PlugboardError will be raised if the settings string is invalid, or if | |
68 // it contains more than max_pairs pairs. Each plug should be present at | |
69 // most once in the settings string. | |
70 | |
71 explicit plugboard(const std::string& settings); | |
72 | |
73 // Return the current settings as a vector of pairs: | |
74 pair_vector get_pairs() const; | |
75 | |
76 // Return the current settings as a string in Heer (army) format: | |
77 std::string army_str() const; | |
78 | |
79 // Return the current settings as a string in Kriegsmarine (navy) format: | |
80 std::string navy_str() const; | |
81 | |
82 // Simulate a signal entering the plugboard on wire n, where n must be | |
83 // an integer between 0 and 25. | |
84 // | |
85 // Returns the wire number of the output signal (0-25). | |
86 // | |
87 // Note that since the plugboard always crosses pairs of wires, it doesn't | |
88 // matter what direction (keyboard -> entry wheel or vice versa) the signal | |
89 // is coming from. | |
90 | |
91 int signal(int n) const | |
92 { | |
93 return wiring_map[n]; | |
94 } | |
95 | |
96 // | |
97 // Functions to support hill-climbing: | |
98 // | |
99 | |
100 // Return the internal state of the wiring: | |
101 alpha_int_array get_wiring() const | |
102 { | |
103 return wiring_map; | |
104 } | |
105 | |
106 // Sets the internal state of the wiring: | |
107 void set_wiring(const alpha_int_array& wiring) | |
108 { | |
109 wiring_map = wiring; | |
110 } | |
111 | |
112 // Returns true if connection n has a cable attached to it. | |
113 // 0 <= n < 26 | |
114 bool is_wired(int n) const | |
115 { | |
116 return wiring_map[n] != n; | |
117 } | |
118 | |
119 // Returns true if connection n has no cable attached to it. | |
120 // 0 <= n < 26 | |
121 bool is_free(int n) const | |
122 { | |
123 return wiring_map[n] == n; | |
124 } | |
125 | |
126 // Removes cable from plug number n [0-25]. | |
127 void disconnect(int n) | |
128 { | |
129 const int x = wiring_map[n]; | |
130 wiring_map[x] = x; | |
131 wiring_map[n] = n; | |
132 } | |
133 | |
134 // Connects plug x to plug y, removing any existing connection first. | |
135 // x & y must be in [0-25]. | |
136 void connect(int x, int y) | |
137 { | |
138 // disconnect any existing connections | |
139 const int m = wiring_map[x]; | |
140 const int n = wiring_map[y]; | |
141 wiring_map[m] = m; | |
142 wiring_map[n] = n; | |
143 | |
144 wiring_map[x] = y; | |
145 wiring_map[y] = x; | |
146 } | |
147 | |
148 // Returns true if plug x is connected to plug y. | |
149 // x & y must be in [0-25]. | |
150 bool is_connected(int x, int y) | |
151 { | |
152 return wiring_map[x] == y && wiring_map[y] == x; | |
153 } | |
154 | |
155 private: | |
156 alpha_int_array wiring_map; | |
157 | |
158 // common constructor code: | |
159 void construct_wiring(const pair_vector& pairs); | |
160 }; | |
161 | |
162 | |
163 // This class can be used to save & restore the state of a plugboard | |
164 // in RAII style: | |
165 | |
166 class plugboard_state_saver | |
167 { | |
168 public: | |
169 explicit plugboard_state_saver(plugboard& pb) | |
170 : pb(pb) | |
171 { | |
172 state = pb.get_wiring(); | |
173 } | |
174 | |
175 ~plugboard_state_saver() | |
176 { | |
177 pb.set_wiring(state); | |
178 } | |
179 | |
180 // disable copying & assignment | |
181 plugboard_state_saver(const plugboard_state_saver&) = delete; | |
182 plugboard_state_saver& operator=(const plugboard_state_saver&) = delete; | |
183 | |
184 private: | |
185 plugboard& pb; | |
186 alpha_int_array state; | |
187 }; | |
188 | |
189 } | |
190 | |
191 #endif |