diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2022-04-19 20:33:11 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2022-04-19 20:33:11 +0200 |
commit | 2a939b5e97604d3129b888f15c9876ffd3a7fe5a (patch) | |
tree | d4ae8114a9527a2e46464ce32b80476a5831fdbb /2020/src/bin/day_3.rs | |
parent | 2410e500560a1989399c8ad0c23fe7aa9827576d (diff) | |
parent | 6a5b143c0fd0a90979d9315b50be2387facb752f (diff) |
Merge branch '2020-main'
Diffstat (limited to '2020/src/bin/day_3.rs')
-rw-r--r-- | 2020/src/bin/day_3.rs | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/2020/src/bin/day_3.rs b/2020/src/bin/day_3.rs new file mode 100644 index 0000000..5e6f0bd --- /dev/null +++ b/2020/src/bin/day_3.rs @@ -0,0 +1,205 @@ +use bevy::app::AppExit; +use bevy::prelude::*; +use bevy::render::camera::Camera; +use std::fs::File; +use std::io::{BufRead, BufReader}; + +fn main() { + App::build() + .add_resource(WindowDescriptor { + title: "Advent of Code".to_string(), + width: 1920, + height: 1080, + ..Default::default() + }) + .add_resource(ClearColor(Color::rgb(0., 0., 0.))) + .add_startup_system(setup_camera.system()) + .add_startup_stage("game_entities") + .add_startup_system_to_stage("game_entities", read_input_file.system()) + .add_system(move_tobogganist.system()) + .add_system(collide_with_trees.system()) + .add_system(clear_finished_tobogganists.system()) + .add_system(end_of_slope.system()) + .add_system(translate_positions.system()) + .add_system(tobogganist_cam.system()) + .add_plugins(DefaultPlugins) + .run(); +} + +fn setup_camera(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) { + commands.spawn(Camera2dComponents::default()); + + commands.insert_resource(Materials { + tobogganist_material: materials.add(Color::rgb(0., 0., 255.).into()), + tree_material: materials.add(Color::rgb(0., 255., 0.).into()), + }); +} + +struct Materials { + tobogganist_material: Handle<ColorMaterial>, + tree_material: Handle<ColorMaterial>, +} + +struct Tobogganist; + +struct Tree; +#[derive(PartialEq, Eq)] +struct Position { + x: usize, + y: usize, +} +struct Velocity { + x: usize, + y: usize, +} +struct MapSize { + width: usize, + height: usize, +} +struct TreeHitCount(usize); +struct Score(usize); + +fn read_input_file(mut commands: Commands, materials: Res<Materials>) { + commands + .spawn(SpriteComponents { + sprite: Sprite::new(Vec2::new(10., 10.)), + material: materials.tobogganist_material.clone(), + ..Default::default() + }) + .with(Tobogganist) + .with(Position { x: 0, y: 0 }) + .with(Velocity { x: 1, y: 1 }) + .with(TreeHitCount(0)); + + commands + .spawn(SpriteComponents { + sprite: Sprite::new(Vec2::new(10., 10.)), + material: materials.tobogganist_material.clone(), + ..Default::default() + }) + .with(Tobogganist) + .with(Position { x: 0, y: 0 }) + .with(Velocity { x: 3, y: 1 }) + .with(TreeHitCount(0)); + + commands + .spawn(SpriteComponents { + sprite: Sprite::new(Vec2::new(10., 10.)), + material: materials.tobogganist_material.clone(), + ..Default::default() + }) + .with(Tobogganist) + .with(Position { x: 0, y: 0 }) + .with(Velocity { x: 5, y: 1 }) + .with(TreeHitCount(0)); + + commands + .spawn(SpriteComponents { + sprite: Sprite::new(Vec2::new(10., 10.)), + material: materials.tobogganist_material.clone(), + ..Default::default() + }) + .with(Tobogganist) + .with(Position { x: 0, y: 0 }) + .with(Velocity { x: 7, y: 1 }) + .with(TreeHitCount(0)); + + commands + .spawn(SpriteComponents { + sprite: Sprite::new(Vec2::new(10., 10.)), + material: materials.tobogganist_material.clone(), + ..Default::default() + }) + .with(Tobogganist) + .with(Position { x: 0, y: 0 }) + .with(Velocity { x: 1, y: 2 }) + .with(TreeHitCount(0)); + + let f = File::open("./inputs/day_3.txt").expect("Failed to read file"); // TODO: Use the asset loading system to load this rather? + let mut width = 0; + let mut height = 0; + for (y, line) in BufReader::new(f).lines().enumerate() { + let line = line.expect("Error reading file"); + let line = line.trim(); + width = width.max(line.len()); + for (x, c) in line.chars().enumerate() { + if c == '#' { + commands + .spawn(SpriteComponents { + sprite: Sprite::new(Vec2::new(10., 10.)), + material: materials.tree_material.clone(), + ..Default::default() + }) + .with(Tree) + .with(Position { x, y }) + .with(TreeHitCount(0)); + } + } + height = y + 1; + } + commands.insert_resource(MapSize { width, height }); + commands.insert_resource(Score(1)); +} + +fn translate_positions(mut transform: Mut<Transform>, position: &Position) { + transform.translation = Vec3::new(position.x as f32 * 10., position.y as f32 * -10., 0.); +} + +fn tobogganist_cam( + tobogganist: Query<With<Tobogganist, &Transform>>, + mut camera: Query<With<Camera, &mut Transform>>, +) { + for mut camera_transform in camera.iter_mut() { + if let Some(tobogganist_transform) = tobogganist.iter().next() { + camera_transform.translation = Vec3::new(0., tobogganist_transform.translation.y(), 0.); + } + } +} + +fn move_tobogganist(map_size: Res<MapSize>, mut position: Mut<Position>, velocity: &Velocity) { + position.x += velocity.x; + position.x %= map_size.width; + position.y += velocity.y; +} + +fn collide_with_trees( + mut tobogganists: Query<With<Tobogganist, (&Position, &mut TreeHitCount)>>, + trees: Query<With<Tree, &Position>>, +) { + for (tobogganist_position, mut tree_hit_count) in tobogganists.iter_mut() { + for tree_position in trees.iter() { + if *tree_position == *tobogganist_position { + tree_hit_count.0 += 1; + } + } + } +} + +fn clear_finished_tobogganists( + mut commands: Commands, + map_size: Res<MapSize>, + mut score: ResMut<Score>, + tobogganists: Query<With<Tobogganist, (Entity, &Position, &Velocity, &TreeHitCount)>>, +) { + for (entity, position, velocity, tree_hit_count) in tobogganists.iter() { + if position.y >= map_size.height { + println!( + "A tobogganist finished heading at incline {} x {}, after hitting {} trees", + velocity.x, velocity.y, tree_hit_count.0 + ); + score.0 *= tree_hit_count.0; + commands.despawn(entity); + } + } +} + +fn end_of_slope( + score: Res<Score>, + mut exit_events: ResMut<Events<AppExit>>, + tobogganists: Query<&Tobogganist>, +) { + if tobogganists.iter().count() == 0 { + println!("All tobogganists finished. Total score: {}", score.0); + exit_events.send(AppExit); + } +} |