58 lines
2.3 KiB
Awk
58 lines
2.3 KiB
Awk
#!/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
|
|
}
|
|
}
|