
program r (infile, outfile, input, output);

{******************************************************************************}
	{Program for encryption and decryption using the rotation method and 
	the Fibionaci sequence.
	-Chris Boshuizen

	This simple variation of my rotation program shifts letters by the 
	values of the Fibionaci sequence f(n) = f(n-1) + f(n-2)
	ie: 1,1,2,3,5,8,13,21..  

	These Fibionaci numbers also can be multiplied by some constant,r.
	To decrypt use -r. 

	Thanks to Stuart Prescott for the procedures isletter.i and lowercase.i,
	and for the help including them. }

{******************************************************************************}


const 
     	cap= 26; 		{this is the length of the cypher-text (ct) 
				alphabet.  Can be 1<=cap<=26, but a 
				reasonable lower limit is 10<=cap<=26}

var	 
	counter,		{position of each character being read}
 	counter1, 		{f(n-1)}
	counter2,		{f(n-2)}
	n,			{the n th Character being shifted}
	cti,			{ascii value of ct}
	r			{the rotation number}
		: integer;  	
	
	pt, 			{plaintext}
	ct			{cyphertext}
		: char;  
	 
    	infile,			{input file}
	outfile 		{output file}
		:text;
  
{******************************************************************************}

{*** requires    isletter.i
     and         lowercase.i}
 
#include "isletter.i"  		{restricts read to lowercase 'a' to 'z'}
#include "lowercase.i" 		{changes uppercase to lowercase}

{******************************************************************************}

begin  {main}
    writeln ('Enter rotation number');
    read (r);
    reset (infile);   
    rewrite (outfile);
    counter:=1; {start at the beginning of the input file}
    counter1:=0;	
    counter2:=0;
	while not eof(infile) do begin
	    if eoln(infile) then begin
	        readln(infile);
		writeln(outfile);
	    end
	    else begin
		read(infile, pt); 
		if isletter(pt) then begin
		    n := ((counter mod cap) + cap) mod cap ; 
	      	    pt:= lowercase(pt);
		    cti:= (((ord(pt) - ord('a')+1) + (((n*r)))) mod 26 +26)mod 26 + ord('a')-1;
		    if cti > (ord('z')) then cti:= cti - 26;	{for r>0, if shifted past z,
								 puts ct back to a}
		    if cti < (ord ('a')) then cti:= cti+ 26;	{for r<0, if shifted below a,
								 puts ct back to z} 
	            counter2:= counter1;
		    counter1:=counter;
		    counter:=counter1+counter2;		
		end
		else begin
		    cti:=ord(pt); 	{don't change the pt if not lowercase a - z}
		end;
	    ct:=chr(cti);		{changes the value of cti into a char ct   }
	    write(outfile, ct);		{and writes ct to the out file		   }
	end;{if eoln}
    end; {while not eof(infile)}
end.  {main}

