# 99bottles.gp:
# script for gnuplot version 4.2 to create the famous 99-bottles-of-beer-song
# Gnuplot is a plotting program, so of course we also make a plot of the bottles.
#
# March 2007 - Bastian MÃ¤rkisch & Ethan Merritt
# Define a maximum number of bottles in case we do not want the whole song.
max = 99
# Initialize the plot only once (bottles is undefined on first entry).
# Open the "dumb" terminal to generate ascii art
# Define the plot layout such that there are 99 character slots for bottles,
# leaving room for a margin and a shelf-divider at each end.
if (!exists("bottles")) \
set term dumb 104 6 ;\
set border 1 front;\
unset xtics ;\
unset ytics ;\
set lmargin 1;\
set rmargin 1;\
set xrange [0:100] ;\
set yrange [-1:1] ;\
unset key
# Create and initialize the bottles counter
if (!exists("bottles")) bottles = max
# String valued function to create the "bottle(s)" string
# To decide wether we should a plural 's' a dirty substring trick is used, but
# we could always use a ternary operator instead
# Note that there is no name conflict with the bottles variable.
bottles(b) = "bottle" . "s"[0:(b != 1)]
# Function which returns the number b or the string "no more" iff b=0.
# The case of the first letter can be switched by the parameter c.
# Please note that this function can be string or number valued.
number(b,c) = (b > 0) ? sprintf("%d",b) : "nN"[c+1:c+1] . "o more"
# We use a ternary operator to decide what to do next ;-)
action = (bottles != 0) ? \
"Take one down and pass it around" : \
"Go to the store and buy some more"
# Write the new verse into a label
# On the sceond line the modulo trick is used to wrap around the number of bottles
Label1 = sprintf("%s %s of beer on the wall, %s %s of beer.\n", \
number(bottles,1), bottles(bottles), number(bottles,0), bottles(bottles))
Label2 = action . ", " . sprintf("%s %s of beer on the wall.", \
number((bottles + max) % (max + 1), 0), bottles(bottles-1))
# Use the verse as a label for the x-axis
set xlabel Label1.Label2 offset 0,-1
# We will use the sampling grid to control how many bottles are drawn.
# But the set of samples always includes the two end points, which we
# don't want. So we over-write the endpoints with shelf dividers.
set label 1 "|" at 0,1 front
set label 2 "|" at 100,1 front
# Draw the shelf
# In the "dumb" terminal, linetype 6 is an ampersand
set samples bottles+2
plot 1 with impulses linetype 6
# gnuplot's loop mechanism is a restart of the current script file (reread)
bottles = bottles - 1
if (bottles >= 0) reread
# We only get here once the song is finished.
# Prepare the bottle counter for a new start...
bottles = max