-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Power Creeps and Effects #258
Power Creeps and Effects #258
Conversation
…s in comments and errors
src/objects.rs
Outdated
@@ -120,12 +122,12 @@ reference_wrappers! { | |||
/// | |||
/// This can be freely implemented for anything with a way to get a position. | |||
pub trait HasPosition { | |||
fn pos(&self) -> Position; | |||
fn pos(&self) -> Result<Position, ConversionError>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this technically solves the problem, I'd argue changing the traits like this doesn't really take advantage of the type system we have.
Specifically, changing the traits like this requires everyone to deal with usually-non-existent error cases dealing with every other non-power-creep object.
In addition, this makes methods like .get_range_to
panic when called with a power creep, and there's no indication in the code that something dangerous has happened. If users had to manually unwrap a PowerCreep result in order to do this, I think that could make things clearer.
The idea I'm coming from here is that ideally, things which behave differently or could fail should be dealt with explicitly by consumers. Users of the crate should be forced to deal with error cases, and shouldn't be able to write code which has a chance of failing at runtime without knowing (without doing an .unwrap() or .expect() somewhere in their own code).
What would you think of just not implementing HasPosition
and other traits for PowerCreep
and instead requiring first converting to an "InstantiatedPowerCreep" or similar before being able to call relevant methods? Or if not that, what are your thoughts on this problem?
Edit: edited shortly after posting to refine my thoughts better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, this kind of change to these methods makes them a lot more awkward to use - my initial attempt at implementation used an enum to wrap an alive-or-dead-power-creep, but that ended up being a mess - this sounds better ;)
The comparison I'm thinking of is that we'd have something akin to a std::rc::Weak
upgrade into a std::rc::Rc
- taking the maybe-alive-power-creep object reference and upgrading it to get a we-know-it's-alive object with room object properties, HasId
, Attackable
etc.
Because this is only applicable to the results of accessing game::power_creeps
(and game::creeps
in the #246 case) case and not for objects found via find()
/look()
, my thinking is to have PowerCreep
as the 'fully alive power creep' representation (which would be the find/look result, intuitively) and to add PowerCreepInfo
or GamePowerCreep
or somesuch which would be the version of the reference returned by game::power_creeps::*
that can be upgrade()
-ed to a full PowerCreep
if it's spawned on the current shard.
I could use some guidance on how to get this implemented - I can't quite get my head around how to get that 'upgrade()' function set up to get the underlying js ref moved from PowerCreepInfo
/ShrodingersPowerCreep
to PowerCreep
during the upgrade()
, to get it converted to Option<PowerCreep>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worked it out and went with AccountPowerCreep
, should be a much less breaking changeset now :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
The comparison I'm thinking of is that we'd have something akin to a std::rc::Weak upgrade into a std::rc::Rc - taking the maybe-alive-power-creep object reference and upgrading it to get a we-know-it's-alive object with room object properties, HasId, Attackable etc.
This sounds like a sane comparison to me. The new scheme looks good!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ShrodingersPowerCreep
🤣
I think I like it better than AccountPowerCreep
😛
… that can be converted to a full PowerCreep if spawned
Ok, last implementation question - should I add a wrapper around |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is another one that is looking quite good!
This one's big enough already. I suggest keeping it separate. PRs aren't expensive! |
…, update tower repair to match creep repair, fmt again with nightly to fix comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good. Thanks!
@@ -276,8 +276,7 @@ pub const INVADERS_ENERGY_GOAL: u32 = 100000; | |||
|
|||
pub const SYSTEM_USERNAME: &str = "Screeps"; | |||
|
|||
pub const SIGN_PLANNED_AREA: &str = | |||
"A new Novice or Respawn Area is being planned somewhere \ | |||
pub const SIGN_PLANNED_AREA: &str = "A new Novice or Respawn Area is being planned somewhere \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rustfmt changed it's default value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The joys of the nightly branch apparently!
js_unwrap! { @{self.as_ref()}.attack( @{target.as_ref()} ) } | ||
} | ||
|
||
pub fn heal(&self, target: &Creep) -> ReturnCode { | ||
pub fn heal<T>(&self, target: &T) -> ReturnCode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you heal enemy creeps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, sure can! You usually wouldn't want to, but there is a useful uncommon case in healing allies' creeps (though my intent for this change was just to make it consistent with the args for the heal function on Creep
)
Added power creeps and the necessary game and power spawn object interfaces to work with them, as well as effects on room objects which are used by both power creeps and strongholds.
Effects can have types representing powers or 'natural effects' (which only strongholds use currently) - this is set up as a nested enum to keep
PowerType
distinct fromEffectType
, though these could also just be a single enum with the relevant integer representations of both power and natural effects if that's overcomplicating things.Implementations on creeps which are identical to those on power creeps have been moved to a
SharedCreepProperties
trait which both creeps and power creeps use - I'm not a huge fan of this naming if there's other ideas.Several attributes on power creeps not spawned in the world are undefined in the same way as the issue reported in #246, causing a number of potential panics. This switches just the directly-impacted functions to return a
Result
, which might be a start toward #3 - currently just bubbling up serde'sConversionError
s which seems potentially not ideal? If this ends up being the final implementation it's probably a good time/release to make similar result changes in other places.Resolves #158