<commit_before>
use std::num::Float;
use sdl::video::{Surface};
use sdl::event::{Key};

use map::{Map};
use math::{LineSeg, Vec2, Mat3};
use input::{InputState};
use math;

pub struct Game<'a> {
    pub pos: Vec2,
    pub face_angle: f32,
    pub map: &'a Map,
    pub show_map: bool,
}

const SPEED: f32 = 0.4;
const TURN: f32 = 0.03;
const FOV_DIV: f32 = 500.0;
const WALL: f32 = 3000.0;

impl<'a> Game<'a> {

    pub fn step(&mut self, input: &InputState) {
        if input.has_key(Key::Left) {
            self.face_angle -= TURN;
        }
        if input.has_key(Key::Right) {
            self.face_angle += TURN;
        }
        if input.has_key(Key::W) {
            self.pos.x += SPEED*Float::sin(self.face_angle);
            self.pos.y -= SPEED*Float::cos(self.face_angle);
        }
        if input.has_key(Key::S) {
            self.pos.x -= SPEED*Float::sin(self.face_angle);
            self.pos.y += SPEED*Float::cos(self.face_angle);
        }
        if input.has_key(Key::A) {
            self.pos.x -= SPEED*Float::cos(self.face_angle);
            self.pos.y -= SPEED*Float::sin(self.face_angle);
        }
        if input.has_key(Key::D) {
            self.pos.x += SPEED*Float::cos(self.face_angle);
            self.pos.y += SPEED*Float::sin(self.face_angle);
        }
        self.show_map = input.has_key(Key::Tab);
    }

    pub fn render(&self, surf: &Surface) {
        if self.show_map {
            self.render_lines(&surf);
        } else {
            self.render_cast(&surf);
        }
    }

    fn render_lines(&self, surf: &Surface) {
        let trans = Mat3::rotation(-self.face_angle)
                  * Mat3::translation(-self.pos);

        surf.clear();
        for wall in self.map.walls.iter() {
            draw_seg(&surf, &wall.transform(trans), 0xFF, 0x00, 0x00);
        }

        let w = surf.get_width() as usize;
        for x in 0..w {
            let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;
            let (q1,q2) = self.cast_ray(offset);
            match q1 {
                Some(dist) => {
                    let hit = Vec2::new(
                         Float::sin(self.face_angle),
                        -Float::cos(self.face_angle)
                    ) * dist;
                    let draw_sg = LineSeg::new(self.pos.x, self.pos.y, q2.x, q2.y);
                    draw_seg(&surf, &draw_sg.transform(trans), 0x00, 0xFF, 0x00);
                }
                None => {}
            }
        }
    }

    fn render_cast(&self, surf: &Surface) {
        let w = surf.get_width() as usize;
        let h = surf.get_height() as usize;

        surf.clear();
        surf.with_lock(|pixels| {
            for x in 0..w {
                let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;
                let (q1,q2) = self.cast_ray(offset);
                match q1 {
                    Some(dist) => {
                        let ray_height = (WALL / dist) as usize;
                        let top = if h > ray_height { (h - ray_height) / 2 } else { 0 };
                        let bottom = h - top;
                        let proto_color = (0xFF-(h/2) + ray_height/2);
                        let color = if proto_color > 0xFF { 0xFF } else { proto_color as u8 };
                        for y in 0..top {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in top..bottom {
                            put_px(pixels, w, x, y, color, 0, 0);
                        }
                        for y in bottom..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                    None => {
                        for y in 0..(h/2) {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in (h/2)..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                }
            }
            true
        });
    }

    fn cast_ray(&self, offset: f32) -> (Option<f32>, Vec2) {
        let ray = LineSeg::new(
            self.pos.x,
            self.pos.y,
            self.pos.x + 1000.0*Float::sin(self.face_angle + offset),
            self.pos.y - 1000.0*Float::cos(self.face_angle + offset)
        );

        let mut shortest: Option<f32> = None;
        let mut vv: Vec2 = math::V2_ORIGIN;

        for wall in self.map.walls.iter() {
            match ray.intersects_at(*wall) {
                Some(t) => {
                    let dist = (wall.at(t) - self.pos).get_length() * Float::cos(offset);
                    shortest = match shortest {
                        Some(d) => { if dist < d { vv = wall.at(t); Some(dist) } else { shortest } }
                        None    => { vv = wall.at(t); Some(dist) }
                    }
                }
                None => {}
            };
        }

        (shortest, vv)
    }
}

fn put_px(pixels: &mut [u8], w: usize, x: usize, y: usize, r: u8, g: u8, b: u8) {
    pixels[3*(w*y+x) + 0] = b;
    pixels[3*(w*y+x) + 1] = g;
    pixels[3*(w*y+x) + 2] = r;
}

fn draw_seg(surf: &Surface, seg: &LineSeg, r: u8, g: u8, b: u8) {
    let w = surf.get_width() as usize;
    let h = surf.get_height() as usize;
    let len = seg.get_length();

    surf.with_lock(|pixels| {
        for t in 0..(len as usize) {
            let pt = seg.at(t as f32 / len);
            let ux = (pt.x + (w/2) as f32) as usize;
            let uy = (pt.y + (h/2) as f32) as usize;

            if ux < w && uy < h {
                put_px(pixels, w, ux, uy, r, g, b);
            }
        };
        true
    });
}
<commit_msg>Fixed warnings<commit_after>
use std::num::Float;
use sdl::video::{Surface};
use sdl::event::{Key};

use map::{Map};
use math::{LineSeg, Vec2, Mat3};
use input::{InputState};
use math;

pub struct Game<'a> {
    pub pos: Vec2,
    pub face_angle: f32,
    pub map: &'a Map,
    pub show_map: bool,
}

const SPEED: f32 = 0.4;
const TURN: f32 = 0.03;
const FOV_DIV: f32 = 500.0;
const WALL: f32 = 3000.0;

impl<'a> Game<'a> {

    pub fn step(&mut self, input: &InputState) {
        if input.has_key(Key::Left) {
            self.face_angle -= TURN;
        }
        if input.has_key(Key::Right) {
            self.face_angle += TURN;
        }
        if input.has_key(Key::W) {
            self.pos.x += SPEED*Float::sin(self.face_angle);
            self.pos.y -= SPEED*Float::cos(self.face_angle);
        }
        if input.has_key(Key::S) {
            self.pos.x -= SPEED*Float::sin(self.face_angle);
            self.pos.y += SPEED*Float::cos(self.face_angle);
        }
        if input.has_key(Key::A) {
            self.pos.x -= SPEED*Float::cos(self.face_angle);
            self.pos.y -= SPEED*Float::sin(self.face_angle);
        }
        if input.has_key(Key::D) {
            self.pos.x += SPEED*Float::cos(self.face_angle);
            self.pos.y += SPEED*Float::sin(self.face_angle);
        }
        self.show_map = input.has_key(Key::Tab);
    }

    pub fn render(&self, surf: &Surface) {
        if self.show_map {
            self.render_lines(&surf);
        } else {
            self.render_cast(&surf);
        }
    }

    fn render_lines(&self, surf: &Surface) {
        let trans = Mat3::rotation(-self.face_angle)
                  * Mat3::translation(-self.pos);

        surf.clear();
        for wall in self.map.walls.iter() {
            draw_seg(&surf, wall.transform(trans), 0xFF, 0x00, 0x00);
        }

        let w = surf.get_width() as usize;
        for x in 0..w {
            let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;
            let (q1,q2) = self.cast_ray(offset);
            match q1 {
                Some(_) => {
                    let draw_sg = LineSeg::new(self.pos.x, self.pos.y, q2.x, q2.y);
                    draw_seg(&surf, draw_sg.transform(trans), 0x00, 0xFF, 0x00);
                }
                None => {}
            }
        }
    }

    fn render_cast(&self, surf: &Surface) {
        let w = surf.get_width() as usize;
        let h = surf.get_height() as usize;

        surf.clear();
        surf.with_lock(|pixels| {
            for x in 0..w {
                let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;
                let (q1,_) = self.cast_ray(offset);
                match q1 {
                    Some(dist) => {
                        let ray_height = (WALL / dist) as usize;
                        let top = if h > ray_height { (h - ray_height) / 2 } else { 0 };
                        let bottom = h - top;
                        let proto_color = 0xFF-(h/2) + ray_height/2;
                        let color = if proto_color > 0xFF { 0xFF } else { proto_color as u8 };
                        for y in 0..top {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in top..bottom {
                            put_px(pixels, w, x, y, color, 0, 0);
                        }
                        for y in bottom..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                    None => {
                        for y in 0..(h/2) {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in (h/2)..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                }
            }
            true
        });
    }

    fn cast_ray(&self, offset: f32) -> (Option<f32>, Vec2) {
        let ray = LineSeg::new(
            self.pos.x,
            self.pos.y,
            self.pos.x + 1000.0*Float::sin(self.face_angle + offset),
            self.pos.y - 1000.0*Float::cos(self.face_angle + offset)
        );

        let mut shortest: Option<f32> = None;
        let mut vv: Vec2 = math::V2_ORIGIN;

        for wall in self.map.walls.iter() {
            match ray.intersects_at(*wall) {
                Some(t) => {
                    let dist = (wall.at(t) - self.pos).get_length() * Float::cos(offset);
                    shortest = match shortest {
                        Some(d) => { if dist < d { vv = wall.at(t); Some(dist) } else { shortest } }
                        None    => { vv = wall.at(t); Some(dist) }
                    }
                }
                None => {}
            };
        }

        (shortest, vv)
    }
}

fn put_px(pixels: &mut [u8], w: usize, x: usize, y: usize, r: u8, g: u8, b: u8) {
    pixels[3*(w*y+x) + 0] = b;
    pixels[3*(w*y+x) + 1] = g;
    pixels[3*(w*y+x) + 2] = r;
}

fn draw_seg(surf: &Surface, seg: LineSeg, r: u8, g: u8, b: u8) {
    let w = surf.get_width() as usize;
    let h = surf.get_height() as usize;
    let len = seg.get_length();

    surf.with_lock(|pixels| {
        for t in 0..(len as usize) {
            let pt = seg.at(t as f32 / len);
            let ux = (pt.x + (w/2) as f32) as usize;
            let uy = (pt.y + (h/2) as f32) as usize;

            if ux < w && uy < h {
                put_px(pixels, w, ux, uy, r, g, b);
            }
        };
        true
    });
}
<|endoftext|>


<commit_before>use world::World;
use camera::Camera;
use color::*;
use car::*;
use bot::BoxRules;
use Pixel;
use control::{Flow, EventHandler};

use std::cell::RefCell;
use std::ops::DerefMut;
use std::time::Instant;

use piston_window::*;
use cgmath::{Vector2, vec3};
use cgmath::prelude::*;

// Configurable game's contansts.
// A tuple presents a range of something.
#[derive(Serialize, Deserialize, Clone)]
pub struct GameConfig {
    pub title: String,
    pub screen_size: ::Pixel,
    pub ups: u64, // Update per second
    pub max_fps: u64,
    pub tunel_size: [f64; 3],
    pub player_size: [f64; 3],
    pub player_speed: (f64, f64), // min and max player speed
    pub player_turn_speed: f64,
    pub bot_size: [(f64, f64); 3], // Range of bot's size
    pub bot_speed: (f64, f64),
    pub bot_turn_speed: (f64, f64),
    pub divider_size: [f64; 2],
    pub camera_height: f64, // Height of camera (from player)
    pub camera_distance: f64, // Distance from camera to player
    pub decor_distance: f64, // Distance between each decoration
    pub sprint_factor: f64,
    pub spawn_time: (f64, f64),
    pub game_sprint: f64, // The increase of game_speed
    pub game_max_speed: f64,
    pub player_jump_v: f64,
    pub player_jump_a: f64,
    pub jump_turn_decrease: f64,
    pub jump_timeout: f64,
    pub mouse_speed: f64,
    pub trueshot_distance: f64,
    pub bullet_stock: i64, // Number of bullets
    pub recharge_time: f64,
    pub bullet_len: f64,
    pub bullet_speed: f64,
    pub zoom_in: bool, // If true, zoom-in while on stare mode
}

impl Default for GameConfig {
    fn default() -> GameConfig {
        use std::f64::consts::PI;
        GameConfig {
            title: "Box Crash".to_owned(),
            screen_size: Pixel::new(800, 600),
            ups: 60,
            max_fps: 60,
            tunel_size: [15., 8., 150.],
            player_size: [1.5, 0.8, 3.],
            player_speed: (20., 120.),
            player_turn_speed: 15.,
            bot_size: [(1., 4.), (0.5, 2.5), (2.5, 8.)],
            bot_speed: (20., 120.),
            bot_turn_speed: (5., 20.),
            divider_size: [1., 7.],
            camera_height: 3.,
            camera_distance: 5.5,
            decor_distance: 8.,
            sprint_factor: 15.,
            spawn_time: (0.25, 1.),
            game_sprint: 1.,
            game_max_speed: 80.,
            player_jump_v: 7.,
            player_jump_a: 5.,
            jump_turn_decrease: 3.,
            jump_timeout: 8.,
            mouse_speed: PI/420.,
            trueshot_distance: 100.,
            bullet_stock: 15,
            recharge_time: 10.,
            bullet_len: 5.,
            bullet_speed: 100.,
            zoom_in: false,
        }
    }
}

// `Game` contains every things to run the game
pub struct Game {
    config: GameConfig,
    world: World, // All objects in the game
    bot_rules: BoxRules, // Rules to create a new bot
    camera: Camera, // Camera for rendering
    state: State, // Current state of game
    // Wrap these caches in `RefCell` to allow interior mutability
    glyphs: RefCell<Glyphs>, // Font cache
    ellipse: RefCell<Ellipse>, // Model to draw a circle
}

struct State {
    pub turn: Turn, // Presents movement of player
    pub sprint: bool, // Player is speeding-up or not
    pub spawn: f64, // Count down time to spawn a new bot
    pub ended: bool, // Game is over or not
    pub game_speed: f64, // Game speed in addition to player's speed
    pub jump_timeout: f64, // Count down to allow the next jump
    pub rotate_cam: bool, // Allow rotation of camera or not
    pub bullets: i64, // The number of bullets left
    pub recharge: f64, // Bullets recharge time
    pub fps: f64, // Real fps of game
    pub last_frame: Instant, // Moment of the last draw
}

pub enum Turn { Left, Right, None, }

impl Game {
    pub fn new(config: GameConfig, window: &PistonWindow) -> Game {
        let glyphs = Glyphs::new("resources/Ubuntu-R.ttf", window.factory.clone(), texture::TextureSettings::new())
            .expect("Unable to load font.");
        let bot_rules = BoxRules {
            size: config.bot_size,
            position: [(0., config.tunel_size[0]), (0., 0.), (config.tunel_size[2], config.tunel_size[2])],
            speed: config.bot_speed,
            turn_speed: config.bot_turn_speed,
            color: vec![RED, ORANGE, VIOLET, GREEN, PALE],
            jump_turn_decrease: config.jump_turn_decrease,
        };
        let world = World::new(&config);
        let camera = Game::new_camera(&config, &world.player);
        let state = State {
            turn: Turn::None,
            sprint: false,
            spawn: 0.,
            ended: false,
            game_speed: 0.,
            jump_timeout: 0.,
            rotate_cam: false,
            bullets: config.bullet_stock,
            recharge: 0.,
            fps: 0.,
            last_frame: Instant::now(),
        };
        let ellipse = Ellipse {
            color: BLACK.alpha(0.).into(),
            border: Some(ellipse::Border {
                color: RED.alpha(0.5).into(),
                radius: 1.,
            }),
            resolution: 16,
        };

        Game {
            config: config,
            world: world,
            bot_rules: bot_rules,
            camera: camera,
            state: state,
            glyphs: RefCell::new(glyphs),
            ellipse: RefCell::new(ellipse),
        }
    }

    fn new_camera<T: Car>(config: &GameConfig, player: &T) -> Camera {
        Camera::new(
            config.screen_size.clone(),
            vec3(0., config.camera_height, -config.camera_distance) + player.pos()
        )
    }
    // Re-calculate fps
    fn update_fps(&mut self) {
        let d = self.state.last_frame.elapsed();
        self.state.last_frame = Instant::now();
        self.state.fps = 1. / (d.as_secs() as f64 + 1e-9*d.subsec_nanos() as f64);
    }

    fn mouse_move(&mut self, x: f64, y: f64) {
        if self.state.rotate_cam {
            self.camera.rotate(x*self.config.mouse_speed, y*self.config.mouse_speed, self.world.player.position);
        }
    }
    fn press(&mut self, key: Button) {
        match key {
            Button::Keyboard(Key::A) => self.state.turn = Turn::Left,
            Button::Keyboard(Key::D) => self.state.turn = Turn::Right,
            Button::Keyboard(Key::W) => self.state.sprint = true,
            Button::Keyboard(Key::Space) => if self.state.jump_timeout <= 0. {
                self.state.jump_timeout = self.config.jump_timeout;
                self.world.player.jump();
            },
            Button::Mouse(MouseButton::Right) => {
                if self.config.zoom_in {
                    self.camera.zoom_in();
                }
                self.state.rotate_cam = true;
            },
            Button::Mouse(MouseButton::Left) => if self.state.rotate_cam && self.state.bullets > 0 {
                let mut pos = self.world.player.position;
                pos.y += self.world.player.size.y;
                let mut d = vec3(0., 0., self.config.trueshot_distance + self.config.camera_distance);
                d = self.camera.c * d.magnitude2() / d.dot(self.camera.c);
                d = self.camera.eye + d - pos;
                d = d * self.config.bullet_speed / d.magnitude();
                self.world.add_bullet(pos, d, self.config.bullet_len);
                self.state.bullets -= 1;
                if self.state.bullets <= 0 {
                    self.state.recharge = self.config.recharge_time;
                }
            },
            _ => (),
        }
    }
    fn release(&mut self, key: Button) {
        match key {
            Button::Keyboard(Key::A) => if let Turn::Left = self.state.turn {
                self.state.turn = Turn::None;
            },
            Button::Keyboard(Key::D) => if let Turn::Right = self.state.turn {
                self.state.turn = Turn::None;
            },
            Button::Keyboard(Key::W) => self.state.sprint = false,
            Button::Mouse(MouseButton::Right) => {
                self.state.rotate_cam = false;
                self.camera = Game::new_camera(&self.config, &self.world.player);
            },
            _ => (),
        }
    }
    fn draw(&mut self, e: &Event, window: &mut PistonWindow) {
        // Return a horizontal bar
        macro_rules! bar {
            ($curr: expr, $full: expr) => {
                [0.,
                15.0,
                self.config.screen_size.w as f64/2.*$curr/$full,
                20.0,]
            };
        }
        let jump_bar = bar!(self.state.jump_timeout, self.config.jump_timeout);
        let recharge_bar = bar!(self.state.recharge, self.config.recharge_time);
        let bullets_bar = bar!(self.state.bullets as f64, self.config.bullet_stock as f64);
        // Closure in `draw_2d` requires unique access to `self`,
        // so we use RefCell to hack it.
        let mut glyphs = self.glyphs.borrow_mut();
        let fps = format!("{:.3}", self.state.fps);
        let lines = self.world.render(&self.camera);
        window.draw_2d(e, |c, g| {
            clear(BLACK.into(), g);
            for (l, color) in lines {
                line(color.into(), 1., convert(l), c.transform, g);
            }
            rectangle(BLUE.alpha(0.4).into(), jump_bar, c.transform, g);
            rectangle(RED.alpha(0.4).into(), recharge_bar, c.transform, g);
            rectangle(GREEN.alpha(0.4).into(), bullets_bar, c.transform, g);
            text(WHITE.into(), 10, &fps, glyphs.deref_mut(), c.transform.trans(0., 10.), g);
        });

        if self.state.rotate_cam {
            let w = 20.;
            let x = self.config.screen_size.w as f64 /2. - w/2.;
            let y = self.config.screen_size.h as f64 /2. - w/2.;
            let ellipse = self.ellipse.borrow();
            window.draw_2d(e, |c, g| {
                ellipse.draw([x, y, w, w], &c.draw_state, c.transform, g);
                rectangle(RED.into(), [x+w/2.-1., y+w/2.-1., 2., 2.], c.transform, g);
            });
        }
    }
    // `dt` stands for delta, duration since the last update
    fn update(&mut self, dt: f64) {
        // Re-calculate delta according to fps
        let dt = if self.state.fps != 0. { 1./self.state.fps}
        else { dt };
        let old = self.world.player.position;
        if self.state.bullets <= 0 {
            self.state.recharge -= dt;
            if self.state.recharge < 0. {
                self.state.bullets = self.config.bullet_stock;
            }
        }
        self.state.jump_timeout -= dt;
        if self.state.game_speed < self.config.game_max_speed {
            self.state.game_speed += dt*self.config.game_sprint;
        }
        if self.state.sprint {
            if self.world.player.speed < self.config.player_speed.1 {
                self.world.player.speed += dt*self.config.sprint_factor;
            }
        } else if self.world.player.speed > self.config.player_speed.0 {
            self.world.player.speed -= dt*self.config.sprint_factor;
        }
        self.state.spawn -= dt;
        if self.state.spawn < 0. {
            self.world.add_bot(&self.bot_rules);
            self.state.spawn += ::rnd(self.config.spawn_time);
        }
        match self.state.turn {
            Turn::Left => self.world.player.turn_left(dt),
            Turn::Right => self.world.player.turn_right(dt),
            Turn::None => (),
        }
        // Update objects in the world
        self.world.update(dt, self.state.game_speed);
        // Validate things like object's boundary, bullets and boxes
        // collisions.
        self.world.validate();
        // Update camera's location
        self.camera.eye += self.world.player.position - old;
        // Check for player's collision with bot
        if self.world.bots.iter().any(|x| self.world.player.crashed(&x.car)) {
            self.state.ended = true;
        }
    }
}

impl EventHandler for Game {
    type Input = ();
    fn handle_event(&mut self, e: Event, window: &mut PistonWindow, _: &mut Self::Input) -> Option<Flow> {
        use Input::*;
        use Loop::*;
        use Motion::*;
        use Event::*;
        match e {
            Loop(Render(_)) => {
                self.update_fps();
                self.draw(&e, window);
            },
            Loop(Update(args)) => self.update(args.dt),
            Input(Button(args)) => {
                use ButtonState::*;
                match args.state {
                    Press => self.press(args.button),
                    Release => self.release(args.button),
                }
            },
            Input(Move(MouseRelative(a, b))) => self.mouse_move(a as f64, b as f64),
            _ => {}
        }

        if self.state.ended {
            Some(Flow::LoseGame)
        } else {
            None
        }
    }
}

fn convert(x: [Vector2<f64>; 2]) -> [f64; 4] {
    [x[0].x, x[0].y, x[1].x, x[1].y]
}
<commit_msg>small change to improve performance<commit_after>use world::World;
use camera::Camera;
use color::*;
use car::*;
use bot::BoxRules;
use Pixel;
use control::{Flow, EventHandler};

use std::cell::RefCell;
use std::ops::DerefMut;
use std::time::Instant;

use piston_window::*;
use cgmath::{Vector2, vec3};
use cgmath::prelude::*;

// Configurable game's contansts.
// A tuple presents a range of something.
#[derive(Serialize, Deserialize, Clone)]
pub struct GameConfig {
    pub title: String,
    pub screen_size: ::Pixel,
    pub ups: u64, // Update per second
    pub max_fps: u64,
    pub tunel_size: [f64; 3],
    pub player_size: [f64; 3],
    pub player_speed: (f64, f64), // min and max player speed
    pub player_turn_speed: f64,
    pub bot_size: [(f64, f64); 3], // Range of bot's size
    pub bot_speed: (f64, f64),
    pub bot_turn_speed: (f64, f64),
    pub divider_size: [f64; 2],
    pub camera_height: f64, // Height of camera (from player)
    pub camera_distance: f64, // Distance from camera to player
    pub decor_distance: f64, // Distance between each decoration
    pub sprint_factor: f64,
    pub spawn_time: (f64, f64),
    pub game_sprint: f64, // The increase of game_speed
    pub game_max_speed: f64,
    pub player_jump_v: f64,
    pub player_jump_a: f64,
    pub jump_turn_decrease: f64,
    pub jump_timeout: f64,
    pub mouse_speed: f64,
    pub trueshot_distance: f64,
    pub bullet_stock: i64, // Number of bullets
    pub recharge_time: f64,
    pub bullet_len: f64,
    pub bullet_speed: f64,
    pub zoom_in: bool, // If true, zoom-in while on stare mode
}

impl Default for GameConfig {
    fn default() -> GameConfig {
        use std::f64::consts::PI;
        GameConfig {
            title: "Box Crash".to_owned(),
            screen_size: Pixel::new(800, 600),
            ups: 60,
            max_fps: 60,
            tunel_size: [15., 8., 150.],
            player_size: [1.5, 0.8, 3.],
            player_speed: (20., 120.),
            player_turn_speed: 15.,
            bot_size: [(1., 4.), (0.5, 2.5), (2.5, 8.)],
            bot_speed: (20., 120.),
            bot_turn_speed: (5., 20.),
            divider_size: [1., 7.],
            camera_height: 3.,
            camera_distance: 5.5,
            decor_distance: 8.,
            sprint_factor: 15.,
            spawn_time: (0.25, 1.),
            game_sprint: 1.,
            game_max_speed: 80.,
            player_jump_v: 7.,
            player_jump_a: 5.,
            jump_turn_decrease: 3.,
            jump_timeout: 8.,
            mouse_speed: PI/420.,
            trueshot_distance: 100.,
            bullet_stock: 15,
            recharge_time: 10.,
            bullet_len: 5.,
            bullet_speed: 100.,
            zoom_in: false,
        }
    }
}

// `Game` contains every things to run the game
pub struct Game {
    config: GameConfig,
    world: World, // All objects in the game
    bot_rules: BoxRules, // Rules to create a new bot
    camera: Camera, // Camera for rendering
    state: State, // Current state of game
    // Wrap these caches in `RefCell` to allow interior mutability
    glyphs: RefCell<Glyphs>, // Font cache
    ellipse: RefCell<Ellipse>, // Model to draw a circle
}

struct State {
    pub turn: Turn, // Presents movement of player
    pub sprint: bool, // Player is speeding-up or not
    pub spawn: f64, // Count down time to spawn a new bot
    pub ended: bool, // Game is over or not
    pub game_speed: f64, // Game speed in addition to player's speed
    pub jump_timeout: f64, // Count down to allow the next jump
    pub rotate_cam: bool, // Allow rotation of camera or not
    pub bullets: i64, // The number of bullets left
    pub recharge: f64, // Bullets recharge time
    pub fps: f64, // Real fps of game
    pub last_frame: Instant, // Moment of the last draw
}

pub enum Turn { Left, Right, None, }

impl Game {
    pub fn new(config: GameConfig, window: &PistonWindow) -> Game {
        let glyphs = Glyphs::new("resources/Ubuntu-R.ttf", window.factory.clone(), texture::TextureSettings::new())
            .expect("Unable to load font.");
        let bot_rules = BoxRules {
            size: config.bot_size,
            position: [(0., config.tunel_size[0]), (0., 0.), (config.tunel_size[2], config.tunel_size[2])],
            speed: config.bot_speed,
            turn_speed: config.bot_turn_speed,
            color: vec![RED, ORANGE, VIOLET, GREEN, PALE],
            jump_turn_decrease: config.jump_turn_decrease,
        };
        let world = World::new(&config);
        let camera = Game::new_camera(&config, &world.player);
        let state = State {
            turn: Turn::None,
            sprint: false,
            spawn: 0.,
            ended: false,
            game_speed: 0.,
            jump_timeout: 0.,
            rotate_cam: false,
            bullets: config.bullet_stock,
            recharge: 0.,
            fps: 0.,
            last_frame: Instant::now(),
        };
        let ellipse = Ellipse {
            color: BLACK.alpha(0.).into(),
            border: Some(ellipse::Border {
                color: RED.alpha(0.5).into(),
                radius: 1.,
            }),
            resolution: 8,
        };

        Game {
            config: config,
            world: world,
            bot_rules: bot_rules,
            camera: camera,
            state: state,
            glyphs: RefCell::new(glyphs),
            ellipse: RefCell::new(ellipse),
        }
    }

    fn new_camera<T: Car>(config: &GameConfig, player: &T) -> Camera {
        Camera::new(
            config.screen_size.clone(),
            vec3(0., config.camera_height, -config.camera_distance) + player.pos()
        )
    }
    // Re-calculate fps
    fn update_fps(&mut self) {
        let d = self.state.last_frame.elapsed();
        self.state.last_frame = Instant::now();
        self.state.fps = 1. / (d.as_secs() as f64 + 1e-9*d.subsec_nanos() as f64);
    }

    fn mouse_move(&mut self, x: f64, y: f64) {
        if self.state.rotate_cam {
            self.camera.rotate(x*self.config.mouse_speed, y*self.config.mouse_speed, self.world.player.position);
        }
    }
    fn press(&mut self, key: Button) {
        match key {
            Button::Keyboard(Key::A) => self.state.turn = Turn::Left,
            Button::Keyboard(Key::D) => self.state.turn = Turn::Right,
            Button::Keyboard(Key::W) => self.state.sprint = true,
            Button::Keyboard(Key::Space) => if self.state.jump_timeout <= 0. {
                self.state.jump_timeout = self.config.jump_timeout;
                self.world.player.jump();
            },
            Button::Mouse(MouseButton::Right) => {
                if self.config.zoom_in {
                    self.camera.zoom_in();
                }
                self.state.rotate_cam = true;
            },
            Button::Mouse(MouseButton::Left) => if self.state.rotate_cam && self.state.bullets > 0 {
                let mut pos = self.world.player.position;
                pos.y += self.world.player.size.y;
                let mut d = vec3(0., 0., self.config.trueshot_distance + self.config.camera_distance);
                d = self.camera.c * d.magnitude2() / d.dot(self.camera.c);
                d = self.camera.eye + d - pos;
                d = d * self.config.bullet_speed / d.magnitude();
                self.world.add_bullet(pos, d, self.config.bullet_len);
                self.state.bullets -= 1;
                if self.state.bullets <= 0 {
                    self.state.recharge = self.config.recharge_time;
                }
            },
            _ => (),
        }
    }
    fn release(&mut self, key: Button) {
        match key {
            Button::Keyboard(Key::A) => if let Turn::Left = self.state.turn {
                self.state.turn = Turn::None;
            },
            Button::Keyboard(Key::D) => if let Turn::Right = self.state.turn {
                self.state.turn = Turn::None;
            },
            Button::Keyboard(Key::W) => self.state.sprint = false,
            Button::Mouse(MouseButton::Right) => {
                self.state.rotate_cam = false;
                self.camera = Game::new_camera(&self.config, &self.world.player);
            },
            _ => (),
        }
    }
    fn draw(&mut self, e: &Event, window: &mut PistonWindow) {
        // Return a horizontal bar
        macro_rules! bar {
            ($curr: expr, $full: expr) => {
                [0.,
                15.0,
                self.config.screen_size.w as f64/2.*$curr/$full,
                20.0,]
            };
        }
        let jump_bar = bar!(self.state.jump_timeout, self.config.jump_timeout);
        let recharge_bar = bar!(self.state.recharge, self.config.recharge_time);
        let bullets_bar = bar!(self.state.bullets as f64, self.config.bullet_stock as f64);
        // Closure in `draw_2d` requires unique access to `self`,
        // so we use RefCell to hack it.
        let mut glyphs = self.glyphs.borrow_mut();
        let fps = format!("{:.3}", self.state.fps);
        let lines = self.world.render(&self.camera);
        window.draw_2d(e, |c, g| {
            clear(BLACK.into(), g);
            for (l, color) in lines {
                line(color.into(), 1., convert(l), c.transform, g);
            }
            rectangle(BLUE.alpha(0.4).into(), jump_bar, c.transform, g);
            rectangle(RED.alpha(0.4).into(), recharge_bar, c.transform, g);
            rectangle(GREEN.alpha(0.4).into(), bullets_bar, c.transform, g);
            text(WHITE.into(), 10, &fps, glyphs.deref_mut(), c.transform.trans(0., 10.), g);
        });

        if self.state.rotate_cam {
            let w = 20.;
            let x = self.config.screen_size.w as f64 /2. - w/2.;
            let y = self.config.screen_size.h as f64 /2. - w/2.;
            let ellipse = self.ellipse.borrow();
            window.draw_2d(e, |c, g| {
                ellipse.draw([x, y, w, w], &c.draw_state, c.transform, g);
                rectangle(RED.into(), [x+w/2.-1., y+w/2.-1., 2., 2.], c.transform, g);
            });
        }
    }
    // `dt` stands for delta, duration since the last update
    fn update(&mut self, dt: f64) {
        // Re-calculate delta according to fps
        let dt = if self.state.fps != 0. { 1./self.state.fps}
        else { dt };
        let old = self.world.player.position;
        if self.state.bullets <= 0 {
            self.state.recharge -= dt;
            if self.state.recharge < 0. {
                self.state.bullets = self.config.bullet_stock;
            }
        }
        self.state.jump_timeout -= dt;
        if self.state.game_speed < self.config.game_max_speed {
            self.state.game_speed += dt*self.config.game_sprint;
        }
        if self.state.sprint {
            if self.world.player.speed < self.config.player_speed.1 {
                self.world.player.speed += dt*self.config.sprint_factor;
            }
        } else if self.world.player.speed > self.config.player_speed.0 {
            self.world.player.speed -= dt*self.config.sprint_factor;
        }
        self.state.spawn -= dt;
        if self.state.spawn < 0. {
            self.world.add_bot(&self.bot_rules);
            self.state.spawn += ::rnd(self.config.spawn_time);
        }
        match self.state.turn {
            Turn::Left => self.world.player.turn_left(dt),
            Turn::Right => self.world.player.turn_right(dt),
            Turn::None => (),
        }
        // Update objects in the world
        self.world.update(dt, self.state.game_speed);
        // Validate things like object's boundary, bullets and boxes
        // collisions.
        self.world.validate();
        // Update camera's location
        self.camera.eye += self.world.player.position - old;
        // Check for player's collision with bot
        if self.world.bots.iter().any(|x| self.world.player.crashed(&x.car)) {
            self.state.ended = true;
        }
    }
}

impl EventHandler for Game {
    type Input = ();
    fn handle_event(&mut self, e: Event, window: &mut PistonWindow, _: &mut Self::Input) -> Option<Flow> {
        use Input::*;
        use Loop::*;
        use Motion::*;
        use Event::*;
        match e {
            Loop(Render(_)) => {
                self.update_fps();
                self.draw(&e, window);
            },
            Loop(Update(args)) => self.update(args.dt),
            Input(Button(args)) => {
                use ButtonState::*;
                match args.state {
                    Press => self.press(args.button),
                    Release => self.release(args.button),
                }
            },
            Input(Move(MouseRelative(a, b))) => self.mouse_move(a as f64, b as f64),
            _ => {}
        }

        if self.state.ended {
            Some(Flow::LoseGame)
        } else {
            None
        }
    }
}

fn convert(x: [Vector2<f64>; 2]) -> [f64; 4] {
    [x[0].x, x[0].y, x[1].x, x[1].y]
}
<|endoftext|>


<commit_before>//! Hints (suggestions at the right of the prompt as you type).

use crate::history::Direction;
use crate::Context;

/// Hints provider
pub trait Hinter {
    /// Takes the currently edited `line` with the cursor `pos`ition and
    /// returns the string that should be displayed or `None`
    /// if no hint is available for the text the user currently typed.
    // TODO Validate: called while editing line but not while moving cursor.
    fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
        let _ = (line, pos, ctx);
        None
    }
}

impl Hinter for () {}

impl<'r, H: ?Sized + Hinter> Hinter for &'r H {
    fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
        (**self).hint(line, pos, ctx)
    }
}

pub struct HistoryHinter {}

impl Hinter for HistoryHinter {
    fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
        let start = if ctx.history_index() == ctx.history().len() {
            ctx.history_index().saturating_sub(1)
        } else {
            ctx.history_index()
        };
        if let Some(history_index) =
            ctx.history
                .starts_with(&line[..pos], start, Direction::Reverse)
        {
            let entry = ctx.history.get(history_index);
            if let Some(entry) = entry {
                if entry == line || entry == &line[..pos] {
                    return None;
                }
            }
            return entry.map(|s| s[pos..].to_owned());
        }
        None
    }
}

#[cfg(test)]
mod test {
    use super::{Hinter, HistoryHinter};
    use crate::history::History;
    use crate::Context;

    #[test]
    pub fn empty_history() {
        let history = History::new();
        let ctx = Context {
            history: &history,
            history_index: 0,
        };
        let hinter = HistoryHinter {};
        let hint = hinter.hint("test", 4, &ctx);
        assert_eq!(None, hint);
    }
}
<commit_msg>Fix HistoryHinter<commit_after>//! Hints (suggestions at the right of the prompt as you type).

use crate::history::Direction;
use crate::Context;

/// Hints provider
pub trait Hinter {
    /// Takes the currently edited `line` with the cursor `pos`ition and
    /// returns the string that should be displayed or `None`
    /// if no hint is available for the text the user currently typed.
    // TODO Validate: called while editing line but not while moving cursor.
    fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
        let _ = (line, pos, ctx);
        None
    }
}

impl Hinter for () {}

impl<'r, H: ?Sized + Hinter> Hinter for &'r H {
    fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
        (**self).hint(line, pos, ctx)
    }
}

pub struct HistoryHinter {}

impl Hinter for HistoryHinter {
    fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
        if pos < line.len() {
            return None;
        }
        let start = if ctx.history_index() == ctx.history().len() {
            ctx.history_index().saturating_sub(1)
        } else {
            ctx.history_index()
        };
        if let Some(history_index) =
            ctx.history
                .starts_with(&line[..pos], start, Direction::Reverse)
        {
            let entry = ctx.history.get(history_index);
            if let Some(entry) = entry {
                if entry == line || entry == &line[..pos] {
                    return None;
                }
            }
            return entry.map(|s| s[pos..].to_owned());
        }
        None
    }
}

#[cfg(test)]
mod test {
    use super::{Hinter, HistoryHinter};
    use crate::history::History;
    use crate::Context;

    #[test]
    pub fn empty_history() {
        let history = History::new();
        let ctx = Context {
            history: &history,
            history_index: 0,
        };
        let hinter = HistoryHinter {};
        let hint = hinter.hint("test", 4, &ctx);
        assert_eq!(None, hint);
    }
}
<|endoftext|>


<commit_before>use std::str;
use std::str::FromStr;
use nom::*;
use nom::IResult::*;
use nock::Noun;

// XXX: Is there a nicer way to ignore the results from eg. newline than
// the superfluous chain!?
named!(gap<()>, alt!(
        chain!(newline, || { () })
      | chain!(tag!(" ") ~ tag!(" ") ~ multispace, || { () })
    )
);

// TODO: Handle separator dots
named!(atom<Noun>,
  map_res!(
    map_res!(
      digit,
      str::from_utf8
    ),
    FromStr::from_str
  )
);

named!(wtcl<Noun>,
   chain!(
       tag!("?:") ~
       x: alt!(
           chain!(
               gap ~
               p: atom ~
               gap ~
               q: atom ~
               gap ~
               r: atom,
               || { n![6, p, q, r] })
        | delimited!(
            tag!("("),
            chain!(
               p: atom ~
               space ~
               q: atom ~
               space ~
               r: atom,
               || { n![6, p, q, r] }),
            tag!(")"))
        ),
    || { x }
    )
);

named!(hoon<Noun>,
    alt!(
        atom
      | wtcl
    )
);

#[cfg(test)]
mod test {
    use nom::IResult;
    use nock::Noun;
    use super::{gap, atom, wtcl};

    #[test]
    fn test_parse_hoon() {
        assert_eq!(atom(&b"1234"[..]), IResult::Done(&b""[..], Noun::Atom(1234)));

        assert_eq!(gap(&b"  "[..]), IResult::Done(&b""[..], ()));
        assert_eq!(gap(&b"    "[..]), IResult::Done(&b""[..], ()));
        assert_eq!(gap(&b"\n"[..]), IResult::Done(&b""[..], ()));
        assert!(gap(&b" "[..]) != IResult::Done(&b""[..], ()));

        assert_eq!(wtcl(&b"?:(1 2 3)"[..]), IResult::Done(&b""[..], n![6, 1, 2, 3]));
        assert_eq!(wtcl(&b"?:  1\n  2\n3"[..]), IResult::Done(&b""[..], n![6, 1, 2, 3]));
    }
}
<commit_msg>Hoon parser does gaps<commit_after>use std::str;
use std::str::FromStr;
use nom::*;
use nom::IResult::*;
use nom::Err::*;
use nock::Noun;

/// Match at least two spaces or one newline.
pub fn gap(input: &[u8]) -> IResult<&[u8], &[u8]> {
    let mut spaces = 0;
    let mut idx = 0;
    for item in input.iter() {
        if *item == '\t' as u8 {
            // Physical tabs are banned.
            // XXX: Should have own ErrorKind tag.
            return Error(Position(ErrorKind::MultiSpace, input));
        }

        if *item == '\n' as u8 {
            spaces += 2;
        } else if is_space(*item) {
            spaces += 1;
        }

        if !is_space(*item) && *item != '\r' as u8 && *item != '\n' as u8 {
            break;
        }

        idx += 1;
    }

    if spaces < 2 {
        return Error(Position(ErrorKind::MultiSpace, input));
    } else {
        return Done(&input[idx..], &input[0..idx]);
    }
}

// TODO: Handle separator dots
named!(atom<Noun>,
  map_res!(
    map_res!(
      digit,
      str::from_utf8
    ),
    FromStr::from_str
  )
);

named!(pqr<(Noun, Noun, Noun)>,
    alt!(
        chain!(
            p: preceded!(gap, atom) ~
            q: preceded!(gap, atom) ~
            r: preceded!(gap, atom),
            || { (p, q, r) })
        | delimited!(
            tag!("("),
            chain!(
                p: atom ~
                multispace ~
                q: atom ~
                multispace ~
                r: atom,
                || { (p, q, r) }),
            tag!(")"))
    )
);

named!(wtcl<Noun>,
   chain!(
       tag!("?:")
     ~ a: pqr
     , || { let (p, q, r) = a.clone(); n![6, p, q, r] }
    )
);

named!(hoon<Noun>,
    alt!(
        atom
      | wtcl
    )
);

#[cfg(test)]
mod test {
    use nom::IResult;
    use nock::Noun;
    use super::{gap, atom, pqr, wtcl};

    #[test]
    fn test_parse_hoon() {
        assert_eq!(atom(&b"1234"[..]),
                   IResult::Done(&b""[..], Noun::Atom(1234)));

        assert!(gap(&b"  "[..]).is_done());
        assert!(gap(&b"    "[..]).is_done());
        assert!(gap(&b"\n"[..]).is_done());
        assert!(gap(&b"\n  "[..]).is_done());
        assert!(gap(&b"  \n  "[..]).is_done());
        assert!(!gap(&b" "[..]).is_done());

        assert_eq!(pqr(&b"(1 2 3)"[..]),
                   IResult::Done(&b""[..], (Noun::Atom(1), Noun::Atom(2), Noun::Atom(3))));
        assert_eq!(pqr(&b"\n1\n2\n3"[..]),
                   IResult::Done(&b""[..], (Noun::Atom(1), Noun::Atom(2), Noun::Atom(3))));
        assert_eq!(pqr(&b"  1  2  3"[..]),
                   IResult::Done(&b""[..], (Noun::Atom(1), Noun::Atom(2), Noun::Atom(3))));

        assert_eq!(wtcl(&b"?:(1 2 3)"[..]),
                   IResult::Done(&b""[..], n![6, 1, 2, 3]));
        assert_eq!(wtcl(&b"?:(1   2\n3)"[..]),
                   IResult::Done(&b""[..], n![6, 1, 2, 3]));
        assert_eq!(wtcl(&b"?:  1\n  2\n3"[..]),
                   IResult::Done(&b""[..], n![6, 1, 2, 3]));
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::os::raw::{
    c_int,
    c_void,
};

use c_ares_sys;
use c_types;

use error::AresError;
use hostent::{
    HasHostent,
    HostAddressResultsIter,
    HostAliasResultsIter,
    HostentBorrowed,
};
use utils::ares_error;

/// The result of a successful host lookup.
#[derive(Clone, Copy)]
pub struct HostResults<'a> {
    hostent: HostentBorrowed<'a>,
}

impl<'a> HostResults<'a> {
    fn new(hostent: &'a c_types::hostent) -> HostResults<'a> {
        HostResults {
            hostent: HostentBorrowed::new(hostent),
        }
    }

    /// Returns the hostname from this `HostResults`.
    pub fn hostname(&self) -> &str {
        self.hostent.hostname()
    }

    /// Returns an iterator over the `IpAddr` values in this `HostResults`.
    pub fn addresses(&self) -> HostAddressResultsIter {
        self.hostent.addresses()
    }

    /// Returns an iterator over the host aliases in this `HostResults`.
    pub fn aliases(&self) -> HostAliasResultsIter {
        self.hostent.aliases()
    }
}

impl<'a> fmt::Display for HostResults<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.hostent.display(fmt)
    }
}

pub unsafe extern "C" fn get_host_callback<F>(
    arg: *mut c_void,
    status: c_int,
    _timeouts: c_int,
    hostent: *mut c_ares_sys::hostent)
    where F: FnOnce(Result<HostResults, AresError>) + 'static {
    let result = if status == c_ares_sys::ARES_SUCCESS {
        let host_results = HostResults::new(&*(hostent as *const c_types::hostent));
        Ok(host_results)
    } else {
        Err(ares_error(status))
    };
    let handler = Box::from_raw(arg as *mut F);
    handler(result);
}
<commit_msg>Long line<commit_after>use std::fmt;
use std::os::raw::{
    c_int,
    c_void,
};

use c_ares_sys;
use c_types;

use error::AresError;
use hostent::{
    HasHostent,
    HostAddressResultsIter,
    HostAliasResultsIter,
    HostentBorrowed,
};
use utils::ares_error;

/// The result of a successful host lookup.
#[derive(Clone, Copy)]
pub struct HostResults<'a> {
    hostent: HostentBorrowed<'a>,
}

impl<'a> HostResults<'a> {
    fn new(hostent: &'a c_types::hostent) -> HostResults<'a> {
        HostResults {
            hostent: HostentBorrowed::new(hostent),
        }
    }

    /// Returns the hostname from this `HostResults`.
    pub fn hostname(&self) -> &str {
        self.hostent.hostname()
    }

    /// Returns an iterator over the `IpAddr` values in this `HostResults`.
    pub fn addresses(&self) -> HostAddressResultsIter {
        self.hostent.addresses()
    }

    /// Returns an iterator over the host aliases in this `HostResults`.
    pub fn aliases(&self) -> HostAliasResultsIter {
        self.hostent.aliases()
    }
}

impl<'a> fmt::Display for HostResults<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.hostent.display(fmt)
    }
}

pub unsafe extern "C" fn get_host_callback<F>(
    arg: *mut c_void,
    status: c_int,
    _timeouts: c_int,
    hostent: *mut c_ares_sys::hostent)
    where F: FnOnce(Result<HostResults, AresError>) + 'static {
    let result = if status == c_ares_sys::ARES_SUCCESS {
        let host_results = HostResults::new(
            &*(hostent as *const c_types::hostent));
        Ok(host_results)
    } else {
        Err(ares_error(status))
    };
    let handler = Box::from_raw(arg as *mut F);
    handler(result);
}
<|endoftext|>


<commit_before>//! This module initializes a project.

use std::fs;
use Error;

/// Creates a folder. The folder must not exist or must be empty.
///
/// Impure.
pub fn make_project_folder(root: &str) -> Result<(), Error> {
    // Make the folder - ignore error.
    let _ = fs::create_dir(root);

    // Check that the folder is empty
    fs::read_dir(root)
        .map_err(|err| Error::Io(err))
        .and_then(|iter| {
            let count = iter.count();
            if count == 0 {
                Ok(())
            } else {
                Err(Error::FolderNotEmpty(root, count))
            }
        })
}

/// Initializes a git repository at root.
///
/// Impure.
pub fn make_repository(root: &str) -> Result<(), Error> {
    Err(Error::TodoErr)
}<commit_msg>implemented make repostory<commit_after>//! This module initializes a project.

use std::fs;
use git2::Repository;
use Error;

/// Creates a folder. The folder must not exist or must be empty.
///
/// Impure.
pub fn make_project_folder(root: &str) -> Result<(), Error> {
    // Make the folder - ignore error.
    let _ = fs::create_dir(root);

    // Check that the folder is empty
    fs::read_dir(root)
        .map_err(|err| Error::Io(err))
        .and_then(|iter| {
            let count = iter.count();
            if count == 0 {
                Ok(())
            } else {
                Err(Error::FolderNotEmpty(root, count))
            }
        })
}

/// Initializes a git repository at root.
///
/// Impure.
pub fn make_repository(root: &str) -> Result<(), Error> {
    Repository::init(root)
        .map_err(|err| Error::Git(err))
        .map(|_| ())
}<|endoftext|>


<commit_before>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::io::net::ip::{SocketAddr, IpAddr};
use std::sync::Arc;

use http::server as http;
use super::{Request, Handler};
use super::status;

use super::response::HttpResponse;
use super::request::HttpRequest;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a Handler, which it uses to create responses for client
    /// requests.
    pub handler: H,
}

// The struct which actually listens and serves requests.
struct IronListener<H> {
    handler: Arc<H>,
    ip: IpAddr,
    port: u16
}

impl<H: Send + Sync> Clone for IronListener<H> {
    fn clone(&self) -> IronListener<H> {
        IronListener {
            // Just increment a reference count.
            handler: self.handler.clone(),
            ip: self.ip.clone(),
            port: self.port.clone()
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    pub fn listen(self, ip: IpAddr, port: u16) {
        use http::server::Server;

        spawn(proc() {
            IronListener {
                handler: Arc::new(self.handler),
                ip: ip,
                port: port
            }.serve_forever();
        });
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in Handler.
    pub fn around(handler: H) -> Iron<H> {
        Iron { handler: handler }
    }
}

impl<H: Handler> http::Server for IronListener<H> {
    fn get_config(&self) -> http::Config {
        http::Config {
            bind_address: SocketAddr {
                ip: self.ip,
                port: self.port
            }
        }
    }

    fn handle_request(&self, http_req: HttpRequest, http_res: &mut HttpResponse) {
        // Create wrapper Request
        let mut req = match Request::from_http(http_req) {
            Ok(req) => req,
            Err(e) => {
                error!("Error getting request: {}", e);
                http_res.status = status::InternalServerError;
                let _ = http_res.write(b"Internal Server Error");
                return;
            }
        };

        // Dispatch the request
        let res = self.handler.call(&mut req);

        match res {
            // Write the response back to http_res
            Ok(res) => res.write_back(http_res),
            Err(e) => {
                error!("Error handling {}: {}", req, e);
                http_res.status = status::InternalServerError;
                let _ = http_res.write(b"Internal Server Error");
            }
        }
    }
}
<commit_msg>(cleanup) Rename Iron::around to Iron::new to avoid confusion with AroundMiddleware.<commit_after>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::io::net::ip::{SocketAddr, IpAddr};
use std::sync::Arc;

use http::server as http;
use super::{Request, Handler};
use super::status;

use super::response::HttpResponse;
use super::request::HttpRequest;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a Handler, which it uses to create responses for client
    /// requests.
    pub handler: H,
}

// The struct which actually listens and serves requests.
struct IronListener<H> {
    handler: Arc<H>,
    ip: IpAddr,
    port: u16
}

impl<H: Send + Sync> Clone for IronListener<H> {
    fn clone(&self) -> IronListener<H> {
        IronListener {
            // Just increment a reference count.
            handler: self.handler.clone(),
            ip: self.ip.clone(),
            port: self.port.clone()
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    pub fn listen(self, ip: IpAddr, port: u16) {
        use http::server::Server;

        spawn(proc() {
            IronListener {
                handler: Arc::new(self.handler),
                ip: ip,
                port: port
            }.serve_forever();
        });
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in Handler.
    pub fn new(handler: H) -> Iron<H> {
        Iron { handler: handler }
    }
}

impl<H: Handler> http::Server for IronListener<H> {
    fn get_config(&self) -> http::Config {
        http::Config {
            bind_address: SocketAddr {
                ip: self.ip,
                port: self.port
            }
        }
    }

    fn handle_request(&self, http_req: HttpRequest, http_res: &mut HttpResponse) {
        // Create wrapper Request
        let mut req = match Request::from_http(http_req) {
            Ok(req) => req,
            Err(e) => {
                error!("Error getting request: {}", e);
                http_res.status = status::InternalServerError;
                let _ = http_res.write(b"Internal Server Error");
                return;
            }
        };

        // Dispatch the request
        let res = self.handler.call(&mut req);

        match res {
            // Write the response back to http_res
            Ok(res) => res.write_back(http_res),
            Err(e) => {
                error!("Error handling {}: {}", req, e);
                http_res.status = status::InternalServerError;
                let _ = http_res.write(b"Internal Server Error");
            }
        }
    }
}
<|endoftext|>


<commit_before>//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use filter::Filter;

pub struct FilteredIterator<T, F, I>(F, I)
    where F: Filter<T>,
          I: Iterator<Item = T>;

impl<T, F, I> Iterator for FilteredIterator<T, F, I>
    where F: Filter<T>,
          I: Iterator<Item = T>
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.1.next() {
            if self.0.filter(&next) {
                return Some(next);
            }
        }

        None
    }
}

pub trait FilterWith<T, F: Filter<T>> : Iterator<Item = T> + Sized {
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self>;
}

impl<I, T, F: Filter<T>> FilterWith<T, F> for I
    where I: Iterator<Item = T>
{
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self> {
        FilteredIterator(f, self)
    }
}

pub struct FilterOksIter<T, E, I, F>(I, F)
    where F: Filter<T>,
          I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterOksIter<T, E, I, F>
    where F: Filter<T>,
          I: Iterator<Item = Result<T, E>>
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.next() {
            match next {
                Err(e) => return Some(Err(e)),
                Ok(t)  => if self.1.filter(&t) {
                    return Some(Ok(t));
                }
            }
        }

        None
    }
}

pub trait FilterOks<T, E, I, F> : Iterator<Item = Result<T, E>>
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<T>
{
    fn filter_oks(self, F) -> FilterOksIter<T, E, I, F>;
}

impl<T, E, I, F> FilterOks<T, E, I, F> for I
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<T>
{
    fn filter_oks(self, f: F) -> FilterOksIter<T, E, I, F> {
        FilterOksIter(self, f)
    }
}

pub struct FilterErrIter<T, E, I, F>(I, F)
    where F: Filter<E>,
          I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterErrIter<T, E, I, F>
    where F: Filter<E>,
          I: Iterator<Item = Result<T, E>>
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.next() {
            match next {
                Ok(t) => return Some(Ok(t)),
                Err(e) => if self.1.filter(&e) {
                    return Some(Err(e));
                }
            }
        }

        None
    }
}

pub trait FilterErr<T, E, I, F> : Iterator<Item = Result<T, E>>
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<E>
{
    fn filter_errs(self, F) -> FilterErrIter<T, E, I, F>;
}

impl<T, E, I, F> FilterErr<T, E, I, F> for I
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<E>
{
    fn filter_errs(self, f: F) -> FilterErrIter<T, E, I, F> {
        FilterErrIter(self, f)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_filter_with() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let foo = Foo;

        let v : Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
            .into_iter()
            .filter_with(foo)
            .collect();

        assert_eq!(v, vec![6, 7, 8, 9]);
    }

    #[test]
    fn test_filter_oks() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let foo = Foo;

        let v : Vec<Result<u64, u64>> =
            vec![Ok(1), Err(2), Ok(3), Err(4), Ok(5), Err(6), Ok(7), Err(8), Ok(9), Err(0)]
            .into_iter()
            .filter_oks(foo)
            .collect();

        assert_eq!(v, vec![Err(2), Err(4), Err(6), Ok(7), Err(8), Ok(9), Err(0)]);
    }

    #[test]
    fn test_filter_errs() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let foo = Foo;

        let v : Vec<Result<u64, u64>> =
            vec![Ok(1), Err(2), Ok(3), Err(4), Ok(5), Err(6), Ok(7), Err(8), Ok(9), Err(0)]
            .into_iter()
            .filter_errs(foo)
            .collect();

        assert_eq!(v, vec![Ok(1), Ok(3), Ok(5), Err(6), Ok(7), Err(8), Ok(9)]);
    }
}

<commit_msg>Fix: Rename to not use blacklisted variable name<commit_after>//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use filter::Filter;

pub struct FilteredIterator<T, F, I>(F, I)
    where F: Filter<T>,
          I: Iterator<Item = T>;

impl<T, F, I> Iterator for FilteredIterator<T, F, I>
    where F: Filter<T>,
          I: Iterator<Item = T>
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.1.next() {
            if self.0.filter(&next) {
                return Some(next);
            }
        }

        None
    }
}

pub trait FilterWith<T, F: Filter<T>> : Iterator<Item = T> + Sized {
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self>;
}

impl<I, T, F: Filter<T>> FilterWith<T, F> for I
    where I: Iterator<Item = T>
{
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self> {
        FilteredIterator(f, self)
    }
}

pub struct FilterOksIter<T, E, I, F>(I, F)
    where F: Filter<T>,
          I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterOksIter<T, E, I, F>
    where F: Filter<T>,
          I: Iterator<Item = Result<T, E>>
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.next() {
            match next {
                Err(e) => return Some(Err(e)),
                Ok(t)  => if self.1.filter(&t) {
                    return Some(Ok(t));
                }
            }
        }

        None
    }
}

pub trait FilterOks<T, E, I, F> : Iterator<Item = Result<T, E>>
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<T>
{
    fn filter_oks(self, F) -> FilterOksIter<T, E, I, F>;
}

impl<T, E, I, F> FilterOks<T, E, I, F> for I
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<T>
{
    fn filter_oks(self, f: F) -> FilterOksIter<T, E, I, F> {
        FilterOksIter(self, f)
    }
}

pub struct FilterErrIter<T, E, I, F>(I, F)
    where F: Filter<E>,
          I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterErrIter<T, E, I, F>
    where F: Filter<E>,
          I: Iterator<Item = Result<T, E>>
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.next() {
            match next {
                Ok(t) => return Some(Ok(t)),
                Err(e) => if self.1.filter(&e) {
                    return Some(Err(e));
                }
            }
        }

        None
    }
}

pub trait FilterErr<T, E, I, F> : Iterator<Item = Result<T, E>>
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<E>
{
    fn filter_errs(self, F) -> FilterErrIter<T, E, I, F>;
}

impl<T, E, I, F> FilterErr<T, E, I, F> for I
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<E>
{
    fn filter_errs(self, f: F) -> FilterErrIter<T, E, I, F> {
        FilterErrIter(self, f)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_filter_with() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v : Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
            .into_iter()
            .filter_with(f)
            .collect();

        assert_eq!(v, vec![6, 7, 8, 9]);
    }

    #[test]
    fn test_filter_oks() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v : Vec<Result<u64, u64>> =
            vec![Ok(1), Err(2), Ok(3), Err(4), Ok(5), Err(6), Ok(7), Err(8), Ok(9), Err(0)]
            .into_iter()
            .filter_oks(f)
            .collect();

        assert_eq!(v, vec![Err(2), Err(4), Err(6), Ok(7), Err(8), Ok(9), Err(0)]);
    }

    #[test]
    fn test_filter_errs() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v : Vec<Result<u64, u64>> =
            vec![Ok(1), Err(2), Ok(3), Err(4), Ok(5), Err(6), Ok(7), Err(8), Ok(9), Err(0)]
            .into_iter()
            .filter_errs(f)
            .collect();

        assert_eq!(v, vec![Ok(1), Ok(3), Ok(5), Err(6), Ok(7), Err(8), Ok(9)]);
    }
}

<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Print fortune using fortune command<commit_after>use std::io::Write;
use std::process::Command;

const FORTUNE: &str = "fortune";

fn main() {
    println!("[FORTUNE COOKIE]");
    println!("{}", fortune());
}

/// Get a fortune cookie.
fn fortune() -> String {
    let output = Command::new(FORTUNE)
        .arg("-s")  // Short fortunes only
        .output()
        .expect("Failed to get fortune");

        String::from_utf8(output.stdout).expect("Failed to decode output")
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate itertools;

extern crate argparse;
extern crate ansi_term;
extern crate time;

mod space;
mod identity;
mod motion;
mod life;
mod mind;

use std::io;
use std::io::Write;
use std::process;

use argparse::{ArgumentParser, Store};
use time::*;

use space::{Locale, Pinfield};
use identity::{Team, JobDescription, Agent};
use motion::{PONY_MOVEMENT_TABLE, FIGUREHEAD_MOVEMENT_TABLE};
use life::{WorldState, Patch, Commit};
use mind::kickoff;

fn the_end() {
    println!("THE END");
    process::exit(0);
}

fn main() {
    // Does argparse not offer a way to Store an argument (not a
    // hardcoded value) into an Option? Contribution opportunity if so??
    //
    // For now, use 0 like None.
    let mut lookahead_depth: u8 = 0;

    {
        let mut parser = ArgumentParser::new();
        parser.set_description("Leafline: an oppositional strategy game engine");
        parser.refer(&mut lookahead_depth).add_option(
            &["--lookahead"], Store,
            "rank moves using AI minimax lookahead this deep."
        );
        parser.parse_args_or_exit();
    }

    let mut world = WorldState::new();
    let mut premonitions: Vec<Commit>;
    loop {
        match lookahead_depth {
            // XXX can we unify the scored and unscored logic? Useful
            // not only on general DRYness principles, but perhaps also
            // toward supporting human vs. computer playish things rather
            // than just advising every movement
            0 => {
                premonitions = world.lookahead();
                if premonitions.len() == 0 {
                    // XXX distinguish between stalemate and
                    // checkm^H^H^H^H^H^Hultimate endangerment
                    the_end();
                }
                world.display();
                println!("");
                for (index, premonition) in premonitions.iter().enumerate() {
                    println!("{:>2}. {}", index, premonition)
                }
            },
            _ => {
                let start_thinking = time::get_time();
                let forecasts = kickoff(world, lookahead_depth);
                let stop_thinking = time::get_time();
                let thinking_time = stop_thinking - start_thinking;
                world.display();
                println!(
                    "(scoring alternatives {} levels deep took {} ms)",
                    lookahead_depth, thinking_time.num_milliseconds()
                 );
                for (index,
                     &(premonition, score)) in forecasts.iter().enumerate() {
                    println!("{:>2}. {} (score {})", index, premonition, score);
                }
                premonitions = forecasts.iter().map(|t| t.0).collect::<Vec<_>>();
                if premonitions.len() == 0 {
                    the_end();
                }
            }

        }
        loop {
            print!("\nSelect a move>> ");
            io::stdout().flush().ok().expect("couldn't flush stdout");
            let mut input_buffer = String::new();
            io::stdin()
                .read_line(&mut input_buffer)
                .ok().expect("couldn't read input");
            let choice: usize = match input_buffer.trim().parse() {
                Ok(i) => i,
                Err(e) => {
                    println!("Error parsing choice: {:?}. Try again.", e);
                    continue;
                }
            };
            if choice < premonitions.len() {
                world = premonitions[choice].tree;
                break;
            } else {
                println!("{} isn't among the choices. Try again.",
                         choice);
            }
        }
    }
}
<commit_msg>core towards correspondence<commit_after>#[macro_use]
extern crate itertools;

extern crate argparse;
extern crate ansi_term;
extern crate time;

mod space;
mod identity;
mod motion;
mod life;
mod mind;

use std::io;
use std::io::Write;
use std::process;

use argparse::{ArgumentParser, Store};
use time::*;

use space::{Locale, Pinfield};
use identity::{Team, JobDescription, Agent};
use motion::{PONY_MOVEMENT_TABLE, FIGUREHEAD_MOVEMENT_TABLE};
use life::{WorldState, Patch, Commit};
use mind::kickoff;

fn forecast(world: WorldState, depth: u8) -> (Vec<(Commit, f32)>, Duration) {
    let start_thinking = time::get_time();
    let forecasts = kickoff(world, depth);
    let stop_thinking = time::get_time();
    let thinking_time = stop_thinking - start_thinking;
    (forecasts, thinking_time)
}

fn oppose(in_medias_res: WorldState, depth: u8) -> WorldState {
    let forecasts = kickoff(in_medias_res, depth);
    let (determination, _karma) = forecasts[0];
    determination.tree
}

fn correspond(reminder: String, depth: u8) -> String {
    let world = WorldState::reconstruct(reminder);
    let world_plus_tick = oppose(world, depth);
    world_plus_tick.preserve()
}

fn the_end() {
    println!("THE END");
    process::exit(0);
}

fn main() {
    // Does argparse not offer a way to Store an argument (not a
    // hardcoded value) into an Option? Contribution opportunity if so??
    //
    // For now, use 0 like None.
    let mut lookahead_depth: u8 = 0;
    let mut postcard: String = "".to_string();
    {
        let mut parser = ArgumentParser::new();
        parser.set_description("Leafline: an oppositional strategy game engine");
        parser.refer(&mut lookahead_depth).add_option(
            &["--lookahead"], Store,
            "rank moves using AI minimax lookahead this deep."
        );
        parser.refer(&mut postcard).add_option(
            &["--correspond"], Store,
            "just output the serialization of the AI's top move in response \
             to the given serialized world-state"
        );
        parser.parse_args_or_exit();
    }

    if !postcard.is_empty() {
        println!("{}", correspond(postcard, lookahead_depth));
        process::exit(0);
    }

    let mut world = WorldState::new();
    let mut premonitions: Vec<Commit>;
    loop {
        match lookahead_depth {
            // XXX can we unify the scored and unscored logic? Useful
            // not only on general DRYness principles, but perhaps also
            // toward supporting human vs. computer playish things rather
            // than just advising every movement
            0 => {
                premonitions = world.lookahead();
                if premonitions.len() == 0 {
                    // XXX distinguish between stalemate and
                    // checkm^H^H^H^H^H^Hultimate endangerment
                    the_end();
                }
                world.display();
                println!("");
                for (index, premonition) in premonitions.iter().enumerate() {
                    println!("{:>2}. {}", index, premonition)
                }
            },
            _ => {
                let (forecasts,
                     thinking_time) = forecast(world, lookahead_depth);
                world.display();
                println!(
                    "(scoring alternatives {} levels deep took {} ms)",
                    lookahead_depth, thinking_time.num_milliseconds()
                 );
                for (index,
                     &(premonition, score)) in forecasts.iter().enumerate() {
                    println!("{:>2}. {} (score {})", index, premonition, score);
                }
                premonitions = forecasts.iter().map(|t| t.0).collect::<Vec<_>>();
                if premonitions.len() == 0 {
                    the_end();
                }
            }

        }
        loop {
            print!("\nSelect a move>> ");
            io::stdout().flush().ok().expect("couldn't flush stdout");
            let mut input_buffer = String::new();
            io::stdin()
                .read_line(&mut input_buffer)
                .ok().expect("couldn't read input");
            let choice: usize = match input_buffer.trim().parse() {
                Ok(i) => i,
                Err(e) => {
                    println!("Error parsing choice: {:?}. Try again.", e);
                    continue;
                }
            };
            if choice < premonitions.len() {
                world = premonitions[choice].tree;
                break;
            } else {
                println!("{} isn't among the choices. Try again.",
                         choice);
            }
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serenity;
extern crate rand;
extern crate typemap;

use typemap::Key;

use serenity::client::Client;
use serenity::model;
use serenity::utils;
use std::env;

use rand::Rng;
use rand::thread_rng;

const PREFIX: &str = "f>";

command!(info(_ctx, msg, _args) {
    msg.channel_id.send_message(|cm| {
        cm.embed(|e| {
            e.title("lfalchbot")
             .colour(utils::Colour::blue())
             .description("(c) LFalch.com 2017")
             .footer(|f| f.text(serenity::constants::USER_AGENT))
        })
    }).unwrap();
});

command!(setgame(ctx, _msg, args) {
    ctx.set_game(model::Game::playing(&args.join(" ")));
});

const CSGO_MSGS: [&str; 4] = [
    "Vi varmer op med en comp!",
    "Jeg er på!",
    "Jeg er mere til Call of Duty ..",
    "Mongoskrald!"
];

const BEARTOOTH: [&str; 3] = [
    "I’m not useless! I’m just the king of excuses!",
    "One life and one decision! Make sure it ends with you still living!",
    "Lorte skat på T-shirts."
];

const RESPONSES: [&str; 4] = [
    "Undskyld, kan ikke snakke lige nu :(",
    "Hey, kan jeg ringe igen senere?",
    "Hva' så din noob!? :P",
    "Ad, hvem er du?"
];

struct BotUser;

impl Key for BotUser {
    type Value = String;
}

fn main() {
    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::new(&token);

    client.with_framework(|f| f
        .configure(|c| c.prefix(PREFIX))
        .command("ping", |c| c.exec_str("Pong!"))
        .on("info", info)
        .on("setgame", setgame)
    );

    {
        let mut data = client.data.lock().unwrap();
        data.insert::<BotUser>(String::default());
    }

    client.on_ready(|ctx, ready| {
        println!("{} is connected!", ready.user.name);
        println!("Guilds:");
        for name in ready.guilds.iter().map(|g| g.id().get().unwrap().name) {
            println!("    {}", name);
        }
        {
            let mut data = ctx.data.lock().unwrap();
            *data.get_mut::<BotUser>().unwrap() = ready.user.tag();
        }
    });

    client.on_message(|ctx, msg| {
        if msg.author.bot {
            return
        }
        let s: String = msg.content.chars()
            .filter(|c| c.is_alphabetic())
            .flat_map(|c|c.to_lowercase())
            .collect();

        if s.contains("csgo") {
            let i = thread_rng().gen_range(0, CSGO_MSGS.len());
            msg.channel_id.say(CSGO_MSGS[i]).unwrap();
        }
        if s.contains("mc") {
            msg.channel_id.say("MINECRAFT!").unwrap();
        }
        if s.contains("beartooth") {
            let i = thread_rng().gen_range(0, BEARTOOTH.len());
            msg.channel_id.say(BEARTOOTH[i]).unwrap();
        }
        if s.contains("rep") {
            msg.channel_id.say("Rep mig!").unwrap();
        }
        if s.contains("meme") {
            msg.channel_id.say("krydrede migmig'er").unwrap();
        }
        if s.contains("rusland") || s.contains("russia") || s.contains("росси") ||
            s.contains("russisk") || s.contains("russian") || s.contains("русск") {
            msg.channel_id.say("Communism is the ultimate goal of socialism!").unwrap();
        }
        let user = {
            ctx.data.lock().unwrap().get::<BotUser>().unwrap().clone()
        };
        if msg.mentions.iter().map(|u| u.tag()).any(|u| u == user) {
            let i = thread_rng().gen_range(0, RESPONSES.len());
            msg.channel_id.say(RESPONSES[i]).unwrap();
        }
    });

    if let Err(why) = client.start() {
        println!("Client error: {:?}", why);
    }
}
<commit_msg>Add more and restructure jokes<commit_after>#[macro_use]
extern crate serenity;
extern crate rand;
extern crate typemap;

use typemap::Key;

use serenity::Result;
use serenity::client::{Client, Context};
use serenity::model;
use serenity::utils;
use std::env;

use rand::Rng;
use rand::thread_rng;

const PREFIX: &str = "f>";

command!(info(_ctx, msg, _args) {
    msg.channel_id.send_message(|cm| {
        cm.embed(|e| {
            e.title("lfalchbot")
             .colour(utils::Colour::blue())
             .description("(c) LFalch.com 2017")
             .footer(|f| f.text(serenity::constants::USER_AGENT))
        })
    }).unwrap();
});

command!(setgame(ctx, _msg, args) {
    ctx.set_game(model::Game::playing(&args.join(" ")));
});

const CSGO_MSGS: [&str; 5] = [
    "Vi varmer op med en comp!",
    "Jeg er på!",
    "Jeg er mere til Call of Duty ..",
    "Сука блядь!",
    "Mongoskrald!"
];

const BEARTOOTH: [&str; 3] = [
    "I’m not useless! I’m just the king of excuses!",
    "One life and one decision! Make sure it ends with you still living!",
    "Lorteskat på T-shirts."
];

const RESPONSES: [&str; 4] = [
    "Undskyld, kan ikke snakke lige nu :(",
    "Hey, kan jeg ringe igen senere?",
    "Hva' så din noob!? :P",
    "Ad, hvem er du?"
];

const REDALERT: [&str; 4] = [
    "Your base is under a salt!",
    "Det gamle lortespil?",
    "Jeg er mere til CSGO.",
    "\"Mine depleted\" ..."
];

struct BotUser;

impl Key for BotUser {
    type Value = String;
}

fn main() {
    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::new(&token);

    client.with_framework(|f| f
        .configure(|c| c.prefix(PREFIX))
        .command("ping", |c| c.exec_str("Pong!"))
        .on("info", info)
        .on("setgame", setgame)
    );

    {
        let mut data = client.data.lock().unwrap();
        data.insert::<BotUser>(String::default());
    }

    client.on_ready(|ctx, ready| {
        println!("{} is connected!", ready.user.name);
        println!("Guilds:");
        for name in ready.guilds.iter().map(|g| g.id().get().unwrap().name) {
            println!("    {}", name);
        }
        {
            let mut data = ctx.data.lock().unwrap();
            *data.get_mut::<BotUser>().unwrap() = ready.user.tag();
        }
    });

    client.on_message(on_message);

    if let Err(why) = client.start() {
        println!("Client error: {:?}", why);
    }
}

fn send_random(chl: model::ChannelId, list: &[&str]) -> Result<model::Message> {
    let i = thread_rng().gen_range(0, list.len());
    chl.say(list[i])
}

fn on_message(ctx: Context, msg: model::Message) {
    if msg.author.bot {
        return
    }
    let s: String = msg.content.chars()
        .filter(|c| c.is_alphanumeric())
        .flat_map(|c|c.to_lowercase())
        .collect();

    if s.contains("css") || s.contains("source") {
        msg.channel_id.say("Hvor er mine skins!?").unwrap();
    }
    if s.contains("csgo") || s.contains("counterstrike") || s.contains("globaloffensive") {
        send_random(msg.channel_id, &CSGO_MSGS).unwrap();
    }
    if s.contains("mc") || s.contains("minecraft") {
        msg.channel_id.say("MINECRAFT!").unwrap();
    }
    if s.contains("beartooth") {
        send_random(msg.channel_id, &BEARTOOTH).unwrap();
    }
    if s.contains("rep") {
        msg.channel_id.say("Rep mig!").unwrap();
    }
    if s.contains("ftl") {
        msg.channel_id.say("Zoltan shield OP").unwrap();
    }
    if s.contains("bindingofisaac") {
        msg.channel_id.say("Mom OP").unwrap();
    }
    if s.contains("meme") {
        msg.channel_id.say("krydrede migmig'er").unwrap();
    }
    if s.contains("gunsoficarus") {
        msg.channel_id.say("Spillere online: 85").unwrap();
    }
    if s.contains("doom") {
        msg.channel_id.say("Rip and tear!").unwrap();
    }
    if s.contains("dyinglight") {
        msg.channel_id.say("Left 4 Dead?").unwrap();
    }
    if s.contains("english") {
        msg.channel_id.send_message(|cm| {
            cm.embed(|e| {
                e.image("http://dev.lfalch.com/english.jpg")
            })
        }).unwrap();
    }
    if s.contains("ra3") || s.contains("redalert") {
        send_random(msg.channel_id, &REDALERT).unwrap();
    }
    if s.contains("rusland") || s.contains("russia") || s.contains("росси") ||
        s.contains("russisk") || s.contains("russian") || s.contains("русск") {
        msg.channel_id.say("Communism is the ultimate goal of socialism.").unwrap();
    }
    let user = {
        ctx.data.lock().unwrap().get::<BotUser>().unwrap().clone()
    };
    if msg.mentions.iter().map(|u| u.tag()).any(|u| u == user) {
        send_random(msg.channel_id, &RESPONSES).unwrap();
    }
}
<|endoftext|>