<commit_before>use core::cmp::{Eq, Ord};
use core::f64::consts::pi;
use funs::triganomic::{cos, sin};
use mat::{Mat3, Mat4};
use num::cast::{NumCast, cast};
use quat::Quat;
use vec::Vec3;

/**
 * The base trait for anglular units
 */
pub trait Angle<T>: Add<self,self>
                  , Sub<self,self>
                  , Mul<T,self>
                  , Div<T,self>
                  , Modulo<T,self>
                  , Neg<self>
                  , Eq, Ord {
    static pure fn full_rotation() -> self;
    static pure fn half_rotation() -> self;
    static pure fn quarter_rotation() -> self;
    static pure fn eighth_rotation() -> self;

    pure fn to_radians() -> Radians<T>;
    pure fn to_degrees() -> Degrees<T>;
}

pub enum Radians<T> = T;

pub impl<T:Copy Num NumCast> Radians<T>: Angle<T> {
    #[inline(always)] static pure fn full_rotation()    -> Radians<T> { Radians(move cast(2.0 * pi)) }
    #[inline(always)] static pure fn half_rotation()    -> Radians<T> { Radians(move cast(pi))       }
    #[inline(always)] static pure fn quarter_rotation() -> Radians<T> { Radians(move cast(pi / 2.0)) }
    #[inline(always)] static pure fn eighth_rotation()  -> Radians<T> { Radians(move cast(pi / 4.0)) }

    #[inline(always)] pure fn to_radians() -> Radians<T> { self }
    #[inline(always)] pure fn to_degrees() -> Degrees<T> { Degrees(*self * cast(180.0 / pi)) }

}

pub impl<T:Copy Num> Radians<T>: Add<Radians<T>, Radians<T>> {
    #[inline(always)] pure fn add(rhs: &Radians<T>) -> Radians<T> { Radians(*self + **rhs) }
}

pub impl<T:Copy Num> Radians<T>: Sub<Radians<T>, Radians<T>> {
    #[inline(always)] pure fn sub(rhs: &Radians<T>) -> Radians<T> { Radians(*self - **rhs) }
}

pub impl<T:Copy Num> Radians<T>: Mul<T, Radians<T>> {
    #[inline(always)] pure fn mul(rhs: &T) -> Radians<T> { Radians(*self * *rhs) }
}

pub impl<T:Copy Num> Radians<T>: Div<T, Radians<T>> {
    #[inline(always)] pure fn div(rhs: &T) -> Radians<T> { Radians(*self / *rhs) }
}

pub impl<T:Copy Num> Radians<T>: Modulo<T, Radians<T>> {
    #[inline(always)] pure fn modulo(rhs: &T) -> Radians<T> { Radians(*self % *rhs) }
}

pub impl<T:Copy Num> Radians<T>: Neg<Radians<T>> {
    #[inline(always)] pure fn neg() -> Radians<T> { Radians(-*self) }
}

pub impl<T:Copy Eq> Radians<T>: Eq {
    #[inline(always)] pure fn eq(other: &Radians<T>) -> bool { *self == **other }
    #[inline(always)] pure fn ne(other: &Radians<T>) -> bool { *self != **other }
}

pub impl<T:Copy Ord> Radians<T>: Ord {
    #[inline(always)] pure fn lt(other: &Radians<T>) -> bool { *self <  **other }
    #[inline(always)] pure fn le(other: &Radians<T>) -> bool { *self <= **other }
    #[inline(always)] pure fn ge(other: &Radians<T>) -> bool { *self >= **other }
    #[inline(always)] pure fn gt(other: &Radians<T>) -> bool { *self >  **other }
}

pub enum Degrees<T> = T;

pub impl<T:Copy Num NumCast> Degrees<T>: Angle<T> {
    #[inline(always)] static pure fn full_rotation()    -> Degrees<T> { Degrees(move cast(360.0)) }
    #[inline(always)] static pure fn half_rotation()    -> Degrees<T> { Degrees(move cast(180.0)) }
    #[inline(always)] static pure fn quarter_rotation() -> Degrees<T> { Degrees(move cast(90.0))  }
    #[inline(always)] static pure fn eighth_rotation()  -> Degrees<T> { Degrees(move cast(45.0))  }

    #[inline(always)] pure fn to_radians() -> Radians<T> { Radians(*self * cast(pi / 180.0)) }
    #[inline(always)] pure fn to_degrees() -> Degrees<T> { self }

}

pub impl<T:Copy Num> Degrees<T>: Add<Degrees<T>, Degrees<T>> {
    #[inline(always)] pure fn add(rhs: &Degrees<T>) -> Degrees<T> { Degrees(*self + **rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Sub<Degrees<T>, Degrees<T>> {
    #[inline(always)] pure fn sub(rhs: &Degrees<T>) -> Degrees<T> { Degrees(*self - **rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Mul<T, Degrees<T>> {
    #[inline(always)] pure fn mul(rhs: &T) -> Degrees<T> { Degrees(*self * *rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Div<T, Degrees<T>> {
    #[inline(always)] pure fn div(rhs: &T) -> Degrees<T> { Degrees(*self / *rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Modulo<T, Degrees<T>> {
    #[inline(always)] pure fn modulo(rhs: &T) -> Degrees<T> { Degrees(*self % *rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Neg<Degrees<T>> {
    #[inline(always)] pure fn neg() -> Degrees<T> { Degrees(-*self) }
}

pub impl<T:Copy Eq> Degrees<T>: Eq {
    #[inline(always)] pure fn eq(other: &Degrees<T>) -> bool { *self == **other }
    #[inline(always)] pure fn ne(other: &Degrees<T>) -> bool { *self != **other }
}

pub impl<T:Copy Ord> Degrees<T>: Ord {
    #[inline(always)] pure fn lt(other: &Degrees<T>) -> bool { *self <  **other }
    #[inline(always)] pure fn le(other: &Degrees<T>) -> bool { *self <= **other }
    #[inline(always)] pure fn ge(other: &Degrees<T>) -> bool { *self >= **other }
    #[inline(always)] pure fn gt(other: &Degrees<T>) -> bool { *self >  **other }
}

/**
 * An angular rotation around an arbitary axis
 */
pub struct Rotation<T> {
    theta: Radians<T>,
    axis: Vec3<T>,
}

pub impl<T:Copy Num NumCast> Rotation<T> {
    #[inline(always)]
    static pure fn new(theta: Radians<T>, axis: Vec3<T>) -> Rotation<T> {
        Rotation { theta: move theta, axis: move axis }
    }

    #[inline(always)]
    pure fn to_mat3() -> Mat3<T> {
        let c:  T = cos(&self.theta);
        let s:  T = sin(&self.theta);
        let _0: T = cast(0);
        let _1: T = cast(1);
        let t:  T = _1 - c;

        let x = self.axis.x;
        let y = self.axis.y;
        let z = self.axis.z;

        Mat3::new(t * x * x + c,       t * x * y + s * z,   t * x * z - s * y,
                  t * x * y - s * z,   t * y * y + c,       t * y * z + s * x,
                  t * x * z - s - y,   t * y * z - s * x,   t * z * z + c)
    }

    #[inline(always)]
    pure fn to_mat4() -> Mat4<T> {
        self.to_mat3().to_mat4()
    }

    #[inline(always)]
    pure fn to_quat() -> Quat<T> {
        let half = self.theta / cast(2);
        Quat::from_sv(cos(&half), self.axis.mul_t(sin(&half)))
    }
}

pub struct Euler<T> {
    x: Radians<T>,   // pitch
    y: Radians<T>,   // yaw
    z: Radians<T>,   // roll
}<commit_msg>Add skeleton wrap method<commit_after>use core::cmp::{Eq, Ord};
use core::f64::consts::pi;
use funs::triganomic::{cos, sin};
use mat::{Mat3, Mat4};
use num::cast::{NumCast, cast};
use quat::Quat;
use vec::Vec3;

/**
 * The base trait for anglular units
 */
pub trait Angle<T>: Add<self,self>
                  , Sub<self,self>
                  , Mul<T,self>
                  , Div<T,self>
                  , Modulo<T,self>
                  , Neg<self>
                  , Eq, Ord {
    static pure fn full_rotation() -> self;
    static pure fn half_rotation() -> self;
    static pure fn quarter_rotation() -> self;
    static pure fn eighth_rotation() -> self;

    pure fn to_radians() -> Radians<T>;
    pure fn to_degrees() -> Degrees<T>;
    pure fn wrap() -> self;
}

pub enum Radians<T> = T;

pub impl<T:Copy Num NumCast> Radians<T>: Angle<T> {
    #[inline(always)] static pure fn full_rotation()    -> Radians<T> { Radians(move cast(2.0 * pi)) }
    #[inline(always)] static pure fn half_rotation()    -> Radians<T> { Radians(move cast(pi))       }
    #[inline(always)] static pure fn quarter_rotation() -> Radians<T> { Radians(move cast(pi / 2.0)) }
    #[inline(always)] static pure fn eighth_rotation()  -> Radians<T> { Radians(move cast(pi / 4.0)) }

    #[inline(always)] pure fn to_radians() -> Radians<T> { self }
    #[inline(always)] pure fn to_degrees() -> Degrees<T> { Degrees(*self * cast(180.0 / pi)) }

    #[inline(always)] pure fn wrap() -> Radians<T> { fail(~"Radians.wrap() not yet implemented") }
}

pub impl<T:Copy Num> Radians<T>: Add<Radians<T>, Radians<T>> {
    #[inline(always)] pure fn add(rhs: &Radians<T>) -> Radians<T> { Radians(*self + **rhs) }
}

pub impl<T:Copy Num> Radians<T>: Sub<Radians<T>, Radians<T>> {
    #[inline(always)] pure fn sub(rhs: &Radians<T>) -> Radians<T> { Radians(*self - **rhs) }
}

pub impl<T:Copy Num> Radians<T>: Mul<T, Radians<T>> {
    #[inline(always)] pure fn mul(rhs: &T) -> Radians<T> { Radians(*self * *rhs) }
}

pub impl<T:Copy Num> Radians<T>: Div<T, Radians<T>> {
    #[inline(always)] pure fn div(rhs: &T) -> Radians<T> { Radians(*self / *rhs) }
}

pub impl<T:Copy Num> Radians<T>: Modulo<T, Radians<T>> {
    #[inline(always)] pure fn modulo(rhs: &T) -> Radians<T> { Radians(*self % *rhs) }
}

pub impl<T:Copy Num> Radians<T>: Neg<Radians<T>> {
    #[inline(always)] pure fn neg() -> Radians<T> { Radians(-*self) }
}

pub impl<T:Copy Eq> Radians<T>: Eq {
    #[inline(always)] pure fn eq(other: &Radians<T>) -> bool { *self == **other }
    #[inline(always)] pure fn ne(other: &Radians<T>) -> bool { *self != **other }
}

pub impl<T:Copy Ord> Radians<T>: Ord {
    #[inline(always)] pure fn lt(other: &Radians<T>) -> bool { *self <  **other }
    #[inline(always)] pure fn le(other: &Radians<T>) -> bool { *self <= **other }
    #[inline(always)] pure fn ge(other: &Radians<T>) -> bool { *self >= **other }
    #[inline(always)] pure fn gt(other: &Radians<T>) -> bool { *self >  **other }
}

pub enum Degrees<T> = T;

pub impl<T:Copy Num NumCast> Degrees<T>: Angle<T> {
    #[inline(always)] static pure fn full_rotation()    -> Degrees<T> { Degrees(move cast(360.0)) }
    #[inline(always)] static pure fn half_rotation()    -> Degrees<T> { Degrees(move cast(180.0)) }
    #[inline(always)] static pure fn quarter_rotation() -> Degrees<T> { Degrees(move cast(90.0))  }
    #[inline(always)] static pure fn eighth_rotation()  -> Degrees<T> { Degrees(move cast(45.0))  }

    #[inline(always)] pure fn to_radians() -> Radians<T> { Radians(*self * cast(pi / 180.0)) }
    #[inline(always)] pure fn to_degrees() -> Degrees<T> { self }

    #[inline(always)] pure fn wrap() -> Degrees<T> { fail(~"Degrees.wrap() not yet implemented") }
}

pub impl<T:Copy Num> Degrees<T>: Add<Degrees<T>, Degrees<T>> {
    #[inline(always)] pure fn add(rhs: &Degrees<T>) -> Degrees<T> { Degrees(*self + **rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Sub<Degrees<T>, Degrees<T>> {
    #[inline(always)] pure fn sub(rhs: &Degrees<T>) -> Degrees<T> { Degrees(*self - **rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Mul<T, Degrees<T>> {
    #[inline(always)] pure fn mul(rhs: &T) -> Degrees<T> { Degrees(*self * *rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Div<T, Degrees<T>> {
    #[inline(always)] pure fn div(rhs: &T) -> Degrees<T> { Degrees(*self / *rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Modulo<T, Degrees<T>> {
    #[inline(always)] pure fn modulo(rhs: &T) -> Degrees<T> { Degrees(*self % *rhs) }
}

pub impl<T:Copy Num> Degrees<T>: Neg<Degrees<T>> {
    #[inline(always)] pure fn neg() -> Degrees<T> { Degrees(-*self) }
}

pub impl<T:Copy Eq> Degrees<T>: Eq {
    #[inline(always)] pure fn eq(other: &Degrees<T>) -> bool { *self == **other }
    #[inline(always)] pure fn ne(other: &Degrees<T>) -> bool { *self != **other }
}

pub impl<T:Copy Ord> Degrees<T>: Ord {
    #[inline(always)] pure fn lt(other: &Degrees<T>) -> bool { *self <  **other }
    #[inline(always)] pure fn le(other: &Degrees<T>) -> bool { *self <= **other }
    #[inline(always)] pure fn ge(other: &Degrees<T>) -> bool { *self >= **other }
    #[inline(always)] pure fn gt(other: &Degrees<T>) -> bool { *self >  **other }
}

/**
 * An angular rotation around an arbitary axis
 */
pub struct Rotation<T> {
    theta: Radians<T>,
    axis: Vec3<T>,
}

pub impl<T:Copy Num NumCast> Rotation<T> {
    #[inline(always)]
    static pure fn new(theta: Radians<T>, axis: Vec3<T>) -> Rotation<T> {
        Rotation { theta: move theta, axis: move axis }
    }

    #[inline(always)]
    pure fn to_mat3() -> Mat3<T> {
        let c:  T = cos(&self.theta);
        let s:  T = sin(&self.theta);
        let _0: T = cast(0);
        let _1: T = cast(1);
        let t:  T = _1 - c;

        let x = self.axis.x;
        let y = self.axis.y;
        let z = self.axis.z;

        Mat3::new(t * x * x + c,       t * x * y + s * z,   t * x * z - s * y,
                  t * x * y - s * z,   t * y * y + c,       t * y * z + s * x,
                  t * x * z - s - y,   t * y * z - s * x,   t * z * z + c)
    }

    #[inline(always)]
    pure fn to_mat4() -> Mat4<T> {
        self.to_mat3().to_mat4()
    }

    #[inline(always)]
    pure fn to_quat() -> Quat<T> {
        let half = self.theta / cast(2);
        Quat::from_sv(cos(&half), self.axis.mul_t(sin(&half)))
    }
}

pub struct Euler<T> {
    x: Radians<T>,   // pitch
    y: Radians<T>,   // yaw
    z: Radians<T>,   // roll
}<|endoftext|>


<commit_before>//The sum of the squares of the first ten natural numbers is,
//
//1^2 + 2^2 + ... + 10^2 = 385
//
//The square of the sum of the first ten natural numbers is,
//
//(1 + 2 + ... + 10)^2 = 55^2 = 3025
//
//Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.
//
//Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

fn solve(setbound: u64) -> u64 {
    let mut sumofsquares = 0;
    let mut squareofsum = 0;
    if setbound == 0 {
        panic!();
    }
    for i in 1..(setbound + 1) {
        sumofsquares += i * i;
        squareofsum += i;
    }
    (squareofsum * squareofsum) - sumofsquares
}

fn main() {
    println!("{}", solve(100).to_string());
}

#[cfg(test)]
mod tests {
    #[test]
    #[should_panic]
    fn sum_square_diff_badbound() {
        super::solve(0);
    }
    #[test]
    fn sum_square_diff_10() {
        assert_eq!(2640, super::solve(10));
    }
    #[test]
    fn sum_square_diff_100() {
        assert_eq!(25164150, super::solve(100));
    }
}
<commit_msg>test commit for new ide<commit_after>//The sum of the squares of the first ten natural numbers is,
//
//1^2 + 2^2 + ... + 10^2 = 385
//
//The square of the sum of the first ten natural numbers is,
//
//(1 + 2 + ... + 10)^2 = 55^2 = 3025
//
//Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.
//
//Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

//test commit

fn solve(setbound: u64) -> u64 {
    let mut sumofsquares = 0;
    let mut squareofsum = 0;
    if setbound == 0 {
        panic!();
    }
    for i in 1..(setbound + 1) {
        sumofsquares += i * i;
        squareofsum += i;
    }
    (squareofsum * squareofsum) - sumofsquares
}

fn main() {
    println!("{}", solve(100).to_string());
}

#[cfg(test)]
mod tests {
    #[test]
    #[should_panic]
    fn sum_square_diff_badbound() {
        super::solve(0);
    }
    #[test]
    fn sum_square_diff_10() {
        assert_eq!(2640, super::solve(10));
    }
    #[test]
    fn sum_square_diff_100() {
        assert_eq!(25164150, super::solve(100));
    }
}
<|endoftext|>


<commit_before>use piston::input::*;

use rand::Rng;

use super::BOARD_WIDTH;
use super::BOARD_HEIGHT;
use super::block::Shape;
use super::block::Tetromino;
use super::block::TETROMINOS;

// 1st entry is # of points for clearing 1 line, etc.
const SCORES_PER_LINE: [u64; 4] = [80, 200, 600, 2400];

const GHOST_PIECE_OPACITY: f32 = 0.35;

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum GameState {
  Playing,
  Paused,
  Over // donezo. player lost or quit
}

pub struct Board {
  pub cells: [[u8; BOARD_WIDTH as usize]; BOARD_HEIGHT as usize],
  pub current_piece: Tetromino, // current active Tetromino
  pub ghost_piece: Tetromino, // ghost piece to display at bottom
  pub state: GameState,
  pub score: u64,

  pub token: i32, // token identifier for use by the game server
  pub new_block: bool, // true for 1 iteration if new block, false otherwise

  // line_counts[i] = # of filled blocks in row i
  line_counts: [i64; BOARD_HEIGHT as usize],
  // for "random bag" generation of the next tetromino
  tetrominos_bag: Vec<Tetromino>,
}

impl Board {
  pub fn init_board() -> Board {
    let mut bag = TETROMINOS.to_vec();
    ::rand::thread_rng().shuffle(&mut bag);

    let first_piece: Tetromino = bag.remove(0);
    let mut ghost_piece: Tetromino = first_piece.clone();
    ghost_piece.y_offset = BOARD_HEIGHT as f64 - ghost_piece.block_height();
    // some shapes are drawn starting from 2nd, not 1st row in block
    if ghost_piece.name == Shape::T || ghost_piece.name == Shape::S || ghost_piece.name == Shape::Z {
      ghost_piece.y_offset -= 1.0;
    }
    ghost_piece.color[3] = GHOST_PIECE_OPACITY; // transparent

    Board {
      cells: [[0; BOARD_WIDTH as usize]; BOARD_HEIGHT as usize],
      current_piece: first_piece,
      ghost_piece: ghost_piece,
      state: GameState::Playing,
      score: 0,

      token: 0,
      new_block: true,

      line_counts: [0; BOARD_HEIGHT as usize],
      tetrominos_bag: bag
    }
  }

  pub fn handle_key_press(&mut self, inp: &Input) {
    match *inp {
      Input::Press(but) => {
        match but {
          Button::Keyboard(Key::Up) => {
            self.current_piece.rotate_right();
            self.ghost_piece.rotate_right();
            // undo rotation if it was invalid...lol
            if self.current_piece_out_of_bounds() {
              self.current_piece.rotate_left();
              self.ghost_piece.rotate_left();
            }
            self.update_ghost_piece();
          }
          Button::Keyboard(Key::Left) => {
            if self.can_move_current_piece_left() {
              self.current_piece.move_left();
              self.update_ghost_piece();
            }
          }
          Button::Keyboard(Key::Right) => {
            if self.can_move_current_piece_right() {
              self.current_piece.move_right();
              self.update_ghost_piece();
            }
          }
          Button::Keyboard(Key::Down) => {
            if self.can_move_piece_down(&self.current_piece) {
              self.current_piece.move_down();
            }
          }
          Button::Keyboard(Key::Space) => {
            // pressing spacebar drops piece to bottom
            while self.can_move_piece_down(&self.current_piece) {
              self.current_piece.move_down();
            }
          }
          // TODO: these options disabled for multiplayer

          // P = pause button
          // Button::Keyboard(Key::P) => {
          //     if self.state == GameState::Playing {
          //         self.state = GameState::Paused;
          //     } else if self.state == GameState::Paused {
          //         self.state = GameState::Playing;
          //     }
          // }

          // R = restart button
          // Button::Keyboard(Key::R) => {
          //     // reset all game variables
          //     let mut bag = TETROMINOS.to_vec();
          //     ::rand::thread_rng().shuffle(&mut bag);

          //     self.cells = [[0; BOARD_WIDTH as usize]; BOARD_HEIGHT as usize];
          //     self.current_piece = bag.remove(0);
          //     self.state = GameState::Playing;
          //     self.line_counts = [0; BOARD_HEIGHT as usize];
          //     self.tetrominos_bag = bag;
          //     self.score = 0;
          //     println!("===== GAME RESTARTED =====");
          // }
          _ => {}
        }
      }
      _ => {}
    }
  }

  // iterate thru board and clear the specified row
  fn clear_row(&mut self, row: usize) {
    for col in 0..BOARD_WIDTH {
      self.cells[row][col as usize] = 0;
    }
    self.line_counts[row] = 0;

    // move all cells above (and including) the cleared row down by one
    for r in (1..(row+1)).rev() {
      for col in 0..BOARD_WIDTH {
        self.cells[r as usize][col as usize] = self.cells[(r-1) as usize][col as usize];
      }
      self.line_counts[r as usize] = self.line_counts[(r-1) as usize];
    }
  }

  pub fn clear_line_if_needed(&mut self) {
    // iterate through rows affected by current piece
    let mut rows_affected = Vec::new();
    let current_y = self.current_piece.y_offset;

    for r in 0..self.current_piece.blocks.len() {
      for c in 0..self.current_piece.blocks[0].len() {
        if self.current_piece.blocks[r][c] == 1 {
          let board_y: usize = ((r as f64) + current_y) as usize;
          rows_affected.push(board_y);
        }
      }
    }

    let mut rows_cleared = 0;
    for row in rows_affected.iter() {
      if self.line_counts[*row] == BOARD_WIDTH {
        self.clear_row(*row);
        rows_cleared += 1;
      }
    }
    if rows_cleared > 0 {
      self.score += SCORES_PER_LINE[rows_cleared - 1];
    }
  }

  pub fn advance_board(&mut self) {
    // println!("=== SCORE: {:?} ===", self.score);

    if self.state != GameState::Playing {
      return
    }
    // check if game is over or not
    // check top row of board and see if any of them are filled?
    for col in 0..self.cells[0].len() {
      if self.cells[0][col] == 1{
        self.state = GameState::Over;
        return
      }
    }

    // make the existing piece fall
    if self.can_move_piece_down(&self.current_piece) {
      self.new_block = false;
      self.current_piece.move_down();
    } else {
      // add piece to board cells
      self.set_piece_on_board();

      // clear line if necessary
      self.clear_line_if_needed();

      // get new piece
      self.current_piece = self.get_next_piece();
      self.new_block = true;
      self.update_ghost_piece();
    }
  }

  fn can_move_piece_down(&self, piece: &Tetromino) -> bool {
    if piece.bottommost() + 1.0 >= BOARD_HEIGHT as f64 {
      return false
    }
    // check if piece will intersect with a piece already on the board
    let current_x = piece.x_offset;
    let current_y = piece.y_offset;
    for row in 0..piece.blocks.len() {
      for col in 0..piece.blocks[0].len() {
        if piece.blocks[row][col] == 1 {
          let board_x: i64 = (col as i64) + (current_x as i64);
          let board_y: i64 = (row as i64) + (current_y as i64) + 1;
          if self.cells[board_y as usize][board_x as usize] == 1 {
            return false;
          }
        }
      }
    }
    true
  }

  fn can_move_current_piece_left(&self) -> bool {
    if self.current_piece.leftmost() - 1.0 < 0.0 {
      return false;
    }
    // check if will intersect with a piece already on the board
    let current_x = self.current_piece.x_offset;
    let current_y = self.current_piece.y_offset;
    for row in 0..self.current_piece.blocks.len() {
      for col in 0..self.current_piece.blocks[0].len() {
        if self.current_piece.blocks[row][col] == 1 {
          let board_x: i64 = (col as i64) + (current_x as i64) - 1;
          let board_y: i64 = (row as i64) + (current_y as i64);
          if self.cells[board_y as usize][board_x as usize] == 1 {
            return false;
          }
        }
      }
    }
    true
  }

  fn can_move_current_piece_right(&self) -> bool {
    if self.current_piece.rightmost() + 1.0 >= BOARD_WIDTH as f64  {
      return false;
    }
    // check if will intersect with a piece already on the board
    let current_x = self.current_piece.x_offset;
    let current_y = self.current_piece.y_offset;
    for row in 0..self.current_piece.blocks.len() {
      for col in 0..self.current_piece.blocks[0].len() {
        if self.current_piece.blocks[row][col] == 1 {
          let board_x: i64 = (col as i64) + (current_x as i64) + 1;
          let board_y: i64 = (row as i64) + (current_y as i64);
          if self.cells[board_y as usize][board_x as usize] == 1 {
            return false;
          }
        }
      }
    }
    true
  }

  fn current_piece_out_of_bounds(&self) -> bool {
    if self.current_piece.leftmost() < 0.0 || self.current_piece.rightmost() >= BOARD_WIDTH as f64 || self.current_piece.bottommost() >= BOARD_HEIGHT as f64 {
      return true
    }
    false
  }

  pub fn set_piece_on_board(&mut self) {
    let current_x = self.current_piece.x_offset;
    let current_y = self.current_piece.y_offset;
    for row in 0..self.current_piece.blocks.len() {
      for col in 0..self.current_piece.blocks[0].len() {
        if self.current_piece.blocks[row][col] == 1 {
          let x: i64 = (col as i64) + (current_x as i64);
          let y: i64 = (row as i64) + (current_y as i64);
          self.cells[y as usize][x as usize] = 1;
          self.line_counts[y as usize] += 1;
        }
      }
    }
  }

  pub fn get_next_piece(&mut self) -> Tetromino {
    if self.tetrominos_bag.len() == 0 {
      self.tetrominos_bag = TETROMINOS.to_vec();
      ::rand::thread_rng().shuffle(&mut self.tetrominos_bag);
    }
    self.tetrominos_bag.remove(0)
  }

  // helper function to update position of ghost piece w/ current piece
  pub fn update_ghost_piece(&mut self) {
    if self.current_piece.name != self.ghost_piece.name {
      self.ghost_piece = self.current_piece.clone();
      self.ghost_piece.color[3] = GHOST_PIECE_OPACITY;
    }
    self.ghost_piece.y_offset = 0.0;
    self.ghost_piece.x_offset = self.current_piece.x_offset;
    while self.can_move_piece_down(&self.ghost_piece) {
      self.ghost_piece.move_down();
    }
  }
}<commit_msg>Made score increment on block placement<commit_after>use piston::input::*;

use rand::Rng;

use super::BOARD_WIDTH;
use super::BOARD_HEIGHT;
use super::block::Shape;
use super::block::Tetromino;
use super::block::TETROMINOS;

// 1st entry is # of points for clearing 1 line, etc.
const SCORES_PER_LINE: [u64; 4] = [80, 200, 600, 2400];

const GHOST_PIECE_OPACITY: f32 = 0.35;

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum GameState {
  Playing,
  Paused,
  Over // donezo. player lost or quit
}

pub struct Board {
  pub cells: [[u8; BOARD_WIDTH as usize]; BOARD_HEIGHT as usize],
  pub current_piece: Tetromino, // current active Tetromino
  pub ghost_piece: Tetromino, // ghost piece to display at bottom
  pub state: GameState,
  pub score: u64,

  pub token: i32, // token identifier for use by the game server
  pub new_block: bool, // true for 1 iteration if new block, false otherwise

  // line_counts[i] = # of filled blocks in row i
  line_counts: [i64; BOARD_HEIGHT as usize],
  // for "random bag" generation of the next tetromino
  tetrominos_bag: Vec<Tetromino>,
}

impl Board {
  pub fn init_board() -> Board {
    let mut bag = TETROMINOS.to_vec();
    ::rand::thread_rng().shuffle(&mut bag);

    let first_piece: Tetromino = bag.remove(0);
    let mut ghost_piece: Tetromino = first_piece.clone();
    ghost_piece.y_offset = BOARD_HEIGHT as f64 - ghost_piece.block_height();
    // some shapes are drawn starting from 2nd, not 1st row in block
    if ghost_piece.name == Shape::T || ghost_piece.name == Shape::S || ghost_piece.name == Shape::Z {
      ghost_piece.y_offset -= 1.0;
    }
    ghost_piece.color[3] = GHOST_PIECE_OPACITY; // transparent

    Board {
      cells: [[0; BOARD_WIDTH as usize]; BOARD_HEIGHT as usize],
      current_piece: first_piece,
      ghost_piece: ghost_piece,
      state: GameState::Playing,
      score: 0,

      token: 0,
      new_block: true,

      line_counts: [0; BOARD_HEIGHT as usize],
      tetrominos_bag: bag
    }
  }

  pub fn handle_key_press(&mut self, inp: &Input) {
    match *inp {
      Input::Press(but) => {
        match but {
          Button::Keyboard(Key::Up) => {
            self.current_piece.rotate_right();
            self.ghost_piece.rotate_right();
            // undo rotation if it was invalid...lol
            if self.current_piece_out_of_bounds() {
              self.current_piece.rotate_left();
              self.ghost_piece.rotate_left();
            }
            self.update_ghost_piece();
          }
          Button::Keyboard(Key::Left) => {
            if self.can_move_current_piece_left() {
              self.current_piece.move_left();
              self.update_ghost_piece();
            }
          }
          Button::Keyboard(Key::Right) => {
            if self.can_move_current_piece_right() {
              self.current_piece.move_right();
              self.update_ghost_piece();
            }
          }
          Button::Keyboard(Key::Down) => {
            if self.can_move_piece_down(&self.current_piece) {
              self.current_piece.move_down();
            }
          }
          Button::Keyboard(Key::Space) => {
            // pressing spacebar drops piece to bottom
            while self.can_move_piece_down(&self.current_piece) {
              self.current_piece.move_down();
            }
          }
          // TODO: these options disabled for multiplayer

          // P = pause button
          // Button::Keyboard(Key::P) => {
          //     if self.state == GameState::Playing {
          //         self.state = GameState::Paused;
          //     } else if self.state == GameState::Paused {
          //         self.state = GameState::Playing;
          //     }
          // }

          // R = restart button
          // Button::Keyboard(Key::R) => {
          //     // reset all game variables
          //     let mut bag = TETROMINOS.to_vec();
          //     ::rand::thread_rng().shuffle(&mut bag);

          //     self.cells = [[0; BOARD_WIDTH as usize]; BOARD_HEIGHT as usize];
          //     self.current_piece = bag.remove(0);
          //     self.state = GameState::Playing;
          //     self.line_counts = [0; BOARD_HEIGHT as usize];
          //     self.tetrominos_bag = bag;
          //     self.score = 0;
          //     println!("===== GAME RESTARTED =====");
          // }
          _ => {}
        }
      }
      _ => {}
    }
  }

  // iterate thru board and clear the specified row
  fn clear_row(&mut self, row: usize) {
    for col in 0..BOARD_WIDTH {
      self.cells[row][col as usize] = 0;
    }
    self.line_counts[row] = 0;

    // move all cells above (and including) the cleared row down by one
    for r in (1..(row+1)).rev() {
      for col in 0..BOARD_WIDTH {
        self.cells[r as usize][col as usize] = self.cells[(r-1) as usize][col as usize];
      }
      self.line_counts[r as usize] = self.line_counts[(r-1) as usize];
    }
  }

  pub fn clear_line_if_needed(&mut self) {
    // iterate through rows affected by current piece
    let mut rows_affected = Vec::new();
    let current_y = self.current_piece.y_offset;

    for r in 0..self.current_piece.blocks.len() {
      for c in 0..self.current_piece.blocks[0].len() {
        if self.current_piece.blocks[r][c] == 1 {
          let board_y: usize = ((r as f64) + current_y) as usize;
          rows_affected.push(board_y);
        }
      }
    }

    let mut rows_cleared = 0;
    for row in rows_affected.iter() {
      if self.line_counts[*row] == BOARD_WIDTH {
        self.clear_row(*row);
        rows_cleared += 1;
      }
    }
    if rows_cleared > 0 {
      self.score += SCORES_PER_LINE[rows_cleared - 1];
    }
  }

  pub fn advance_board(&mut self) {
    // println!("=== SCORE: {:?} ===", self.score);

    if self.state != GameState::Playing {
      return
    }
    // check if game is over or not
    // check top row of board and see if any of them are filled?
    for col in 0..self.cells[0].len() {
      if self.cells[0][col] == 1{
        self.state = GameState::Over;
        return
      }
    }

    // make the existing piece fall
    if self.can_move_piece_down(&self.current_piece) {
      self.new_block = false;
      self.current_piece.move_down();
    } else {
      // add piece to board cells
      self.set_piece_on_board();
      self.score += 10;

      // clear line if necessary
      self.clear_line_if_needed();

      // get new piece
      self.current_piece = self.get_next_piece();
      self.new_block = true;
      self.update_ghost_piece();
    }
  }

  fn can_move_piece_down(&self, piece: &Tetromino) -> bool {
    if piece.bottommost() + 1.0 >= BOARD_HEIGHT as f64 {
      return false
    }
    // check if piece will intersect with a piece already on the board
    let current_x = piece.x_offset;
    let current_y = piece.y_offset;
    for row in 0..piece.blocks.len() {
      for col in 0..piece.blocks[0].len() {
        if piece.blocks[row][col] == 1 {
          let board_x: i64 = (col as i64) + (current_x as i64);
          let board_y: i64 = (row as i64) + (current_y as i64) + 1;
          if self.cells[board_y as usize][board_x as usize] == 1 {
            return false;
          }
        }
      }
    }
    true
  }

  fn can_move_current_piece_left(&self) -> bool {
    if self.current_piece.leftmost() - 1.0 < 0.0 {
      return false;
    }
    // check if will intersect with a piece already on the board
    let current_x = self.current_piece.x_offset;
    let current_y = self.current_piece.y_offset;
    for row in 0..self.current_piece.blocks.len() {
      for col in 0..self.current_piece.blocks[0].len() {
        if self.current_piece.blocks[row][col] == 1 {
          let board_x: i64 = (col as i64) + (current_x as i64) - 1;
          let board_y: i64 = (row as i64) + (current_y as i64);
          if self.cells[board_y as usize][board_x as usize] == 1 {
            return false;
          }
        }
      }
    }
    true
  }

  fn can_move_current_piece_right(&self) -> bool {
    if self.current_piece.rightmost() + 1.0 >= BOARD_WIDTH as f64  {
      return false;
    }
    // check if will intersect with a piece already on the board
    let current_x = self.current_piece.x_offset;
    let current_y = self.current_piece.y_offset;
    for row in 0..self.current_piece.blocks.len() {
      for col in 0..self.current_piece.blocks[0].len() {
        if self.current_piece.blocks[row][col] == 1 {
          let board_x: i64 = (col as i64) + (current_x as i64) + 1;
          let board_y: i64 = (row as i64) + (current_y as i64);
          if self.cells[board_y as usize][board_x as usize] == 1 {
            return false;
          }
        }
      }
    }
    true
  }

  fn current_piece_out_of_bounds(&self) -> bool {
    if self.current_piece.leftmost() < 0.0 || self.current_piece.rightmost() >= BOARD_WIDTH as f64 || self.current_piece.bottommost() >= BOARD_HEIGHT as f64 {
      return true
    }
    false
  }

  pub fn set_piece_on_board(&mut self) {
    let current_x = self.current_piece.x_offset;
    let current_y = self.current_piece.y_offset;
    for row in 0..self.current_piece.blocks.len() {
      for col in 0..self.current_piece.blocks[0].len() {
        if self.current_piece.blocks[row][col] == 1 {
          let x: i64 = (col as i64) + (current_x as i64);
          let y: i64 = (row as i64) + (current_y as i64);
          self.cells[y as usize][x as usize] = 1;
          self.line_counts[y as usize] += 1;
        }
      }
    }
  }

  pub fn get_next_piece(&mut self) -> Tetromino {
    if self.tetrominos_bag.len() == 0 {
      self.tetrominos_bag = TETROMINOS.to_vec();
      ::rand::thread_rng().shuffle(&mut self.tetrominos_bag);
    }
    self.tetrominos_bag.remove(0)
  }

  // helper function to update position of ghost piece w/ current piece
  pub fn update_ghost_piece(&mut self) {
    if self.current_piece.name != self.ghost_piece.name {
      self.ghost_piece = self.current_piece.clone();
      self.ghost_piece.color[3] = GHOST_PIECE_OPACITY;
    }
    self.ghost_piece.y_offset = 0.0;
    self.ghost_piece.x_offset = self.current_piece.x_offset;
    while self.can_move_piece_down(&self.ghost_piece) {
      self.ghost_piece.move_down();
    }
  }
}
<|endoftext|>


<commit_before>#![feature(if_let)]
extern crate "pkg-config" as pkg_config;
use std::io;
use std::io::fs;
use std::io::fs::PathExtensions;
use std::io::process::{ProcessExit, Command};
use std::path::Path;
use std::os;

fn main() {
	io::println("Searching for LibJIT");
	match pkg_config::find_library("jit") {
		Ok(()) => return,
		Err(..) => {}
	}
	let ref out_dir = Path::new(os::getenv("OUT_DIR").expect("OUT_DIR needed for compilation"));
	let ref final_lib_path = Path::new("native/jit/.libs/libjit.so");
	let ref dest_path = out_dir.join("libjit.so");
	let ref submod_path = Path::new("native");
	if !dest_path.exists() {
		if !final_lib_path.exists() {
			if !submod_path.exists() {
				run(Command::new("git").arg("submodule").arg("init"));
			}
			run(Command::new("git").arg("submodule").arg("update"));
			run(Command::new("sh").arg("auto_gen.sh").cwd(submod_path));
			run(Command::new("./configure").cwd(submod_path));
			run(Command::new("make").cwd(submod_path));
		}
		fs::copy(final_lib_path, dest_path).unwrap();
	}
    println!("cargo:root={}", out_dir.display());
    println!("cargo:rustc-flags=-l jit:static");
	println!("cargo:rustc-flags=-L {}", out_dir.display());
}
fn run(command: &mut Command) {
	let process = command.output().unwrap();
	println!("{}", command);
	if !process.status.success() {
		panic!("failed with output: \n{}\n{}", String::from_utf8_lossy(process.output[]), String::from_utf8_lossy(process.error[]));
	}
}<commit_msg>Add new option to `configure` so LibJIT should have `-fPIC` option enabled<commit_after>#![feature(if_let)]
extern crate "pkg-config" as pkg_config;
use std::io;
use std::io::fs;
use std::io::fs::PathExtensions;
use std::io::process::Command;
use std::path::Path;
use std::os;

fn main() {
	io::println("Searching for LibJIT");
	match pkg_config::find_library("jit") {
		Ok(()) => return,
		Err(..) => {}
	}
	let ref out_dir = Path::new(os::getenv("OUT_DIR").expect("OUT_DIR needed for compilation"));
	let ref final_lib_dir = Path::new("native/jit/.libs");
	let ref submod_path = Path::new("native");
	if !final_lib_dir.exists() {
		if !final_lib_dir.exists() {
			if !submod_path.exists() {
				run(Command::new("git").arg("submodule").arg("init"));
			}
			run(Command::new("git").arg("submodule").arg("update"));
			run(Command::new("sh").arg("auto_gen.sh").cwd(submod_path));
			run(Command::new("./configure --enable-shared").cwd(submod_path));
			run(Command::new("make").cwd(submod_path));
		}
	}
    println!("cargo:root={}", out_dir.display());
    println!("cargo:rustc-flags=-l jit:static");
	println!("cargo:rustc-flags=-L {}", final_lib_dir.display());
}
fn run(command: &mut Command) {
	let process = command.output().unwrap();
	println!("{}", command);
	if !process.status.success() {
		panic!("failed with output: \n{}\n{}", String::from_utf8_lossy(process.output[]), String::from_utf8_lossy(process.error[]));
	}
}<|endoftext|>


<commit_before>use std::io::Read;
use std::fs;
use std::env;
use std::path::PathBuf;

#[cfg(unix)] use std::os::unix::fs::MetadataExt;

use flate2::read::GzDecoder;
use tar::Archive;
use curl::http;
use walkdir::{WalkDir, WalkDirIterator, DirEntry};
use time;

use error::TldrError::{self, CacheError, UpdateError};
use types::OsType;

#[derive(Debug)]
pub struct Cache {
    url: String,
    os: OsType,
}

impl Cache {

    pub fn new<S>(url: S, os: OsType) -> Cache where S: Into<String> {
        Cache {
            url: url.into(),
            os: os,
        }
    }

    /// Return the path to the cache directory.
    fn get_cache_dir(&self) -> Result<PathBuf, TldrError> {
        // Allow overriding the cache directory by setting the
        // $TLDR_RS_CACHE_DIR env variable.
        if let Ok(value) = env::var("TLDR_RS_CACHE_DIR") {
            let path = PathBuf::from(value);
            if path.exists() && path.is_dir() {
                return Ok(path)
            } else {
                return Err(CacheError(
                    "Path specified by $TLDR_RS_CACHE_DIR \
                     does not exist or is not a directory.".into()
                ));
            }
        };

        // Otherwise, fall back to ~/.cache/tldr-rs
        let home_dir = try!(env::home_dir().ok_or(
            CacheError("Could not determine home directory".into())
        ));
        Ok(home_dir.join(".cache").join("tldr-rs"))
    }

    /// Download the archive
    fn download(&self) -> Result<http::Response, TldrError> {
        let resp = try!(
            http::handle()
                 .follow_location(1)
                 .get(&self.url[..])
                 .exec()
        );
        Ok(resp)
    }

    /// Decompress and open the archive
    fn decompress<R: Read>(&self, reader: R) -> Result<Archive<GzDecoder<R>>, TldrError> {
        let decoder = try!(GzDecoder::new(reader).map_err(|_| UpdateError("Could not decode gzip data".into())));
        Ok(Archive::new(decoder))
    }

    /// Update the pages cache.
    pub fn update(&self) -> Result<(), TldrError> {
        // First, download the compressed data
        let response = try!(self.download());

        // Decompress the response body into an `Archive`
        let mut archive = try!(self.decompress(response.get_body()));

        // Determine paths
        let cache_dir = try!(self.get_cache_dir());

        // Clear cache directory
        // Note: This is not the best solution. Ideally we would download the
        // archive to a temporary directory and then swap the two directories.
        // But renaming a directory doesn't work across filesystems and Rust
        // does not yet offer a recursive directory copying function. So for
        // now, we'll use this approach.
        try!(self.clear());

        // Extract archive
        try!(archive.unpack(&cache_dir).map_err(|e| {
            UpdateError(format!("Could not unpack compressed data: {}", e))
        }));

        Ok(())
    }

    #[cfg(unix)]
    /// Return the number of seconds since the cache directory was last modified.
    pub fn last_update(&self) -> Option<i64> {
        if let Ok(cache_dir) = self.get_cache_dir() {
            if let Ok(metadata) = fs::metadata(cache_dir.join("tldr-master")) {
                let mtime = metadata.mtime();
                let now = time::now_utc().to_timespec();
                return Some(now.sec - mtime)
            };
        };
        None
    }

    /// Return the platform directory.
    fn get_platform_dir(&self) -> Option<&'static str> {
        match self.os {
            OsType::Linux => Some("linux"),
            OsType::OsX => Some("osx"),
            OsType::SunOs => None, // TODO: Does Rust support SunOS?
            OsType::Other => None,
        }
    }

    /// Search for a page and return the path to it.
    pub fn find_page(&self, name: &str) -> Option<PathBuf> {
        // Build page file name
        let page_filename = format!("{}.md", name);

        // Get platform dir
        let platforms_dir = match self.get_cache_dir() {
            Ok(cache_dir) => cache_dir.join("tldr-master").join("pages"),
            _ => return None,
        };

        // Determine platform
        let platform = self.get_platform_dir();

        // Search for the page in the platform specific directory
        if let Some(pf) = platform {
            let path = platforms_dir.join(&pf).join(&page_filename);
            if path.exists() && path.is_file() {
                return Some(path);
            }
        }

        // If platform is not supported or if platform specific page does not exist,
        // look up the page in the "common" directory.
        let path = platforms_dir.join("common").join(&page_filename);

        // Return it if it exists, otherwise give up and return `None`
        if path.exists() && path.is_file() {
            Some(path)
        } else {
            None
        }
    }

    /// Return the available pages.
    pub fn list_pages(&self) -> Result<Vec<String>, TldrError> {

        // Determine platforms directory and platform
        let cache_dir = try!(self.get_cache_dir());
        let platforms_dir = cache_dir.join("tldr-master").join("pages");
        let platform_dir = self.get_platform_dir();

        // Closure that allows the WalkDir instance to traverse platform
        // specific and common page directories, but not others.
        let should_walk = |entry: &DirEntry| -> bool {
            let file_type = entry.file_type();
            let file_name = match entry.file_name().to_str() {
                Some(name) => name,
                None => return false,
            };
            if file_type.is_dir() {
                if file_name == "common" {
                    return true;
                }
                if let Some(platform) = platform_dir {
                    return file_name == platform;
                }
            } else if file_type.is_file() {
                return true
            }
            false
        };

        // Recursively walk through common and (if applicable) platform specific directory
        let mut pages = WalkDir::new(platforms_dir)
                                .min_depth(1) // Skip root directory
                                .into_iter()
                                .filter_entry(|e| should_walk(e)) // Filter out pages for other architectures
                                .filter_map(|e| e.ok()) // Convert results to options, filter out errors
                                .filter_map(|e| {
                                    let path = e.path();
                                    let extension = &path.extension().and_then(|s| s.to_str()).unwrap_or("");
                                    if e.file_type().is_file() && extension == &"md" {
                                        path.file_stem().and_then(|stem| stem.to_str().map(|s| s.into()))
                                    } else {
                                        None
                                    }
                                })
                                .collect::<Vec<String>>();
        pages.sort();
        pages.dedup();
        Ok(pages)
    }

    /// Delete the cache directory.
    pub fn clear(&self) -> Result<(), TldrError> {
        let path = try!(self.get_cache_dir());
        if path.exists() && path.is_dir() {
            try!(fs::remove_dir_all(&path).map_err(|_| {
                CacheError(format!("Could not remove cache directory ({}).", path.display()))
            }));
        } else if path.exists() {
            return Err(CacheError(format!("Cache path ({}) is not a directory.", path.display())));
        } else {
            return Err(CacheError(format!("Cache path ({}) does not exist.", path.display())));
        };
        Ok(())
    }

}
<commit_msg>Fix creation of cache dir<commit_after>use std::io::Read;
use std::fs;
use std::env;
use std::path::PathBuf;

#[cfg(unix)] use std::os::unix::fs::MetadataExt;

use flate2::read::GzDecoder;
use tar::Archive;
use curl::http;
use walkdir::{WalkDir, WalkDirIterator, DirEntry};
use time;

use error::TldrError::{self, CacheError, UpdateError};
use types::OsType;

#[derive(Debug)]
pub struct Cache {
    url: String,
    os: OsType,
}

impl Cache {

    pub fn new<S>(url: S, os: OsType) -> Cache where S: Into<String> {
        Cache {
            url: url.into(),
            os: os,
        }
    }

    /// Return the path to the cache directory.
    fn get_cache_dir(&self) -> Result<PathBuf, TldrError> {
        // Allow overriding the cache directory by setting the
        // $TLDR_RS_CACHE_DIR env variable.
        if let Ok(value) = env::var("TLDR_RS_CACHE_DIR") {
            let path = PathBuf::from(value);
            if path.exists() && path.is_dir() {
                return Ok(path)
            } else {
                return Err(CacheError(
                    "Path specified by $TLDR_RS_CACHE_DIR \
                     does not exist or is not a directory.".into()
                ));
            }
        };

        // Otherwise, fall back to ~/.cache/tldr-rs
        let home_dir = try!(env::home_dir().ok_or(
            CacheError("Could not determine home directory".into())
        ));
        Ok(home_dir.join(".cache").join("tldr-rs"))
    }

    /// Download the archive
    fn download(&self) -> Result<http::Response, TldrError> {
        let resp = try!(
            http::handle()
                 .follow_location(1)
                 .get(&self.url[..])
                 .exec()
        );
        Ok(resp)
    }

    /// Decompress and open the archive
    fn decompress<R: Read>(&self, reader: R) -> Result<Archive<GzDecoder<R>>, TldrError> {
        let decoder = try!(GzDecoder::new(reader).map_err(|_| UpdateError("Could not decode gzip data".into())));
        Ok(Archive::new(decoder))
    }

    /// Update the pages cache.
    pub fn update(&self) -> Result<(), TldrError> {
        // First, download the compressed data
        let response = try!(self.download());

        // Decompress the response body into an `Archive`
        let mut archive = try!(self.decompress(response.get_body()));

        // Determine paths
        let cache_dir = try!(self.get_cache_dir());

        // Make sure that cache directory exists
        debug!("Ensure cache directory {:?} exists", &cache_dir);
        try!(fs::create_dir_all(&cache_dir).map_err(|e| {
            UpdateError(format!("Could not create cache directory: {}", e))
        }));

        // Clear cache directory
        // Note: This is not the best solution. Ideally we would download the
        // archive to a temporary directory and then swap the two directories.
        // But renaming a directory doesn't work across filesystems and Rust
        // does not yet offer a recursive directory copying function. So for
        // now, we'll use this approach.
        try!(self.clear());

        // Extract archive
        try!(archive.unpack(&cache_dir).map_err(|e| {
            UpdateError(format!("Could not unpack compressed data: {}", e))
        }));

        Ok(())
    }

    #[cfg(unix)]
    /// Return the number of seconds since the cache directory was last modified.
    pub fn last_update(&self) -> Option<i64> {
        if let Ok(cache_dir) = self.get_cache_dir() {
            if let Ok(metadata) = fs::metadata(cache_dir.join("tldr-master")) {
                let mtime = metadata.mtime();
                let now = time::now_utc().to_timespec();
                return Some(now.sec - mtime)
            };
        };
        None
    }

    /// Return the platform directory.
    fn get_platform_dir(&self) -> Option<&'static str> {
        match self.os {
            OsType::Linux => Some("linux"),
            OsType::OsX => Some("osx"),
            OsType::SunOs => None, // TODO: Does Rust support SunOS?
            OsType::Other => None,
        }
    }

    /// Search for a page and return the path to it.
    pub fn find_page(&self, name: &str) -> Option<PathBuf> {
        // Build page file name
        let page_filename = format!("{}.md", name);

        // Get platform dir
        let platforms_dir = match self.get_cache_dir() {
            Ok(cache_dir) => cache_dir.join("tldr-master").join("pages"),
            _ => return None,
        };

        // Determine platform
        let platform = self.get_platform_dir();

        // Search for the page in the platform specific directory
        if let Some(pf) = platform {
            let path = platforms_dir.join(&pf).join(&page_filename);
            if path.exists() && path.is_file() {
                return Some(path);
            }
        }

        // If platform is not supported or if platform specific page does not exist,
        // look up the page in the "common" directory.
        let path = platforms_dir.join("common").join(&page_filename);

        // Return it if it exists, otherwise give up and return `None`
        if path.exists() && path.is_file() {
            Some(path)
        } else {
            None
        }
    }

    /// Return the available pages.
    pub fn list_pages(&self) -> Result<Vec<String>, TldrError> {

        // Determine platforms directory and platform
        let cache_dir = try!(self.get_cache_dir());
        let platforms_dir = cache_dir.join("tldr-master").join("pages");
        let platform_dir = self.get_platform_dir();

        // Closure that allows the WalkDir instance to traverse platform
        // specific and common page directories, but not others.
        let should_walk = |entry: &DirEntry| -> bool {
            let file_type = entry.file_type();
            let file_name = match entry.file_name().to_str() {
                Some(name) => name,
                None => return false,
            };
            if file_type.is_dir() {
                if file_name == "common" {
                    return true;
                }
                if let Some(platform) = platform_dir {
                    return file_name == platform;
                }
            } else if file_type.is_file() {
                return true
            }
            false
        };

        // Recursively walk through common and (if applicable) platform specific directory
        let mut pages = WalkDir::new(platforms_dir)
                                .min_depth(1) // Skip root directory
                                .into_iter()
                                .filter_entry(|e| should_walk(e)) // Filter out pages for other architectures
                                .filter_map(|e| e.ok()) // Convert results to options, filter out errors
                                .filter_map(|e| {
                                    let path = e.path();
                                    let extension = &path.extension().and_then(|s| s.to_str()).unwrap_or("");
                                    if e.file_type().is_file() && extension == &"md" {
                                        path.file_stem().and_then(|stem| stem.to_str().map(|s| s.into()))
                                    } else {
                                        None
                                    }
                                })
                                .collect::<Vec<String>>();
        pages.sort();
        pages.dedup();
        Ok(pages)
    }

    /// Delete the cache directory.
    pub fn clear(&self) -> Result<(), TldrError> {
        let path = try!(self.get_cache_dir());
        if path.exists() && path.is_dir() {
            try!(fs::remove_dir_all(&path).map_err(|_| {
                CacheError(format!("Could not remove cache directory ({}).", path.display()))
            }));
        } else if path.exists() {
            return Err(CacheError(format!("Cache path ({}) is not a directory.", path.display())));
        } else {
            return Err(CacheError(format!("Cache path ({}) does not exist.", path.display())));
        };
        Ok(())
    }

}
<|endoftext|>


<commit_before>use std::convert::From;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter::FromIterator;
use std::iter::Iterator;
use std::ops::Deref;

use rand::Rng;
use smallvec::SmallVec;

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct DimensionSize(pub usize);

pub trait Coordinate: PartialEq + Eq + Hash + Copy + Clone + Debug + Ord + PartialOrd {

    fn from_row_major_index(index: usize, row_size: DimensionSize) -> Self;
    fn from_row_column_indices(col_index: usize, row_index: usize) -> Self;
    fn as_cartesian_2d(&self) -> Cartesian2DCoordinate;
}

pub trait Cell {

    type Coord: Coordinate;
    type Direction: Eq + PartialEq + Copy + Clone + Debug;
                          // Require that the Option fixed size Vec specifically wraps Coord with an Option otherwise
                          // we get type errors saying a general CoordinateOptionFixedSizeVec IntoIterator::Item cannot `unwrap`.
                          // associated type specification, not trait type parameter, but almost same syntax...
                          // e.g. FromIterator<T> is a type parameter to the trait
                          //      IntoIterator<Item=T> is an associated type specialisation
                          // Deref<Target=[Self::Coord]> gives access to the `iter` of slices.
    type CoordinateSmallVec: FromIterator<Self::Coord> + Deref<Target=[Self::Coord]>;
    type CoordinateOptionFixedSizeVec: FromIterator<Option<Self::Coord>> + Deref<Target=[Option<Self::Coord>]>;
    type DirectionFixedSizeVec: FromIterator<Self::Direction> + Deref<Target=[Self::Direction]>;

    /// Creates a small vec of the possible directions away from this Cell.
    fn offset_directions(coord: &Option<Self::Coord>) -> Self::DirectionFixedSizeVec;

    /// Creates a new `Coord` offset 1 cell away in the given direction.
    /// Returns None if the Coordinate is not representable.
    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord>;

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction;
    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction;
    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction;
}

#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug, Ord, PartialOrd)]
pub struct Cartesian2DCoordinate {
    pub x: u32,
    pub y: u32,
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum CompassPrimary {
    North,
    South,
    East,
    West,
}

#[derive(Copy, Clone, Debug)]
pub struct SquareCell;

impl Cell for SquareCell {
    type Coord = Cartesian2DCoordinate;  // : Debug, Copy, Clone
    type Direction = CompassPrimary;
    type CoordinateSmallVec = SmallVec<[Self::Coord; 4]>;

    // do not really want this indirection as it requires me to make option itself, unwrapping a trait?
    // prefer the const 4, but they do not exist in the language yet
    // could just dynamically query the size of CoordinateSmallVec? No then the option variant is not a compile time decision
    // argh
    type CoordinateOptionFixedSizeVec = SmallVec<[Option<Self::Coord>; 4]>;

    type DirectionFixedSizeVec = SmallVec<[CompassPrimary; 4]>;

    fn offset_directions(_: &Option<Self::Coord>) -> Self::DirectionFixedSizeVec {
        [CompassPrimary::North,
         CompassPrimary::South,
         CompassPrimary::East,
         CompassPrimary::West]
        .into_iter().cloned().collect::<Self::DirectionFixedSizeVec>()
    }

    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord> {

        let (x, y) = (coord.x, coord.y);
        match dir {
            CompassPrimary::North => {
                if y > 0 {
                    Some(Cartesian2DCoordinate { x: x, y: y - 1 })
                } else {
                    None
                }
            }
            CompassPrimary::South => Some(Cartesian2DCoordinate { x: x, y: y + 1 }),
            CompassPrimary::East => Some(Cartesian2DCoordinate { x: x + 1, y: y }),
            CompassPrimary::West => {
                if x > 0 {
                    Some(Cartesian2DCoordinate { x: x - 1, y: y })
                } else {
                    None
                }
            }
        }
    }

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        const DIRS_COUNT: usize = 4;
        const DIRS: [CompassPrimary; DIRS_COUNT] =
            [CompassPrimary::North, CompassPrimary::South, CompassPrimary::East, CompassPrimary::West];
        let dir_index = rng.gen::<usize>() % DIRS_COUNT;
        DIRS[dir_index]
    }

    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            CompassPrimary::North
        } else {
            CompassPrimary::South
        }
    }
    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            CompassPrimary::East
        } else {
            CompassPrimary::West
        }
    }
}

impl Cartesian2DCoordinate {
    pub fn new(x: u32, y: u32) -> Cartesian2DCoordinate {
        Cartesian2DCoordinate { x: x, y: y }
    }
}
impl Coordinate for Cartesian2DCoordinate {

    fn from_row_major_index(index: usize, row_size: DimensionSize) -> Cartesian2DCoordinate {
        let DimensionSize(size) = row_size;
        let x = index % size;
        let y = index / size;

        Cartesian2DCoordinate::new(x as u32, y as u32)
    }

    fn from_row_column_indices(col_index: usize, row_index: usize) -> Self {
        Cartesian2DCoordinate::new(col_index as u32, row_index as u32)
    }

    fn as_cartesian_2d(&self) -> Cartesian2DCoordinate {
        *self
    }
}

impl From<(u32, u32)> for Cartesian2DCoordinate {
    fn from(x_y_pair: (u32, u32)) -> Cartesian2DCoordinate {
        Cartesian2DCoordinate::new(x_y_pair.0, x_y_pair.1)
    }
}
<commit_msg>PolarCell skeleton<commit_after>use std::convert::From;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter::FromIterator;
use std::iter::Iterator;
use std::ops::Deref;

use rand::Rng;
use smallvec::SmallVec;

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct DimensionSize(pub usize);

pub trait Coordinate: PartialEq + Eq + Hash + Copy + Clone + Debug + Ord + PartialOrd {

    fn from_row_major_index(index: usize, row_size: DimensionSize) -> Self;
    fn from_row_column_indices(col_index: usize, row_index: usize) -> Self;
    fn as_cartesian_2d(&self) -> Cartesian2DCoordinate;
}

pub trait Cell {

    type Coord: Coordinate;
    type Direction: Eq + PartialEq + Copy + Clone + Debug;
                          // Require that the Option fixed size Vec specifically wraps Coord with an Option otherwise
                          // we get type errors saying a general CoordinateOptionFixedSizeVec IntoIterator::Item cannot `unwrap`.
                          // associated type specification, not trait type parameter, but almost same syntax...
                          // e.g. FromIterator<T> is a type parameter to the trait
                          //      IntoIterator<Item=T> is an associated type specialisation
                          // Deref<Target=[Self::Coord]> gives access to the `iter` of slices.
    type CoordinateSmallVec: FromIterator<Self::Coord> + Deref<Target=[Self::Coord]>;
    type CoordinateOptionFixedSizeVec: FromIterator<Option<Self::Coord>> + Deref<Target=[Option<Self::Coord>]>;
    type DirectionFixedSizeVec: FromIterator<Self::Direction> + Deref<Target=[Self::Direction]>;

    /// Creates a small vec of the possible directions away from this Cell.
    fn offset_directions(coord: &Option<Self::Coord>) -> Self::DirectionFixedSizeVec;

    /// Creates a new `Coord` offset 1 cell away in the given direction.
    /// Returns None if the Coordinate is not representable.
    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord>;

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction;
    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction;
    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction;
}

#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug, Ord, PartialOrd)]
pub struct Cartesian2DCoordinate {
    pub x: u32,
    pub y: u32,
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum CompassPrimary {
    North,
    South,
    East,
    West,
}

#[derive(Copy, Clone, Debug)]
pub struct SquareCell;

impl Cell for SquareCell {
    type Coord = Cartesian2DCoordinate;  // : Debug, Copy, Clone
    type Direction = CompassPrimary;
    type CoordinateSmallVec = SmallVec<[Self::Coord; 4]>;

    // do not really want this indirection as it requires me to make option itself, unwrapping a trait?
    // prefer the const 4, but they do not exist in the language yet
    // could just dynamically query the size of CoordinateSmallVec? No then the option variant is not a compile time decision
    // argh
    type CoordinateOptionFixedSizeVec = SmallVec<[Option<Self::Coord>; 4]>;

    type DirectionFixedSizeVec = SmallVec<[CompassPrimary; 4]>;

    fn offset_directions(_: &Option<Self::Coord>) -> Self::DirectionFixedSizeVec {
        [CompassPrimary::North,
         CompassPrimary::South,
         CompassPrimary::East,
         CompassPrimary::West]
        .into_iter().cloned().collect::<Self::DirectionFixedSizeVec>()
    }

    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord> {

        let (x, y) = (coord.x, coord.y);
        match dir {
            CompassPrimary::North => {
                if y > 0 {
                    Some(Cartesian2DCoordinate { x: x, y: y - 1 })
                } else {
                    None
                }
            }
            CompassPrimary::South => Some(Cartesian2DCoordinate { x: x, y: y + 1 }),
            CompassPrimary::East => Some(Cartesian2DCoordinate { x: x + 1, y: y }),
            CompassPrimary::West => {
                if x > 0 {
                    Some(Cartesian2DCoordinate { x: x - 1, y: y })
                } else {
                    None
                }
            }
        }
    }

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        const DIRS_COUNT: usize = 4;
        const DIRS: [CompassPrimary; DIRS_COUNT] =
            [CompassPrimary::North, CompassPrimary::South, CompassPrimary::East, CompassPrimary::West];
        let dir_index = rng.gen::<usize>() % DIRS_COUNT;
        DIRS[dir_index]
    }

    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            CompassPrimary::North
        } else {
            CompassPrimary::South
        }
    }
    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            CompassPrimary::East
        } else {
            CompassPrimary::West
        }
    }
}

impl Cartesian2DCoordinate {
    pub fn new(x: u32, y: u32) -> Cartesian2DCoordinate {
        Cartesian2DCoordinate { x: x, y: y }
    }
}
impl Coordinate for Cartesian2DCoordinate {

    fn from_row_major_index(index: usize, row_size: DimensionSize) -> Cartesian2DCoordinate {
        let DimensionSize(size) = row_size;
        let x = index % size;
        let y = index / size;

        Cartesian2DCoordinate::new(x as u32, y as u32)
    }

    fn from_row_column_indices(col_index: usize, row_index: usize) -> Self {
        Cartesian2DCoordinate::new(col_index as u32, row_index as u32)
    }

    fn as_cartesian_2d(&self) -> Cartesian2DCoordinate {
        *self
    }
}

impl From<(u32, u32)> for Cartesian2DCoordinate {
    fn from(x_y_pair: (u32, u32)) -> Cartesian2DCoordinate {
        Cartesian2DCoordinate::new(x_y_pair.0, x_y_pair.1)
    }
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct PolarCell;

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum ClockDirection {
    Clockwise,
    CounterClockwise,
    Inward,
    Outward
}

impl Cell for PolarCell {

    type Coord = Cartesian2DCoordinate;
    type Direction = ClockDirection;
    type CoordinateSmallVec = SmallVec<[Self::Coord; 8]>;
    type CoordinateOptionFixedSizeVec = SmallVec<[Option<Self::Coord>; 8]>;
    type DirectionFixedSizeVec = SmallVec<[Self::Direction; 8]>;

    /// Creates a small vec of the possible directions away from this Cell.
    fn offset_directions(coord: &Option<Self::Coord>) -> Self::DirectionFixedSizeVec {
        [ClockDirection::Clockwise,
         ClockDirection::CounterClockwise,
         ClockDirection::Inward,
         ClockDirection::Outward]
        .into_iter().cloned().collect::<Self::DirectionFixedSizeVec>()

        // and extend from the outward direction instance? [ClockDirection::Outward, ClockDirection::Outward, ClockDirection::Outward]?
    }

    /// Creates a new `Coord` offset 1 cell away in the given direction.
    /// Returns None if the Coordinate is not representable.
    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord> {

        let (x, y) = (coord.x, coord.y);
        match dir {
            ClockDirection::Clockwise => {

            }
            ClockDirection::CounterClockwise => {},
            ClockDirection::Inward => {},
            ClockDirection::Outward => {

            }
        };

        None
    }

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction { // what about multiple outward options? outward is not a single direction
        const DIRS_COUNT: usize = 4;
        const DIRS: [ClockDirection; DIRS_COUNT] =
            [ClockDirection::Clockwise, ClockDirection::CounterClockwise, ClockDirection::Inward, ClockDirection::Outward];
        let dir_index = rng.gen::<usize>() % DIRS_COUNT;
        DIRS[dir_index]
    }

    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            ClockDirection::Clockwise
        } else {
            ClockDirection::CounterClockwise
        }
    }

    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            ClockDirection::Inward
        } else {
            ClockDirection::Outward
        }
    }

}

// Polar grid constructor
// number of rows, assume "columns" is 1, which will be adaptively subdivided.
// so need a RectGrid where can specify the rows and columns

<|endoftext|>


<commit_before>/*
 * Copyright 2015 Justin Noah <justinnoah at gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use std::default::Default;

pub struct Chip8 {
    // Clear Display (SDL - black screen)
    pub cls: bool,

    /*
     * 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
     * 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
     * 0x200-0xFFF - Program ROM and work RAM
     */
    pub memory: [u8; 4096],

    /*
     * CPU registers: The Chip 8 has 15 8-bit general purpose registers
     * named V0,V1 up to VE. The 16th register is used  for the ‘carry flag’.
     */
    pub registers: [u8; 16],

    // Index register
    pub i: u16,

    // program counter
    pub pc: u16,

    // Screen - 64 x 32 pixels
    pub graphics: [u8; 64*32],

    // No timers, but 60hz counters
    pub delay_timer: u8,
    pub sound_timer: u8,

    // Stack needed to jump to certain addresses or call subroutines
    // The chip8 stack has 16 levels
    pub stack_pointer: u16,
    pub stack: [u16; 16],

    // Chip8 keypad had 16 keys - keep track of the kb state
    pub keypad: [u8; 16],
}

impl Default for Chip8 {
    #[inline]
    fn default() -> Chip8 {
        Chip8 {
            // Let's clear the screen at start
            cls: true,
            memory: [0u8; 4096],
            registers: [0u8; 16],
            i: 0u16,
            pc: 0x200u16,
            graphics: [0u8; 64*32],
            delay_timer: 0u8,
            sound_timer: 0u8,
            stack_pointer: 0u16,
            stack: [0u16; 16],
            keypad: [0u8; 16],
        }
    }
}

impl Chip8 {
   pub fn cycle(&mut self) {
        // fetch
        let highbits: u8 = self.memory[(self.pc as uint)];
        let lowbits: u8 = self.memory[(self.pc + 1) as uint];
        let mut opcode: u16 = highbits as u16;
        opcode = (opcode << 8) | lowbits as u16;

        // Decode
        match opcode {
            // Clear screen
            0x00e0 => self.cls = true,
            // RET
            0x00ee  => {
                // Move program counter to the top of the stack
                self.pc = self.stack[(self.stack_pointer as uint)];
                // Decrement the stack pointer
                self.stack_pointer -= 1
            },
            // 1nnn - JP addr - jump to nnn
            op @ 0x1000 ... 0x1fff   =>  self.pc = op ^ 0x1000,
            // 2nnn - CALL addr - call subroutine at nnn
            op @ 0x2000 ... 0x2fff   => {
                let nnn = op ^ 0x2000;
                // Increment the stack pointer
                self.stack_pointer += 1;
                // Put the value of pc ontop of the stack
                self.stack[self.stack_pointer as uint] = self.pc;
                // Set the pc to nnn
                self.pc = nnn;
            },
            // 3xkk - Skip next instruction if Vx == kk
            op @ 0x3000 ... 0x3fff => {
                let V: u8 = ((op & 0x0F00) >> 8) as u8;
                let byte: u8 = (op & 0x00FF) as u8;
                if self.registers[V as uint] == byte {
                    self.pc += 2;
                }
            },
            // 4xkk - Skip next instruction if Vx != kk
            op @ 0x4000 ... 0x4fff => {
                let V: u8 = ((op & 0x0F00) >> 8) as u8;
                let byte: u8 = (op & 0x00FF) as u8;
                if self.registers[V as uint] != byte {
                    self.pc += 2;
                }
            },
            // 5xy0 -  Skip next instruction if Vx == Vy
            op @ 0x5000 ... 0x5ff0 if op % 16  == 0 => {
                let vx: u8 = ((op & 0x0f00) >> 8) as u8;
                let vy: u8 = ((op & 0x00f0) >> 4) as u8;
                if vx == vy {
                    self.pc += 2;
                }
            },
            // Unsupported
            op @ _ => println!("Unknown opcode: {:X}", op),
        }
        // Execute
        // Increment the counter
        self.pc += 2;
        // Update timers
    }
}
<commit_msg>added more opcodes<commit_after>/*
 * Copyright 2015 Justin Noah <justinnoah at gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use std::default::Default;

pub struct Chip8 {
    // Clear Display (SDL - black screen)
    pub cls: bool,

    /*
     * 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
     * 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
     * 0x200-0xFFF - Program ROM and work RAM
     */
    pub memory: [u8; 4096],

    /*
     * CPU registers: The Chip 8 has 15 8-bit general purpose registers
     * named V0,V1 up to VE. The 16th register is used  for the ‘carry flag’.
     */
    pub registers: [u8; 16],

    // Index register
    pub i: u16,

    // program counter
    pub pc: u16,

    // Screen - 64 x 32 pixels
    pub graphics: [u8; 64*32],

    // No timers, but 60hz counters
    pub delay_timer: u8,
    pub sound_timer: u8,

    // Stack needed to jump to certain addresses or call subroutines
    // The chip8 stack has 16 levels
    pub stack_pointer: u16,
    pub stack: [u16; 16],

    // Chip8 keypad had 16 keys - keep track of the kb state
    pub keypad: [u8; 16],
}

impl Default for Chip8 {
    #[inline]
    fn default() -> Chip8 {
        Chip8 {
            // Let's clear the screen at start
            cls: true,
            memory: [0u8; 4096],
            registers: [0u8; 16],
            i: 0u16,
            pc: 0x200u16,
            graphics: [0u8; 64*32],
            delay_timer: 0u8,
            sound_timer: 0u8,
            stack_pointer: 0u16,
            stack: [0u16; 16],
            keypad: [0u8; 16],
        }
    }
}

impl Chip8 {
   pub fn cycle(&mut self) {
        // fetch
        let highbits: u8 = self.memory[(self.pc as uint)];
        let lowbits: u8 = self.memory[(self.pc + 1) as uint];
        let mut opcode: u16 = highbits as u16;
        opcode = (opcode << 8) | lowbits as u16;

        // Decode
        match opcode {
            // Clear screen
            0x00e0 => self.cls = true,
            // RET
            0x00ee  => {
                // Move program counter to the top of the stack
                self.pc = self.stack[(self.stack_pointer as uint)];
                // Decrement the stack pointer
                self.stack_pointer -= 1
            },
            // 1nnn - JP addr - jump to nnn
            op @ 0x1000 ... 0x1fff   =>  self.pc = op ^ 0x1000,
            // 2nnn - CALL addr - call subroutine at nnn
            op @ 0x2000 ... 0x2fff   => {
                let nnn = op ^ 0x2000;
                // Increment the stack pointer
                self.stack_pointer += 1;
                // Put the value of pc ontop of the stack
                self.stack[self.stack_pointer as uint] = self.pc;
                // Set the pc to nnn
                self.pc = nnn;
            },
            // 3xkk - SE Vx, byte - Skip next instruction if Vx == kk
            op @ 0x3000 ... 0x3fff => {
                let V: u8 = ((op & 0x0F00) >> 8) as u8;
                let byte: u8 = (op & 0x00FF) as u8;
                if self.registers[V as uint] == byte {
                    self.pc += 2;
                }
            },
            // 4xkk - SNE Vx, byte - Skip next instruction if Vx != kk
            op @ 0x4000 ... 0x4fff => {
                let V: u8 = ((op & 0x0F00) >> 8) as u8;
                let byte: u8 = (op & 0x00FF) as u8;
                if self.registers[V as uint] != byte {
                    self.pc += 2;
                }
            },
            // 5xy0 - SE Vx, Vy - Skip next instruction if Vx == Vy
            op @ 0x5000 ... 0x5ff0 if op % 16  == 0 => {
                let vx: u8 = ((op & 0x0f00) >> 8) as u8;
                let vy: u8 = ((op & 0x00f0) >> 4) as u8;
                if vx == vy {
                    self.pc += 2;
                }
            },
            // 6xkk - LD Vx, byte -  Set Vx = kk
            op @ 0x6000 ... 0x6fff => {
                self.registers[((op & 0x0f00) >> 8) as uint] = (op & 0x00ff) as u8;
            },
            // 7xkk - ADD Vx, byte -  Set Vx = Vx + kk
            op @ 0x7000 ... 0x7fff => {
                self.registers[((op & 0x0f00) >> 8) as uint] += (op & 0x00ff) as u8;
            },
            // 8xy0 - 8xye
            op @ 0x8000 ... 0x8ffe => {
                let x  =  (op & 0x000f) as uint;
                let vy = ((op & 0x00f0) >> 4) as uint;
                let vx = ((op & 0x0f00) >> 8) as uint;

                match x {
                    // 8xy0 - LD Vx, Vy - Set Vx = Vy.
                    0 => self.registers[vx] = self.registers[vy],
                    // 8xy1 - OR Vx, Vy - Set Vx = Vx OR Vy
                    1 => self.registers[vx] = self.registers[vx] | self.registers[vy],
                    // 8xy2 - AND Vx, Vy - Set Vx = Vx AND Vy
                    2 => self.registers[vx] = self.registers[vx] & self.registers[vy],
                    // 8xy3 - XOR Vx, Vy - Set Vx = Vx XOR Vy
                    3 => self.registers[vx] = self.registers[vx] ^ self.registers[vy],
                    // 8xy4 - ADD Vx, Vy - Set Vx = Vx + Vy, set VF = carry
                    4 => {
                        let added = self.registers[vx] + self.registers[vy];
                        if added > 255 {
                            self.registers[vx] = 0xff;
                            self.registers[15] = 1;
                        } else {
                            self.registers[vx] = added;
                            self.registers[15] = 0;
                        }
                    },
                    // 8xy5 - SUB Vx, Vy - Set Vx = Vx - Vy, set VF = NOT borrow
                    5 => {
                        if self.registers[vx] > self.registers[vy] {
                            self.registers[15] = 1;
                        } else {
                            self.registers[15] = 0;
                        }
                        self.registers[vx] -= self.registers[vy];
                    },
                    // 8xy6 - SHR Vx {, Vy} - Set Vx = Vx SHR 1
                    6 => {
                        if self.registers[vx] & 1 == 1 {
                            self.registers[15] = 1;
                        } else {
                            self.registers[15] = 0;
                        }
                        self.registers[vx] /= 2;
                    },
                    // 8xy7 - SUBN Vx, Vy - Set Vx = Vy - Vx, set VF = NOT borrow
                    7 => {
                        if self.registers[vy] > self.registers[vx] {
                            self.registers[15] = 1;
                        } else {
                            self.registers[15] = 0;
                        }
                        self.registers[vx] -= self.registers[vy];
                    },
                    // 8xyE - SHL Vx {, Vy} - Set Vx = Vx SHL 1
                    14 => {
                        if self.registers[vx] > 127 {
                            self.registers[15] = 1;
                        } else {
                            self.registers[15] = 0;
                        }
                        self.registers[vx] *= 2;
                    },
                    _ => println!{"Unknown opcode: 0x{:X}", op},
                }
            },
            // 9xy0 - SNE Vx, Vy - Skip next instruction if Vx != Vy
            op @ 0x9000 ... 0x9ff0 if op % 16 == 0 => {
                let vy = ((op & 0x00f0) >> 4) as uint;
                let vx = ((op & 0x0f00) >> 8) as uint;
                if self.registers[vx] != self.registers[vy] {
                    self.pc += 2;
                }
            },
            // Unsupported
            op @ _ => println!("Unknown opcode: 0x{:X}", op),
        }
        // Execute
        // Increment the counter
        self.pc += 2;
        // Update timers
    }
}
<|endoftext|>


<commit_before>use consumer::*;
use producer::*;
use std::rc::Rc;
use stream::*;

/// Constructs a new empty `Stream` based on a `Empty`.
///
/// # Examples
///
/// ```
/// use asyncplify::*;
///
/// Empty
///     .subscribe();
/// ```
pub struct Empty;

impl Stream<()> for Empty {
    fn consume<C: Consumer<()>>(self, mut consumer: C) {
        consumer.init(Rc::new(Producer::new()));
    }
}

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

    #[test]
    fn it_works() {
        let mut count = 0;

        Empty.tap(|_| count += 1)
             .subscribe();

        assert!(count == 0, "count = {}", count);
    }
}
<commit_msg>add an example for Empty<commit_after>use consumer::*;
use producer::*;
use std::rc::Rc;
use stream::*;

/// Constructs a new empty `Stream` based on a `Empty`.
///
/// # Examples
///
/// ```
/// use asyncplify::*;
///
/// let mut count = 0;
///
/// Empty
///     .tap(|_| count += 1)
///     .subscribe();
///
/// assert!(count == 0, "count = {}", count);
/// ```
pub struct Empty;

impl Stream<()> for Empty {
    fn consume<C: Consumer<()>>(self, mut consumer: C) {
        consumer.init(Rc::new(Producer::new()));
    }
}<|endoftext|>


<commit_before>//! Error and Result module.
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;

use httparse;
use openssl::ssl::error::SslError;
use url;
use solicit::http::HttpError as Http2Error;

use self::Error::{
    Method,
    Uri,
    Version,
    Header,
    Status,
    Io,
    Ssl,
    TooLarge,
    Http2,
};

/// Result type often returned from methods that can have hyper `Error`s.
pub type Result<T> = ::std::result::Result<T, Error>;

/// A set of errors that can occur parsing HTTP streams.
#[derive(Debug)]
pub enum Error {
    /// An invalid `Method`, such as `GE,T`.
    Method,
    /// An invalid `RequestUri`, such as `exam ple.domain`.
    Uri(url::ParseError),
    /// An invalid `HttpVersion`, such as `HTP/1.1`
    Version,
    /// An invalid `Header`.
    Header,
    /// A message head is too large to be reasonable.
    TooLarge,
    /// An invalid `Status`, such as `1337 ELITE`.
    Status,
    /// An `io::Error` that occurred while trying to read or write to a network stream.
    Io(IoError),
    /// An error from the `openssl` library.
    Ssl(SslError),
    /// An HTTP/2-specific error, coming from the `solicit` library.
    Http2(Http2Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Method => "Invalid Method specified",
            Version => "Invalid HTTP version specified",
            Header => "Invalid Header provided",
            TooLarge => "Message head is too large",
            Status => "Invalid Status provided",
            Uri(ref e) => e.description(),
            Io(ref e) => e.description(),
            Ssl(ref e) => e.description(),
            Http2(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Io(ref error) => Some(error),
            Ssl(ref error) => Some(error),
            Uri(ref error) => Some(error),
            Http2(ref error) => Some(error),
            _ => None,
        }
    }
}

impl From<IoError> for Error {
    fn from(err: IoError) -> Error {
        Io(err)
    }
}

impl From<url::ParseError> for Error {
    fn from(err: url::ParseError) -> Error {
        Uri(err)
    }
}

impl From<SslError> for Error {
    fn from(err: SslError) -> Error {
        match err {
            SslError::StreamError(err) => Io(err),
            err => Ssl(err),
        }
    }
}

impl From<httparse::Error> for Error {
    fn from(err: httparse::Error) -> Error {
        match err {
            httparse::Error::HeaderName => Header,
            httparse::Error::HeaderValue => Header,
            httparse::Error::NewLine => Header,
            httparse::Error::Status => Status,
            httparse::Error::Token => Header,
            httparse::Error::TooManyHeaders => TooLarge,
            httparse::Error::Version => Version,
        }
    }
}

impl From<Http2Error> for Error {
    fn from(err: Http2Error) -> Error {
        Error::Http2(err)
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error as StdError;
    use std::io;
    use httparse;
    use openssl::ssl::error::SslError;
    use solicit::http::HttpError as Http2Error;
    use url;
    use super::Error;
    use super::Error::*;

    #[test]
    fn test_cause() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = Io(orig);
        assert_eq!(e.cause().unwrap().description(), desc);
    }

    macro_rules! from {
        ($from:expr => $error:pat) => {
            match Error::from($from) {
                e @ $error => {
                    assert!(e.description().len() > 5);
                } ,
                _ => panic!("{:?}", $from)
            }
        }
    }

    macro_rules! from_and_cause {
        ($from:expr => $error:pat) => {
            match Error::from($from) {
                e @ $error => {
                    let desc = e.cause().unwrap().description();
                    assert_eq!(desc, $from.description().to_owned());
                    assert_eq!(desc, e.description());
                },
                _ => panic!("{:?}", $from)
            }
        }
    }

    #[test]
    fn test_from() {

        from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => Io(..));
        from_and_cause!(url::ParseError::EmptyHost => Uri(..));
        from_and_cause!(SslError::SslSessionClosed => Ssl(..));
        from_and_cause!(Http2Error::UnknownStreamId => Http2(..));

        from!(SslError::StreamError(io::Error::new(io::ErrorKind::Other, "ssl negotiation")) => Io(..));

        from!(httparse::Error::HeaderName => Header);
        from!(httparse::Error::HeaderName => Header);
        from!(httparse::Error::HeaderValue => Header);
        from!(httparse::Error::NewLine => Header);
        from!(httparse::Error::Status => Status);
        from!(httparse::Error::Token => Header);
        from!(httparse::Error::TooManyHeaders => TooLarge);
        from!(httparse::Error::Version => Version);
    }
}
<commit_msg>feat(error): add private __Nonexhaustive variant to Error<commit_after>//! Error and Result module.
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;

use httparse;
use openssl::ssl::error::SslError;
use url;
use solicit::http::HttpError as Http2Error;

use self::Error::{
    Method,
    Uri,
    Version,
    Header,
    Status,
    Io,
    Ssl,
    TooLarge,
    Http2,
};

/// Result type often returned from methods that can have hyper `Error`s.
pub type Result<T> = ::std::result::Result<T, Error>;

/// A set of errors that can occur parsing HTTP streams.
#[derive(Debug)]
pub enum Error {
    /// An invalid `Method`, such as `GE,T`.
    Method,
    /// An invalid `RequestUri`, such as `exam ple.domain`.
    Uri(url::ParseError),
    /// An invalid `HttpVersion`, such as `HTP/1.1`
    Version,
    /// An invalid `Header`.
    Header,
    /// A message head is too large to be reasonable.
    TooLarge,
    /// An invalid `Status`, such as `1337 ELITE`.
    Status,
    /// An `io::Error` that occurred while trying to read or write to a network stream.
    Io(IoError),
    /// An error from the `openssl` library.
    Ssl(SslError),
    /// An HTTP/2-specific error, coming from the `solicit` library.
    Http2(Http2Error),

    #[doc(hidden)]
    __Nonexhaustive(Void)
}

#[doc(hidden)]
pub enum Void {}

impl fmt::Debug for Void {
    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
        match *self {}
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Method => "Invalid Method specified",
            Version => "Invalid HTTP version specified",
            Header => "Invalid Header provided",
            TooLarge => "Message head is too large",
            Status => "Invalid Status provided",
            Uri(ref e) => e.description(),
            Io(ref e) => e.description(),
            Ssl(ref e) => e.description(),
            Http2(ref e) => e.description(),
            Error::__Nonexhaustive(ref void) =>  match *void {}
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Io(ref error) => Some(error),
            Ssl(ref error) => Some(error),
            Uri(ref error) => Some(error),
            Http2(ref error) => Some(error),
            _ => None,
        }
    }
}

impl From<IoError> for Error {
    fn from(err: IoError) -> Error {
        Io(err)
    }
}

impl From<url::ParseError> for Error {
    fn from(err: url::ParseError) -> Error {
        Uri(err)
    }
}

impl From<SslError> for Error {
    fn from(err: SslError) -> Error {
        match err {
            SslError::StreamError(err) => Io(err),
            err => Ssl(err),
        }
    }
}

impl From<httparse::Error> for Error {
    fn from(err: httparse::Error) -> Error {
        match err {
            httparse::Error::HeaderName => Header,
            httparse::Error::HeaderValue => Header,
            httparse::Error::NewLine => Header,
            httparse::Error::Status => Status,
            httparse::Error::Token => Header,
            httparse::Error::TooManyHeaders => TooLarge,
            httparse::Error::Version => Version,
        }
    }
}

impl From<Http2Error> for Error {
    fn from(err: Http2Error) -> Error {
        Error::Http2(err)
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error as StdError;
    use std::io;
    use httparse;
    use openssl::ssl::error::SslError;
    use solicit::http::HttpError as Http2Error;
    use url;
    use super::Error;
    use super::Error::*;

    #[test]
    fn test_cause() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = Io(orig);
        assert_eq!(e.cause().unwrap().description(), desc);
    }

    macro_rules! from {
        ($from:expr => $error:pat) => {
            match Error::from($from) {
                e @ $error => {
                    assert!(e.description().len() > 5);
                } ,
                _ => panic!("{:?}", $from)
            }
        }
    }

    macro_rules! from_and_cause {
        ($from:expr => $error:pat) => {
            match Error::from($from) {
                e @ $error => {
                    let desc = e.cause().unwrap().description();
                    assert_eq!(desc, $from.description().to_owned());
                    assert_eq!(desc, e.description());
                },
                _ => panic!("{:?}", $from)
            }
        }
    }

    #[test]
    fn test_from() {

        from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => Io(..));
        from_and_cause!(url::ParseError::EmptyHost => Uri(..));
        from_and_cause!(SslError::SslSessionClosed => Ssl(..));
        from_and_cause!(Http2Error::UnknownStreamId => Http2(..));

        from!(SslError::StreamError(io::Error::new(io::ErrorKind::Other, "ssl negotiation")) => Io(..));

        from!(httparse::Error::HeaderName => Header);
        from!(httparse::Error::HeaderName => Header);
        from!(httparse::Error::HeaderValue => Header);
        from!(httparse::Error::NewLine => Header);
        from!(httparse::Error::Status => Status);
        from!(httparse::Error::Token => Header);
        from!(httparse::Error::TooManyHeaders => TooLarge);
        from!(httparse::Error::Version => Version);
    }
}
<|endoftext|>