use super::{area::*, defs::*, neutral::*};
use std::cell::{Cell, RefCell};
use std::rc::Rc;
#[derive(Default)]
pub struct MiniTile {
altitude: Cell<Altitude>,
area_id: Cell<AreaId>,
}
const blocking_cp: AreaId = AreaId::MIN;
impl MiniTile {
pub fn walkable(&self) -> bool {
self.area_id.get() != 0
}
pub fn altitude(&self) -> Altitude {
self.altitude.get()
}
pub fn sea(&self) -> bool {
self.altitude.get() == 0
}
pub fn lake(&self) -> bool {
self.altitude.get() != 0 && !self.walkable()
}
pub fn terrain(&self) -> bool {
self.walkable()
}
pub fn area_id(&self) -> AreaId {
self.area_id.get()
}
pub fn set_walkable(&self, walkable: bool) {
if walkable {
self.area_id.set(-1);
self.altitude.set(-1);
} else {
self.area_id.set(0);
self.altitude.set(1);
}
}
pub fn sea_or_lake(&self) -> bool {
self.altitude.get() == 1
}
pub fn set_sea(&self) {
debug_assert!(!self.walkable() && self.sea_or_lake());
self.altitude.set(0);
}
pub fn set_lake(&self) {
debug_assert!(!self.walkable() && self.sea());
self.altitude.set(-1);
}
pub fn altitude_missing(&self) -> bool {
self.altitude.get() == -1
}
pub fn set_altitude(&self, a: Altitude) {
debug_assert!(self.altitude_missing() && a > 0);
self.altitude.set(a);
}
pub fn area_id_missing(&self) -> bool {
self.area_id.get() == -1
}
pub fn set_area_id(&self, id: AreaId) {
debug_assert!(self.area_id_missing() && id >= 1);
self.area_id.set(id);
}
pub fn replace_area_id(&self, id: AreaId) {
debug_assert!(self.area_id.get() > 0 && (id >= 1 || id <= -2) && id != self.area_id.get());
self.area_id.set(id);
}
pub fn set_blocked(&self) {
debug_assert!(self.area_id_missing());
self.area_id.set(blocking_cp);
}
pub fn blocked(&self) -> bool {
self.area_id.get() == blocking_cp
}
pub fn replace_blocked_area_id(&self, id: AreaId) {
debug_assert!(self.area_id.get() == blocking_cp && id >= 1);
self.area_id.set(id);
}
}
pub struct Tile {
neutral: *mut dyn Neutral,
min_altitude: Altitude,
area_id: AreaId,
internal_data: i32,
bits: Bits,
pub(crate) mark: TileMark,
}
markable!(tile_mark, TileMark);
impl Default for Tile {
fn default() -> Self {
Self {
neutral: std::ptr::null_mut::<Mineral>(),
min_altitude: 0,
area_id: 0,
internal_data: 0,
bits: Default::default(),
mark: Default::default(),
}
}
}
#[derive(Default)]
pub struct Bits {
buildable: bool,
ground_height: u8,
doodad: bool,
}
impl Tile {
pub fn buildable(&self) -> bool {
self.bits.buildable
}
pub fn area_id(&self) -> AreaId {
self.area_id
}
pub fn min_altitude(&self) -> Altitude {
self.min_altitude
}
pub fn walkable(&self) -> bool {
self.area_id != 0
}
pub fn terrain(&self) -> bool {
self.walkable()
}
pub fn ground_height(&self) -> isize {
self.bits.ground_height as isize
}
pub fn doodad(&self) -> bool {
self.bits.doodad
}
pub fn get_neutral(&self) -> *mut dyn Neutral {
self.neutral
}
pub fn stacked_neutrals(&self) -> isize {
let mut stack_size = 0;
let mut stacked = self.get_neutral();
while !stacked.is_null() {
stack_size += 1;
stacked = unsafe { &*stacked }.next_stacked();
}
stack_size
}
pub fn set_buildable(&mut self) {
self.bits.buildable = true;
}
pub fn set_ground_height(&mut self, h: i32) {
debug_assert!((0 <= h) && (h <= 2));
self.bits.ground_height = h as u8;
}
pub fn set_doodad(&mut self) {
self.bits.doodad = true;
}
pub fn add_neutral(&mut self, neutral: *mut dyn Neutral) {
self.neutral = neutral;
}
pub fn set_area_id(&mut self, id: AreaId) {
debug_assert!((id == -1) || self.area_id == 0 && id != 0);
self.area_id = id;
}
pub fn reset_area_id(&mut self) {
self.area_id = 0;
}
pub fn set_min_altitude(&mut self, a: Altitude) {
debug_assert!(a >= 0);
self.min_altitude = a;
}
pub fn remove_neutral(&mut self, neutral: *mut dyn Neutral) {
debug_assert!(
!self.neutral.is_null()
&& unsafe { &*self.neutral }.unit_id() == unsafe { &*neutral }.unit_id()
);
self.neutral = std::ptr::null_mut::<Mineral>();
}
pub fn internal_data(&self) -> i32 {
self.internal_data
}
pub fn set_internal_data(&mut self, data: i32) {
self.internal_data = data;
}
}
pub trait TileOfPosition<P> {
type Tile;
}