<commit_before>use super::fitness::Fitness;
use super::traits::{Genotype, Distance};
use super::selection;
use rand::{Rng, Closed01};
use super::traits::Mate;
use std::marker::PhantomData;
use std::num::Zero;
use std::fmt::Debug;
use std::cmp;
use rayon::par_iter::*;
use super::prob::probabilistic_round;

#[derive(Debug)]
pub struct Individual<T: Debug> {
    fitness: Fitness,
    genome: Box<T>,
}

pub trait Rating {}
#[derive(Debug)]
pub struct Rated;
#[derive(Debug)]
pub struct Unrated;

impl Rating for Rated {}
impl Rating for Unrated {}

#[derive(Debug)]
pub struct Population<T: Genotype + Debug, R: Rating> {
    individuals: Vec<Individual<T>>,
    _marker: PhantomData<R>,
}

impl<T: Genotype + Debug, R: Rating> Population<T, R> {
    pub fn new() -> Population<T, R> {
        Population {
            individuals: Vec::new(),
            _marker: PhantomData,
        }
    }

    pub fn new_from_vec(v: Vec<Individual<T>>) -> Population<T, R> {
        Population {
            individuals: v,
            _marker: PhantomData,
        }
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }
}

impl<T: Genotype + Debug> Population<T, Unrated> {
    pub fn add_genome(&mut self, genome: Box<T>) {
        self.individuals.push(Individual {
            fitness: Zero::zero(),
            genome: genome,
        });
    }

    pub fn rate<F>(mut self, f: &F) -> Population<T, Rated>
        where F: Fn(&T) -> Fitness
    {
        for ind in self.individuals.iter_mut() {
            let fitness = f(&ind.genome);
            ind.fitness = fitness;
        }
        Population {
            individuals: self.individuals,
            _marker: PhantomData,
        }
    }

    pub fn rate_par<F>(mut self, f: &F) -> Population<T, Rated>
        where F: Sync + Fn(&T) -> Fitness
    {
        self.individuals.par_iter_mut().for_each(|ind| {
            let fitness = f(&ind.genome);
            ind.fitness = fitness;
        });

        Population {
            individuals: self.individuals,
            _marker: PhantomData,
        }
    }
}

impl<T: Genotype + Debug> Population<T, Rated> {
    pub fn add_individual(&mut self, ind: Individual<T>) {
        self.individuals.push(ind);
    }

    // Return true if genome at position `i` is better that `j`
    fn compare_ij(&self, i: usize, j: usize) -> bool {
        self.individuals[i].fitness > self.individuals[j].fitness
    }

    fn mean_fitness(&self) -> Fitness {
        let sum: Fitness = self.individuals.iter().map(|ind| ind.fitness).sum();
        sum / Fitness::new(self.len() as f64)
    }

    pub fn max_fitness(&self) -> Option<Fitness> {
        self.individuals.iter().max_by_key(|ind| ind.fitness).map(|i| i.fitness)
    }

    // higher value of fitness means that the individual is fitter.
    pub fn sort(mut self) -> Self {
        (&mut self.individuals).sort_by(|a, b| a.fitness.cmp(&b.fitness).reverse());
        self
    }

    /// Merge `self` with the first `n` individuals from population `other`.
    pub fn merge(&mut self, other: Population<T, Rated>, n: Option<usize>) {
        let len = other.individuals.len();
        self.individuals.extend(other.individuals.into_iter().take(n.unwrap_or(len)));
    }

    // We want to create a population of approximately `pop_size`. We do not care if there are
    // slightly more or slightly less individuals than that.
    //
    // 1. sort whole popluation into niches
    // 2. calculate the number of offspring for each niche.
    // 3. each niche produces offspring.
    //    - sort each niche according to the fitness value.
    //    - r% of the best genomes produce offspring
    //    - determine the elitist size. those are always copied into the new generation.
    //
    pub fn produce_offspring<C, M, R>(self,
                                      pop_size: usize,
                                      // how many of the best individuals of a niche are copied as-is into the
                                      // new population?
                                      elite_percentage: Closed01<f64>,
                                      // how many of the best individuals of a niche are selected for
                                      // reproduction?
                                      selection_percentage: Closed01<f64>,
                                      tournament_k: usize,
                                      compatibility_threshold: f64,
                                      compatibility: &C,
                                      mate: &mut M,
                                      rng: &mut R)
                                      -> (Population<T, Rated>, Population<T, Unrated>)
        where R: Rng,
              C: Distance<T>,
              M: Mate<T>
    {
        debug!("population size: {}", self.len());

        assert!(elite_percentage.0 <= selection_percentage.0); // XXX
        assert!(self.len() > 0);
        let niches = self.partition(rng, compatibility_threshold, compatibility);
        let num_niches = niches.len();

        debug!("number of niches: {}", num_niches);

        assert!(num_niches > 0);
        let total_mean: Fitness = niches.iter().map(|ind| ind.mean_fitness()).sum();
        assert!(total_mean.get() >= 0.0);

        let mut new_unrated_population: Population<T, Unrated> = Population::new();
        let mut new_rated_population: Population<T, Rated> = Population::new();

        for niche in niches.into_iter() {
            let percentage_of_population: f64 = if total_mean.get() == 0.0 {
                // all individuals have a fitness of 0.0.
                // we will equally allow each niche to procude offspring.
                1.0 / (num_niches as f64)
            } else {
                (niche.mean_fitness() / total_mean).get()
            };

            // calculate new size of niche, and size of elites, and selection size.
            assert!(percentage_of_population >= 0.0 && percentage_of_population <= 1.0);

            let niche_size = pop_size as f64 * percentage_of_population;

            // number of elitary individuals to copy from the old niche generation into the new.
            let elite_size =
                cmp::max(1,
                         probabilistic_round(niche_size * elite_percentage.0, rng) as usize);

            // number of offspring to produce.
            let offspring_size = probabilistic_round(niche_size * (1.0 - elite_percentage.0),
                                                     rng) as usize;

            // number of the best individuals to use for mating.
            let select_size = probabilistic_round(niche_size *
                                                  selection_percentage.0,
                                                  rng) as usize;

            let sorted_niche = niche.sort();

            let select_size = cmp::min(select_size, sorted_niche.len());

            // at first produce ```offspring_size``` individuals from the top ```select_size```
            // individuals.
            if select_size > 0 {
                let mut n = offspring_size;
                while n > 0 {
                    let parent1 = selection::tournament_selection_fast(rng,
                                                                       |i, j| {
                                                                           sorted_niche.compare_ij(i,j)
                                                                       },
                                                                       select_size,
                                                                       cmp::min(select_size,
                                                                                tournament_k));
                    let parent2 = selection::tournament_selection_fast(rng,
                                                                       |i, j| {
                                                                           sorted_niche.compare_ij(i,j)
                                                                       },
                                                                       select_size,
                                                                       cmp::min(select_size,
                                                                                tournament_k));

                    let offspring = mate.mate(&sorted_niche.individuals[parent1].genome,
                                              &sorted_niche.individuals[parent2].genome,
                                              rng);
                    new_unrated_population.add_genome(Box::new(offspring));
                    n -= 1;
                }
            }

            // now copy the elites
            new_rated_population.merge(sorted_niche, Some(elite_size));
        }

        return (new_rated_population, new_unrated_population);
    }

    // Partitions the whole population into species (niches)
    fn partition<R, C>(self,
                       rng: &mut R,
                       compatibility_threshold: f64,
                       compatibility: &C)
                       -> Vec<Population<T, Rated>>
        where R: Rng,
              C: Distance<T>
    {
        let mut niches: Vec<Population<T, Rated>> = Vec::new();

        'outer: for ind in self.individuals.into_iter() {
            for niche in niches.iter_mut() {
                // Is this genome compatible with this niche? Test against a random genome.
                let compatible = match rng.choose(&niche.individuals) {
                    Some(probe) => {
                        compatibility.distance(&probe.genome, &ind.genome) < compatibility_threshold
                    }
                    // If a niche is empty, a genome always is compatible (note that a niche can't be empyt)
                    None => true,
                };
                if compatible {
                    niche.add_individual(ind);
                    continue 'outer;
                }
            }
            // if no compatible niche was found, create a new niche containing this genome.
            let mut new_niche = Population::new();
            new_niche.add_individual(ind);
            niches.push(new_niche);
        }

        niches
    }
}

pub struct Runner<'a, T, C, M, F>
    where T: Genotype + Debug,
          C: Distance<T> + 'a,
          M: Mate<T> + 'a,
          F: Sync + Fn(&T) -> Fitness + 'a
{
    // anticipated population size
    pub pop_size: usize,
    // how many of the best individuals of a niche are copied as-is into the
    // new population?
    pub elite_percentage: Closed01<f64>,
    // how many of the best individuals of a niche are selected for
    // reproduction?
    pub selection_percentage: Closed01<f64>,
    pub tournament_k: usize,
    pub compatibility_threshold: f64,
    pub compatibility: &'a C,
    pub mate: &'a mut M,
    pub fitness: &'a F,
    pub _marker: PhantomData<T>,
}

impl<'a, T, C, M, F> Runner<'a, T, C, M, F>
    where T: Genotype + Debug,
          C: Distance<T> + 'a,
          M: Mate<T> + 'a,
          F: Sync + Fn(&T) -> Fitness + 'a
{
    pub fn run<R, G>(&mut self,
                     initial_pop: Population<T, Unrated>,
                     goal_condition: &G,
                     rng: &mut R)
                     -> (usize, Population<T, Rated>)
        where R: Rng,
              G: Fn(usize, &Population<T, Rated>) -> bool
    {
        let mut iteration: usize = 0;
        let mut current_rated_pop = initial_pop.rate_par(self.fitness);

        while !goal_condition(iteration, &current_rated_pop) {
            let (new_rated, new_unrated) =
                current_rated_pop.produce_offspring(self.pop_size,
                                                    Closed01(self.elite_percentage.0),
                                                    Closed01(self.selection_percentage.0),
                                                    self.tournament_k,
                                                    self.compatibility_threshold,
                                                    self.compatibility,
                                                    self.mate,
                                                    rng);

            current_rated_pop = new_rated;
            current_rated_pop.merge(new_unrated.rate_par(self.fitness), None);
            iteration += 1;
        }

        return (iteration, current_rated_pop);
    }
}
<commit_msg>Fix comment<commit_after>use super::fitness::Fitness;
use super::traits::{Genotype, Distance};
use super::selection;
use rand::{Rng, Closed01};
use super::traits::Mate;
use std::marker::PhantomData;
use std::num::Zero;
use std::fmt::Debug;
use std::cmp;
use rayon::par_iter::*;
use super::prob::probabilistic_round;

#[derive(Debug)]
pub struct Individual<T: Debug> {
    fitness: Fitness,
    genome: Box<T>,
}

pub trait Rating {}
#[derive(Debug)]
pub struct Rated;
#[derive(Debug)]
pub struct Unrated;

impl Rating for Rated {}
impl Rating for Unrated {}

#[derive(Debug)]
pub struct Population<T: Genotype + Debug, R: Rating> {
    individuals: Vec<Individual<T>>,
    _marker: PhantomData<R>,
}

impl<T: Genotype + Debug, R: Rating> Population<T, R> {
    pub fn new() -> Population<T, R> {
        Population {
            individuals: Vec::new(),
            _marker: PhantomData,
        }
    }

    pub fn new_from_vec(v: Vec<Individual<T>>) -> Population<T, R> {
        Population {
            individuals: v,
            _marker: PhantomData,
        }
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }
}

impl<T: Genotype + Debug> Population<T, Unrated> {
    pub fn add_genome(&mut self, genome: Box<T>) {
        self.individuals.push(Individual {
            fitness: Zero::zero(),
            genome: genome,
        });
    }

    pub fn rate<F>(mut self, f: &F) -> Population<T, Rated>
        where F: Fn(&T) -> Fitness
    {
        for ind in self.individuals.iter_mut() {
            let fitness = f(&ind.genome);
            ind.fitness = fitness;
        }
        Population {
            individuals: self.individuals,
            _marker: PhantomData,
        }
    }

    pub fn rate_par<F>(mut self, f: &F) -> Population<T, Rated>
        where F: Sync + Fn(&T) -> Fitness
    {
        self.individuals.par_iter_mut().for_each(|ind| {
            let fitness = f(&ind.genome);
            ind.fitness = fitness;
        });

        Population {
            individuals: self.individuals,
            _marker: PhantomData,
        }
    }
}

impl<T: Genotype + Debug> Population<T, Rated> {
    pub fn add_individual(&mut self, ind: Individual<T>) {
        self.individuals.push(ind);
    }

    // Return true if genome at position `i` is better that `j`
    fn compare_ij(&self, i: usize, j: usize) -> bool {
        self.individuals[i].fitness > self.individuals[j].fitness
    }

    fn mean_fitness(&self) -> Fitness {
        let sum: Fitness = self.individuals.iter().map(|ind| ind.fitness).sum();
        sum / Fitness::new(self.len() as f64)
    }

    pub fn max_fitness(&self) -> Option<Fitness> {
        self.individuals.iter().max_by_key(|ind| ind.fitness).map(|i| i.fitness)
    }

    // higher value of fitness means that the individual is fitter.
    pub fn sort(mut self) -> Self {
        (&mut self.individuals).sort_by(|a, b| a.fitness.cmp(&b.fitness).reverse());
        self
    }

    /// Merge `self` with the first `n` individuals from population `other`.
    pub fn merge(&mut self, other: Population<T, Rated>, n: Option<usize>) {
        let len = other.individuals.len();
        self.individuals.extend(other.individuals.into_iter().take(n.unwrap_or(len)));
    }

    // We want to create a population of approximately `pop_size`. We do not care if there are
    // slightly more or slightly less individuals than that.
    //
    // 1. sort whole popluation into niches
    // 2. calculate the number of offspring for each niche.
    // 3. each niche produces offspring.
    //    - sort each niche according to the fitness value.
    //    - r% of the best genomes produce offspring
    //    - determine the elitist size. those are always copied into the new generation.
    //
    pub fn produce_offspring<C, M, R>(self,
                                      pop_size: usize,
                                      // how many of the best individuals of a niche are copied as-is into the
                                      // new population?
                                      elite_percentage: Closed01<f64>,
                                      // how many of the best individuals of a niche are selected for
                                      // reproduction?
                                      selection_percentage: Closed01<f64>,
                                      tournament_k: usize,
                                      compatibility_threshold: f64,
                                      compatibility: &C,
                                      mate: &mut M,
                                      rng: &mut R)
                                      -> (Population<T, Rated>, Population<T, Unrated>)
        where R: Rng,
              C: Distance<T>,
              M: Mate<T>
    {
        debug!("population size: {}", self.len());

        assert!(elite_percentage.0 <= selection_percentage.0); // XXX
        assert!(self.len() > 0);
        let niches = self.partition(rng, compatibility_threshold, compatibility);
        let num_niches = niches.len();

        debug!("number of niches: {}", num_niches);

        assert!(num_niches > 0);
        let total_mean: Fitness = niches.iter().map(|ind| ind.mean_fitness()).sum();
        assert!(total_mean.get() >= 0.0);

        let mut new_unrated_population: Population<T, Unrated> = Population::new();
        let mut new_rated_population: Population<T, Rated> = Population::new();

        for niche in niches.into_iter() {
            let percentage_of_population: f64 = if total_mean.get() == 0.0 {
                // all individuals have a fitness of 0.0.
                // we will equally allow each niche to procude offspring.
                1.0 / (num_niches as f64)
            } else {
                (niche.mean_fitness() / total_mean).get()
            };

            // calculate new size of niche, and size of elites, and selection size.
            assert!(percentage_of_population >= 0.0 && percentage_of_population <= 1.0);

            let niche_size = pop_size as f64 * percentage_of_population;

            // number of elitary individuals to copy from the old niche generation into the new.
            let elite_size =
                cmp::max(1,
                         probabilistic_round(niche_size * elite_percentage.0, rng) as usize);

            // number of offspring to produce.
            let offspring_size = probabilistic_round(niche_size * (1.0 - elite_percentage.0),
                                                     rng) as usize;

            // number of the best individuals to use for mating.
            let select_size = probabilistic_round(niche_size *
                                                  selection_percentage.0,
                                                  rng) as usize;

            let sorted_niche = niche.sort();

            let select_size = cmp::min(select_size, sorted_niche.len());

            // at first produce `offspring_size` individuals from the top `select_size`
            // individuals.
            if select_size > 0 {
                let mut n = offspring_size;
                while n > 0 {
                    let parent1 = selection::tournament_selection_fast(rng,
                                                                       |i, j| {
                                                                           sorted_niche.compare_ij(i,j)
                                                                       },
                                                                       select_size,
                                                                       cmp::min(select_size,
                                                                                tournament_k));
                    let parent2 = selection::tournament_selection_fast(rng,
                                                                       |i, j| {
                                                                           sorted_niche.compare_ij(i,j)
                                                                       },
                                                                       select_size,
                                                                       cmp::min(select_size,
                                                                                tournament_k));

                    let offspring = mate.mate(&sorted_niche.individuals[parent1].genome,
                                              &sorted_niche.individuals[parent2].genome,
                                              rng);
                    new_unrated_population.add_genome(Box::new(offspring));
                    n -= 1;
                }
            }

            // now copy the elites
            new_rated_population.merge(sorted_niche, Some(elite_size));
        }

        return (new_rated_population, new_unrated_population);
    }

    // Partitions the whole population into species (niches)
    fn partition<R, C>(self,
                       rng: &mut R,
                       compatibility_threshold: f64,
                       compatibility: &C)
                       -> Vec<Population<T, Rated>>
        where R: Rng,
              C: Distance<T>
    {
        let mut niches: Vec<Population<T, Rated>> = Vec::new();

        'outer: for ind in self.individuals.into_iter() {
            for niche in niches.iter_mut() {
                // Is this genome compatible with this niche? Test against a random genome.
                let compatible = match rng.choose(&niche.individuals) {
                    Some(probe) => {
                        compatibility.distance(&probe.genome, &ind.genome) < compatibility_threshold
                    }
                    // If a niche is empty, a genome always is compatible (note that a niche can't be empyt)
                    None => true,
                };
                if compatible {
                    niche.add_individual(ind);
                    continue 'outer;
                }
            }
            // if no compatible niche was found, create a new niche containing this genome.
            let mut new_niche = Population::new();
            new_niche.add_individual(ind);
            niches.push(new_niche);
        }

        niches
    }
}

pub struct Runner<'a, T, C, M, F>
    where T: Genotype + Debug,
          C: Distance<T> + 'a,
          M: Mate<T> + 'a,
          F: Sync + Fn(&T) -> Fitness + 'a
{
    // anticipated population size
    pub pop_size: usize,
    // how many of the best individuals of a niche are copied as-is into the
    // new population?
    pub elite_percentage: Closed01<f64>,
    // how many of the best individuals of a niche are selected for
    // reproduction?
    pub selection_percentage: Closed01<f64>,
    pub tournament_k: usize,
    pub compatibility_threshold: f64,
    pub compatibility: &'a C,
    pub mate: &'a mut M,
    pub fitness: &'a F,
    pub _marker: PhantomData<T>,
}

impl<'a, T, C, M, F> Runner<'a, T, C, M, F>
    where T: Genotype + Debug,
          C: Distance<T> + 'a,
          M: Mate<T> + 'a,
          F: Sync + Fn(&T) -> Fitness + 'a
{
    pub fn run<R, G>(&mut self,
                     initial_pop: Population<T, Unrated>,
                     goal_condition: &G,
                     rng: &mut R)
                     -> (usize, Population<T, Rated>)
        where R: Rng,
              G: Fn(usize, &Population<T, Rated>) -> bool
    {
        let mut iteration: usize = 0;
        let mut current_rated_pop = initial_pop.rate_par(self.fitness);

        while !goal_condition(iteration, &current_rated_pop) {
            let (new_rated, new_unrated) =
                current_rated_pop.produce_offspring(self.pop_size,
                                                    Closed01(self.elite_percentage.0),
                                                    Closed01(self.selection_percentage.0),
                                                    self.tournament_k,
                                                    self.compatibility_threshold,
                                                    self.compatibility,
                                                    self.mate,
                                                    rng);

            current_rated_pop = new_rated;
            current_rated_pop.merge(new_unrated.rate_par(self.fitness), None);
            iteration += 1;
        }

        return (iteration, current_rated_pop);
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::{Peek, Poke};
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, Vector2D};

unsafe impl<T: Poke, U> Poke for Point2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        2 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.x.poke_into(bytes);
        let bytes = self.y.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Point2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).x);
        let bytes = T::peek_from(bytes, &mut (*output).y);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for Rect<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        Point2D::<T, U>::max_size() + Size2D::<T, U>::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.origin.poke_into(bytes);
        let bytes = self.size.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Rect<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).origin);
        let bytes = Size2D::<T, U>::peek_from(bytes, &mut (*output).size);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for SideOffsets2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        4 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.top.poke_into(bytes);
        let bytes = self.right.poke_into(bytes);
        let bytes = self.bottom.poke_into(bytes);
        let bytes = self.left.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for SideOffsets2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).top);
        let bytes = T::peek_from(bytes, &mut (*output).right);
        let bytes = T::peek_from(bytes, &mut (*output).bottom);
        let bytes = T::peek_from(bytes, &mut (*output).left);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for Size2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        2 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.width.poke_into(bytes);
        let bytes = self.height.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Size2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).width);
        let bytes = T::peek_from(bytes, &mut (*output).height);
        bytes
    }
}

unsafe impl<T: Poke, S, D> Poke for Transform3D<T, S, D> {
    #[inline(always)]
    fn max_size() -> usize {
        16 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.m11.poke_into(bytes);
        let bytes = self.m12.poke_into(bytes);
        let bytes = self.m13.poke_into(bytes);
        let bytes = self.m14.poke_into(bytes);
        let bytes = self.m21.poke_into(bytes);
        let bytes = self.m22.poke_into(bytes);
        let bytes = self.m23.poke_into(bytes);
        let bytes = self.m24.poke_into(bytes);
        let bytes = self.m31.poke_into(bytes);
        let bytes = self.m32.poke_into(bytes);
        let bytes = self.m33.poke_into(bytes);
        let bytes = self.m34.poke_into(bytes);
        let bytes = self.m41.poke_into(bytes);
        let bytes = self.m42.poke_into(bytes);
        let bytes = self.m43.poke_into(bytes);
        let bytes = self.m44.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, S, D> Peek for Transform3D<T, S, D> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).m11);
        let bytes = T::peek_from(bytes, &mut (*output).m12);
        let bytes = T::peek_from(bytes, &mut (*output).m13);
        let bytes = T::peek_from(bytes, &mut (*output).m14);
        let bytes = T::peek_from(bytes, &mut (*output).m21);
        let bytes = T::peek_from(bytes, &mut (*output).m22);
        let bytes = T::peek_from(bytes, &mut (*output).m23);
        let bytes = T::peek_from(bytes, &mut (*output).m24);
        let bytes = T::peek_from(bytes, &mut (*output).m31);
        let bytes = T::peek_from(bytes, &mut (*output).m32);
        let bytes = T::peek_from(bytes, &mut (*output).m33);
        let bytes = T::peek_from(bytes, &mut (*output).m34);
        let bytes = T::peek_from(bytes, &mut (*output).m41);
        let bytes = T::peek_from(bytes, &mut (*output).m42);
        let bytes = T::peek_from(bytes, &mut (*output).m43);
        let bytes = T::peek_from(bytes, &mut (*output).m44);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for Vector2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        2 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.x.poke_into(bytes);
        let bytes = self.y.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Vector2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).x);
        let bytes = T::peek_from(bytes, &mut (*output).y);
        bytes
    }
}
<commit_msg>Bug 1711648 - Implement Peek and Poke for euclid::Box2D. r=gfx-reviewers,jrmuizel<commit_after>// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::{Peek, Poke};
use euclid::{Point2D, Rect, Box2D, SideOffsets2D, Size2D, Transform3D, Vector2D};

unsafe impl<T: Poke, U> Poke for Point2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        2 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.x.poke_into(bytes);
        let bytes = self.y.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Point2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).x);
        let bytes = T::peek_from(bytes, &mut (*output).y);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for Rect<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        Point2D::<T, U>::max_size() + Size2D::<T, U>::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.origin.poke_into(bytes);
        let bytes = self.size.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Rect<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).origin);
        let bytes = Size2D::<T, U>::peek_from(bytes, &mut (*output).size);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for Box2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        Point2D::<T, U>::max_size() * 2
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.min.poke_into(bytes);
        let bytes = self.max.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Box2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).min);
        let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).max);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for SideOffsets2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        4 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.top.poke_into(bytes);
        let bytes = self.right.poke_into(bytes);
        let bytes = self.bottom.poke_into(bytes);
        let bytes = self.left.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for SideOffsets2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).top);
        let bytes = T::peek_from(bytes, &mut (*output).right);
        let bytes = T::peek_from(bytes, &mut (*output).bottom);
        let bytes = T::peek_from(bytes, &mut (*output).left);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for Size2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        2 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.width.poke_into(bytes);
        let bytes = self.height.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Size2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).width);
        let bytes = T::peek_from(bytes, &mut (*output).height);
        bytes
    }
}

unsafe impl<T: Poke, S, D> Poke for Transform3D<T, S, D> {
    #[inline(always)]
    fn max_size() -> usize {
        16 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.m11.poke_into(bytes);
        let bytes = self.m12.poke_into(bytes);
        let bytes = self.m13.poke_into(bytes);
        let bytes = self.m14.poke_into(bytes);
        let bytes = self.m21.poke_into(bytes);
        let bytes = self.m22.poke_into(bytes);
        let bytes = self.m23.poke_into(bytes);
        let bytes = self.m24.poke_into(bytes);
        let bytes = self.m31.poke_into(bytes);
        let bytes = self.m32.poke_into(bytes);
        let bytes = self.m33.poke_into(bytes);
        let bytes = self.m34.poke_into(bytes);
        let bytes = self.m41.poke_into(bytes);
        let bytes = self.m42.poke_into(bytes);
        let bytes = self.m43.poke_into(bytes);
        let bytes = self.m44.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, S, D> Peek for Transform3D<T, S, D> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).m11);
        let bytes = T::peek_from(bytes, &mut (*output).m12);
        let bytes = T::peek_from(bytes, &mut (*output).m13);
        let bytes = T::peek_from(bytes, &mut (*output).m14);
        let bytes = T::peek_from(bytes, &mut (*output).m21);
        let bytes = T::peek_from(bytes, &mut (*output).m22);
        let bytes = T::peek_from(bytes, &mut (*output).m23);
        let bytes = T::peek_from(bytes, &mut (*output).m24);
        let bytes = T::peek_from(bytes, &mut (*output).m31);
        let bytes = T::peek_from(bytes, &mut (*output).m32);
        let bytes = T::peek_from(bytes, &mut (*output).m33);
        let bytes = T::peek_from(bytes, &mut (*output).m34);
        let bytes = T::peek_from(bytes, &mut (*output).m41);
        let bytes = T::peek_from(bytes, &mut (*output).m42);
        let bytes = T::peek_from(bytes, &mut (*output).m43);
        let bytes = T::peek_from(bytes, &mut (*output).m44);
        bytes
    }
}

unsafe impl<T: Poke, U> Poke for Vector2D<T, U> {
    #[inline(always)]
    fn max_size() -> usize {
        2 * T::max_size()
    }
    #[inline(always)]
    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
        let bytes = self.x.poke_into(bytes);
        let bytes = self.y.poke_into(bytes);
        bytes
    }
}
impl<T: Peek, U> Peek for Vector2D<T, U> {
    #[inline(always)]
    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
        let bytes = T::peek_from(bytes, &mut (*output).x);
        let bytes = T::peek_from(bytes, &mut (*output).y);
        bytes
    }
}
<|endoftext|>


<commit_before>//#![feature(libc)]
mod report_test;
mod telldus;
mod sender;
mod receiver;
mod config;
mod internaltypes;

use std::sync::mpsc::channel;
use std::thread;

#[allow(dead_code)]
pub fn main() {
	//uncomment to write new config. useful when changing the config signature
	//config::write_config(); return;
	//uncomment to write an extmsg::Message to stdout
	//extmsg::write_message(); return;

	let config = config::read_config().unwrap();
	telldus::init();

	let (tx, rx) = channel();
	let timertx = tx.clone();

	let recv_handle = receiver::start(config.receiver_port, config.password, tx);
	let send_handle = sender::start(config.clients, rx);
	// regular updates are initiated here. a simple timer which notifies the sender
	let update_thread = thread::spawn(move || {
		loop {
			timertx.send(internaltypes::SenderAction::Update).unwrap();
			thread::sleep_ms(5000 as u32);
		}
	});
	recv_handle.join().unwrap();
	send_handle.join().unwrap();
	update_thread.join().unwrap();
	telldus::close();
}

#[test]
fn test_retvalue() {
	assert!(main::retvalue()==2);
}
<commit_msg>Added use of extmsg. Small bug after rewrite<commit_after>//#![feature(libc)]
mod report_test;
mod telldus;
mod sender;
mod receiver;
mod config;
mod internaltypes;

use std::sync::mpsc::channel;
use std::thread;
use common::extmsg;

#[allow(dead_code)]
pub fn main() {
	//uncomment to write new config. useful when changing the config signature
	//config::write_config(); return;
	//uncomment to write an extmsg::Message to stdout
	//extmsg::write_message(); return;

	let config = config::read_config().unwrap();
	telldus::init();

	let (tx, rx) = channel();
	let timertx = tx.clone();

	let recv_handle = receiver::start(config.receiver_port, config.password, tx);
	let send_handle = sender::start(config.clients, rx);
	// regular updates are initiated here. a simple timer which notifies the sender
	let update_thread = thread::spawn(move || {
		loop {
			timertx.send(internaltypes::SenderAction::Update).unwrap();
			thread::sleep_ms(5000 as u32);
		}
	});
	recv_handle.join().unwrap();
	send_handle.join().unwrap();
	update_thread.join().unwrap();
	telldus::close();
}

#[test]
fn test_retvalue() {
	assert!(main::retvalue()==2);
}
<|endoftext|>


<commit_before>#![feature(alloc)]
extern crate alloc;

use alloc::heap;
use std::mem;
use std::ops::{Add,Sub,Mul,Div};

pub static B: u64 = 1;
pub static KB: u64 = 1000;
pub static MB: u64 = 1000000;
pub static GB: u64 = 1000000000;
pub static TB: u64 = 1000000000000;
pub static PB: u64 = 1000000000000000;

#[derive(Debug)]
struct ByteSize {
  size: u64
}

impl ByteSize {
  #[inline(always)]
  pub fn b(size: u64) -> ByteSize {
    ByteSize {size: size}
  }

  #[inline(always)]
  pub fn kb(size: u64) -> ByteSize {
    ByteSize {size: size * KB}
  }

  #[inline(always)]
  pub fn mb(size: u64) -> ByteSize {
    ByteSize {size: size * MB}
  }

  #[inline(always)]
  pub fn gb(size: u64) -> ByteSize {
    ByteSize {size: size * GB}
  }

  #[inline(always)]
  pub fn tb(size: u64) -> ByteSize {
    ByteSize {size: size * TB}
  }

  #[inline(always)]
  pub fn pb(size: u64) -> ByteSize {
    ByteSize {size: size * PB}
  }

  #[inline(always)]
  pub fn as_u64(self) -> u64 {
    self.size
  }

  #[inline(always)]
  pub fn as_usize(self) -> usize {
    self.size as usize
  }
}

impl Add<u64> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn add(self, rhs: u64) -> ByteSize {
    ByteSize {size: (self.size + rhs)}
  }
}

impl Add<ByteSize> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn add(self, rhs: ByteSize) -> ByteSize {
    ByteSize {size: (self.size + rhs.size)}
  }
}

impl Sub<u64> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn sub(self, rhs: u64) -> ByteSize {
    ByteSize {size: (self.size + rhs)}
  }
}

impl Sub<ByteSize> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn sub(self, rhs: ByteSize) -> ByteSize {
    ByteSize {size: (self.size + rhs.size)}
  }
}

impl Mul<u64> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn mul(self, rhs: u64) -> ByteSize {
    ByteSize {size: (self.size * rhs)}
  }
}

impl Div<u64> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn div(self, rhs: u64) -> ByteSize {
    ByteSize {size: (self.size / rhs)}
  }
}

#[derive(Debug, Clone, Copy)]
struct Buf {
  ptr: usize,
  limit: usize
}

trait UnSafeDatumWriter {
  fn write_bool(&mut self, value: bool);
  fn write_i8  (&mut self, value: i8);
  fn write_i16 (&mut self, value: i16);
  fn write_i32 (&mut self, value: i32);
  fn write_i64 (&mut self, value: i64);
  fn write_f32 (&mut self, value: f32);
  fn write_f64 (&mut self, value: f64);
}

trait UnSafeDatumReader {
  fn read_bool(&mut self) -> bool;
  fn read_i8  (&mut self) -> i8;
  fn read_i16 (&mut self) -> i16;
  fn read_i32 (&mut self) -> i32;
  fn read_i64 (&mut self) -> i64;
  fn read_f32 (&mut self) -> f32;
  fn read_f64 (&mut self) -> f64;
}

impl UnSafeDatumWriter for Buf {

  fn write_bool(&mut self, value: bool) {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    unsafe {
      *(self.ptr as *mut i8) = value as i8;
    }

    self.ptr += mem::size_of::<i8>();
  }
  fn write_i8  (&mut self, value: i8) {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    unsafe {
      *(self.ptr as *mut i8) = value;
    }

    self.ptr += mem::size_of::<i8>();
  }

  fn write_i16 (&mut self, value: i16) {
    debug_assert!((self.ptr + mem::size_of::<i16>()) <= self.limit, "buffer overrun");

    unsafe {
      *(self.ptr as *mut i16) = value;
    }

    self.ptr += mem::size_of::<i16>();
  }

  fn write_i32 (&mut self, value: i32) {
    debug_assert!((self.ptr + mem::size_of::<i32>()) <= self.limit, "buffer overrun");

    unsafe {
      *(self.ptr as *mut i32) = value;
    }

    self.ptr += mem::size_of::<i32>();
  }

  fn write_i64 (&mut self, value: i64) {
    debug_assert!((self.ptr + mem::size_of::<i64>()) <= self.limit, "buffer overrun");

    unsafe {
      *(self.ptr as *mut i64) = value as i64;
    }

    self.ptr += mem::size_of::<i64>();
  }

  fn write_f32 (&mut self, value: f32) {
    debug_assert!((self.ptr + mem::size_of::<f32>()) <= self.limit, "buffer overrun");

    unsafe {
      *(self.ptr as *mut f32) = value;
    }

    self.ptr += mem::size_of::<i32>();
  }

  fn write_f64 (&mut self, value: f64) {
    debug_assert!((self.ptr + mem::size_of::<f64>()) <= self.limit, "buffer overrun");

    unsafe {
      *(self.ptr as *mut f64) = value;
    }

    self.ptr += mem::size_of::<f64>();
  }
}

impl UnSafeDatumReader for Buf {
  fn read_bool(&mut self) -> bool {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i8>();

    unsafe {
      *(ptr as *const bool)
    }
  }
  fn read_i8(&mut self) -> i8 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i8>();

    unsafe {
      *(ptr as *const i8)
    }
  }
  fn read_i16(&mut self) -> i16 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i16>();

    unsafe {
      *(ptr as *const i16)
    }
  }
  fn read_i32(&mut self) -> i32 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i32>();

    unsafe {
      *(ptr as *const i32)
    }
  }
  fn read_i64(&mut self) -> i64 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i64>();

    unsafe {
      *(ptr as *const i64)
    }
  }
  fn read_f32(&mut self) -> f32 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<f32>();

    unsafe {
      *(ptr as *const f32)
    }
  }
  fn read_f64 (&mut self) -> f64 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit, "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<f64>();

    unsafe {
      *(ptr as *const f64)
    }
  }
}

struct Chunk {
  ptr: *const u8,
  len: usize
}

struct Arena {
  init_size: usize,
  page_size: usize,
  chunk: *mut Chunk,
  chunks: Vec<*const Chunk>
}

impl Arena {
  // pub fn new() -> Arena {

  //   chunk

  //   Arena {
  //     init_size: 4 * KB,
  //     increase_size: 4 * KB,
  //   }
  // }

  // pub fn new_with_increase_size(init_size: usize, increase_size: usize) -> Arena {

  // }

  pub fn alloc(size: usize) -> Buf {
    let ptr: *mut u8 = unsafe {
      heap::allocate(size, 16) as *mut u8
    };

    if ptr.is_null() { alloc::oom() }

    Buf {
      ptr: ptr as usize,
      limit: (ptr as usize + size)
    }
  }

  fn grow(&self) {

  }
}

#[test]
fn test_buf_read_write() {
  let mut buf = Arena::alloc(ByteSize::kb(16).as_usize());
  let mut copy = buf;

  buf.write_bool(true);
  buf.write_i8(1);
  buf.write_i16(9);
  buf.write_i32(8);
  buf.write_i64(0);
  buf.write_f32(4.0);
  buf.write_f64(1.0);

  assert_eq!(copy.read_bool(), true);
  assert_eq!(copy.read_i8(), 1);
  assert_eq!(copy.read_i16(), 9);
  assert_eq!(copy.read_i32(), 8);
  assert_eq!(copy.read_i64(), 0);
  assert_eq!(copy.read_f32(), 4 as f32);
  assert_eq!(copy.read_f64(), 1 as f64);
}

#[test]
#[should_panic(expected = "buffer overrun")]
fn test_write_buf_overrun() {
  let mut buf = Arena::alloc(ByteSize::b(16).as_usize());

  buf.write_i32(1);
  buf.write_i32(2);
  buf.write_i32(3);
  buf.write_i32(4);
  buf.write_i32(4); // this write exceeds allocated buffer size
}<commit_msg>Implement initial arena version.<commit_after>#![feature(alloc)]
extern crate alloc;

use alloc::heap;
use std::mem;
use std::ops::{Add,Sub,Mul,Div};

pub static B: u64 = 1;
pub static KB: u64 = 1000;
pub static MB: u64 = 1000000;
pub static GB: u64 = 1000000000;
pub static TB: u64 = 1000000000000;
pub static PB: u64 = 1000000000000000;

#[derive(Debug)]
struct ByteSize {
  size: u64
}

impl ByteSize {
  #[inline(always)]
  pub fn b(size: u64) -> ByteSize {
    ByteSize {size: size}
  }

  #[inline(always)]
  pub fn kb(size: u64) -> ByteSize {
    ByteSize {size: size * KB}
  }

  #[inline(always)]
  pub fn mb(size: u64) -> ByteSize {
    ByteSize {size: size * MB}
  }

  #[inline(always)]
  pub fn gb(size: u64) -> ByteSize {
    ByteSize {size: size * GB}
  }

  #[inline(always)]
  pub fn tb(size: u64) -> ByteSize {
    ByteSize {size: size * TB}
  }

  #[inline(always)]
  pub fn pb(size: u64) -> ByteSize {
    ByteSize {size: size * PB}
  }

  #[inline(always)]
  pub fn as_u64(self) -> u64 {
    self.size
  }

  #[inline(always)]
  pub fn as_usize(self) -> usize {
    self.size as usize
  }
}

impl Add<u64> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn add(self, rhs: u64) -> ByteSize {
    ByteSize {size: (self.size + rhs)}
  }
}

impl Add<ByteSize> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn add(self, rhs: ByteSize) -> ByteSize {
    ByteSize {size: (self.size + rhs.size)}
  }
}

impl Sub<u64> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn sub(self, rhs: u64) -> ByteSize {
    ByteSize {size: (self.size + rhs)}
  }
}

impl Sub<ByteSize> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn sub(self, rhs: ByteSize) -> ByteSize {
    ByteSize {size: (self.size + rhs.size)}
  }
}

impl Mul<u64> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn mul(self, rhs: u64) -> ByteSize {
    ByteSize {size: (self.size * rhs)}
  }
}

impl Div<u64> for ByteSize {
  type Output = ByteSize;

  #[inline(always)]
  fn div(self, rhs: u64) -> ByteSize {
    ByteSize {size: (self.size / rhs)}
  }
}

#[derive(Debug, Clone, Copy)]
pub struct Buf {
  ptr: usize,
  limit: usize
}

trait UnSafeDatumWriter {
  fn write_bool(&mut self, value: bool);
  fn write_i8  (&mut self, value: i8);
  fn write_i16 (&mut self, value: i16);
  fn write_i32 (&mut self, value: i32);
  fn write_i64 (&mut self, value: i64);
  fn write_f32 (&mut self, value: f32);
  fn write_f64 (&mut self, value: f64);
}

trait UnSafeDatumReader {
  fn read_bool(&mut self) -> bool;
  fn read_i8  (&mut self) -> i8;
  fn read_i16 (&mut self) -> i16;
  fn read_i32 (&mut self) -> i32;
  fn read_i64 (&mut self) -> i64;
  fn read_f32 (&mut self) -> f32;
  fn read_f64 (&mut self) -> f64;
}

impl UnSafeDatumWriter for Buf {

  fn write_bool(&mut self, value: bool) {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    unsafe {
      *(self.ptr as *mut i8) = value as i8;
    }

    self.ptr += mem::size_of::<i8>();
  }
  fn write_i8  (&mut self, value: i8) {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    unsafe {
      *(self.ptr as *mut i8) = value;
    }

    self.ptr += mem::size_of::<i8>();
  }

  fn write_i16 (&mut self, value: i16) {
    debug_assert!((self.ptr + mem::size_of::<i16>()) <= self.limit,
      "buffer overrun");

    unsafe {
      *(self.ptr as *mut i16) = value;
    }

    self.ptr += mem::size_of::<i16>();
  }

  fn write_i32 (&mut self, value: i32) {
    debug_assert!((self.ptr + mem::size_of::<i32>()) <= self.limit,
      "buffer overrun");

    unsafe {
      *(self.ptr as *mut i32) = value;
    }

    self.ptr += mem::size_of::<i32>();
  }

  fn write_i64 (&mut self, value: i64) {
    debug_assert!((self.ptr + mem::size_of::<i64>()) <= self.limit,
      "buffer overrun");

    unsafe {
      *(self.ptr as *mut i64) = value as i64;
    }

    self.ptr += mem::size_of::<i64>();
  }

  fn write_f32 (&mut self, value: f32) {
    debug_assert!((self.ptr + mem::size_of::<f32>()) <= self.limit,
      "buffer overrun");

    unsafe {
      *(self.ptr as *mut f32) = value;
    }

    self.ptr += mem::size_of::<i32>();
  }

  fn write_f64 (&mut self, value: f64) {
    debug_assert!((self.ptr + mem::size_of::<f64>()) <= self.limit,
      "buffer overrun");

    unsafe {
      *(self.ptr as *mut f64) = value;
    }

    self.ptr += mem::size_of::<f64>();
  }
}

impl UnSafeDatumReader for Buf {
  fn read_bool(&mut self) -> bool {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i8>();

    unsafe {
      *(ptr as *const bool)
    }
  }

  fn read_i8(&mut self) -> i8 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i8>();

    unsafe {
      *(ptr as *const i8)
    }
  }
  fn read_i16(&mut self) -> i16 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i16>();

    unsafe {
      *(ptr as *const i16)
    }
  }
  fn read_i32(&mut self) -> i32 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i32>();

    unsafe {
      *(ptr as *const i32)
    }
  }
  fn read_i64(&mut self) -> i64 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<i64>();

    unsafe {
      *(ptr as *const i64)
    }
  }
  fn read_f32(&mut self) -> f32 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<f32>();

    unsafe {
      *(ptr as *const f32)
    }
  }
  fn read_f64 (&mut self) -> f64 {
    debug_assert!((self.ptr + mem::size_of::<i8>()) <= self.limit,
      "buffer overrun");

    let ptr = self.ptr;
    self.ptr += mem::size_of::<f64>();

    unsafe {
      *(ptr as *const f64)
    }
  }
}

#[derive(Copy, Clone)]
struct Chunk {
  #[allow(raw_pointer_derive)]
  ptr: *const u8,
}

pub struct Arena {
  page_size: usize,
  chunk: Chunk,
  offset: usize,
  chunks: Vec<Chunk>
}

impl Arena {
  pub fn new(page_size: usize) -> Arena {

    let allocated: *mut u8 = unsafe {
      heap::allocate(page_size, 16) as *mut u8
    };

    let first_chunk = Chunk{ptr: allocated};

    Arena {
      page_size: page_size,
      chunk: first_chunk,
      offset: 0,
      chunks: Vec::new()
    }
  }

  pub fn alloc(&mut self, size: usize) -> Buf {
    if !self.ensure_alloc(size) {
      self.new_chunk();
    }

    let addr = self.chunk.ptr as usize;
    let offset = addr + size;
    Buf {ptr: addr, limit: offset}
  }

  fn ensure_alloc(&self, size: usize) -> bool {
    (self.page_size - self.offset) <= size
  }

  fn new_chunk(&mut self) {

    let allocated: *mut u8 = unsafe {
      heap::allocate(self.page_size, 16) as *mut u8
    };

    if allocated.is_null() { alloc::oom() }

    let last_chunk = self.chunk;
    self.offset = 0;
    self.chunks.push(last_chunk);
    self.chunk = Chunk{ptr: allocated};
  }
}

#[test]
fn test_buf_read_write() {
  let mut arena = Arena::new(ByteSize::kb(16).as_usize());
  let mut buf = arena.alloc(ByteSize::kb(1).as_usize());
  let mut copy = buf;

  buf.write_bool(true);
  buf.write_i8(1);
  buf.write_i16(9);
  buf.write_i32(8);
  buf.write_i64(0);
  buf.write_f32(4.0);
  buf.write_f64(1.0);

  assert_eq!(copy.read_bool(), true);
  assert_eq!(copy.read_i8(), 1);
  assert_eq!(copy.read_i16(), 9);
  assert_eq!(copy.read_i32(), 8);
  assert_eq!(copy.read_i64(), 0);
  assert_eq!(copy.read_f32(), 4 as f32);
  assert_eq!(copy.read_f64(), 1 as f64);
}

#[test]
#[should_panic(expected = "buffer overrun")]
fn test_write_buf_overrun() {
  let mut arena = Arena::new(ByteSize::kb(16).as_usize());
  let mut buf = arena.alloc(ByteSize::b(16).as_usize());

  buf.write_i32(1);
  buf.write_i32(2);
  buf.write_i32(3);
  buf.write_i32(4);
  buf.write_i32(4); // this write exceeds allocated buffer size
}<|endoftext|>


<commit_before>#[derive(Clone)]
#[derive(Debug)]
pub enum CellState
{
	Dead,
	Alive
}

pub struct Simulator<'a> {
	iterationNum: u32,
	height: u32,
	width: u32,
	output_dir: String,
	starting_states: Vec<Vec<CellState>>,
	current_states: &'a mut Vec<Vec<CellState>>,
	current_iteration: u32,
}

impl<'a> Simulator<'a> {
	fn run_simulation() {

	}
}<commit_msg>Almost iterating over the cells<commit_after>#[derive(Clone)]
#[derive(Debug)]
pub enum CellState
{
	Dead,
	Alive
}

pub struct Simulator {
	iteration_num: u32,
	height: usize,
	width: usize,
	output_dir: String,
	starting_states: Vec<Vec<CellState>>,
	//current_states: Vec<Vec<Cell>>,
	current_iteration: u32,
}

impl<'a> Simulator {
	pub fn run_simulation(&mut self) {
		// Set up first cells
		let mut current_states = Vec::new();
		for x in 0..self.starting_states.len() {
			let mut row = Vec::new();
			for y in 0..self.starting_states[x].len() {
				row.push(Cell {
					state: self.starting_states[x][y].clone(),
					row: x,
					col: y,
				});
			}
			current_states.push(row);
		}
		loop {
			// Create new states
			let mut new_states = Vec::new();
			for x in 0..self.height {
				let mut new_row = Vec::new();
				for y in 0..self.width {
					let new_cell = current_states[x][y].iterate(&current_states);
					new_row.push(new_cell);
				}
				new_states.push(new_row);
			}
			// Set current states
			current_states = new_states;
			// TODO Output
			// Increment iteration
			self.current_iteration += 1;
			if self.current_iteration == self.iteration_num {
				break;
			}
		}
	}
}

#[derive(Clone)]
struct Cell {
	state: CellState,
	row: usize,
	col: usize,
}

impl Cell {
	fn iterate(self, prev_state: &Vec<Vec<Cell>>) -> Cell {
		return Cell {
			state: self.state,
			row: self.row,
			col: self.col,
		};
	}
}<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

#[macro_use]
use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Box<Self::List>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::List>) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res ;

    // Derived from above:
    fn is_empty (self:&Self, st:&mut A, list:&Self::List) -> bool {
        self.elim(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Box<Self::Tree>, Box<Self::Tree>) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::Tree>, Box<Self::Tree>) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Arg,Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                                  -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Box<Self::List>)       -> Self::List { List::Cons(hd,tl) }
    fn name (_:&mut A, nm:A::Name, tl:Box<Self::List>)  -> Self::List { List::Name(nm, tl) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)               -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>)      -> Self::List { List::Art(art) }

    fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, tl),
            List::Name(ref nm, ref tl) => namef(st, nm, tl),
            List::Art(ref art) => {
                let list = st.force(art);
                self.elim(st, &list, nilf, consf, namef)
            }
        }
    }
}

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager, prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (l, list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, l, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (l, list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    l.elim (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), Box::new(left_tree.clone()), Box::new(right_tree) ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, l, &rest, &tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations, named by name.
                // TODO: Memoize the recursive calls to tree_of_list_rec.
                let tree = T::name( st, nm.clone(), Box::new(left_tree.clone()), Box::new(right_tree) ) ;
                tree_of_list_rec::<A,X,T,L> ( st, l, &rest, &tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (l:&L, st:&mut A, list:&Rc<L::List>)
     -> Rc<T::Tree>
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, l, list, &nil, 0 as u32, u32::max_value()) ;
    assert!( l.is_empty( st, &rest ) );
    tree
}
<commit_msg>structures type-checks against new API<commit_after>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

#[macro_use]
use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Box<Self::List>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::List>) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res ;

    // Derived from above:
    fn is_empty (self:&Self, st:&mut A, list:&Self::List) -> bool {
        self.elim(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Box<Self::Tree>, Box<Self::Tree>) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::Tree>, Box<Self::Tree>) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Arg,Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                                  -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Box<Self::List>)       -> Self::List { List::Cons(hd,tl) }
    fn name (_:&mut A, nm:A::Name, tl:Box<Self::List>)  -> Self::List { List::Name(nm, tl) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)               -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>)      -> Self::List { List::Art(art) }

    fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, tl),
            List::Name(ref nm, ref tl) => namef(st, nm, tl),
            List::Rc(ref rc) => self.elim(st, &*rc, nilf, consf, namef),
            List::Art(ref art) => {
                let list = st.force(art);
                self.elim(st, &list, nilf, consf, namef)
            }
        }
    }
}

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager, prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (l, list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, l, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (l, list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    l.elim (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), Box::new(left_tree.clone()), Box::new(right_tree) ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, l, &rest, &tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations, named by name.
                // TODO: Memoize the recursive calls to tree_of_list_rec.
                let tree = T::name( st, nm.clone(), Box::new(left_tree.clone()), Box::new(right_tree) ) ;
                tree_of_list_rec::<A,X,T,L> ( st, l, &rest, &tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (l:&L, st:&mut A, list:&L::List) -> T::Tree
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, l, list, &nil, 0 as u32, u32::max_value()) ;
    assert!( l.is_empty( st, &rest ) );
    tree
}
<|endoftext|>


<commit_before>use std::collections::hashmap::HashMap;
use std::uint;
use std::rand;
use std::rand::Rng;
use cgmath::{Vector2};
use calx::color::RGB;
use calx::color::consts::*;
use world::system::{World, Entity, EngineLogic};
use world::spatial::{Location, Position, DIRECTIONS6};
use world::mapgen::{AreaSpec};
use world::mapgen;
use world::area::Area;
use world::fov::Fov;
use world::dijkstra;

#[deriving(Clone, Show)]
pub struct MobComp {
    pub t: MobType,
    pub max_hp: int,
    pub hp: int,
    pub power: int,
    pub armor: int,
    pub status: int,
}

impl MobComp {
    pub fn new(t: MobType) -> MobComp {
        let data = MOB_KINDS[t as uint];
        let status = if t != Player { status::Asleep as int } else { 0 };
        MobComp {
            t: t,
            max_hp: data.power / 2,
            hp: data.power / 2,
            power: data.power,
            armor: 0,
            status: status,
        }
    }
}

pub mod intrinsic {
#[deriving(Eq, PartialEq, Clone)]
pub enum Intrinsic {
    /// Moves 1/3 slower than usual.
    Slow        = 0b1,
    /// Moves 1/3 faster than usual, stacks with Quick status.
    Fast        = 0b10,
    /// Can manipulate objects and doors.
    Hands       = 0b100,
}
}

pub mod status {
#[deriving(Eq, PartialEq, Clone)]
pub enum Status {
    /// Moves 1/3 slower than usual.
    Slow        = 0b1,
    /// Moves 1/3 faster than usual, stacks with Fast intrinsic.
    Quick       = 0b10,
    /// Mob is inactive until disturbed.
    Asleep      = 0b100,
    /// Mob moves erratically.
    Confused    = 0b1000,
}
}

pub struct MobKind {
    pub typ: MobType,
    pub name: &'static str,
    pub power: int,
    pub area_spec: AreaSpec,
    pub sprite: uint,
    pub color: RGB,
    pub intrinsics: int,
}

// Intrinsic flag union.
macro_rules! f {
    { $($flag:ident),* } => { 0 $( | intrinsic::$flag as int )* }
}

macro_rules! mob_data {
    {
        count: $count:expr;
        $($symbol:ident: $power:expr, $depth:expr, $biome:ident, $sprite:expr, $color:expr, $flags:expr;)*

    } => {
#[deriving(Eq, PartialEq, Clone, Show)]
pub enum MobType {
    $($symbol,)*
}

pub static MOB_KINDS: [MobKind, ..$count] = [
    $(MobKind {
        typ: $symbol,
        name: stringify!($symbol),
        power: $power,
        area_spec: AreaSpec {
            depth: $depth,
            biome: mapgen::$biome,
        },
        sprite: $sprite,
        color: $color,
        intrinsics: $flags,
    },)*
];

// End macro
    }
}

mob_data! {
    count: 10;
//  Symbol   power, depth, biome, sprite, color,        intrinsics
    Player:     5,  -1, Anywhere, 51, AZURE,            f!();
    Dreg:       2,   1, Anywhere, 72, OLIVE,            f!(Hands);
    Snake:      2,   1, Overland, 71, GREEN,            f!();
    Ooze:       4,   3, Dungeon,  77, LIGHTSEAGREEN,    f!();
    Flayer:     8,   4, Anywhere, 75, INDIANRED,        f!();
    Ogre:       9,   5, Anywhere, 73, DARKSLATEGRAY,    f!(Hands);
    Wraith:     10,  6, Dungeon,  74, HOTPINK,          f!(Hands);
    Octopus:    12,  7, Anywhere, 63, DARKTURQUOISE,    f!();
    Efreet:     15,  8, Anywhere, 78, ORANGE,           f!();
    Serpent:    20,  9, Dungeon,  94, CORAL,            f!();
}

/// Trait for entities that are mobile things.
pub trait Mob {
    fn is_active(&self) -> bool;
    fn acts_this_frame(&self) -> bool;
    fn has_intrinsic(&self, f: intrinsic::Intrinsic) -> bool;
    fn has_status(&self, s: status::Status) -> bool;
    fn add_status(&mut self, s: status::Status);
    fn remove_status(&mut self, s: status::Status);
    fn mob_type(&self) -> MobType;
    fn power(&self) -> int;
    fn update_ai(&mut self);

    /// Try to move the mob in a direction, then try to roll around obstacles
    /// if the direction is blocked.
    fn smart_move(&mut self, dir8: uint) -> Option<Vector2<int>>;

    fn enemy_at(&self, loc: Location) -> Option<Entity>;
    fn attack(&mut self, loc: Location);

    /// Something interesting is happening at location. See if the mob needs to
    /// wake up and investigate.
    fn alert_at(&mut self, loc: Location);
}

impl Mob for Entity {
    fn is_active(&self) -> bool {
        if !self.has::<MobComp>() { return false; }
        if self.has_status(status::Asleep) { return false; }
        return true;
    }

    fn acts_this_frame(&self) -> bool {
        if !self.has::<MobComp>() { return false; }
        if !self.is_active() { return false; }

        // Go through a cycle of 5 phases to get 4 possible speeds.
        // System idea from Jeff Lait.
        let phase = self.world().get_tick() % 5;
        match phase {
            0 => return true,
            1 => return self.has_intrinsic(intrinsic::Fast),
            2 => return true,
            3 => return self.has_status(status::Quick),
            4 => return !self.has_intrinsic(intrinsic::Slow),
            _ => fail!("Invalid action phase"),
        }
    }

    fn has_intrinsic(&self, f: intrinsic::Intrinsic) -> bool {
        self.into::<MobComp>().map_or(false,
            |m| MOB_KINDS[m.t as uint].intrinsics as int & f as int != 0)
    }

    fn has_status(&self, s: status::Status) -> bool {
        self.into::<MobComp>().map_or(false,
            |m| m.status as int & s as int != 0)
    }

    fn add_status(&mut self, s: status::Status) {
        self.into::<MobComp>().as_mut().map(
            |m| m.status |= s as int);
    }

    fn remove_status(&mut self, s: status::Status) {
        self.into::<MobComp>().as_mut().map(
            |m| m.status &= !(s as int));
    }

    fn mob_type(&self) -> MobType { self.into::<MobComp>().unwrap().t }

    fn power(&self) -> int { self.into::<MobComp>().unwrap().power }

    fn update_ai(&mut self) {
        if self.world().player().is_some() {
            let player = self.world().player().unwrap();
            let pathing = Pathing::at_loc(&self.world(), player.location());

            let move = pathing.towards_from(self.location());
            match move {
                Some(loc) => {
                    let move_dir = &self.location().dir6_towards(loc);
                    match self.enemy_at(loc) {
                        Some(_) => { self.attack(loc); }
                        _ => { self.move(move_dir); }
                    }
                    return;
                }
                _ => ()
            }
        }

        // No target, wander around randomly.
        self.move(rand::task_rng().choose(DIRECTIONS6.as_slice()).unwrap());
    }

    fn smart_move(&mut self, dir8: uint) -> Option<Vector2<int>> {
        static SMART_MOVE: &'static [&'static [Vector2<int>]] = &[
            &[DIRECTIONS6[0], DIRECTIONS6[5], DIRECTIONS6[1]],
            &[DIRECTIONS6[1], DIRECTIONS6[0], DIRECTIONS6[2]],
            &[DIRECTIONS6[2], DIRECTIONS6[1], DIRECTIONS6[3]],
            &[DIRECTIONS6[3], DIRECTIONS6[2], DIRECTIONS6[4]],
            &[DIRECTIONS6[4], DIRECTIONS6[3], DIRECTIONS6[5]],
            &[DIRECTIONS6[5], DIRECTIONS6[4], DIRECTIONS6[0]],

            // Right sideways move zigzag.
            &[DIRECTIONS6[1], DIRECTIONS6[2]],
            &[DIRECTIONS6[2], DIRECTIONS6[1]],

            // Left sideways move zigzag.
            &[DIRECTIONS6[5], DIRECTIONS6[4]],
            &[DIRECTIONS6[4], DIRECTIONS6[5]],
            ];
        // "horizontal" movement is a zig-zag since there's no natural hex axis
        // in that direction. Find out the grid column the mob is on and
        // determine whether to zig or zag based on that.
        let loc = self.location();
        let zag = ((loc.x - loc.y) % 2) as uint;

        let deltas = SMART_MOVE[match dir8 {
                0 => 0,
                1 => 1,
                2 => 6 + zag,
                3 => 2,
                4 => 3,
                5 => 4,
                6 => 8 + zag,
                7 => 5,
                _ => fail!("Invalid dir8"),
            }];

        for delta in deltas.iter() {
            let new_loc = loc + *delta;
            match self.enemy_at(new_loc) {
                Some(_) => {
                    self.attack(new_loc);
                    return None;
                }
                _ => ()
            }
            if self.move(delta) { return Some(*delta); }
        }

        None
    }

    fn enemy_at(&self, loc: Location) -> Option<Entity> {
        let targs = self.world().mobs_at(loc);
        // Nothing to fight.
        if targs.len() == 0 { return None; }
        // TODO: Alignment check
        Some(targs[0].clone())
    }

    fn attack(&mut self, loc: Location) {
        let p = self.power();
        // No power, can't fight.
        if p == 0 { return; }

        let target = match self.enemy_at(loc) {
            None => return,
            Some(t) => t,
        };

        // Every five points of power is one certain hit.
        let full = p / 5;
        let partial = (p % 5) as f64 / 5.0;

        // TODO: Make some rng utility functions.
        let r = rand::random::<f64>() % 1.0;

        let damage = full + if r < partial { 1 } else { 0 };

        // TODO: A deal_damage method.
        let mut tm = target.into::<MobComp>().unwrap();
        tm.hp -= damage;

        if tm.hp <= 0 {
            if target.mob_type() == Player {
                println!("TODO handle player death");
                tm.hp = tm.max_hp;
            }
            // TODO: Whatever extra stuff we want to do when killing a mob.
            // It's probably a special occasion if it's the player avatar.
            self.world().delete_entity(&target);
        }
    }

    fn alert_at(&mut self, loc: Location) {
        // TODO: More complex logic. Check the square for enemies, don't wake
        // up if enemy is stealthed successfully.
        if self.has_status(status::Asleep) {
            if self.location().dist(loc) < 6 {
                self.remove_status(status::Asleep);

                // XXX: Msging REALLY needs a nicer API.
                self.world().system_mut().fx.msg(format!("{} wakes up.", MOB_KINDS[self.mob_type() as uint].name).as_slice());
            }
        }
    }
}

/// Game world trait for global creature operations.
pub trait Mobs {
    fn mobs_at(&self, loc: Location) -> Vec<Entity>;
    fn mobs(&self) -> Vec<Entity>;
    fn player(&self) -> Option<Entity>;
    fn player_has_turn(&self) -> bool;
    fn clear_npcs(&mut self);
    fn update_mobs(&mut self);
    fn wake_up_mobs(&mut self);
}

impl Mobs for World {
    fn mobs_at(&self, loc: Location) -> Vec<Entity> {
        self.entities_at(loc).iter().filter(|e| e.has::<MobComp>())
            .map(|e| e.clone()).collect()
    }

    fn mobs(&self) -> Vec<Entity> {
        self.entities().filter(|e| e.has::<MobComp>())
            .map(|e| e.clone()).collect()
    }

    fn player(&self) -> Option<Entity> {
        for e in self.mobs().iter() {
            if e.mob_type() == Player {
                return Some(e.clone());
            }
        }
        None
    }

    fn player_has_turn(&self) -> bool {
        match self.player() {
            Some(p) => p.acts_this_frame(),
            _ => false
        }
    }

    fn clear_npcs(&mut self) {
        for e in self.mobs().mut_iter() {
            if e.mob_type() != Player {
                e.delete();
            }
        }
    }

    fn update_mobs(&mut self) {
        self.wake_up_mobs();

        for mob in self.mobs().mut_iter() {
            if !mob.acts_this_frame() { continue; }
            if mob.mob_type() == Player { continue; }
            mob.update_ai();
        }

        self.advance_frame();
    }

    fn wake_up_mobs(&mut self) {
        if self.player().is_none() { return; }
        let player_fov = self.camera().into::<Fov>().unwrap();
        let player_loc = self.player().unwrap().location();
        for &loc in player_fov.deref().seen_locs() {
            for mob in self.mobs_at(loc).mut_iter() {
                mob.alert_at(player_loc);
            }
        }
    }
}

pub struct Pathing {
    gradient: HashMap<Location, uint>,
}

impl Pathing {
    /// Pathing map towards a single point.
    pub fn at_loc(world: &World, loc: Location) -> Pathing {
        Pathing {
            gradient: dijkstra::build_map(
                vec![loc],
                |&loc| world.open_neighbors(loc, DIRECTIONS6.iter()),
                256),
        }
    }

    fn neighbors(&self, loc: Location) -> Vec<Location> {
        DIRECTIONS6.iter().map(|&d| loc + d).collect()
    }

    pub fn towards_from(&self, current: Location) -> Option<Location> {
        let mut ret = None;
        let mut best = uint::MAX;
        for n in self.neighbors(current).iter() {
            match self.gradient.find(n) {
                Some(&weight) if weight <= best => {
                    ret = Some(*n);
                    best = weight;
                }
                _ => ()
            }
        }
        ret
    }
}
<commit_msg>Adjust power levels<commit_after>use std::collections::hashmap::HashMap;
use std::uint;
use std::rand;
use std::rand::Rng;
use cgmath::{Vector2};
use calx::color::RGB;
use calx::color::consts::*;
use world::system::{World, Entity, EngineLogic};
use world::spatial::{Location, Position, DIRECTIONS6};
use world::mapgen::{AreaSpec};
use world::mapgen;
use world::area::Area;
use world::fov::Fov;
use world::dijkstra;

#[deriving(Clone, Show)]
pub struct MobComp {
    pub t: MobType,
    pub max_hp: int,
    pub hp: int,
    pub power: int,
    pub armor: int,
    pub status: int,
}

impl MobComp {
    pub fn new(t: MobType) -> MobComp {
        let data = MOB_KINDS[t as uint];
        let status = if t != Player { status::Asleep as int } else { 0 };
        MobComp {
            t: t,
            max_hp: data.power,
            hp: data.power,
            power: data.power,
            armor: 0,
            status: status,
        }
    }
}

pub mod intrinsic {
#[deriving(Eq, PartialEq, Clone)]
pub enum Intrinsic {
    /// Moves 1/3 slower than usual.
    Slow        = 0b1,
    /// Moves 1/3 faster than usual, stacks with Quick status.
    Fast        = 0b10,
    /// Can manipulate objects and doors.
    Hands       = 0b100,
}
}

pub mod status {
#[deriving(Eq, PartialEq, Clone)]
pub enum Status {
    /// Moves 1/3 slower than usual.
    Slow        = 0b1,
    /// Moves 1/3 faster than usual, stacks with Fast intrinsic.
    Quick       = 0b10,
    /// Mob is inactive until disturbed.
    Asleep      = 0b100,
    /// Mob moves erratically.
    Confused    = 0b1000,
}
}

pub struct MobKind {
    pub typ: MobType,
    pub name: &'static str,
    pub power: int,
    pub area_spec: AreaSpec,
    pub sprite: uint,
    pub color: RGB,
    pub intrinsics: int,
}

// Intrinsic flag union.
macro_rules! f {
    { $($flag:ident),* } => { 0 $( | intrinsic::$flag as int )* }
}

macro_rules! mob_data {
    {
        count: $count:expr;
        $($symbol:ident: $power:expr, $depth:expr, $biome:ident, $sprite:expr, $color:expr, $flags:expr;)*

    } => {
#[deriving(Eq, PartialEq, Clone, Show)]
pub enum MobType {
    $($symbol,)*
}

pub static MOB_KINDS: [MobKind, ..$count] = [
    $(MobKind {
        typ: $symbol,
        name: stringify!($symbol),
        power: $power,
        area_spec: AreaSpec {
            depth: $depth,
            biome: mapgen::$biome,
        },
        sprite: $sprite,
        color: $color,
        intrinsics: $flags,
    },)*
];

// End macro
    }
}

mob_data! {
    count: 10;
//  Symbol   power, depth, biome, sprite, color,        intrinsics
    Player:     6,  -1, Anywhere, 51, AZURE,            f!();
    Dreg:       1,   1, Anywhere, 72, OLIVE,            f!(Hands);
    Snake:      1,   1, Overland, 71, GREEN,            f!();
    Ooze:       3,   3, Dungeon,  77, LIGHTSEAGREEN,    f!();
    Flayer:     4,   4, Anywhere, 75, INDIANRED,        f!();
    Ogre:       6,   5, Anywhere, 73, DARKSLATEGRAY,    f!(Hands);
    Wraith:     8,   6, Dungeon,  74, HOTPINK,          f!(Hands);
    Octopus:    10,  7, Anywhere, 63, DARKTURQUOISE,    f!();
    Efreet:     12,  8, Anywhere, 78, ORANGE,           f!();
    Serpent:    15,  9, Dungeon,  94, CORAL,            f!();
}

/// Trait for entities that are mobile things.
pub trait Mob {
    fn is_active(&self) -> bool;
    fn acts_this_frame(&self) -> bool;
    fn has_intrinsic(&self, f: intrinsic::Intrinsic) -> bool;
    fn has_status(&self, s: status::Status) -> bool;
    fn add_status(&mut self, s: status::Status);
    fn remove_status(&mut self, s: status::Status);
    fn mob_type(&self) -> MobType;
    fn power(&self) -> int;
    fn update_ai(&mut self);

    /// Try to move the mob in a direction, then try to roll around obstacles
    /// if the direction is blocked.
    fn smart_move(&mut self, dir8: uint) -> Option<Vector2<int>>;

    fn enemy_at(&self, loc: Location) -> Option<Entity>;
    fn attack(&mut self, loc: Location);

    /// Something interesting is happening at location. See if the mob needs to
    /// wake up and investigate.
    fn alert_at(&mut self, loc: Location);
}

impl Mob for Entity {
    fn is_active(&self) -> bool {
        if !self.has::<MobComp>() { return false; }
        if self.has_status(status::Asleep) { return false; }
        return true;
    }

    fn acts_this_frame(&self) -> bool {
        if !self.has::<MobComp>() { return false; }
        if !self.is_active() { return false; }

        // Go through a cycle of 5 phases to get 4 possible speeds.
        // System idea from Jeff Lait.
        let phase = self.world().get_tick() % 5;
        match phase {
            0 => return true,
            1 => return self.has_intrinsic(intrinsic::Fast),
            2 => return true,
            3 => return self.has_status(status::Quick),
            4 => return !self.has_intrinsic(intrinsic::Slow),
            _ => fail!("Invalid action phase"),
        }
    }

    fn has_intrinsic(&self, f: intrinsic::Intrinsic) -> bool {
        self.into::<MobComp>().map_or(false,
            |m| MOB_KINDS[m.t as uint].intrinsics as int & f as int != 0)
    }

    fn has_status(&self, s: status::Status) -> bool {
        self.into::<MobComp>().map_or(false,
            |m| m.status as int & s as int != 0)
    }

    fn add_status(&mut self, s: status::Status) {
        self.into::<MobComp>().as_mut().map(
            |m| m.status |= s as int);
    }

    fn remove_status(&mut self, s: status::Status) {
        self.into::<MobComp>().as_mut().map(
            |m| m.status &= !(s as int));
    }

    fn mob_type(&self) -> MobType { self.into::<MobComp>().unwrap().t }

    fn power(&self) -> int { self.into::<MobComp>().unwrap().power }

    fn update_ai(&mut self) {
        if self.world().player().is_some() {
            let player = self.world().player().unwrap();
            let pathing = Pathing::at_loc(&self.world(), player.location());

            let move = pathing.towards_from(self.location());
            match move {
                Some(loc) => {
                    let move_dir = &self.location().dir6_towards(loc);
                    match self.enemy_at(loc) {
                        Some(_) => { self.attack(loc); }
                        _ => { self.move(move_dir); }
                    }
                    return;
                }
                _ => ()
            }
        }

        // No target, wander around randomly.
        self.move(rand::task_rng().choose(DIRECTIONS6.as_slice()).unwrap());
    }

    fn smart_move(&mut self, dir8: uint) -> Option<Vector2<int>> {
        static SMART_MOVE: &'static [&'static [Vector2<int>]] = &[
            &[DIRECTIONS6[0], DIRECTIONS6[5], DIRECTIONS6[1]],
            &[DIRECTIONS6[1], DIRECTIONS6[0], DIRECTIONS6[2]],
            &[DIRECTIONS6[2], DIRECTIONS6[1], DIRECTIONS6[3]],
            &[DIRECTIONS6[3], DIRECTIONS6[2], DIRECTIONS6[4]],
            &[DIRECTIONS6[4], DIRECTIONS6[3], DIRECTIONS6[5]],
            &[DIRECTIONS6[5], DIRECTIONS6[4], DIRECTIONS6[0]],

            // Right sideways move zigzag.
            &[DIRECTIONS6[1], DIRECTIONS6[2]],
            &[DIRECTIONS6[2], DIRECTIONS6[1]],

            // Left sideways move zigzag.
            &[DIRECTIONS6[5], DIRECTIONS6[4]],
            &[DIRECTIONS6[4], DIRECTIONS6[5]],
            ];
        // "horizontal" movement is a zig-zag since there's no natural hex axis
        // in that direction. Find out the grid column the mob is on and
        // determine whether to zig or zag based on that.
        let loc = self.location();
        let zag = ((loc.x - loc.y) % 2) as uint;

        let deltas = SMART_MOVE[match dir8 {
                0 => 0,
                1 => 1,
                2 => 6 + zag,
                3 => 2,
                4 => 3,
                5 => 4,
                6 => 8 + zag,
                7 => 5,
                _ => fail!("Invalid dir8"),
            }];

        for delta in deltas.iter() {
            let new_loc = loc + *delta;
            match self.enemy_at(new_loc) {
                Some(_) => {
                    self.attack(new_loc);
                    return None;
                }
                _ => ()
            }
            if self.move(delta) { return Some(*delta); }
        }

        None
    }

    fn enemy_at(&self, loc: Location) -> Option<Entity> {
        let targs = self.world().mobs_at(loc);
        // Nothing to fight.
        if targs.len() == 0 { return None; }
        // TODO: Alignment check
        Some(targs[0].clone())
    }

    fn attack(&mut self, loc: Location) {
        let p = self.power();
        // No power, can't fight.
        if p == 0 { return; }

        let target = match self.enemy_at(loc) {
            None => return,
            Some(t) => t,
        };

        // Every five points of power is one certain hit.
        let full = p / 5;
        let partial = (p % 5) as f64 / 5.0;

        // TODO: Make some rng utility functions.
        let r = rand::random::<f64>() % 1.0;

        let damage = full + if r < partial { 1 } else { 0 };

        // TODO: A deal_damage method.
        let mut tm = target.into::<MobComp>().unwrap();
        tm.hp -= damage;

        if tm.hp <= 0 {
            if target.mob_type() == Player {
                println!("TODO handle player death");
                tm.hp = tm.max_hp;
            }
            // TODO: Whatever extra stuff we want to do when killing a mob.
            // It's probably a special occasion if it's the player avatar.
            self.world().delete_entity(&target);
        }
    }

    fn alert_at(&mut self, loc: Location) {
        // TODO: More complex logic. Check the square for enemies, don't wake
        // up if enemy is stealthed successfully.
        if self.has_status(status::Asleep) {
            if self.location().dist(loc) < 6 {
                self.remove_status(status::Asleep);

                // XXX: Msging REALLY needs a nicer API.
                self.world().system_mut().fx.msg(format!("{} wakes up.", MOB_KINDS[self.mob_type() as uint].name).as_slice());
            }
        }
    }
}

/// Game world trait for global creature operations.
pub trait Mobs {
    fn mobs_at(&self, loc: Location) -> Vec<Entity>;
    fn mobs(&self) -> Vec<Entity>;
    fn player(&self) -> Option<Entity>;
    fn player_has_turn(&self) -> bool;
    fn clear_npcs(&mut self);
    fn update_mobs(&mut self);
    fn wake_up_mobs(&mut self);
}

impl Mobs for World {
    fn mobs_at(&self, loc: Location) -> Vec<Entity> {
        self.entities_at(loc).iter().filter(|e| e.has::<MobComp>())
            .map(|e| e.clone()).collect()
    }

    fn mobs(&self) -> Vec<Entity> {
        self.entities().filter(|e| e.has::<MobComp>())
            .map(|e| e.clone()).collect()
    }

    fn player(&self) -> Option<Entity> {
        for e in self.mobs().iter() {
            if e.mob_type() == Player {
                return Some(e.clone());
            }
        }
        None
    }

    fn player_has_turn(&self) -> bool {
        match self.player() {
            Some(p) => p.acts_this_frame(),
            _ => false
        }
    }

    fn clear_npcs(&mut self) {
        for e in self.mobs().mut_iter() {
            if e.mob_type() != Player {
                e.delete();
            }
        }
    }

    fn update_mobs(&mut self) {
        self.wake_up_mobs();

        for mob in self.mobs().mut_iter() {
            if !mob.acts_this_frame() { continue; }
            if mob.mob_type() == Player { continue; }
            mob.update_ai();
        }

        self.advance_frame();
    }

    fn wake_up_mobs(&mut self) {
        if self.player().is_none() { return; }
        let player_fov = self.camera().into::<Fov>().unwrap();
        let player_loc = self.player().unwrap().location();
        for &loc in player_fov.deref().seen_locs() {
            for mob in self.mobs_at(loc).mut_iter() {
                mob.alert_at(player_loc);
            }
        }
    }
}

pub struct Pathing {
    gradient: HashMap<Location, uint>,
}

impl Pathing {
    /// Pathing map towards a single point.
    pub fn at_loc(world: &World, loc: Location) -> Pathing {
        Pathing {
            gradient: dijkstra::build_map(
                vec![loc],
                |&loc| world.open_neighbors(loc, DIRECTIONS6.iter()),
                256),
        }
    }

    fn neighbors(&self, loc: Location) -> Vec<Location> {
        DIRECTIONS6.iter().map(|&d| loc + d).collect()
    }

    pub fn towards_from(&self, current: Location) -> Option<Location> {
        let mut ret = None;
        let mut best = uint::MAX;
        for n in self.neighbors(current).iter() {
            match self.gradient.find(n) {
                Some(&weight) if weight <= best => {
                    ret = Some(*n);
                    best = weight;
                }
                _ => ()
            }
        }
        ret
    }
}
<|endoftext|>