#!/sbin/env awk -f # TCh: the simplest TinyChoice game engine port to POSIX AWK # Usage: awk -f tch.awk your-story.txt # Controls: respond with a number to go to a particular choice, q to quit # Created by Luxferre in 2023, released into public domain BEGIN { curscreen = "" # store the current screen key firstscreen = "" split("", screens) # init the screens map if(ARGC < 2) {print "No input story file!"; exit(1)} while((getline < ARGV[1]) > 0) { if($0 ~ /^=.*=$/) { # header line processing if(curscreen) { # finalize the previous entry gsub(/^\n+/, "", screens[curscreen]) gsub(/\n+$/, "", screens[curscreen]) } else firstscreen = -999 curscreen = tolower(substr($0, 2, length($0)-2)) if(firstscreen == -999) firstscreen = curscreen # save the key value } else if(curscreen) screens[curscreen] = screens[curscreen] $0 "\n" } close(ARGV[1]) delete ARGV[1] # actual runtime logic curscreen = ("start" in screens) ? "start" : firstscreen while(length(curscreen) > 0) { # get the lines of the current screen l = split(screens[curscreen], lines, "\n") split("", choices) # init the choices array ch = 1 # init the choice number for(i=1;i<=l;i++) { # we must iterate in order line = lines[i] if(index(line, "->") > 0) { # we have a choice spec split(line, rch, /[ \t]*\->[ \t]*/) tlabel = rch[1] # label is before -> tscreen = rch[2] # target screen is after -> gsub(/^[ \t]+/, "", tlabel) # trim leading spaces in the label gsub(/[ \t]+$/, "", tlabel) # trim trailing spaces in the label gsub(/^[ \t]+/, "", tscreen) # trim leading spaces in the ref gsub(/[ \t]+$/, "", tscreen) # trim trailing spaces in the ref if(!(tscreen in screens)) { printf("Invalid reference %s!\n", tscreen) exit(1) } choices[ch] = tscreen printf("%u) %s\n", ch++, tlabel) } else print line # just print the line "as is" } do { printf "\n> "; if((getline) <= 0) break # prompt for the user choice if($1 == "q" || $1 == "Q" || $1 == "quit" || $1 == "QUIT") { print "Bye!"; exit(0) } ch = int($1) } while(!(ch && (ch in choices) && (choices[ch] in screens))) curscreen = choices[ch] # jump to the selected screen } }