The Big Book of Small EK9 Programs

Adapted from Al Sweigart's The Big Book of Small Python Projects: 81 Easy Practice Programs (No Starch Press, 2021; copyright © 2021 Al Sweigart), which he makes freely available under a Creative Commons Attribution-NonCommercial-ShareAlike licence at inventwithpython.com/bigbookpython. Changes were made: each program was ported from Python to EK9 and remodelled in EK9's idioms.

Project 61 — ROT13 Cipher

This is project 61 of the book, ported to EK9. Its chapter is still being written; until then, this page shows the port itself: a run of it, the whole program, and how it keeps to the original.

A sample run

The player's answers are piped in:

Hello, World!
Uryyb, Jbeyq!
QUIT

Run it with:

ek9 rot13cipher.ek9 < input.txt

It prints:

ROT13 Cipher, by Al Sweigart al@inventwithpython.com

Enter a message to encrypt/decrypt (or QUIT):
The translated message is:
Uryyb, Jbeyq!

Enter a message to encrypt/decrypt (or QUIT):
The translated message is:
Hello, World!

Enter a message to encrypt/decrypt (or QUIT):

The program

#!ek9
defines module bigbook.rot13cipher

  defines constant

    UpperLetters <- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    LowerLetters <- "abcdefghijklmnopqrstuvwxyz"
    Shift <- 13

  defines class

    //THE input idiom of this book, copied unchanged from lib/LineInput.ek9 (the reasons are
    //there): read with next(), and every input loop also stops when ended() is true.
    LineInput
      stdin as Stdin: Stdin()
      inputEnded as Boolean: false

      next()
        <- rtn as String: stdin.next()
        if not rtn?
          inputEnded: true

      ended() as pure
        <- rtn as Boolean: Boolean(inputEnded)

      override operator ? as pure
        <- rtn as Boolean: true

    //THE INPUT AND OUTPUT: everything the player sees or types goes through here, worded by Say.
    Console
      stdout as Stdout: Stdout()
      input as LineInput: LineInput()
      say as Say: Say("en")

      Console()
        -> words as Say
        say: words

      showIntroduction()
        stdout.println(say.introduction())
        stdout.println("")

      //The message to translate; unset when the player types QUIT or the input ends.
      nextMessage()
        <- rtn as String: String()
        stdout.println(say.askMessage())
        if message <- input.next()
          if message.upperCase() <> say.quit()
            rtn: message

      //The translation is computed, not worded: it is shown as the cipher made it. The blank
      //line after it is layout.
      showTranslated()
        -> translated as String
        stdout.println(say.translated())
        stdout.println(translated)
        stdout.println("")

      ended() as pure
        <- rtn as Boolean: input.ended()

      override operator ? as pure
        <- rtn as Boolean: true

  defines function

    //THE GAME: the cipher, with no input or output.

    //A letter moves 13 places round its own alphabet, so case is kept. indexOf is unset for a
    //character that is not in the alphabet, and the guard lets it through unchanged.
    rotated() as pure
      -> character as Character
      <- rtn as String: $character
      letters <- character.isUpperCase() <- UpperLetters : LowerLetters
      if position <- letters.indexOf(character)
        shifted <- (position + Shift) rem length letters
        rtn: letters.subString(shifted, shifted + 1)

    //13 is half of 26, so the same rotation both encrypts and decrypts.
    rot13() as pure
      -> message as String
      <- rtn as String: cat message | map with rotated | collect as String

  defines function

    //THE language of the words, copied unchanged from lib/Language.ek9: BIGBOOK_LANG when it
    //is set (fr, zh, ...), otherwise en.
    language()
      <- rtn as String: EnvVars().get("BIGBOOK_LANG") ?: "en"

  //THE WORDS: every word the player sees or types.
  defines text for "en"

    Say

      introduction()
        "ROT13 Cipher, by Al Sweigart al@inventwithpython.com"

      askMessage()
        "Enter a message to encrypt/decrypt (or QUIT):"

      quit()
        "QUIT"

      translated()
        "The translated message is:"

  defines program

    //ROT13 Cipher (Big Book project 61). Translates each message until the player types QUIT.
    //The game decides; the Console asks and tells, in the player's words.
    Rot13Cipher()
      //A language with no words of its own is unset: ?: falls back to English.
      console <- Console(Say(language()) ?: Say("en"))

      console.showIntroduction()
      running <- true
      while running and not console.ended()
        if message <- console.nextMessage()
          console.showTranslated(rot13(message))
        else
          running: false

About this port