/*
* 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 .
*
*/
// Filename : OW_WALL.CPP
// Description : class World for building wall
// Ownership : Gilbert
#include
#include
#include
#include
#include
#include
#include
#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 -------//
//
// xLoc, yLoc - the location on which the wall should be built
// 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 :
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 :
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 -------//
//
// xLoc, yLoc - the location on which the wall should be destructed
// 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 :
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 ---------//