/* * Copyright (c) 2012 Felix Mo. All rights reserved. * * CitySim is published under the terms of the MIT License. See the LICENSE file for more information. * */ import greenfoot.*; import java.awt.Dimension; import java.util.ArrayList; import java.util.HashMap; import java.util.Arrays; import java.util.Collections; import java.awt.Point; /** * Write a description of class ResidentialZone here. * * @author (your name) * @version (a version number or a date) */ public class ResidentialZone extends Zone { public static final int TYPE_ID = 1; public static final int SIZE_WIDTH = 3; public static final int SIZE_HEIGHT = 3; public static final String NAME = "Residential"; public static final int PRICE = 100; // STAGES (10 stages, incl. initial stage) public static int[][] stages = new int[10][]; public static final int[] STAGE_INITIALTILE = { 241, 241, 241, 241, 241, 241, 262, 271, 388, 397 }; public static final int[] STAGE_MAXCAPACITY = { 0, 4, 8, 32, 48, 64, 512, 1024, 4096, 5120 }; static { for (int stage = 0; stage < STAGE_INITIALTILE.length; stage++) { // Initialize stage stages[stage] = new int[SIZE_WIDTH * SIZE_HEIGHT]; int tile = STAGE_INITIALTILE[stage]; for (int e = 0; e < SIZE_WIDTH * SIZE_HEIGHT; e++) { stages[stage][e] = tile; tile++; } if (stage < 6) { int y = 250; for (int x = 0; x < stage; x++) { stages[stage][x] = y; y++; } } } } public ResidentialZone(HashMap properties) { super(properties); } public void simulate() { // Do not simulate if no roads connect to zone if (Data.tilesAroundZoneWithCriteria(this, "road > 0").length == 0) { // this.setScore(0); return; } int score = 0; // Start with a score based upon the scores of nearby zones // Zone[] area = Data.zonesInAreaOfZone(this, 5, ResidentialZone.TYPE_ID, IndustrialZone.TYPE_ID, CommercialZone.TYPE_ID); // if (area.length > 0) { // int sSum = 0; // for (Zone z : area) { // sSum += z.score(); // } // int avg = (int)(sSum / area.length); // avg // } Zone[] police = Data.sortedZonesInAreaOfZone(this, 15, PoliceStation.TYPE_ID); // Check for police protection if (police.length > 0) { score += 15; } // else { // score -= 10; // } // Check for fire protection if (Data.zonesInAreaOfZone(this, 15, FireStation.TYPE_ID).length > 0) { score += 15; } // else { // score -= 10; // } // Check for nearby recreational areas Tile[] recTiles = Data.tilesInRadiusOfZoneMatchingCriteria(this, 10, "recreation = 1"); if (recTiles.length > 0) { score += 20; } Zone[] iZones = Data.zonesInAreaOfZone(this, 15, IndustrialZone.TYPE_ID); Zone[] cZones = Data.zonesInAreaOfZone(this, 10, CommercialZone.TYPE_ID); // Food if (cZones.length > 0) { this.setFood(1); score += 20; } else { score -= 10; } int deaths = 0; // Calculate pollution levels based on surroundings // 0 = NONE // 1-30 = LOW // 31-50 = MEDIUM // 51+ = HIGH // 100 = MAX int pollution = 0; pollution += Data.tilesInRadiusOfZoneMatchingCriteria(this, 10, "road > 0").length * 2; // Roads (+2 / road) pollution += iZones.length * 10; // Industrial zones (+10 / zone) pollution += Data.zonesInAreaOfZone(this, 15, CoalPowerPlant.TYPE_ID).length * 25; pollution += Data.zonesInAreaOfZone(this, 10, NuclearPowerPlant.TYPE_ID).length * 15; pollution = Math.min(100, pollution); this.setPollution(pollution); score -= (int)(pollution); if (this.allocation() > 0) { // Calculate crime levels // < 6 - LOW // 6 - 12 - MEDIUM // > 12 - HIGH int dP = 0; if (police.length > 0) { Point closetPolice = police[0].origin(); Point dToPolice = new Point(Math.abs(closetPolice.x - this.origin().x), Math.abs(closetPolice.y - this.origin().y)); dP = (dToPolice.x + dToPolice.y) / 2; } int crime = (int)(((this.allocation() / this.capacity()) * 100) / (dP == 0 ? 2 : (20 - dP))); setCrime(crime); if (crime < 6) { score += 20; } else if (crime >= 6 & crime <= 12) { score -= 5; } else { score -= 10; } // Crime-related deaths int crimeDeathsModifier = (crime > 12 ? 3 : (crime >= 6 ? 5 : (crime < 6 ? 7 : 0))); int crimeDeaths = 0; if (crimeDeathsModifier > 0) { crimeDeaths = Greenfoot.getRandomNumber(Math.max(1, (int)(this.allocation()/crimeDeathsModifier)))+1; } // if (crimeDeaths > 0) score -= 25; deaths += crimeDeaths; // Pollution deaths int pollutionDeathsModifier = (pollution > 50 ? 2 : (pollution >= 31 ? 3 : (pollution >= 1 ? 4 : 0))); // Determines the modifer based on pollution levels int pollutionDeaths = 0; if (pollutionDeathsModifier > 0) { pollutionDeaths = Greenfoot.getRandomNumber(Math.max(1, (int)(this.allocation()/pollutionDeathsModifier)))+1; // Determine the number of pollution based deaths } // if (pollutionDeaths > 0) score -= 25; deaths += pollutionDeaths; // Natural deaths int naturalDeaths = 0; if (this.allocation() - deaths > 0) { naturalDeaths = Greenfoot.getRandomNumber(Math.max(1, (int)(this.allocation()-deaths)/4))+1; } deaths += naturalDeaths; // Poverty deaths int povertyDeaths = 0; if (this.food() == 0 && this.allocation() - deaths > 0) { povertyDeaths = Greenfoot.getRandomNumber(Math.max(1, (int)(this.allocation()-deaths/2)))+1; } deaths += povertyDeaths; this.setAllocation(this.allocation() - Math.min(deaths, this.allocation()-1)); } // Births int births = 0; if (this.allocation() != this.capacity() && this.powered() && this.food() == 1 && this.pollution() < 100) { if (this.allocation() == 0) { births = Greenfoot.getRandomNumber((int)(this.capacity()/2))+1; } else { births = Greenfoot.getRandomNumber((this.capacity() - this.allocation()))+1; } } if (births > 0) score += 25; this.setAllocation(this.allocation() + births); if (this.powered()) { score += 25; } else { score -= 25; } int density = 0; if (this.allocation() > 0 && this.capacity() > 0) { density = (int)((this.allocation() / this.capacity()) * 100); } if (this.score() > 0 && this.powered()) { if (((((score / this.score()) * 100)-100) >= 50 && this.stage() < ResidentialZone.STAGE_MAXCAPACITY.length) || this.stage() == 0 || (this.stage() < ResidentialZone.STAGE_MAXCAPACITY.length && (score >= 80 && density >= 85))) { if (!(this.allocation() == 0 && this.stage() == 1) && (this.stage() == 0 || density >= 70)) { // Do not increment stage if the zone is unused and is at the first stage this.setCapacity(Math.max((Greenfoot.getRandomNumber(ResidentialZone.STAGE_MAXCAPACITY[Math.max(1, this.stage()-1)])+1), (int)(ResidentialZone.STAGE_MAXCAPACITY[Math.max(1, this.stage()-1)]/2)) + ResidentialZone.STAGE_MAXCAPACITY[Math.max(1, this.stage()-1)]); this.incrementStage(); } } } this.setScore(score); new ZoneDBUpdateThread(this).start(); } public static void zoneTiles(ArrayList<ArrayList<Tile>> selectedTiles) { Cash.subtract(PRICE); int width = selectedTiles.size(); int height = ((ArrayList)selectedTiles.get(0)).size(); addToCount(width*height); int k = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { Tile tile = selectedTiles.get(j).get(i); tile.setType(ResidentialZone.stages[0][k]); k++; } } CSLogger.sharedLogger().info("Zoning " + (width*height) + " tiles for residential use..."); updateTiles(selectedTiles); } public static int count() { return ((Integer)Data.zoneStats().get(Data.ZONESTATS_RESIDENTIALCOUNT)).intValue(); } public static void addToCount(int more) { HashMap zoneStats = Data.zoneStats(); zoneStats.put(Data.ZONESTATS_RESIDENTIALCOUNT, new Integer(count()+more)); Data.updateZoneStats(zoneStats); } public static void subtractFromCount(int less) { HashMap zoneStats = Data.zoneStats(); zoneStats.put(Data.ZONESTATS_RESIDENTIALCOUNT, new Integer(count()-less)); Data.updateZoneStats(zoneStats); } }