/* w_con.c * * Micropolis, Unix Version. This game was released for the Unix platform * in or about 1990 and has been modified for inclusion in the One Laptop * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If * you need assistance with this program, you may contact: * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. You should have received a * copy of the GNU General Public License along with this program. If * not, see . * * ADDITIONAL TERMS per GNU GPL Section 7 * * No trademark or publicity rights are granted. This license does NOT * give you any right, title or interest in the trademark SimCity or any * other Electronic Arts trademark. You may not distribute any * modification of this program using the trademark SimCity or claim any * affliation or association with Electronic Arts Inc. or its employees. * * Any propagation or conveyance of this program must include this * copyright notice and these terms. * * If you convey this program (or any modifications of it) and assume * contractual liability for the program to recipients of it, you agree * to indemnify Electronic Arts for any liability that those contractual * assumptions impose on Electronic Arts. * * You may not misrepresent the origins of this program; modified * versions of the program must be marked as such and not identified as * the original program. * * This disclaimer supplements the one included in the General Public * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES, * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING, * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY * NOT APPLY TO YOU. */ #include "sim.h" short _RoadTable[16] = { 66, 67, 66, 68, 67, 67, 69, 73, 66, 71, 66, 72, 70, 75, 74, 76 }; short _RailTable[16] = { 226, 227, 226, 228, 227, 227, 229, 233, 226, 231, 226, 232, 230, 235, 234, 236 }; short _WireTable[16] = { 210, 211, 210, 212, 211, 211, 213, 217, 210, 215, 210, 216, 214, 219, 218, 220 }; #define NeutralizeRoad(Tile) \ if (((Tile &= LOMASK) >= 64) && \ ((Tile & LOMASK) <= 207)) { \ Tile = (Tile & 0x000F) + 64; \ } /* comefrom: check3Border check4Border check5Border processWand */ int ConnecTile(short x, short y, short *TileAdrPtr, short Command) { short Tile; int result = 1; /* make sure the array subscripts are in bounds */ if (!TestBounds(x, y)) { return (0); } /* AutoDoze */ if ((Command >= 2) && (Command <= 4)) { if ((autoBulldoze != 0) && (TotalFunds > 0) && ((Tile = (*TileAdrPtr)) & BULLBIT)) { NeutralizeRoad(Tile); /* Maybe this should check BULLBIT instead of checking tile values? */ if (((Tile >= TINYEXP) && (Tile <= LASTTINYEXP)) || ((Tile < 64) && (Tile != 0))) { Spend(1); (*TileAdrPtr) = 0; } } } switch (Command) { case 0: /* Fix zone */ _FixZone(x, y, TileAdrPtr); break; case 1: /* Doze zone */ result = _LayDoze(x, y, TileAdrPtr); _FixZone(x, y, TileAdrPtr); break; case 2: /* Lay Road */ result = _LayRoad(x, y, TileAdrPtr); _FixZone(x, y, TileAdrPtr); break; case 3: /* Lay Rail */ result = _LayRail(x, y, TileAdrPtr); _FixZone(x, y, TileAdrPtr); break; case 4: /* Lay Wire */ result = _LayWire(x, y, TileAdrPtr); _FixZone(x, y, TileAdrPtr); break; } return result; } /* comefrom: ConnecTile */ int _LayDoze(int x, int y, short *TileAdrPtr) { short Tile; if (!(TotalFunds)) { return -2; /* no mas dinero. */ } Tile = (*TileAdrPtr); if (!(Tile & BULLBIT)) { return 0; /* Check dozeable bit. */ } NeutralizeRoad(Tile); switch (Tile) { 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: /* Dozing over water, replace with water. */ (*TileAdrPtr) = RIVER; break; default: /* Dozing on land, replace with land. Simple, eh? */ (*TileAdrPtr) = DIRT; break; } Spend(1); /* Costs $1.00....*/ return 1; } /* comefrom: ConnecTile */ int _LayRoad(int x, int y, short *TileAdrPtr) { short Tile; int cost = 10; if (TotalFunds < 10) { return -2; } Tile = (*TileAdrPtr) & LOMASK; switch (Tile) { case DIRT: (*TileAdrPtr) = ROADS | BULLBIT | BURNBIT; break; case RIVER: /* Road on Water */ case REDGE: case CHANNEL: /* Check how to build bridges, if possible. */ if (TotalFunds < 50) { return -2; } cost = 50; if (x < (WORLD_X - 1)) { Tile = TileAdrPtr[WORLD_Y]; NeutralizeRoad(Tile); if ((Tile == VRAILROAD) || (Tile == HBRIDGE) || ((Tile >= ROADS) && (Tile <= HROADPOWER))) { (*TileAdrPtr) = HBRIDGE | BULLBIT; break; } } if (x > 0) { Tile = TileAdrPtr[-WORLD_Y]; NeutralizeRoad(Tile); if ((Tile == VRAILROAD) || (Tile == HBRIDGE) || ((Tile >= ROADS) && (Tile <= INTERSECTION))) { (*TileAdrPtr) = HBRIDGE | BULLBIT; break; } } if (y < (WORLD_Y - 1)) { Tile = TileAdrPtr[1]; NeutralizeRoad(Tile); if ((Tile == HRAILROAD) || (Tile == VROADPOWER) || ((Tile >= VBRIDGE) && (Tile <= INTERSECTION))) { (*TileAdrPtr) = VBRIDGE | BULLBIT; break; } } if (y > 0) { Tile = TileAdrPtr[-1]; NeutralizeRoad(Tile); if ((Tile == HRAILROAD) || (Tile == VROADPOWER) || ((Tile >= VBRIDGE) && (Tile <= INTERSECTION))) { (*TileAdrPtr) = VBRIDGE | BULLBIT; break; } } /* Can't do road... */ return 0; case LHPOWER: /* Road on power */ (*TileAdrPtr) = VROADPOWER | CONDBIT | BURNBIT | BULLBIT; break; case LVPOWER: /* Road on power #2 */ (*TileAdrPtr) = HROADPOWER | CONDBIT | BURNBIT | BULLBIT; break; case LHRAIL: /* Road on rail */ (*TileAdrPtr) = HRAILROAD | BURNBIT | BULLBIT; break; case LVRAIL: /* Road on rail #2 */ (*TileAdrPtr) = VRAILROAD | BURNBIT | BULLBIT; break; default: /* Can't do road */ return 0; } Spend(cost); return 1; } /* comefrom: ConnecTile */ int _LayRail(int x, int y, short *TileAdrPtr) { short Tile; int cost = 20; if (TotalFunds < 20) { return -2; } Tile = (*TileAdrPtr) & LOMASK; NeutralizeRoad(Tile); switch (Tile) { case 0: /* Rail on Dirt */ (*TileAdrPtr) = 226 | BULLBIT | BURNBIT; break; case 2: /* Rail on Water */ case 3: case 4: /* Check how to build underwater tunnel, if possible. */ if (TotalFunds < 100) { return -2; } cost = 100; if (x < (WORLD_X - 1)) { Tile = TileAdrPtr[WORLD_Y]; NeutralizeRoad(Tile); if ((Tile == 221) || (Tile == 224) || ((Tile >= 226) && (Tile <= 237))) { (*TileAdrPtr) = 224 | BULLBIT; break; } } if (x > 0) { Tile = TileAdrPtr[-WORLD_Y]; NeutralizeRoad(Tile); if ((Tile == 221) || (Tile == 224) || ((Tile > 225) && (Tile < 238))) { (*TileAdrPtr) = 224 | BULLBIT; break; } } if (y < (WORLD_Y - 1)) { Tile = TileAdrPtr[1]; NeutralizeRoad(Tile); if ((Tile == 222) || (Tile == 238) || ((Tile > 224) && (Tile < 237))) { (*TileAdrPtr) = 225 | BULLBIT; break; } } if (y > 0) { Tile = TileAdrPtr[-1]; NeutralizeRoad(Tile); if ((Tile == 222) || (Tile == 238) || ((Tile > 224) && (Tile < 237))) { (*TileAdrPtr) = 225 | BULLBIT; break; } } /* Can't do rail... */ return 0; case 210: /* Rail on power */ (*TileAdrPtr) = 222 | CONDBIT | BURNBIT | BULLBIT; break; case 211: /* Rail on power #2 */ (*TileAdrPtr) = 221 | CONDBIT | BURNBIT | BULLBIT; break; case 66: /* Rail on road */ (*TileAdrPtr) = 238 | BURNBIT | BULLBIT; break; case 67: /* Rail on road #2 */ (*TileAdrPtr) = 237 | BURNBIT | BULLBIT; break; default: /* Can't do rail */ return 0; } Spend(cost); return 1; } /* comefrom: ConnecTile */ int _LayWire(int x, int y, short *TileAdrPtr) { short Tile; int cost = 5; if (TotalFunds < 5) { return -2; } Tile = (*TileAdrPtr) & LOMASK; NeutralizeRoad(Tile); switch (Tile) { case 0: /* Wire on Dirt */ (*TileAdrPtr) = 210 | CONDBIT | BURNBIT | BULLBIT; break; case 2: /* Wire on Water */ case 3: case 4: /* Check how to lay underwater wire, if possible. */ if (TotalFunds < 25) return -2; cost = 25; if (x < (WORLD_X - 1)) { Tile = TileAdrPtr[WORLD_Y]; if (Tile & CONDBIT) { NeutralizeRoad(Tile); if ((Tile != 77) && (Tile != 221) && (Tile != 208)) { (*TileAdrPtr) = 209 | CONDBIT | BULLBIT; break; } } } if (x > 0) { Tile = TileAdrPtr[-WORLD_Y]; if (Tile & CONDBIT) { NeutralizeRoad(Tile); if ((Tile != 77) && (Tile != 221) && (Tile != 208)) { (*TileAdrPtr) = 209 | CONDBIT | BULLBIT; break; } } } if (y < (WORLD_Y - 1)) { Tile = TileAdrPtr[1]; if (Tile & CONDBIT) { NeutralizeRoad(Tile); if ((Tile != 78) && (Tile != 222) && (Tile != 209)) { (*TileAdrPtr) = 208 | CONDBIT | BULLBIT; break; } } } if (y > 0) { Tile = TileAdrPtr[-1]; if (Tile & CONDBIT) { NeutralizeRoad(Tile); if ((Tile != 78) && (Tile != 222) && (Tile != 209)) { (*TileAdrPtr) = 208 | CONDBIT | BULLBIT; break; } } } /* Can't do wire... */ return 0; case 66: /* Wire on Road */ (*TileAdrPtr) = 77 | CONDBIT | BURNBIT | BULLBIT; break; case 67: /* Wire on Road #2 */ (*TileAdrPtr) = 78 | CONDBIT | BURNBIT | BULLBIT; break; case 226: /* Wire on rail */ (*TileAdrPtr) = 221 | CONDBIT | BURNBIT | BULLBIT; break; case 227: /* Wire on rail #2 */ (*TileAdrPtr) = 222 | CONDBIT | BURNBIT | BULLBIT; break; default: /* Can't do wire */ return 0; } Spend(cost); return 1; } /* comefrom: ConnecTile */ _FixZone(int x, int y, short *TileAdrPtr) { _FixSingle(x,y, &TileAdrPtr[0]); if (y > 0) { _FixSingle(x, y-1, &TileAdrPtr[-1]); } if (x < (WORLD_X - 1)) { _FixSingle(x+1, y, &TileAdrPtr[WORLD_Y]); } if (y < (WORLD_Y - 1)) { _FixSingle(x, y+1, &TileAdrPtr[1]); } if (x > 0) { _FixSingle(x-1, y, &TileAdrPtr[-WORLD_Y]); } } /* comefrom: _FixZone */ _FixSingle(int x, int y, short *TileAdrPtr) { short Tile; short adjTile = 0; Tile = (*TileAdrPtr) & LOMASK; NeutralizeRoad(Tile); if ((Tile >= 66) && (Tile <= 76)) { /* Cleanup Road */ if (y > 0) { Tile = TileAdrPtr[-1]; NeutralizeRoad(Tile); if (((Tile == 237) || ((Tile >= 64) && (Tile <= 78))) && (Tile != 77) && (Tile != 238) && (Tile != 64)) adjTile |= 0x0001; } if (x < (WORLD_X - 1)) { Tile = TileAdrPtr[WORLD_Y]; NeutralizeRoad(Tile); if (((Tile == 238) || ((Tile >= 64) && (Tile <= 78))) && (Tile != 78) && (Tile != 237) && (Tile != 65)) adjTile |= 0x0002; } if (y < (WORLD_Y - 1)) { Tile = TileAdrPtr[1]; NeutralizeRoad(Tile); if (((Tile == 237) || ((Tile >= 64) && (Tile <= 78))) && (Tile != 77) && (Tile != 238) && (Tile != 64)) adjTile |= 0x0004; } if (x > 0) { Tile = TileAdrPtr[-WORLD_Y]; NeutralizeRoad(Tile); if (((Tile == 238) || ((Tile >= 64) && (Tile <= 78))) && (Tile != 78) && (Tile != 237) && (Tile != 65)) adjTile |= 0x0008; } (*TileAdrPtr) = _RoadTable[adjTile] | BULLBIT | BURNBIT; return; } if ((Tile >= 226) && (Tile <= 236)) { /* Cleanup Rail */ if (y > 0) { Tile = TileAdrPtr[-1]; NeutralizeRoad(Tile); if ((Tile >= 221) && (Tile <= 238) && (Tile != 221) && (Tile != 237) && (Tile != 224)) adjTile |= 0x0001; } if (x < (WORLD_X - 1)) { Tile = TileAdrPtr[WORLD_Y]; NeutralizeRoad(Tile); if ((Tile >= 221) && (Tile <= 238) && (Tile != 222) && (Tile != 238) && (Tile != 225)) adjTile |= 0x0002; } if (y < (WORLD_Y - 1)) { Tile = TileAdrPtr[1]; NeutralizeRoad(Tile); if ((Tile >= 221) && (Tile <= 238) && (Tile != 221) && (Tile != 237) && (Tile != 224)) adjTile |= 0x0004; } if (x > 0) { Tile = TileAdrPtr[-WORLD_Y]; NeutralizeRoad(Tile); if ((Tile >= 221) && (Tile <= 238) && (Tile != 222) && (Tile != 238) && (Tile != 225)) adjTile |= 0x0008; } (*TileAdrPtr) = _RailTable[adjTile] | BULLBIT | BURNBIT; return; } if ((Tile >= 210) && (Tile <= 220)) { /* Cleanup Wire */ if (y > 0) { Tile = TileAdrPtr[-1]; if (Tile & CONDBIT) { NeutralizeRoad(Tile); if ((Tile != 209) && (Tile != 78) && (Tile != 222)) adjTile |= 0x0001; } } if (x < (WORLD_X - 1)) { Tile = TileAdrPtr[WORLD_Y]; if (Tile & CONDBIT) { NeutralizeRoad(Tile); if ((Tile != 208) && (Tile != 77) && (Tile != 221)) adjTile |= 0x0002; } } if (y < (WORLD_Y - 1)) { Tile = TileAdrPtr[1]; if (Tile & CONDBIT) { NeutralizeRoad(Tile); if ((Tile != 209) && (Tile != 78) && (Tile != 222)) adjTile |= 0x0004; } } if (x > 0) { Tile = TileAdrPtr[-WORLD_Y]; if (Tile & CONDBIT) { NeutralizeRoad(Tile); if ((Tile != 208) && (Tile != 77) && (Tile != 221)) adjTile |= 0x0008; } } (*TileAdrPtr) = _WireTable[adjTile] | BULLBIT | BURNBIT | CONDBIT; return; } }