screeps/enums/action_error_codes/
creep_error_codes.rs

1use std::{error::Error, fmt};
2
3use num_derive::FromPrimitive;
4use serde_repr::{Deserialize_repr, Serialize_repr};
5
6use crate::{constants::ErrorCode, FromReturnCode};
7
8/// Error codes used by [Creep::claim_reactor](crate::Creep::claim_reactor).
9///
10/// [Screeps API Docs](https://docs-season.screeps.com/api/#Creep.claimReactor).
11///
12/// [Screeps Engine Source Code](https://github.com/screeps/mod-season5/blob/master/src/creep.claimReactor.js#L14)
13#[cfg(feature = "seasonal-season-5")]
14#[derive(
15    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
16)]
17#[repr(i8)]
18pub enum CreepClaimReactorErrorCode {
19    NotOwner = -1,
20    Busy = -4,
21    InvalidTarget = -7,
22    NotInRange = -9,
23    NoBodypart = -12,
24}
25
26#[cfg(feature = "seasonal-season-5")]
27impl FromReturnCode for CreepClaimReactorErrorCode {
28    type Error = Self;
29
30    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
31        let maybe_result = Self::try_result_from_i8(val);
32        #[cfg(feature = "unsafe-return-conversion")]
33        unsafe {
34            maybe_result.unwrap_unchecked()
35        }
36        #[cfg(not(feature = "unsafe-return-conversion"))]
37        maybe_result.unwrap()
38    }
39
40    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
41        match val {
42            0 => Some(Ok(())),
43            -1 => Some(Err(CreepClaimReactorErrorCode::NotOwner)),
44            -4 => Some(Err(CreepClaimReactorErrorCode::Busy)),
45            -7 => Some(Err(CreepClaimReactorErrorCode::InvalidTarget)),
46            -9 => Some(Err(CreepClaimReactorErrorCode::NotInRange)),
47            -12 => Some(Err(CreepClaimReactorErrorCode::NoBodypart)),
48            _ => None,
49        }
50    }
51}
52
53#[cfg(feature = "seasonal-season-5")]
54impl fmt::Display for CreepClaimReactorErrorCode {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        let msg: &'static str = match self {
57            CreepClaimReactorErrorCode::NotOwner => "you are not the owner of this creep",
58            CreepClaimReactorErrorCode::Busy => "the creep is still being spawned",
59            CreepClaimReactorErrorCode::InvalidTarget => "the target is not a reactor",
60            CreepClaimReactorErrorCode::NotInRange => "the target is too far away",
61            CreepClaimReactorErrorCode::NoBodypart => {
62                "there are no claim body parts in this creep’s body"
63            }
64        };
65
66        write!(f, "{}", msg)
67    }
68}
69
70#[cfg(feature = "seasonal-season-5")]
71impl Error for CreepClaimReactorErrorCode {}
72
73#[cfg(feature = "seasonal-season-5")]
74impl From<CreepClaimReactorErrorCode> for ErrorCode {
75    fn from(value: CreepClaimReactorErrorCode) -> Self {
76        // Safety: CreepClaimReactorErrorCode is repr(i8), so we can cast it to get the
77        // discriminant value, which will match the raw return code value that ErrorCode
78        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
79        // Safety: CreepClaimReactorErrorCode discriminants are always error code
80        // values, and thus the Result returned here will always be an `Err` variant, so
81        // we can always extract the error without panicking
82        Self::result_from_i8(value as i8).unwrap_err()
83    }
84}
85
86/// Error codes used by [Creep::attack](crate::Creep::attack).
87///
88/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.attack).
89///
90/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L593)
91#[derive(
92    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
93)]
94#[repr(i8)]
95pub enum CreepAttackErrorCode {
96    NotOwner = -1,
97    Busy = -4,
98    InvalidTarget = -7,
99    NotInRange = -9,
100    NoBodypart = -12,
101}
102
103impl FromReturnCode for CreepAttackErrorCode {
104    type Error = Self;
105
106    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
107        let maybe_result = Self::try_result_from_i8(val);
108        #[cfg(feature = "unsafe-return-conversion")]
109        unsafe {
110            maybe_result.unwrap_unchecked()
111        }
112        #[cfg(not(feature = "unsafe-return-conversion"))]
113        maybe_result.unwrap()
114    }
115
116    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
117        match val {
118            0 => Some(Ok(())),
119            -1 => Some(Err(CreepAttackErrorCode::NotOwner)),
120            -4 => Some(Err(CreepAttackErrorCode::Busy)),
121            -7 => Some(Err(CreepAttackErrorCode::InvalidTarget)),
122            -9 => Some(Err(CreepAttackErrorCode::NotInRange)),
123            -12 => Some(Err(CreepAttackErrorCode::NoBodypart)),
124            _ => None,
125        }
126    }
127}
128
129impl fmt::Display for CreepAttackErrorCode {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        let msg: &'static str = match self {
132            CreepAttackErrorCode::NotOwner => "you are not the owner of this creep",
133            CreepAttackErrorCode::Busy => "the creep is still being spawned",
134            CreepAttackErrorCode::InvalidTarget => "the target is not a valid attackable object",
135            CreepAttackErrorCode::NotInRange => "the target is too far away",
136            CreepAttackErrorCode::NoBodypart => {
137                "there are no attack body parts in this creep’s body"
138            }
139        };
140
141        write!(f, "{}", msg)
142    }
143}
144
145impl Error for CreepAttackErrorCode {}
146
147impl From<CreepAttackErrorCode> for ErrorCode {
148    fn from(value: CreepAttackErrorCode) -> Self {
149        // Safety: CreepAttackErrorCode is repr(i8), so we can cast it to get the
150        // discriminant value, which will match the raw return code value that ErrorCode
151        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
152        // Safety: CreepAttackErrorCode discriminants are always error code values, and
153        // thus the Result returned here will always be an `Err` variant, so we can
154        // always extract the error without panicking
155        Self::result_from_i8(value as i8).unwrap_err()
156    }
157}
158
159/// Error codes used by
160/// [Creep::attack_controller](crate::Creep::attack_controller).
161///
162/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.attackController).
163///
164/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L885)
165#[derive(
166    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
167)]
168#[repr(i8)]
169pub enum AttackControllerErrorCode {
170    NotOwner = -1,
171    Busy = -4,
172    InvalidTarget = -7,
173    NotInRange = -9,
174    Tired = -11,
175    NoBodypart = -12,
176}
177
178impl FromReturnCode for AttackControllerErrorCode {
179    type Error = Self;
180
181    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
182        let maybe_result = Self::try_result_from_i8(val);
183        #[cfg(feature = "unsafe-return-conversion")]
184        unsafe {
185            maybe_result.unwrap_unchecked()
186        }
187        #[cfg(not(feature = "unsafe-return-conversion"))]
188        maybe_result.unwrap()
189    }
190
191    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
192        match val {
193            0 => Some(Ok(())),
194            -1 => Some(Err(AttackControllerErrorCode::NotOwner)),
195            -4 => Some(Err(AttackControllerErrorCode::Busy)),
196            -7 => Some(Err(AttackControllerErrorCode::InvalidTarget)),
197            -9 => Some(Err(AttackControllerErrorCode::NotInRange)),
198            -11 => Some(Err(AttackControllerErrorCode::Tired)),
199            -12 => Some(Err(AttackControllerErrorCode::NoBodypart)),
200            _ => None,
201        }
202    }
203}
204
205impl fmt::Display for AttackControllerErrorCode {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        let msg: &'static str = match self {
208            AttackControllerErrorCode::NotOwner => "you are not the owner of this creep",
209            AttackControllerErrorCode::Busy => "the creep is still being spawned",
210            AttackControllerErrorCode::InvalidTarget => {
211                "the target is not a valid owned or reserved controller object"
212            }
213            AttackControllerErrorCode::NotInRange => "the target is too far away",
214            AttackControllerErrorCode::Tired => {
215                "you have to wait until the next attack is possible"
216            }
217            AttackControllerErrorCode::NoBodypart => {
218                "there are not enough claim body parts in this creep’s body"
219            }
220        };
221
222        write!(f, "{}", msg)
223    }
224}
225
226impl Error for AttackControllerErrorCode {}
227
228impl From<AttackControllerErrorCode> for ErrorCode {
229    fn from(value: AttackControllerErrorCode) -> Self {
230        // Safety: AttackControllerErrorCode is repr(i8), so we can cast it to get the
231        // discriminant value, which will match the raw return code value that ErrorCode
232        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
233        // Safety: AttackControllerErrorCode discriminants are always error code values,
234        // and thus the Result returned here will always be an `Err` variant, so we can
235        // always extract the error without panicking
236        Self::result_from_i8(value as i8).unwrap_err()
237    }
238}
239
240/// Error codes used by [Creep::build](crate::Creep::build).
241///
242/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.build).
243///
244/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L762)
245#[derive(
246    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
247)]
248#[repr(i8)]
249pub enum BuildErrorCode {
250    NotOwner = -1,
251    Busy = -4,
252    NotEnoughResources = -6,
253    InvalidTarget = -7,
254    NotInRange = -9,
255    NoBodypart = -12,
256}
257
258impl FromReturnCode for BuildErrorCode {
259    type Error = Self;
260
261    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
262        let maybe_result = Self::try_result_from_i8(val);
263        #[cfg(feature = "unsafe-return-conversion")]
264        unsafe {
265            maybe_result.unwrap_unchecked()
266        }
267        #[cfg(not(feature = "unsafe-return-conversion"))]
268        maybe_result.unwrap()
269    }
270
271    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
272        match val {
273            0 => Some(Ok(())),
274            -1 => Some(Err(BuildErrorCode::NotOwner)),
275            -4 => Some(Err(BuildErrorCode::Busy)),
276            -6 => Some(Err(BuildErrorCode::NotEnoughResources)),
277            -7 => Some(Err(BuildErrorCode::InvalidTarget)),
278            -9 => Some(Err(BuildErrorCode::NotInRange)),
279            -12 => Some(Err(BuildErrorCode::NoBodypart)),
280            _ => None,
281        }
282    }
283}
284
285impl fmt::Display for BuildErrorCode {
286    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287        let msg: &'static str = match self {
288            BuildErrorCode::NotOwner => "you are not the owner of this creep",
289            BuildErrorCode::Busy => "the creep is still being spawned",
290            BuildErrorCode::NotEnoughResources => "the creep does not have any carried energy",
291            BuildErrorCode::InvalidTarget => "the target is not a valid construction site object or the structure cannot be built here (probably because of a creep at the same square)",
292            BuildErrorCode::NotInRange => "the target is too far away",
293            BuildErrorCode::NoBodypart => "there are no work body parts in this creep’s body",
294        };
295
296        write!(f, "{}", msg)
297    }
298}
299
300impl Error for BuildErrorCode {}
301
302impl From<BuildErrorCode> for ErrorCode {
303    fn from(value: BuildErrorCode) -> Self {
304        // Safety: BuildErrorCode is repr(i8), so we can cast it to get the discriminant
305        // value, which will match the raw return code value that ErrorCode expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
306        // Safety: BuildErrorCode discriminants are always error code values, and thus
307        // the Result returned here will always be an `Err` variant, so we can always
308        // extract the error without panicking
309        Self::result_from_i8(value as i8).unwrap_err()
310    }
311}
312
313/// Error codes used by [Creep::cancel_order](crate::Creep::cancel_order).
314///
315/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.cancelOrder).
316///
317/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L1008)
318#[derive(
319    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
320)]
321#[repr(i8)]
322pub enum CreepCancelOrderErrorCode {
323    NotFound = -5,
324}
325
326impl FromReturnCode for CreepCancelOrderErrorCode {
327    type Error = Self;
328
329    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
330        let maybe_result = Self::try_result_from_i8(val);
331        #[cfg(feature = "unsafe-return-conversion")]
332        unsafe {
333            maybe_result.unwrap_unchecked()
334        }
335        #[cfg(not(feature = "unsafe-return-conversion"))]
336        maybe_result.unwrap()
337    }
338
339    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
340        match val {
341            0 => Some(Ok(())),
342            -5 => Some(Err(CreepCancelOrderErrorCode::NotFound)),
343            _ => None,
344        }
345    }
346}
347
348impl fmt::Display for CreepCancelOrderErrorCode {
349    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350        let msg: &'static str = match self {
351            CreepCancelOrderErrorCode::NotFound => "the order with the specified name is not found",
352        };
353
354        write!(f, "{}", msg)
355    }
356}
357
358impl Error for CreepCancelOrderErrorCode {}
359
360impl From<CreepCancelOrderErrorCode> for ErrorCode {
361    fn from(value: CreepCancelOrderErrorCode) -> Self {
362        // Safety: CreepCancelOrderErrorCode is repr(i8), so we can cast it to get the
363        // discriminant value, which will match the raw return code value that ErrorCode
364        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
365        // Safety: CreepCancelOrderErrorCode discriminants are always error code values,
366        // and thus the Result returned here will always be an `Err` variant, so we can
367        // always extract the error without panicking
368        Self::result_from_i8(value as i8).unwrap_err()
369    }
370}
371
372/// Error codes used by
373/// [Creep::claim_controller](crate::Creep::claim_controller).
374///
375/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.claimController).
376///
377/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L839)
378#[derive(
379    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
380)]
381#[repr(i8)]
382pub enum ClaimControllerErrorCode {
383    NotOwner = -1,
384    Busy = -4,
385    InvalidTarget = -7,
386    Full = -8,
387    NotInRange = -9,
388    NoBodypart = -12,
389    GclNotEnough = -15,
390}
391
392impl FromReturnCode for ClaimControllerErrorCode {
393    type Error = Self;
394
395    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
396        let maybe_result = Self::try_result_from_i8(val);
397        #[cfg(feature = "unsafe-return-conversion")]
398        unsafe {
399            maybe_result.unwrap_unchecked()
400        }
401        #[cfg(not(feature = "unsafe-return-conversion"))]
402        maybe_result.unwrap()
403    }
404
405    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
406        match val {
407            0 => Some(Ok(())),
408            -1 => Some(Err(ClaimControllerErrorCode::NotOwner)),
409            -4 => Some(Err(ClaimControllerErrorCode::Busy)),
410            -7 => Some(Err(ClaimControllerErrorCode::InvalidTarget)),
411            -8 => Some(Err(ClaimControllerErrorCode::Full)),
412            -9 => Some(Err(ClaimControllerErrorCode::NotInRange)),
413            -12 => Some(Err(ClaimControllerErrorCode::NoBodypart)),
414            -15 => Some(Err(ClaimControllerErrorCode::GclNotEnough)),
415            _ => None,
416        }
417    }
418}
419
420impl fmt::Display for ClaimControllerErrorCode {
421    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
422        let msg: &'static str = match self {
423            ClaimControllerErrorCode::NotOwner => "you are not the owner of this creep",
424            ClaimControllerErrorCode::Busy => "the creep is still being spawned",
425            ClaimControllerErrorCode::InvalidTarget => {
426                "the target is not a valid neutral controller object"
427            }
428            ClaimControllerErrorCode::Full => {
429                "you cannot claim more than 3 rooms in the novice area"
430            }
431            ClaimControllerErrorCode::NotInRange => "the target is too far away",
432            ClaimControllerErrorCode::NoBodypart => {
433                "there are no claim body parts in this creep’s body"
434            }
435            ClaimControllerErrorCode::GclNotEnough => "your global control level is not enough",
436        };
437
438        write!(f, "{}", msg)
439    }
440}
441
442impl Error for ClaimControllerErrorCode {}
443
444impl From<ClaimControllerErrorCode> for ErrorCode {
445    fn from(value: ClaimControllerErrorCode) -> Self {
446        // Safety: ClaimControllerErrorCode is repr(i8), so we can cast it to get the
447        // discriminant value, which will match the raw return code value that ErrorCode
448        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
449        // Safety: ClaimControllerErrorCode discriminants are always error code values,
450        // and thus the Result returned here will always be an `Err` variant, so we can
451        // always extract the error without panicking
452        Self::result_from_i8(value as i8).unwrap_err()
453    }
454}
455
456/// Error codes used by [Creep::dismantle](crate::Creep::dismantle).
457///
458/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.dismantle).
459///
460/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L1016)
461#[derive(
462    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
463)]
464#[repr(i8)]
465pub enum DismantleErrorCode {
466    NotOwner = -1,
467    Busy = -4,
468    InvalidTarget = -7,
469    NotInRange = -9,
470    NoBodypart = -12,
471}
472
473impl FromReturnCode for DismantleErrorCode {
474    type Error = Self;
475
476    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
477        let maybe_result = Self::try_result_from_i8(val);
478        #[cfg(feature = "unsafe-return-conversion")]
479        unsafe {
480            maybe_result.unwrap_unchecked()
481        }
482        #[cfg(not(feature = "unsafe-return-conversion"))]
483        maybe_result.unwrap()
484    }
485
486    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
487        match val {
488            0 => Some(Ok(())),
489            -1 => Some(Err(DismantleErrorCode::NotOwner)),
490            -4 => Some(Err(DismantleErrorCode::Busy)),
491            -7 => Some(Err(DismantleErrorCode::InvalidTarget)),
492            -9 => Some(Err(DismantleErrorCode::NotInRange)),
493            -12 => Some(Err(DismantleErrorCode::NoBodypart)),
494            _ => None,
495        }
496    }
497}
498
499impl fmt::Display for DismantleErrorCode {
500    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
501        let msg: &'static str = match self {
502            DismantleErrorCode::NotOwner => "you are not the owner of this creep",
503            DismantleErrorCode::Busy => "the creep is still being spawned",
504            DismantleErrorCode::InvalidTarget => "the target is not a valid structure object",
505            DismantleErrorCode::NotInRange => "the target is too far away",
506            DismantleErrorCode::NoBodypart => "there are no work body parts in this creep’s body",
507        };
508
509        write!(f, "{}", msg)
510    }
511}
512
513impl Error for DismantleErrorCode {}
514
515impl From<DismantleErrorCode> for ErrorCode {
516    fn from(value: DismantleErrorCode) -> Self {
517        // Safety: DismantleErrorCode is repr(i8), so we can cast it to get the
518        // discriminant value, which will match the raw return code value that ErrorCode
519        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
520        // Safety: DismantleErrorCode discriminants are always error code values, and
521        // thus the Result returned here will always be an `Err` variant, so we can
522        // always extract the error without panicking
523        Self::result_from_i8(value as i8).unwrap_err()
524    }
525}
526
527/// Error codes used by
528/// [Creep::generate_safe_mode](crate::Creep::generate_safe_mode).
529///
530/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.generateSafeMode).
531///
532/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L1049)
533#[derive(
534    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
535)]
536#[repr(i8)]
537pub enum GenerateSafeModeErrorCode {
538    NotOwner = -1,
539    Busy = -4,
540    NotEnoughResources = -6,
541    InvalidTarget = -7,
542    NotInRange = -9,
543}
544
545impl FromReturnCode for GenerateSafeModeErrorCode {
546    type Error = Self;
547
548    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
549        let maybe_result = Self::try_result_from_i8(val);
550        #[cfg(feature = "unsafe-return-conversion")]
551        unsafe {
552            maybe_result.unwrap_unchecked()
553        }
554        #[cfg(not(feature = "unsafe-return-conversion"))]
555        maybe_result.unwrap()
556    }
557
558    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
559        match val {
560            0 => Some(Ok(())),
561            -1 => Some(Err(GenerateSafeModeErrorCode::NotOwner)),
562            -4 => Some(Err(GenerateSafeModeErrorCode::Busy)),
563            -6 => Some(Err(GenerateSafeModeErrorCode::NotEnoughResources)),
564            -7 => Some(Err(GenerateSafeModeErrorCode::InvalidTarget)),
565            -9 => Some(Err(GenerateSafeModeErrorCode::NotInRange)),
566            _ => None,
567        }
568    }
569}
570
571impl fmt::Display for GenerateSafeModeErrorCode {
572    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
573        let msg: &'static str = match self {
574            GenerateSafeModeErrorCode::NotOwner => "you are not the owner of this creep",
575            GenerateSafeModeErrorCode::Busy => "the creep is still being spawned",
576            GenerateSafeModeErrorCode::NotEnoughResources => {
577                "the creep does not have enough ghodium"
578            }
579            GenerateSafeModeErrorCode::InvalidTarget => {
580                "the target is not a valid controller object"
581            }
582            GenerateSafeModeErrorCode::NotInRange => "the target is too far away",
583        };
584
585        write!(f, "{}", msg)
586    }
587}
588
589impl Error for GenerateSafeModeErrorCode {}
590
591impl From<GenerateSafeModeErrorCode> for ErrorCode {
592    fn from(value: GenerateSafeModeErrorCode) -> Self {
593        // Safety: GenerateSafeModeErrorCode is repr(i8), so we can cast it to get the
594        // discriminant value, which will match the raw return code value that ErrorCode
595        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
596        // Safety: GenerateSafeModeErrorCode discriminants are always error code values,
597        // and thus the Result returned here will always be an `Err` variant, so we can
598        // always extract the error without panicking
599        Self::result_from_i8(value as i8).unwrap_err()
600    }
601}
602
603/// Error codes used by [Creep::harvest](crate::Creep::harvest).
604///
605/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.harvest).
606///
607/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L335)
608#[derive(
609    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
610)]
611#[repr(i8)]
612pub enum HarvestErrorCode {
613    NotOwner = -1,
614    Busy = -4,
615    NotFound = -5,
616    NotEnoughResources = -6,
617    InvalidTarget = -7,
618    NotInRange = -9,
619    Tired = -11,
620    NoBodypart = -12,
621    RclNotEnough = -14,
622}
623
624impl FromReturnCode for HarvestErrorCode {
625    type Error = Self;
626
627    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
628        let maybe_result = Self::try_result_from_i8(val);
629        #[cfg(feature = "unsafe-return-conversion")]
630        unsafe {
631            maybe_result.unwrap_unchecked()
632        }
633        #[cfg(not(feature = "unsafe-return-conversion"))]
634        maybe_result.unwrap()
635    }
636
637    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
638        match val {
639            0 => Some(Ok(())),
640            -1 => Some(Err(HarvestErrorCode::NotOwner)),
641            -4 => Some(Err(HarvestErrorCode::Busy)),
642            -5 => Some(Err(HarvestErrorCode::NotFound)),
643            -6 => Some(Err(HarvestErrorCode::NotEnoughResources)),
644            -7 => Some(Err(HarvestErrorCode::InvalidTarget)),
645            -9 => Some(Err(HarvestErrorCode::NotInRange)),
646            -11 => Some(Err(HarvestErrorCode::Tired)),
647            -12 => Some(Err(HarvestErrorCode::NoBodypart)),
648            -14 => Some(Err(HarvestErrorCode::RclNotEnough)),
649            _ => None,
650        }
651    }
652}
653
654impl fmt::Display for HarvestErrorCode {
655    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
656        let msg: &'static str = match self {
657            HarvestErrorCode::NotOwner => "you are not the owner of this creep, or the room controller is owned or reserved by another player",
658            HarvestErrorCode::Busy => "the creep is still being spawned",
659            HarvestErrorCode::NotFound => "extractor not found. you must build an extractor structure to harvest minerals. learn more",
660            HarvestErrorCode::NotEnoughResources => "the target does not contain any harvestable energy or mineral",
661            HarvestErrorCode::InvalidTarget => "the target is not a valid source or mineral object",
662            HarvestErrorCode::NotInRange => "the target is too far away",
663            HarvestErrorCode::Tired => "the extractor or the deposit is still cooling down",
664            HarvestErrorCode::NoBodypart => "there are no work body parts in this creep’s body",
665            HarvestErrorCode::RclNotEnough => "room controller level insufficient to use the extractor",
666        };
667
668        write!(f, "{}", msg)
669    }
670}
671
672impl Error for HarvestErrorCode {}
673
674impl From<HarvestErrorCode> for ErrorCode {
675    fn from(value: HarvestErrorCode) -> Self {
676        // Safety: HarvestErrorCode is repr(i8), so we can cast it to get the
677        // discriminant value, which will match the raw return code value that ErrorCode
678        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
679        // Safety: HarvestErrorCode discriminants are always error code values, and thus
680        // the Result returned here will always be an `Err` variant, so we can always
681        // extract the error without panicking
682        Self::result_from_i8(value as i8).unwrap_err()
683    }
684}
685
686/// Error codes used by [Creep::heal](crate::Creep::heal).
687///
688/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.heal).
689///
690/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L678)
691#[derive(
692    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
693)]
694#[repr(i8)]
695pub enum CreepHealErrorCode {
696    NotOwner = -1,
697    Busy = -4,
698    InvalidTarget = -7,
699    NotInRange = -9,
700    NoBodypart = -12,
701}
702
703impl FromReturnCode for CreepHealErrorCode {
704    type Error = Self;
705
706    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
707        let maybe_result = Self::try_result_from_i8(val);
708        #[cfg(feature = "unsafe-return-conversion")]
709        unsafe {
710            maybe_result.unwrap_unchecked()
711        }
712        #[cfg(not(feature = "unsafe-return-conversion"))]
713        maybe_result.unwrap()
714    }
715
716    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
717        match val {
718            0 => Some(Ok(())),
719            -1 => Some(Err(CreepHealErrorCode::NotOwner)),
720            -4 => Some(Err(CreepHealErrorCode::Busy)),
721            -7 => Some(Err(CreepHealErrorCode::InvalidTarget)),
722            -9 => Some(Err(CreepHealErrorCode::NotInRange)),
723            -12 => Some(Err(CreepHealErrorCode::NoBodypart)),
724            _ => None,
725        }
726    }
727}
728
729impl fmt::Display for CreepHealErrorCode {
730    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
731        let msg: &'static str = match self {
732            CreepHealErrorCode::NotOwner => "you are not the owner of this creep",
733            CreepHealErrorCode::Busy => "the creep is still being spawned",
734            CreepHealErrorCode::InvalidTarget => "the target is not a valid creep object",
735            CreepHealErrorCode::NotInRange => "the target is too far away",
736            CreepHealErrorCode::NoBodypart => "there are no heal body parts in this creep’s body",
737        };
738
739        write!(f, "{}", msg)
740    }
741}
742
743impl Error for CreepHealErrorCode {}
744
745impl From<CreepHealErrorCode> for ErrorCode {
746    fn from(value: CreepHealErrorCode) -> Self {
747        // Safety: CreepHealErrorCode is repr(i8), so we can cast it to get the
748        // discriminant value, which will match the raw return code value that ErrorCode
749        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
750        // Safety: CreepHealErrorCode discriminants are always error code values, and
751        // thus the Result returned here will always be an `Err` variant, so we can
752        // always extract the error without panicking
753        Self::result_from_i8(value as i8).unwrap_err()
754    }
755}
756
757/// Error codes used by [Creep::move_direction](crate::Creep::move_direction).
758///
759/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.move).
760///
761/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L126)
762#[derive(
763    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
764)]
765#[repr(i8)]
766pub enum CreepMoveDirectionErrorCode {
767    NotOwner = -1,
768    Busy = -4,
769    InvalidArgs = -10,
770    Tired = -11,
771    NoBodypart = -12,
772}
773
774impl FromReturnCode for CreepMoveDirectionErrorCode {
775    type Error = Self;
776
777    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
778        let maybe_result = Self::try_result_from_i8(val);
779        #[cfg(feature = "unsafe-return-conversion")]
780        unsafe {
781            maybe_result.unwrap_unchecked()
782        }
783        #[cfg(not(feature = "unsafe-return-conversion"))]
784        maybe_result.unwrap()
785    }
786
787    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
788        match val {
789            0 => Some(Ok(())),
790            -1 => Some(Err(CreepMoveDirectionErrorCode::NotOwner)),
791            -4 => Some(Err(CreepMoveDirectionErrorCode::Busy)),
792            -10 => Some(Err(CreepMoveDirectionErrorCode::InvalidArgs)),
793            -11 => Some(Err(CreepMoveDirectionErrorCode::Tired)),
794            -12 => Some(Err(CreepMoveDirectionErrorCode::NoBodypart)),
795            _ => None,
796        }
797    }
798}
799
800impl fmt::Display for CreepMoveDirectionErrorCode {
801    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
802        let msg: &'static str = match self {
803            CreepMoveDirectionErrorCode::NotOwner => "you are not the owner of this creep",
804            CreepMoveDirectionErrorCode::Busy => "the creep is still being spawned",
805            CreepMoveDirectionErrorCode::InvalidArgs => "the provided direction is incorrect",
806            CreepMoveDirectionErrorCode::Tired => "the fatigue indicator of the creep is non-zero",
807            CreepMoveDirectionErrorCode::NoBodypart => {
808                "there are no move body parts in this creep’s body"
809            }
810        };
811
812        write!(f, "{}", msg)
813    }
814}
815
816impl Error for CreepMoveDirectionErrorCode {}
817
818impl From<CreepMoveDirectionErrorCode> for ErrorCode {
819    fn from(value: CreepMoveDirectionErrorCode) -> Self {
820        // Safety: CreepMoveDirectionErrorCode is repr(i8), so we can cast it to get the
821        // discriminant value, which will match the raw return code value that ErrorCode
822        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
823        // Safety: CreepMoveDirectionErrorCode discriminants are always error code
824        // values, and thus the Result returned here will always be an `Err` variant, so
825        // we can always extract the error without panicking
826        Self::result_from_i8(value as i8).unwrap_err()
827    }
828}
829
830/// Error codes used by [Creep::move_pulled_by](crate::Creep::move_pulled_by).
831///
832/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.move).
833///
834/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L126)
835#[derive(
836    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
837)]
838#[repr(i8)]
839pub enum CreepMovePulledByErrorCode {
840    NotOwner = -1,
841    Busy = -4,
842    NotInRange = -9,
843    InvalidArgs = -10,
844}
845
846impl FromReturnCode for CreepMovePulledByErrorCode {
847    type Error = Self;
848
849    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
850        let maybe_result = Self::try_result_from_i8(val);
851        #[cfg(feature = "unsafe-return-conversion")]
852        unsafe {
853            maybe_result.unwrap_unchecked()
854        }
855        #[cfg(not(feature = "unsafe-return-conversion"))]
856        maybe_result.unwrap()
857    }
858
859    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
860        match val {
861            0 => Some(Ok(())),
862            -1 => Some(Err(CreepMovePulledByErrorCode::NotOwner)),
863            -4 => Some(Err(CreepMovePulledByErrorCode::Busy)),
864            -9 => Some(Err(CreepMovePulledByErrorCode::NotInRange)),
865            -10 => Some(Err(CreepMovePulledByErrorCode::InvalidArgs)),
866            _ => None,
867        }
868    }
869}
870
871impl fmt::Display for CreepMovePulledByErrorCode {
872    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
873        let msg: &'static str = match self {
874            CreepMovePulledByErrorCode::NotOwner => "you are not the owner of this creep",
875            CreepMovePulledByErrorCode::Busy => "the creep is still being spawned",
876            CreepMovePulledByErrorCode::NotInRange => "the target creep is too far away",
877            CreepMovePulledByErrorCode::InvalidArgs => "the provided direction is incorrect",
878        };
879
880        write!(f, "{}", msg)
881    }
882}
883
884impl Error for CreepMovePulledByErrorCode {}
885
886impl From<CreepMovePulledByErrorCode> for ErrorCode {
887    fn from(value: CreepMovePulledByErrorCode) -> Self {
888        // Safety: CreepMovePulledByErrorCode is repr(i8), so we can cast it to get the
889        // discriminant value, which will match the raw return code value that ErrorCode
890        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
891        // Safety: CreepMovePulledByErrorCode discriminants are always error code
892        // values, and thus the Result returned here will always be an `Err` variant, so
893        // we can always extract the error without panicking
894        Self::result_from_i8(value as i8).unwrap_err()
895    }
896}
897
898/// Error codes used by [Creep::move_by_path](crate::Creep::move_by_path).
899///
900/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.moveByPath).
901///
902/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L305)
903#[derive(
904    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
905)]
906#[repr(i8)]
907pub enum CreepMoveByPathErrorCode {
908    NotOwner = -1,
909    Busy = -4,
910    NotFound = -5,
911    InvalidArgs = -10,
912    Tired = -11,
913    NoBodypart = -12,
914}
915
916impl FromReturnCode for CreepMoveByPathErrorCode {
917    type Error = Self;
918
919    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
920        let maybe_result = Self::try_result_from_i8(val);
921        #[cfg(feature = "unsafe-return-conversion")]
922        unsafe {
923            maybe_result.unwrap_unchecked()
924        }
925        #[cfg(not(feature = "unsafe-return-conversion"))]
926        maybe_result.unwrap()
927    }
928
929    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
930        match val {
931            0 => Some(Ok(())),
932            -1 => Some(Err(CreepMoveByPathErrorCode::NotOwner)),
933            -4 => Some(Err(CreepMoveByPathErrorCode::Busy)),
934            -5 => Some(Err(CreepMoveByPathErrorCode::NotFound)),
935            -10 => Some(Err(CreepMoveByPathErrorCode::InvalidArgs)),
936            -11 => Some(Err(CreepMoveByPathErrorCode::Tired)),
937            -12 => Some(Err(CreepMoveByPathErrorCode::NoBodypart)),
938            _ => None,
939        }
940    }
941}
942
943impl fmt::Display for CreepMoveByPathErrorCode {
944    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
945        let msg: &'static str = match self {
946            CreepMoveByPathErrorCode::NotOwner => "you are not the owner of this creep",
947            CreepMoveByPathErrorCode::Busy => "the creep is still being spawned",
948            CreepMoveByPathErrorCode::NotFound => {
949                "the specified path doesn't match the creep's location"
950            }
951            CreepMoveByPathErrorCode::InvalidArgs => "path is not a valid path array",
952            CreepMoveByPathErrorCode::Tired => "the fatigue indicator of the creep is non-zero",
953            CreepMoveByPathErrorCode::NoBodypart => {
954                "there are no move body parts in this creep’s body"
955            }
956        };
957
958        write!(f, "{}", msg)
959    }
960}
961
962impl Error for CreepMoveByPathErrorCode {}
963
964impl From<CreepMoveByPathErrorCode> for ErrorCode {
965    fn from(value: CreepMoveByPathErrorCode) -> Self {
966        // Safety: CreepMoveByPathErrorCode is repr(i8), so we can cast it to get the
967        // discriminant value, which will match the raw return code value that ErrorCode
968        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
969        // Safety: CreepMoveByPathErrorCode discriminants are always error code values,
970        // and thus the Result returned here will always be an `Err` variant, so we can
971        // always extract the error without panicking
972        Self::result_from_i8(value as i8).unwrap_err()
973    }
974}
975
976/// Error codes used by [Creep::move_to](crate::Creep#method.move_to).
977///
978/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.moveTo).
979///
980/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L158)
981#[derive(
982    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
983)]
984#[repr(i8)]
985pub enum CreepMoveToErrorCode {
986    NotOwner = -1,
987    NoPath = -2,
988    Busy = -4,
989    NotFound = -5,
990    InvalidTarget = -7,
991    Tired = -11,
992    NoBodypart = -12,
993}
994
995impl FromReturnCode for CreepMoveToErrorCode {
996    type Error = Self;
997
998    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
999        let maybe_result = Self::try_result_from_i8(val);
1000        #[cfg(feature = "unsafe-return-conversion")]
1001        unsafe {
1002            maybe_result.unwrap_unchecked()
1003        }
1004        #[cfg(not(feature = "unsafe-return-conversion"))]
1005        maybe_result.unwrap()
1006    }
1007
1008    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1009        match val {
1010            0 => Some(Ok(())),
1011            -1 => Some(Err(CreepMoveToErrorCode::NotOwner)),
1012            -2 => Some(Err(CreepMoveToErrorCode::NoPath)),
1013            -4 => Some(Err(CreepMoveToErrorCode::Busy)),
1014            -5 => Some(Err(CreepMoveToErrorCode::NotFound)),
1015            -7 => Some(Err(CreepMoveToErrorCode::InvalidTarget)),
1016            -11 => Some(Err(CreepMoveToErrorCode::Tired)),
1017            -12 => Some(Err(CreepMoveToErrorCode::NoBodypart)),
1018            _ => None,
1019        }
1020    }
1021}
1022
1023impl fmt::Display for CreepMoveToErrorCode {
1024    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1025        let msg: &'static str = match self {
1026            CreepMoveToErrorCode::NotOwner => "you are not the owner of this creep",
1027            CreepMoveToErrorCode::NoPath => "no path to the target could be found",
1028            CreepMoveToErrorCode::Busy => "the creep is still being spawned",
1029            CreepMoveToErrorCode::NotFound => "the creep has no memorized path to reuse",
1030            CreepMoveToErrorCode::InvalidTarget => "the target provided is invalid",
1031            CreepMoveToErrorCode::Tired => "the fatigue indicator of the creep is non-zero",
1032            CreepMoveToErrorCode::NoBodypart => "there are no move body parts in this creep’s body",
1033        };
1034
1035        write!(f, "{}", msg)
1036    }
1037}
1038
1039impl Error for CreepMoveToErrorCode {}
1040
1041impl From<CreepMoveToErrorCode> for ErrorCode {
1042    fn from(value: CreepMoveToErrorCode) -> Self {
1043        // Safety: CreepMoveToErrorCode is repr(i8), so we can cast it to get the
1044        // discriminant value, which will match the raw return code value that ErrorCode
1045        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1046        // Safety: CreepMoveToErrorCode discriminants are always error code values, and
1047        // thus the Result returned here will always be an `Err` variant, so we can
1048        // always extract the error without panicking
1049        Self::result_from_i8(value as i8).unwrap_err()
1050    }
1051}
1052
1053/// Error codes used by [Creep::pull](crate::Creep::pull).
1054///
1055/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.pull).
1056///
1057/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L1093)
1058#[derive(
1059    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
1060)]
1061#[repr(i8)]
1062pub enum PullErrorCode {
1063    NotOwner = -1,
1064    Busy = -4,
1065    InvalidTarget = -7,
1066    NotInRange = -9,
1067}
1068
1069impl FromReturnCode for PullErrorCode {
1070    type Error = Self;
1071
1072    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
1073        let maybe_result = Self::try_result_from_i8(val);
1074        #[cfg(feature = "unsafe-return-conversion")]
1075        unsafe {
1076            maybe_result.unwrap_unchecked()
1077        }
1078        #[cfg(not(feature = "unsafe-return-conversion"))]
1079        maybe_result.unwrap()
1080    }
1081
1082    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1083        match val {
1084            0 => Some(Ok(())),
1085            -1 => Some(Err(PullErrorCode::NotOwner)),
1086            -4 => Some(Err(PullErrorCode::Busy)),
1087            -7 => Some(Err(PullErrorCode::InvalidTarget)),
1088            -9 => Some(Err(PullErrorCode::NotInRange)),
1089            _ => None,
1090        }
1091    }
1092}
1093
1094impl fmt::Display for PullErrorCode {
1095    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1096        let msg: &'static str = match self {
1097            PullErrorCode::NotOwner => "you are not the owner of this creep",
1098            PullErrorCode::Busy => "the creep is still being spawned",
1099            PullErrorCode::InvalidTarget => "the target provided is invalid",
1100            PullErrorCode::NotInRange => "the target is too far away",
1101        };
1102
1103        write!(f, "{}", msg)
1104    }
1105}
1106
1107impl Error for PullErrorCode {}
1108
1109impl From<PullErrorCode> for ErrorCode {
1110    fn from(value: PullErrorCode) -> Self {
1111        // Safety: PullErrorCode is repr(i8), so we can cast it to get the discriminant
1112        // value, which will match the raw return code value that ErrorCode expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1113        // Safety: PullErrorCode discriminants are always error code values, and thus
1114        // the Result returned here will always be an `Err` variant, so we can always
1115        // extract the error without panicking
1116        Self::result_from_i8(value as i8).unwrap_err()
1117    }
1118}
1119
1120/// Error codes used by [Creep::ranged_attack](crate::Creep::ranged_attack).
1121///
1122/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.rangedAttack).
1123///
1124/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L626)
1125#[derive(
1126    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
1127)]
1128#[repr(i8)]
1129pub enum RangedAttackErrorCode {
1130    NotOwner = -1,
1131    Busy = -4,
1132    InvalidTarget = -7,
1133    NotInRange = -9,
1134    NoBodypart = -12,
1135}
1136
1137impl FromReturnCode for RangedAttackErrorCode {
1138    type Error = Self;
1139
1140    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
1141        let maybe_result = Self::try_result_from_i8(val);
1142        #[cfg(feature = "unsafe-return-conversion")]
1143        unsafe {
1144            maybe_result.unwrap_unchecked()
1145        }
1146        #[cfg(not(feature = "unsafe-return-conversion"))]
1147        maybe_result.unwrap()
1148    }
1149
1150    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1151        match val {
1152            0 => Some(Ok(())),
1153            -1 => Some(Err(RangedAttackErrorCode::NotOwner)),
1154            -4 => Some(Err(RangedAttackErrorCode::Busy)),
1155            -7 => Some(Err(RangedAttackErrorCode::InvalidTarget)),
1156            -9 => Some(Err(RangedAttackErrorCode::NotInRange)),
1157            -12 => Some(Err(RangedAttackErrorCode::NoBodypart)),
1158            _ => None,
1159        }
1160    }
1161}
1162
1163impl fmt::Display for RangedAttackErrorCode {
1164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1165        let msg: &'static str = match self {
1166            RangedAttackErrorCode::NotOwner => "you are not the owner of this creep",
1167            RangedAttackErrorCode::Busy => "the creep is still being spawned",
1168            RangedAttackErrorCode::InvalidTarget => "the target is not a valid attackable object",
1169            RangedAttackErrorCode::NotInRange => "the target is too far away",
1170            RangedAttackErrorCode::NoBodypart => {
1171                "there are no ranged_attack body parts in this creep’s body"
1172            }
1173        };
1174
1175        write!(f, "{}", msg)
1176    }
1177}
1178
1179impl Error for RangedAttackErrorCode {}
1180
1181impl From<RangedAttackErrorCode> for ErrorCode {
1182    fn from(value: RangedAttackErrorCode) -> Self {
1183        // Safety: RangedAttackErrorCode is repr(i8), so we can cast it to get the
1184        // discriminant value, which will match the raw return code value that ErrorCode
1185        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1186        // Safety: RangedAttackErrorCode discriminants are always error code values, and
1187        // thus the Result returned here will always be an `Err` variant, so we can
1188        // always extract the error without panicking
1189        Self::result_from_i8(value as i8).unwrap_err()
1190    }
1191}
1192
1193/// Error codes used by [Creep::ranged_heal](crate::Creep::ranged_heal).
1194///
1195/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.rangedHeal).
1196///
1197/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L706)
1198#[derive(
1199    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
1200)]
1201#[repr(i8)]
1202pub enum RangedHealErrorCode {
1203    NotOwner = -1,
1204    Busy = -4,
1205    InvalidTarget = -7,
1206    NotInRange = -9,
1207    NoBodypart = -12,
1208}
1209
1210impl FromReturnCode for RangedHealErrorCode {
1211    type Error = Self;
1212
1213    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
1214        let maybe_result = Self::try_result_from_i8(val);
1215        #[cfg(feature = "unsafe-return-conversion")]
1216        unsafe {
1217            maybe_result.unwrap_unchecked()
1218        }
1219        #[cfg(not(feature = "unsafe-return-conversion"))]
1220        maybe_result.unwrap()
1221    }
1222
1223    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1224        match val {
1225            0 => Some(Ok(())),
1226            -1 => Some(Err(RangedHealErrorCode::NotOwner)),
1227            -4 => Some(Err(RangedHealErrorCode::Busy)),
1228            -7 => Some(Err(RangedHealErrorCode::InvalidTarget)),
1229            -9 => Some(Err(RangedHealErrorCode::NotInRange)),
1230            -12 => Some(Err(RangedHealErrorCode::NoBodypart)),
1231            _ => None,
1232        }
1233    }
1234}
1235
1236impl fmt::Display for RangedHealErrorCode {
1237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1238        let msg: &'static str = match self {
1239            RangedHealErrorCode::NotOwner => "you are not the owner of this creep",
1240            RangedHealErrorCode::Busy => "the creep is still being spawned",
1241            RangedHealErrorCode::InvalidTarget => "the target is not a valid creep object",
1242            RangedHealErrorCode::NotInRange => "the target is too far away",
1243            RangedHealErrorCode::NoBodypart => "there are no heal body parts in this creep’s body",
1244        };
1245
1246        write!(f, "{}", msg)
1247    }
1248}
1249
1250impl Error for RangedHealErrorCode {}
1251
1252impl From<RangedHealErrorCode> for ErrorCode {
1253    fn from(value: RangedHealErrorCode) -> Self {
1254        // Safety: RangedHealErrorCode is repr(i8), so we can cast it to get the
1255        // discriminant value, which will match the raw return code value that ErrorCode
1256        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1257        // Safety: RangedHealErrorCode discriminants are always error code values, and
1258        // thus the Result returned here will always be an `Err` variant, so we can
1259        // always extract the error without panicking
1260        Self::result_from_i8(value as i8).unwrap_err()
1261    }
1262}
1263
1264/// Error codes used by
1265/// [Creep::ranged_mass_attack](crate::Creep::ranged_mass_attack).
1266///
1267/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.rangedMassAttack).
1268///
1269/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L658)
1270#[derive(
1271    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
1272)]
1273#[repr(i8)]
1274pub enum RangedMassAttackErrorCode {
1275    NotOwner = -1,
1276    Busy = -4,
1277    NoBodypart = -12,
1278}
1279
1280impl FromReturnCode for RangedMassAttackErrorCode {
1281    type Error = Self;
1282
1283    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
1284        let maybe_result = Self::try_result_from_i8(val);
1285        #[cfg(feature = "unsafe-return-conversion")]
1286        unsafe {
1287            maybe_result.unwrap_unchecked()
1288        }
1289        #[cfg(not(feature = "unsafe-return-conversion"))]
1290        maybe_result.unwrap()
1291    }
1292
1293    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1294        match val {
1295            0 => Some(Ok(())),
1296            -1 => Some(Err(RangedMassAttackErrorCode::NotOwner)),
1297            -4 => Some(Err(RangedMassAttackErrorCode::Busy)),
1298            -12 => Some(Err(RangedMassAttackErrorCode::NoBodypart)),
1299            _ => None,
1300        }
1301    }
1302}
1303
1304impl fmt::Display for RangedMassAttackErrorCode {
1305    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1306        let msg: &'static str = match self {
1307            RangedMassAttackErrorCode::NotOwner => "you are not the owner of this creep",
1308            RangedMassAttackErrorCode::Busy => "the creep is still being spawned",
1309            RangedMassAttackErrorCode::NoBodypart => {
1310                "there are no ranged_attack body parts in this creep’s body"
1311            }
1312        };
1313
1314        write!(f, "{}", msg)
1315    }
1316}
1317
1318impl Error for RangedMassAttackErrorCode {}
1319
1320impl From<RangedMassAttackErrorCode> for ErrorCode {
1321    fn from(value: RangedMassAttackErrorCode) -> Self {
1322        // Safety: RangedMassAttackErrorCode is repr(i8), so we can cast it to get the
1323        // discriminant value, which will match the raw return code value that ErrorCode
1324        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1325        // Safety: RangedMassAttackErrorCode discriminants are always error code values,
1326        // and thus the Result returned here will always be an `Err` variant, so we can
1327        // always extract the error without panicking
1328        Self::result_from_i8(value as i8).unwrap_err()
1329    }
1330}
1331
1332/// Error codes used by [Creep::repair](crate::Creep::repair).
1333///
1334/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.repair).
1335///
1336/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L734)
1337#[derive(
1338    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
1339)]
1340#[repr(i8)]
1341pub enum CreepRepairErrorCode {
1342    NotOwner = -1,
1343    Busy = -4,
1344    NotEnoughResources = -6,
1345    InvalidTarget = -7,
1346    NotInRange = -9,
1347    NoBodypart = -12,
1348}
1349
1350impl FromReturnCode for CreepRepairErrorCode {
1351    type Error = Self;
1352
1353    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
1354        let maybe_result = Self::try_result_from_i8(val);
1355        #[cfg(feature = "unsafe-return-conversion")]
1356        unsafe {
1357            maybe_result.unwrap_unchecked()
1358        }
1359        #[cfg(not(feature = "unsafe-return-conversion"))]
1360        maybe_result.unwrap()
1361    }
1362
1363    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1364        match val {
1365            0 => Some(Ok(())),
1366            -1 => Some(Err(CreepRepairErrorCode::NotOwner)),
1367            -4 => Some(Err(CreepRepairErrorCode::Busy)),
1368            -6 => Some(Err(CreepRepairErrorCode::NotEnoughResources)),
1369            -7 => Some(Err(CreepRepairErrorCode::InvalidTarget)),
1370            -9 => Some(Err(CreepRepairErrorCode::NotInRange)),
1371            -12 => Some(Err(CreepRepairErrorCode::NoBodypart)),
1372            _ => None,
1373        }
1374    }
1375}
1376
1377impl fmt::Display for CreepRepairErrorCode {
1378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1379        let msg: &'static str = match self {
1380            CreepRepairErrorCode::NotOwner => "you are not the owner of this creep",
1381            CreepRepairErrorCode::Busy => "the creep is still being spawned",
1382            CreepRepairErrorCode::NotEnoughResources => "the creep does not carry any energy",
1383            CreepRepairErrorCode::InvalidTarget => "the target is not a valid structure object",
1384            CreepRepairErrorCode::NotInRange => "the target is too far away",
1385            CreepRepairErrorCode::NoBodypart => "there are no work body parts in this creep’s body",
1386        };
1387
1388        write!(f, "{}", msg)
1389    }
1390}
1391
1392impl Error for CreepRepairErrorCode {}
1393
1394impl From<CreepRepairErrorCode> for ErrorCode {
1395    fn from(value: CreepRepairErrorCode) -> Self {
1396        // Safety: CreepRepairErrorCode is repr(i8), so we can cast it to get the
1397        // discriminant value, which will match the raw return code value that ErrorCode
1398        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1399        // Safety: CreepRepairErrorCode discriminants are always error code values, and
1400        // thus the Result returned here will always be an `Err` variant, so we can
1401        // always extract the error without panicking
1402        Self::result_from_i8(value as i8).unwrap_err()
1403    }
1404}
1405
1406/// Error codes used by
1407/// [Creep::reserve_controller](crate::Creep::reserve_controller).
1408///
1409/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.reserveController).
1410///
1411/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L955)
1412#[derive(
1413    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
1414)]
1415#[repr(i8)]
1416pub enum ReserveControllerErrorCode {
1417    NotOwner = -1,
1418    Busy = -4,
1419    InvalidTarget = -7,
1420    NotInRange = -9,
1421    NoBodypart = -12,
1422}
1423
1424impl FromReturnCode for ReserveControllerErrorCode {
1425    type Error = Self;
1426
1427    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
1428        let maybe_result = Self::try_result_from_i8(val);
1429        #[cfg(feature = "unsafe-return-conversion")]
1430        unsafe {
1431            maybe_result.unwrap_unchecked()
1432        }
1433        #[cfg(not(feature = "unsafe-return-conversion"))]
1434        maybe_result.unwrap()
1435    }
1436
1437    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1438        match val {
1439            0 => Some(Ok(())),
1440            -1 => Some(Err(ReserveControllerErrorCode::NotOwner)),
1441            -4 => Some(Err(ReserveControllerErrorCode::Busy)),
1442            -7 => Some(Err(ReserveControllerErrorCode::InvalidTarget)),
1443            -9 => Some(Err(ReserveControllerErrorCode::NotInRange)),
1444            -12 => Some(Err(ReserveControllerErrorCode::NoBodypart)),
1445            _ => None,
1446        }
1447    }
1448}
1449
1450impl fmt::Display for ReserveControllerErrorCode {
1451    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1452        let msg: &'static str = match self {
1453            ReserveControllerErrorCode::NotOwner => "you are not the owner of this creep",
1454            ReserveControllerErrorCode::Busy => "the creep is still being spawned",
1455            ReserveControllerErrorCode::InvalidTarget => {
1456                "the target is not a valid neutral controller object"
1457            }
1458            ReserveControllerErrorCode::NotInRange => "the target is too far away",
1459            ReserveControllerErrorCode::NoBodypart => {
1460                "there are no claim body parts in this creep’s body"
1461            }
1462        };
1463
1464        write!(f, "{}", msg)
1465    }
1466}
1467
1468impl Error for ReserveControllerErrorCode {}
1469
1470impl From<ReserveControllerErrorCode> for ErrorCode {
1471    fn from(value: ReserveControllerErrorCode) -> Self {
1472        // Safety: ReserveControllerErrorCode is repr(i8), so we can cast it to get the
1473        // discriminant value, which will match the raw return code value that ErrorCode
1474        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1475        // Safety: ReserveControllerErrorCode discriminants are always error code
1476        // values, and thus the Result returned here will always be an `Err` variant, so
1477        // we can always extract the error without panicking
1478        Self::result_from_i8(value as i8).unwrap_err()
1479    }
1480}
1481
1482/// Error codes used by [Creep::sign_controller](crate::Creep::sign_controller).
1483///
1484/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.signController).
1485///
1486/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L1072)
1487#[derive(
1488    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
1489)]
1490#[repr(i8)]
1491pub enum SignControllerErrorCode {
1492    Busy = -4,
1493    InvalidTarget = -7,
1494    NotInRange = -9,
1495}
1496
1497impl FromReturnCode for SignControllerErrorCode {
1498    type Error = Self;
1499
1500    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
1501        let maybe_result = Self::try_result_from_i8(val);
1502        #[cfg(feature = "unsafe-return-conversion")]
1503        unsafe {
1504            maybe_result.unwrap_unchecked()
1505        }
1506        #[cfg(not(feature = "unsafe-return-conversion"))]
1507        maybe_result.unwrap()
1508    }
1509
1510    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1511        match val {
1512            0 => Some(Ok(())),
1513            -4 => Some(Err(SignControllerErrorCode::Busy)),
1514            -7 => Some(Err(SignControllerErrorCode::InvalidTarget)),
1515            -9 => Some(Err(SignControllerErrorCode::NotInRange)),
1516            _ => None,
1517        }
1518    }
1519}
1520
1521impl fmt::Display for SignControllerErrorCode {
1522    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1523        let msg: &'static str = match self {
1524            SignControllerErrorCode::Busy => "the creep is still being spawned",
1525            SignControllerErrorCode::InvalidTarget => "the target is not a valid controller object",
1526            SignControllerErrorCode::NotInRange => "the target is too far away",
1527        };
1528
1529        write!(f, "{}", msg)
1530    }
1531}
1532
1533impl Error for SignControllerErrorCode {}
1534
1535impl From<SignControllerErrorCode> for ErrorCode {
1536    fn from(value: SignControllerErrorCode) -> Self {
1537        // Safety: SignControllerErrorCode is repr(i8), so we can cast it to get the
1538        // discriminant value, which will match the raw return code value that ErrorCode
1539        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1540        // Safety: SignControllerErrorCode discriminants are always error code values,
1541        // and thus the Result returned here will always be an `Err` variant, so we can
1542        // always extract the error without panicking
1543        Self::result_from_i8(value as i8).unwrap_err()
1544    }
1545}
1546
1547/// Error codes used by
1548/// [Creep::upgrade_controller](crate::Creep::upgrade_controller).
1549///
1550/// [Screeps API Docs](https://docs.screeps.com/api/#Creep.upgradeController).
1551///
1552/// [Screeps Engine Source Code](https://github.com/screeps/engine/blob/97c9d12385fed686655c13b09f5f2457dd83a2bf/src/game/creeps.js#L919)
1553#[derive(
1554    Debug, PartialEq, Eq, Clone, Copy, Hash, FromPrimitive, Deserialize_repr, Serialize_repr,
1555)]
1556#[repr(i8)]
1557pub enum UpgradeControllerErrorCode {
1558    NotOwner = -1,
1559    Busy = -4,
1560    NotEnoughResources = -6,
1561    InvalidTarget = -7,
1562    NotInRange = -9,
1563    NoBodypart = -12,
1564}
1565
1566impl FromReturnCode for UpgradeControllerErrorCode {
1567    type Error = Self;
1568
1569    fn result_from_i8(val: i8) -> Result<(), Self::Error> {
1570        let maybe_result = Self::try_result_from_i8(val);
1571        #[cfg(feature = "unsafe-return-conversion")]
1572        unsafe {
1573            maybe_result.unwrap_unchecked()
1574        }
1575        #[cfg(not(feature = "unsafe-return-conversion"))]
1576        maybe_result.unwrap()
1577    }
1578
1579    fn try_result_from_i8(val: i8) -> Option<Result<(), Self::Error>> {
1580        match val {
1581            0 => Some(Ok(())),
1582            -1 => Some(Err(UpgradeControllerErrorCode::NotOwner)),
1583            -4 => Some(Err(UpgradeControllerErrorCode::Busy)),
1584            -6 => Some(Err(UpgradeControllerErrorCode::NotEnoughResources)),
1585            -7 => Some(Err(UpgradeControllerErrorCode::InvalidTarget)),
1586            -9 => Some(Err(UpgradeControllerErrorCode::NotInRange)),
1587            -12 => Some(Err(UpgradeControllerErrorCode::NoBodypart)),
1588            _ => None,
1589        }
1590    }
1591}
1592
1593impl fmt::Display for UpgradeControllerErrorCode {
1594    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1595        let msg: &'static str = match self {
1596            UpgradeControllerErrorCode::NotOwner => "you are not the owner of this creep or the target controller",
1597            UpgradeControllerErrorCode::Busy => "the creep is still being spawned",
1598            UpgradeControllerErrorCode::NotEnoughResources => "the creep does not have any carried energy",
1599            UpgradeControllerErrorCode::InvalidTarget => "the target is not a valid controller object, or the controller upgrading is blocked",
1600            UpgradeControllerErrorCode::NotInRange => "the target is too far away",
1601            UpgradeControllerErrorCode::NoBodypart => "there are no work body parts in this creep’s body",
1602        };
1603
1604        write!(f, "{}", msg)
1605    }
1606}
1607
1608impl Error for UpgradeControllerErrorCode {}
1609
1610impl From<UpgradeControllerErrorCode> for ErrorCode {
1611    fn from(value: UpgradeControllerErrorCode) -> Self {
1612        // Safety: UpgradeControllerErrorCode is repr(i8), so we can cast it to get the
1613        // discriminant value, which will match the raw return code value that ErrorCode
1614        // expects.   Ref: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.discriminant.coercion.intro
1615        // Safety: UpgradeControllerErrorCode discriminants are always error code
1616        // values, and thus the Result returned here will always be an `Err` variant, so
1617        // we can always extract the error without panicking
1618        Self::result_from_i8(value as i8).unwrap_err()
1619    }
1620}