Home Java Java-tips Oop Q-hammurabi Programming: Hammurabi I

Ask Questions?

View Latest Questions

Advertisement


 
 

Programming: Hammurabi I
Posted on: March 12, 2008 at 12:00 AM
Your program will simulate the functioning of an early agricultural society. It is based on the ancient computer game Hammurabi, named after a Babylonian king (See en.wikipedia.org/wiki/Hammurabi) famous for his laws. He also ran a very authoritarian soci

Java Notes

Programming: Hammurabi I

Description

Your program will simulate the functioning of an early agricultural society. It is based on the ancient computer game Hammurabi, named after a Babylonian king (See en.wikipedia.org/wiki/Hammurabi) famous for his laws. He also ran a very authoritarian society in which the peasants were allocated fixed rations of food by the state.

Goal. The user, who has just become the ruler of a kingdom, wants to make a place in history by having having the largest population of peasants. The simulation will last five years or until everyone has starved.

Grain is the basic resource. Each year, ask the ruler how to use the grain in storage.

  • How many bushels to feed the people.
  • How many bushels to use as seed for planting next year's crop.

The remaining grain, if any, is saved for the next year in case of a bad harvest.

Initial Conditions

Your program should create a Kingdom with the following values: an area of 1500 acres, a population of 100, and with 4000 bushels of grain from the previous harvest.

Food and Population Rules

Each person needs a minimum of 20 bushels of grain per year to survive.

Starvation. If the ruler doesn't allocate enough food for everyone, some will starve. The population is then reduced by the number of people who starved.

Immigrants if lots of food. If people receive more than 20 bushels per person, immigrants from neighboring kingdoms will be attracted, resulting in a population increase.

Formula. This simplistic idea of the size of the population can be computed by simply dividing the total amount of food by the amount needed per person.

    myPopulation = food / FOOD_REQUIRED_PER_PERSON

This is inside the simulateOneYear method, where myPopulation is an instance variable representing the Kingdom's current population, and FOOD_REQUIRED_PER_PERSON is a constant predefined to be 20.

For example, if the ruler allocates 2400 bushels, this will support a population of 2400 / 20, which is 120. This would become the new population.

Agriculture

Seed for Planting. Not all grain can be used for feeding the people. Some must be used to plant next year's crop. It takes two bushels of grain to plant an acre. To plant everything therefore requires 2 * area bushels of grain.

Harvest. There are variations in the weather each year. The yield varies from 2 to 6 bushels per planted acre. This number is randomly generated each year.

Separation of concerns - The purpose of each class is different

One of the main purposes of separating a program into different classes is to group data and methods that belong together and not mix the different responsibilities of the classes.

Hammurabi class

This contains the main program, which creates a new Kingdom, gets information from the user/ruler on how to allocate the grain each year, simulates one year, and display the results for that year. It should continue in a loop until the end of the simulation time period or everyone has starved. It should know nothing about how the Kingdom class functions internally; it's communication is only by means of calling a Kingdom object's methods.

There is a private utility method, displayStatus, which is used to display the year, population, and grain of the Kingdom that is passed to it.

The Kingdom class represents the information about a kingdom, and provides methods for getting this information. In addition, it provides a method that simulates one year given the amount of grain to be used for food and seed. The simulation updates instance variables to reflect what happened during that year. This class must not contain user interface operations -- no input / output. All interaction with the user must be in the calling program in the Hammurabi class.

The Hammurabi class first version

This class runs the simulation and provides the user interface. It contains the main method. It creates a Kingdom object called samaria, but you can change that.

This class uses the default constructor. When you write assignments to instance variables, these will be used to initialize any objects which are created. Or these assignments could have been put in a constructor.

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
// File   : hammurabi0/Hammurabi.java
// Purpose: Starting point for working on the Hammurabi program.
// Author : Fred Swartz
// Date   : 07 Oct 2005
// TODO   : * Prompt for amount to feed peasants.
//          * Check that there is enough grain to meet requests.
//          * Also stop simulation if population is 0 (while condition)

import javax.swing.*;

public class Hammurabi {

    //============================================================= main
    public static void main(String[] args) {

        //... Initialization
        Kingdom samaria = new Kingdom();  // Create a new Kingdom


        //... Run the simulation for 5 years or until everyone starves.
        while (samaria.getYear() <= 5) {
            //... Display state of the kingdom at beginning of each year.
            JOptionPane.showMessageDialog(null, samaria.toString());

            //TODO: Ask the ruler how much to feed the people.
            int food = 0;  // Temporary substitute for asking for input.

            //.. Ask the ruler how much grain should be used for seed.
            String plantStr = JOptionPane.showInputDialog(null,
                    "Exalted Ruler, how much of the remaining "
                    + (samaria.getGrain()-food) + " bushels should be planted?");
            int seeds = Integer.parseInt(plantStr);

            //... TODO: Check if not enough grain for this request, Reprompt.

            //... Update the food and population of this kingdom.
            samaria.simulateOneYear(food, seeds);
        }

        //... Show final state.
        JOptionPane.showMessageDialog(null, "At end " + samaria.toString());
    }
}

The Kingdom class first version

There are two portions to a class: data (instance variables) and methods. This class also has "getters" to get instance variable values. The simulateOneYear method, which takes parameters for how much grain to use to plant the next crop, and how much grain to feed the population. Extend it to add population, including a getter method, and extend the simulateOneYear method to update the population.

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
 66 
// File   : hammurabi0/Kingdom.java
// Purpose: Represents a "kingdom".  Starting version.
// Author : Fred Swartz
// Date   : 07 Oct 2005
// TODO   : * Add population instance variable.  Default value 100.
//          * Add a getter method for population.
//          * Compute the new population based on food in simulation..

class Kingdom {
    //========================================================== constants
    private final static int MIN_GRAIN_TO_SURVIVE = 20;
    private final static int MAX_LAND_FARMABLE_PER_PERSON = 15;
    private final static int SEED_REQUIRED_PER_ACRE = 2;

    //================================================= instance variables
    private int myGrain = 4000; // Bushels of grain in storage.
    private int myArea  = 1500; // Area of kingdom.in acres.  Note that
                                // myArea isn't used yet, but will be if
                                // you add a check for the total amount
                                // of land that can be planted.
    private int myYear  = 0;    // Years since founding of kingdom.
    private int myHarvest = 0;  // Last harvest in bushels.

    //=========================================================== getGrain
    public int getGrain() {
        return myGrain;
    }

    //============================================================ getYear
    public int getYear() {
        return myYear;
    }

    //=========================================================== toString
    public String toString() {
        // TODO: Don't forget to add population here too.
        return "Kingdom status at year " + myYear
               + ", last harvest = " + myHarvest
               + ", total grain = " + myGrain;
    }

    //==================================================== simulateOneYear
    public void simulateOneYear(int food, int seed) {

        //TODO: Need to calculate new population.based on food.

        //... Reduce grain stockpile by amount used for food and seed
        myGrain = myGrain - food - seed;

        //... Calculate new harvest
        //    1. How many acres can be planted with seed.
        //    2. The yield per acre is random (2-6)
        //    3. Harvest is yield * area planted.
        int acresPlanted = seed / SEED_REQUIRED_PER_ACRE;
        // TODO: Check that there are enough people and there is
        //       enough land to actually plant that number of
        //       acres.
        int yieldPerAcre = 2 + (int)(5 * Math.random());
        myHarvest        = yieldPerAcre * acresPlanted;

        //... Compute new amount of grain in storage.
        myGrain += myHarvest;  // New amount of grain in storage.

        myYear++;              // Another year has passed.
    }
}

Extra credit possibilities

This above game omits some interesting aspects. After you have the simple version of the program running as described above, you might want to make it more "realistic" by adding some of the following features.

  • Better interface. Don't hesitate to make the interface better.
  • Buying and selling land. Land can be bought from the neighboring kingdoms (or sold back to them) for 20 bushels per acre. The yearly plan that the ruler makes should therefore include how much land to buy/sell in addition to the food and seed allocations. Allowing land to be added is the only way to get the population to really grow.
  • Farming limits. The amount of land that one peasant can farm should be limited to 15 acres. If the population drops, it may not be possible to farm all land.
  • Revolt. If more than 45% of the population starves, there is a revolt which overthrows the ruler, and the game ends.
  • Soldiers. My wife's first reaction was to ask about the soldiers. They could play an important role, but exactly what will be left up to you (eg, suppress revolts, capture land, etc). But perhaps they have to be fed better than the peasants.
  • Additional random fluctuations
    • Rats. Each year, rats eat a random amount from 0-10% of your grain
    • Plague. There is a 15% chance each year of a plague. If that happens, half the population dies.
Advertisement


DMCA.com