#!/usr/bin/python
##################################################################################
#
# ktouchgen.py Builds Levelfiles for ktouch
# This is an enhanced reimplementation of a programm written by
# Haavard Froeiland <havard@student.unsw.edu.au>
#
# This Version was written by
# Hendrik Naumann <hn75@gmx.de>
# License: GPL
# Last edited: 11.10.2001
##################################################################################
#
# SYNTAX OF THE CONFIGFILE
#
# Sections:
# [Main]
# level_rows = Generated rows per level
# row_length = Length of the generated rows
#
# [Level<Num>] Settings for the Levels to create
# lchars = Chars that must be in the words
# in the following levels these chars will be
# permitted to be in the words
# title = Title of the Level. If not given it is set to
# lchars
# rows = Number of rows. This overwrites level_rows.
# type = 0 Wordlist will be used for Level. If type is
# not given this is default.
# type > 0 Words will be created from lchars and permitted
# chars. The number of type indicates the length
# of the genrated words.
#
##################################################################################
from whrandom import randint , random
import string
from string import join , maketrans , translate , count , strip , lower , find , upper
import time
import sys
import ConfigParser
import regex
DOCSTRING = """
Usage :
. / ktouchgen . py wordfile configfile outputfile
wordfile Is an file containing the words the levels are build from .
It should contain one word on each line
configfile File that contains the configuration of the levels .
See ktouchgen . py for documentation .
outputfile The name of the new levelfile . If it exists it will
be overwritten .
"""
class LevelList :
" Level List Class "
def __init__ ( self , Levelchars , Permitchars ) :
self . list = { 0 : [ join ( Levelchars , " " ) ] }
self . wordcount = 0.0
self . llist = Levelchars
self . plist = Permitchars
def SelectWords ( self , Wordlist ) :
"""
SelectWords ( self , Wordlist )
Searches for words only contain Permitchars and at least
one Levelchar .
Calculate the number of levelchars / per chars of the word
and fill this values in an mapping
{ lchars / chars * 1000 : [ list of words with this property ] }
"""
Transstring = maketrans ( " " , " " )
pliststring = join ( self . plist , " " )
lliststring = join ( self . llist , " " )
for Word in Wordlist :
lchar_count = 0
if len ( translate ( Word , Transstring , pliststring ) ) == 0 :
lchar_count = len ( Word ) - len ( translate ( Word , Transstring , lliststring ) )
if lchar_count :
weight = int ( ( float ( lchar_count ) / float ( len ( Word ) ) ) * 1000 )
if self . list . has_key ( weight ) :
self . list [ weight ] . append ( Word )
else :
self . list [ weight ] = [ Word ]
self . wordcount = self . wordcount + 1
def GetRandomList ( self , listlength ) :
"""
GetRandomList ( self , listlength )
Returns a list of randomwords with listlength length .
First choose words with most Levelchars , if these are
not enough , words with less are chosen .
"""
retlist = [ ]
selectlist = [ ]
length = 0
val = 0
temp = 0
keys = self . list . keys ( )
keys . sort ( )
keys . reverse ( )
for key in keys :
if length < listlength :
for count in range ( len ( self . list [ key ] ) - 1 ) :
if length < listlength and key > 0 :
num = randint ( 0 , len ( self . list [ key ] ) - 1 )
word = self . list [ key ] [ num ]
temp = temp + key
del ( self . list [ key ] [ num ] )
val = val + 1
length = length + len ( word )
selectlist . append ( word )
else :
break
else :
break
temp = float ( temp ) / val / 10
print ' Got words with an averages of %(temp).2f %% lchars. ' % vars ( )
# Select the returnlist from selectlist
val = val - 1
length = 0
while length < listlength :
word = selectlist [ randint ( 0 , val ) ]
length = length + len ( word )
retlist . append ( word )
return retlist
def GenArtWord ( self , Wordlength ) :
"""
GenArtWord ( self , Wordlength )
Builds an artifical word ( with length Wordlength ) out of Levelchars and Permitchars .
Does it like : random ( lchar ) + random ( pchar ) + . . . . .
"""
ret = " "
while len ( ret ) < Wordlength :
ret = ret + self . llist [ randint ( 0 , len ( self . llist ) - 1 ) ] + self . plist [ randint ( 0 , len ( self . plist ) - 1 ) ]
return ret
def GetArtList ( self , Listlength , Wordlength ) :
"""
GetArtList ( self , Listlength , Wordlength )
Buids an Wordlist with length Listlength out of artificial words .
See : self . GenArtWord ( )
"""
length = 0
ret = [ ]
while length < Listlength :
word = self . GenArtWord ( Wordlength )
ret . append ( word )
length = length + len ( word )
return ret
def main ( argv ) :
Wordlist = [ ]
UpcaseWordlist = [ ]
# Reading the Wordlist
try :
wordfile = open ( argv [ 1 ] , ' r ' )
except IOError :
print " \n Wordfile couldn ' t be opened. \n " , DOCSTRING
return 1
# Create two Wordlists, one with first char lowered
# (more words for the first levels) and one like it ist read
for wordstring in wordfile . readlines ( ) :
wordstring = strip ( wordstring )
if lower ( wordstring ) != wordstring :
UpcaseWordlist . append ( wordstring )
Wordlist . append ( lower ( wordstring ) )
wordfile . close ( )
# Parse the configfile
# Creates a List Levelops with [(Options), ]
# Optiontuple contains (lchars, title, rows)
conf = ConfigParser . ConfigParser ( )
try :
file = open ( argv [ 2 ] , ' r ' )
except IOError :
print ' \n Configfile could not be opened. \n ' , DOCSTRING
return 1
file . close ( )
conf . read ( argv [ 2 ] )
try :
Rowlength = conf . getint ( ' Main ' , ' row_length ' )
except ConfigParser . MissingSectionHeaderError :
print ' \n Wrong configfile. See ktouchgen.py for Documentation. ' + DOCSTRING
Levelrows = conf . getint ( ' Main ' , ' level_rows ' )
Levelops = [ ]
Levelnum = 1
section = ' Level ' + str ( Levelnum )
while conf . has_section ( section ) :
lchars = [ ]
try :
for char in strip ( conf . get ( section , ' lchars ' ) ) :
lchars . append ( char )
except ConfigParser . NoOptionError :
print ' \n No characters defined for level %(Levelnum)s ! ' % vars ( )
return 1
try :
title = conf . get ( section , ' title ' )
except ConfigParser . NoOptionError :
title = join ( lchars )
try :
rows = conf . getint ( section , ' rows ' )
except ConfigParser . NoOptionError :
rows = Levelrows
try :
type = conf . getint ( section , ' type ' )
except ConfigParser . NoOptionError :
type = 0
Levelops . append ( ( lchars , title , rows , type ) )
Levelnum = Levelnum + 1
section = ' Level ' + str ( Levelnum )
print ' \n Configuration for %(Levelnum)s levels read. \n !!! Be aware, if the Levels are not numberd correctly \n !!! they will not be read completely! ' % vars ( )
# Generate Output
try :
outfile = open ( argv [ 3 ] , ' w ' )
except IOError :
print " Outputfile could not be opened. \n " , DOCSTRING
return 1
outfile . write ( ' ######################################################### \n ' + \
' # Trainingfile generaded ' + time . ctime ( time . time ( ) ) + ' \n ' + \
' # Program written by Hendrik Naumann <hn75@gmx.de> \n ' + \
' # Inspired by H<> vard Fr<46> iland \' s version \n ' + \
' ######################################################### \n ' )
permit_chars = [ ]
Levelnum = 0
for Option in Levelops :
cachestring = " "
Levelnum = Levelnum + 1
for new_char in Option [ 0 ] :
if new_char not in join ( permit_chars , " " ) :
permit_chars . extend ( Option [ 0 ] )
outfile . write ( ' \n # Level %(Levelnum)s \n ' % vars ( ) + Option [ 1 ] + " \n " )
print " Generating Level " + str ( Levelnum )
print join ( permit_chars , " " )
# Generate a LevelList object and give the needed Wordlists
levelwordlist = LevelList ( Option [ 0 ] , permit_chars )
if Option [ 3 ] == 0 :
if lower ( join ( permit_chars , " " ) ) != join ( permit_chars , " " ) :
if upper ( join ( Option [ 0 ] , " " ) ) != join ( Option [ 0 ] , " " ) :
levelwordlist . SelectWords ( Wordlist )
levelwordlist . SelectWords ( UpcaseWordlist )
else :
levelwordlist . SelectWords ( Wordlist )
randomlist = levelwordlist . GetRandomList ( Rowlength * Option [ 2 ] )
else :
randomlist = levelwordlist . GetArtList ( Rowlength * Option [ 2 ] , Option [ 3 ] )
# Write the randomlist
for word in randomlist :
cachestring = cachestring + " " + word
if len ( cachestring ) > Rowlength - 3 :
outfile . write ( strip ( cachestring ) + " \n " )
cachestring = " "
outfile . close ( )
return 0
if __name__ == " __main__ " :
if len ( sys . argv ) == 4 :
main ( sys . argv )
else :
print ' \n Wrong number of parameters \n ' + DOCSTRING