Skip to content

Commit c9abd31

Browse files
authored
Rename is_edge functions to is_room_edge, add one for Position, move RoomXY its to own file (#497)
1 parent 7dab513 commit c9abd31

File tree

5 files changed

+289
-276
lines changed

5 files changed

+289
-276
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Unreleased
1414
- Add function `name_jsstring` to `SharedCreepProperties` trait, `Flag`, and `StructureSpawn`
1515
- Add function `raw_memory::segments_jsstring` to get the object as `JsHashMap<u8, JsString>`
1616
- Add `RoomTerrain::get_xy` which takes a `RoomXY` instead of a coordinate pair
17-
- Add `RoomCoordinate::is_edge` and `RoomXY::is_edge`
17+
- Add `RoomCoordinate::is_room_edge`, `RoomXY::is_room_edge`, and `Position::is_room_edge`
1818
- Add new extra constant `constants::extra::CONTROLLER_DOWNGRADE_PROGRESS_RATIO`, which is
1919
the percentage toward the previous level that a downgrading controller's progress is set to
2020
- Add new extra constants `constants::extra::MOVE_COST_PLAIN`, `MOVE_COST_ROAD`, `MOVE_COST_SWAMP`

src/local.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod object_id;
77
mod position;
88
mod room_coordinate;
99
mod room_name;
10+
mod room_xy;
1011
mod terrain;
1112

1213
/// Represents two constants related to room names.
@@ -32,5 +33,5 @@ use crate::ROOM_SIZE;
3233

3334
pub use self::{
3435
cost_matrix::*, lodash_filter::*, object_id::*, position::*, room_coordinate::*, room_name::*,
35-
terrain::*,
36+
room_xy::*, terrain::*,
3637
};

src/local/position/extra_math.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ use super::Position;
66
use crate::{constants::Direction, local::position::WorldPositionOutOfBoundsError};
77

88
impl Position {
9+
/// Returns whether this coordinate represents a room edge position (0 or
10+
/// 49)
11+
pub fn is_room_edge(self) -> bool {
12+
self.xy().is_room_edge()
13+
}
14+
915
/// Returns a new position offset from this position by the specified x
1016
/// coords and y coords.
1117
///

src/local/room_coordinate.rs

Lines changed: 5 additions & 274 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
use std::{error::Error, fmt};
22

3-
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
3+
use serde::{Deserialize, Serialize};
44

5-
use crate::constants::{Direction, ROOM_SIZE};
6-
7-
pub(crate) const ROOM_AREA: usize = (ROOM_SIZE as usize) * (ROOM_SIZE as usize);
5+
use crate::constants::ROOM_SIZE;
86

97
#[derive(Debug, Clone, Copy)]
10-
pub struct OutOfBoundsError(u8);
8+
pub struct OutOfBoundsError(pub u8);
119

1210
impl fmt::Display for OutOfBoundsError {
1311
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -17,65 +15,13 @@ impl fmt::Display for OutOfBoundsError {
1715

1816
impl Error for OutOfBoundsError {}
1917

20-
/// Converts a [`RoomXY`] coordinate pair to a linear index appropriate for use
21-
/// with the internal representation of a [`CostMatrix`] or [`LocalCostMatrix`].
22-
///
23-
/// [`CostMatrix`]: crate::objects::CostMatrix
24-
/// [`LocalCostMatrix`]: crate::local::LocalCostMatrix
25-
#[inline]
26-
pub const fn xy_to_linear_index(xy: RoomXY) -> usize {
27-
xy.x.u8() as usize * ROOM_SIZE as usize + xy.y.u8() as usize
28-
}
29-
30-
/// Converts a linear index from the internal representation of a [`CostMatrix`]
31-
/// or [`LocalCostMatrix`] to a [`RoomXY`] coordinate pair for the position the
32-
/// index represents.
33-
///
34-
/// [`CostMatrix`]: crate::objects::CostMatrix
35-
/// [`LocalCostMatrix`]: crate::local::LocalCostMatrix
36-
#[inline]
37-
pub fn linear_index_to_xy(idx: usize) -> RoomXY {
38-
assert!(idx < ROOM_AREA, "Out of bounds index: {idx}");
39-
// SAFETY: bounds checking above ensures both are within range.
40-
RoomXY {
41-
x: unsafe { RoomCoordinate::unchecked_new((idx / (ROOM_SIZE as usize)) as u8) },
42-
y: unsafe { RoomCoordinate::unchecked_new((idx % (ROOM_SIZE as usize)) as u8) },
43-
}
44-
}
45-
46-
/// Converts a [`RoomXY`] coordinate pair to a terrain index appropriate for use
47-
/// with the internal representation of [`RoomTerrain`] or [`LocalRoomTerrain`].
48-
///
49-
/// [`RoomTerrain`]: crate::objects::RoomTerrain
50-
/// [`LocalRoomTerrain`]: crate::local::LocalRoomTerrain
51-
#[inline]
52-
pub const fn xy_to_terrain_index(xy: RoomXY) -> usize {
53-
xy.y.u8() as usize * ROOM_SIZE as usize + xy.x.u8() as usize
54-
}
55-
56-
/// Converts a terrain index from the internal representation of a
57-
/// [`RoomTerrain`] or [`LocalRoomTerrain`] to a [`RoomXY`] coordinate pair for
58-
/// the position the index represents.
59-
///
60-
/// [`RoomTerrain`]: crate::objects::RoomTerrain
61-
/// [`LocalRoomTerrain`]: crate::local::LocalRoomTerrain
62-
#[inline]
63-
pub fn terrain_index_to_xy(idx: usize) -> RoomXY {
64-
assert!(idx < ROOM_AREA, "Out of bounds index: {idx}");
65-
// SAFETY: bounds checking above ensures both are within range.
66-
RoomXY {
67-
x: unsafe { RoomCoordinate::unchecked_new((idx % (ROOM_SIZE as usize)) as u8) },
68-
y: unsafe { RoomCoordinate::unchecked_new((idx / (ROOM_SIZE as usize)) as u8) },
69-
}
70-
}
71-
7218
/// An X or Y coordinate in a room, restricted to the valid range of
7319
/// coordinates.
7420
#[derive(
7521
Debug, Hash, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
7622
)]
7723
#[serde(try_from = "u8", into = "u8")]
78-
pub struct RoomCoordinate(u8);
24+
pub struct RoomCoordinate(pub u8);
7925

8026
impl RoomCoordinate {
8127
/// Create a `RoomCoordinate` from a `u8`, returning an error if the
@@ -110,7 +56,7 @@ impl RoomCoordinate {
11056
}
11157

11258
/// Get whether this coordinate represents an edge position (0 or 49)
113-
pub const fn is_edge(self) -> bool {
59+
pub const fn is_room_edge(self) -> bool {
11460
self.0 == 0 || self.0 == ROOM_SIZE - 1
11561
}
11662

@@ -180,139 +126,6 @@ impl fmt::Display for RoomCoordinate {
180126
}
181127
}
182128

183-
/// An X/Y pair representing a given coordinate relative to any room.
184-
#[derive(Debug, Default, Hash, Clone, Copy, PartialEq, Eq)]
185-
pub struct RoomXY {
186-
pub x: RoomCoordinate,
187-
pub y: RoomCoordinate,
188-
}
189-
190-
impl RoomXY {
191-
/// Create a `RoomXY` from a pair of `u8`, without checking whether it's in
192-
/// the range of valid values.
193-
///
194-
/// # Safety
195-
/// Calling this method with `x >= ROOM_SIZE` or `y >= ROOM_SIZE` can result
196-
/// in undefined behaviour when the resulting `RoomXY` is used.
197-
#[inline]
198-
pub unsafe fn unchecked_new(x: u8, y: u8) -> Self {
199-
RoomXY {
200-
x: RoomCoordinate::unchecked_new(x),
201-
y: RoomCoordinate::unchecked_new(y),
202-
}
203-
}
204-
205-
/// Get whether this coordinate pair represents an edge position (0 or 49
206-
/// for either coordinate)
207-
pub const fn is_edge(self) -> bool {
208-
self.x.is_edge() || self.y.is_edge()
209-
}
210-
211-
/// Get the coordinate adjusted by a certain value, returning `None` if the
212-
/// result is outside the valid room area.
213-
///
214-
/// Example usage:
215-
///
216-
/// ```
217-
/// use screeps::local::RoomXY;
218-
///
219-
/// let zero = unsafe { RoomXY::unchecked_new(0, 0) };
220-
/// let one = unsafe { RoomXY::unchecked_new(1, 1) };
221-
/// let forty_nine = unsafe { RoomXY::unchecked_new(49, 49) };
222-
///
223-
/// assert_eq!(zero.checked_add((1, 1)), Some(one));
224-
/// assert_eq!(zero.checked_add((-1, 0)), None);
225-
/// assert_eq!(zero.checked_add((49, 49)), Some(forty_nine));
226-
/// assert_eq!(forty_nine.checked_add((1, 1)), None);
227-
/// ```
228-
pub fn checked_add(self, rhs: (i8, i8)) -> Option<RoomXY> {
229-
let x = match self.x.checked_add(rhs.0) {
230-
Some(x) => x,
231-
None => return None,
232-
};
233-
let y = match self.y.checked_add(rhs.1) {
234-
Some(y) => y,
235-
None => return None,
236-
};
237-
Some(RoomXY { x, y })
238-
}
239-
240-
/// Get the coordinate adjusted by a certain value, saturating at the edges
241-
/// of the room if the result would be outside the valid room area.
242-
///
243-
/// Example usage:
244-
///
245-
/// ```
246-
/// use screeps::local::RoomXY;
247-
///
248-
/// let zero = unsafe { RoomXY::unchecked_new(0, 0) };
249-
/// let one = unsafe { RoomXY::unchecked_new(1, 1) };
250-
/// let forty_nine = unsafe { RoomXY::unchecked_new(49, 49) };
251-
///
252-
/// assert_eq!(zero.saturating_add((1, 1)), one);
253-
/// assert_eq!(zero.saturating_add((-1, 0)), zero);
254-
/// assert_eq!(zero.saturating_add((49, 49)), forty_nine);
255-
/// assert_eq!(zero.saturating_add((i8::MAX, i8::MAX)), forty_nine);
256-
/// assert_eq!(forty_nine.saturating_add((1, 1)), forty_nine);
257-
/// assert_eq!(forty_nine.saturating_add((i8::MIN, i8::MIN)), zero);
258-
/// ```
259-
pub fn saturating_add(self, rhs: (i8, i8)) -> RoomXY {
260-
let x = self.x.saturating_add(rhs.0);
261-
let y = self.y.saturating_add(rhs.1);
262-
RoomXY { x, y }
263-
}
264-
265-
/// Get the neighbor of a given `RoomXY` in the given direction, returning
266-
/// `None` if the result is outside the valid room area.
267-
///
268-
/// Example usage:
269-
///
270-
/// ```
271-
/// use screeps::{constants::Direction::*, local::RoomXY};
272-
///
273-
/// let zero = unsafe { RoomXY::unchecked_new(0, 0) };
274-
/// let one = unsafe { RoomXY::unchecked_new(1, 1) };
275-
/// let forty_nine = unsafe { RoomXY::unchecked_new(49, 49) };
276-
///
277-
/// assert_eq!(zero.checked_add_direction(BottomRight), Some(one));
278-
/// assert_eq!(zero.checked_add_direction(TopLeft), None);
279-
/// assert_eq!(one.checked_add_direction(TopLeft), Some(zero));
280-
/// assert_eq!(forty_nine.checked_add_direction(BottomRight), None);
281-
/// ```
282-
pub fn checked_add_direction(self, rhs: Direction) -> Option<RoomXY> {
283-
let (dx, dy) = rhs.into();
284-
self.checked_add((dx as i8, dy as i8))
285-
}
286-
287-
/// Get the neighbor of a given `RoomXY` in the given direction, saturating
288-
/// at the edges if the result is outside the valid room area.
289-
///
290-
/// Example usage:
291-
///
292-
/// ```
293-
/// use screeps::{constants::Direction::*, local::RoomXY};
294-
///
295-
/// let zero = unsafe { RoomXY::unchecked_new(0, 0) };
296-
/// let one = unsafe { RoomXY::unchecked_new(1, 1) };
297-
/// let forty_nine = unsafe { RoomXY::unchecked_new(49, 49) };
298-
///
299-
/// assert_eq!(zero.saturating_add_direction(BottomRight), one);
300-
/// assert_eq!(zero.saturating_add_direction(TopLeft), zero);
301-
/// assert_eq!(one.saturating_add_direction(TopLeft), zero);
302-
/// assert_eq!(forty_nine.saturating_add_direction(BottomRight), forty_nine);
303-
/// ```
304-
pub fn saturating_add_direction(self, rhs: Direction) -> RoomXY {
305-
let (dx, dy) = rhs.into();
306-
self.saturating_add((dx as i8, dy as i8))
307-
}
308-
}
309-
310-
impl fmt::Display for RoomXY {
311-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312-
write!(f, "({}, {})", self.x, self.y)
313-
}
314-
}
315-
316129
impl From<RoomCoordinate> for u8 {
317130
fn from(coord: RoomCoordinate) -> u8 {
318131
coord.0
@@ -326,85 +139,3 @@ impl TryFrom<u8> for RoomCoordinate {
326139
RoomCoordinate::new(coord)
327140
}
328141
}
329-
330-
impl From<RoomXY> for (u8, u8) {
331-
fn from(xy: RoomXY) -> (u8, u8) {
332-
(xy.x.0, xy.y.0)
333-
}
334-
}
335-
336-
impl TryFrom<(u8, u8)> for RoomXY {
337-
type Error = OutOfBoundsError;
338-
339-
fn try_from(xy: (u8, u8)) -> Result<RoomXY, OutOfBoundsError> {
340-
Ok(RoomXY {
341-
x: RoomCoordinate::try_from(xy.0)?,
342-
y: RoomCoordinate::try_from(xy.1)?,
343-
})
344-
}
345-
}
346-
347-
impl From<(RoomCoordinate, RoomCoordinate)> for RoomXY {
348-
fn from(xy: (RoomCoordinate, RoomCoordinate)) -> RoomXY {
349-
RoomXY { x: xy.0, y: xy.1 }
350-
}
351-
}
352-
353-
impl From<RoomXY> for (RoomCoordinate, RoomCoordinate) {
354-
fn from(xy: RoomXY) -> (RoomCoordinate, RoomCoordinate) {
355-
(xy.x, xy.y)
356-
}
357-
}
358-
359-
#[derive(Serialize, Deserialize)]
360-
struct ReadableXY {
361-
x: RoomCoordinate,
362-
y: RoomCoordinate,
363-
}
364-
365-
impl From<ReadableXY> for RoomXY {
366-
fn from(ReadableXY { x, y }: ReadableXY) -> RoomXY {
367-
RoomXY { x, y }
368-
}
369-
}
370-
371-
impl From<RoomXY> for ReadableXY {
372-
fn from(RoomXY { x, y }: RoomXY) -> ReadableXY {
373-
ReadableXY { x, y }
374-
}
375-
}
376-
377-
impl Serialize for RoomXY {
378-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
379-
where
380-
S: Serializer,
381-
{
382-
if serializer.is_human_readable() {
383-
ReadableXY::from(*self).serialize(serializer)
384-
} else {
385-
let xy: (u8, u8) = (*self).into();
386-
let packed: u16 = ((xy.0 as u16) << 8) | (xy.1 as u16);
387-
packed.serialize(serializer)
388-
}
389-
}
390-
}
391-
392-
impl<'de> Deserialize<'de> for RoomXY {
393-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
394-
where
395-
D: Deserializer<'de>,
396-
{
397-
if deserializer.is_human_readable() {
398-
ReadableXY::deserialize(deserializer).map(Into::into)
399-
} else {
400-
let packed = u16::deserialize(deserializer)?;
401-
let xy = (((packed >> 8) & 0xFF) as u8, (packed & 0xFF) as u8);
402-
RoomXY::try_from(xy).map_err(|err: OutOfBoundsError| {
403-
de::Error::invalid_value(
404-
de::Unexpected::Unsigned(err.0 as u64),
405-
&format!("a non-negative integer less-than {ROOM_SIZE}").as_str(),
406-
)
407-
})
408-
}
409-
}
410-
}

0 commit comments

Comments
 (0)