water_map.h

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD 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, version 2.
00006  * OpenTTD 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.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef WATER_MAP_H
00013 #define WATER_MAP_H
00014 
00015 #include "depot_type.h"
00016 #include "tile_map.h"
00017 
00021 enum WaterTileTypeBitLayout {
00022   WBL_TYPE_BEGIN        = 4,   
00023   WBL_TYPE_COUNT        = 4,   
00024 
00025   WBL_TYPE_NORMAL       = 0x0, 
00026   WBL_TYPE_LOCK         = 0x1, 
00027   WBL_TYPE_DEPOT        = 0x8, 
00028 
00029   WBL_COAST_FLAG        = 0,   
00030 
00031   WBL_LOCK_ORIENT_BEGIN = 0,   
00032   WBL_LOCK_ORIENT_COUNT = 2,   
00033   WBL_LOCK_PART_BEGIN   = 2,   
00034   WBL_LOCK_PART_COUNT   = 2,   
00035 
00036   WBL_DEPOT_PART        = 0,   
00037   WBL_DEPOT_AXIS        = 1,   
00038 };
00039 
00041 enum WaterTileType {
00042   WATER_TILE_CLEAR, 
00043   WATER_TILE_COAST, 
00044   WATER_TILE_LOCK,  
00045   WATER_TILE_DEPOT, 
00046 };
00047 
00049 enum WaterClass {
00050   WATER_CLASS_SEA,     
00051   WATER_CLASS_CANAL,   
00052   WATER_CLASS_RIVER,   
00053   WATER_CLASS_INVALID, 
00054 };
00056 template <> struct EnumPropsT<WaterClass> : MakeEnumPropsT<WaterClass, byte, WATER_CLASS_SEA, WATER_CLASS_INVALID, WATER_CLASS_INVALID, 2> {};
00057 
00059 enum DepotPart {
00060   DEPOT_PART_NORTH = 0, 
00061   DEPOT_PART_SOUTH = 1, 
00062   DEPOT_PART_END
00063 };
00064 
00066 enum LockPart {
00067   LOCK_PART_MIDDLE = 0, 
00068   LOCK_PART_LOWER  = 1, 
00069   LOCK_PART_UPPER  = 2, 
00070 };
00071 
00077 static inline WaterTileType GetWaterTileType(TileIndex t)
00078 {
00079   assert(IsTileType(t, MP_WATER));
00080 
00081   switch (GB(_m[t].m5, WBL_TYPE_BEGIN, WBL_TYPE_COUNT)) {
00082     case WBL_TYPE_NORMAL: return HasBit(_m[t].m5, WBL_COAST_FLAG) ? WATER_TILE_COAST : WATER_TILE_CLEAR;
00083     case WBL_TYPE_LOCK:  return WATER_TILE_LOCK;
00084     case WBL_TYPE_DEPOT:  return WATER_TILE_DEPOT;
00085     default: NOT_REACHED();
00086   }
00087 }
00088 
00095 static inline bool HasTileWaterClass(TileIndex t)
00096 {
00097   return IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION) || IsTileType(t, MP_INDUSTRY) || IsTileType(t, MP_OBJECT);
00098 }
00099 
00106 static inline WaterClass GetWaterClass(TileIndex t)
00107 {
00108   assert(HasTileWaterClass(t));
00109   return (WaterClass)GB(_m[t].m1, 5, 2);
00110 }
00111 
00118 static inline void SetWaterClass(TileIndex t, WaterClass wc)
00119 {
00120   assert(HasTileWaterClass(t));
00121   SB(_m[t].m1, 5, 2, wc);
00122 }
00123 
00130 static inline bool IsTileOnWater(TileIndex t)
00131 {
00132   return (GetWaterClass(t) != WATER_CLASS_INVALID);
00133 }
00134 
00141 static inline bool IsWater(TileIndex t)
00142 {
00143   return GetWaterTileType(t) == WATER_TILE_CLEAR;
00144 }
00145 
00152 static inline bool IsSea(TileIndex t)
00153 {
00154   return IsWater(t) && GetWaterClass(t) == WATER_CLASS_SEA;
00155 }
00156 
00163 static inline bool IsCanal(TileIndex t)
00164 {
00165   return IsWater(t) && GetWaterClass(t) == WATER_CLASS_CANAL;
00166 }
00167 
00174 static inline bool IsRiver(TileIndex t)
00175 {
00176   return IsWater(t) && GetWaterClass(t) == WATER_CLASS_RIVER;
00177 }
00178 
00184 static inline bool IsWaterTile(TileIndex t)
00185 {
00186   return IsTileType(t, MP_WATER) && IsWater(t);
00187 }
00188 
00195 static inline bool IsCoast(TileIndex t)
00196 {
00197   return GetWaterTileType(t) == WATER_TILE_COAST;
00198 }
00199 
00205 static inline bool IsCoastTile(TileIndex t)
00206 {
00207   return IsTileType(t, MP_WATER) && IsCoast(t);
00208 }
00209 
00216 static inline bool IsShipDepot(TileIndex t)
00217 {
00218   return GetWaterTileType(t) == WATER_TILE_DEPOT;
00219 }
00220 
00226 static inline bool IsShipDepotTile(TileIndex t)
00227 {
00228   return IsTileType(t, MP_WATER) && IsShipDepot(t);
00229 }
00230 
00237 static inline Axis GetShipDepotAxis(TileIndex t)
00238 {
00239   assert(IsShipDepotTile(t));
00240   return (Axis)GB(_m[t].m5, WBL_DEPOT_AXIS, 1);
00241 }
00242 
00249 static inline DepotPart GetShipDepotPart(TileIndex t)
00250 {
00251   assert(IsShipDepotTile(t));
00252   return (DepotPart)GB(_m[t].m5, WBL_DEPOT_PART, 1);
00253 }
00254 
00261 static inline DiagDirection GetShipDepotDirection(TileIndex t)
00262 {
00263   return XYNSToDiagDir(GetShipDepotAxis(t), GetShipDepotPart(t));
00264 }
00265 
00272 static inline TileIndex GetOtherShipDepotTile(TileIndex t)
00273 {
00274 return t + (GetShipDepotPart(t) != DEPOT_PART_NORTH ? -1 : 1) * (GetShipDepotAxis(t) != AXIS_X ? TileDiffXY(0, 1) : TileDiffXY(1, 0));
00275 }
00276 
00283 static inline TileIndex GetShipDepotNorthTile(TileIndex t)
00284 {
00285   assert(IsShipDepot(t));
00286   TileIndex tile2 = GetOtherShipDepotTile(t);
00287 
00288   return t < tile2 ? t : tile2;
00289 }
00290 
00297 static inline bool IsLock(TileIndex t)
00298 {
00299   return GetWaterTileType(t) == WATER_TILE_LOCK;
00300 }
00301 
00308 static inline DiagDirection GetLockDirection(TileIndex t)
00309 {
00310   assert(IsLock(t));
00311   return (DiagDirection)GB(_m[t].m5, WBL_LOCK_ORIENT_BEGIN, WBL_LOCK_ORIENT_COUNT);
00312 }
00313 
00320 static inline byte GetLockPart(TileIndex t)
00321 {
00322   assert(IsLock(t));
00323   return GB(_m[t].m5, WBL_LOCK_PART_BEGIN, WBL_LOCK_PART_COUNT);
00324 }
00325 
00332 static inline byte GetWaterTileRandomBits(TileIndex t)
00333 {
00334   assert(IsTileType(t, MP_WATER));
00335   return _m[t].m4;
00336 }
00337 
00344 static inline bool HasTileWaterGround(TileIndex t)
00345 {
00346   return HasTileWaterClass(t) && IsTileOnWater(t) && !IsCoastTile(t);
00347 }
00348 
00349 
00354 static inline void MakeShore(TileIndex t)
00355 {
00356   SetTileType(t, MP_WATER);
00357   SetTileOwner(t, OWNER_WATER);
00358   SetWaterClass(t, WATER_CLASS_SEA);
00359   _m[t].m2 = 0;
00360   _m[t].m3 = 0;
00361   _m[t].m4 = 0;
00362   _m[t].m5 = WBL_TYPE_NORMAL << WBL_TYPE_BEGIN | 1 << WBL_COAST_FLAG;
00363   SB(_m[t].m6, 2, 4, 0);
00364   _me[t].m7 = 0;
00365 }
00366 
00374 static inline void MakeWater(TileIndex t, Owner o, WaterClass wc, uint8 random_bits)
00375 {
00376   SetTileType(t, MP_WATER);
00377   SetTileOwner(t, o);
00378   SetWaterClass(t, wc);
00379   _m[t].m2 = 0;
00380   _m[t].m3 = 0;
00381   _m[t].m4 = random_bits;
00382   _m[t].m5 = WBL_TYPE_NORMAL << WBL_TYPE_BEGIN;
00383   SB(_m[t].m6, 2, 4, 0);
00384   _me[t].m7 = 0;
00385 }
00386 
00391 static inline void MakeSea(TileIndex t)
00392 {
00393   MakeWater(t, OWNER_WATER, WATER_CLASS_SEA, 0);
00394 }
00395 
00401 static inline void MakeRiver(TileIndex t, uint8 random_bits)
00402 {
00403   MakeWater(t, OWNER_WATER, WATER_CLASS_RIVER, random_bits);
00404 }
00405 
00412 static inline void MakeCanal(TileIndex t, Owner o, uint8 random_bits)
00413 {
00414   assert(o != OWNER_WATER);
00415   MakeWater(t, o, WATER_CLASS_CANAL, random_bits);
00416 }
00417 
00427 static inline void MakeShipDepot(TileIndex t, Owner o, DepotID did, DepotPart part, Axis a, WaterClass original_water_class)
00428 {
00429   SetTileType(t, MP_WATER);
00430   SetTileOwner(t, o);
00431   SetWaterClass(t, original_water_class);
00432   _m[t].m2 = did;
00433   _m[t].m3 = 0;
00434   _m[t].m4 = 0;
00435   _m[t].m5 = WBL_TYPE_DEPOT << WBL_TYPE_BEGIN | part << WBL_DEPOT_PART | a << WBL_DEPOT_AXIS;
00436   SB(_m[t].m6, 2, 4, 0);
00437   _me[t].m7 = 0;
00438 }
00439 
00449 static inline void MakeLockTile(TileIndex t, Owner o, LockPart part, DiagDirection dir, WaterClass original_water_class)
00450 {
00451   SetTileType(t, MP_WATER);
00452   SetTileOwner(t, o);
00453   SetWaterClass(t, original_water_class);
00454   _m[t].m2 = 0;
00455   _m[t].m3 = 0;
00456   _m[t].m4 = 0;
00457   _m[t].m5 = WBL_TYPE_LOCK << WBL_TYPE_BEGIN | part << WBL_LOCK_PART_BEGIN | dir << WBL_LOCK_ORIENT_BEGIN;
00458   SB(_m[t].m6, 2, 4, 0);
00459   _me[t].m7 = 0;
00460 }
00461 
00471 static inline void MakeLock(TileIndex t, Owner o, DiagDirection d, WaterClass wc_lower, WaterClass wc_upper, WaterClass wc_middle)
00472 {
00473   TileIndexDiff delta = TileOffsByDiagDir(d);
00474 
00475   /* Keep the current owner for the upper and lower part if it is a
00476    * water tile so we can restore the owner after deleting the lock. */
00477   MakeLockTile(t, o, LOCK_PART_MIDDLE, d, wc_middle);
00478   MakeLockTile(t - delta, IsWaterTile(t - delta) ? GetTileOwner(t - delta) : o, LOCK_PART_LOWER, d, wc_lower);
00479   MakeLockTile(t + delta, IsWaterTile(t + delta) ? GetTileOwner(t + delta) : o, LOCK_PART_UPPER, d, wc_upper);
00480 }
00481 
00482 #endif /* WATER_MAP_H */