# ===================================================================
# Enigma Machine Simulation - rotor
# ===================================================================
from EnigmaConfig import EnigmaConfig
import EnigmaUtils as util
import copy
class EnigmaRotor():
# ---------------------------------------------------------------
# ---- initialize rotor object
# ---------------------------------------------------------------
# ---- abc alphabet list
# ---- abclen alphabet list length
# ---- abcunk unknown character substitute
# ---- rotors configuration file dictionary of
# ---- rotor lists (I,II,...,VIII)
# ---- rotor_name rotor name (from rotors)
# ---- rotor_start rotor start position (idx=0)
# ---- rotor_count rotation/advancement count
# ---- lst randomized list of indexes from
# ---- configuration file
# ---- (associated with the alphabet)
# ---- lstlen length, lst
# ---- ltor left-to-right substitution list
# ---- rtol right-to-left substitution list
#----------------------------------------------------------------
def __init__(self,config,rotor_name,rotor_start):
self.abc = config.abc
self.abcidx = config.abcidx
self.abclen = config.abclen
self.abcunk = config.abcunk
self.rotors = config.rotors
self.rotor_name = rotor_name
self.rotor_start = rotor_start
self.rotor_count = 0
self.lst = []
self.lstlen = []
self.rtol = []
self.ltor = []
self.reset(rotor_name,rotor_start)
# ---------------------------------------------------------------
# ---- character substitution right-to-left
# ---------------------------------------------------------------
def rtol_substitution(self,idx):
return self.rtol[idx]
# ---------------------------------------------------------------
# ---- character substitution left-to-right
# ---------------------------------------------------------------
def ltor_substitution(self,idx):
return self.ltor[idx]
# ---------------------------------------------------------------
# ---- reset rotor starting position
# ---------------------------------------------------------------
def reset(self,rotor_name,rotor_start):
self.rotor_name = rotor_name
self.rotor_start = rotor_start
self.rotor_count = 0
# ---- fill rotor randomized substitution list
self.lst = self.rotors[rotor_name] # indexes list
self.lstlen = len(self.lst) # indexes list length
# ---- fill in the rtol randomized substitution list
self.rtol = [None] * self.lstlen
for i in range(self.lstlen):
self.rtol[i] = self.lst[i]
# --- shift rtol list so rotor_start is index 0
if rotor_start >= 0:
self.rtol = self._shift_rotor(rotor_start,self.rtol)
# ---- sync rotor's ltor list with it's rotl list
self.ltor = [None] * self.lstlen
for i in range(self.abclen):
self.ltor[self.rtol[i]] = i
# ---------------------------------------------------------------
# ---- helper function: set rotor configuration
# ---------------------------------------------------------------
def _shift_rotor(self,idx,lst):
# ---- create new list
new_lst = [-1] * self.lstlen # set everything to -1
# --- copy lower half of original list to new list
i = 0 # new list index
for j in range(idx,self.lstlen):
new_lst[i] = lst[j] # copy original list to new list
i += 1 # increment new list index
# ---- copy upper part of original list to new list
for j in range(0,idx):
new_lst[i] = lst[j] # copy original list to new list
i += 1 # increment new list index
##print(f'new lst: {self.rotor_name} {self.rotor_start}')
##print(f'old={lst} new={new_lst}')
return new_lst
# ---------------------------------------------------------------
# ---- display rotor internals
# ----------------------------------------------------------------
def display(self,title=None,all=True):
print()
for k in self.rotors.keys():
print(f'{k:>4} {self.rotors[k]}')
print()
if title:
print(title)
if all:
print('-lst- l-to-r r-to-l')
for i in range(self.lstlen):
print(f'{i:2} {self.lst[i]:<2} ' +
f'{i:>2} -> {self.ltor[i]:<2} ' +
f'{self.rtol[i]:>2} <- {i:<2}')
print(f'rotor_name = {self.rotor_name}')
print(f'rotor_start = {self.rotor_start}')
print(f'rotor_count = {self.rotor_count}')