Using Groovy to write scripts

Leave a comment

Due to its simplicity and flexibility, Groovy is a great language to write readable scripts providing a variety of capabilities. Several tasks can easily be simplified to a Groovy script. Below is my top 5 of most useful Groovy language features.

Closely related to Java:

If you can write Java code, you can write Groovy code. In Groovy you can make use of all the libraries the Java platform has to offer. Furthermore a lot of the Java syntax also works in Groovy.

Functional programming:

Another useful aspect of Groovy programming are its closures. These allow you to treat chunks of code as separate code, which makes it possible to inject these chunks into another function. A good example showcasing the use of closures is the ‘each’ function that is added to a lot of objects.

String[] animals = ["horse", "dog", "cat"]

animals.each {
    println(it)
}

GStrings:

GStrings are a useful addition to traditional Java strings allowing you to inject expressions right into the string itself.

def value = 'horse'
println("The given animal is a ${value}!")

Text file processing capabilities:

Groovy adds the eachLine function to the File class, which makes it very easy to process a text document line by line.

new File("text.txt").eachLine {
    line ->
    println(line)
}

Type inference:

def variable = 'Test'

Using the ‘def’ keyword, you can omit the type of a variable. The compiler will ‘infer’ this type based on the operations and assignments you perform using it.

cleaner.groovy explained

Leave a comment

//Create a String array containing the data files.
String[] filesToClean = [
    "names_male.dic",
    "names_female.dic",
    "names_last.dic"
]

//For each data file.
filesToClean.each {
    String filename ->

    def file = new File(filename)

    //Create a temporary file.
    def tempfile = new File("${filename}.temp")
    def tempfileWriter = new PrintWriter(tempfile)

    //For each line.
    file.eachLine {
        line ->

        //Take the first 15 characters and remove trailing spaces.
        def cleanedLine = line.substring(0, 15).trim()

        //Write the cleaned line to the temporary file.
        tempfileWriter.println(cleanedLine)
    }

    tempfileWriter.flush()
    tempfileWriter.close()

    //Delete the original file.
    file.delete()

    //Rename the temporary file to the name of the original file.
    tempfile.renameTo(filename)
}

Random existing name algorithm

Leave a comment

Of all name generation algorithms, this one is probably the easiest to write.

Java Code:

public String generateName() {
    int randomNumber = random.nextInt(names.size());
    return names.get(randomNumber);
}

In which ‘names’ is a list of names and ‘random’ is a random generator.

Advantages:

  • Names generated are as strong as those in the list.
  • Very easy to implement.

Disadvantages:

  • The amount of names you can generate is as limited as the amount of names you have in the provided list.
  • High probability of non-unique names.

Remarks:

If you want to use this algorithm in a larger function, which returns multiple names, it is advisable to store the returned names in a HashSet or a similar collection to avoid duplicate results.

Output:

GLENN MARCUS BENTON LOREN EARLE
STEVE CARY SAL HOSEA RALEIGH
FRITZ HORACE SHERWOOD JUDE MCKINLEY
DERICK MARC CRISTOBAL MORGAN OLIVER
ROYCE RUSSEL DEANGELO ASA IAN
DANILO COY RICKIE ROSS BLAKE
ISAAC KEITH BUDDY HOBERT BUSTER
CHADWICK HERBERT DORIAN FLETCHER FERNANDO
OMAR TRENT CHARLEY BERNARDO THANH
FABIAN MICKEY MARLON GARFIELD FILIBERTO
ASHLEY HANK PEDRO NORMAND PATRICIA
ERNEST ARNOLDO LORENZO FORREST ANTIONE
PABLO OLLIE ESTEBAN RUDOLF TYLER
ANDRE HARLEY DEMARCUS HERMAN PHIL
STEPHEN RUBEN ALAN CYRIL JORDON
FRANKLYN ROBIN WILEY ANGEL HILTON
ROCCO GASTON GUADALUPE MIQUEL DELMAR
STUART CLAYTON DAN DEANDRE JACK
LANNY ELVIN GALEN JOSE RICKEY
ABDUL CHONG ARTHUR SHAD ERIN

Unit testing algorithms that use random numbers

Leave a comment

While writing algorithms for my name generation library I encountered a problem. Since I wanted to write my algorithms in a test-driven manner and the random existing name algorithm uses a random number generator I had a problem because I didn’t know how to write unit tests for classes containing some randomness.

After trying out some things I wrote the unit test shown below:

@Test
public void testGenerateName() {
    List<String> names = new ArrayList<String>();
    names.add(FIRST_NAME);
    names.add(SECOND_NAME);

    RandomExistingNameStrategy generatorStrategy = new RandomExistingNameStrategy(names);

    Random randomMock = mock(Random.class);
    generatorStrategy.setRandom(randomMock);

    when(randomMock.nextInt(names.size())).thenReturn(0);
    assertEquals(FIRST_NAME, generatorStrategy.generateName());
    when(randomMock.nextInt(names.size())).thenReturn(1);
    assertEquals(SECOND_NAME, generatorStrategy.generateName());

    verify(randomMock, times(2)).nextInt(names.size());
}

I used the Mockito mocking framework to create a mock of the Random generator, which I then inserted using a package-private setter method. I scripted the mock to return first the value 0 and then the value 1, which allowed me to test the output of the algorithm.

Name generation test data

Leave a comment

As always, when you’re trying to test an algorithm it is useful to have some test data at your disposal. I searched around and came up with the given lists of names that will be used by our name generation algorithms:

I downloaded these lists as files and renamed them like this:

  • names_male.dic
  • names_female.dic
  • names_last.dic

Now the only problem left with these files is that the data is unclean. What I mean by this is that the files contain some other data, which we don’t need for our algorithms. Cleaning these files can be done using a simple groovy script. (I’ll explain this script in one of my next posts)

cleaner.groovy

def filesToClean = [
    "names_male.dic",
    "names_female.dic",
    "names_last.dic"
]

filesToClean.each {
    filename ->

    def file = new File(filename)
    def tempfile = new File("${filename}.temp")
    def tempfileWriter = new PrintWriter(tempfile)

    file.eachLine {
        line ->

        def cleanedLine = line.substring(0, 15).trim()
        tempfileWriter.println(cleanedLine)
    }

    tempfileWriter.flush()
    tempfileWriter.close()

    file.delete()
    tempfile.renameTo(filename)
}

Now that we have some clean dictionaries to work with we can start writing name generation algorithms.

Hangman

Leave a comment

Hangman

As I said, I’ll be regularly reposting content of my old blog on this new one. Here is an edited version of one of my old posts:

I’ll soon restart work on my Hangman game. This time the programming language I’ve chosen is Java. The rules and features of the game are described next. You will notice that I’ve chosen a subset of the original features, this is due to the vagueness of some of the original features.

Rules:

Everyone knows the pen & paper game of Hangman in which you have to guess a word before you are being hanged. If you guess a wrong character, then a new part of the gallows is drawn. When the entire gallows has been drawn, you have lost the game.

Features:

My computer version of the Hangman game will include following features:

  • Several game variants (Normal mode, Time trial, Death race and Battle mode)
  • Several play modes (Human only, Human vs. Human, Human vs. AI, Human vs. AI or Human)
  • AI bot

Artificial intelligence:

The artificial intelligence in the game is a separate entity connecting to the server. Several features I currently have in mind for the AI are:

  • Learning (The AI’s vocabulary grows, as it plays more games)
  • Chatting (The AI’s try to participate in the in-game chatting)
  • Name generation (The bots generate their names either based on a dictionary of names, or based on the other players names)

Name generation library

Leave a comment

Description

I’m currently working on a Java port of my C# name generation library. I’ll be reposting some of the articles I made on my other blog concerning name generation to get you all up to speed on the different algorithms implemented by the library.

The algorithms that will be included in the port are:

  • Random existing name algorithm
  • Markov chain name generation algorithm (Standard, grammar-based)
  • Syllable-based name generation algorithm

I will provide posts with information concerning each of these algorithms and furthermore I will publish the final jar file on this blog using an open-source license.

Use

A name generation library like this can be used in a lot of computer games, but it would be especially useful in roleplaying games. You would be able to use it to generate names for the peoples and locations of your fantasy world for example.

Older Entries

Follow

Get every new post delivered to your Inbox.