/*
* 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 : OMATRIX.H
//Description : Object road direction turn
#ifndef __OMATRIX_H
#define __OMATRIX_H
#ifndef __OUNITRES_H
#include
#endif
#include
//----- Define bit meanings Location::flag ------//
#define LOCATE_WALK_LAND 0x01
#define LOCATE_WALK_SEA 0x02
#define LOCATE_COAST 0x08
// ----- govern the usage of extra_para ---------//
#define LOCATE_SITE_MASK 0xf0
#define LOCATE_HAS_SITE 0x10
#define LOCATE_HAD_WALL 0x20
#define LOCATE_HAS_DIRT 0x30
#define LOCATE_SITE_RESERVED 0xf0
// occupied by other block such as hill, plant
// ----- govern the usage of cargo_recno -------//
#define LOCATE_BLOCK_MASK 0xf00
#define LOCATE_IS_HILL 0x100
#define LOCATE_IS_PLANT 0x200
#define LOCATE_IS_TOWN 0x300
#define LOCATE_IS_FIRM 0x400
#define LOCATE_IS_WALL 0x500
#define LOCATE_IS_ROCK 0xf00
#define LOCATE_POWER_OFF 0x1000 // true if no power_nation_recno can be set in this location
#define LOCATE_HARBOR_BIT 0x2000 // true if the terrain is suitable to build harbor (x,y) to (x+2,y+2)
// ------- constant on visibility ----------//
// const unsigned char FULL_VISIBILITY = MAX_BRIGHTNESS_ADJUST_DEGREE * 8 + 7;
const unsigned char FULL_VISIBILITY = 87;
// if a location has not been explored, visibility = 0
// if a location has been explored, visibility is bewtween 36-87
const unsigned char EXPLORED_VISIBILITY = 30; // don't see this to multiple of 8
const unsigned char MAX_VISIT_LEVEL = FULL_VISIBILITY;
//------- Define structure Location -------//
#pragma pack(1)
struct Location
{
public:
unsigned short loc_flag;
short terrain_id;
short cargo_recno;
short air_cargo_recno;
unsigned char extra_para;
//------------------------------------------------//
// when (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAS_SITE
// > extra_para = raw recno
//
// when (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAD_WALL
// > extra_para = time remained that can't build wall
//
// when (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAS_DIRT
// > extra_para = dirt recno
//
// when (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_HILL
// > cargo_recno = top hill block id
// > extra_para = bottom hill block id
//
// when (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_FIRM
// > cargo_recno = firm recno
//
// when (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_TOWN
// > cargo_recno = town zone recno
//
// when (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_PLANT
// > extra_para = id. of the plant bitmap
// > cargo_recno = low byte - inner x, high byte - inner y
//
// when (loc_flag & LOCATE_BLOCK_MASK) == LOCATION_IS_WALL
// > extra_para = id. of the city wall bitmap
// > high byte of cargo_recno = hit points remained for the wall
//
// when (loc_flag & LOCATE_BLOCK_MASK) == LOCATION_IS_ROCK
// > cargo_recno = rock recno in rock_array
//
// when (loc_flag & LOCATE_BLOCK_MASK) == 0 and cargo_recno != 0
// > carge_recno = unit id
//------------------------------------------------//
char fire_level; // -100 to 100, current fire level
char flammability; // -100 to 100, likelihood of fire
char power_nation_recno; // 0-no nation has power over this location
unsigned char region_id;
unsigned char visit_level; // drop from FULL_VISIBILITY to 0
public:
//------ functions that check the type of the location ------//
int walkable() { return loc_flag & LOCATE_WALK_LAND; }
int sailable() { return loc_flag & LOCATE_WALK_SEA; }
int walkable(int teraMask)
{ return loc_flag & teraMask; }
void walkable_reset();
// void walkable_on() { loc_flag |= LOCATE_WALK_LAND; }
void walkable_off() { loc_flag &= ~(LOCATE_WALK_LAND | LOCATE_WALK_SEA); }
void walkable_on(int teraMask) { loc_flag |= teraMask; }
void walkable_off(int teraMask) { loc_flag &= ~teraMask; }
int is_coast() { return loc_flag & LOCATE_COAST; }
// int explored() { return loc_flag & LOCATE_EXPLORED; }
// void explored_on() { loc_flag |= LOCATE_EXPLORED; }
// void explored_off() { loc_flag &= (~LOCATE_EXPLORED); }
int explored() { return visit_level > 0; }
void explored_on() { if( visit_level < EXPLORED_VISIBILITY*2) visit_level = EXPLORED_VISIBILITY*2; }
void explored_off() { visit_level = 0; }
// ---------- visibility --------//
unsigned char visibility() { return visit_level/2; }
void dec_visibility() { if( visit_level > EXPLORED_VISIBILITY*2) --visit_level; }
void set_visited() { visit_level = MAX_VISIT_LEVEL*2; }
void set_visited(unsigned char v) { if( visit_level < v*2) visit_level = v*2; }
int is_plateau();
// ----------- site -------------//
int can_build_site(int teraMask=LOCATE_WALK_LAND)
{ return (loc_flag & teraMask) && !(loc_flag & LOCATE_SITE_MASK) && !has_site(); }
void set_site(int siteRecno);
int has_site() { return (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAS_SITE; }
int site_recno() { if( has_site() ) return extra_para; else return 0; }
void remove_site();
// ------------ wall timeout ----------//
int had_wall() { return (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAD_WALL; }
// after wall destructed, cannot build wall again for some time
// the decrease time
// (LOCATE_HAD_WALL)
void set_wall_timeout(int initTimeout);
int wall_timeout() { return extra_para; }
int dec_wall_timeout(int=1);
void remove_wall_timeout();
// ----------- dirt -------------//
int can_add_dirt()
{ return !(loc_flag & LOCATE_SITE_MASK); }
void set_dirt(int dirtRecno);
int has_dirt() { return (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAS_DIRT; }
int dirt_recno() { if( has_dirt() ) return extra_para; else return 0; }
void remove_dirt();
// ---------- firm ----------//
int is_firm() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_FIRM; }
int can_build_firm(int teraMask = LOCATE_WALK_LAND)
{ return !cargo_recno && (loc_flag & teraMask) && !(loc_flag & LOCATE_BLOCK_MASK) && !is_power_off(); }
// ####### begin Gilbert 17/7 ###########//
int can_build_harbor(int teraMask = LOCATE_WALK_LAND)
{ return !cargo_recno && (loc_flag & teraMask) && !(loc_flag & LOCATE_BLOCK_MASK); }
// ####### end Gilbert 17/7 ###########//
void set_firm(int firmRecno);
int firm_recno() { if( is_firm() ) return cargo_recno; else return 0; }
void remove_firm();
// ---------- town ------------//
int is_town() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_TOWN; }
void set_town(int townRecno);
int can_build_town()
{ return !cargo_recno && (loc_flag & LOCATE_WALK_LAND) && !(loc_flag & LOCATE_BLOCK_MASK) && !has_site() && !is_power_off(); }
int town_recno() { if( is_town() ) return cargo_recno; else return 0; }
void remove_town();
// ---------- hill -------------//
int has_hill() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_HILL; }
int can_add_hill() // exception : it has already a hill
{ return has_hill() || // (loc_flag & LOCATE_WALK_LAND) &&
!cargo_recno && !(loc_flag & (LOCATE_BLOCK_MASK | LOCATE_SITE_MASK)); }
void set_hill(int hillId);
int hill_id1() { return cargo_recno; }
int hill_id2() { return extra_para; }
void remove_hill();
// ---------- wall ------------//
int is_wall() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_WALL; }
int can_build_wall()
{ return !cargo_recno && (loc_flag & LOCATE_WALK_LAND) &&
!(loc_flag & (LOCATE_BLOCK_MASK | LOCATE_SITE_MASK)) && !has_site(); }
void set_wall(int wallId, int townRecno, int hitPoints);
void set_wall_creating();
void set_wall_destructing();
void chg_wall_id( int wallId) { extra_para = wallId; }
int wall_id() { if( is_wall() ) return extra_para; else return 0; }
int wall_nation_recno() { return power_nation_recno; }
int wall_hit_point() { return cargo_recno >> 8; }
int wall_town_recno() { return cargo_recno || 0xFF; }
//---------------------------------------------------//
// initial 0, 1 to 100:creating, -1 to -100: destructing
// except 0 or 100, hit point slowly increase by 1
//---------------------------------------------------//
int wall_abs_hit_point() { return wall_hit_point() >= 0? wall_hit_point() : -wall_hit_point(); }
int inc_wall_hit_point(int grow=1);
int attack_wall(int damage=1);
int wall_grade() { return wall_hit_point() >= 0 ? (wall_hit_point()+24) / 25 : (wall_hit_point()-24)/25;}
int is_wall_creating() { return wall_hit_point() > 0; }
int is_wall_destructing() { return wall_hit_point() < 0; }
void remove_wall(int setTimeOut=-1);
// ---------- plant -----------//
int is_plant() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_PLANT; }
int can_add_plant(int teraMask = LOCATE_WALK_LAND)
{ return !cargo_recno && (loc_flag & teraMask) && !(loc_flag & (LOCATE_BLOCK_MASK | LOCATE_SITE_MASK)) && !has_site(); }
void set_plant(int plantId, int offsetX, int offsetY);
int plant_id() { if( is_plant() ) return extra_para; else return 0; }
int plant_inner_x() { return cargo_recno & 0xFF; }
int plant_inner_y() { return cargo_recno >> 8; }
void grow_plant() { extra_para++; }
void remove_plant();
// ---------- rock ------------//
int is_rock() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_ROCK; }
int can_add_rock(int teraMask = LOCATE_WALK_LAND)
{ return !cargo_recno && (loc_flag & teraMask) && !(loc_flag & LOCATE_BLOCK_MASK); }
void set_rock(short rockArrayRecno);
short rock_array_recno() { if( is_rock() ) return cargo_recno; else return 0; }
void remove_rock();
// call region_type only when generating region number
RegionType region_type() { return walkable()?REGION_LAND:(sailable()?REGION_SEA:REGION_INPASSABLE); }
// --------- functions on fire ---------//
char fire_str() { return fire_level; }
char fire_src() { return flammability; }
void set_fire_str(char str) { fire_level = str; }
void set_fire_src(char src) { flammability = src; }
void add_fire_str(char str) { fire_level += str; }
void add_fire_src(char src) { flammability += src; }
int can_set_fire() { return flammability >= -50; }
//----- functions whose results affected by mobile_type -----//
//int is_blocked(int mobileType) { return mobileType==UNIT_AIR ? air_cargo_recno : cargo_recno; } // return 1 or 0 (although both are the same)
int unit_recno(int mobileType) { return mobileType==UNIT_AIR ? air_cargo_recno : cargo_recno; } // return the exact cargo recno
int has_unit(int mobileType);
int has_any_unit(int mobileType = UNIT_LAND);
int get_any_unit(int& mobileType);
int is_accessible(int mobileType); // whether the location is accessible to the unit of the specific mobile type
int is_unit_group_accessible(int mobileType, DWORD curGroupId);
//int can_move(int mobileType) { return is_accessible(mobileType) && cargo_recno==0; }
int can_move(int mobileType) { return is_accessible(mobileType) && (mobileType==UNIT_AIR ? !air_cargo_recno : !cargo_recno); }
//### begin alex 24/6 ###//
//------------ power --------------//
void set_power_on();
void set_power_off();
int is_power_off();
//#### end alex 24/6 ####//
//----------- harbor bit -----------//
void set_harbor_bit() { loc_flag |= LOCATE_HARBOR_BIT; }
void clear_harbor_bit() { loc_flag &= ~LOCATE_HARBOR_BIT; }
int can_build_whole_harbor() { return loc_flag & LOCATE_HARBOR_BIT; }
};
#pragma pack()
//------------ Define class Matrix -----------//
class World;
class Matrix
{
friend class World;
public:
int max_x_loc, max_y_loc; // read from map file
Location *loc_matrix;
int top_x_loc, top_y_loc; // the top left location of current zoom window
int cur_x_loc, cur_y_loc;
int cur_cargo_width, cur_cargo_height; // cur_x2_loc = cur_x_loc + cur_cargo_width
int disp_x_loc, disp_y_loc; // calculated in Matrix()
int loc_width, loc_height; // passed as para in Matrix()
int win_x1, win_y1, win_x2, win_y2;
int image_x1, image_y1, image_x2, image_y2;
int image_width, image_height;
char own_matrix;
char *save_image_buf;
char just_drawn_flag; // whether the matrix has just been drawn by draw()
public:
virtual ~Matrix();
void init(int,int,int,int,int,int,int,int,int);
void assign_map(Matrix*);
void assign_map(Location*,int,int);
virtual void paint();
virtual void draw();
virtual void disp();
virtual int detect() {return 0;}
virtual void refresh();
virtual void scroll(int,int);
Location* get_loc(int xLoc,int yLoc)
{ return loc_matrix+yLoc * max_x_loc + xLoc; }
protected:
virtual void post_draw() {;}
virtual void draw_loc(int x,int y,int xLoc,int yLoc,Location* locPtr) {;}
void init_var();
int valid_cur_box(int=1);
void valid_disp_area(int=0);
};
//--------- Define inline functions ----------//
//-------- Begin of function Location::is_accessible --------//
inline int Location::is_accessible(int mobileType)
{
switch(mobileType)
{
case UNIT_LAND:
return walkable();
break;
case UNIT_SEA:
return sailable();
break;
case UNIT_AIR:
return 1;
break;
}
return 0;
}
//-------- End of function Location::is_accessible --------//
#endif