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
00194 nCounter = cnt->counter;
00195
00196 if (vgame.BuildCount[nCounter] == 0)
00197 return (rv);
00198
00199 start = cnt->start;
00200 end = cnt->end;
00201
00202
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
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
00215 if ((UInt16)game.units[i].type == type)
00216 return (rv);
00217 game.units[i].active = 0;
00218 }
00219 }
00220
00221
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
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
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
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
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
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
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
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:
00674 tobuil = Z_POWERROAD_PHOR;
00675 break;
00676 case Z_POWERLINE+1:
00677 tobuil = Z_POWERROAD_PVER;
00678 break;
00679 case Z_PIPE_START:
00680 tobuil = Z_PIPEROAD_PHOR;
00681 break;
00682 case Z_PIPE_START+1:
00683 tobuil = Z_PIPEROAD_PVER;
00684 break;
00685 case Z_RAIL_START:
00686 tobuil = Z_RAILOVROAD_RHOR;
00687 break;
00688 case Z_RAIL_START+1:
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
00714
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:
00787 tobuil = Z_RAILPOWER_RVER;
00788 break;
00789 case Z_POWERLINE+1:
00790 tobuil = Z_RAILPOWER_RHOR;
00791 break;
00792 case Z_PIPE_START:
00793 tobuil = Z_RAILPIPE_RVER;
00794 break;
00795 case Z_PIPE_START+1:
00796 tobuil = Z_RAILPIPE_RHOR;
00797 break;
00798 case Z_ROAD_START:
00799 tobuil = Z_RAILOVROAD_RVER;
00800 break;
00801 case Z_ROAD_START+1:
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
00827
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
00914 case Z_ROAD_START:
00915 tobuil = Z_POWERROAD_PVER;
00916 break;
00917 case Z_ROAD_START+1:
00918 tobuil = Z_POWERROAD_PHOR;
00919 break;
00920 case Z_PIPE_START:
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:
00927 tobuil = Z_RAILPOWER_RHOR;
00928 break;
00929 case Z_RAIL_START+1:
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:
00987 elt = Z_PIPEROAD_PVER;
00988 break;
00989 case Z_ROAD_START+1:
00990 elt = Z_PIPEROAD_PHOR;
00991 break;
00992 case Z_RAIL_START:
00993 elt = Z_RAILPIPE_RHOR;
00994 break;
00995 case Z_RAIL_START+1:
00996 elt = Z_RAILPIPE_RVER;
00997 break;
00998 case Z_POWERLINE_START:
00999 elt = Z_POWER_WATER_PHOR;
01000 break;
01001 case Z_POWERLINE_START+1:
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
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
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 }