use super::MchprsWorld;
use crate::UniversalSchematic;
use mchprs_blocks::BlockPos;
use mchprs_world::World;
use std::collections::HashMap;
pub fn generate_truth_table(schematic: &UniversalSchematic) -> Vec<HashMap<String, bool>> {
let mut world = match MchprsWorld::new(schematic.clone()) {
Ok(w) => w,
Err(e) => {
log::error!("Failed to create world: {}", e);
return Vec::new();
}
};
let (inputs, outputs) = find_inputs_and_outputs(&world);
log::debug!("Inputs: {:?}", inputs);
log::debug!("Outputs: {:?}", outputs);
let mut truth_table = Vec::new();
let input_combinations = generate_input_combinations(inputs.len());
for combination in input_combinations {
for (i, &input_pos) in inputs.iter().enumerate() {
if combination[i] {
world.on_use_block(input_pos);
}
}
world.tick(20);
world.flush();
let mut result = HashMap::new();
for (i, &input_pos) in inputs.iter().enumerate() {
result.insert(format!("Input {}", i), world.get_lever_power(input_pos));
}
for (i, &output_pos) in outputs.iter().enumerate() {
result.insert(format!("Output {}", i), world.is_lit(output_pos));
}
truth_table.push(result);
world = match MchprsWorld::new(schematic.clone()) {
Ok(w) => w,
Err(_) => return truth_table, };
}
truth_table
}
fn find_inputs_and_outputs(world: &MchprsWorld) -> (Vec<BlockPos>, Vec<BlockPos>) {
let mut inputs = Vec::new();
let mut outputs = Vec::new();
let dimensions = world.schematic.get_dimensions();
for x in 0..dimensions.0 {
for y in 0..dimensions.1 {
for z in 0..dimensions.2 {
let pos = BlockPos::new(x, y, z);
let block = world.get_block(pos);
let block_name = block.get_name();
match block_name {
"lever" => inputs.push(pos),
"redstone_lamp" => outputs.push(pos),
_ => {}
}
}
}
}
(inputs, outputs)
}
fn generate_input_combinations(num_inputs: usize) -> Vec<Vec<bool>> {
(0..2usize.pow(num_inputs as u32))
.map(|i| (0..num_inputs).map(|j| (i & (1 << j)) != 0).collect())
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_input_combinations() {
let combos = generate_input_combinations(2);
assert_eq!(combos.len(), 4);
assert_eq!(combos[0], vec![false, false]);
assert_eq!(combos[1], vec![true, false]);
assert_eq!(combos[2], vec![false, true]);
assert_eq!(combos[3], vec![true, true]);
}
}