public void infectCity(PopupPanel popupPanel, City city, boolean primaryInfection) {

		String infectionSummary = "<b>" + city.getName() + "</b> is infected and ";
		
		// Infections of this type of disease no longer happen if the cure is found and the disease eradicated
		int diseaseType = city.getGroup();
		if (d_cureFound[diseaseType] && d_diseaseCubesLeft[diseaseType] == MAX_DISEASE_CUBES) {
			return;
		}
		
		if (city.getInfectLevel() < 3) {
			
			city.incrementInfectionLevel();
			d_diseaseCubesLeft[diseaseType]--;
			infectionSummary += "its infection level has risen to " + city.getInfectLevel() + ".";
			popupPanel.appendBodyText(infectionSummary);
		}
		else {
			
			d_numOutbreaks++;
			if (primaryInfection) {
				s_currentOutbreakSeed++;
			}
			city.setLastOutbreakSeed(s_currentOutbreakSeed);
			ArrayList<City> neighbors = city.getNeighbors();
			ArrayList<City> toInfect = new ArrayList<City>();
			for (int i = 0; i < neighbors.size(); i++) {
				City neighbor = neighbors.get(i);
				if (neighbor.getLastOutbreakSeed() != s_currentOutbreakSeed) {

					if (toInfect.size() == 0) {
						infectionSummary += "there is an OUTBREAK! The infection overflows into <b>" + neighbor.getName() + "</b>";
					}
					else {
						infectionSummary += ", <b>" + neighbor.getName() + "</b>";
					}
					toInfect.add(neighbor);
				}
			}
			
			// If any neighbors were hit, output the infection message for this outbreak and THEN
			// recursively infect those cities; this is necessary to get the messages in the correct order
			if (toInfect.size() > 0) {
				popupPanel.appendBodyText(infectionSummary);
				while (toInfect.size() > 0) {
					infectCity(popupPanel, toInfect.remove(0), false);
				}
			}
			
		}
	}