/* * 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.awt.Point; /** * Write a description of class CommercialZone here. * * @author (your name) * @version (a version number or a date) */ public class CommercialZone extends Zone { public static final int TYPE_ID = 2; public static final int SIZE_WIDTH = 3; public static final int SIZE_HEIGHT = 3; public static final String NAME = "Commercial"; public static final int PRICE = 100; // STAGES public static int[][] stages = new int[14][]; public static final int[] STAGE_INITIALTILE = { 424, 568, 478, 532, 577, 451, 460, 496, 514, 550, 541, 559, 586, 604 }; public static final int[] STAGE_MAXCAPACITY = { 0, 16, 32, 128, 256, 512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192 }; 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++; } } } public CommercialZone(HashMap properties) { super(properties); } public void simulate() { // Set zone score to 0 and 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); // // if (avg > 0) { // score = (int)(avg/2); // // } // } // Check for police protection Zone[] police = Data.sortedZonesInAreaOfZone(this, 15, PoliceStation.TYPE_ID); if (police.length > 0) { score += 15; } else { score -= 5; } // Check for fire protection if (Data.zonesInAreaOfZone(this, 15, FireStation.TYPE_ID).length > 0) { score += 15; } else { score -= 5; } // Check for nearby recreational areas if (Data.tilesInRadiusOfZoneMatchingCriteria(this, 10, "recreation = 1").length > 0) { score += 20; } // Accessiblity to consumers score += Math.max(50, Data.zonesInAreaOfZone(this, 15, ResidentialZone.TYPE_ID).length * 5); // Accessibility to suppliers Zone[] iZones = Data.zonesInAreaOfZone(this, 15, IndustrialZone.TYPE_ID); score += Math.max(50, iZones.length * 5); // Calculate pollution levels based on surroundings // 0 = NONE // 1-20 = LOW // 21-40 = MEDIUM // 41+ = HIGH 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 : Math.max(1, (20 - dP)))); setCrime(crime); if (crime < 6) { score += 25; } else if (crime >= 6 & crime <= 12) { score -= 5; } else { score -= 10; } } int density = 0; if (this.allocation() > 0 && this.capacity() > 0) { density = (int)((this.allocation() / this.capacity()) * 100); } if (this.score() > 0 && this.powered()) { // Increment stage IF: // 1. score has improved by 50% // 2. zone is at stage 0 // 3. score is 65/100 & density is >= 90% if (((((score / this.score()) * 100)-100) >= 50 && this.stage() < CommercialZone.STAGE_MAXCAPACITY.length) || this.stage() == 0 || (this.stage() < CommercialZone.STAGE_MAXCAPACITY.length && (score >= 70 && density >= 80))) { if (!(this.allocation() == 0 && this.stage() == 1) && (this.stage() == 0 || density >= 70)) { this.setCapacity(Math.max((Greenfoot.getRandomNumber(CommercialZone.STAGE_MAXCAPACITY[Math.max(1, this.stage()-1)])+1), (int)(CommercialZone.STAGE_MAXCAPACITY[Math.max(1, this.stage()-1)]/2)) + CommercialZone.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(CommercialZone.stages[0][k]); k++; } } CSLogger.sharedLogger().info("Zoning " + (width*height) + " tiles for commercial use..."); updateTiles(selectedTiles); } public static int count() { return ((Integer)Data.zoneStats().get(Data.ZONESTATS_COMMERCIALCOUNT)).intValue(); } public static void addToCount(int more) { HashMap zoneStats = Data.zoneStats(); zoneStats.put(Data.ZONESTATS_COMMERCIALCOUNT, new Integer(count()+more)); Data.updateZoneStats(zoneStats); } public static void subtractFromCount(int less) { HashMap zoneStats = Data.zoneStats(); zoneStats.put(Data.ZONESTATS_COMMERCIALCOUNT, new Integer(count()-less)); Data.updateZoneStats(zoneStats); } }