program Hamurabi (input, output);

  var
  Year,
  Population,
  Area,
  Grain : integer;
  Grain_given_to_population_this_year,
  Acres_seeded_this_year,
  Population_starved_this_year,
  Population_born_this_year,
  Grain_eaten_by_rats_this_year,
  Harvest_per_acre_this_year : integer;
  Plague_this_year : boolean;
  Total_population_starved : integer;
  Average_percentage_starved : real;
  Mismatchflag,
  Breakflag,
  Very_wrong_answer,
  Too_many_people_starved : boolean;


  procedure ShowTooFewBushelsMessage;
  begin
    writeln('HAMURABI:  THINK AGAIN.  YOU HAVE ONLY');
    writeln(Grain, ' BUSHELS OF GRAIN.  NOW THEN.');
  end;


  procedure ShowTooFewAcresMessage;
  begin
    writeln('HAMURABI:  THINK AGAIN. YOU HAVE ONLY ', Area, ' ACRES.  NOW THEN,');
  end;


  procedure ShowTooFewPeopleMessage;
  begin
    writeln('BUT YOU HAVE ONLY ', Population, ' PEOPLE TO TEND THE FIELDS!  NOW THEN,');
  end;


  procedure ShowIntroText;
  begin
    writeln;
    writeln;
    writeln('HAMURABI':32);
    writeln('CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY':50);
    writeln;
    writeln('PORTED TO AMIGA BY DR. GURU':43);
    writeln;
    writeln;
    writeln('TRY YOUR HAND AT GOVERNING ANCIENT SUMERIA');
    writeln('FOR A TEN-YEAR TERM OF OFFICE.');
    writeln;
  end;


  procedure Initialize;
  begin
    Year := 1;
    Population := 100;
    Area := 1000;
    Grain := 2800;
    Total_population_starved := 0;
    Average_percentage_starved := 0;
    Population_starved_this_year := 0;
    Population_born_this_year := 5;
    Grain_eaten_by_rats_this_year := 200;
    Harvest_per_acre_this_year := 3;
    Plague_this_year := FALSE;
    Mismatchflag := FALSE;
    Breakflag := FALSE;
    Very_wrong_answer := FALSE;
    Too_many_people_starved := FALSE;
    randomize;
  end;


  procedure ReportStats;
  begin
    writeln;
    writeln;
    writeln('HAMURABI: I BEG TO REPORT TO YOU,');
    writeln('IN YEAR ', Year, ', ', Population_starved_this_year, ' PEOPLE STARVED, ', Population_born_this_year, ' CAME TO THE CITY,');
    if Plague_this_year = TRUE then writeln('A HORRIBLE PLAGUE STRUCK! HALF THE PEOPLE DIED.');
    writeln('POPULATION IS NOW ', Population);
    writeln('THE CITY NOW OWNS ', Area,' ACRES.');
    writeln('YOU HARVESTED ', Harvest_per_acre_this_year, ' BUSHELS PER ACRE.');
    writeln('RATS ATE ', Grain_eaten_by_rats_this_year, ' BUSHELS.');
    writeln('YOU NOW HAVE ', Grain, ' BUSHELS IN STORE.');
    writeln;
  end;


  procedure BuySellLand;
  var
  Inputstring : string;
  Code,
  Acre_price,
  Acres_bought,
  Acres_sold : integer;
  begin
    Acre_price := 17 + Random(10);
    writeln('LAND IS TRADING AT ', Acre_price, ' BUSHELS PER ACRE');
    repeat
    begin
      write('HOW MANY ACRES DO YOU WISH TO BUY? ');
      readln(Inputstring);
      Val(Inputstring, Acres_bought, Code);
      if Acres_bought < 0 then
      begin
        Very_wrong_answer := TRUE;
        exit;
      end;
      if Acre_price * Acres_bought > Grain then ShowTooFewBushelsMessage;
    end;
    until Acre_price * Acres_bought <= Grain;
    if Acres_bought > 0 then
    begin
      Area := Area + Acres_bought;
      Grain := Grain - Acres_bought * Acre_price;
    end;
    if Acres_bought = 0 then
    begin
      repeat
      begin
        write('HOW MANY ACRES TO YOU WISH TO SELL? ');
        readln(Inputstring);
        Val(Inputstring, Acres_sold , Code);
        if Acres_sold < 0 then
        begin
          Very_wrong_answer := TRUE;
          exit;
        end;
        if Acres_sold > Area then ShowTooFewAcresMessage;
      end;
      until Acres_sold <= Area;
      Area := Area - Acres_sold;
      Grain := Grain + Acres_sold * Acre_price;
    end;
  end;


  procedure FeedPeople;
  var
  Code : integer;
  Inputstring : string;
  begin
    writeln;
    repeat
    begin
      write('HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE? ');
      readln(Inputstring);
      Val(Inputstring, Grain_given_to_population_this_year , Code);
      if Grain_given_to_population_this_year < 0 then
        begin
          Very_wrong_answer := TRUE;
          exit;
        end;
      if Grain_given_to_population_this_year > Grain then ShowTooFewBushelsMessage;
    end
    until Grain_given_to_population_this_year <= Grain;
    Grain := Grain - Grain_given_to_population_this_year;
  end;


  procedure PlantSeeds;
  var
  Code : integer;
  Inputstring : string;
  begin
    writeln;
    repeat
    begin
      Mismatchflag := FALSE;
      write('HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED? ');
      readln(Inputstring);
      Val(Inputstring, Acres_seeded_this_year, Code);
      if Acres_seeded_this_year < 0 then
        begin
          Mismatchflag := TRUE;
          Very_wrong_answer := TRUE;
          exit;
        end;
      if Acres_seeded_this_year > Area then
      begin
        ShowTooFewAcresMessage;
        Mismatchflag := TRUE;
      end;
      if Mismatchflag = FALSE then
      begin
        if trunc(Acres_seeded_this_year/2) > Grain then
        begin
          ShowTooFewBushelsMessage;
          Mismatchflag := TRUE;
        end;
      end;
      if Mismatchflag = FALSE then
      begin
        if Acres_seeded_this_year >= 10*Population then
        begin
          ShowTooFewPeopleMessage;
          Mismatchflag := TRUE;
        end;
      end;
    end;
    until Mismatchflag = FALSE;
    Grain := Grain - trunc(Acres_seeded_this_year/2);
  end;


  procedure CalculateHarvestAndRats;
  var Rats_variable_temp : integer;
  begin
    Harvest_per_acre_this_year := random(5) + 1;
    Grain_eaten_by_rats_this_year := 0;
    Rats_variable_temp := random(5) + 1;
    if ((Rats_variable_temp = 2) OR (Rats_variable_temp = 4)) then
      Grain_eaten_by_rats_this_year := trunc(Grain/Rats_variable_temp);
    Grain := Grain + Harvest_per_acre_this_year*Acres_seeded_this_year - Grain_eaten_by_rats_this_year;
  end;


  procedure CalculatePopulationGrowthStarvingAndPlague;
  var Population_fed_temp : integer;
  begin
    Population_born_this_year := trunc((random(5) + 1)*(20*Area + Grain)/(Population*100) + 1);
    Population_fed_temp := trunc(Grain_given_to_population_this_year/20);
    Population_starved_this_year := Population - Population_fed_temp;
    if Population_starved_this_year < 0 then Population_starved_this_year := 0;
    if Population_starved_this_year > 0.45*Population then
    begin
      Too_many_people_starved := TRUE;
      exit;
    end;
    Average_percentage_starved := ((Year - 1)*Average_percentage_starved + 100*Population_starved_this_year/Population)/Year;
    Population := Population - Population_starved_this_year;
    Total_population_starved := Total_population_starved + Population_starved_this_year;
    Population := Population + Population_born_this_year;
    if random(100) < 15 then
    begin
      Plague_this_year := TRUE;
      Population := trunc(Population/2);
    end
    else
      Plague_this_year := FALSE;
  end;


  procedure ShowEndEvaluation;
  var
  k : integer;
  Acres_per_person : real;
  begin

    if Very_wrong_answer = TRUE then
    begin
      writeln;
      writeln('HAMURABI: I CANNOT DO WHAT YOU WISH.');
      writeln('GET YOURSELF ANOTHER STEWARD!!!!!');
    end
    else
      if Too_many_people_starved = TRUE then
      begin
        writeln;
        writeln;
        writeln('YOU STARVED ', Population_starved_this_year, ' PEOPLE IN ONE YEAR!!!');
        writeln('DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY');
        writeln('BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE');
        writeln('ALSO BEEN DECLARED NATIONAL FINK!!!!');
      end
      else
      begin
        ReportStats;
        Acres_per_person := area/population;
        writeln('IN YOUR 10-YEAR TERM OF OFFICE, ', Average_percentage_starved:3:1, ' PERCENT OF THE');
        writeln('POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF');
        writeln(Total_population_starved, ' PEOPLE DIED!!');
        writeln('YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH');
        writeln(acres_per_person:4:2, ' ACRES PER PERSON.');
        if ((Average_percentage_starved > 33) OR (Acres_per_person < 7)) then
        begin {grade D}
          writeln('DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY');
          writeln('BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE');
          writeln('ALSO BEEN DECLARED NATIONAL FINK!!!!');
        end
        else
          if ((Average_percentage_starved > 10) OR (Acres_per_person < 9)) then
          begin {grade C}
            writeln('YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV.');
            writeln('THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND,');
            writeln('FRANKLY, HATE YOUR GUTS!!');
          end
          else
            if ((Average_percentage_starved > 3) OR (Acres_per_person < 10)) then
            begin {grade B}
              writeln('YOUR PERFOMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT');
              writeln('REALLY WASN',chr(39),'T TOO BAD AT ALL. ', trunc(Population*0.8*random), ' PEOPLE');
              writeln('DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR');
              writeln('TRIVIAL PROBLEMS.');
            end
            else
            begin {grade A}
              writeln('A FANTASTIC PERFORMANCE!!  CHARLEMAGNE, DISRAELI, AND');
              writeln('JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!');
            end;
      end;
    for k := 1 to 10 do
      write(chr(7)); {BEL character = alarm sign}
    writeln('SO LONG FOR NOW.');
    writeln;
  end;

begin
  ShowIntroText;
  Initialize;
  while (year <= 10) AND (Breakflag = FALSE) do
  begin
    ReportStats;
    BuySellLand;
    if Very_wrong_answer = TRUE then Breakflag := TRUE;
    if Breakflag = FALSE then
    begin
      FeedPeople;
      if Very_wrong_answer = TRUE then Breakflag := TRUE;
    end
    if Breakflag = FALSE then
    begin
      PlantSeeds;
      if Very_wrong_answer = TRUE then Breakflag := TRUE;
    end
    if Breakflag = FALSE then
    begin
      CalculateHarvestAndRats;
      CalculatePopulationGrowthStarvingAndPlague;
      if Too_many_people_starved = TRUE then Breakflag := TRUE;
    end
    if Breakflag = FALSE then Year := Year + 1;
  end;
  ShowEndEvaluation;
end.