Dienstag, 20. August 2013

Hamurabi - die Version zum Artikel


Zu der Artikelreihe "Die 5-Minuten-App", die über drei Ausgaben im Java Magazin erscheint, ist hier für alle Interessierten die jeweils aktuellste Version der dort verwendeten Klasse "Hamurabi.java" zu finden. 
Wer möchte kann die Klasse "Hamurabi.java" auch hier herunterladen. Der Link auf die Datei kann sich unter Umständen später ändern, also gegebenenfalls Verlinkungen oder Bookmarks bitte nur auf dieses Blog setzen. 
Viel Spaß! Anregungen oder auch andere Versionen sind übrigens jederzeit willkommen!
 
/*
 * Hamurabi
 *
 * Frei nach der urspruenglichen BASIC-Version von David H. Ahl, 
 * dem alleine jegliche Ehre und Dank gebuehren.
 * Veroeffentlicht in den 70er Jahren seinem Buch BASIC Computer Games. 
 * Ereignisse und auch die klassische Plage und Ratten fehlen in dieser 
 * einfachen Version. Diese vereinfachte Version ist fuer die 
 * Beitragsreihe "Die 5-Minuten-App" geschrieben. 
 *
 * Mein Dank geht an Werner Diwischek und ganz besonders an 
 * Tim Riemer fuer die ausfuehrlichen Kommentare.
 * Da es nach deren Durchsicht noch etliche Aenderungen gab, gehen 
 * moegliche Unschoenheiten natuerlich ausschliesslich auf mich.
 * 
 * Die aktuellste Version und auch eine vollstaendigere  
 * Version finden Sie unter http://www.punktuelles-im-web.net 
 * Ich freue mich dort ueber Kommentare, Kritik und vielleicht auch 
 * weitere Versionen von Hammurabi.
 * 
 */

package net.einedomain.hamurabi;

import java.util.Random;


/**
 * Ein vereinfachte Version des Spiels Hammurabi.
 * 
 * @author Stephan Elter
 * @version 1.4
 */
public class Hamurabi {

private int verteileKorn = 2000;
private int saeheKorn = 400;
private int kaufeLand = 0;
private int verkaufeLand = 0;
private int ernteProAcker;
private int verstorbeneBuergerGesamt = 0;

private int jahr = 1;
private int buerger = 100;
private int korn = 6000;
private int land = 400;
private int neueBuerger = 0;
private int verstorbeneBuerger = 0;
private int geerntetesKorn = 0;
private int landPreis;
private String abbruchGrund = "";
private boolean ende = false;
private Random random = new Random();

public Hamurabi() {

/*
* erstmalig den Landpreis und Rate fuer Ernte festlegen
*/

bestimmeLandPreis();
bestimmeWetter();

}

public int getKorn() {
return korn;
}

public int getLand() {
return land;
}

public boolean getEnde() {

return ende;
}

public String getBericht() {

if (ende) {
return abbruchGrund;
}

StringBuilder info = new StringBuilder();
StringBuilder ernte = new StringBuilder("\nDas Wetter war ");

/*
* Sicher ist es besser den Text in einer Activity zu erzeugen, damit
* unsere Activities aber aus Platzgruenden schlank bleiben koennen,
* erledigen wir das hier. Please don't try this at home!
*/

switch (ernteProAcker) {

case 1:
case 2:
ernte.append("sehr schlecht. ");
break;
case 3:
ernte.append("schlecht. ");
break;
case 4:
case 5:
ernte.append("normal. ");
break;
case 6:
case 7:
ernte.append("gut. ");
break;
case 8:
case 9:
case 10:
ernte.append("besonders gut. ");
break;
default:
ernte.append("durchschnittlich. ");
}

if (jahr > 1 && geerntetesKorn > 0) {
ernte.append("Die Ernte betrug ");
ernte.append(geerntetesKorn);
ernte.append(" Scheffel Korn. ");
}

info.append("Wir schreiben das Jahr ");
info.append(jahr);
info.append(" Eurer Herrschaft. \n");
info.append("Euer Reich zählt ");
info.append(buerger);
info.append(" treue Bürger. \n");
if (neueBuerger > 0) {
info.append(neueBuerger);
info.append(" neue Bürger kamen in unser Land. \n");
}
if (verstorbeneBuerger > 0) {
info.append("Es starben ");
info.append(verstorbeneBuerger);
info.append(" Bürger. \n");
}
info.append(ernte);
info.append("In den Kornkammern lagern ");
info.append(korn);
info.append(" Scheffel Korn. ");
info.append("Ihr besitzt ");
info.append(land);
info.append(" Acker Land. ");
info.append("Ein Acker Land kostet ");
info.append(landPreis);
info.append(" Scheffel Korn. ");

return info.toString();

}

private void bestimmeLandPreis() {
/*
* Ganz banal wird der Preis fuer einen Acker Land berechnet. Hier ganz
* ohne goettliche Hilfe, also ohne den Wert noch irgendwie zu
* beeinflussen.
*/
landPreis = random.nextInt(7) + 1;
}

private void bestimmeWetter() {
/*
* Wie wird das Wetter und wie faellt damit die Ernte aus? Auf jeden
* Fall helfen wir der Gluecksfee zugunsten der Spieler ein klein wenig
* auf die Spruenge. Wer dem Spieler etwas mehr helfen moechte, kann
* hier natuerlich noch weiter "unterstuetzend" eingreifen.
*/
ernteProAcker = random.nextInt(5) + random.nextInt(5) + 2;
}

public void zug(int verkauf, int ankauf, int nahrung, int saat) {

/*
* Die ganz normale Paranoia, sind die gegebenen Befehle und Werte
* sinnvoll?
*/
if (verkauf < 0) {
verkauf = 0;
}
if (ankauf < 0) {
ankauf = 0;
}
if (nahrung < 1) {
nahrung = 1;
}

if (saat < 0) {
saat = 1;
}
verkaufeLand = verkauf;
kaufeLand = ankauf;
verteileKorn = nahrung;
saeheKorn = saat;

/*
* Vollstaendigen Zug (erst) nach einer Pruefung durchfuehren. Sollte
* das Ende aktuell oder schon frueher erreicht sein, ist kein Zug mehr
* moeglich.
*/

if (!ende) {
if (!pruefeEnde()) {
berechneZug();
}
}

}

private void berechneZug() {

/*
* Hurra! Ein neues Jahr bricht an
*/

jahr = jahr + 1;

/*
* Neues Wetter, neues Glueck? Wie wird die Ernte in diesem Jahr?
*/

bestimmeWetter();

/*
* HANDEL Es kann nur verkauft werden wenn genug Land im Besitz ist, und
* das Korn fuer die Order ausreicht. Gleichzeitiger Kauf und Verkauf
* sind moeglich, auch wenn das nicht sinnvoll ist. Es muss immer 1
* Acker Land im Besitz bleiben und Korn wird zur Sicherheit nie null.
*/
if (verkaufeLand < land) {
if ((korn + (verkaufeLand - kaufeLand) * landPreis) > 0) {
land = land + kaufeLand - verkaufeLand;
korn = korn + (verkaufeLand - kaufeLand) * landPreis;
if (korn < 1) {
korn = 1;
}
}
}

/*
* NAHRUNG Nahrung verteilen. Es kann natuerlich nur verteilt werden was
* da ist. Korn wird zur Sicherheit nie null.
*/
if (verteileKorn > korn) {
verteileKorn = korn;
}
korn = korn - verteileKorn;
if (korn < 1) {
korn = 1;
}

/*
* Auswirkungen der Nahrungsverteilung auf die Bevoelkerung. Reicht das
* Korn fuer alle? 20 Korn pro Buerger? Na dann Prost! Sterben Buerger
* wegen Mangel oder kommen neue Buerger ins Land aufgrund des
* Ueberflusses? Auch hier greifen wir ein um eine moegliche
* Bevoelkerungsexplosion in den Griff zu bekommen.
*/
neueBuerger = 0;
verstorbeneBuerger = 0;
int ausreichendNahrung;
ausreichendNahrung = verteileKorn / 20 - buerger;

if (ausreichendNahrung > 0) {
neueBuerger = ausreichendNahrung / 2;
} else {
verstorbeneBuerger = -ausreichendNahrung;
}

if (neueBuerger > 50) {
neueBuerger = 35 + random.nextInt(20) + 1;
}
verstorbeneBuergerGesamt += verstorbeneBuerger;
buerger = buerger + neueBuerger - verstorbeneBuerger;

/*
* AUSSAAT Es kann (ueberraschenderweise) nur das ausgesaeht werden was
* auch da ist, auch zu viel bereitgestelltes Korn verfaellt. Pro Acker
* werden 2 Scheffel Korn benoetigt. Sind genug Buerger als Arbeiter zum
* Aussaehen da? Wie viel Land, bzw. Acker stehen zur Aussaat denn noch
* zur Verfuegung?
*/
if (korn < saeheKorn) {
saeheKorn = korn;
}
korn = korn - saeheKorn;
if (korn < 1) {
korn = 1;
}

saeheKorn = saeheKorn / 2;

if (buerger * 10 <= saeheKorn) {
saeheKorn = buerger * 10;
}
if (land < saeheKorn) {
saeheKorn = land;
}

/*
* ERNTE Endlich Zeit fuer einen Korn! Verdient haben wir es uns. Da
* runde Zahlen doof sind, machen wir sie eben etwas unrund - falls es
* ueberhaupt eine nennenswerte Ernte gibt.
*/

geerntetesKorn = ernteProAcker * saeheKorn;
if (geerntetesKorn > 150) {
geerntetesKorn = geerntetesKorn + random.nextInt(99);
}
korn = korn + geerntetesKorn;

/*
* Nur noch neuen aktuellen Landpreis bestimmen
*/
bestimmeLandPreis();

}

private boolean pruefeEnde() {

StringBuilder text = new StringBuilder();
/*
* Ist ein Abbruchgrund erreicht? Auch hier waere es sicher besser den
* Text in einer Activity zu erzeugen, So please don't try this at home!
*/
if (verstorbeneBuergerGesamt > 500) {
ende = true;
text.append("Eure Bürger haben sich gegen Eure Herrschaft erhoben. Zu viele Eurer Untertanen starben unter Eurer Herrschaft. ");
}
if (buerger < 10) {
ende = true;
text.append("Ihr habt zu wenige Untertanen. ");
}
if (korn < 10) {
ende = true;
text.append("Eure Kornkammern sind leer. ");
}
if (land < 10) {
ende = true;
text.append("Ihr habt zu wenig Land. ");
}
if (jahr > 24 && ende == false) {
ende = true;
text.append("Nach 25 Jahren ist das Ende Eurer Zeit als Herrscher gekommen.\nEuer Name soll auf ewig gerühmt werden! Ihr habt weise und gerecht regiert.");
}
if (ende) {
abbruchGrund = "\nEure Herrschaft ist beendet. " + text.toString();
}

return ende;
}

}

Keine Kommentare:

Kommentar veröffentlichen