annotate enigma/rotor.h @ 0:74ebb2150658

Initial commit. Working on the rotor class.
author Brian Neal <bgneal@gmail.com>
date Thu, 21 Jun 2012 21:05:26 -0500
parents
children 1459e74fda3f
rev   line source
bgneal@0 1 #ifndef CPP_ENIGMA_ROTOR_H
bgneal@0 2 #define CPP_ENIGMA_ROTOR_H
bgneal@0 3 // Copyright (C) 2012 by Brian Neal.
bgneal@0 4 // This file is part of Cpp-Enigma, the Enigma Machine simulation.
bgneal@0 5 // Cpp-Enigma is released under the MIT License (see License.txt).
bgneal@0 6 //
bgneal@0 7 // rotor.h - This file contains the rotor class.
bgneal@0 8
bgneal@0 9 #include <string>
bgneal@0 10 #include "enigma_types.h"
bgneal@0 11
bgneal@0 12
bgneal@0 13 namespace enigma
bgneal@0 14 {
bgneal@0 15 class rotor_error : public enigma_error
bgneal@0 16 {
bgneal@0 17 public:
bgneal@0 18 explicit rotor_error(const std::string& what_arg)
bgneal@0 19 : enigma_error(what_arg)
bgneal@0 20 {}
bgneal@0 21 };
bgneal@0 22
bgneal@0 23 // The rotor class represents the Enigma Machine rotors (Walzen).
bgneal@0 24 //
bgneal@0 25 // A rotor has 26 circularly arranged pins on the right (entry) side and 26
bgneal@0 26 // contacts on the left side. Each pin is connected to a single contact by
bgneal@0 27 // internal wiring, thus establishing a substitution cipher. We represent this
bgneal@0 28 // wiring by establishing a mapping from a pin to a contact (and vice versa for
bgneal@0 29 // the return path). Internally we number the pins and contacts from 0-25 in a
bgneal@0 30 // clockwise manner with 0 being the "top".
bgneal@0 31 //
bgneal@0 32 // An alphabetic or numeric ring is fastened to the rotor by the operator. The
bgneal@0 33 // labels of this ring are displayed to the operator through a small window on
bgneal@0 34 // the top panel. The ring can be fixed to the rotor in one of 26 different
bgneal@0 35 // positions; this is called the ring setting (Ringstellung). We will number
bgneal@0 36 // the ring settings from 0-25 where 0 means no offset (e.g. the letter "A" is
bgneal@0 37 // mapped to pin 0 on an alphabetic ring). A ring setting of 1 means the letter
bgneal@0 38 // "B" is mapped to pin 0.
bgneal@0 39 //
bgneal@0 40 // Each rotor can be in one of 26 positions on the spindle, with position 0
bgneal@0 41 // where pin/contact 0 is being indicated in the operator window. The rotor
bgneal@0 42 // rotates towards the operator by mechanical means during normal operation as
bgneal@0 43 // keys are being pressed during data entry. Position 1 is thus defined to be
bgneal@0 44 // one step from position 0. Likewise, position 25 is the last position before
bgneal@0 45 // another step returns it to position 0, completing 1 trip around the spindle.
bgneal@0 46 //
bgneal@0 47 // Finally, a rotor has a "stepping" or "turnover" parameter. Physically this
bgneal@0 48 // is implemented by putting a notch on the alphabet ring and it controls when
bgneal@0 49 // the rotor will "kick" the rotor to its left, causing the neighbor rotor to
bgneal@0 50 // rotate. Most rotors had one notch, but some Kriegsmarine rotors had 2
bgneal@0 51 // notches and thus rotated twice as fast.
bgneal@0 52 //
bgneal@0 53 // Note that due to the system of ratchets and pawls, the middle rotor (in a 3
bgneal@0 54 // rotor Enigma) can "double-step". The middle rotor will advance on the next
bgneal@0 55 // step of the first rotor a second time in a row, if the middle rotor is in
bgneal@0 56 // its own turnover position.
bgneal@0 57 //
bgneal@0 58 // Note that we allow the stepping parameter to be None. This indicates the
bgneal@0 59 // rotor does not rotate. This allows us to model the entry wheel and
bgneal@0 60 // reflectors as stationary rotors.
bgneal@0 61
bgneal@0 62 class rotor
bgneal@0 63 {
bgneal@0 64 public:
bgneal@0 65 // rotor constructor:
bgneal@0 66 //
bgneal@0 67 // model_name - e.g. "I", "II", "III", "Beta", "Gamma"
bgneal@0 68 //
bgneal@0 69 // wiring - this should be a string of 26 alphabetic characters that
bgneal@0 70 // represents the internal wiring transformation of the signal as it enters
bgneal@0 71 // from the right side. This is the format used in various online
bgneal@0 72 // resources. For example, for the Wehrmacht Enigma type I rotor the
bgneal@0 73 // mapping is "EKMFLGDQVZNTOWYHXUSPAIBRCJ".
bgneal@0 74 //
bgneal@0 75 // ring_setting - this should be an integer from 0-25, inclusive, which
bgneal@0 76 // indicates the Ringstellung. A value of 0 means there is no offset; e.g.
bgneal@0 77 // the letter "A" is fixed to pin 0. A value of 1 means "B" is mapped to
bgneal@0 78 // pin 0.
bgneal@0 79 //
bgneal@0 80 // stepping - this is the stepping or turnover parameter. It should be
bgneal@0 81 // a string such as "Q". This will indicate that when the rotor transitions
bgneal@0 82 // from "Q" to "R" (by observing the operator window), the rotor will "kick"
bgneal@0 83 // the rotor to its left, causing it to rotate. If the rotor has more than one
bgneal@0 84 // notch, a string of length 2 could be used, e.g. "ZM". Another way to think
bgneal@0 85 // of this parameter is that when a character in the stepping string is visible
bgneal@0 86 // in the operator window, a notch is lined up with the pawl on the left side
bgneal@0 87 // of the rotor. This will allow the pawl to push up on the rotor *and* the
bgneal@0 88 // rotor to the left when the next key is depressed.
bgneal@0 89 //
bgneal@0 90 // Note that for purposes of simulation, our rotors will always use
bgneal@0 91 // alphabetic labels A-Z. In reality, the Heer & Luftwaffe devices used
bgneal@0 92 // numbers 01-26, and Kriegsmarine devices used A-Z. Our usage of A-Z is
bgneal@0 93 // simply for simulation convenience.
bgneal@0 94 // display.
bgneal@0 95
bgneal@0 96 rotor(const char* name, const char* wiring, int ring_setting = 0, const char* stepping = 0);
bgneal@0 97
bgneal@0 98 // Returns the rotor name:
bgneal@0 99 const std::string& name() const { return rotor_name; }
bgneal@0 100
bgneal@0 101 // Spin the rotor such that the string val appears in the operator window:
bgneal@0 102 void set_display(const char* val);
bgneal@0 103
bgneal@0 104 // Returns what is currently being displayed in the operator window:
bgneal@0 105 std::string get_display() const;
bgneal@0 106
bgneal@0 107 // Simulate a signal entering the rotor from the right at a given pin:
bgneal@0 108 // n must be an integer between 0 and 25.
bgneal@0 109 // Returns the contact number of the output signal (0-25).
bgneal@0 110 int signal_in(int n) const;
bgneal@0 111
bgneal@0 112 // Simulate a signal entering the rotor from the left at a given contact position n.
bgneal@0 113 // n must be an integer between 0 and 25.
bgneal@0 114 // Returns the pin number of the output signal (0-25).
bgneal@0 115 int signal_out(int n) const;
bgneal@0 116
bgneal@0 117 // Return true if this rotor has a notch in the stepping position and false otherwise:
bgneal@0 118 bool notch_over_pawl() const;
bgneal@0 119
bgneal@0 120 // Rotate the rotor forward one step:
bgneal@0 121 void rotate();
bgneal@0 122
bgneal@0 123 private:
bgneal@0 124 std::string rotor_name;
bgneal@0 125 std::string wiring_str;
bgneal@0 126 int ring_setting;
bgneal@0 127 int pos;
bgneal@0 128 int rotations;
bgneal@0 129 };
bgneal@0 130 }
bgneal@0 131
bgneal@0 132 #endif