00001
00002
00003
00004
00005
00006
00007
00008 #include <stdio.h>
00009 #include "lclib.h"
00010 #include "common.h"
00011 #include "lctypes.h"
00012 #include "lin-city.h"
00013 #include "engine.h"
00014 #include "engglobs.h"
00015 #include "cliglobs.h"
00016 #include "simulate.h"
00017
00018
00019 #include "lcintl.h"
00020 #include "power.h"
00021 #include "transport.h"
00022
00023
00024 int grid_num = 0;
00025
00026
00027
00028 int grid_inc = 0;
00029
00030 Grid * grid[MAX_GRIDS];
00031
00032 #define POWER_MODULUS 25 // Controls how often we see a packet
00033
00034
00035
00036
00037
00038
00039
00040 void
00041 power_time_step ()
00042 {
00043 int gi;
00044 int net;
00045
00046 if (grid_num == 0)
00047 return;
00048
00049 for (gi = 1; gi <= grid_num; gi++) {
00050 grid[gi]->total_power = grid[gi]->avail_power -
00051 (grid[gi]->power_lines * POWER_LINE_LOSS);
00052
00053 net = (grid[gi]->total_power - grid[gi]->demand);
00054 if (net < 0)
00055 grid[gi]->powered = -1;
00056 else if (net < (grid[gi]->avail_power / 4))
00057 grid[gi]->powered = 0;
00058 else
00059 grid[gi]->powered = 1;
00060
00061 grid[gi]->avail_power = 0;
00062 grid[gi]->demand = 0;
00063 }
00064
00065
00066 for (gi = 0; gi < numof_substations; gi++)
00067 MP_INFO(substationx[gi],substationy[gi]).int_5 = 0;
00068 }
00069
00070
00071 void
00072 map_power_grid ()
00073 {
00074 int mapx, mapy;
00075 grid_num = 0;
00076 grid_inc++;
00077
00078 for (mapx = 0; mapx < WORLD_SIDE_LEN; mapx++) {
00079 for (mapy = 0; mapy < WORLD_SIDE_LEN; mapy++) {
00080 if (XY_IS_GRID(mapx,mapy)) {
00081 if (MP_INFO(mapx,mapy).int_7 != grid_inc) {
00082 if (grid_num == MAX_GRIDS) {
00083 printf("You have too many power grids. Join some of them\n");
00084 return;
00085 }
00086 grid[++grid_num] = (Grid *)lcalloc(sizeof(Grid));
00087 grid[grid_num]->total_power = 0;
00088 grid[grid_num]->power_lines = 0;
00089 grid[grid_num]->demand = 0;
00090 grid[grid_num]->max_power = 0;
00091
00092 recurse_power_grid(mapx,mapy,0);
00093 }
00094 }
00095 }
00096 }
00097 #ifdef DEBUG_POWER
00098 printf("grid_inc: %d found %d grids\n",grid_inc, grid_num);
00099 #endif
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 int
00115 check_grid(int x, int y, int xi, int yi)
00116 {
00117 if (XY_IS_GRID(x,y) && !IS_OLD_WINDMILL(x,y)) {
00118 if (GRID_CURRENT(x,y)) {
00119 if (MP_INFO(x,y).int_6 != grid_num)
00120
00121
00122
00123
00124
00125 printf("recurse_power_grid insane: %d, %d on a different grid!\n",
00126 x,y);
00127 } else if (!IS_POWER_LINE(x,y)) {
00128 if (IS_POWER_SOURCE(x,y)) {
00129 project_power(x,y);
00130 grid[grid_num]->total_power += MP_INFO(x,y).int_1;
00131 }
00132
00133 MP_INFO(x,y).int_6 = grid_num;
00134 MP_INFO(x,y).int_7 = grid_inc;
00135
00136 } else
00137 return 1;
00138 } else if (XY_IS_TRANSPORT(x,y) || XY_IS_WATER(x,y)) {
00139 if (xi == 0 && yi == 0)
00140 return 0;
00141 if (x+xi >= 1 && x+xi < WORLD_SIDE_LEN &&
00142 y+yi >= 1 && y+yi < WORLD_SIDE_LEN)
00143 return (check_grid(x+xi,y+yi,0,0) ? 2 : 0);
00144 else
00145 return 0;
00146 }
00147
00148 return 0;
00149 }
00150
00151
00152
00153
00154
00155 void
00156 recurse_power_grid (int startx, int starty, int steps)
00157 {
00158 static int level;
00159 int count = steps;
00160 short dir = -1;
00161 int mapx = startx, mapy = starty;
00162 int inc;
00163
00164 level++;
00165
00166 if (count % POWER_MODULUS == 0)
00167 count = 0;
00168
00169
00170
00171
00172
00173
00174 if (IS_OLD_WINDMILL(mapx, mapy)) {
00175 MP_INFO(mapx,mapy).int_6 = grid_num;
00176 MP_INFO(mapx,mapy).int_7 = grid_inc;
00177
00178 grid[grid_num]->max_power += MP_INFO(mapx,mapy).int_1;
00179
00180 level--;
00181 return;
00182 }
00183
00184
00185
00186
00187 while (dir != 0) {
00188
00189
00190
00191
00192 if (IS_POWER_LINE(mapx,mapy)) {
00193 grid[grid_num]->power_lines++;
00194 MP_INFO(mapx,mapy).int_5 = (count++ % POWER_MODULUS);
00195 if ((MP_TYPE(mapx,mapy) >= 1) && (MP_TYPE(mapx,mapy) <= 11))
00196 MP_TYPE(mapx,mapy) += 11;
00197
00198
00199 }
00200
00201 MP_INFO(mapx,mapy).int_6 = grid_num;
00202 MP_INFO(mapx,mapy).int_7 = grid_inc;
00203
00204
00205
00206
00207
00208
00209
00210 if (mapx >= 1)
00211 if (inc = check_grid(mapx - 1, mapy, -1, 0))
00212 if (dir < 1)
00213 dir = WEST;
00214 else
00215 recurse_power_grid(mapx - inc, mapy, count + 1);
00216
00217
00218
00219 if (mapy >= 1)
00220 if (inc = check_grid(mapx, mapy - 1, 0, -1))
00221 if (dir < 1)
00222 dir = NORTH;
00223 else
00224 recurse_power_grid(mapx, mapy - inc, count + 1);
00225
00226
00227
00228 if (mapx < WORLD_SIDE_LEN)
00229 if (inc = check_grid(mapx + 1, mapy, 1, 0))
00230 if (dir < 1)
00231 dir = EAST;
00232 else
00233 recurse_power_grid(mapx + inc, mapy, count + 1);
00234
00235
00236
00237 if (mapy < WORLD_SIDE_LEN)
00238 if (inc = check_grid(mapx, mapy + 1, 0, 1))
00239 if (dir < 1)
00240 dir = SOUTH;
00241 else
00242 recurse_power_grid(mapx, mapy + inc, count + 1);
00243
00244
00245
00246 switch (dir) {
00247 case (-1):
00248 {
00249 dir = 0;
00250 } break;
00251 case WEST:
00252 {
00253 if (mapx >= 1)
00254 if (inc = check_grid(mapx - 1, mapy, -1, 0)) {
00255 mapx -= inc;
00256 dir = -1;
00257 } else
00258 dir = 0;
00259 } break;
00260
00261 case NORTH:
00262 {
00263 if (mapy >= 1)
00264 if (inc = check_grid(mapx, mapy - 1, 0, -1)) {
00265 mapy -= inc;
00266 dir = -1;
00267 } else
00268 dir = 0;
00269 } break;
00270
00271 case EAST:
00272 {
00273 if (mapx < WORLD_SIDE_LEN)
00274 if (inc = check_grid(mapx + 1, mapy, 1, 0)) {
00275 mapx += inc;
00276 dir = -1;
00277 } else
00278 dir = 0;
00279 } break;
00280
00281 case SOUTH:
00282 { if (mapy < WORLD_SIDE_LEN)
00283 if (inc = check_grid(mapx, mapy + 1, 0, 1)) {
00284 mapy += inc;
00285 dir = -1;
00286 } else
00287 dir = 0;
00288 } break;
00289 }
00290 }
00291
00292 level--;
00293
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 void
00303 project_power(int mapx, int mapy)
00304 {
00305 switch (MP_GROUP(mapx,mapy)) {
00306 case GROUP_COAL_POWER:
00307 {
00308 grid[grid_num]->max_power += MP_INFO(mapx,mapy).int_1;
00309 } break;
00310 case GROUP_SOLAR_POWER:
00311 {
00312 grid[grid_num]->max_power += MP_INFO(mapx,mapy).int_3;
00313 } break;
00314 case GROUP_WINDMILL:
00315 {
00316 grid[grid_num]->max_power += MP_INFO(mapx,mapy).int_1;
00317 } break;
00318 default:
00319 {
00320 printf("default case in project_power");
00321 printf("\tMP_GROUP = %d\n",MP_GROUP(mapx,mapy));
00322 } break;
00323 }
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333 int
00334 get_power (int x, int y, int power, int block_industry)
00335 {
00336
00337 int i;
00338 int xi, yi;
00339 int grid_tmp;
00340
00341 if (numof_substations == 0)
00342 return(0);
00343
00344 for (i = 0; i < numof_substations; i++)
00345 {
00346 xi = substationx[i];
00347 yi = substationy[i];
00348 if (abs (xi - x) < SUBSTATION_RANGE &&
00349 abs (yi - y) < SUBSTATION_RANGE) {
00350
00351 if (block_industry != 0 && MP_GROUP(xi, yi) == GROUP_WINDMILL)
00352 continue;
00353
00354 grid_tmp = MP_INFO(xi,yi).int_6;
00355
00356 grid[grid_tmp]->demand += power;
00357 if (grid[grid_tmp]->total_power >= power) {
00358 grid[grid_tmp]->total_power -= power;
00359 MP_INFO(xi,yi).int_5 += power;
00360 return 1;
00361 }
00362
00363 }
00364 }
00365 return 0;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 void
00377 do_power_substation (int x, int y)
00378 {
00379 switch(grid[MP_INFO(x,y).int_6]->powered) {
00380 case -1: {
00381 MP_TYPE(x,y) = CST_SUBSTATION_R;
00382 } break;
00383 case 0 : {
00384 MP_TYPE(x,y) = CST_SUBSTATION_RG;
00385 } break;
00386 case 1 : {
00387 MP_TYPE(x,y) = CST_SUBSTATION_G;
00388 } break;
00389 default : {
00390 printf("Default case in do_power_substation\n");
00391 } break;
00392 }
00393 }
00394
00395 int
00396 add_a_substation (int x, int y)
00397 {
00398 if (numof_substations >= MAX_NUMOF_SUBSTATIONS)
00399 return (0);
00400 substationx[numof_substations] = x;
00401 substationy[numof_substations] = y;
00402 numof_substations++;
00403 return (1);
00404 }
00405
00406 void
00407 remove_a_substation (int x, int y)
00408 {
00409 int q;
00410 for (q = 0; q < numof_substations; q++)
00411 if (substationx[q] == x && substationy[q] == y)
00412 break;
00413 for (; q < numof_substations; q++)
00414 {
00415 substationx[q] = substationx[q + 1];
00416 substationy[q] = substationy[q + 1];
00417 }
00418 numof_substations--;
00419 }
00420
00421 void
00422 shuffle_substations (void)
00423 {
00424 int q, x, r, m;
00425 m = (numof_substations / 2) + 1;
00426 for (x = 0; x < m; x++)
00427 {
00428 r = rand () % numof_substations;
00429 if (r == x)
00430 continue;
00431 q = substationx[x];
00432 substationx[x] = substationx[r];
00433 substationx[r] = q;
00434 q = substationy[x];
00435 substationy[x] = substationy[r];
00436 substationy[r] = q;
00437 }
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 void
00452 do_windmill (int x, int y)
00453 {
00454 int anim_tile;
00455
00456 if (get_jobs (x, y, WINDMILL_JOBS) != 0) {
00457 MP_INFO(x,y).int_5 = MP_INFO(x,y).int_1;
00458 grid[MP_INFO(x,y).int_6]->avail_power += MP_INFO(x,y).int_1;
00459 } else {
00460 MP_INFO(x,y).int_4 = real_time + MODERN_WINDMILL_ANIM_SPEED;
00461 return;
00462 }
00463
00464
00465 if (real_time > MP_INFO(x,y).int_4) {
00466 MP_INFO(x,y).int_3++;
00467 if (MP_INFO(x,y).int_2 < MODERN_WINDMILL_TECH) {
00468 MP_INFO(x,y).int_4 = real_time + ANTIQUE_WINDMILL_ANIM_SPEED;
00469 } else {
00470 MP_INFO(x,y).int_4 = real_time + MODERN_WINDMILL_ANIM_SPEED;
00471 }
00472 }
00473
00474
00475 anim_tile = (MP_INFO(x,y).int_3 % 3);
00476
00477 if (MP_INFO(x,y).int_2 < MODERN_WINDMILL_TECH)
00478 MP_TYPE(x,y) = CST_WINDMILL_1_W + anim_tile;
00479 else
00480 switch(grid[MP_INFO(x,y).int_6]->powered)
00481 {
00482 case -1:
00483 MP_TYPE(x,y) = CST_WINDMILL_1_R + anim_tile;
00484 break;
00485 case 0 :
00486 MP_TYPE(x,y) = CST_WINDMILL_1_RG + anim_tile;
00487 break;
00488 case 1 :
00489 MP_TYPE(x,y) = CST_WINDMILL_1_G + anim_tile;
00490 break;
00491 default :
00492 printf("Default case in do_power_substation\n");
00493 break;
00494 }
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 void
00512 do_power_source (int x, int y)
00513 {
00514 if (get_jobs(x, y, SOLAR_POWER_JOBS)) {
00515 MP_INFO(x,y).int_5 = MP_INFO(x,y).int_3;
00516 grid[MP_INFO(x,y).int_6]->avail_power += MP_INFO(x,y).int_3;
00517 } else {
00518 MP_INFO(x,y).int_5 = 0;
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 void
00534 do_power_source_coal (int x, int y)
00535 {
00536
00537
00538 if (MP_INFO(x,y).int_2 < MAX_COAL_AT_POWER_STATION) {
00539
00540
00541 if (XY_IS_TRANSPORT(x-1, y+1) && MP_INFO(x-1, y+1).int_3 > 0) {
00542 if (get_jobs (x, y, JOBS_LOAD_COAL) != 0)
00543 {
00544 MP_INFO(x,y).int_2 += (MP_INFO(x-1, y+1).int_3 / 2
00545 + ((MP_INFO(x-1, y+1).int_3) % 2));
00546 MP_INFO(x-1, y+1).int_3 /= 2;
00547 MP_POL(x,y)++;
00548 }
00549 }
00550
00551 else if (XY_IS_TRANSPORT(x+1, y-1) && MP_INFO(x+1, y-1).int_3 > 0) {
00552 if (get_jobs (x, y, JOBS_LOAD_COAL) != 0)
00553 MP_INFO(x,y).int_2 += (MP_INFO(x+1, y-1).int_3 / 2
00554 + ((MP_INFO(x+1, y-1).int_3) % 2));
00555 MP_INFO(x + 1,y - 1).int_3 /= 2;
00556 MP_POL(x,y)++;
00557 }
00558 }
00559
00560
00561 if ((MP_INFO(x,y).int_3 + JOBS_COALPS_GENERATE + 10)
00562 < MAX_JOBS_AT_COALPS)
00563 if (get_jobs (x, y, JOBS_COALPS_GENERATE + 10) != 0)
00564 MP_INFO(x,y).int_3 += JOBS_COALPS_GENERATE + 10;
00565
00566
00567 if (MP_INFO(x,y).int_2 > POWERS_COAL_OUTPUT / 500 &&
00568 MP_INFO(x,y).int_3 > JOBS_COALPS_GENERATE)
00569 {
00570 MP_INFO(x,y).int_5 = MP_INFO(x,y).int_1;
00571 MP_INFO(x,y).int_3 -= JOBS_COALPS_GENERATE;
00572 MP_INFO(x,y).int_2 -= POWERS_COAL_OUTPUT / 500;
00573 coal_used += POWERS_COAL_OUTPUT / 500;
00574 MP_POL(x,y) += POWERS_COAL_POLLUTION;
00575 grid[MP_INFO(x,y).int_6]->avail_power += MP_INFO(x,y).int_1;
00576 }
00577
00578
00579
00580 if (MP_INFO(x,y).int_2 > (MAX_COAL_AT_POWER_STATION
00581 - (MAX_COAL_AT_POWER_STATION / 5)))
00582 MP_TYPE(x,y) = CST_POWERS_COAL_FULL;
00583 else if (MP_INFO(x,y).int_2 > (MAX_COAL_AT_POWER_STATION / 2))
00584 MP_TYPE(x,y) = CST_POWERS_COAL_MED;
00585 else if (MP_INFO(x,y).int_2 > (MAX_COAL_AT_POWER_STATION / 10))
00586 MP_TYPE(x,y) = CST_POWERS_COAL_LOW;
00587 else
00588 MP_TYPE(x,y) = CST_POWERS_COAL_EMPTY;
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598 void
00599 do_power_line (int x, int y)
00600 {
00601 if (grid[MP_INFO(x,y).int_6]->powered == -1)
00602 return;
00603
00604 switch(MP_INFO(x,y).int_5)
00605 {
00606 case 0:
00607 MP_INFO(x,y).int_5 = POWER_MODULUS;
00608 break;
00609 case 1:
00610 if (!(MP_TYPE(x,y) <= 11 && MP_TYPE(x,y) >= 1))
00611 break;
00612 MP_TYPE(x,y) += 11;
00613 break;
00614 case 2:
00615 if (!(MP_TYPE(x,y) >= 11 && MP_TYPE(x,y) <= 22))
00616 break;
00617 MP_TYPE(x,y) -= 11;
00618 break;
00619 }
00620
00621 MP_INFO(x,y).int_5--;
00622 }