Posted to tcl by hypnotoad at Mon Oct 22 18:16:29 GMT 2018view pretty

package provide pheme_random 0.1
#package require pheme
namespace eval ::pheme {}
namespace eval ::randomword {}

# Adapted from https://www.dwheeler.com/totro.pl.txt

namespace eval ::randomword {}

proc ::randomword::lrandom list {
  set len [llength $list]
  set idx [expr int(rand()*$len)]
  return [lindex $list $idx]
}

proc ::randomword::lshuffle list {
  set len [llength $list]
  set idx [expr int(rand()*$len)]
  return [lindex $list $idx]
}

proc ::randomword::table {pattern type table} {
  foreach {letter frequency rule} $table {
    for {set x 0} {$x < $frequency} {incr x} {
      dict set cards [incr cardnum] [list $letter $rule]
    }
  }
  set body {}
  append body \n "  " [list set cards $cards]
  append body {
  set srule [yield [info coroutine]]
  while 1 {
    set idxlist [dict keys $cards]
    set N [llength $idxlist]
    set order {}
    foreach id $idxlist {
      set idx [expr {int(floor(rand()*[llength $order]))}]
      set order [::linsert $order $idx $id]
    }
    foreach id $order {
      lassign [dict get $cards $id] letter lrule
      #puts [list $letter $lrule | $srule] ;
      if {$srule && ($srule & $lrule)==0} {  continue }
      set srule [yield $letter]
    }
    if {$srule & 1} { yield {} }

  }
  }
  coroutine ::randomword::${pattern}_$type apply [list {} $body]
}

###
# Syllable Rules
#
# 1 - Can be at ending
# 2 - Can be at beginning
# 4 - Can be in the middle
# 8 - "strong" syllable
# 16 - "sonerant" syllable
###

###
# Build a table of vowels for generic words
###
::randomword::table generic vowel {
  a 12 7
  e 12 7
  i 12 7
  o 12 7
  u 12 7
  ae 1 7
  ai 1 7
  ao 1 7
  aa 1 7
  ay 2 7
  ea 1 7
  ei 3 7
  eo 1 7
  eu 1 7
  ee 1 7
  eau 1 7
  ia 1 7
  io 1 7
  iu 1 7
  ii 1 7
  oa 1 7
  oe 1 7
  oi 1 7
  ou 1 7
  oo 1 7
  ua 2 7
  '  1 4
  y 1 7
}

###
# Build a table of consonants for generic words
###
::randomword::table generic consonant {
  b 3 7
  br 2 6
  c 3 7
  ch 1 7
  ck 1 5
  cl 1 6
  cr 1 6
  d 3 7
  df 1 6
  dr 2 7
  f 3 7
  fl 1 6
  fr 2 6
  g 3 7
  gh 1 7
  gl 1 6
  gr 2 6
  h 3 7
  j 3 7
  k 3 7
  kl 1 6
  kr 2 6
  l 3 7
  ll 1 6
  m 3 7
  n 3 7
  nk 1 5
  p 3 7
  ph 1 7
  pl 1 6
  pr 1 6
  qu 1 6
  r 3 7
  rk 1 5
  s 3 7
  sc 1 7
  sh 1 7
  sk 1 7
  sl 1 6
  sr 1 6
  ss 1 5
  st 1 7
  str 1 6
  t 3 7
  th 1 7
  tr 1 6
  v 3 7
  w 3 7
  wh 1 6
  wk 1 0
  x 1 7
  y 1 7
}

###
# Build a table of vowels for female words
###
###
# Syllable Rules
#
# 1 - Can be at ending
# 2 - Can be at beginning
# 4 - Can be in the middle
# 8 - "strong" syllable
# 16 - "sonerant" syllable
###

::randomword::table female vowel {
  a 12 7
  e 12 7
  i 12 7
  o 12 6
  u 12 6
  ae 1 6
  ai 1 7
  ao 1 6
  aa 1 7
  ah 6 7
  ay 2 7
  ea 1 6
  ei 3 7
  eo 1 6
  eu 1 6
  ee 1 7
  eau 1 6
  ia 1 7
  io 1 6
  iu 1 6
  ii 1 7
  oa 1 6
  oe 1 6
  oi 1 6
  ou 1 6
  oo 1 6
  ua 2 6
  '  1 4
  y 1 7
}

::randomword::table female consonant {
  b 3 6
  br 2 6
  c 3 6
  ch 1 6
  ck 1 5
  cl 1 6
  cr 1 6
  d 3 6
  df 1 6
  dr 2 6
  f 3 6
  fl 1 6
  fr 2 6
  g 3 6
  gh 1 7
  gl 1 6
  gr 2 6
  h 3 6
  j 3 6
  k 3 6
  kl 1 6
  kr 2 6
  l 3 7
  ll 1 7
  m 3 7
  n 3 7
  nk 1 5
  ng 1 6
  p 3 6
  ph 1 7
  pl 1 6
  pr 1 6
  qu 1 6
  r 3 7
  rk 1 5
  s 3 6
  sc 1 6
  sh 1 6
  sk 1 6
  sl 1 6
  sr 1 6
  ss 1 5
  st 1 6
  str 1 6
  t 3 6
  th 1 6
  tr 1 6
  v 3 6
  w 3 6
  wh 1 6
  wk 1 0
  x 1 6
  y 1 7
}

###
# Build a table of vowels for male words
###
::randomword::table male vowel {
  a 12 7
  e 12 7
  i 12 7
  o 12 7
  u 12 7
  ae 1 7
  ai 1 7
  ao 1 7
  aa 1 7
  ay 2 7
  ea 1 7
  ei 3 7
  eo 1 7
  eu 1 7
  ee 1 7
  eau 1 7
  ia 1 7
  io 1 7
  iu 1 7
  ii 1 7
  oa 1 7
  oe 1 7
  oi 1 7
  ou 1 7
  oo 1 7
  ua 2 7
  '  1 4
  y 1 7
}

::randomword::table male consonant {
    b 3 7
    br 2 6
    c 3 7
    ch 1 7
    ck 1 5
    cl 1 6
    cr 1 6
    d 3 7
    df 1 6
    dr 2 7
    f 3 7
    fl 1 6
    fr 2 6
    g 3 7
    gh 1 7
    gl 1 6
    gr 2 6
    h 3 7
    j 3 7
    k 3 7
    kl 1 6
    kr 2 6
    l 3 7
    ll 1 6
    m 3 7
    n 3 7
    nk 1 5
    p 3 7
    ph 1 7
    pl 1 6
    pr 1 6
    qu 1 6
    r 3 7
    rk 1 5
    s 3 7
    sc 1 7
    sh 1 7
    sk 1 7
    sl 1 6
    sr 1 6
    ss 1 5
    st 1 7
    str 1 6
    t 3 7
    th 1 7
    tr 1 6
    v 3 7
    w 3 7
    wh 1 6
    wk 1 0
    x 1 7
    y 1 7
}

proc ::randomword::word {{pattern generic} {length 0}}  {
  if {$length <=0 } {
    set length [expr {3+int(rand()*10)}]
  }
  set vowel [expr {rand()>0.5}]
  set word {}
  for {set i 0} {$i < $length} {incr i} {
    if {$i==0} {
      # Pattern cannot be at the start of a word
      set srule 2
    } elseif {$i==($length-1)} {
      # Pattern cannot be at the end of a word
      set srule 1
    } else {
      # Pattern cannot be in the middle of a word
      set srule 4
    }
    if {$vowel} {
      set chars [${pattern}_vowel $srule]
      #[lrandom $::randomword::vowels($pattern)]
    } else {
      set chars [${pattern}_consonant $srule]
      #set letter [lrandom $::randomword::consonants($pattern)]
    }
    append word $chars
    set vowel [expr {$vowel ^ 1}]
  }
  return $word
}