123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113 |
- /*
- * Seven Kingdoms: Ancient Adversaries
- *
- * Copyright 1997,1998 Enlight Software Ltd.
- *
- * 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 2 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 <http://www.gnu.org/licenses/>.
- *
- */
- // Filename : OW_WALL.CPP
- // Description : class World for building wall
- // Ownership : Gilbert
- #include <OWORLD.h>
- #include <OMATRIX.h>
- #include <WALLTILE.h>
- #include <OWALLRES.h>
- #include <OTOWN.h>
- #include <OREMOTE.h>
- #include <ONATIONA.h>
- #define WALL_GROWTH_RATE 6
- //--------------- begin of function World::can_build_area ----------//
- int World::can_build_area(short x1, short y1, short x2, short y2)
- {
- int x,y;
- err_when(x1 > x2 || y1 > y2);
- for(y = y1; y <= y2; ++y)
- for( x = x1; x <= x2; ++x)
- if( ! get_loc(x,y)->can_build_wall())
- return FALSE;
- return TRUE;
- }
- //--------------- end of function World::can_build_area ----------//
- //--------------- begin of function World::build_wall ----------//
- void World::build_wall(int townRecno, short initHp)
- {
- Town* townPtr = town_array[townRecno];
- int xLoc1 = max(0, townPtr->loc_x1-WALL_SPACE_LOC);
- int yLoc1 = max(0, townPtr->loc_y1-WALL_SPACE_LOC);
- int xLoc2 = min(MAX_WORLD_X_LOC-1, townPtr->loc_x2+WALL_SPACE_LOC);
- int yLoc2 = min(MAX_WORLD_Y_LOC-1, townPtr->loc_y2+WALL_SPACE_LOC);
- //--------------- build city wall -------------//
- build_wall_section(xLoc1, yLoc1, xLoc2, yLoc2, townRecno, initHp);
- }
- //--------------- end of function World::build_wall ----------//
- //--------------- begin of function World::build_wall_section ----------//
- void World::build_wall_section(short x1, short y1, short x2, short y2,
- short townRecno, short initHp)
- {
- //--------- build west wall -----------//
- Location *locPtr;
- short westWallFirst;
- for( westWallFirst = y1; westWallFirst < y2; ++westWallFirst)
- {
- if( get_loc(x1,westWallFirst)->can_build_wall() )
- {
- //--------- find place for the west gate ---------//
- if( x1 >= GATE_WIDTH-1 && y2-y1 >= GATE_LENGTH)
- {
- //----- try from the middle, and then butterfly outward ---//
- short increment = 0;
- short trial, westGateY;
- for( trial=y2-y1-GATE_LENGTH, westGateY=y1+(trial+1)/2;
- trial > 0; --trial, westGateY += increment)
- {
- if(can_build_area(x1-GATE_WIDTH+1, westGateY,
- x1, westGateY+GATE_LENGTH-1) )
- {
- //-------- put west gate --------- //
- build_west_gate(x1-GATE_WIDTH+1, westGateY, townRecno, initHp);
- break;
- }
- increment = -increment;
- if( increment >= 0)
- ++increment;
- else
- --increment;
- }
- //---------- put other wall ----------//
- build_west_wall(x1, y1, y2, townRecno, initHp);
- //--------- open west gate ----------//
- open_west_gate(x1, westGateY, townRecno);
- }
- else
- {
- //-------- x1 too small for gate -------//
- get_loc(x1,westWallFirst)->set_wall(NTOWER, townRecno, initHp);
- get_loc(x1,westWallFirst)->set_fire_src(-50);
- }
- break;
- }
- }
- //--------- build east wall -----------
- short eastWallFirst;
- for( eastWallFirst = y1; eastWallFirst < y2; ++eastWallFirst)
- {
- if( get_loc(x2, eastWallFirst)->can_build_wall())
- {
- //---------- find place for the gate --------- //
- if( x2 <= max_x_loc - GATE_WIDTH +1 && y2-y1 >= GATE_LENGTH)
- {
- //---- try from the middle, and then butterfly outward ----//
- short increment = 0;
- short trial, eastGateY;
- for( trial=y2-y1-GATE_LENGTH, eastGateY=y1+(trial+1)/2;
- trial > 0; --trial, eastGateY += increment)
- {
- if(can_build_area(x2, eastGateY, x2+GATE_WIDTH-1, eastGateY+GATE_LENGTH-1) )
- {
- //----------- put east gate ----------//
- build_east_gate(x2, eastGateY, townRecno, initHp);
- break;
- }
- increment = -increment;
- if( increment >= 0)
- ++increment;
- else
- --increment;
- }
- //-------- put other wall ---------//
- build_east_wall(x2, y1, y2, townRecno, initHp);
- //--------- open east gate ----------//
- open_east_gate(x2, eastGateY, townRecno);
- }
- else
- {
- //------- x2 too big for gate ---------//
- get_loc(x2,eastWallFirst)->set_wall(NETOWER, townRecno, initHp);
- get_loc(x2,eastWallFirst)->set_fire_src(-50);
- }
- break;
- }
- }
- //--------- build north wall -----------//
- short northWallFirst;
- for( northWallFirst = x1; northWallFirst < x2; ++northWallFirst)
- {
- if( (locPtr = get_loc(northWallFirst, y1))->can_build_wall() ||
- ( locPtr->is_wall() && locPtr->wall_town_recno() == townRecno) )
- {
- //-------- find place for the north gate --------//
- if( y1 >= GATE_WIDTH-1 && x2-x1 >= GATE_LENGTH)
- {
- //------- try from the middle, and then butterfly outward -------//
- short increment = 0;
- short trial, northGateX;
- for( trial=x2-x1-GATE_LENGTH, northGateX=x1+(trial+1)/2;
- trial > 0; --trial, northGateX += increment)
- {
- if(can_build_area(northGateX, y1-GATE_WIDTH+1,
- northGateX+GATE_LENGTH-1, y1) )
- {
- //--------------- put north gate ----------------//
- build_north_gate(northGateX, y1-GATE_WIDTH+1, townRecno, initHp);
- break;
- }
- increment = -increment;
- if( increment >= 0)
- ++increment;
- else
- --increment;
- }
- //----------- put other wall --------------//
- build_north_wall(x1, x2, y1, townRecno, initHp);
- //--------- open north gate ----------//
- open_north_gate(northGateX, y1, townRecno);
- }
- else
- {
- //------------ y1 too small for gate -----------//
- if(locPtr->can_build_wall() )
- {
- locPtr->set_wall(NTOWER, townRecno, initHp);
- locPtr->set_fire_src(-50);
- }
- }
- break;
- }
- }
- //--------- build south wall -----------
- short southWallFirst;
- for( southWallFirst = x1; southWallFirst < x2; ++southWallFirst)
- {
- if( (locPtr = get_loc(southWallFirst, y2))->can_build_wall() ||
- ( locPtr->is_wall() && locPtr->wall_town_recno() == townRecno) )
- {
- //---------- find place for the south gate ----------//
- if( y2 <= max_y_loc-GATE_WIDTH+1 && x2-x1 >= GATE_LENGTH)
- {
- //----- try from the middle, and then butterfly outward ----//
- short increment = 0;
- short trial, southGateX;
- for( trial=x2-x1-GATE_LENGTH, southGateX=x1+(trial+1)/2;
- trial > 0; --trial, southGateX += increment)
- {
- if(can_build_area(southGateX, y2,
- southGateX+GATE_LENGTH-1, y2+GATE_WIDTH-1) )
- {
- //----------- put south gate -------------//
- build_south_gate(southGateX, y2, townRecno, initHp);
- break;
- }
- increment = -increment;
- if( increment >= 0)
- ++increment;
- else
- --increment;
- }
- //----------- put other wall -------------//
- build_south_wall(x1, x2, y2, townRecno, initHp);
- //--------- open north gate ----------//
- open_south_gate(southGateX, y2, townRecno);
- }
- else
- {
- //---------- y2 too big for gate ----------//
- if(locPtr->can_build_wall() )
- {
- locPtr->set_wall(STOWER, townRecno, initHp);
- locPtr->set_fire_src(-50);
- }
- }
- break;
- }
- }
- }
- //--------------- end of function World::build_wall_section ----------//
- //--------------- begin of function World::build_west_gate ----------//
- void World::build_west_gate(short x1, short y1, short townRecno, short initHp)
- {
- //--------- put two gate towers -----------//
- Location *locPtr = get_loc(x1,y1);
- locPtr->set_wall(WGATE_NTOWER_NW, townRecno, initHp);
- (locPtr+1)->set_wall(WGATE_NTOWER_NE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1, y1+1);
- locPtr->set_wall(WGATE_NTOWER_SW, townRecno, initHp);
- (locPtr+1)->set_wall(WGATE_NTOWER_SE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1,y1+GATE_LENGTH-2);
- locPtr->set_wall(WGATE_STOWER_NW, townRecno, initHp);
- (locPtr+1)->set_wall(WGATE_STOWER_NE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1, y1+GATE_LENGTH-1);
- locPtr->set_wall(WGATE_STOWER_SW, townRecno, initHp);
- (locPtr+1)->set_wall(WGATE_STOWER_SE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- //---------- put gate -----------//
- char gateId = WGATE_BASE;
- for(short y = 2; y < GATE_LENGTH-2; ++y)
- {
- locPtr = get_loc(x1, y1+y);
- for(short x = 0; x < GATE_WIDTH; ++x, ++locPtr)
- {
- locPtr->set_wall(gateId++, townRecno, initHp);
- locPtr->set_fire_src(-50);
- }
- }
- }
- //--------------- end of function World::build_west_gate ----------//
- //--------------- begin of function World::build_west_wall ----------//
- void World::build_west_wall(short x1, short y1, short y2, short townRecno,
- short initHp)
- {
- //---------- find segments of buildable terrain ---------//
- short startY = y1, endY = y1;
- while(startY <= y2)
- {
- for( ; startY <= y2 && !get_loc(x1,startY)->can_build_wall(); ++startY);
- if( startY <= y2) // a place is found
- {
- //-------- found segment end -----------//
- for( endY = startY+1; endY <= y2 && get_loc(x1,endY)->can_build_wall() ;++endY);
- --endY;
-
- if( startY == endY)
- {
- //------- equal square, draw a single tower --------//
- get_loc(x1, startY)->set_wall(SINGLE_TOWER, townRecno, initHp);
- get_loc(x1, startY)->set_fire_src(-50);
- }
- else
- {
- short startSquare = NTOWER;
- short endSquare = STOWER;
- // if startY-1 is a wall, hence a gate, start with a wall with shadow
- if( startY > y1 && get_loc(x1, startY-1)->is_wall() )
- {
- startSquare = NSWALL_SHADOW;
- }
- // if endY+1 is a wall, hence a gate, start with a wall
- if( endY < y2 && get_loc(x1, endY+1)->is_wall() )
- {
- endSquare = NSWALL;
- }
- for( short y = startY; y < endY; ++y)
- {
- get_loc(x1, y)->set_wall(startSquare, townRecno, initHp);
- get_loc(x1, y)->set_fire_src(-50);
- switch(startSquare)
- {
- case NTOWER:
- startSquare = NSWALL_SHADOW;
- break;
- case NSWALL_SHADOW:
- startSquare = NSWALL;
- break;
- // otherwise unchange
- }
- }
- get_loc(x1, endY)->set_wall(endSquare, townRecno, initHp);
- get_loc(x1, endY)->set_fire_src(-50);
- }
- startY = endY +1;
- }
- }
- }
- //--------------- end of function World::build_west_wall ----------//
- //--------------- begin of function World::open_west_gate ----------//
- void World::open_west_gate(short x2, short y1, short townRecno)
- {
- //------ check if any west gate tile is built ---------//
- Location *locPtr = get_loc(x2,y1+2);
- if( locPtr->is_wall() && locPtr->wall_id() == WGATE_N &&
- locPtr->wall_town_recno() == townRecno)
- {
- for(short y = 3; y < GATE_LENGTH-3; ++y)
- for(short x = 0; x < GATE_WIDTH; ++x)
- get_loc(x2-x, y1+y)->remove_wall();
- }
- }
- //--------------- end of function World::open_west_gate ----------//
- //--------------- begin of function World::build_east_gate ----------//
- void World::build_east_gate(short x1, short y1, short townRecno, short initHp)
- {
- //---------- put two gate towers ----------//
- Location *locPtr = get_loc(x1,y1);
- locPtr->set_wall(EGATE_NTOWER_NW, townRecno, initHp);
- (locPtr+1)->set_wall(EGATE_NTOWER_NE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1, y1+1);
- locPtr->set_wall(EGATE_NTOWER_SW, townRecno, initHp);
- (locPtr+1)->set_wall(EGATE_NTOWER_SE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1,y1+GATE_LENGTH-2);
- locPtr->set_wall(EGATE_STOWER_NW, townRecno, initHp);
- (locPtr+1)->set_wall(EGATE_STOWER_NE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1, y1+GATE_LENGTH-1);
- locPtr->set_wall(EGATE_STOWER_SW, townRecno, initHp);
- (locPtr+1)->set_wall(EGATE_STOWER_SE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- //------------- put gate ----------------//
- char gateId = EGATE_BASE;
- for(short y = 2; y < GATE_LENGTH-2; ++y)
- {
- locPtr = get_loc(x1, y+y1);
- for(short x = 0; x < GATE_WIDTH; ++x, ++locPtr)
- {
- locPtr->set_wall(gateId++, townRecno, initHp);
- locPtr->set_fire_src(-50);
- }
- }
- }
- //--------------- end of function World::build_east_gate ----------//
- //--------------- begin of function World::build_east_wall ----------//
- void World::build_east_wall(short x1, short y1, short y2, short townRecno,
- short initHp)
- {
- //--------- find segments of buildable terrain ---------//
- short startY = y1, endY = y1;
- while(startY <= y2)
- {
- for( ; startY <= y2 && !get_loc(x1,startY)->can_build_wall(); ++startY);
- if( startY <= y2) // a place is found
- {
- //-------- found segment end -------------//
- for( endY = startY+1; endY <= y2 && get_loc(x1,endY)->can_build_wall() ;++endY);
- --endY;
-
- if( startY == endY)
- {
- //----------- equal square, draw a single tower --------//
- get_loc(x1, startY)->set_wall(SINGLE_TOWER, townRecno, initHp);
- get_loc(x1, startY)->set_fire_src(-50);
- }
- else
- {
- short startSquare = NTOWER;
- short endSquare = STOWER;
- // if startY-1 is a wall, hence a gate, start with a wall with shadow
- if( startY > y1 && get_loc(x1, startY-1)->is_wall() )
- {
- startSquare = NSWALL_SHADOW;
- }
- // if endY+1 is a wall, hence a gate, start with a wall
- if( endY < y2 && get_loc(x1, endY+1)->is_wall() )
- {
- endSquare = NSWALL;
- }
- for( short y = startY; y < endY; ++y)
- {
- get_loc(x1, y)->set_wall(startSquare, townRecno, initHp);
- get_loc(x1, y)->set_fire_src(-50);
- switch(startSquare)
- {
- case NTOWER:
- startSquare = NSWALL_SHADOW;
- break;
- case NSWALL_SHADOW:
- startSquare = NSWALL;
- break;
- // otherwise unchange
- }
- }
- get_loc(x1, endY)->set_wall(endSquare, townRecno, initHp);
- get_loc(x1, endY)->set_fire_src(-50);
- }
- startY = endY +1;
- }
- }
- }
- //--------------- end of function World::build_east_wall ----------//
- //--------------- begin of function World::open_east_gate ----------//
- void World::open_east_gate(short x1, short y1, short townRecno)
- {
- //------ check if any east gate tile is built ---------//
- Location *locPtr = get_loc(x1,y1+2);
- if( locPtr->is_wall() && locPtr->wall_id() == EGATE_N &&
- locPtr->wall_town_recno() == townRecno)
- {
- for(short y = 3; y < GATE_LENGTH-3; ++y)
- for(short x = 0; x < GATE_WIDTH; ++x)
- get_loc(x1+x, y1+y)->remove_wall();
- }
- }
- //--------------- end of function World::open_east_gate ----------//
- //--------------- begin of function World::build_north_gate ----------//
- void World::build_north_gate(short x1, short y1, short townRecno,
- short initHp)
- {
- //---------- put two gate towers -----------//
- Location *locPtr = get_loc(x1,y1);
- locPtr->set_wall(NGATE_WTOWER_NW, townRecno, initHp);
- (locPtr+1)->set_wall(NGATE_WTOWER_NE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1+GATE_LENGTH-2, y1);
- locPtr->set_wall(NGATE_ETOWER_NW, townRecno, initHp);
- (locPtr+1)->set_wall(NGATE_ETOWER_NE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1,y1+1);
- locPtr->set_wall(NGATE_WTOWER_SW, townRecno, initHp);
- (locPtr+1)->set_wall(NGATE_WTOWER_SE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1+GATE_LENGTH-2, y1+1);
- locPtr->set_wall(NGATE_ETOWER_SW, townRecno, initHp);
- (locPtr+1)->set_wall(NGATE_ETOWER_SE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- //------------ put gate -------------//
- char gateId = NGATE_BASE;
- for(short y = 0; y < GATE_WIDTH; ++y)
- {
- locPtr = get_loc(x1+2, y1+y);
- for(short x = 2; x < GATE_LENGTH-2; ++x, ++locPtr)
- {
- locPtr->set_wall(gateId++, townRecno, initHp);
- locPtr->set_fire_src(-50);
- }
- }
- }
- //--------------- end of function World::build_north_gate ----------//
- //--------------- begin of function World::build_north_wall ----------//
- void World::build_north_wall(short x1, short x2, short y1, short townRecno,
- short initHp)
- {
- //---------- find segments of buildable terrain ---------//
- short startX = x1, endX = x1;
- while(startX <= x2)
- {
- for( ; startX <= x2 && !get_loc(startX, y1)->can_build_wall(); ++startX);
- if( startX <= x2) // a place is found
- {
- //--------- found segment end ----------//
- for( endX = startX+1; endX <= x2 && get_loc(endX, y1)->can_build_wall() ;++endX);
- --endX;
-
- if( startX == endX)
- {
- //---------- equal square, draw a single tower ---------//
- get_loc(startX, y1)->set_wall(SINGLE_TOWER, townRecno, initHp);
- get_loc(startX, y1)->set_fire_src(-50);
- }
- else
- {
- short startSquare = WTOWER;
- short endSquare = ETOWER;
- // if startX-1 is a wall, hence a gate, start with a wall with shadow
- if( startX > x1 && get_loc(startX-1, y1)->is_wall() )
- {
- startSquare = EWWALL_SHADOW;
- // if startX-1 is a NTOWER (corner) , change it to NWTOWER
- Location *leftLoc;
- if( (leftLoc = get_loc(startX-1, y1))->wall_id() == NTOWER
- && leftLoc->wall_town_recno() == townRecno )
- {
- leftLoc->remove_wall();
- leftLoc->set_wall(NWTOWER, townRecno, initHp);
- }
- }
- // if endX+1 is a wall, hence a gate, start with a wall
- if( endX < x2 && get_loc(endX+1, y1)->is_wall() )
- {
- endSquare = EWWALL;
- // if endX+1 is a NTOWER (corner) , change it to NETOWER
- Location *rightLoc;
- if( (rightLoc = get_loc(endX+1,y1))->wall_id() == NTOWER
- && rightLoc->wall_town_recno() == townRecno)
- {
- rightLoc->remove_wall();
- rightLoc->set_wall(NETOWER, townRecno, initHp);
- }
- }
- for( short x = startX; x < endX; ++x)
- {
- get_loc(x, y1)->set_wall(startSquare, townRecno, initHp);
- get_loc(x, y1)->set_fire_src(-50);
- switch(startSquare)
- {
- case WTOWER:
- startSquare = EWWALL_SHADOW;
- break;
- case EWWALL_SHADOW:
- startSquare = EWWALL;
- break;
- // otherwise unchange
- }
- }
- get_loc(endX, y1)->set_wall(endSquare, townRecno, initHp);
- get_loc(endX, y1)->set_fire_src(-50);
- }
- startX = endX +1;
- }
- }
- }
- //--------------- end of function World::build_north_wall ----------//
- //--------------- begin of function World::open_north_gate ----------//
- void World::open_north_gate(short x1, short y2, short townRecno)
- {
- //------ check if any north gate tile is built ---------//
- Location *locPtr = get_loc(x1+2,y2);
- if( locPtr->is_wall() && locPtr->wall_id() == NGATE_W &&
- locPtr->wall_town_recno() == townRecno)
- {
- for(short x = 3; x < GATE_LENGTH-3; ++x)
- for(short y = 0; y < GATE_WIDTH; ++y)
- get_loc(x1+x, y2-y)->remove_wall();
- }
- }
- //--------------- end of function World::open_north_gate ----------//
- //--------------- begin of function World::build_south_gate ----------//
- void World::build_south_gate(short x1, short y1, short townRecno, short initHp)
- {
- //---------- put two gate towers ----------//
- Location *locPtr = get_loc(x1,y1);
- locPtr->set_wall(SGATE_WTOWER_NW, townRecno, initHp);
- (locPtr+1)->set_wall(SGATE_WTOWER_NE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1+GATE_LENGTH-2, y1);
- locPtr->set_wall(SGATE_ETOWER_NW, townRecno, initHp);
- (locPtr+1)->set_wall(SGATE_ETOWER_NE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1,y1+1);
- locPtr->set_wall(SGATE_WTOWER_SW, townRecno, initHp);
- (locPtr+1)->set_wall(SGATE_WTOWER_SE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- locPtr = get_loc(x1+GATE_LENGTH-2, y1+1);
- locPtr->set_wall(SGATE_ETOWER_SW, townRecno, initHp);
- (locPtr+1)->set_wall(SGATE_ETOWER_SE, townRecno, initHp);
- locPtr->set_fire_src(-50);
- (locPtr+1)->set_fire_src(-50);
- //------------ put gate --------------//
- char gateId = SGATE_BASE;
- for(short y = 0; y < GATE_WIDTH; ++y)
- {
- locPtr = get_loc(x1+2, y1+y);
- for(short x = 2; x < GATE_LENGTH-2; ++x, ++locPtr)
- {
- locPtr->set_wall(gateId++, townRecno, initHp);
- locPtr->set_fire_src(-50);
- }
- }
- }
- //--------------- end of function World::build_south_gate ----------//
- //--------------- begin of function World::build_south_wall ----------//
- void World::build_south_wall(short x1, short x2, short y1, short townRecno,
- short initHp)
- {
- //----------- find segments of buildable terrain -------------//
- short startX = x1, endX = x1;
- while(startX <= x2)
- {
- for( ; startX <= x2 && !get_loc(startX, y1)->can_build_wall(); ++startX);
- if( startX <= x2) // a place is found
- {
- //---------- found segment end ---------//
- for( endX = startX+1; endX <= x2 && get_loc(endX, y1)->can_build_wall() ;++endX);
- --endX;
-
- if( startX == endX)
- {
- //--------- equal square, draw a single tower --------//
- get_loc(startX, y1)->set_wall(SINGLE_TOWER, townRecno, initHp);
- get_loc(startX, y1)->set_fire_src(-50);
- }
- else
- {
- short startSquare = WTOWER;
- short endSquare = ETOWER;
- // if startX-1 is a wall, hence a gate, start with a wall with shadow
- if( startX > x1 && get_loc(startX-1, y1)->is_wall() )
- {
- startSquare = EWWALL_SHADOW;
- // if startX-1 is a STOWER (corner) , change it to SWTOWER
- Location *leftLoc;
- if( (leftLoc = get_loc(startX-1, y1))->wall_id() == STOWER
- && leftLoc->wall_town_recno() == townRecno )
- {
- leftLoc->remove_wall();
- leftLoc->set_wall(SWTOWER, townRecno, initHp);
- }
- }
- // if endY+1 is a wall, hence a gate, start with a wall with shadow
- if( endX < x2 && get_loc(endX+1, y1)->is_wall() )
- {
- endSquare = EWWALL;
- // if endX+1 is a STOWER (corner) , change it to SETOWER
- Location *rightLoc;
- if( (rightLoc = get_loc(endX+1, y1))->wall_id() == STOWER
- && rightLoc->wall_town_recno() == townRecno)
- {
- rightLoc->remove_wall();
- rightLoc->set_wall(SETOWER, townRecno, initHp);
- }
- }
- for( short x = startX; x < endX; ++x)
- {
- get_loc(x, y1)->set_wall(startSquare, townRecno, initHp);
- get_loc(x, y1)->set_fire_src(-50);
- switch(startSquare)
- {
- case WTOWER:
- startSquare = EWWALL_SHADOW;
- break;
- case EWWALL_SHADOW:
- startSquare = EWWALL;
- break;
- // otherwise unchange
- }
- }
- get_loc(endX, y1)->set_wall(endSquare, townRecno, initHp);
- get_loc(endX, y1)->set_fire_src(-50);
- }
- startX = endX +1;
- }
- }
- }
- //--------------- end of function World::build_south_wall ----------//
- //--------------- begin of function World::open_south_gate ----------//
- void World::open_south_gate(short x1, short y1, short townRecno)
- {
- //------ check if any south gate tile is built ---------//
- Location *locPtr = get_loc(x1+2,y1);
- if( locPtr->is_wall() && locPtr->wall_id() == SGATE_W &&
- locPtr->wall_town_recno() == townRecno)
- {
- for(short x = 3; x < GATE_LENGTH-3; ++x)
- for(short y = 0; y < GATE_WIDTH; ++y)
- get_loc(x1+x, y1+y)->remove_wall();
- }
- }
- //--------------- end of function World::open_south_gate ----------//
- //--------------- begin of function World::form_wall -----------//
- //
- // adjust wall tile, return no. of tile changed
- //
- int World::form_wall(short x, short y, short maxRecur)
- {
- Location *locPtr = get_loc(x,y);
- if( !locPtr->is_wall() || maxRecur < 0)
- return 0;
- int wallTile = locPtr->wall_id();
- int blockChanged = 0;
- int flag = 0;
- if( y == 0 || get_loc(x,y-1)->is_wall()) // north square
- flag |= 1;
- if( x == max_x_loc-1 || get_loc(x+1,y)->is_wall() ) // east square
- flag |= 2;
- if( y == max_y_loc-1 || get_loc(x,y+1)->is_wall() ) // south square
- flag |= 4;
- if( x == 0 || get_loc(x-1,y)->is_wall() ) // west square
- flag |= 8;
- int newWallTile, newWallRubble;
- // ------- find new wall tile ---------//
- switch(flag)
- {
- case 0: // no surrounding square is wall
- newWallTile = SINGLE_TOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 1: // only north square is wall
- newWallTile = STOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 2: // only east
- newWallTile = WTOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 3: // north and east
- newWallTile = SWTOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 4: // south only
- newWallTile = NTOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 5: // north and south
- newWallTile = NSWALL;
- if( y > 0 && get_loc(x,y-1)->is_wall() )
- {
- int northWallTile = get_loc(x,y-1)->wall_id();
- if( northWallTile != NSWALL && northWallTile != NSWALL_SHADOW &&
- !is_wall_rubble(northWallTile))
- newWallTile = NSWALL_SHADOW;
- }
- newWallRubble = NSWALL_CON1;
- break;
- case 6: // east and south
- newWallTile = NWTOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 7: // east and north and south
- newWallTile = NWTOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 8: // west only
- newWallTile = ETOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 9: // west and north
- newWallTile = SETOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 10: // west and east
- newWallTile = EWWALL;
- if( x > 0 && get_loc(x-1,y)->is_wall() )
- {
- int westWallTile = get_loc(x-1,y)->wall_id();
- if( westWallTile != EWWALL && westWallTile != EWWALL_SHADOW &&
- !is_wall_rubble(westWallTile) )
- newWallTile = EWWALL_SHADOW;
- }
- newWallRubble = EWWALL_CON1;
- break;
- case 11: // west and east and north
- newWallTile = ETOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 12: // west and south
- newWallTile = NETOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 13: // west and south and north
- newWallTile = NETOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 14: // west and south and east
- newWallTile = NETOWER;
- newWallRubble = TOWER_CON1;
- break;
- case 15: // all four
- newWallTile = NETOWER;
- newWallRubble = TOWER_CON1;
- break;
- }
- // --- adjust newWallTile from wall_grade() ------//
- switch(get_loc(x,y)->wall_grade())
- {
- case 1:
- newWallTile = newWallRubble;
- break;
- case -1:
- newWallTile = newWallRubble + TOWER_DES1 - TOWER_CON1; // e.g. TOWER_CON1 -> TOWER_DES1
- break;
- case 2:
- newWallTile = newWallRubble + 1;
- break;
- case -2:
- newWallTile = newWallRubble + TOWER_DES2 - TOWER_CON1;
- break;
- case 3:
- newWallTile = newWallRubble + 2;
- break;
- case -3:
- newWallTile = newWallRubble + TOWER_DES3 - TOWER_CON1;
- break;
- case 4:
- case -4:
- // no change
- break;
- default:
- err_here();
- }
-
- // --- change wall tile, such as change to tower, add shadow ----//
- if( wallTile != newWallTile)
- {
- locPtr->chg_wall_id(newWallTile);
- blockChanged ++;
- }
-
- // change adjacent sqaure
- if( y > 0 && get_loc(x,y-1)->is_wall() )
- blockChanged += form_wall(x, y-1, maxRecur-1);
- if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
- blockChanged += form_wall(x, y+1, maxRecur-1);
- if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
- blockChanged += form_wall(x+1, y, maxRecur-1);
- if( x > 0 && get_loc(x-1,y)->is_wall() )
- blockChanged += form_wall(x-1, y, maxRecur-1);
- return blockChanged;
- }
- //--------------- end of function World::form_wall -----------//
- //--------------- begin of function World::correct_wall -----------//
- //
- // adjust adjacent wall tiles, return no. of tile changed
- //
- int World::correct_wall(short x, short y, short maxRecur)
- {
- if( maxRecur < 0)
- return 0;
- int blockChanged = 0;
- // change adjacent sqaure
- if( y > 0 && get_loc(x,y-1)->is_wall() )
- blockChanged += form_wall(x, y-1, maxRecur-1);
- if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
- blockChanged += form_wall(x, y+1, maxRecur-1);
- if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
- blockChanged += form_wall(x+1, y, maxRecur-1);
- if( x > 0 && get_loc(x-1,y)->is_wall() )
- blockChanged += form_wall(x-1, y, maxRecur-1);
- return blockChanged;
- }
- //---------- begin of function World::form_world_wall -----//
- void World::form_world_wall()
- {
- static int init_build_wall_seq = 0;
- #define SPACING 12
- static char build_wall_x_seq[SPACING*SPACING];
- static char build_wall_y_seq[SPACING*SPACING];
- static int next_build_wall_seq;
- int x, y;
- if(! init_build_wall_seq )
- {
- init_build_wall_seq = 1;
- DWORD seed = m.get_random_seed();
- // ------ initialize with linear sequence----- //
- for( y = 0; y < SPACING; ++y)
- {
- for( x = 0; x < SPACING; ++x)
- {
- build_wall_x_seq[y*SPACING+x] = x;
- build_wall_y_seq[y*SPACING+x] = y;
- }
- }
- m.set_random_seed(176682233); // hard code
-
- //------- shuffle randomly ----------//
- for(int t = SPACING * SPACING -1; t >= 0; --t)
- {
- int u = m.random(SPACING * SPACING);
- // ----- swap build_wall_x/y_seq[t] with [u]
- char tmp;
- tmp = build_wall_x_seq[t];
- build_wall_x_seq[t] = build_wall_x_seq[u];
- build_wall_x_seq[u] = tmp;
- tmp = build_wall_y_seq[t];
- build_wall_y_seq[t] = build_wall_y_seq[u];
- build_wall_y_seq[u] = tmp;
- }
- next_build_wall_seq = 0;
- m.set_random_seed(seed);
- }
- for(int trial = 7; trial > 0 ; --trial)
- {
- for(y = build_wall_y_seq[next_build_wall_seq]; y < max_y_loc; y+= SPACING)
- {
- for(x = build_wall_x_seq[next_build_wall_seq]; x < max_x_loc; x+= SPACING)
- {
- Location *locPtr = get_loc(x,y);
- // ######## begin Gilbert 7/3 ##########//
- if( locPtr->had_wall() )
- {
- locPtr->dec_wall_timeout();
- }
- else if( locPtr->is_wall())
- // ######## end Gilbert 7/3 ##########//
- {
- int prevGrade = locPtr->wall_grade();
- int newGrade;
- if( locPtr->inc_wall_hit_point(WALL_GROWTH_RATE) == 0)
- {
- locPtr->remove_wall();
- if( y > 0 && get_loc(x,y-1)->is_wall() )
- form_wall(x,y-1, 1);
- if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
- form_wall(x,y+1, 1);
- if( x > 0 && get_loc(x-1,y)->is_wall() )
- form_wall(x-1,y, 1);
- if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
- form_wall(x+1,y, 1);
- }
- else if( prevGrade != (newGrade=locPtr->wall_grade()) )
- {
- form_wall(x,y,2);
- }
- }
- }
- }
- next_build_wall_seq = (next_build_wall_seq+1) % (SPACING*SPACING);
- }
- }
- //---------- end of function World::form_world_wall -----//
- //------- Begin of function World::build_wall_tile -------//
- //
- // <int> xLoc, yLoc - the location on which the wall should be built
- // <int> nationRecno - recno of the builder nation
- //
- // see also ZoomMatrix->draw_build_marker
- //
- void World::build_wall_tile(int xLoc, int yLoc, short nationRecno, char remoteAction)
- {
- Location *locPtr = get_loc(xLoc, yLoc);
- if( can_build_wall(xLoc, yLoc, nationRecno))
- {
- if( !remoteAction && remote.is_enable() )
- {
- // packet structure : <nation recno> <xLoc> <yLoc>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_BUILD, 3*sizeof(short));
- shortPtr[0] = nationRecno;
- shortPtr[1] = xLoc;
- shortPtr[2] = yLoc;
- }
- else
- {
- locPtr->set_wall(TOWER_CON1,nationRecno, 1);
- locPtr->set_fire_src(-50);
- // nation_array[nationRecno]->add_expense( (float)BUILD_WALL_COST );
- }
- }
- else if( locPtr->is_wall_destructing() &&
- can_destruct_wall(xLoc, yLoc, nationRecno))
- {
- if( !remoteAction && remote.is_enable() )
- {
- // packet structure : <nation recno> <xLoc> <yLoc>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_BUILD, 3*sizeof(short));
- shortPtr[0] = nationRecno;
- shortPtr[1] = xLoc;
- shortPtr[2] = yLoc;
- }
- else
- {
- locPtr->set_wall_creating();
- // nation_array[nationRecno]->add_expense( (float)
- // BUILD_WALL_COST * (100-locPtr->wall_abs_hit_point()) / 100 );
- }
- }
- }
- //--------- End of function World::build_wall_tile ---------//
- //------- Begin of function World::destruct_wall_tile -------//
- //
- // <int> xLoc, yLoc - the location on which the wall should be destructed
- // <int> nationRecno - recno of the destructer nation
- //
- // see also ZoomMatrix->draw_build_marker
- //
- void World::destruct_wall_tile(int xLoc, int yLoc, short nationRecno, char remoteAction)
- {
- Location *locPtr = get_loc(xLoc, yLoc);
- if( locPtr->is_wall_creating() && can_destruct_wall(xLoc, yLoc, nationRecno) )
- {
- if( !remoteAction && remote.is_enable() )
- {
- // packet structure : <nation recno> <xLoc> <yLoc>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_DESTRUCT, 3*sizeof(short));
- shortPtr[0] = nationRecno;
- shortPtr[1] = xLoc;
- shortPtr[2] = yLoc;
- }
- else
- {
- locPtr->set_wall_destructing();
- // nation_array[nationRecno]->add_expense( (float) DESTRUCT_WALL_COST );
- }
- }
- }
- //--------- End of function World::destruct_wall_tile ---------//
|