Loads of work to replace panics with results.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use crate::dynamic_data::choices::TurnChoice;
|
||||
use crate::dynamic_data::script_handling::ScriptSource;
|
||||
use crate::dynamic_data::Pokemon;
|
||||
use crate::{script_hook, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{script_hook, PkmnError, ValueIdentifiable, ValueIdentifier};
|
||||
use anyhow::Result;
|
||||
use anyhow_ext::anyhow;
|
||||
use parking_lot::lock_api::MappedRwLockReadGuard;
|
||||
@@ -39,14 +39,17 @@ impl ChoiceQueue {
|
||||
/// Dequeues the next turn choice to be executed. This gives ownership to the callee, and replaces
|
||||
/// our own reference to the turn choice with an empty spot. It also increments the current position
|
||||
/// by one.
|
||||
pub fn dequeue(&mut self) -> Option<TurnChoice> {
|
||||
pub fn dequeue(&mut self) -> Result<Option<TurnChoice>> {
|
||||
let mut write_lock = self.queue.write();
|
||||
if self.current >= write_lock.len() {
|
||||
return None;
|
||||
return Ok(None);
|
||||
}
|
||||
let c = write_lock[self.current].take();
|
||||
let c = write_lock
|
||||
.get_mut(self.current)
|
||||
.ok_or(anyhow!("Unable to get current turn choice"))?
|
||||
.take();
|
||||
self.current += 1;
|
||||
c
|
||||
Ok(c)
|
||||
}
|
||||
|
||||
/// This reads what the next choice to execute will be, without modifying state.
|
||||
@@ -55,7 +58,10 @@ impl ChoiceQueue {
|
||||
if self.current >= read_lock.len() {
|
||||
Ok(None)
|
||||
} else {
|
||||
let v = RwLockReadGuard::try_map(read_lock, |a| a[self.current].as_ref());
|
||||
let v = RwLockReadGuard::try_map(read_lock, |a| match a.get(self.current) {
|
||||
Some(Some(v)) => Some(v),
|
||||
_ => None,
|
||||
});
|
||||
match v {
|
||||
Ok(v) => Ok(Some(v)),
|
||||
Err(_) => Err(anyhow!("Could not map choice")),
|
||||
@@ -71,11 +77,13 @@ impl ChoiceQueue {
|
||||
/// This resorts the yet to be executed choices. This can be useful for dealing with situations
|
||||
/// such as Pokemon changing forms just after the very start of a turn, when turn order has
|
||||
/// technically already been decided.
|
||||
pub fn resort(&mut self) {
|
||||
pub fn resort(&mut self) -> Result<()> {
|
||||
let len = self.queue.read().len();
|
||||
let mut write_lock = self.queue.write();
|
||||
for index in self.current..len {
|
||||
let choice = &mut write_lock[index];
|
||||
let choice = &mut write_lock
|
||||
.get_mut(index)
|
||||
.ok_or(PkmnError::IndexOutOfBounds { index, len })?;
|
||||
if let Some(choice) = choice {
|
||||
let mut speed = choice.user().boosted_stats().speed();
|
||||
script_hook!(change_speed, (*choice), choice, &mut speed);
|
||||
@@ -83,7 +91,14 @@ impl ChoiceQueue {
|
||||
}
|
||||
}
|
||||
|
||||
write_lock[self.current..len].sort_unstable_by(|a, b| b.cmp(a));
|
||||
write_lock
|
||||
.get_mut(self.current..len)
|
||||
.ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: self.current,
|
||||
len,
|
||||
})?
|
||||
.sort_unstable_by(|a, b| b.cmp(a));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This moves the choice of a specific Pokemon up to the next choice to be executed.
|
||||
@@ -92,7 +107,7 @@ impl ChoiceQueue {
|
||||
let mut desired_index = None;
|
||||
// Find the index for the choice we want to move up.
|
||||
for index in self.current..queue_lock.len() {
|
||||
if let Some(choice) = &queue_lock[index] {
|
||||
if let Some(Some(choice)) = &queue_lock.get(index) {
|
||||
if pokemon.value_identifier() == choice.user().value_identifier() {
|
||||
desired_index = Some(index);
|
||||
break;
|
||||
@@ -106,8 +121,14 @@ impl ChoiceQueue {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
let len = queue_lock.len();
|
||||
// Take the choice we want to move forward out of it's place.
|
||||
let choice = queue_lock[desired_index]
|
||||
let choice = queue_lock
|
||||
.get_mut(desired_index)
|
||||
.ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: self.current,
|
||||
len,
|
||||
})?
|
||||
.take()
|
||||
.ok_or(anyhow!("Choice was already taken"))?;
|
||||
// Iterate backwards from the spot before the choice we want to move up, push them all back
|
||||
@@ -115,8 +136,15 @@ impl ChoiceQueue {
|
||||
for index in (self.current..desired_index).rev() {
|
||||
queue_lock.swap(index, index + 1);
|
||||
}
|
||||
let len = queue_lock.len();
|
||||
// Place the choice that needs to be next in the next to be executed position.
|
||||
let _ = queue_lock[self.current].insert(choice);
|
||||
let _ = queue_lock
|
||||
.get_mut(self.current)
|
||||
.ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: self.current,
|
||||
len,
|
||||
})?
|
||||
.insert(choice);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
@@ -125,9 +153,16 @@ impl ChoiceQueue {
|
||||
}
|
||||
|
||||
/// Internal helper function to be easily able to iterate over the yet to be executed choices.
|
||||
pub(crate) fn get_queue(&self) -> MappedRwLockReadGuard<'_, RawRwLock, [Option<TurnChoice>]> {
|
||||
pub(crate) fn get_queue(&self) -> Result<MappedRwLockReadGuard<'_, RawRwLock, [Option<TurnChoice>]>> {
|
||||
let read_lock = self.queue.read();
|
||||
RwLockReadGuard::map(read_lock, |a| &a[self.current..self.queue.read().len()])
|
||||
match RwLockReadGuard::try_map(read_lock, |a| a.get(self.current..self.queue.read().len())) {
|
||||
Ok(v) => Ok(v),
|
||||
Err(_) => Err(PkmnError::IndexOutOfBounds {
|
||||
index: self.current,
|
||||
len: self.queue.read().len(),
|
||||
}
|
||||
.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +190,7 @@ mod tests {
|
||||
#[test]
|
||||
fn dequeue_from_empty_queue() {
|
||||
let mut queue = ChoiceQueue::new(Vec::new());
|
||||
assert!(queue.dequeue().is_none());
|
||||
assert!(queue.dequeue().unwrap().is_none());
|
||||
}
|
||||
|
||||
fn get_user(level: LevelInt) -> Pokemon {
|
||||
@@ -196,7 +231,7 @@ mod tests {
|
||||
|
||||
let mut queue = ChoiceQueue::new(vec![Some(TurnChoice::Pass(PassChoice::new(user)))]);
|
||||
assert!(queue.has_next());
|
||||
assert_eq!(7, queue.dequeue().unwrap().speed());
|
||||
assert_eq!(7, queue.dequeue().unwrap().unwrap().speed());
|
||||
assert!(!queue.has_next());
|
||||
assert!(queue.peek().unwrap().is_none());
|
||||
}
|
||||
@@ -224,7 +259,7 @@ mod tests {
|
||||
Some(TurnChoice::Pass(PassChoice::new(user1.clone()))),
|
||||
Some(TurnChoice::Pass(PassChoice::new(user2))),
|
||||
]);
|
||||
let inner_queue = queue.get_queue();
|
||||
let inner_queue = queue.get_queue().unwrap();
|
||||
assert_eq!(
|
||||
inner_queue[0].as_ref().unwrap().user().value_identifier(),
|
||||
user1.value_identifier()
|
||||
@@ -240,8 +275,8 @@ mod tests {
|
||||
Some(TurnChoice::Pass(PassChoice::new(user1))),
|
||||
Some(TurnChoice::Pass(PassChoice::new(user2))),
|
||||
]);
|
||||
assert_eq!(25, queue.dequeue().unwrap().speed());
|
||||
assert_eq!(6, queue.dequeue().unwrap().speed());
|
||||
assert_eq!(25, queue.dequeue().unwrap().unwrap().speed());
|
||||
assert_eq!(6, queue.dequeue().unwrap().unwrap().speed());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -254,12 +289,12 @@ mod tests {
|
||||
Some(TurnChoice::Pass(PassChoice::new(user2.clone()))),
|
||||
]);
|
||||
|
||||
user2.change_level_by(60);
|
||||
user2.change_level_by(60).unwrap();
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.peek().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
queue.resort();
|
||||
queue.resort().unwrap();
|
||||
assert_eq!(
|
||||
user2.value_identifier(),
|
||||
queue.peek().unwrap().unwrap().user().value_identifier()
|
||||
@@ -283,11 +318,11 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
user2.value_identifier(),
|
||||
queue.dequeue().unwrap().user().value_identifier()
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.dequeue().unwrap().user().value_identifier()
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -302,13 +337,13 @@ mod tests {
|
||||
]);
|
||||
assert_eq!(
|
||||
user2.value_identifier(),
|
||||
queue.dequeue().unwrap().user().value_identifier()
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert!(!queue.move_pokemon_choice_next(user2.as_ref()).unwrap());
|
||||
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.dequeue().unwrap().user().value_identifier()
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert!(queue.peek().unwrap().is_none())
|
||||
}
|
||||
@@ -362,18 +397,18 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
users[4].value_identifier(),
|
||||
queue.dequeue().unwrap().user().value_identifier()
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
for index in 0..4 {
|
||||
assert_eq!(
|
||||
users[index].value_identifier(),
|
||||
queue.dequeue().unwrap().user().value_identifier()
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
}
|
||||
for index in 5..7 {
|
||||
assert_eq!(
|
||||
users[index].value_identifier(),
|
||||
queue.dequeue().unwrap().user().value_identifier()
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user