(Wiring) Logic - make wiring turing complete

This commit is contained in:
Daniel Mizerski 2021-05-06 18:50:15 +02:00
parent 8ae1d106cf
commit 3197bcd12a
4 changed files with 98 additions and 15 deletions

View File

@ -93,6 +93,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Potion Kit is renamed to "consumables" and gives potions and mushroom curry - Potion Kit is renamed to "consumables" and gives potions and mushroom curry
- Cultist Kit gives cape, rings and necklace in addition to armour and weapons. - Cultist Kit gives cape, rings and necklace in addition to armour and weapons.
- Reworked minotaur to have unique attacks. - Reworked minotaur to have unique attacks.
- Wiring is now turing complete
### Removed ### Removed

View File

@ -4,6 +4,7 @@
use crate::{ use crate::{
settings::{BanRecord, EditableSetting}, settings::{BanRecord, EditableSetting},
wiring::{Logic, OutputFormula},
Server, SpawnPoint, StateExt, Server, SpawnPoint, StateExt,
}; };
use assets::AssetExt; use assets::AssetExt;
@ -1721,9 +1722,39 @@ fn handle_spawn_wiring(
pos.0.x += 3.0; pos.0.x += 3.0;
let mut outputs1 = HashMap::new(); let mut outputs1 = HashMap::new();
outputs1.insert(String::from("color"), wiring::OutputFormula::OnDeath { outputs1.insert(
value: 1.0, "deaths_last_tick".to_string(),
radius: 30.0, wiring::OutputFormula::OnDeath {
value: 1.0,
radius: 30.0,
},
);
outputs1.insert(
"deaths_accumulated".to_string(),
OutputFormula::Logic(Box::new(Logic {
kind: wiring::LogicKind::Sum,
left: OutputFormula::Logic(Box::new(Logic {
kind: wiring::LogicKind::Sub,
left: OutputFormula::Input {
name: "deaths_accumulated".to_string(),
},
right: OutputFormula::Logic(Box::new(Logic {
kind: wiring::LogicKind::Min,
left: OutputFormula::Input {
name: "pressed".to_string(),
},
right: OutputFormula::Input {
name: "deaths_accumulated".to_string(),
},
})),
})),
right: OutputFormula::Input {
name: "deaths_last_tick".to_string(),
},
})),
);
outputs1.insert("pressed".to_string(), OutputFormula::OnCollide {
value: f32::MAX,
}); });
let builder1 = server let builder1 = server
@ -1757,9 +1788,9 @@ fn handle_spawn_wiring(
actions: vec![ actions: vec![
WiringAction { WiringAction {
formula: wiring::OutputFormula::Input { formula: wiring::OutputFormula::Input {
name: String::from("color"), name: String::from("deaths_accumulated"),
}, },
threshold: 1.0, threshold: 5.0,
effects: vec![WiringActionEffect::SpawnProjectile { effects: vec![WiringActionEffect::SpawnProjectile {
constr: comp::ProjectileConstructor::Arrow { constr: comp::ProjectileConstructor::Arrow {
damage: 1.0, damage: 1.0,
@ -1798,12 +1829,32 @@ fn handle_spawn_wiring(
outputs: HashMap::new(), outputs: HashMap::new(),
}) })
.with(Circuit { .with(Circuit {
wires: vec![Wire { wires: vec![
input_entity: ent1, Wire {
input_field: String::from("color"), input_entity: ent1,
output_entity: ent2, input_field: String::from("deaths_last_tick"),
output_field: String::from("color"), output_entity: ent1,
}], output_field: String::from("deaths_last_tick"),
},
Wire {
input_entity: ent1,
input_field: String::from("deaths_accumulated"),
output_entity: ent1,
output_field: String::from("deaths_accumulated"),
},
Wire {
input_entity: ent1,
input_field: String::from("pressed"),
output_entity: ent1,
output_field: String::from("pressed"),
},
Wire {
input_entity: ent1,
input_field: String::from("deaths_accumulated"),
output_entity: ent2,
output_field: String::from("deaths_accumulated"),
},
],
}); });
builder3.build(); builder3.build();

View File

@ -1,5 +1,5 @@
use super::WiringData; use super::WiringData;
use crate::wiring::OutputFormula; use crate::wiring::{Logic, LogicKind, OutputFormula};
use common::{ use common::{
comp::{PhysicsState, Pos}, comp::{PhysicsState, Pos},
resources::EntitiesDiedLastTick, resources::EntitiesDiedLastTick,
@ -84,9 +84,8 @@ pub fn compute_output(
match output_formula { match output_formula {
OutputFormula::Constant { value } => *value, OutputFormula::Constant { value } => *value,
OutputFormula::Input { name } => *inputs.get(name).unwrap_or(&0.0), OutputFormula::Input { name } => *inputs.get(name).unwrap_or(&0.0),
OutputFormula::Logic(_logic) => { OutputFormula::Logic(logic) => {
warn!("Not implemented OutputFormula::Logic"); output_formula_logic(logic, inputs, physics_state, entities_died_last_tick, pos)
0.0
}, },
OutputFormula::SineWave { .. } => { OutputFormula::SineWave { .. } => {
warn!("Not implemented OutputFormula::SineWave"); warn!("Not implemented OutputFormula::SineWave");
@ -130,3 +129,34 @@ fn output_formula_on_death(
} }
0.0 0.0
} }
#[allow(clippy::too_many_arguments)]
fn output_formula_logic(
logic: &Logic,
inputs: &HashMap<String, f32>,
physics_state: Option<&PhysicsState>,
entities_died_last_tick: &Read<EntitiesDiedLastTick>,
pos: Option<&Pos>,
) -> f32 {
let left = compute_output(
&logic.left,
inputs,
physics_state,
entities_died_last_tick,
pos,
);
let right = compute_output(
&logic.right,
inputs,
physics_state,
entities_died_last_tick,
pos,
);
match logic.kind {
LogicKind::Max => f32::max(left, right),
LogicKind::Min => f32::min(left, right),
LogicKind::Sub => left - right,
LogicKind::Sum => left + right,
LogicKind::Mul => left * right,
}
}

View File

@ -37,6 +37,7 @@ pub enum LogicKind {
Max, // acts like Or Max, // acts like Or
Sub, // `|x| { 5.0 - x }` acts like Not, depending on reference voltages Sub, // `|x| { 5.0 - x }` acts like Not, depending on reference voltages
Sum, Sum,
Mul,
} }
pub struct WiringAction { pub struct WiringAction {