#!/usr/bin/env bash

# This is a shell script port of LAND/LORD, by No Time To Play,
# itself a clone of the classic game Hamurabi. Use as you wish.
# Tested in bash, zsh and pdksh as of 2018-10-03. Beware of bugs.

typeset -i population land grain starved immigrants
typeset -i rats planted yield price year plague

population=100
land=1000
grain=$((2000 + $RANDOM % 6 * 100))
starved=10
immigrants=5
rats=200
planted=300
yield=$(($RANDOM % 5 + 1))
price=$(($RANDOM % 6 + 17))
year=1701
plague=0 # The game uses arithmetic truth values: 0 is false.

function report {
	echo

	echo "Milord, I report: in the summer of $year,"

	if (($starved == 1)); then
		echo -n "1 worker ran away, and"
	else
		echo -n "$starved workers ran away, and"
	fi

	echo " $immigrants came seeking work."

	if (($plague)); then
		echo "   A dysentery epidemic claimed half our numbers."
	fi

	echo "Our population total is currently $population."
	echo -n "We harvested $(($yield * $planted)) bushels"
	echo " at $yield bushels per acre."
	echo "Rats destroyed $rats bushels of grain,"
	echo "leaving us with $grain in the barns."
	echo "The plantation now comprises $land acres of land."
	echo "Land trades for the equivalent of $price bushels per acre."
}

function instruct {
	while true; do
		echo -n "How many acres of land to buy? "
		read buying
		if (($buying < 0)); then
			buying=$((-$buying))
		fi
		if (($buying * $price <= $grain)); then
			break
		else
			echo "But we don't have enough grain to sell!"
		fi
	done
	if (($buying > 0)); then
		land=$(($land + $buying))
		grain=$(($grain - $buying * $price))
		echo "Very well, we are left with $grain bushels of grain."
	fi

	while true; do
		echo -n "How many acres of land to sell? "
		read selling
		if (($selling < 0)); then
			selling=$((-$selling))
		fi
		if (($selling <= $land)); then
			break
		else
			echo "But we only have $land acres of land!"
		fi
	done
	if (($selling > 0)); then
		land=$(($land - $selling))
		grain=$(($grain + $selling * $price))
		echo "Very well, we now have $grain bushels of grain."
	fi

	while true; do
		echo -n "How many bushels of grain to pay workers in? "
		read fed
		if (($fed < 0)); then
			fed=$((-$fed))
		fi
		if (($fed <= $grain)); then
			break
		else
			echo "But we only have $grain bushels of grain!"
		fi
	done
	grain=$(($grain - $fed))

	while true; do
		echo -n "How many acres of land to seed? "
		read planted
		if (($planted < 0)); then
			planted=$((-$planted))
		fi
		if (($planted > $land)); then
			echo "But we only have $land acres of land!"
		elif (($planted > $grain * 2)); then
			echo "But we only have $grain bushels of grain!"
		elif (($planted > $population * 10)); then
			echo "But we only have $population people!"
		else
			break
		fi
	done
}

function advance {
	yield=$(($RANDOM % 5 + 1))
	grain=$(($grain + $yield * $planted))
	rats=$(($RANDOM % ($grain * 7 / 100)))
	grain=$(($grain - $rats))
	starved=$(($population - $fed / 20))
	if (($starved < 0)); then
		starved=0
	fi
	population=$(($population - $starved))
	if (($population > 0)); then
		local -i immigrants1=$(($starved / 2))
		local -i immigrants2=$(((5 - $yield) * $grain / 600 + 1))
		immigrants=$(($immigrants1 + $immigrants2))
		if (($immigrants > 50)); then
			immigrants=50
		elif (($immigrants < 0)); then
			immigrants=0
		fi
		population=$(($population + $immigrants))
		plague=$(($RANDOM % ($land / $population) == 0))
		if (($plague)); then
			population=$(($population / 2))
		fi
	fi
	price=$(($RANDOM % 6 + 17))
	year=$(($year + 1))
}

typeset -l answer

until ((population < 1)); do
	report
  
	if (($year % 10 == 0)); then
		echo -n "Should we go on? "; read answer
		if [[ "$answer" == "n" || "$answer" == "no" ]]; then
			echo "And so our story ends."
			exit
		fi
	fi

	instruct
	advance
done

echo

echo "Milord, I have bad news. Everyone left us."
echo "We're broke. Ruined."
echo "If only you could try again..."
