Hammurabi is a very old computer game, in which you are the ruler of ancient Samaria, trying to increase the wealth of your country. Your job is to bring this program into the 21st century by writing it in Scala.
Since some of you have never programmed before, this assignment is in the form of a step-by-step tutorial. Later assignments will leave more up to you.
println statement to print out the following introductory message:
Congratulations, you are the newest ruler of ancient Samaria, elected
for a ten year term of office. Your duties are to dispense food, direct
farming, and buy and sell land as needed to support your people. Watch
out for rat infestations and the plague! Grain is the general currency,
measured in bushels. The following will help you in your decisions:
* Each person needs at least 20 bushels of grain per year to survive.
* Each person can farm at most 10 acres of land.
* It takes 2 bushels of grain to farm an acre of land.
* The market price for land fluctuates yearly.
Rule wisely and you will be showered with appreciation at the end of
your term. Rule poorly and you will be kicked out of office!
Hint #1: You can put this all into a single println statement by
using a so-called “triply-quoted string”; that is, a string
that begins and ends with three double quote marks. Such a string can hold more than one line.How to run this:
|
println statement from above into a function called
printIntroductoryMessage. Test your function by calling it from the REPL.Save and load the modified program. Since the println expression
is now inside a function, it is not automatically executed when
you load the program. To run it, enterprintIntroductoryMessage |
hammurabi. Inside this function put a call to printIntroductoryMessage.Once we have more than one function, we have to arrange them in a certain order. This is a nuisance. To avoid this problem, "wrap" all your code into an object, like this: object Hammurabi {
|
hammurabi function. Since your function is now inside the Hammurabi object, call it by entering Hammurabi.hammurabi. That is, the name of the object, a dot, and the name of the function you want to call. Other functions can be tested similarly. hammurabi function, before the call to printIntroductoryMessage var starved = 0 // how many people starved
var immigrants = 5 // how many people came to the city
var population = 100
var harvest = 3000 // total bushels harvested
var bushelsPerAcre = 3 // amount harvested for each acre planted
var rats_ate = 200 // bushels destroyed by rats
var bushelsInStorage = 2800
var acresOwned = 1000
var pricePerAcre = 19 // each acre costs this many bushels
var plagueDeaths = 0
hammurabi, write a loop to print the following report ten times, with the variable year set to 1, 2, 3, ..., 10. Each of the numbers in the report (shown in red) should be the value of the corresponding variable (remember that you can "add" strings and numbers).
O great Hammurabi! You are in year 1 of your ten year rule. In the previous year 0 people starved to death. In the previous year 5 people entered the kingdom. The population is now 100. We harvested 3000 bushels at 3 bushels per acre. Rats destroyed 200 bushels, leaving 2800 bushels in storage. The city owns 1000 acres of land. Land is currently worth 19 bushels per acre. There were 0 deaths from the plague.
Remember that expressions inside parentheses can extend across more than one line. It is good style to keep your lines short (less than about 80 characters) in a program. A good place to break some of the above println statements is just after a +.
The above summary represents the initial state, at the beginning of
the first year--that is, when you first take office, and before you do any of
the computations below). So, for example, the previous year (under a
different ruler) must have started with 95 people; none starved, and 5
entered the kingdom, so as you enter office you rule 100 people.
Since you are not yet changing the values of any of the variables, when you test the hammurabi function you should get the same report (except for the year number) printed out ten times.
That's it for most of the printing.
var answer = readLine(prompt).toIntbut if the user enters something that isn't an integer, the program will crash. That's frustrating. Instead, copy and test the following function, which I have written for you:
def readInt(message: String): Int = {
try {
readLine(message).toInt
} catch {
case _ : Throwable =>
println("That's not an integer. Please enter an integer.")
readInt(message)
}
}
Questions should be asked in this order, and the player does not get a chance to go back and change an earlier answer. A player who is buying land is not allowed to sell land during the same turn; so if the user asks to buy land, do not call the function that asks how much land to sell.
As an example, the first function has been written for you.
def askHowMuchLandToBuy(bushels: Int, price: Int) = {
var acresToBuy = readInt("How many acres will you buy? ")
while (acresToBuy < 0 || acresToBuy * price > bushels) {
println("O Great Hammurabi, we have but " + bushels + " bushels of grain!")
acresToBuy = readInt("How many acres will you buy? ")
}
acresToBuy
}
And here is a sample call to the function (which you would put inside the hammurabi function).
var acresToBuy = askHowMuchLandToBuy(bushelsInStorage, pricePerAcre) acresOwned = acresOwned + acresToBuyEach function should be given just enough information to test whether the user's answer is legal, and to return that legal answer. That answer should then be used (within the
hammurabi function) to adjust the values of the variables declared in #4 above. Don't forget to test each function as you write it!hammurabi function. Do the update immediately, before going on to the next part (for example, if people die of the plague, there are fewer people when you check for starvation). Test each function as you go.population variable immediately, before going on to the next part.true 15% of the time, and false the other
85% of the time. Or, you could pass in the number of people you have, and return the number
who died (or the number you have left).(20 * number of acres + amount of grain in
storage) / (100 * population) + 1.hammurabi function but outside the "year loop"), use a function to print out a final summary, and to tell the
player how good a job he/she did. I'll leave the details up to you, but the
usual evaluation is based on how many people starved, and how many acres you end up with.Hammurabi.hammurabi at the very end of the file. All the required arithmetic in this program should be integer. You do not need doubles; rounding errors of one or two percentage points are acceptable.
To get random numbers, you need to get a random number generator from Scala's vast library of pre-written code. Put this line at the very beginning of your program:
import scala.util.Random
To get a new random number in the range 0 to n-1, call Random.nextInt(n).
For example, to simulate the roll of a die, you could use Random.nextInt(6)+1. (The +1 is necessary because the function call will return a number between 0 and 5, inclusive.) To do something that happens p percent of the time, use
if (Random.nextInt(100) < p) {
// do something
}
import scala.util.Random
object Hammurabi {
def hammurabi = {...}
Other function definitions
}
Hammurabi.hammurabi
It would be a good idea to read How Assignments Are Graded, but here's a summary: Do exactly what the assignment says to do, use good programming style, test your program carefully, zip up your program (if it's more than a single file), and turn it in via Canvas. Late programs will lose points.
Your program is due before .
"Zipping" files is a way to compress them (make them smaller). More important for this class, it is also a way to combine multiple files into a single file that can be easily uploaded and downloaded.
For this assignment (and many early assignments), your program will consist of only a single file. It is easier for everybody if you don't zip it first. But if your program consists of multiple files, Zip up the entire directory for that program, and submit the zipped file.
Important: "Zip" means the universally understood .zip format. Submissions using a proprietary format such as Microsoft's .rar will be penalized according to how much trouble they cause us.
All assignments are to be submitted via Canvas.
Assignments will be due at 6am precisely. There will be a 10 point penalty (out of 100 points) for programs between one minute and one week late, and a 25 point penalty for programs later than one week. At some unspecified time after one week we will stop accepting assignments.