diff --git a/src/micropolisj/engine/Bulldozer.java b/src/micropolisj/engine/Bulldozer.java index 8f2fafc..83eb613 100644 --- a/src/micropolisj/engine/Bulldozer.java +++ b/src/micropolisj/engine/Bulldozer.java @@ -13,118 +13,125 @@ class Bulldozer extends ToolStroke @Override public ToolResult apply() { - ToolResult checkResult = check(); - if (checkResult != ToolResult.SUCCESS) { - return checkResult; - } - Rectangle b = getBounds(); - if (b.width == 1 && b.height == 1 && - isZoneCenter(city.getTile(b.x, b.y))) - { - return dozeZone(b.x, b.y); - } + ToolEffect eff = new ToolEffect(city, b.x, b.y); - int countDozed = 0; - for (int y = b.y; y < b.y+b.height; y++) { - for (int x = b.x; x < b.x+b.width; x++) { + // scan selection area for rubble, forest, etc... + for (int y = 0; y < b.height; y++) { + for (int x = 0; x < b.width; x++) { - char tile = city.getTile(x, y); - if (isDozeable(tile)) { - countDozed++; + int tile = eff.getTile(x, y); + if (isDozeable(tile) && !isZoneCenter(tile)) { - dozeField(x, y); - } - - } - } - return ToolResult.SUCCESS; - } - - @Override - public ToolResult check() - { - Rectangle b = getBounds(); - if (b.width == 1 && b.height == 1 && - isZoneCenter(city.getTile(b.x, b.y))) - { - int cost = 1; - return city.budget.totalFunds >= cost ? - ToolResult.SUCCESS : - ToolResult.INSUFFICIENT_FUNDS; - } - - int countDozed = 0; - for (int y = b.y; y < b.y+b.height; y++) { - for (int x = b.x; x < b.x+b.width; x++) { - - char tile = city.getTile(x, y); - if (isDozeable(tile)) { - countDozed++; + dozeField(new TranslatedToolEffect(eff, x, y)); } } } - int cost = 1 * countDozed; - return city.budget.totalFunds < cost ? ToolResult.INSUFFICIENT_FUNDS : - countDozed != 0 ? ToolResult.SUCCESS : - ToolResult.NONE; + // scan selection area for zones... + for (int y = 0; y < b.height; y++) { + for (int x = 0; x < b.width; x++) { + + if (isZoneCenter(eff.getTile(x,y))) { + dozeZone(new TranslatedToolEffect(eff, x, y)); + } + } + } + + return eff.apply(); } - ToolResult dozeZone(int xpos, int ypos) + void dozeZone(ToolEffectIfc eff) { - assert city.testBounds(xpos, ypos); - - char currTile = city.getTile(xpos, ypos); - char tmp = (char)(currTile & LOMASK); + int currTile = eff.getTile(0, 0); // zone center bit is set assert isZoneCenter(currTile); - city.spend(1); - switch (checkSize(tmp)) + eff.spend(1); + switch (checkSize(currTile)) { case 3: - city.makeSound(xpos, ypos, Sound.EXPLOSION_HIGH); - putRubble(xpos, ypos, 3, 3); + eff.makeSound(0, 0, Sound.EXPLOSION_HIGH); + putRubble(new TranslatedToolEffect(eff, -1, -1), 3, 3); break; case 4: - city.makeSound(xpos, ypos, Sound.EXPLOSION_LOW); - putRubble(xpos, ypos, 4, 4); + eff.makeSound(0, 0, Sound.EXPLOSION_LOW); + putRubble(new TranslatedToolEffect(eff, -1, -1), 4, 4); break; case 6: - city.makeSound(xpos, ypos, Sound.EXPLOSION_BOTH); - putRubble(xpos, ypos, 6, 6); + eff.makeSound(0, 0, Sound.EXPLOSION_BOTH); + putRubble(new TranslatedToolEffect(eff, -1, -1), 6, 6); break; default: assert false; break; } - return ToolResult.SUCCESS; + return; } - ToolResult dozeField(int xpos, int ypos) + void dozeField(ToolEffectIfc eff) { - char tile = city.getTile(xpos, ypos); + int tile = eff.getTile(0, 0); // check dozeable bit assert isDozeable(tile); tile = neutralizeRoad(tile); - if (isOverWater(tile)) + if (isOverWater((char)tile)) { // dozing over water, replace with water. - city.setTile(xpos, ypos, RIVER); + eff.setTile(0, 0, RIVER); } else { // dozing on land, replace with land. Simple, eh? - city.setTile(xpos, ypos, DIRT); + eff.setTile(0, 0, DIRT); } - city.spend(1); - return ToolResult.SUCCESS; + eff.spend(1); + return; } + void putRubble(ToolEffectIfc eff, int w, int h) + { + for (int yy = 0; yy < h; yy++) { + for (int xx = 0; xx < w; xx++) { + int tile = eff.getTile(xx,yy); + if (tile == CLEAR) + continue; + tile = tile & LOMASK; + if (tile != RADTILE && tile != DIRT) { + int nTile = (TINYEXP + city.PRNG.nextInt(3)) + | ANIMBIT | BULLBIT; + eff.setTile(xx, yy, nTile); + } + } + } + } + + int checkSize(int tile) + { + tile = tile & LOMASK; + if ((tile >= (RESBASE-1) && tile <= (PORTBASE-1)) || + (tile >= (LASTPOWERPLANT+1) && tile <= (POLICESTATION+4))) + { + return 3; + } + else if ((tile >= PORTBASE && tile <= LASTPORT) || + (tile >= COALBASE && tile <= LASTPOWERPLANT) || + (tile >= STADIUMBASE && tile <= LASTZONE)) + { + return 4; + } + else if (tile == TileConstants.AIRPORT) + { + return 6; + } + else + { + return 0; + } + } } diff --git a/src/micropolisj/engine/ToolEffect.java b/src/micropolisj/engine/ToolEffect.java index cb9a40f..fac7c18 100644 --- a/src/micropolisj/engine/ToolEffect.java +++ b/src/micropolisj/engine/ToolEffect.java @@ -33,6 +33,12 @@ class ToolEffect implements ToolEffectIfc } } + //implements ToolEffectIfc + public void makeSound(int dx, int dy, Sound sound) + { + preview.makeSound(dx, dy, sound); + } + //implements ToolEffectIfc public void setTile(int dx, int dy, int tileValue) { @@ -45,6 +51,12 @@ class ToolEffect implements ToolEffectIfc preview.spend(amount); } + //implements ToolEffectIfc + public void toolResult(ToolResult tr) + { + preview.toolResult(tr); + } + ToolResult apply() { if (originX - preview.offsetX < 0 || diff --git a/src/micropolisj/engine/ToolEffectIfc.java b/src/micropolisj/engine/ToolEffectIfc.java index 81ddc07..de55292 100644 --- a/src/micropolisj/engine/ToolEffectIfc.java +++ b/src/micropolisj/engine/ToolEffectIfc.java @@ -7,6 +7,8 @@ public interface ToolEffectIfc */ int getTile(int dx, int dy); + void makeSound(int dx, int dy, Sound sound); + /** * Sets the tile value at a relative location. */ @@ -16,4 +18,6 @@ public interface ToolEffectIfc * Deduct an amount from the controller's cash funds. */ void spend(int amount); + + void toolResult(ToolResult tr); } diff --git a/src/micropolisj/engine/ToolPreview.java b/src/micropolisj/engine/ToolPreview.java index e416fff..f2d7e19 100644 --- a/src/micropolisj/engine/ToolPreview.java +++ b/src/micropolisj/engine/ToolPreview.java @@ -1,6 +1,6 @@ package micropolisj.engine; -import java.util.Arrays; +import java.util.*; import static micropolisj.engine.TileConstants.*; public class ToolPreview implements ToolEffectIfc @@ -9,11 +9,28 @@ public class ToolPreview implements ToolEffectIfc public int offsetY; public short [][] tiles; public int cost; + public ToolResult toolResult; + public List sounds; + + public static class SoundInfo + { + public int dx; + public int dy; + public Sound sound; + + SoundInfo(int dx, int dy, Sound sound) + { + this.dx = dx; + this.dy = dy; + this.sound = sound; + } + } ToolPreview() { this.tiles = new short[1][1]; this.tiles[0][0] = CLEAR; + this.sounds = new ArrayList(); } //implements ToolEffectIfc @@ -84,6 +101,12 @@ public class ToolPreview implements ToolEffectIfc } } + //implements ToolEffectIfc + public void makeSound(int dx, int dy, Sound sound) + { + sounds.add(new SoundInfo(dx, dy, sound)); + } + //implements ToolEffectIfc public void setTile(int dx, int dy, int tileValue) { @@ -96,4 +119,10 @@ public class ToolPreview implements ToolEffectIfc { cost += amount; } + + //implements ToolEffectIfc + public void toolResult(ToolResult tr) + { + this.toolResult = tr; + } } diff --git a/src/micropolisj/engine/ToolStroke.java b/src/micropolisj/engine/ToolStroke.java index e6ab29d..893e45e 100644 --- a/src/micropolisj/engine/ToolStroke.java +++ b/src/micropolisj/engine/ToolStroke.java @@ -32,73 +32,36 @@ public class ToolStroke public ToolResult apply() { - ToolResult checkResult = check(); - if (checkResult != ToolResult.SUCCESS) { - return checkResult; - } + ToolResult tr = ToolResult.NONE; Rectangle r = getBounds(); - for (int i = r.y; i < r.y + r.height; i += tool.getHeight()) { - for (int j = r.x; j < r.x + r.width; - j += tool.getWidth()) { - apply1(j + (tool.getWidth() >= 3 ? 1 : 0), - i + (tool.getHeight() >= 3 ? 1 : 0) - ); - } - } - // TODO- actually check the result of application - return ToolResult.SUCCESS; - } + ToolEffect eff = new ToolEffect(city, r.x, r.y); - ToolResult checkZoneTool() - { - Rectangle b = getBounds(); - int cost = 0; - int numPlaced = 0; - - for (int i = b.y; i < b.y + b.height; i += tool.getHeight()) { - for (int j = b.x; j < b.x + b.width; j += tool.getWidth()) { - int x = j + (tool.getWidth() >= 3 ? 1 : 0); - int y = i + (tool.getHeight() >= 3 ? 1 : 0); - int c = costToPlaceZone(x, y); - - if (c != Integer.MAX_VALUE) { - numPlaced++; - cost += c; + for (int i = 0; i < r.height; i += tool.getHeight()) { + for (int j = 0; j < r.width; j += tool.getWidth()) { + ToolResult tmp = apply1( + new TranslatedToolEffect(eff, j, i) + ); + if (tmp == ToolResult.SUCCESS) { + tr = tmp; + } + else if (tr == ToolResult.NONE) { + tr = tmp; } } } - return numPlaced == 0 ? ToolResult.NONE : - cost <= city.budget.totalFunds ? ToolResult.SUCCESS : - ToolResult.INSUFFICIENT_FUNDS; - } - - /** - * @return SUCCESS if the operation will succeed, and at least - * one tile will be changed; - * INSUFFICIENT_FUNDS in case there's not enough money, - * and NONE is it is a null op. - */ - ToolResult check() - { - switch (tool) - { - // case RAIL: - // case ROADS: - // case WIRE: - // return checkRailRoadWireTool(); - // case PARK: - // return checkParkTool(); - default: - return checkZoneTool(); + ToolResult tmp = eff.apply(); + if (tmp != ToolResult.NONE) { + return tmp; + } + else { + return tr; } - } - ToolResult apply1(int xpos, int ypos) + ToolResult apply1(ToolEffectIfc eff) { - ToolEffect eff = new ToolEffect(city, xpos, ypos); ToolResult tr = ToolResult.SUCCESS; switch (tool) @@ -108,43 +71,43 @@ public class ToolStroke break; case RESIDENTIAL: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, RESBASE); + tr = applyZone(eff, 3, 3, RESBASE); break; case COMMERCIAL: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, COMBASE); + tr = applyZone(eff, 3, 3, COMBASE); break; case INDUSTRIAL: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, INDBASE); + tr = applyZone(eff, 3, 3, INDBASE); break; case FIRE: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, FIRESTBASE); + tr = applyZone(eff, 3, 3, FIRESTBASE); break; case POLICE: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, POLICESTBASE); + tr = applyZone(eff, 3, 3, POLICESTBASE); break; case POWERPLANT: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, COALBASE); + tr = applyZone(eff, 4, 4, COALBASE); break; case STADIUM: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, STADIUMBASE); + tr = applyZone(eff, 4, 4, STADIUMBASE); break; case SEAPORT: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, PORTBASE); + tr = applyZone(eff, 4, 4, PORTBASE); break; case NUCLEAR: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, NUCLEARBASE); + tr = applyZone(eff, 4, 4, NUCLEARBASE); break; case AIRPORT: - tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 6, 6, AIRPORTBASE); + tr = applyZone(eff, 6, 6, AIRPORTBASE); break; default: @@ -152,11 +115,7 @@ public class ToolStroke throw new Error("unexpected tool: "+tool); } - if (tr != ToolResult.SUCCESS) { - return tr; - } - - return eff.apply(); + return tr; } public void dragTo(int xdest, int ydest) @@ -196,38 +155,6 @@ public class ToolStroke return r; } - int costToPlaceZone(int xpos, int ypos) - { - final int width = tool.getWidth(); - final int height = tool.getHeight(); - - int cost = tool.getToolCost(); - boolean canBuild = true; - for (int rowNum = 0; rowNum < height; rowNum++) { - for (int colNum = 0; colNum < width; colNum++) { - int x = xpos - 1 + colNum; - int y = ypos - 1 + rowNum; - - char tileValue = (char) (city.getTile(x,y) & LOMASK); - if (tileValue != DIRT) - { - if (city.autoBulldoze) - { - if (canAutoBulldozeZ(tileValue)) - cost++; - else - canBuild = false; - } - else - canBuild = false; - } - } - } - - return canBuild ? cost : - Integer.MAX_VALUE; - } - ToolResult applyZone(ToolEffectIfc eff, int width, int height, char tileBase) { int cost = tool.getToolCost(); @@ -556,22 +483,6 @@ public class ToolStroke return; } - void putRubble(int xpos, int ypos, int w, int h) - { - for (int xx = xpos - 1; xx <= xpos + w-2; xx++) { - for (int yy = ypos - 1; yy <= ypos + h-2; yy++) { - if (city.testBounds(xx, yy)) { - int tile = city.getTile(xx,yy) & LOMASK; - if (tile != RADTILE && tile != DIRT) { - int nTile = (TINYEXP + city.PRNG.nextInt(3)) - | ANIMBIT | BULLBIT; - city.setTile(xx, yy, (char)nTile); - } - } - } - } - } - boolean isBigZone(int tile) { if (tile >= RESBASE && tile <= LASTZONE) @@ -583,27 +494,4 @@ public class ToolStroke else return false; } - - int checkSize(int tile) - { - if ((tile >= (RESBASE-1) && tile <= (PORTBASE-1)) || - (tile >= (LASTPOWERPLANT+1) && tile <= (POLICESTATION+4))) - { - return 3; - } - else if ((tile >= PORTBASE && tile <= LASTPORT) || - (tile >= COALBASE && tile <= LASTPOWERPLANT) || - (tile >= STADIUMBASE && tile <= LASTZONE)) - { - return 4; - } - else if (tile == TileConstants.AIRPORT) - { - return 6; - } - else - { - return 0; - } - } } diff --git a/src/micropolisj/engine/TranslatedToolEffect.java b/src/micropolisj/engine/TranslatedToolEffect.java index ca0039f..9a4feb5 100644 --- a/src/micropolisj/engine/TranslatedToolEffect.java +++ b/src/micropolisj/engine/TranslatedToolEffect.java @@ -19,6 +19,12 @@ class TranslatedToolEffect implements ToolEffectIfc return base.getTile(x+dx, y+dy); } + //implements ToolEffectIfc + public void makeSound(int x, int y, Sound sound) + { + base.makeSound(x+dx, y+dy, sound); + } + //implements ToolEffectIfc public void setTile(int x, int y, int tileValue) { @@ -30,4 +36,10 @@ class TranslatedToolEffect implements ToolEffectIfc { base.spend(amount); } + + //implements ToolEffectIfc + public void toolResult(ToolResult tr) + { + base.toolResult(tr); + } }