Newer
Older
moobreeder / Herd.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 is a singleton class that holds the current herd.
 */

import java.util.ArrayList;
import java.util.Random;
import java.io.*;

public class Herd
{
	public static int initialSize = 4;
	private static Herd singleton;
	//allow other classes to access the RNG
	public static Random random; 
	
	private ArrayList<Cow> herd;
	private Cow[] parents;
	private Cow[] offspring;

	private Herd()
	{
		herd = new ArrayList<Cow>();
		parents = new Cow[] {null, null};
		offspring = new Cow[] {null, null};
		for (int i = 0; i < initialSize; i++) {
			String sex = "female";
			if ((i % 2) == 0) sex = "male";
			herd.add(new Cow(sex));
		}
	}

	public static Herd getInstance()
	{
		if (singleton == null) {
			random = new Random();
			singleton = new Herd();
		}
		return singleton;
	}

	public int size()
	{
		return herd.size();
	}

	public Cow getNthCow(int n)
	{
		return herd.get(n);
	}

	public Cow getCow(int id)
	{
		for (int c = 0; c < herd.size(); c++) {
			if (herd.get(c).getID() == id)
				return herd.get(c);
		}
		return null;
	}

	public void removeCow(int id)
	{
		Cow c = getCow(id);
		if (c != null) herd.remove(c);
	}

	public boolean isParent(int id)
	{
		if ((parents[0] != null && parents[0].getID() == id) ||
			(parents[1] != null && parents[1].getID() == id))
			return true;
		else return false;
	}

	public void setParent(int id)
	{
		Cow p = getCow(id);
		if (p == null) return;
		if (p.getSex() == "male") parents[0] = p;
		else if (p.getSex() == "female") parents[1] = p;
	}

	public void removeParent(int id)
	{
		if (parents[0] != null && parents[0].getID() == id)
			parents[0] = null;
		else if (parents[1] != null && parents[1].getID() == id)
			parents[1] = null;
	}

	public String checkBreeding()
	{
		//check both parents present
		if (parents[0] == null) return "You haven't selected a bull!";
		if (parents[1] == null) return "You haven't selected a cow!";
		//check previous offspring
		if (offspring[0] != null || offspring[1] != null)
			return "You still have calves from the last round of breeding!";
		//check age difference (max 3 generations)
		if (Math.abs(parents[0].getGeneration() - parents[1].getGeneration()) > 3)
			return "The age difference between the parents is too great!";
		//check for siblings
		if (parents[0].getParents()[0] == parents[1].getParents()[0] &&
			parents[0].getParents()[1] == parents[1].getParents()[1])
			return "You cannot let siblings mate!";
		return "OK";
	}

	public void breed()
	{
		if (checkBreeding() != "OK") return;
		int noffs = random.nextInt(2)+1;
		offspring[0] = new Cow(parents[0], parents[1]);
		if (noffs == 2) offspring[1] = new Cow(parents[0], parents[1]);
	}

	public boolean isCalf(int id)
	{
		if ((offspring[0] != null && offspring[0].getID() == id) ||
			(offspring[1] != null && offspring[1].getID() == id))
			return true;
		else return false;
	}

	public void keepCalf(int id)
	{
		int o = -1;
		if (offspring[0] != null && offspring[0].getID() == id) o = 0;
		else if (offspring[1] != null && offspring[1].getID() == id) o = 1;
		if (o >= 0) {
			herd.add(offspring[o]);
			offspring[o] = null;
		}
	}

	public void discardCalf(int id)
	{
		int o = -1;
		if (offspring[0] != null && offspring[0].getID() == id) o = 0;
		else if (offspring[1] != null && offspring[1].getID() == id) o = 1;
		if (o >= 0) offspring[o] = null;
	}

	//TODO Test the serialization code!
	
	public static void saveHerd(String filename)
	{
		if (singleton == null) return;
		try {
			FileOutputStream fileOut = new FileOutputStream(filename);
			ObjectOutputStream out = new ObjectOutputStream(fileOut);
			out.writeObject(singleton);
			out.close();
			fileOut.close();
		} catch (IOException i) {
			i.printStackTrace();
		}
	}

	public static void loadHerd(String filename)
	{
		singleton = null;
		try {
			FileInputStream fileIn = new FileInputStream(filename);
			ObjectInputStream in = new ObjectInputStream(fileIn);
			singleton = (Herd) in.readObject();
			in.close();
			fileIn.close();
		} catch (IOException i) {
			i.printStackTrace();
		} catch (ClassNotFoundException c) {
			c.printStackTrace();
		}
	}

	public static void resetHerd()
	{
		singleton = null;
	}
}