// This file is part of MicropolisJ. // Copyright (C) 2013 Jason Long // Portions Copyright (C) 1989-2007 Electronic Arts Inc. // // MicropolisJ is free software; you can redistribute it and/or modify // it under the terms of the GNU GPLv3, with additional terms. // See the README file, included in this distribution, for details. package micropolisj.engine; import java.util.Arrays; /** * Contains symbolic names of certain tile values, * and helper functions to test tile attributes. * Attributes of tiles that are interesting: * */ public class TileConstants { // // terrain mapping // public static final short CLEAR = -1; public static final char DIRT = 0; public static final char RIVER = 2; public static final char REDGE = 3; public static final char CHANNEL = 4; public static final char FIRSTRIVEDGE = 5; public static final char LASTRIVEDGE = 20; public static final char TREEBASE = 21; public static final char WOODS_LOW = TREEBASE; public static final char WOODS = 37; public static final char UNUSED_TRASH2 = 39; public static final char WOODS_HIGH = UNUSED_TRASH2; public static final char WOODS2 = 40; public static final char WOODS5 = 43; public static final char RUBBLE = 44; public static final char LASTRUBBLE = 47; public static final char FLOOD = 48; public static final char LASTFLOOD = 51; public static final char RADTILE = 52; public static final char FIRE = 56; public static final char FIREBASE = 56; public static final char ROADBASE = 64; public static final char HBRIDGE = 64; public static final char VBRIDGE = 65; public static final char ROADS = 66; public static final char ROADS2 = 67; private static final char ROADS3 = 68; private static final char ROADS4 = 69; private static final char ROADS5 = 70; private static final char ROADS6 = 71; private static final char ROADS7 = 72; private static final char ROADS8 = 73; private static final char ROADS9 = 74; private static final char ROADS10 = 75; public static final char INTERSECTION = 76; public static final char HROADPOWER = 77; public static final char VROADPOWER = 78; public static final char BRWH = 79; //horz bridge, open public static final char LTRFBASE = 80; public static final char BRWV = 95; //vert bridge, open public static final char HTRFBASE = 144; private static final char LASTROAD = 206; public static final char POWERBASE = 208; public static final char HPOWER = 208; //underwater power-line public static final char VPOWER = 209; public static final char LHPOWER = 210; public static final char LVPOWER = 211; public static final char LVPOWER2 = 212; private static final char LVPOWER3 = 213; private static final char LVPOWER4 = 214; private static final char LVPOWER5 = 215; private static final char LVPOWER6 = 216; private static final char LVPOWER7 = 217; private static final char LVPOWER8 = 218; private static final char LVPOWER9 = 219; private static final char LVPOWER10 = 220; public static final char RAILHPOWERV = 221; public static final char RAILVPOWERH = 222; public static final char LASTPOWER = 222; public static final char RAILBASE = 224; public static final char HRAIL = 224; //underwater rail (horz) public static final char VRAIL = 225; //underwater rail (vert) public static final char LHRAIL = 226; public static final char LVRAIL = 227; public static final char LVRAIL2 = 228; private static final char LVRAIL3 = 229; private static final char LVRAIL4 = 230; private static final char LVRAIL5 = 231; private static final char LVRAIL6 = 232; private static final char LVRAIL7 = 233; private static final char LVRAIL8 = 234; private static final char LVRAIL9 = 235; private static final char LVRAIL10 = 236; public static final char HRAILROAD = 237; public static final char VRAILROAD = 238; public static final char LASTRAIL = 238; public static final char RESBASE = 240; public static final char FREEZ = 244; //free zone? public static final char HOUSE = 249; public static final char LHTHR = 249; //12 house tiles public static final char HHTHR = 260; public static final char RZB = 265; //residential zone base public static final char HOSPITAL = 409; public static final char CHURCH = 418; public static final char COMBASE = 423; public static final char COMCLR = 427; public static final char CZB = 436; //commercial zone base private static final char COMLAST = 609; public static final char INDBASE = 612; public static final char INDCLR = 616; private static final char LASTIND = 620; private static final char IND1 = 621; public static final char IZB = 625; public static final char PORTBASE = 693; public static final char PORT = 698; private static final char LASTPORT = 708; public static final char AIRPORTBASE = 709; public static final char AIRPORT = 716; public static final char COALBASE = 745; public static final char POWERPLANT = 750; private static final char LASTPOWERPLANT = 760; public static final char FIRESTBASE = 761; public static final char FIRESTATION = 765; public static final char POLICESTBASE = 770; public static final char POLICESTATION = 774; public static final char STADIUMBASE = 779; public static final char STADIUM = 784; public static final char FULLSTADIUM = 800; public static final char NUCLEARBASE = 811; public static final char NUCLEAR = 816; public static final char LASTZONE = 826; public static final char LIGHTNINGBOLT = 827; public static final char HBRDG0 = 828; //draw bridge tiles (horz) public static final char HBRDG1 = 829; public static final char HBRDG2 = 830; public static final char HBRDG3 = 831; private static final char RADAR_ANIM = 832; public static final char FOUNTAIN = 840; private static final char INDBASE2 = 844; private static final char SMOKEBASE = 852; public static final char TINYEXP = 860; private static final char SOMETINYEXP = 864; private static final char LASTTINYEXP = 867; private static final char SMOKEBASE2 = 884; public static final char FOOTBALLGAME1 = 932; public static final char FOOTBALLGAME2 = 940; public static final char VBRDG0 = 948; //draw bridge tiles (vert) public static final char VBRDG1 = 949; public static final char VBRDG2 = 950; public static final char VBRDG3 = 951; private static final char URANIUM_FUEL = 952; public static final char LAST_TILE = 956; static final char [] RoadTable = new char[] { ROADS, ROADS2, ROADS, ROADS3, ROADS2, ROADS2, ROADS4, ROADS8, ROADS, ROADS6, ROADS, ROADS7, ROADS5, ROADS10, ROADS9, INTERSECTION }; static final char [] RailTable = new char[] { LHRAIL, LVRAIL, LHRAIL, LVRAIL2, LVRAIL, LVRAIL, LVRAIL3, LVRAIL7, LHRAIL, LVRAIL5, LHRAIL, LVRAIL6, LVRAIL4, LVRAIL9, LVRAIL8, LVRAIL10 }; static final char [] WireTable = new char[] { LHPOWER, LVPOWER, LHPOWER, LVPOWER2, LVPOWER, LVPOWER, LVPOWER3, LVPOWER7, LHPOWER, LVPOWER5, LHPOWER, LVPOWER6, LVPOWER4, LVPOWER9, LVPOWER8, LVPOWER10 }; // // status bits // public static final char PWRBIT = 32768; // bit 15 ... currently powered // bit 14 ... unused // bit 13 ... unused public static final char BULLBIT = 4096; // bit 12 ... is bulldozable // bit 11 ... unused // bit 10 ... unused public static final char ALLBITS = 64512; // mask for upper 6 bits public static final char LOMASK = 1023; //mask for low 10 bits private TileConstants() {} /** * Checks whether the tile can be auto-bulldozed for * placement of road, rail, or wire. */ public static boolean canAutoBulldozeRRW(int tileValue) { // can we autobulldoze this tile? return ( (tileValue >= FIRSTRIVEDGE && tileValue <= LASTRUBBLE) || (tileValue >= TINYEXP && tileValue <= LASTTINYEXP) ); } /** * Checks whether the tile can be auto-bulldozed for * placement of a zone. */ public static boolean canAutoBulldozeZ(char tileValue) { //FIXME- what is significance of POWERBASE+2 and POWERBASE+12 ? // can we autobulldoze this tile? if ((tileValue >= FIRSTRIVEDGE && tileValue <= LASTRUBBLE) || (tileValue >= POWERBASE + 2 && tileValue <= POWERBASE + 12) || (tileValue >= TINYEXP && tileValue <= LASTTINYEXP)) { return true; } else { return false; } } //used by scanTile public static String getTileBehavior(int tile) { tile &= LOMASK; TileSpec ts = Tiles.get(tile); return ts != null ? ts.getAttribute("behavior") : null; } //used by queryZoneStatus public static int getDescriptionNumber(int tile) { tile &= LOMASK; TileSpec ts = Tiles.get(tile); if (ts != null) { return ts.getDescriptionNumber(); } else { return -1; } } public static int getPollutionValue(int tile) { TileSpec spec = Tiles.get(tile & LOMASK); return spec != null ? spec.getPollutionValue() : 0; } public static boolean isAnimated(int tile) { TileSpec spec = Tiles.get(tile & LOMASK); return spec != null && spec.animNext != null; } //used by setFire() public static boolean isArsonable(int tile) { return ( !isZoneCenter(tile) && (tile & LOMASK) >= LHTHR && (tile & LOMASK) <= LASTZONE ); } //used by Sprite::destroyTile public static boolean isBridge(int tile) { return isRoad(tile) && !isCombustible(tile); } public static boolean isCombustible(int tile) { TileSpec spec = Tiles.get(tile & LOMASK); return spec != null && spec.canBurn; } public static boolean isConductive(int tile) { TileSpec spec = Tiles.get(tile & LOMASK); return spec != null && spec.canConduct; } public static boolean isFire(int tile) { int tmp = tile & LOMASK; return (tmp >= FIREBASE && tmp < ROADBASE); } /** Used in repairZone(). */ public static boolean isIndestructible(int tile) { int tmp = tile & LOMASK; return tmp >= RUBBLE && tmp < ROADBASE; } /** Used in zonePlop(). */ public static boolean isIndestructible2(int tile) { int tmp = tile & LOMASK; return tmp >= FLOOD && tmp < ROADBASE; } public static boolean isRadioactive(int tile) { int tmp = tile & LOMASK; return (tmp >= RADTILE && tmp < FIREBASE); } public static boolean isOverWater(int tile) { // Note: BRWV will be converted to BRWH by the following // function. int tmp = neutralizeRoad(tile & LOMASK); switch (tmp) { case HBRIDGE: case VBRIDGE: case BRWV: case BRWH: case HBRDG0: case HBRDG1: case HBRDG2: case HBRDG3: case VBRDG0: case VBRDG1: case VBRDG2: case VBRDG3: case HPOWER: case VPOWER: case HRAIL: case VRAIL: return true; default: return false; } } public static boolean isRubble(int cell) { return (((cell & LOMASK) >= RUBBLE) && ((cell & LOMASK) <= LASTRUBBLE)); } public static boolean isTree(char cell) { return (((cell & LOMASK) >= WOODS_LOW) && ((cell & LOMASK) <= WOODS_HIGH)); } //used by makeEarthquake public static boolean isVulnerable(int tile) { int tem2 = tile & LOMASK; if (tem2 < RESBASE || tem2 > LASTZONE || isZoneCenter(tile) ) { return false; } else { return true; } } public static boolean checkWet(int tile) { int x = tile & LOMASK; return (x == POWERBASE || x == POWERBASE+1 || x == RAILBASE || x == RAILBASE + 1 || x == BRWH || x == BRWV); } public static int getZoneSizeFor(int tile) { int ch = tile & LOMASK; if (ch >= RESBASE && ch < PORTBASE) { return 3; } else if (ch >= PORTBASE && ch <= LASTPORT) { return 4; } else if (ch >= AIRPORTBASE && ch < COALBASE) { return 6; } else if (ch >= COALBASE && ch <= LASTPOWERPLANT) { return 4; } else if (ch >= FIRESTBASE && ch < STADIUMBASE) { return 3; } else if (ch >= STADIUMBASE && ch <= LASTZONE) { return 4; } else { return 0; } } public static boolean isConstructed(int tile) { return tile >= 0 && (tile & LOMASK) >= ROADBASE; } static boolean isRiverEdge(int tile) { return (tile & LOMASK) > 4 && (tile & LOMASK) < 21; } public static boolean isDozeable(int tile) { return tile >= 0 && (tile & BULLBIT) != 0; } static boolean isFloodable(int tile) { return (tile == DIRT || ((tile & BULLBIT) != 0 && isCombustible(tile))); } /** * Note: does not include rail/road tiles. * @see #isRoadAny */ public static boolean isRoad(int tile) { int tmp = tile & LOMASK; return (tmp >= ROADBASE && tmp < POWERBASE); } public static boolean isRoadAny(int tile) { int tmp = tile & LOMASK; return (tmp >= ROADBASE && tmp < POWERBASE) || (tmp == HRAILROAD) || (tmp == VRAILROAD); } /** * Checks whether the tile is a road that will automatically change to connect to * neighboring roads. */ public static boolean isRoadDynamic(int tile) { int tmp = neutralizeRoad(tile); return (tmp >= ROADS && tmp <= INTERSECTION); } public static boolean roadConnectsEast(int tile) { tile = neutralizeRoad(tile); return (((tile == VRAILROAD) || (tile >= ROADBASE && tile <= VROADPOWER) ) && (tile != VROADPOWER) && (tile != HRAILROAD) && (tile != VBRIDGE)); } public static boolean roadConnectsNorth(int tile) { tile = neutralizeRoad(tile); return (((tile == HRAILROAD) || (tile >= ROADBASE && tile <= VROADPOWER) ) && (tile != HROADPOWER) && (tile != VRAILROAD) && (tile != ROADBASE)); } public static boolean roadConnectsSouth(int tile) { tile = neutralizeRoad(tile); return (((tile == HRAILROAD) || (tile >= ROADBASE && tile <= VROADPOWER) ) && (tile != HROADPOWER) && (tile != VRAILROAD) && (tile != ROADBASE)); } public static boolean roadConnectsWest(int tile) { tile = neutralizeRoad(tile); return (((tile == VRAILROAD) || (tile >= ROADBASE && tile <= VROADPOWER) ) && (tile != VROADPOWER) && (tile != HRAILROAD) && (tile != VBRIDGE)); } public static boolean isRail(int tile) { int tmp = tile & LOMASK; return (tmp >= RAILBASE && tmp < RESBASE); } public static boolean isRailAny(int tile) { int tmp = tile & LOMASK; return (tmp >= RAILBASE && tmp < RESBASE) || (tmp == RAILHPOWERV) || (tmp == RAILVPOWERH); } public static boolean isRailDynamic(int tile) { int tmp = tile & LOMASK; return (tmp >= LHRAIL && tmp <= LVRAIL10); } public static boolean railConnectsEast(int tile) { tile = neutralizeRoad(tile); return (tile >= RAILHPOWERV && tile <= VRAILROAD && tile != RAILVPOWERH && tile != VRAILROAD && tile != VRAIL); } public static boolean railConnectsNorth(int tile) { tile = neutralizeRoad(tile); return (tile >= RAILHPOWERV && tile <= VRAILROAD && tile != RAILHPOWERV && tile != HRAILROAD && tile != HRAIL); } public static boolean railConnectsSouth(int tile) { tile = neutralizeRoad(tile); return (tile >= RAILHPOWERV && tile <= VRAILROAD && tile != RAILHPOWERV && tile != HRAILROAD && tile != HRAIL); } public static boolean railConnectsWest(int tile) { tile = neutralizeRoad(tile); return (tile >= RAILHPOWERV && tile <= VRAILROAD && tile != RAILVPOWERH && tile != VRAILROAD && tile != VRAIL); } public static boolean isWireDynamic(int tile) { int tmp = tile & LOMASK; return (tmp >= LHPOWER && tmp <= LVPOWER10); } public static boolean wireConnectsEast(int tile) { int ntile = neutralizeRoad(tile); return (isConductive(tile) && ntile != HPOWER && ntile != HROADPOWER && ntile != RAILHPOWERV); } public static boolean wireConnectsNorth(int tile) { int ntile = neutralizeRoad(tile); return (isConductive(tile) && ntile != VPOWER && ntile != VROADPOWER && ntile != RAILVPOWERH); } public static boolean wireConnectsSouth(int tile) { int ntile = neutralizeRoad(tile); return (isConductive(tile) && ntile != VPOWER && ntile != VROADPOWER && ntile != RAILVPOWERH); } public static boolean wireConnectsWest(int tile) { int ntile = neutralizeRoad(tile); return (isConductive(tile) && ntile != HPOWER && ntile != HROADPOWER && ntile != RAILHPOWERV); } public static boolean isCommercialZone(int tile) { int tmp = tile & LOMASK; TileSpec ts = Tiles.get(tmp); if (ts != null) { if (ts.owner != null) { ts = ts.owner; } return ts.getBooleanAttribute("commercial-zone"); } return false; } public static boolean isHospitalOrChurch(int tile) { return (tile & LOMASK) >= HOSPITAL && (tile & LOMASK) < COMBASE; } /** * Checks whether the tile is defined with the "industrial-zone" attribute. * Note: the old version of this function erroneously included the coal power * plant smoke as an industrial zone. */ public static boolean isIndustrialZone(int tile) { int tmp = tile & LOMASK; TileSpec ts = Tiles.get(tmp); if (ts != null) { if (ts.owner != null) { ts = ts.owner; } return ts.getBooleanAttribute("industrial-zone"); } return false; } public static boolean isResidentialClear(int tile) { return (tile & LOMASK) >= RESBASE && (tile & LOMASK) <= RESBASE+8; } /** Note: does not include hospital/church. * @see #isHospitalOrChurch */ public static boolean isResidentialZone(int tile) { return (tile & LOMASK) >= RESBASE && (tile & LOMASK) < HOSPITAL; } // includes hospital/church. public static boolean isResidentialZoneAny(int tile) { int tmp = tile & LOMASK; TileSpec ts = Tiles.get(tmp); if (ts != null) { if (ts.owner != null) { ts = ts.owner; } return ts.getBooleanAttribute("residential-zone"); } return false; } public static boolean isSpecialZone(int tile) { assert isZoneCenter(tile); return (tile & LOMASK) >= PORTBASE; } /** Tile represents a part of any sort of building. */ public static boolean isZoneAny(int tile) { return (tile & LOMASK) >= RESBASE; } public static boolean isZoneCenter(int tile) { TileSpec spec = Tiles.get(tile & LOMASK); return spec != null && spec.zone; } /** * Converts a road tile value with traffic to the equivalent * road tile without traffic. */ public static char neutralizeRoad(int tile) { tile &= LOMASK; if (tile >= ROADBASE && tile <= LASTROAD) { tile = ((tile - ROADBASE) & 0xf) + ROADBASE; } return (char)tile; } /** * Determine the population level of a Residential zone * tile. Note: the input tile MUST be a full-size res zone, * it cannot be an empty zone. * @return int multiple of 8 between 16 and 40. */ public static int residentialZonePop(int tile) { TileSpec ts = Tiles.get(tile & LOMASK); return ts.getPopulation(); } /** * Determine the population level of a Commercial zone * tile. * The input tile MAY be an empty zone. * @return int between 0 and 5. */ public static int commercialZonePop(int tile) { TileSpec ts = Tiles.get(tile & LOMASK); return ts.getPopulation() / 8; } /** * Determine the population level of an Industrial zone tile. * The input tile MAY be an empty zone. * @return int between 0 and 4. */ public static int industrialZonePop(int tile) { TileSpec ts = Tiles.get(tile & LOMASK); return ts.getPopulation() / 8; } }