Main Page   Data Structures   File List   Data Fields   Globals   Related Pages  

source/build.c

Go to the documentation of this file.
00001 
00009 #include <config.h>
00010 
00011 #ifdef PALM
00012 #include <PalmOS.h>
00013 #include <simcity.h>
00014 #else
00015 #include <sys/types.h>
00016 #include <stddef.h>
00017 #include <assert.h>
00018 #endif
00019 #include <zakdef.h>
00020 #include <compilerpragmas.h>
00021 #include <build.h>
00022 #include <globals.h>
00023 #include <ui.h>
00024 #include <logging.h>
00025 #include <locking.h>
00026 #include <drawing.h>
00027 #include <simulation.h>
00028 #include <sections.h>
00029 
00031 typedef int (*BuildF)(UInt16 xpos, UInt16 ypos, welem_t type);
00032 
00033 static int Build_Road(UInt16 xpos, UInt16 ypos, welem_t type) BUILD_SECTION;
00034 static int Build_Rail(UInt16 xpos, UInt16 ypos, welem_t type) BUILD_SECTION;
00035 static int Build_PowerLine(UInt16 xpos, UInt16 ypos, welem_t type) BUILD_SECTION;
00036 static int Build_WaterPipe(UInt16 xpos, UInt16 ypos, welem_t type) BUILD_SECTION;
00037 static int Build_Generic(UInt16 xpos, UInt16 ypos, welem_t type) BUILD_SECTION;
00038 static int Build_Generic4(UInt16 xpos, UInt16 ypos, welem_t type) BUILD_SECTION;
00039 static int Build_Defence(UInt16 xpos, UInt16 ypos, welem_t type) BUILD_SECTION;
00040 
00041 static void CreateForest(UInt32 pos, UInt16 size) BUILD_SECTION;
00042 static void RemoveDefence(UInt16 xpos, UInt16 ypos) BUILD_SECTION;
00043 static int CantBulldoze(welem_t type) BUILD_SECTION;
00044 static UInt16 blockSize(welem_t type) BUILD_SECTION;
00045 static void Doff(welem_t base, welem_t node, UInt16 *x, UInt16 *y) BUILD_SECTION;
00046 static Int16 IsBulldozable(welem_t zone) BUILD_SECTION;
00047 
00048 static Int16 SpendMoney(UInt32 howMuch);
00049 
00057 static const struct _bldStruct {
00058         BuildCode bt;   
00059         BuildF func;    
00060         welem_t type;   
00061         UInt8 gridsToUpdate; 
00063 } buildStructure[] = {
00064         { Be_Bulldozer, Build_Bulldoze, 0, GRID_ALL },
00065         { Be_Zone_Residential, Build_Generic, Z_RESIDENTIAL_SLUM, GRID_ALL },
00066         { Be_Zone_Commercial, Build_Generic, Z_COMMERCIAL_SLUM, GRID_ALL},
00067         { Be_Zone_Industrial, Build_Generic, Z_INDUSTRIAL_SLUM, GRID_ALL},
00068         { Be_Road, Build_Road, 0, 0 },
00069         { Be_Rail, Build_Rail, 0, 0 },
00070         { Be_Power_Plant, Build_Generic4, Z_COALPLANT, GRID_ALL },
00071         { Be_Nuclear_Plant, Build_Generic4, Z_NUCLEARPLANT, GRID_ALL },
00072         { Be_Power_Line, Build_PowerLine, 0, GRID_ALL },
00073         { Be_Water_Pump, Build_Generic, Z_PUMP, GRID_ALL },
00074         { Be_Water_Pipe, Build_WaterPipe, 0, GRID_WATER },
00075         { Be_Tree, Build_Generic, Z_FAKETREE, 0 },
00076         { Be_Water, Build_Generic, Z_FAKEWATER, 0 },
00077         { Be_Fire_Station, Build_Generic4, Z_FIRESTATION, GRID_ALL },
00078         { Be_Police_Station, Build_Generic4, Z_POLICEDEPT, GRID_ALL },
00079         { Be_Military_Base, Build_Generic4, Z_ARMYBASE, GRID_ALL },
00080         { Be_OOB, NULL, 0, 0 },
00081         { Be_Defence_Fire, Build_Defence, DuFireman, 0 },
00082         { Be_Defence_Police, Build_Defence, DuPolice, 0 },
00083         { Be_Defence_Military, Build_Defence, DuMilitary, 0 },
00084 };
00085 
00086 #define BS_LEN  ((sizeof (buildStructure) / sizeof (buildStructure[0])))
00087 
00092 int
00093 BuildSomething(UInt16 xpos, UInt16 ypos)
00094 {
00095         UInt16 item = UIGetSelectedBuildItem();
00096         struct _bldStruct *be;
00097 
00098         if (item >= BS_LEN) {
00099                 UIDisplayError1("Unknown Build Item");
00100                 return (0);
00101         }
00102         be = (struct _bldStruct *)&(buildStructure[item]);
00103 
00104         if (be->bt == Be_OOB) return (0);
00105 
00106         if (be->func(xpos, ypos, be->type)) {
00107                 welem_t elt;
00108                 LockZone(lz_world);
00109                 elt = GetGraphicNumber(WORLDPOS(xpos, ypos));
00110                 UnlockZone(lz_world);
00111                 AddGridUpdate(be->gridsToUpdate);
00112                 UIPaintMapField(xpos, ypos, elt);
00113                 UIPaintMapStatus(xpos, ypos, elt, 0);
00114                 return (1);
00115         }
00116         return (0);
00117 }
00118 
00126 static void
00127 RemoveDefence(UInt16 xpos, UInt16 ypos)
00128 {
00129         int i;
00130 
00131         for (i = 0; i < NUM_OF_UNITS; i++) {
00132                 if (game.units[i].x == xpos &&
00133                     game.units[i].y == ypos) {
00134                         game.units[i].active = 0;
00135                         DrawCross(game.units[i].x, game.units[i].y, 1, 1);
00136                 }
00137         }
00138 }
00139 
00140 void
00141 RemoveAllDefence(void)
00142 {
00143         int i;
00144 
00145         for (i = 0; i < NUM_OF_UNITS; i++) {
00146                 if (game.units[i].active != 0) {
00147                         game.units[i].active = 0;
00148                         DrawCross(game.units[i].x, game.units[i].y, 1, 1);
00149                 }
00150         }
00151 }
00152 
00154 static const struct buildCounters {
00155         DefenceUnitTypes        unit; 
00156         UInt16                  counter; 
00157         UInt16                  start; 
00158         UInt16                  end; 
00159 } counters[] = {
00160         { DuFireman, bc_fire_stations, DEF_FIREMEN_START, DEF_FIREMEN_END },
00161         { DuPolice, bc_police_departments, DEF_POLICE_START, DEF_POLICE_END },
00162         { DuMilitary, bc_military_bases, DEF_MILITARY_START,
00163                 DEF_MILITARY_END }
00164 };
00165 
00173 static int
00174 Build_Defence(UInt16 xpos, UInt16 ypos, welem_t type)
00175 {
00176         UInt16 oldx;
00177         UInt16 oldy;
00178         UInt16 i;
00179         Int16 sel = -1;
00180         UInt16 newactive = 1;
00181         UInt16 start;
00182         UInt16 end;
00183         UInt16 max;
00184         UInt16 nCounter;
00185         const struct buildCounters *cnt;
00186         int rv = 0;
00187 
00188         if (type > DuMilitary)
00189                 return (rv);
00190 
00191         cnt = &counters[type];
00192 
00193         /* this is here to make sure not too many of any item are created */
00194         nCounter = cnt->counter;
00195 
00196         if (vgame.BuildCount[nCounter] == 0)
00197                 return (rv); /* no special building */
00198 
00199         start = cnt->start;
00200         end = cnt->end;
00201 
00202         /* make sure we can't make too many objects */
00203         if (((unsigned)((end - start) + 1) <
00204                     (unsigned)(vgame.BuildCount[nCounter] / 3)))
00205                 max = end;
00206         else
00207                 max = (UInt16)(vgame.BuildCount[nCounter] / 3 + start);
00208 
00209         /* first remove all defence on this tile */
00210         for (i = 0; i < NUM_OF_UNITS; i++) {
00211                 if (xpos == game.units[i].x &&
00212                         ypos == game.units[i].y &&
00213                         game.units[i].active != 0) {
00214                         /* no need to build something already here */
00215                         if ((UInt16)game.units[i].type == type)
00216                                 return (rv);
00217                         game.units[i].active = 0;
00218                 }
00219         }
00220 
00221         /* find an empty slot for the new defence unit */
00222         for (i = start; i <= max; i++) {
00223                 if (game.units[i].active == 0) {
00224                         sel = (Int16)i;
00225                         break;
00226                 }
00227         }
00228         if (sel == -1) {
00229                 /* none found - start from the beginning */
00230                 for (i = start; i <= max; i++) {
00231                         if (game.units[i].active == 1) {
00232                                 sel = (Int16)i;
00233                                 newactive = 2;
00234                                 break;
00235                         } else {
00236                                 game.units[i].active = 2;
00237                         }
00238                 }
00239         }
00240         if (sel == -1) {
00241                 /* if STILL none found - then it's number 0 */
00242                 for (i = start; i <= max; i++) {
00243                         if (game.units[i].active != 0) {
00244                                 game.units[i].active = 1;
00245                         }
00246                 }
00247                 sel = (Int16)start;
00248                 newactive = 2;
00249         }
00250 
00251         oldx = game.units[sel].x;
00252         oldy = game.units[sel].y;
00253 
00254         game.units[sel].x = xpos;
00255         game.units[sel].y = ypos;
00256         game.units[sel].active = newactive;
00257         game.units[sel].type = (DefenceUnitTypes)type;
00258 
00259         LockZone(lz_world);
00260         rv = 1;
00261         DrawCross(oldx, oldy, 1, 1);
00262         DrawCross(xpos, ypos, 1, 1);
00263         UnlockZone(lz_world);
00264         return (rv);
00265 }
00266 
00268 static int
00269 CantBulldoze(welem_t type)
00270 {
00271         return (type == Z_DIRT || type == Z_FIRE1 || type == Z_FIRE2 ||
00272             type == Z_FIRE3 || type == Z_REALWATER || type == Z_CRATER);
00273 }
00274 
00281 static UInt16
00282 blockSize(welem_t type)
00283 {
00284         /* This works because all the multiblocks are sequential */
00285         if (type >= Z_COALPLANT_START && type <= Z_ARMYBASE_END)
00286                 return (4);
00287         return (1);
00288 }
00289 
00290 int
00291 Build_Bulldoze(UInt16 xpos, UInt16 ypos, welem_t _type __attribute__((unused)))
00292 {
00293         int rv = 0;
00294         welem_t type;
00295 
00296         LockZone(lz_world);
00297         type = getWorld(WORLDPOS(xpos, ypos));
00298 
00299         WriteLog("BuildBulldoze(type=%d)\n", (int)type);
00300         if (CantBulldoze(type)) {
00301                 RemoveDefence(xpos, ypos);
00302                 goto end;
00303         }
00304         if (SpendMoney(BUILD_COST_BULLDOZER * blockSize(type))) {
00305                 Build_Destroy(xpos, ypos);
00306                 rv = 1;
00307         } else {
00308                 UIProblemNotify(peOutOfMoney);
00309         }
00310 end:
00311         UnlockZone(lz_world);
00312         return (rv);
00313 }
00314 
00322 static void
00323 Doff(welem_t base, welem_t node, UInt16 *x, UInt16 *y)
00324 {
00325         *x -= (UInt16)((node - base) % 2);
00326         *y -= (UInt16)((node - base) / 2);
00327 }
00328 
00329 void
00330 Build_Destroy(UInt16 xpos, UInt16 ypos)
00331 {
00332         welem_t type;
00333         /* Destroy a 1x1 square area */
00334         UInt16 x_destroy = 1;
00335         UInt16 tx_destroy = 1;
00336         UInt16 y_destroy = 1;
00337         UInt16 ty_destroy = 1;
00338 
00339         type = getWorld(WORLDPOS(xpos, ypos));
00340         RemoveDefence(xpos, ypos);
00341 
00342         if (IsCommercial(type)) {
00343                 vgame.BuildCount[bc_count_commercial]--;
00344                 vgame.BuildCount[bc_value_commercial] -= ZoneValue(type);
00345                 goto finish;
00346         }
00347         if (IsResidential(type)) {
00348                 vgame.BuildCount[bc_count_residential]--;
00349                 vgame.BuildCount[bc_value_residential] -= ZoneValue(type);
00350                 goto finish;
00351         }
00352         if (IsIndustrial(type)) {
00353                 vgame.BuildCount[bc_count_industrial]--;
00354                 vgame.BuildCount[bc_value_industrial] -= ZoneValue(type);
00355                 goto finish;
00356         }
00357         if (IsFakeTree(type)) {
00358                 vgame.BuildCount[bc_count_trees]--;
00359                 goto finish;
00360         }
00361         if (IsFakeWater(type)) {
00362                 vgame.BuildCount[bc_water]--;
00363                 goto finish;
00364         }
00365         if (IsWaste(type)) {
00366                 vgame.BuildCount[bc_waste]--;
00367                 goto finish;
00368         }
00369         if (type >= Z_FIRE1 && type <= Z_FIRE3) {
00370                 vgame.BuildCount[bc_fire]--;
00371                 goto finish;
00372         }
00373         
00374         if (IsCoalPlant(type)) {
00375                 vgame.BuildCount[bc_coalplants]--;
00376                 x_destroy = 2;
00377                 y_destroy = 2;
00378                 Doff(Z_COALPLANT_START, type, &xpos, &ypos);
00379                 goto finish;
00380         }
00381         if (IsNukePlant(type)) {
00382                 vgame.BuildCount[bc_nuclearplants]--;
00383                 x_destroy = 2;
00384                 y_destroy = 2;
00385                 Doff(Z_NUCLEARPLANT_START, type, &xpos, &ypos);
00386                 goto finish;
00387         }
00388         if (IsFireStation(type)) {
00389                 vgame.BuildCount[bc_fire_stations]--;
00390                 x_destroy = 2;
00391                 y_destroy = 2;
00392                 Doff(Z_FIRESTATION_START, type, &xpos, &ypos);
00393                 goto finish;
00394         }
00395         if (IsPoliceDept(type)) {
00396                 vgame.BuildCount[bc_police_departments]--;
00397                 x_destroy = 2;
00398                 y_destroy = 2;
00399                 Doff(Z_POLICEDEPT_START, type, &xpos, &ypos);
00400                 goto finish;
00401         }
00402         if (IsArmyBase(type)) {
00403                 vgame.BuildCount[bc_military_bases]--;
00404                 x_destroy = 2;
00405                 y_destroy = 2;
00406                 Doff(Z_ARMYBASE_START, type, &xpos, &ypos);
00407                 goto finish;
00408         }
00409         if (IsPump(type)) {
00410                 vgame.BuildCount[bc_waterpumps]--;
00411                 goto finish;
00412         }
00413         
00414         if (IsRoad(type)) {
00415                 vgame.BuildCount[bc_count_roads]--;
00416                 vgame.BuildCount[bc_value_roads] -= ZoneValue(type);
00417         }
00418         if (IsPowerLine(type)) {
00419                 vgame.BuildCount[bc_powerlines]--;
00420         }
00421         if (IsWaterPipe(type)) {
00422                 vgame.BuildCount[bc_waterpipes]--;
00423         }
00424         if (IsRoadPipe(type)) {
00425                 vgame.BuildCount[bc_count_roads]--;
00426                 vgame.BuildCount[bc_waterpipes]--;
00427                 vgame.BuildCount[bc_value_roads] -= ZoneValue(type);
00428         }
00429         if (IsRoadPower(type)) {
00430                 vgame.BuildCount[bc_count_roads]--;
00431                 vgame.BuildCount[bc_powerlines]--;
00432                 vgame.BuildCount[bc_value_roads] -= ZoneValue(type);
00433         }
00434         if (IsPowerWater(type)) {
00435                 vgame.BuildCount[bc_waterpipes]--;
00436                 vgame.BuildCount[bc_powerlines]--;
00437         }
00438 
00439         if (IsRail(type)) {
00440                 vgame.BuildCount[bc_count_rail]--;
00441                 vgame.BuildCount[bc_value_rail] -= ZoneValue(type);
00442         }
00443         if (IsRailPower(type)) {
00444                 vgame.BuildCount[bc_count_rail]--;
00445                 vgame.BuildCount[bc_value_rail] -= ZoneValue(type);
00446                 vgame.BuildCount[bc_powerlines]--;
00447         }
00448         if (IsRailPipe(type)) {
00449                 vgame.BuildCount[bc_count_rail]--;
00450                 vgame.BuildCount[bc_value_rail] -= ZoneValue(type);
00451                 vgame.BuildCount[bc_waterpipes]--;
00452         }
00453         if (IsRailOvRoad(type)) {
00454                 vgame.BuildCount[bc_count_rail]--;
00455                 vgame.BuildCount[bc_value_rail] -= ZoneValue(type);
00456                 vgame.BuildCount[bc_count_roads]--;
00457                 vgame.BuildCount[bc_value_roads] -= ZoneValue(type);
00458         }
00459 
00460 finish:
00461         AddGridUpdate(GRID_ALL);
00462 
00463         if (IsRoadBridge(type) || IsRailTunnel(type) || IsRealWater(type)) {
00464                 /* A bridge turns into real_water when detroyed */
00465                 setWorldAndFlag(WORLDPOS(xpos, ypos), Z_REALWATER, 0);
00466         } else {
00467                 if ((x_destroy != 1) || (y_destroy != 1)) {
00468                         ty_destroy = y_destroy;
00469                         while(ty_destroy) {
00470                                 tx_destroy=x_destroy;
00471                                 while(tx_destroy) {
00472                                         setWorldAndFlag(
00473                                             WORLDPOS(xpos - 1 + tx_destroy,
00474                                             ypos - 1 + ty_destroy), Z_DIRT, 0);
00475                                         tx_destroy--;
00476                                 }
00477                                 ty_destroy--;
00478                         }
00479                 } else {
00480                         setWorldAndFlag(WORLDPOS(xpos, ypos), Z_DIRT, 0);
00481                 }
00482         }
00483 
00484         /* Locks the world flags itself */
00485         DrawCross(xpos, ypos, x_destroy, y_destroy);
00486 }
00487 
00489 static const struct _costMappings {
00490         UInt16 type; 
00491         UInt32 cost; 
00492         Int16 count; 
00493 } genericMappings[] = {
00494         { Z_RESIDENTIAL_SLUM, BUILD_COST_ZONE, -1 },
00495         { Z_INDUSTRIAL_SLUM, BUILD_COST_ZONE, -1 },
00496         { Z_COMMERCIAL_SLUM, BUILD_COST_ZONE, -1 },
00497         { Z_COALPLANT, BUILD_COST_POWER_PLANT, bc_coalplants },
00498         { Z_NUCLEARPLANT, BUILD_COST_NUCLEAR_PLANT, bc_nuclearplants },
00499         { Z_FAKEWATER, BUILD_COST_WATER, bc_water },
00500         { Z_FAKETREE, BUILD_COST_TREE, bc_count_trees },
00501         { Z_FIRESTATION, BUILD_COST_FIRE_STATION, bc_fire_stations },
00502         { Z_POLICEDEPT, BUILD_COST_POLICE_STATION, bc_police_departments },
00503         { Z_ARMYBASE, BUILD_COST_MILITARY_BASE, bc_military_bases },
00504         { Z_PUMP, BUILD_COST_WATER_PUMP, bc_waterpumps },
00505         { 0, 0, -1 }
00506 };
00507 
00514 static Int16
00515 IsBulldozable(welem_t zone)
00516 {
00517         return ((zone == Z_DIRT) ||
00518             ((zone == Z_REALTREE) && GETAUTOBULLDOZE()));
00519 }
00520 
00529 static int
00530 Build_Generic4(UInt16 xpos, UInt16 ypos, welem_t type)
00531 {
00532         unsigned char worldItem;
00533         unsigned long toSpend = 0;
00534         UInt16 loopx, loopy;
00535         Int8 canbuild = 1;
00536         int rv = 0;
00537 
00538         struct _costMappings *cmi = (struct _costMappings *)getIndexOf(
00539             (char *)&genericMappings[0], sizeof (genericMappings[0]), type);
00540 #ifdef PALM
00541         ErrFatalDisplayIf(cmi == NULL, "No generic->item mapping");
00542 #else
00543         assert(cmi != NULL);
00544 #endif
00545         if (cmi == NULL)
00546                 return (rv);
00547         LockZone(lz_world);
00548         LockZone(lz_flags);
00549 
00550         toSpend = cmi->cost;
00551 
00552         for (loopx = xpos; loopx < xpos + 2; loopx++) {
00553                 for (loopy = ypos; loopy < ypos + 2; loopy++) {
00554                         worldItem = getWorld(WORLDPOS(loopx, loopy));
00555                         if (IsBulldozable(worldItem)) {
00556                                 if (worldItem == Z_REALTREE)
00557                                         toSpend += BUILD_COST_BULLDOZER;
00558                         } else {
00559                                 canbuild = 0;
00560                         }
00561                 }
00562         }
00563         if (!canbuild) {
00564                 LockZone(lz_flags);
00565                 UnlockZone(lz_world);
00566                 return (rv);
00567         }
00568 
00569         if (SpendMoney(toSpend)) {
00570                 for (loopy = ypos; loopy < ypos + 2; loopy++) {
00571                         for (loopx = xpos; loopx < xpos + 2; loopx++)
00572                                 setWorldAndFlag(WORLDPOS(loopx, loopy),
00573                                     type++, 0);
00574                         }
00575 
00576                 if (cmi->count != -1)
00577                         vgame.BuildCount[cmi->count]++;
00578 
00579                 DrawCross(xpos, ypos, 2, 2);
00580                 rv = 1;
00581         } else {
00582                 UIProblemNotify(peOutOfMoney);
00583         }
00584         UnlockZone(lz_flags);
00585         UnlockZone(lz_world);
00586         return (rv);
00587 }
00588 
00597 static int
00598 Build_Generic(UInt16 xpos, UInt16 ypos, welem_t type)
00599 {
00600         welem_t worldItem;
00601         UInt32 toSpend = 0;
00602         int rv = 0;
00603 
00604         struct _costMappings *cmi = (struct _costMappings *)getIndexOf(
00605             (char *)&genericMappings[0], sizeof (genericMappings[0]), type);
00606 #ifdef PALM
00607         ErrFatalDisplayIf(cmi == NULL, "No generic->item mapping");
00608 #else
00609         assert(cmi != NULL);
00610 #endif
00611         if (cmi == NULL)
00612                 return (rv);
00613         LockZone(lz_world);
00614         LockZone(lz_flags);
00615 
00616         toSpend = cmi->cost;
00617 
00618         worldItem = getWorld(WORLDPOS(xpos, ypos));
00619 
00620         if ((type == Z_FAKETREE) && ((worldItem == Z_REALTREE) ||
00621                     (worldItem == Z_FAKETREE))) {
00622                 UnlockZone(lz_world);
00623                 UnlockZone(lz_flags);
00624                 return (rv);
00625         }
00626 
00627         if (IsBulldozable(worldItem)) {
00628                 if (worldItem == Z_REALTREE) toSpend += BUILD_COST_BULLDOZER;
00629                 if (SpendMoney(toSpend)) {
00630                         setWorldAndFlag(WORLDPOS(xpos, ypos),
00631                             (welem_t)type, 0);
00632                         DrawCross(xpos, ypos, 1, 1);
00633 
00634                         /*  update counter */
00635                         if (IsRoad(type)) {
00636                                 vgame.BuildCount[bc_count_roads]++;
00637                         } else {
00638                                 if (cmi->count != -1)
00639                                         vgame.BuildCount[cmi->count]++;
00640                         }
00641                         rv = 1;
00642                 } else {
00643                         UIProblemNotify(peOutOfMoney);
00644                         }
00645         }
00646         UnlockZone(lz_flags);
00647         UnlockZone(lz_world);
00648         return (rv);
00649 }
00650 
00659 static int
00660 Build_Road(UInt16 xpos, UInt16 ypos, welem_t type __attribute__((unused)))
00661 {
00662         welem_t old;
00663         UInt32 toSpend = 0;
00664         int rv = 0;
00665 
00666         LockZone(lz_world);
00667         LockZone(lz_flags);
00668         old = getWorld(WORLDPOS(xpos, ypos));
00669         toSpend = BUILD_COST_ROAD;
00670         if (IsPowerLine(old) || IsWaterPipe(old) || IsRail(old)) {
00671                 welem_t tobuil = 0;
00672                 switch (GetSpecialGraphicNumber(WORLDPOS(xpos, ypos))) {
00673                 case Z_POWERLINE: /* straight power line - Horizontal */
00674                         tobuil = Z_POWERROAD_PHOR;
00675                         break;
00676                 case Z_POWERLINE+1: /* Straight power line - Vertical */
00677                         tobuil = Z_POWERROAD_PVER;
00678                         break;
00679                 case Z_PIPE_START: /* Straight water pipe - Horizontal */
00680                         tobuil = Z_PIPEROAD_PHOR;
00681                         break;
00682                 case Z_PIPE_START+1: /* Straight water pipe - Vertical */
00683                         tobuil = Z_PIPEROAD_PVER;
00684                         break;
00685                 case Z_RAIL_START: /* Straight rail line - Horizontal */
00686                         tobuil = Z_RAILOVROAD_RHOR;
00687                         break;
00688                 case Z_RAIL_START+1: /* Straight rail line - Vertical */
00689                         tobuil = Z_RAILOVROAD_RVER;
00690                         break;
00691                 }
00692                 if (tobuil == 0)
00693                         goto leaveme;
00694                 if (SpendMoney(toSpend)) {
00695                         setWorldAndFlag(WORLDPOS(xpos, ypos), tobuil, 0);
00696                         DrawCross(xpos, ypos, 1, 1);
00697                         vgame.BuildCount[bc_count_roads]++;
00698                         rv = 1;
00699                 } else {
00700                         UIProblemNotify(peOutOfMoney);
00701                 }
00702         } else if (IsRealWater(old)) {
00703                 welem_t tobuil = 0;
00704                 UInt8 check_rd;
00705                 UInt8 check_br;
00706                 UInt32 wp = WORLDPOS(xpos, ypos);
00707                 check_rd = CheckNextTo(wp, DIR_ALL, IsRoad);
00708                 check_br = CheckNextTo(wp, DIR_ALL, IsRoadBridge);
00709 
00710                 if ((check_rd == 0) && (check_br == 0))
00711                         goto leaveme;
00712                 /*
00713                  * build a bridge only if one of the squares around is
00714                  * either a bridge or a road.
00715                  */
00716                 if ((check_rd & DIR_UP) || (check_rd & DIR_DOWN)) {
00717                         tobuil = Z_BRIDGE_VER;
00718                         goto success_build;
00719                 }
00720                 if ((check_rd & DIR_LEFT) || (check_rd & DIR_RIGHT)) {
00721                         tobuil = Z_BRIDGE_HOR;
00722                         goto success_build;
00723                 }
00724                 if (((check_br & DIR_LEFT) &&
00725                     (getWorld(WORLDPOS(xpos - 1, ypos)) == Z_BRIDGE_HOR)) ||
00726                     ((check_br & DIR_RIGHT) &&
00727                     (getWorld(WORLDPOS(xpos + 1, ypos)) == Z_BRIDGE_HOR))) {
00728                         tobuil = Z_BRIDGE_HOR;
00729                 } else if (((check_br & DIR_UP) &&
00730                     (getWorld(WORLDPOS(xpos, ypos - 1)) == Z_BRIDGE_VER)) ||
00731                     ((check_br & DIR_DOWN) &&
00732                     (getWorld(WORLDPOS(xpos, ypos + 1)) == Z_BRIDGE_VER))) {
00733                         tobuil = Z_BRIDGE_VER;
00734                 }
00735                 if (tobuil == 0)
00736                         goto leaveme;
00737                 toSpend = BUILD_COST_BRIDGE;
00738 success_build:
00739                 if (SpendMoney(toSpend)) {
00740                         setWorldAndFlag(WORLDPOS(xpos, ypos), tobuil, 0);
00741                         DrawCross(xpos, ypos, 1, 1);
00742                         vgame.BuildCount[bc_count_roads]++;
00743                         rv = 1;
00744                 } else {
00745                         UIProblemNotify(peOutOfMoney);
00746                 }
00747         } else if (IsBulldozable(old)) {
00748                 if (old == Z_REALTREE) toSpend += BUILD_COST_BULLDOZER;
00749                 if (SpendMoney(toSpend)) {
00750                         setWorldAndFlag(WORLDPOS(xpos, ypos), Z_ROAD, 0);
00751                         DrawCross(xpos, ypos, 1, 1);
00752                         vgame.BuildCount[bc_count_roads]++;
00753                         rv = 1;
00754                 } else {
00755                         UIProblemNotify(peOutOfMoney);
00756                 }
00757         }
00758 leaveme:
00759         UnlockZone(lz_flags);
00760         UnlockZone(lz_world);
00761         return (rv);
00762 }
00763 
00772 static int
00773 Build_Rail(UInt16 xpos, UInt16 ypos, welem_t type __attribute__((unused)))
00774 {
00775         welem_t old;
00776         UInt32 toSpend = 0;
00777         int rv = 0;
00778 
00779         LockZone(lz_world);
00780         LockZone(lz_flags);
00781         old = getWorld(WORLDPOS(xpos, ypos));
00782         toSpend = BUILD_COST_RAIL;
00783         if (IsPowerLine(old) || IsWaterPipe(old) || IsRoad(old)) {
00784                 welem_t tobuil = 0;
00785                 switch (GetSpecialGraphicNumber(WORLDPOS(xpos, ypos))) {
00786                 case Z_POWERLINE: /* straight power line - Horizontal */
00787                         tobuil = Z_RAILPOWER_RVER;
00788                         break;
00789                 case Z_POWERLINE+1: /* Straight power line - Vertical */
00790                         tobuil = Z_RAILPOWER_RHOR;
00791                         break;
00792                 case Z_PIPE_START: /* Straight water pipe - Horizontal */
00793                         tobuil = Z_RAILPIPE_RVER;
00794                         break;
00795                 case Z_PIPE_START+1: /* Straight water pipe - Vertical */
00796                         tobuil = Z_RAILPIPE_RHOR;
00797                         break;
00798                 case Z_ROAD_START: /* Straight road - Horizontal */
00799                         tobuil = Z_RAILOVROAD_RVER;
00800                         break;
00801                 case Z_ROAD_START+1: /* Straight road - Vertical */
00802                         tobuil = Z_RAILOVROAD_RHOR;
00803                         break;
00804                 }
00805                 if (tobuil == 0)
00806                         goto leaveme;
00807                 if (SpendMoney(toSpend)) {
00808                         setWorldAndFlag(WORLDPOS(xpos, ypos), tobuil, 0);
00809                         DrawCross(xpos, ypos, 1, 1);
00810                         vgame.BuildCount[bc_count_rail]++;
00811                         rv = 1;
00812                 } else {
00813                         UIProblemNotify(peOutOfMoney);
00814                 }
00815         } else if (IsRealWater(old)) {
00816                 welem_t tobuil = 0;
00817                 UInt8 check_rd;
00818                 UInt8 check_br;
00819                 UInt32 wp = WORLDPOS(xpos, ypos);
00820                 check_rd = CheckNextTo(wp, DIR_ALL, IsRail);
00821                 check_br = CheckNextTo(wp, DIR_ALL, IsRailTunnel);
00822 
00823                 if ((check_rd == 0) && (check_br == 0))
00824                         goto leaveme;
00825                 /*
00826                  * build a tunnel only if one of the squares around is
00827                  * either a tunnel or a rail line.
00828                  */
00829                 if ((check_rd & DIR_UP) || (check_rd & DIR_DOWN)) {
00830                         tobuil = Z_RAILTUNNEL_RVER;
00831                         goto success_build;
00832                 }
00833                 if ((check_rd & DIR_LEFT) || (check_rd & DIR_RIGHT)) {
00834                         tobuil = Z_RAILTUNNEL_RHOR;
00835                         goto success_build;
00836                 }
00837                 if (((check_br & DIR_LEFT) &&
00838                     (getWorld(WORLDPOS(xpos - 1, ypos)) ==
00839                      Z_RAILTUNNEL_RHOR)) || ((check_br & DIR_RIGHT) &&
00840                     (getWorld(WORLDPOS(xpos + 1, ypos)) ==
00841                      Z_RAILTUNNEL_RHOR))) {
00842                         tobuil = Z_RAILTUNNEL_RHOR;
00843                 } else if (((check_br & DIR_UP) &&
00844                     (getWorld(WORLDPOS(xpos, ypos - 1)) ==
00845                      Z_RAILTUNNEL_RVER)) || ((check_br & DIR_DOWN) &&
00846                     (getWorld(WORLDPOS(xpos, ypos + 1)) ==
00847                      Z_RAILTUNNEL_RVER))) {
00848                         tobuil = Z_RAILTUNNEL_RVER;
00849                 }
00850                 if (tobuil == 0)
00851                         goto leaveme;
00852                 toSpend = BUILD_COST_RAILTUNNEL;
00853 success_build:
00854                 if (SpendMoney(toSpend)) {
00855                         setWorldAndFlag(WORLDPOS(xpos, ypos), tobuil, 0);
00856                         DrawCross(xpos, ypos, 1, 1);
00857                         vgame.BuildCount[bc_count_rail]++;
00858                         rv = 1;
00859                 } else {
00860                         UIProblemNotify(peOutOfMoney);
00861                 }
00862         } else if (IsBulldozable(old)) {
00863                 if (old == Z_REALTREE) toSpend += BUILD_COST_BULLDOZER;
00864                 if (SpendMoney(toSpend)) {
00865                         setWorldAndFlag(WORLDPOS(xpos, ypos), Z_RAIL, 0);
00866                         DrawCross(xpos, ypos, 1, 1);
00867                         vgame.BuildCount[bc_count_rail]++;
00868                         rv = 1;
00869                 } else {
00870                         UIProblemNotify(peOutOfMoney);
00871                 }
00872         }
00873 leaveme:
00874         UnlockZone(lz_world);
00875         UnlockZone(lz_flags);
00876         return (rv);
00877 }
00878 
00887 static int
00888 Build_PowerLine(UInt16 xpos, UInt16 ypos, welem_t type __attribute__((unused)))
00889 {
00890         welem_t old;
00891         UInt32 toSpend = 0;
00892         int rv = 0;
00893 
00894         LockZone(lz_world);
00895         LockZone(lz_flags);
00896 
00897         old = getWorld(WORLDPOS(xpos, ypos));
00898         toSpend = BUILD_COST_POWER_LINE;
00899         if (IsBulldozable(old)) {
00900                 if (old == Z_REALTREE) toSpend += BUILD_COST_BULLDOZER;
00901                 if (SpendMoney(toSpend)) {
00902                         setWorldAndFlag(WORLDPOS(xpos, ypos), Z_POWERLINE, 0);
00903                         DrawCross(xpos, ypos, 1, 1);
00904                         vgame.BuildCount[bc_powerlines]++;
00905                         rv = 1;
00906                 } else {
00907                         UIProblemNotify(peOutOfMoney);
00908                 }
00909         }
00910         if (IsRoad(old) || IsWaterPipe(old) || IsRail(old)) {
00911                 welem_t tobuil = 0;
00912                 switch (GetSpecialGraphicNumber(WORLDPOS(xpos, ypos))) {
00913                 /* straight road - horizontal, vertical power line */
00914                 case Z_ROAD_START:
00915                         tobuil = Z_POWERROAD_PVER;
00916                         break;
00917                 case Z_ROAD_START+1: /* straight road - vertical */
00918                         tobuil = Z_POWERROAD_PHOR;
00919                         break;
00920                 case Z_PIPE_START: /* straight pipe - horizontal */
00921                         tobuil = Z_POWER_WATER_PVER;
00922                         break;
00923                 case Z_PIPE_START+1:
00924                         tobuil = Z_POWER_WATER_PHOR;
00925                         break;
00926                 case Z_RAIL_START: /* straight rail - horizontal */
00927                         tobuil = Z_RAILPOWER_RHOR;
00928                         break;
00929                 case Z_RAIL_START+1: /* straight rail - vertical */
00930                         tobuil = Z_RAILPOWER_RVER;
00931                         break;
00932                 }
00933                 if (tobuil == 0)
00934                         goto leaveme;
00935                 if (SpendMoney(toSpend)) {
00936                         setWorldAndFlag(WORLDPOS(xpos, ypos), tobuil, 0);
00937                         DrawCross(xpos, ypos, 1, 1);
00938                         vgame.BuildCount[bc_powerlines]++;
00939                         rv = 1;
00940                 } else {
00941                         UIProblemNotify(peOutOfMoney);
00942                 }
00943         }
00944 leaveme:
00945         UnlockZone(lz_world);
00946         UnlockZone(lz_flags);
00947         return (rv);
00948 }
00949 
00958 static int
00959 Build_WaterPipe(UInt16 xpos, UInt16 ypos, welem_t type __attribute__((unused)))
00960 {
00961         welem_t old;
00962         UInt32 toSpend = 0;
00963         welem_t elt = 0;
00964         int rv = 0;
00965 
00966         LockZone(lz_world);
00967         LockZone(lz_flags);
00968 
00969         toSpend = BUILD_COST_WATER_PIPE;
00970         old = getWorld(WORLDPOS(xpos, ypos));
00971         if (IsBulldozable(old)) {
00972                 if (old == Z_REALTREE) toSpend += BUILD_COST_BULLDOZER;
00973                 if (SpendMoney(toSpend)) {
00974                         setWorldAndFlag(WORLDPOS(xpos, ypos), Z_PIPE, 0);
00975                         DrawCross(xpos, ypos, 1, 1);
00976                         vgame.BuildCount[bc_waterpipes]++;
00977                         rv = 1;
00978                         goto leaveme;
00979                 } else {
00980                         UIProblemNotify(peOutOfMoney);
00981                         goto leaveme;
00982                 }
00983         }
00984         if (IsRoad(old) || IsPowerLine(old) || IsRail(old)) {
00985                 switch (GetSpecialGraphicNumber(WORLDPOS(xpos, ypos))) {
00986                 case Z_ROAD_START: /* straight road - Horizontal */
00987                         elt = Z_PIPEROAD_PVER;
00988                         break;
00989                 case Z_ROAD_START+1: /* straight road - Vertical */
00990                         elt = Z_PIPEROAD_PHOR;
00991                         break;
00992                 case Z_RAIL_START: /* straight rail - Horizontal */
00993                         elt = Z_RAILPIPE_RHOR;
00994                         break;
00995                 case Z_RAIL_START+1: /* rail - Vertical */
00996                         elt = Z_RAILPIPE_RVER;
00997                         break;
00998                 case Z_POWERLINE_START: /* powerline - Horizontal */
00999                         elt = Z_POWER_WATER_PHOR;
01000                         break;
01001                 case Z_POWERLINE_START+1: /* powerline - Vertical */
01002                         elt = Z_POWER_WATER_PVER;
01003                         break;
01004                 }
01005                 if (elt == 0)
01006                         goto leaveme;
01007                 if (SpendMoney(toSpend)) {
01008                         setWorldAndFlag(WORLDPOS(xpos, ypos), elt, 0);
01009                         DrawCross(xpos, ypos, 1, 1);
01010                         vgame.BuildCount[bc_waterpipes]++;
01011                         rv = 1;
01012                 } else {
01013                         UIProblemNotify(peOutOfMoney);
01014                 }
01015         }
01016 leaveme:
01017         UnlockZone(lz_flags);
01018         UnlockZone(lz_world);
01019         return (rv);
01020 }
01021 
01029 static Int16
01030 SpendMoney(UInt32 howMuch)
01031 {
01032         if (howMuch > (UInt32)getCredits())
01033                 return (0);
01034 
01035         WriteLog("Spend Money: %ld\n", howMuch);
01036         decCredits((Int32)howMuch);
01037 
01038         /* now redraw the credits */
01039         addGraphicUpdate(gu_credits);
01040         return (1);
01041 }
01042 
01046 void
01047 CreateFullRiver(void)
01048 {
01049         UInt16 i, j, k, width;
01050         int axis;
01051         UInt16 kmax;
01052 
01053         width = (UInt16)(GetRandomNumber(5) + 5);
01054         axis = (int)GetRandomNumber(1);
01055         kmax = axis ? getMapWidth() : getMapHeight();
01056 
01057         /* This is the start position of the center of the river */
01058         j = (UInt16)GetRandomNumber(kmax);
01059 
01060         LockZone(lz_world);
01061         LockZone(lz_flags);
01062 
01063         for (i = 0; i < kmax; i++) {
01064                 for (k = j; k < (width + j); k++) {
01065                         if (k < kmax) {
01066                                 if (axis)
01067                                         setWorldAndFlag(WORLDPOS(i, k),
01068                                             Z_REALWATER, 0);
01069                                 else
01070                                         setWorldAndFlag(WORLDPOS(k, i),
01071                                             Z_REALWATER, 0);
01072                         }
01073                 }
01074 
01075                 switch (GetRandomNumber(3)) {
01076                 case 0:
01077                         if (width >  5)
01078                                 width--;
01079                         break;
01080                 case 1:
01081                         if (width < 15)
01082                                 width++;
01083                         break;
01084                 default:
01085                         break;
01086                 }
01087                 switch (GetRandomNumber(4)) {
01088                 case 0:
01089                         if (j > 0)
01090                                 j--;
01091                         break;
01092                 case 1:
01093                         if (j < kmax)
01094                                 j++;
01095                         break;
01096                 default:
01097                         break;
01098                 }
01099         }
01100         UnlockZone(lz_flags);
01101         UnlockZone(lz_world);
01102 }
01103 
01108 void
01109 CreateForests(void)
01110 {
01111         UInt16 i, j, k;
01112         UInt32 pos;
01113 
01114         j = (UInt16)(GetRandomNumber(6) + 7);
01115         for (i = 0; i < j; i++) {
01116                 k = (UInt16)(GetRandomNumber(6) + 8);
01117                 pos = (UInt16)GetRandomNumber(MapMul());
01118                 CreateForest(pos, k);
01119         }
01120 }
01121 
01127 static void
01128 CreateForest(UInt32 pos, UInt16 size)
01129 {
01130         UInt16 x, y, i, j, s;
01131 
01132         x = (UInt16)(pos % getMapWidth());
01133         y = (UInt16)(pos / getMapWidth());
01134         LockZone(lz_world);
01135         LockZone(lz_flags);
01136         i = x - size > 0 ? x - size : 0;
01137         j = y - size > 0 ? y - size : 0;
01138 
01139         for (; i <= x + size; i++) {
01140                 for (j = y - size; j <= y + size; j++) {
01141                         if (i >= getMapWidth() ||
01142                             j >= getMapHeight())
01143                                 continue;
01144                         if (getWorld(WORLDPOS(i, j)) != Z_DIRT)
01145                                 continue;
01146                         s = ((y > j) ? (y - j) : (j - y)) +
01147                             ((x > i) ? (x - i) : (i - x));
01148                         if (GetRandomNumber(s) < 2) {
01150                                 setWorldAndFlag(WORLDPOS(i, j), Z_REALTREE, 0);
01151                                 vgame.BuildCount[bc_count_trees]++;
01152                         }
01153                 }
01154                 j = y - size > 0 ? y - size : 0;
01155         }
01156         UnlockZone(lz_flags);
01157         UnlockZone(lz_world);
01158 }

Generated on Mon Aug 30 19:44:16 2004 for pocketcity by doxygen1.2.18