Slightly cleaner stub exit coherence logic

This commit is contained in:
projectmoon 2024-01-12 10:24:11 +01:00
parent 3d90917f65
commit fed6d2581d
1 changed files with 38 additions and 78 deletions

View File

@ -1,5 +1,6 @@
use anyhow::{anyhow, Result};
use std::cell::RefCell;
use std::mem;
use std::rc::Rc;
use itertools::Itertools;
@ -79,10 +80,19 @@ pub(super) fn check_scene_coherence<'a>(scene: &'a Scene) -> Vec<CoherenceFailur
pub fn reverse_direction(direction: &str) -> String {
match direction.to_lowercase().as_ref() {
// compass directions
"north" => "south".to_string(),
"south" => "north".to_string(),
"east" => "west".to_string(),
"west" => "east".to_string(),
// more compass directions
"northwest" => "southeast".to_string(),
"northeast" => "southwest".to_string(),
"southeast" => "northwest".to_string(),
"southwest" => "northeast".to_string(),
// abstract directions
"up" => "down".to_string(),
"down" => "up".to_string(),
"in" => "out".to_string(),
@ -91,53 +101,11 @@ pub fn reverse_direction(direction: &str) -> String {
}
}
fn find_exit_by_connection(exit: &Exit, connected_scene: &Scene) -> bool {
let connected_key = connected_scene._key.as_deref().unwrap();
Some(exit.scene_key.as_ref()) == connected_scene._key.as_deref()
|| exit.scene_id.as_deref() == connected_scene._id.as_deref()
|| exit.name.to_lowercase() == connected_scene.name.to_lowercase()
|| exit.name == connected_key
}
fn find_exit_by_direction(exit: &Exit, direction_from: &str) -> bool {
exit.direction == reverse_direction(direction_from)
}
// fn yoink<'a>(
// //exits: Vec<&'a mut Exit>,
// mut exits: Vec<&'a mut Exit>,
// direction_from: &'a str,
// connected_scene: &'a Scene,
// ) -> Option<&'a mut Exit> {
// if exits.len() > 1 {
// exits
// .iter()
// .find_map(|exit| match find_exit_by_direction(*exit, direction_from) {
// true => Some(&mut **exit),
// _ => None,
// })
// .or_else(|| {
// exits.iter().find_map(|&exit| {
// match find_exit_by_connection(exit, connected_scene) {
// true => Some(&mut *exit),
// _ => None,
// }
// })
// })
// } else if exits.len() == 1 {
// Some(exits[0])
// } else {
// None
// }
// }
/// Attempt to reconnect back to the connected scene. The model is
/// not always good at this. Here, we correct it by attempting to
/// find the exit by name, and also making sure the direction is
/// coherently reversed.
/// Attempt to reconnect back to the connected scene. The model is not
/// always good at this. Here, we correct it by attempting to find the
/// exit and making sure the direction is coherently reversed. A
/// linkback exit is created from scratch if one cannot be found.
pub fn make_scene_from_stub_coherent(content: &mut ContentContainer, connected_scene: &Scene) {
// TODO we need to perhaps also make the exit from scratch if the
// LLM did not generate it at all.
let new_scene = content.owner.as_scene_mut();
let connected_key = connected_scene._key.as_deref().unwrap();
let connected_id = connected_scene._id.as_deref().unwrap();
@ -151,46 +119,38 @@ pub fn make_scene_from_stub_coherent(content: &mut ContentContainer, connected_s
let reversed_direction = reverse_direction(direction_from);
// Rethink this.
// 1. Delete any exits that have the same direction as the reversed direction_from
// AND do not point to connected scene ID.
// 2. Find potential connected exit and modify as normal.
new_scene.exits.retain(|exit| {
(exit.direction == reversed_direction && exit.scene_key == connected_key)
|| exit.direction != reversed_direction
});
////////////////////////////////
// It is possible we have an exit that leads in the direction of
// the way back, or one exit that is created to go back to the connected scene.
let exit_to_change = new_scene.exits.iter_mut().find(|exit| {
exit.direction == reverse_direction(direction_from)
// 1. Delete any exit that is from the reversed direction, or
// has the name/ID/key of the connected scene.
let mut stubs_to_delete = vec![];
let keep_exit = |exit: &Exit| {
!(exit.direction == reversed_direction
|| Some(exit.scene_key.as_ref()) == connected_scene._key.as_deref()
|| exit.scene_id.as_deref() == connected_scene._id.as_deref()
|| exit.name.to_lowercase() == connected_scene.name.to_lowercase()
|| exit.name == connected_key
|| exit.name == connected_id
|| exit.name == connected_id)
};
new_scene.exits.retain_mut(|exit| {
let keep = keep_exit(exit);
if !keep {
stubs_to_delete.push(mem::take(&mut exit.scene_key));
}
keep
});
if let Some(exit) = exit_to_change {
// Delete the stub that was this exit, and update the exit
content.contained.retain(|c| match &c.content {
Content::SceneStub(stub) => stub._id != exit.scene_id,
// Delete corresponding stubs
content.contained.retain(|c| match &c.content {
Content::SceneStub(stub) => match stub._key.as_ref() {
Some(key) => !stubs_to_delete.contains(key),
_ => true,
});
},
_ => true,
});
// Fix up exit to point back to connected scene.
exit.scene_id = connected_scene._id.clone();
exit.scene_key = connected_scene._key.as_ref().unwrap().clone();
exit.direction = reverse_direction(direction_from);
} else {
println!("WARNING: could not correct stub exit - creating manually");
// Could not find a connected exit at all. Create one manually
let exit = Exit::from_connected_scene(connected_scene, &reversed_direction);
new_scene.exits.push(exit);
}
// Add new linkback exit
let exit = Exit::from_connected_scene(connected_scene, &reversed_direction);
new_scene.exits.push(exit);
}
pub async fn make_scene_coherent(