1 /*
2 * Seven Kingdoms: Ancient Adversaries
3 *
4 * Copyright 1997,1998 Enlight Software Ltd.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 //Filename : OMATRIX.H
22 //Description : Object road direction turn
23
24 #ifndef __OMATRIX_H
25 #define __OMATRIX_H
26
27 #ifndef __OUNITRES_H
28 #include <OUNITRES.h>
29 #endif
30
31 #include <OREGION.h>
32
33 //----- Define bit meanings Location::flag ------//
34 #define LOCATE_WALK_LAND 0x01
35 #define LOCATE_WALK_SEA 0x02
36 #define LOCATE_COAST 0x08
37
38 // ----- govern the usage of extra_para ---------//
39 #define LOCATE_SITE_MASK 0xf0
40 #define LOCATE_HAS_SITE 0x10
41 #define LOCATE_HAD_WALL 0x20
42 #define LOCATE_HAS_DIRT 0x30
43 #define LOCATE_SITE_RESERVED 0xf0
44 // occupied by other block such as hill, plant
45
46 // ----- govern the usage of cargo_recno -------//
47 #define LOCATE_BLOCK_MASK 0xf00
48 #define LOCATE_IS_HILL 0x100
49 #define LOCATE_IS_PLANT 0x200
50 #define LOCATE_IS_TOWN 0x300
51 #define LOCATE_IS_FIRM 0x400
52 #define LOCATE_IS_WALL 0x500
53 #define LOCATE_IS_ROCK 0xf00
54
55 #define LOCATE_POWER_OFF 0x1000 // true if no power_nation_recno can be set in this location
56 #define LOCATE_HARBOR_BIT 0x2000 // true if the terrain is suitable to build harbor (x,y) to (x+2,y+2)
57
58 // ------- constant on visibility ----------//
59 // const unsigned char FULL_VISIBILITY = MAX_BRIGHTNESS_ADJUST_DEGREE * 8 + 7;
60 const unsigned char FULL_VISIBILITY = 87;
61 // if a location has not been explored, visibility = 0
62 // if a location has been explored, visibility is bewtween 36-87
63 const unsigned char EXPLORED_VISIBILITY = 30; // don't see this to multiple of 8
64 const unsigned char MAX_VISIT_LEVEL = FULL_VISIBILITY;
65
66
67 //------- Define structure Location -------//
68
69 #pragma pack(1)
70 struct Location
71 {
72 public:
73 unsigned short loc_flag;
74 short terrain_id;
75
76 short cargo_recno;
77 short air_cargo_recno;
78
79 unsigned char extra_para;
80
81 //------------------------------------------------//
82 // when (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAS_SITE
83 // > extra_para = raw recno
84 //
85 // when (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAD_WALL
86 // > extra_para = time remained that can't build wall
87 //
88 // when (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAS_DIRT
89 // > extra_para = dirt recno
90 //
91 // when (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_HILL
92 // > cargo_recno = top hill block id
93 // > extra_para = bottom hill block id
94 //
95 // when (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_FIRM
96 // > cargo_recno = firm recno
97 //
98 // when (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_TOWN
99 // > cargo_recno = town zone recno
100 //
101 // when (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_PLANT
102 // > extra_para = id. of the plant bitmap
103 // > cargo_recno = low byte - inner x, high byte - inner y
104 //
105 // when (loc_flag & LOCATE_BLOCK_MASK) == LOCATION_IS_WALL
106 // > extra_para = id. of the city wall bitmap
107 // > high byte of cargo_recno = hit points remained for the wall
108 //
109 // when (loc_flag & LOCATE_BLOCK_MASK) == LOCATION_IS_ROCK
110 // > cargo_recno = rock recno in rock_array
111 //
112 // when (loc_flag & LOCATE_BLOCK_MASK) == 0 and cargo_recno != 0
113 // > carge_recno = unit id
114 //------------------------------------------------//
115
116 char fire_level; // -100 to 100, current fire level
117 char flammability; // -100 to 100, likelihood of fire
118
119 char power_nation_recno; // 0-no nation has power over this location
120 uint8_t region_id;
121 unsigned char visit_level; // drop from FULL_VISIBILITY to 0
122
123 public:
124 //------ functions that check the type of the location ------//
125
walkableLocation126 int walkable() { return loc_flag & LOCATE_WALK_LAND; }
sailableLocation127 int sailable() { return loc_flag & LOCATE_WALK_SEA; }
walkableLocation128 int walkable(int teraMask)
129 { return loc_flag & teraMask; }
130 void walkable_reset();
131 // void walkable_on() { loc_flag |= LOCATE_WALK_LAND; }
walkable_offLocation132 void walkable_off() { loc_flag &= ~(LOCATE_WALK_LAND | LOCATE_WALK_SEA); }
133
walkable_onLocation134 void walkable_on(int teraMask) { loc_flag |= teraMask; }
walkable_offLocation135 void walkable_off(int teraMask) { loc_flag &= ~teraMask; }
136
is_coastLocation137 int is_coast() { return loc_flag & LOCATE_COAST; }
138
139 // int explored() { return loc_flag & LOCATE_EXPLORED; }
140 // void explored_on() { loc_flag |= LOCATE_EXPLORED; }
141 // void explored_off() { loc_flag &= (~LOCATE_EXPLORED); }
exploredLocation142 int explored() { return visit_level > 0; }
explored_onLocation143 void explored_on() { if( visit_level < EXPLORED_VISIBILITY*2) visit_level = EXPLORED_VISIBILITY*2; }
explored_offLocation144 void explored_off() { visit_level = 0; }
145
146 // ---------- visibility --------//
visibilityLocation147 unsigned char visibility() { return visit_level/2; }
dec_visibilityLocation148 void dec_visibility() { if( visit_level > EXPLORED_VISIBILITY*2) --visit_level; }
set_visitedLocation149 void set_visited() { visit_level = MAX_VISIT_LEVEL*2; }
set_visitedLocation150 void set_visited(unsigned char v) { if( visit_level < v*2) visit_level = v*2; }
151
152 int is_plateau();
153
154
155 // ----------- site -------------//
156 int can_build_site(int teraMask=LOCATE_WALK_LAND)
157 { return (loc_flag & teraMask) && !(loc_flag & LOCATE_SITE_MASK) && !has_site(); }
158 void set_site(int siteRecno);
has_siteLocation159 int has_site() { return (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAS_SITE; }
site_recnoLocation160 int site_recno() { if( has_site() ) return extra_para; else return 0; }
161 void remove_site();
162
163 // ------------ wall timeout ----------//
had_wallLocation164 int had_wall() { return (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAD_WALL; }
165 // after wall destructed, cannot build wall again for some time
166 // the decrease time
167 // (LOCATE_HAD_WALL)
168 void set_wall_timeout(int initTimeout);
wall_timeoutLocation169 int wall_timeout() { return extra_para; }
170 int dec_wall_timeout(int=1);
171 void remove_wall_timeout();
172
173 // ----------- dirt -------------//
can_add_dirtLocation174 int can_add_dirt()
175 { return !(loc_flag & LOCATE_SITE_MASK); }
176 void set_dirt(int dirtRecno);
has_dirtLocation177 int has_dirt() { return (loc_flag & LOCATE_SITE_MASK) == LOCATE_HAS_DIRT; }
dirt_recnoLocation178 int dirt_recno() { if( has_dirt() ) return extra_para; else return 0; }
179 void remove_dirt();
180
181 // ---------- firm ----------//
is_firmLocation182 int is_firm() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_FIRM; }
183 int can_build_firm(int teraMask = LOCATE_WALK_LAND)
184 { return !cargo_recno && (loc_flag & teraMask) && !(loc_flag & LOCATE_BLOCK_MASK) && !is_power_off(); }
185 // ####### begin Gilbert 17/7 ###########//
186 int can_build_harbor(int teraMask = LOCATE_WALK_LAND)
187 { return !cargo_recno && (loc_flag & teraMask) && !(loc_flag & LOCATE_BLOCK_MASK); }
188 // ####### end Gilbert 17/7 ###########//
189 void set_firm(int firmRecno);
firm_recnoLocation190 int firm_recno() { if( is_firm() ) return cargo_recno; else return 0; }
191 void remove_firm();
192
193 // ---------- town ------------//
is_townLocation194 int is_town() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_TOWN; }
195 void set_town(int townRecno);
can_build_townLocation196 int can_build_town()
197 { return !cargo_recno && (loc_flag & LOCATE_WALK_LAND) && !(loc_flag & LOCATE_BLOCK_MASK) && !has_site() && !is_power_off(); }
town_recnoLocation198 int town_recno() { if( is_town() ) return cargo_recno; else return 0; }
199 void remove_town();
200
201 // ---------- hill -------------//
has_hillLocation202 int has_hill() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_HILL; }
can_add_hillLocation203 int can_add_hill() // exception : it has already a hill
204 { return has_hill() || // (loc_flag & LOCATE_WALK_LAND) &&
205 !cargo_recno && !(loc_flag & (LOCATE_BLOCK_MASK | LOCATE_SITE_MASK)); }
206 void set_hill(int hillId);
hill_id1Location207 int hill_id1() { return cargo_recno; }
hill_id2Location208 int hill_id2() { return extra_para; }
209 void remove_hill();
210
211 // ---------- wall ------------//
is_wallLocation212 int is_wall() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_WALL; }
can_build_wallLocation213 int can_build_wall()
214 { return !cargo_recno && (loc_flag & LOCATE_WALK_LAND) &&
215 !(loc_flag & (LOCATE_BLOCK_MASK | LOCATE_SITE_MASK)) && !has_site(); }
216 void set_wall(int wallId, int townRecno, int hitPoints);
217 void set_wall_creating();
218 void set_wall_destructing();
chg_wall_idLocation219 void chg_wall_id( int wallId) { extra_para = wallId; }
wall_idLocation220 int wall_id() { if( is_wall() ) return extra_para; else return 0; }
wall_nation_recnoLocation221 int wall_nation_recno() { return power_nation_recno; }
wall_hit_pointLocation222 int wall_hit_point() { return cargo_recno >> 8; }
wall_town_recnoLocation223 int wall_town_recno() { return cargo_recno || 0xFF; }
224 //---------------------------------------------------//
225 // initial 0, 1 to 100:creating, -1 to -100: destructing
226 // except 0 or 100, hit point slowly increase by 1
227 //---------------------------------------------------//
wall_abs_hit_pointLocation228 int wall_abs_hit_point() { return wall_hit_point() >= 0? wall_hit_point() : -wall_hit_point(); }
229 int inc_wall_hit_point(int grow=1);
230 int attack_wall(int damage=1);
wall_gradeLocation231 int wall_grade() { return wall_hit_point() >= 0 ? (wall_hit_point()+24) / 25 : (wall_hit_point()-24)/25;}
is_wall_creatingLocation232 int is_wall_creating() { return wall_hit_point() > 0; }
is_wall_destructingLocation233 int is_wall_destructing() { return wall_hit_point() < 0; }
234 void remove_wall(int setTimeOut=-1);
235
236 // ---------- plant -----------//
is_plantLocation237 int is_plant() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_PLANT; }
238 int can_add_plant(int teraMask = LOCATE_WALK_LAND)
239 { return !cargo_recno && (loc_flag & teraMask) && !(loc_flag & (LOCATE_BLOCK_MASK | LOCATE_SITE_MASK)) && !has_site(); }
240 void set_plant(int plantId, int offsetX, int offsetY);
plant_idLocation241 int plant_id() { if( is_plant() ) return extra_para; else return 0; }
plant_inner_xLocation242 int plant_inner_x() { return cargo_recno & 0xFF; }
plant_inner_yLocation243 int plant_inner_y() { return cargo_recno >> 8; }
grow_plantLocation244 void grow_plant() { extra_para++; }
245 void remove_plant();
246
247 // ---------- rock ------------//
is_rockLocation248 int is_rock() { return (loc_flag & LOCATE_BLOCK_MASK) == LOCATE_IS_ROCK; }
249 int can_add_rock(int teraMask = LOCATE_WALK_LAND)
250 { return !cargo_recno && (loc_flag & teraMask) && !(loc_flag & LOCATE_BLOCK_MASK); }
251 void set_rock(short rockArrayRecno);
rock_array_recnoLocation252 short rock_array_recno() { if( is_rock() ) return cargo_recno; else return 0; }
253 void remove_rock();
254
255 // call region_type only when generating region number
region_typeLocation256 RegionType region_type() { return walkable()?REGION_LAND:(sailable()?REGION_SEA:REGION_INPASSABLE); }
257
258 // --------- functions on fire ---------//
fire_strLocation259 char fire_str() { return fire_level; }
fire_srcLocation260 char fire_src() { return flammability; }
set_fire_strLocation261 void set_fire_str(char str) { fire_level = str; }
set_fire_srcLocation262 void set_fire_src(char src) { flammability = src; }
add_fire_strLocation263 void add_fire_str(char str) { fire_level += str; }
add_fire_srcLocation264 void add_fire_src(char src) { flammability += src; }
can_set_fireLocation265 int can_set_fire() { return flammability >= -50; }
266
267 //----- functions whose results affected by mobile_type -----//
268
269 //int is_blocked(int mobileType) { return mobileType==UNIT_AIR ? air_cargo_recno : cargo_recno; } // return 1 or 0 (although both are the same)
unit_recnoLocation270 int unit_recno(int mobileType) { return mobileType==UNIT_AIR ? air_cargo_recno : cargo_recno; } // return the exact cargo recno
271
272 int has_unit(int mobileType);
273 int has_any_unit(int mobileType = UNIT_LAND);
274 int get_any_unit(int& mobileType);
275 int is_accessible(int mobileType); // whether the location is accessible to the unit of the specific mobile type
276
277 int is_unit_group_accessible(int mobileType, uint32_t curGroupId);
278
279 //int can_move(int mobileType) { return is_accessible(mobileType) && cargo_recno==0; }
can_moveLocation280 int can_move(int mobileType) { return is_accessible(mobileType) && (mobileType==UNIT_AIR ? !air_cargo_recno : !cargo_recno); }
281
282 //### begin alex 24/6 ###//
283 //------------ power --------------//
284 void set_power_on();
285 void set_power_off();
286 int is_power_off();
287 //#### end alex 24/6 ####//
288
289 //----------- harbor bit -----------//
set_harbor_bitLocation290 void set_harbor_bit() { loc_flag |= LOCATE_HARBOR_BIT; }
clear_harbor_bitLocation291 void clear_harbor_bit() { loc_flag &= ~LOCATE_HARBOR_BIT; }
can_build_whole_harborLocation292 int can_build_whole_harbor() { return loc_flag & LOCATE_HARBOR_BIT; }
293 };
294 #pragma pack()
295
296 //------------ Define class Matrix -----------//
297
298 class World;
299
300 class Matrix
301 {
302 friend class World;
303
304 public:
305 int max_x_loc, max_y_loc; // read from map file
306 Location *loc_matrix;
307
308 int top_x_loc, top_y_loc; // the top left location of current zoom window
309 int cur_x_loc, cur_y_loc;
310 int cur_cargo_width, cur_cargo_height; // cur_x2_loc = cur_x_loc + cur_cargo_width
311
312 int disp_x_loc, disp_y_loc; // calculated in Matrix()
313 int loc_width, loc_height; // passed as para in Matrix()
314
315 int win_x1, win_y1, win_x2, win_y2;
316 int image_x1, image_y1, image_x2, image_y2;
317 int image_width, image_height;
318
319 char own_matrix;
320
321 char *save_image_buf;
322 char just_drawn_flag; // whether the matrix has just been drawn by draw()
323
324 public:
325 virtual ~Matrix();
326
327 void init(int,int,int,int,int,int,int,int,int);
328 void assign_map(Matrix*);
329 void assign_map(Location*,int,int);
330
331 virtual void paint();
332 virtual void draw();
333 virtual void disp();
detect()334 virtual int detect() {return 0;}
335 virtual void refresh();
336 virtual void scroll(int,int);
337
get_loc(int xLoc,int yLoc)338 Location* get_loc(int xLoc,int yLoc)
339 { return loc_matrix+yLoc * max_x_loc + xLoc; }
340
341 protected:
post_draw()342 virtual void post_draw() {;}
draw_loc(int x,int y,int xLoc,int yLoc,Location * locPtr)343 virtual void draw_loc(int x,int y,int xLoc,int yLoc,Location* locPtr) {;}
344
345 void init_var();
346 int valid_cur_box(int=1);
347 void valid_disp_area(int=0);
348 };
349
350 //--------- Define inline functions ----------//
351
352 //-------- Begin of function Location::is_accessible --------//
353
is_accessible(int mobileType)354 inline int Location::is_accessible(int mobileType)
355 {
356 switch(mobileType)
357 {
358 case UNIT_LAND:
359 return walkable();
360 break;
361
362 case UNIT_SEA:
363 return sailable();
364 break;
365
366 case UNIT_AIR:
367 return 1;
368 break;
369 }
370
371 return 0;
372 }
373 //-------- End of function Location::is_accessible --------//
374
375 #endif
376