Newer
Older
moobreeder / Cow.java
/**
 * Moobreeder is a simple cow breeding game to illustrate the principles of
 * selective breeding to KS3 pupils.
 *
 * (c) Daniel Vedder 2018, Amano Christian School
 * Licensed under the terms of the MIT license.
 * https://git.synoikos.de/daniel/moobreeder
 */

/*
 * This file holds the cow class and associated methods.
 */

import java.util.HashMap;
import java.util.Iterator;
import java.io.Serializable;

public class Cow implements Serializable
{
	private static int idCounter = 1;
	private static int maxGen = 1;
	
	private int id;
	private int generation;
	private int[] parents;
	private String name;
	private String sex;
	private HashMap<String, Integer> traits;

	/*
	 * This constructor provides a default cow or bull to start the game with.
	 */
	public Cow(String desiredSex)
	{
		sex = desiredSex;
		id = idCounter;
		idCounter++;
		name = makeName(sex, id);
		generation = 1;
		traits = new HashMap<String, Integer>();
		traits.put("milk", Herd.randomInt(5));
		traits.put("strength", Herd.randomInt(5));
		traits.put("meat", Herd.randomInt(5));
		traits.put("aggression", Herd.randomInt(10));
		parents = new int[] {0,0};
	}

	/*
	 * This constructor is used when a cow is born through breeding.
	 */
	public Cow(Cow father, Cow mother)
	{
		//Figure out the ID and save the parents' ID numbers
		id = idCounter;
		idCounter++;
		parents = new int[] {father.getID(), mother.getID()};
		//Figure out the generation
		if (father.getGeneration() > mother.getGeneration())
			generation = father.getGeneration()+1;
		else generation = mother.getGeneration()+1;
		if (generation > maxGen) maxGen = generation;
		//Choose a random sex
		if (Herd.randomInt(2) == 1) sex = "male";
		else sex = "female";
		name = makeName(sex, id);
		//Calculate new trait values
		traits = new HashMap<String, Integer>();
		Iterator<String> keys = mother.getTraits().keySet().iterator();
		while (keys.hasNext()) {
			String k = keys.next();
			traits.put(k, combineTrait(father.getTraits().get(k),
									   mother.getTraits().get(k)));
		}
	}

	public static int getMaxGen()
	{
		return maxGen;
	}

	public int getID()
	{
		return id;
	}

	public int getGeneration()
	{
		return generation;
	}

	public int[] getParents()
	{
		return parents;
	}
	
	public String getName()
	{
		return name;
	}

	public String getSex()
	{
		return sex;
	}

	public HashMap<String, Integer> getTraits()
	{
		return traits;
	}

	public String rateCow(String use)
	{
		int rating = 0;
		String trait = "";
		if (use == "dairy") trait = "milk";
		else if (use == "plowing") trait = "strength";
		else if (use == "beef") trait = "meat";
		else System.out.println("ERROR No such use: "+use);
		rating = (traits.get(trait)*2) - (int) (Math.pow(traits.get("aggression"),2));
		return "This is a "+rating2string(rating)+" cow for "+use+".";
	}

	/*
	 * Return a string rating for values between 0 and 20.
	 */
	private String rating2string(int rating)
	{
		if (rating < 1) return "useless";
		else if (rating < 3) return "terrible";
		else if (rating < 6) return "pretty bad";
		else if (rating < 9) return "moderate";
		else if (rating < 12) return "passable";
		else if (rating < 15) return "fairly good";
		else if (rating < 18) return "pretty good";
		else if (rating < 20) return "very good";
		else return "excellent";
	}

	private String makeName(String sex, int id)
	{
		if (sex == "male") return "Bull #"+id+" "+unicode(0x1F402);
		else if (sex == "female") return "Cow #"+id+" "+unicode(0x1F404);
		else return "ERROR No such sex: "+sex;
	}

	private String unicode(int codePoint)
	{
		return new StringBuilder().appendCodePoint(codePoint).toString();
	}

	private int combineTrait(int fathertrait, int mothertrait)
	{
		//FIXME This should have a higher variance
		int newtrait = (int) Math.round((fathertrait+mothertrait)/2);
		int quartertrait = (int) Math.round(newtrait*0.25);
		int randomfactor = Herd.randomInt(quartertrait*2) - quartertrait;
		return newtrait+randomfactor;
	}

	public static void resetCounters()
	{
		idCounter = 1;
		maxGen = 1;
	}	
}