Randomise rune selection with allrunes

Longer post: An initial version (an experiment with LuaTeX)

The allrunes package is a part of the TeX distributions, we are all set up and ready to go.

The medieval runes are listed on pages 18 and 19 in the manual. The only needed change was \.u which should be an input alternative in the main y rune only (neither as main v rune nor as an alternative among y variants).

To solve this task I used this idea which I had had in mind for some time. Each \prettyRunes command saves its content to an external TeX file (mal-temp.tex), it's a similar approach as with \index command (idx->ind file). The problem is that we need to load it back after some modification and we need only one entry at a time.

I've solved this particular problem by adding \ifnum\counter...\fi to the external file and loading the resulting file back at a TeX level. The file is loaded multiple times, once per \prettyRunes. It's worth mentioning that we need at least two runs of TeX: the first run generates a temporary TeX file, which is processed by a standalone Lua script (mal-runes.lua) and the output file (mal-result.tex) is loaded back during the second and next runs of TeX.

I should also write a comment that regular paragraph in TeX is converted to the \par command (it's working using this method), the problem would be if we use ^^J which is a TeX alternative to well known \n escape character in other languages. In such a case this method fails, Lua script would understand one such entry as several inputs.

Lua is taking one line as one entry. The disadvantage is that it isn't a general approach. Better approach would be to add a unique mark, e.g. +++mal+++, at the end of each entry at a TeX level, then we could have several paragraphs serving as one entry. At a TeX level we would use \long\def\somecommand... which allows us to process more paragraphs per one call.

This is the TeX file which is processed by xelatex or lualatex. We could even use pdflatex but I had some difficulties in the last block of z to \aa, meaning that we cannot use all the commands from the manual to display runes. I stayed with lualatex.

% run: xelatex or lualatex mal-runes.tex
\documentclass[a4paper]{article}
%\usepackage[utf8]{inputenc}
% addition for pdflatex, some letters, e.g. ä ö, are not working well, we must use input alternatives
\pagestyle{empty}
\parindent=0pt
\usepackage{xcolor}
\usepackage{allrunes}
\newwrite\malwrite
\openout\malwrite=mal-temp.tex
\newcount\malc \malc=0
\def\malfile{mal-result.tex}

\def\prettyRunes#1{%
  \advance\malc by 1%
  \write\malwrite{#1}%
  %#1% An original text.
  \IfFileExists{\malfile}{%
    {\armfamily\mdseries% bf, md, lf
\par % to be commented out
{\normalfont Before (input \the\malc): }{\color{blue}#1}\par% original entry; to be commented out
{\normalfont After (output \the\malc): }{\color{green}% to be commented out
%\makebox[0pt][l]{\color{red}\input{mal-result-1.tex}}% comparing random seed versions
\input{\malfile}}%
}\par\smallskip%  to be commented out
    }% End of \armfamily...
    {}%#1% Shall I display anything after the first run of TeX?
  }
\begin{document}
Text before. \prettyRunes{This is {a} slab of text} 
% first letter "a" is protected from modification, the second letter "a" is not...
Some text. \prettyRunes{Another test \tdot\.N\rdot {\tdot}{\.N}{\rdot}} 
% \tdot, \.N and \rdot are also modified, the last three runes are not as they are protected...
Text after. \par\bigskip
%\ifx % all runes to process, deeper testing
\prettyRunes{a\a\.a\adot\'aA bB c\c\.cC\^c d\.t\tbar\=t\tdot\'t\tflag\~t\tring\^tD\.T\D\"T}
\prettyRunes{e\.i\e\=iE\^i fF g\.kG\'k\g\=k h\h H i k l\l\.l\lbar\=l\ldot\'l\lflag\~l\lring\^l m\m}
\prettyRunes{n\n\.n\ndot\'nN\N\.N o p\"b\p\.b\P\Pdots\"\P P q\q\Q r\rdot\.r\r}
\prettyRunes{sS\S tT\T \th þ\TH Þ\thth \dh ð \.\th \DH Ð \.\TH}
\prettyRunes{u v V\.f\v\'f\V\~f w x\x X\X y\.uYv\y\"u\Y\=u}
\prettyRunes{z\z Z äæ\ae \o öø \O ÖØ \oo\oO \ey\arlaug\tvimadur\belgthor jå\aa}
%\fi
\closeout\malwrite
\end{document}

After running lualatex mal-runes.tex we are generating mal-temp.tex. The content of this file in this example looks like this:

This is {a} slab of text
Another test \tdot \.N\rdot {\tdot }{\.N}{\rdot }
a\a \.a\adot \'aA bB c\c \.cC\^c d\.t\tbar \=t\tdot \'t\tflag \~t\tring \^tD\.T\D \"T
e\.i\e \=iE\^i fF g\.kG\'k\g \=k h\h H i k l\l \.l\lbar \=l\ldot \'l\lflag \~l\lring \^l m\m 
n\n \.n\ndot \'nN\N \.N o p\"b\p \.b\P \Pdots \"\P P q\q \Q r\rdot \.r\r 
sS\S tT\T \th þ\TH Þ\thth \dh ð \.\th \DH Ð \.\TH 
u v V\.f\v \'f\V \~f w x\x X\X y\.uYv\y \"u\Y \=u
z\z Z äæ\ae \o öø \O ÖØ \oo \oO \ey \arlaug \tvimadur \belgthor jå\aa 

We've used \prettyRunes eight times and the file also has eight lines. Now it's time to process it by texlua mal-runes.lua. This is the code.

-- I am mal-runes.lua file...
-- I take characters and convert them to runes main+alternatives randomly...
-- Listed TeX commands are ignored (the second and next columns), 
--   { } is a form of a letter protection (the first column only; it can be used in other columns, but there is no need for that)...
math.randomseed(0) -- to be changed anytime, e.g. to 1

--[[ All runes; 
   the first column is input form and main runes, 
   the other columns are variant forms (allrunes.pdf from TeX Live distribution)... 
   those can serve as input as well...
   the only difference from allrunes.pdf, version 2.1, pp. 18 and 19, is "\.u", which is used only once next to the "y" letter...
   ]]
runes={
  { {"a"}, {"\\a ","\\.a"}, {"\\adot ","\\\'a"}, {"A"} },
  { {"b"}, {"B"} },
  { {"c"}, {"\\c ","\\.c"}, {"C","\\^c"} }, 
  { {"d","\\.t"}, {"\\tbar ","\\=t"}, {"\\tdot ","\\\'t"}, {"\\tflag ","\\~t"}, {"\\tring ","\\^t"}, {"D","\\.T"}, {"\\D ","\\\"T"} },
  { {"e","\\.i"}, {"\\e ","\\=i"}, {"E","\\^i"} },
  { {"f"}, {"F"} },
  { {"g","\\.k"}, {"G","\\\'k"}, {"\\g ","\\=k"} },
  { {"h"}, {"\\h "}, {"H"} },
  { {"i"} },
  { {"k"} },
  { {"l"}, {"\\l ","\\.l"}, {"\\lbar ","\\=l"}, {"\\ldot ","\\\'l"}, {"\\lflag ","\\~l"}, {"\\lring ","\\^l"} }, 
  { {"m"}, {"\\m "} }, 
  { {"n"}, {"\\n ","\\.n"}, {"\\ndot ","\\\'n"}, {"N"}, {"\\N ","\\.N"} },
  { {"o"} },
  { {"p","\\\"b"}, {"\\p ","\\.b"}, {"\\P "}, {"\\Pdots ","\\\"\\P"}, {"P"} },
  { {"q"}, {"\\q "}, {"\\Q "} },
  { {"r"}, {"\\rdot ","\\.r"}, {"\\r "} },
  { {"s"}, {"S"}, {"\\S "} },
  { {"t"}, {"T"}, {"\\T "} },
  { {"þ","\\th "}, {"Þ","\\TH "}, {"\\thth "} },
  { {"ð","\\dh ","\\.\\th"}, {"Ð","\\DH ","\\.\\TH"} },
  { {"u"} },
  { {"v"}, {"V","\\.f"}, {"\\v ","\\\'f"}, {"\\V ","\\~f"} },
  { {"w"} },
  { {"x"}, {"\\x "}, {"X"}, {"\\X "} }, 
  { {"y","\\.u"}, {"Y"}, {"v"}, {"\\y ","\\\"u"}, {"\\Y ","\\=u"} },
  { {"z"}, {"\\z "}, {"Z"} },
  { {"ä","æ","\\ae "} },
  { {"ö","ø","\\o "}, {"Ö","Ø","\\O "}, {"\\oo "}, {"\\oO "} },
  { {"\\ey "} },
  { {"\\arlaug "} },
  { {"\\tvimadur "} },
  { {"\\belgthor "} },
  { {"j"} },
  { {"å","\\aa "} },   
  } -- end of runes...


-- The core function...
function testme(mstring)

-- Some initial setup and clearing variables...
local s=""
local temp=mstring
local charnew=""

repeat -- Trimming the original string to get an empty string in the end...
-- Clearing some variables needed within one string...
local char="" 
local line=0
--local protected=0

-- The core cycles: search in whole runes data table (lines, then columns, then cells)...
for i,iline in pairs(runes) do -- each rune (lines)
  for j,jline in pairs(iline) do -- main+variant forms (columns)
    for k,kline in pairs(jline) do -- each form of TeX input and output (cells)
      --if j>1 then io.write("   ") end
      --print(kline)
      --s=s.."{\\normalfont\\url{"..kline.."}\\ }"..kline.."{\\normalfont,\\ }"
      --  s=s..kline.." "
      --if string==kline then print(kline.."shoda") end
--      if j==1 then -- Is it a protected form, e.g. {a}?

-- Should I save e.g. \a or \arlaug? Take the longest match!
-- Protected part...
lookfor="{"..kline.."}"
partfor=string.sub(temp,1,string.len(lookfor))
if partfor==lookfor then -- Found!
  --print(partfor.." match of protected string") 
  if string.len(partfor)>string.len(char) then char=partfor; line=i; protected=1; end
end
-- Common or unprotected part...
partfor=string.sub(temp,1,string.len(kline))
if partfor==kline then -- Found!
  --print(partfor.." simple match") 
  if string.len(partfor)>string.len(char) then char=partfor; line=i; protected=0; end
end
--print(kline,partfor)
--      end -- of j==1
    end -- of for kline
  end -- of for jline
  --print()
  --s=s.."\\par "    
end -- of for iline

-- Character has been found in runes data table...
if char~="" then 
  tempvalue=math.random(#runes[line]) -- random number in interval [1,n]
  --print(tempvalue) -- which column has been chosen?
  charnew=runes[line][tempvalue][1] -- I am selecting random column and its first option
  if protected==0 then
  s=s..charnew --.." " -- add a space by force to protect TeX commands
    else -- character hasn't been found, move by one character/byte by force...
  s=s..char --.." "
  end -- of if protected
  temp=string.sub(temp,string.len(char)+1) -- trim string from left 
  else 
  s=s..string.sub(temp,1,1) -- skip an unrecognized characted
  temp=string.sub(temp,1+1) -- trim string from left by one character
end -- of if char

-- If I am not skipping a character, e.g. a space, print me found information (for debugging purposes)...
--[[
if line~=0 then
print("s = "..s)
print("temp = "..temp)
print("line = "..line)
print("len of data in that line = "..#runes[line].."\n")
end -- of if line
]]

until temp==""
--print(s) -- a preview of result
-- global replacings for purpose of pdflatex (not working completely)
--[[
s=string.gsub(s,"þ","\\th ")
s=string.gsub(s,"Þ","\\TH ")
s=string.gsub(s,"ð","\\dh ")
s=string.gsub(s,"Ð","\\DH ")
s=string.gsub(s,"ä","\\ae ")
s=string.gsub(s,"æ","\\ae ")
s=string.gsub(s,"ö","\\o ")
s=string.gsub(s,"ø","\\o ")
s=string.gsub(s,"Ö","\\O ")
s=string.gsub(s,"Ø","\\O ")
s=string.gsub(s,"å","\\aa ")
]]

-- Protection is no longer needed... it could help with typesetting kernings.
s=string.gsub(s,"{","")
s=string.gsub(s,"}","")
whereto:write(s)
end -- of core function named testme


-- A single test with protected letter "b"...
-- testme([[a{b}\V c]])

-- A real test which is processing a TeX file...
-- One line is one entry (for multiline input we would need a mark at the end of each entry, generally speaking, it is not implemented here).
local counter=0
whereto=io.open("mal-result.tex","w")
io.write("Processing entry/line ")
for line in io.lines("mal-temp.tex") do
counter=counter+1
io.write(counter.." ")
whereto:write("\\ifnum\\malc="..counter.." ")
--whereto:write(line)
-- global replacements for pdflatex (not working completely)
--[[
line=string.gsub(line,"\\IeC {\\th }","þ")
line=string.gsub(line,"\\IeC {\\TH }","Þ")
line=string.gsub(line,"\\IeC {\\dh }","ð")
line=string.gsub(line,"\\IeC {\\DH }","Ð")
line=string.gsub(line,"\\IeC {\\\"a}","ä")
line=string.gsub(line,"\\IeC {\\ae }","æ")
line=string.gsub(line,"\\IeC {\\\"o}","ö")
line=string.gsub(line,"\\IeC {\\o }","ø")
line=string.gsub(line,"\\IeC {\\\"O}","Ö")
line=string.gsub(line,"\\IeC {\\O }","Ø")
line=string.gsub(line,"\\IeC {\\r a}","å")
]]
testme(line)
--if counter==1 then
--  whereto:write(s)
--end -- of if counter
whereto:write("\\fi\n")
end -- of for line

-- Closing the opened file and Lua script...
whereto:close()

We are getting this message at the terminal: Processing entry/line 1 2 3 4 5 6 7 8. The script generated the mal-result.tex file, this is it:

\ifnum\malc=1 t\h is is a s\lring aB of T\e \x \T \fi
\ifnum\malc=2 a\ndot o\T \h E\rdot  tEst \D nr\tdot \.N\rdot \fi
\ifnum\malc=3 \adot \adot \a \a aA bB \c C\c \c C \tbar \tflag \tbar \D \tdot \tdot D\tdot \tdot \tbar d\tring \tring \tflag \fi
\ifnum\malc=4 Ee\e eEE fF GGgGGG hHH i k l\lbar \lflag lll\lring l\l \ldot \ldot  mm\fi
\ifnum\malc=5 N\ndot n\n \N \n N\n  o \Pdots \P \Pdots \p \Pdots \P \Pdots  \p  \q q\Q r\rdot \r \rdot \fi
\ifnum\malc=6 SsStT\T Þ\thth \thth \thth \thth ðð Ð Ðð ð \fi
\ifnum\malc=7 u v \v vVVV\V  w \X \x XxYvYVYyvY\fi
\ifnum\malc=8 \z \z z äää\oO \oO ö \oo Ö\oo  öÖ\ey \arlaug \tvimadur \belgthor jåå\fi

It added \ifnum... \fi per line and it randomly changed each rune. We can use a protection per rune, e.g. from a we type {a}, or, instead of \thth we use {\thth} etc. It's a note to Lua not to change the rune randomly but to stick to its original writing. Now, it works for one rune only, therefore we cannot protect more runes as in {abc}, we must use {a}{b}{c} form.

We could check out the second line more closely:

  • \tdot \.N\rdot changed to \D nr.

  • {\tdot }{\.N}{\rdot } hasn't changed, Lua only deleted its protection and the actual form (seed set to zero) is this: \tdot \.N\rdot.

After the second run of lualatex mal-runes.tex we are getting this:

mwe: common

First line is a preview of entered runes, the second line is a modified alternative.

We could compare outputs with different math.randomseed set in Lua, e.g. by following these steps.

  • Run lualatex mal-runes.tex once.
  • Modify mal-runes.lua, line 5 from math.randomseed(0) to math.randomseed(1).
  • Run texlua mal-runes.lua.
  • Make a copy of TeX file by cp mal-result.tex mal-result-1.tex.
  • Modify mal-runes.lua, line 5 from math.randomseed(1) back to math.randomseed(0).
  • Run texlua mal-runes.lua.
  • Uncomment line 23 which starts with \makebox in mal-runes.tex.
  • Run lualatex mal-runes.tex once.

We are getting this output. We can spot differences where the glyphs are in red color. It's a rough estimate because runes and its variants have different widths.

mwe: version with different seeds

The production version looks like this when we comment out lines 20, 21, 22, 23 and 25 in the mal-runes.tex file. If we need to allow line break after each rune we could delete -- in lines 105 and 107 in the mal-runes.lua code. Instead of space we could also use \\allowbreak or even \\hfill. This the final preview of our efforts.

mwe: plain/production version


A trial of a solution, using a loop through the text to be runed. Due to lack of time, I could not make code for every medieval rune, but will come back later on.

\documentclass[12pt,paper=a4]{scrbook}
\usepackage{xstring}
\usepackage{etoolbox}
\usepackage{forloop}
\usepackage{inputenc}
\usepackage{allrunes}
\usepackage[first=1,last=10,quiet,counter=runerand]{lcg}
\usepackage{blindtext}





\makeatletter

\newrobustcmd{\RandomARune}{%
\chgrand[first=1,last=3,quiet=y]% 3 A runes
%\typeout{\arabic{runerand}}
\rand%
\ifnumequal{\number\value{runerand}}{1}{%
\a}{%
\ifnumequal{\number\value{runerand}}{2}{%
\'a}{%
A}}%
}%


\newrobustcmd{\RandomBRune}{%  
\chgrand[first=1,last=2]% 2 B runes
\rand% 
\typeout{\arabic{runerand}}%
\ifnumequal{\number\value{runerand}}{1}{%
b}{%
B}%
}%

\newrobustcmd{\RandomCRune}{%  
\chgrand[first=1,last=3,quiet=y]% 3 C runes
\typeout{\arabic{runerand}}%
\rand% 
\ifnumequal{\number\value{runerand}}{1}{%
c}{%
\ifnumequal{\number\value{runerand}}{2}{%
C}{%
\c}}%
}%


\newrobustcmd{\RandomDRune}{%
\chgrand[first=1,last=7]%  7 D runes
\rand%
\ifnumequal{\number\value{runerand}}{1}{%
d}{%
\ifnumequal{\number\value{runerand}}{2}{%
D}{%
\ifnumequal{\number\value{runerand}}{3}{%
\D}{%
\ifnumequal{\number\value{runerand}}{4}{%
\tring}{%
\ifnumequal{\number\value{runerand}}{5}{%
\tdot}{%
\ifnumequal{\number\value{runerand}}{6}{%
\tflag}{%
\tbar}}}}}}%
}%





\newrobustcmd{\RandomERune}{%  
\chgrand[first=1,last=3,quiet=y]% 3 E runes
\rand% 
\typeout{\arabic{runerand}}%
\ifnumequal{\number\value{runerand}}{1}{%
e}{%
\ifnumequal{\number\value{runerand}}{2}{%
E}{%
\e}}%
}%

\newrobustcmd{\RandomFRune}{%  
\chgrand[first=1,last=2,quiet=y]% 2 F runes
\rand% 
\typeout{\arabic{runerand}}%
\ifnumequal{\number\value{runerand}}{1}{%
f}{%
F}%
}%


\newrobustcmd{\RandomGRune}{%  
\chgrand[first=1,last=3,quiet=y]% 3 G runes
\rand% 
\typeout{\arabic{runerand}}%
\ifnumequal{\number\value{runerand}}{1}{%
g}{%
\ifnumequal{\number\value{runerand}}{2}{%
G}{%
\g}}%
}%

\newrobustcmd{\RandomHRune}{%  
\chgrand[first=1,last=3,quiet=y]% 3 H runes
\rand% 
\ifnumequal{\number\value{runerand}}{1}{%
h}{%
\ifnumequal{\number\value{runerand}}{2}{%
H}{%
\h}}%
}%





\newrobustcmd{\RandomNRune}{%
\chgrand[first=1,last=5,quiet=y]% 5 N runes
\typeout{\arabic{runerand}}
\rand%
\ifnumequal{\number\value{runerand}}{1}{%
\n}{%
\ifnumequal{\number\value{runerand}}{2}{%
\ndot}{%
\ifnumequal{\number\value{runerand}}{3}{%
\N}{%
\ifnumequal{\number\value{runerand}}{4}{%
n}{%
N}}}}%
}%




\newrobustcmd{\RandomLRune}{%
\chgrand[first=1,last=6,quiet=y]% 6 L runes
\typeout{\arabic{runerand}}
\rand%
\ifnumequal{\number\value{runerand}}{1}{%
\l}{%
\ifnumequal{\number\value{runerand}}{2}{%
\lbar}{%
\ifnumequal{\number\value{runerand}}{3}{%
\ldot}{%
\ifnumequal{\number\value{runerand}}{4}{%
\lflag}{%
\ifnumequal{\number\value{runerand}}{5}{%
l}{%
\lring}}}}}%
}%


\newrobustcmd{\RandomMRune}{%  
\chgrand[first=1,last=2,quiet=y]% 2 M runes
\rand% 
\typeout{\arabic{runerand}}%
\ifnumequal{\number\value{runerand}}{1}{%
m}{%
\m}%
\gdef\my@randseed{\number\value{runerand}}%
}%


\newrobustcmd{\RandomPRune}{%
\chgrand[first=1,last=5,quiet=y]% 5 P runes
\typeout{\arabic{runerand}}
\rand%
\ifnumequal{\number\value{runerand}}{1}{%
p}{%
\ifnumequal{\number\value{runerand}}{2}{%
\p}{%
\ifnumequal{\number\value{runerand}}{3}{%
\Pdots}{%
\ifnumequal{\number\value{runerand}}{4}{%
\P}{%
P}}}}%
}%




\newrobustcmd{\RandomRRune}{%  
\chgrand[first=1,last=3,quiet=y]% 3 R runes
\rand% 
\ifnumequal{\number\value{runerand}}{1}{%
r}{%
\ifnumequal{\number\value{runerand}}{2}{%
\rdot}{%
\r}}%
}%


\newrobustcmd{\RandomSRune}{%  
\chgrand[first=1,last=3,quiet=y]% 3 S runes
\rand% 
\ifnumequal{\number\value{runerand}}{1}{%
s}{%
\ifnumequal{\number\value{runerand}}{2}{%
S}{%
\S}}%
}%

\newrobustcmd{\RandomTRune}{%  
\chgrand[first=1,last=3,quiet=y]% 3 T runes
\rand% 
\ifnumequal{\number\value{runerand}}{1}{%
t}{%
\ifnumequal{\number\value{runerand}}{2}{%
T}{%
\T}}%
}%





\makeatother

\newcounter{loopcounter}%
\newcounter{textlengthcounter}%


\makeatletter
\newrobustcmd{\TextWithRandomRunes}[1]{%
\def\myresult{}%
\def\my@textlength{}%
\expandarg\StrLen{#1}[\my@textlength]%
\setcounter{textlengthcounter}{0}% For safety
\setcounter{textlengthcounter}{\my@textlength}%
\addtocounter{textlengthcounter}{1}%
\forloop{loopcounter}{1}{\value{loopcounter} < \value{textlengthcounter}}%
{%
\expandarg%
\StrChar{#1}{\number\value{loopcounter}}[\myresult]%
\IfStrEq*{\myresult}{a}{\textarm{\RandomARune}}{%
\IfStrEq*{\myresult}{A}{\textarm{\RandomARune}}{%
\IfStrEq*{\myresult}{b}{\textarm{\RandomBRune}}{%
\IfStrEq*{\myresult}{B}{\textarm{\RandomBRune}}{%
\IfStrEq*{\myresult}{c}{\textarm{\RandomCRune}}{%
\IfStrEq*{\myresult}{C}{\textarm{\RandomCRune}}{%
\IfStrEq*{\myresult}{d}{\textarm{\RandomDRune}}{%
\IfStrEq*{\myresult}{D}{\textarm{\RandomDRune}}{%
\IfStrEq*{\myresult}{e}{\textarm{\RandomERune}}{%
\IfStrEq*{\myresult}{E}{\textarm{\RandomERune}}{%
\IfStrEq*{\myresult}{f}{\textarm{\RandomFRune}}{%
\IfStrEq*{\myresult}{F}{\textarm{\RandomFRune}}{%
\IfStrEq*{\myresult}{g}{\textarm{\RandomGRune}}{%
\IfStrEq*{\myresult}{G}{\textarm{\RandomGRune}}{%
\IfStrEq*{\myresult}{h}{\textarm{\RandomHRune}}{%
\IfStrEq*{\myresult}{H}{\textarm{\RandomHRune}}{%
\IfStrEq*{\myresult}{l}{\textarm{\RandomLRune}}{%
\IfStrEq*{\myresult}{L}{\textarm{\RandomLRune}}{%
\IfStrEq*{\myresult}{m}{\textarm{\RandomMRune}}{%
\IfStrEq*{\myresult}{M}{\textarm{\RandomMRune}}{%
\IfStrEq*{\myresult}{n}{\textarm{\RandomNRune}}{%
\IfStrEq*{\myresult}{N}{\textarm{\RandomNRune}}{%
\IfStrEq*{\myresult}{p}{\textarm{\RandomPRune}}{%
\IfStrEq*{\myresult}{P}{\textarm{\RandomPRune}}{%
\IfStrEq*{\myresult}{r}{\textarm{\RandomRRune}}{%
\IfStrEq*{\myresult}{R}{\textarm{\RandomRRune}}{%
\IfStrEq*{\myresult}{s}{\textarm{\RandomSRune}}{%
\IfStrEq*{\myresult}{S}{\textarm{\RandomSRune}}{%
\IfStrEq*{\myresult}{t}{\textarm{\RandomTRune}}{%
\IfStrEq*{\myresult}{T}{\textarm{\RandomTRune}}{%
\IfStrEq*{\myresult}{ }{ }{% 
\textarm{\myresult}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}%
\undef\myresult%
\undef\my@textlength%
} %End of loop
}%
\makeatother


\begin{document}
\def\mytext{Dan Dannington uses the fantastic LaTeX code}%


\mytext


\TextWithRandomRunes{\mytext}%

\TextWithRandomRunes{\mytext}%

\TextWithRandomRunes{\mytext}%


\end{document}

Other to-do aspects

  • Add other runes
  • Check for spaces
  • Improve possible output Change the
  • style of runes (medieval,nordish, etc)

enter image description here