Esempio n. 1
0
bool player::eat( item &food, bool force )
{
    if( !food.is_food() ) {
        return false;
    }
    // Check if it's rotten before eating!
    food.calc_rot( global_square_location() );
    const auto ret = force ? can_eat( food ) : will_eat( food, is_player() );
    if( !ret.success() ) {
        return false;
    }

    if( food.type->has_use() ) {
        if( food.type->invoke( *this, food, pos() ) <= 0 ) {
            return false;
        }
    }

    // Note: the block below assumes we decided to eat it
    // No coming back from here

    const bool hibernate = has_active_mutation( trait_id( "HIBERNATE" ) );
    const int nutr = nutrition_for( food );
    const int quench = food.type->comestible->quench;
    const bool spoiled = food.rotten();

    // The item is solid food
    const bool chew = food.type->comestible->comesttype == "FOOD" || food.has_flag( "USE_EAT_VERB" );
    // This item is a drink and not a solid food (and not a thick soup)
    const bool drinkable = !chew && food.type->comestible->comesttype == "DRINK";
    // If neither of the above is true then it's a drug and shouldn't get mealtime penalty/bonus

    if( hibernate &&
        ( get_hunger() > -60 && get_thirst() > -60 ) &&
        ( get_hunger() - nutr < -60 || get_thirst() - quench < -60 ) ) {
        add_memorial_log( pgettext( "memorial_male", "Began preparing for hibernation." ),
                          pgettext( "memorial_female", "Began preparing for hibernation." ) );
        add_msg_if_player(
            _( "You've begun stockpiling calories and liquid for hibernation.  You get the feeling that you should prepare for bed, just in case, but...you're hungry again, and you could eat a whole week's worth of food RIGHT NOW." ) );
    }

    const bool will_vomit = get_hunger() < 0 && nutr >= 5 && !has_trait( trait_id( "GOURMAND" ) ) &&
                            !hibernate &&
                            !has_trait( trait_id( "SLIMESPAWNER" ) ) && !has_trait( trait_id( "EATHEALTH" ) ) &&
                            rng( -200, 0 ) > get_hunger() - nutr;
    const bool saprophage = has_trait( trait_id( "SAPROPHAGE" ) );
    if( spoiled && !saprophage ) {
        add_msg_if_player( m_bad, _( "Ick, this %s doesn't taste so good..." ), food.tname().c_str() );
        if( !has_trait( trait_id( "SAPROVORE" ) ) && !has_trait( trait_id( "EATDEAD" ) ) &&
            ( !has_bionic( bio_digestion ) || one_in( 3 ) ) ) {
            add_effect( effect_foodpoison, rng( 60, ( nutr + 1 ) * 60 ) );
        }
        consume_effects( food );
    } else if( spoiled && saprophage ) {
        add_msg_if_player( m_good, _( "Mmm, this %s tastes delicious..." ), food.tname().c_str() );
        consume_effects( food );
    } else {
        consume_effects( food );
    }

    const bool amorphous = has_trait( trait_id( "AMORPHOUS" ) );
    int mealtime = 250;
    if( drinkable || chew ) {
        // Those bonuses/penalties only apply to food
        // Not to smoking weed or applying bandages!
        if( has_trait( trait_id( "MOUTH_TENTACLES" ) )  || has_trait( trait_id( "MANDIBLES" ) ) ) {
            mealtime /= 2;
        } else if( has_trait( trait_id( "GOURMAND" ) ) ) {
            // Don't stack those two - that would be 25 moves per item
            mealtime -= 100;
        }

        if( has_trait( trait_id( "BEAK_HUM" ) ) && !drinkable ) {
            mealtime += 200; // Much better than PROBOSCIS but still optimized for fluids
        } else if( has_trait( trait_id( "SABER_TEETH" ) ) ) {
            mealtime += 250; // They get In The Way
        }

        if( amorphous ) {
            mealtime *= 1.1;
            // Minor speed penalty for having to flow around it
            // rather than just grab & munch
        }
    }

    moves -= mealtime;

    // If it's poisonous... poison us.
    // TODO: Move this to a flag
    if( food.poison > 0 && !has_trait( trait_id( "EATPOISON" ) ) &&
        !has_trait( trait_id( "EATDEAD" ) ) ) {
        if( food.poison >= rng( 2, 4 ) ) {
            add_effect( effect_poison, food.poison * 100 );
        }

        add_effect( effect_foodpoison, food.poison * 300 );
    }

    if( amorphous ) {
        add_msg_player_or_npc( _( "You assimilate your %s." ), _( "<npcname> assimilates a %s." ),
                               food.tname().c_str() );
    } else if( drinkable ) {
        add_msg_player_or_npc( _( "You drink your %s." ), _( "<npcname> drinks a %s." ),
                               food.tname().c_str() );
    } else if( chew ) {
        add_msg_player_or_npc( _( "You eat your %s." ), _( "<npcname> eats a %s." ),
                               food.tname().c_str() );
    }

    if( item::find_type( food.type->comestible->tool )->tool ) {
        // Tools like lighters get used
        use_charges( food.type->comestible->tool, 1 );
    }

    if( has_bionic( bio_ethanol ) && food.type->can_use( "ALCOHOL" ) ) {
        charge_power( rng( 50, 200 ) );
    }
    if( has_bionic( bio_ethanol ) && food.type->can_use( "ALCOHOL_WEAK" ) ) {
        charge_power( rng( 25, 100 ) );
    }
    if( has_bionic( bio_ethanol ) && food.type->can_use( "ALCOHOL_STRONG" ) ) {
        charge_power( rng( 75, 300 ) );
    }

    if( food.has_flag( "CANNIBALISM" ) ) {
        // Sapiovores don't recognize humans as the same species.
        // But let them possibly feel cool about eating sapient stuff - treat like psycho
        const bool cannibal = has_trait( trait_id( "CANNIBAL" ) );
        const bool psycho = has_trait( trait_id( "PSYCHOPATH" ) ) || has_trait( trait_id( "SAPIOVORE" ) );
        const bool spiritual = has_trait( trait_id( "SPIRITUAL" ) );
        if( cannibal && psycho && spiritual ) {
            add_msg_if_player( m_good,
                               _( "You feast upon the human flesh, and in doing so, devour their spirit." ) );
            // You're not really consuming anything special; you just think you are.
            add_morale( MORALE_CANNIBAL, 25, 300 );
        } else if( cannibal && psycho ) {
            add_msg_if_player( m_good, _( "You feast upon the human flesh." ) );
            add_morale( MORALE_CANNIBAL, 15, 200 );
        } else if( cannibal && spiritual ) {
            add_msg_if_player( m_good, _( "You consume the sacred human flesh." ) );
            // Boosted because you understand the philosophical implications of your actions, and YOU LIKE THEM.
            add_morale( MORALE_CANNIBAL, 15, 200 );
        } else if( cannibal ) {
            add_msg_if_player( m_good, _( "You indulge your shameful hunger." ) );
            add_morale( MORALE_CANNIBAL, 10, 50 );
        } else if( psycho && spiritual ) {
            add_msg_if_player( _( "You greedily devour the taboo meat." ) );
            // Small bonus for violating a taboo.
            add_morale( MORALE_CANNIBAL, 5, 50 );
        } else if( psycho ) {
            add_msg_if_player( _( "Meh. You've eaten worse." ) );
        } else if( spiritual ) {
            add_msg_if_player( m_bad,
                               _( "This is probably going to count against you if there's still an afterlife." ) );
            add_morale( MORALE_CANNIBAL, -60, -400, 600, 300 );
        } else {
            add_msg_if_player( m_bad, _( "You feel horrible for eating a person." ) );
            add_morale( MORALE_CANNIBAL, -60, -400, 600, 300 );
        }
    }

    // Allergy check
    const auto allergy = allergy_type( food );
    if( allergy != MORALE_NULL ) {
        add_msg_if_player( m_bad, _( "Yuck! How can anybody eat this stuff?" ) );
        add_morale( allergy, -75, -400, 300, 240 );
    }
    // Carnivores CAN eat junk food, but they won't like it much.
    // Pizza-scraping happens in consume_effects.
    if( has_trait( trait_id( "CARNIVORE" ) ) && food.has_flag( "ALLERGEN_JUNK" ) &&
        !food.has_flag( "CARNIVORE_OK" ) ) {
        add_msg_if_player( m_bad, _( "Your stomach begins gurgling and you feel bloated and ill." ) );
        add_morale( MORALE_NO_DIGEST, -25, -125, 300, 240 );
    }
    if( !spoiled && chew && has_trait( trait_id( "SAPROPHAGE" ) ) ) {
        // It's OK to *drink* things that haven't rotted.  Alternative is to ban water.  D:
        add_msg_if_player( m_bad, _( "Your stomach begins gurgling and you feel bloated and ill." ) );
        add_morale( MORALE_NO_DIGEST, -75, -400, 300, 240 );
    }
    if( food.has_flag( "URSINE_HONEY" ) && ( !crossed_threshold() ||
            has_trait( trait_id( "THRESH_URSINE" ) ) ) &&
        mutation_category_level["MUTCAT_URSINE"] > 40 ) {
        //Need at least 5 bear mutations for effect to show, to filter out mutations in common with other mutcats
        int honey_fun = has_trait( trait_id( "THRESH_URSINE" ) ) ?
                        std::min( mutation_category_level["MUTCAT_URSINE"] / 8, 20 ) :
                        mutation_category_level["MUTCAT_URSINE"] / 12;
        if( honey_fun < 10 ) {
            add_msg_if_player( m_good, _( "You find the sweet taste of honey surprisingly palatable." ) );
        } else {
            add_msg_if_player( m_good, _( "You feast upon the sweet honey." ) );
        }
        add_morale( MORALE_HONEY, honey_fun, 100 );
    }

    if( will_vomit ) {
        vomit();
    }

    // chance to become parasitised
    if( !( has_bionic( bio_digestion ) || has_trait( trait_id( "PARAIMMUNE" ) ) ) ) {
        if( food.type->comestible->parasites > 0 && one_in( food.type->comestible->parasites ) ) {
            switch( rng( 0, 3 ) ) {
                case 0:
                    if( !has_trait( trait_id( "EATHEALTH" ) ) ) {
                        add_effect( effect_tapeworm, 1, num_bp, true );
                    }
                    break;
                case 1:
                    if( !has_trait( trait_id( "ACIDBLOOD" ) ) ) {
                        add_effect( effect_bloodworms, 1, num_bp, true );
                    }
                    break;
                case 2:
                    add_effect( effect_brainworms, 1, num_bp, true );
                    break;
                case 3:
                    add_effect( effect_paincysts, 1, num_bp, true );
            }
        }
    }

    for( const auto &v : this->vitamins_from( food ) ) {
        auto qty = has_effect( effect_tapeworm ) ? v.second / 2 : v.second;

        // can never develop hypervitaminosis from consuming food
        vitamin_mod( v.first, qty );
    }

    food.mod_charges( -1 );
    return true;
}
Esempio n. 2
0
void function_minimizer::pvm_master_mcmc_routine(int nmcmc,int iseed0,double dscale,
  int restart_flag)
{
  uostream * pofs_psave=NULL;
  dmatrix mcmc_display_matrix;
  int mcmc_save_index=1;
  int mcmc_wrap_flag=0;
  int mcmc_gui_length=10000;
  int no_sd_mcmc=0;

  int on2=-1;
  if ( (on2=option_match(ad_comm::argc,ad_comm::argv,"-nosdmcmc"))>-1)
    no_sd_mcmc=1;

  if (stddev_params::num_stddev_params==0)
  {
    cerr << " You must declare at least one object of type sdreport "
         << endl << " to do the mcmc calculations" << endl;
     return;
  }
  {
    //ofstream of_bf("testbf");

    //if (adjm_ptr) set_labels_for_mcmc();

    ivector number_offsets;
    dvector lkvector;
    //double current_bf=0;
    double lcurrent_bf=0;
    double size_scale=1.0;
    double total_spread=200;
    //double total_spread=2500;
    uostream * pofs_sd = NULL;
    int nvar=initial_params::nvarcalc(); // get the number of active parameters
    int scov_option=0;
    dmatrix s_covar;
    dvector s_mean;
    int on=-1;
    int ncsim=25000;
    int nslots=800;
    //int nslots=3600;
    int initial_nsim=4800;
    int ntmp=0;
    int ncor=0;
    double bfsum=0;
    int ibfcount=0;
    double llbest;
    double lbmax;

    //if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcscov",ntmp))>-1)
    //{
    scov_option=1;
    s_covar.allocate(1,nvar,1,nvar);
    s_mean.allocate(1,nvar);
    s_mean.initialize();
    s_covar.initialize();

    int ndvar=stddev_params::num_stddev_calc();
    int numdvar=stddev_params::num_stddev_number_calc();
    /*
    if (adjm_ptr)
    {
      mcmc_display_matrix.allocate(1,numdvar,1,mcmc_gui_length);
      number_offsets.allocate(1,numdvar);
      number_offsets=stddev_params::copy_all_number_offsets();
    }
    */
    dvector x(1,nvar);
    dvector scale(1,nvar);
    dmatrix values;
    int have_hist_flag=0;
    initial_params::xinit(x);
    dvector pen_vector(1,nvar);
    {
      initial_params::reset(dvar_vector(x),pen_vector);
      cout << pen_vector << endl << endl;
    }

    initial_params::mc_phase=0;
    initial_params::stddev_scale(scale,x);
    initial_params::mc_phase=1;
    dvector bmn(1,nvar);
    dvector mean_mcmc_values(1,ndvar);
    dvector s(1,ndvar);
    dvector h(1,ndvar);
    //dvector h;
    dvector square_mcmc_values(1,ndvar);
    square_mcmc_values.initialize();
    mean_mcmc_values.initialize();
    bmn.initialize();
    int use_empirical_flag=0;
    int diag_option=0;
    int topt=0;
    if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcdiag"))>-1)
    {
      diag_option=1;
      cout << " Setting covariance matrix to diagonal with entries " << dscale
           << endl;
    }
    dmatrix S(1,nvar,1,nvar);
    dvector sscale(1,nvar);
    if (!diag_option)
    {
      int on,nopt;
      int rescale_bounded_flag=0;
      double rescale_bounded_power=0.5;
      if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcrb",nopt))>-1)
      {
        if (nopt)
        {
          int iii=atoi(ad_comm::argv[on+1]);
          if (iii < 1 || iii > 9)
          {
            cerr << " -mcrb argument must be integer between 1 and 9 --"
                    " using default of 5" << endl;
            rescale_bounded_power=0.5;
          }
          else
            rescale_bounded_power=iii/10.0;
        }
        else
        {
          rescale_bounded_power=0.5;
        }
        rescale_bounded_flag=1;
      }
      if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcec"))>-1)
      {
        use_empirical_flag=1;
      }
      if (use_empirical_flag)
      {
        read_empirical_covariance_matrix(nvar,S,ad_comm::adprogram_name);
      }
      else if (!rescale_bounded_flag)
      {
        int tmp;
        read_covariance_matrix(S,nvar,tmp,sscale);
      }
      else
      {
        read_hessian_matrix_and_scale1(nvar,S,rescale_bounded_power,
          mcmc2_flag);
        //read_hessian_matrix_and_scale(nvar,S,pen_vector);
      }

      {  // scale covariance matrix for model space
        dmatrix tmp(1,nvar,1,nvar);
        for (int i=1;i<=nvar;i++)
        {
          tmp(i,i)=S(i,i)*(scale(i)*scale(i));
          for (int j=1;j<i;j++)
          {
            tmp(i,j)=S(i,j)*(scale(i)*scale(j));
            tmp(j,i)=tmp(i,j);
          }
        }
        S=tmp;
      }
    }
    else
    {
      S.initialize();
      for (int i=1;i<=nvar;i++)
      {
        S(i,i)=dscale;
      }
    }

    cout << sort(eigenvalues(S)) << endl;
    dmatrix chd = choleski_decomp( (dscale*2.4/sqrt(double(nvar))) * S);
    dmatrix chdinv=inv(chd);
    int sgn;

    dmatrix symbds(1,2,1,nvar);
    initial_params::set_all_simulation_bounds(symbds);
    ofstream ofs_sd1((char*)(ad_comm::adprogram_name + adstring(".mc2")));

    {
      long int iseed=0;
      int number_sims;
      if (nmcmc<=0)
      {
        number_sims=  100000;
      }
      else
      {
        number_sims=  nmcmc;
      }
      //cin >> iseed;
      if (iseed0<=0)
      {
        iseed=-36519;
      }
      else
      {
        iseed=-iseed0;
      }
      if (iseed>0)
      {
        iseed=-iseed;
      }
      cout << "Initial seed value " << iseed << endl;
      random_number_generator rng(iseed);
      rng.better_rand();
      //better_rand(iseed);
      double lprob=0.0;
      double lpinv=0.0;
      double lprob3=0.0;
      // get lower and upper bounds

      independent_variables y(1,nvar);
      independent_variables parsave(1,nvar);

      // read in the mcmc values to date
      int ii=1;
      dmatrix hist;
      if (restart_flag)
      {
        int tmp=0;
        if (!no_sd_mcmc) {
          hist.allocate(1,ndvar,-nslots,nslots);
          tmp=read_hist_data(hist,h,mean_mcmc_values,s,parsave,iseed,
            size_scale);
          values.allocate(1,ndvar,-nslots,nslots);
          for (int i=1;i<=ndvar;i++)
          {
            values(i).fill_seqadd(mean_mcmc_values(i)-0.5*total_spread*s(i)
              +.5*h(i),h(i));
          }
        }
        if (iseed>0)
        {
          iseed=-iseed;
        }
        double br=rng.better_rand();
        if (tmp) have_hist_flag=1;
        chd=size_scale*chd;
        chdinv=chdinv/size_scale;
      }
      else
      {
        int on=-1;
        int nopt=0;
        if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcpin",nopt))>-1)
        {
          if (nopt)
          {
            cifstream cif((char *)ad_comm::argv[on+1]);
            if (!cif)
            {
              cerr << "Error trying to open mcmc par input file "
                   << ad_comm::argv[on+1] << endl;
              exit(1);
            }
            cif >> parsave;
            if (!cif)
            {
              cerr << "Error reading from mcmc par input file "
                   << ad_comm::argv[on+1] << endl;
              exit(1);
            }
          }
          else
          {
            cerr << "Illegal option with -mcpin" << endl;
          }
        }
        else
        {
          ii=1;
          initial_params::copy_all_values(parsave,ii);
        }
      }

      ii=1;
      initial_params::restore_all_values(parsave,ii);

      gradient_structure::set_NO_DERIVATIVES();
      ofstream ogs("sims");
      ogs << nvar << " " << number_sims << endl;
      initial_params::xinit(y);

      send_int_to_slaves(1);
      double llc=-pvm_master_get_monte_carlo_value(nvar,y);
      send_int_to_slaves(1);
      llbest=-pvm_master_get_monte_carlo_value(nvar,y);



      lbmax=llbest;
      // store current mcmc variable values in param_values
      //dmatrix store_mcmc_values(1,number_sims,1,ndvar);
#if defined(USE_BAYES_FACTORS)
      lkvector.allocate(1,number_sims);
#endif
      dvector mcmc_values(1,ndvar);
      dvector mcmc_number_values;
      //if (adjm_ptr) mcmc_number_values.allocate(1,numdvar);
      int offs=1;
      stddev_params::copy_all_values(mcmc_values,offs);

      /*
      if (adjm_ptr)
      {
        offs=1;
        stddev_params::copy_all_number_values(mcmc_number_values,offs);
      }
      */
      int change_ball=2500;
      int nopt;
      if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcscale",nopt))>-1)
      {
        if (nopt)
        {
          int iii=atoi(ad_comm::argv[on+1]);
          if (iii <=0)
          {
            cerr << " Invalid option following command line option -mcball -- "
              << endl << " ignored" << endl;
          }
          else
            change_ball=iii;
        }
      }
      int iac=0;
      int liac=0;
      int isim=0;
      int itmp=0;
      double logr;
      int u_option=0;
      double ll;
      int s_option=1;
      int psvflag=0;
      if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcu"))>-1)
      {
        u_option=1;
      }
      if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcnoscale"))>-1)
      {
        s_option=0;
      }
      //cout << llc << " " << llc << endl;
      int iac_old=0;
      int i_old=0;

      {
       if (!restart_flag)
       {
         pofs_sd =
           new uostream((char*)(ad_comm::adprogram_name + adstring(".mcm")));
       }

      int mcsave_flag=0;
      int mcrestart_flag=option_match(ad_comm::argc,ad_comm::argv,"-mcr");

      if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcsave"))>-1)
      {
        int jj=(int)atof(ad_comm::argv[on+1]);
        if (jj <=0)
        {
          cerr << " Invalid option following command line option -mcsave -- "
            << endl;
        }
        else
        {
          mcsave_flag=jj;
          if ( mcrestart_flag>-1)
          {
            // check that nvar is correct
            {
              uistream uis((char*)(ad_comm::adprogram_name + adstring(".psv")));
              if (!uis)
              {
                cerr << "Error trying to open file" <<
                  ad_comm::adprogram_name + adstring(".psv") <<
                  " for mcrestart" <<   endl;
                cerr << " I am starting a new file " << endl;
                psvflag=1;
              }
              else
              {
                int nv1;
                uis >> nv1;
                if (nv1 !=nvar)
                {
                  cerr << "wrong number of independent variables in" <<
                    ad_comm::adprogram_name + adstring(".psv") <<
                  cerr << " I am starting a new file " << endl;
                  psvflag=1;
                }
              }
            }

            if (!psvflag) {
              pofs_psave=
                new uostream(
                  (char*)(ad_comm::adprogram_name + adstring(".psv")),ios::app);
            } else {
              pofs_psave=
                new uostream((char*)(ad_comm::adprogram_name + adstring(".psv")));
            }

          } else {
Esempio n. 3
0
void mission_start::place_npc_software(mission *miss)
{
 npc* dev = g->find_npc(miss->npc_id);
 if (dev == NULL) {
  debugmsg("Couldn't find NPC! %d", miss->npc_id);
  return;
 }
 g->u.i_add( item("usb_drive", 0) );
 add_msg(_("%s gave you a USB drive."), dev->name.c_str());

 std::string type = "house";

 switch (dev->myclass) {
 case NC_HACKER:
  miss->item_id = "software_hacking";
  break;
 case NC_DOCTOR:
  miss->item_id = "software_medical";
  type = "s_pharm";
  miss->follow_up = MISSION_GET_ZOMBIE_BLOOD_ANAL;
  break;
 case NC_SCIENTIST:
  miss->item_id = "software_math";
  break;
 default:
  miss->item_id = "software_useless";
 }

    int dist = 0;
    point place;
    if (type == "house") {
        place = random_house_in_closest_city();
    } else {
        place = overmap_buffer.find_closest(dev->global_omt_location(), type, dist, false);
    }
    miss->target = place;
    overmap_buffer.reveal(place, 6, g->get_levz());

 tinymap compmap;
 compmap.load(place.x * 2, place.y * 2, g->get_levz(), false);
 point comppoint;

    oter_id oter = overmap_buffer.ter(place.x, place.y, 0);
    if( is_ot_type("house", oter) || is_ot_type("s_pharm", oter) || oter == "" ) {
        std::vector<point> valid;
        for (int x = 0; x < SEEX * 2; x++) {
            for (int y = 0; y < SEEY * 2; y++) {
                if (compmap.ter(x, y) == t_floor && compmap.furn(x, y) == f_null) {
                    bool okay = false;
                    int wall = 0;
                    for (int x2 = x - 1; x2 <= x + 1 && !okay; x2++) {
                        for (int y2 = y - 1; y2 <= y + 1 && !okay; y2++) {
                            if (compmap.furn(x2, y2) == f_bed || compmap.furn(x2, y2) == f_dresser) {
                                okay = true;
                                valid.push_back( point(x, y) );
                            }
                            if ( compmap.has_flag_ter("WALL", x2, y2) ) {
                                wall++;
                            }
                        }
                    }
                    if ( wall == 5 ) {
                        if ( compmap.is_last_ter_wall( true, x, y, SEEX * 2, SEEY * 2, NORTH ) &&
                             compmap.is_last_ter_wall( true, x, y, SEEX * 2, SEEY * 2, SOUTH ) &&
                             compmap.is_last_ter_wall( true, x, y, SEEX * 2, SEEY * 2, WEST ) &&
                             compmap.is_last_ter_wall( true, x, y, SEEX * 2, SEEY * 2, EAST ) ) {
                            valid.push_back( point(x, y) );
                        }
                    }
                }
            }
        }
        if (valid.empty()) {
            comppoint = point( rng(6, SEEX * 2 - 7), rng(6, SEEY * 2 - 7) );
        } else {
            comppoint = valid[rng(0, valid.size() - 1)];
        }
    }

 compmap.ter_set(comppoint.x, comppoint.y, t_console);
 computer *tmpcomp = compmap.add_computer(comppoint.x, comppoint.y, string_format(_("%s's Terminal"), dev->name.c_str()), 0);
 tmpcomp->mission_id = miss->uid;
 tmpcomp->add_option(_("Download Software"), COMPACT_DOWNLOAD_SOFTWARE, 0);
 compmap.save();
}
Esempio n. 4
0
bool monster::move_to( const tripoint &p, bool force, const float stagger_adjustment )
{
    const bool digs = digging();
    const bool flies = has_flag( MF_FLIES );
    const bool on_ground = !digs && !flies;
    const bool climbs = has_flag( MF_CLIMBS ) && g->m.has_flag( TFLAG_NO_FLOOR, p );
    // Allows climbing monsters to move on terrain with movecost <= 0
    Creature *critter = g->critter_at( p, is_hallucination() );
    if( g->m.has_flag( "CLIMBABLE", p ) ) {
        if( g->m.impassable( p ) && critter == nullptr ) {
            if( flies ) {
                moves -= 100;
                force = true;
                if( g->u.sees( *this ) ) {
                    add_msg( _( "The %1$s flies over the %2$s." ), name().c_str(),
                             g->m.has_flag_furn( "CLIMBABLE", p ) ? g->m.furnname( p ).c_str() :
                             g->m.tername( p ).c_str() );
                }
            } else if( has_flag( MF_CLIMBS ) ) {
                moves -= 150;
                force = true;
                if( g->u.sees( *this ) ) {
                    add_msg( _( "The %1$s climbs over the %2$s." ), name().c_str(),
                             g->m.has_flag_furn( "CLIMBABLE", p ) ? g->m.furnname( p ).c_str() :
                             g->m.tername( p ).c_str() );
                }
            }
        }
    }

    if( critter != nullptr && !force ) {
        return false;
    }

    // Make sure that we can move there, unless force is true.
    if( !force && !can_move_to( p ) ) {
        return false;
    }

    if( !force ) {
        // This adjustment is to make it so that monster movement speed relative to the player
        // is consistent even if the monster stumbles,
        // and the same regardless of the distance measurement mode.
        // Note: Keep this as float here or else it will cancel valid moves
        const float cost = stagger_adjustment *
                           ( float )( climbs ? calc_climb_cost( pos(), p ) :
                                      calc_movecost( pos(), p ) );
        if( cost > 0.0f ) {
            moves -= ( int )ceil( cost );
        } else {
            return false;
        }
    }

    //Check for moving into/out of water
    bool was_water = g->m.is_divable( pos() );
    bool will_be_water = on_ground && can_submerge() && g->m.is_divable( p );

    if( was_water && !will_be_water && g->u.sees( p ) ) {
        //Use more dramatic messages for swimming monsters
        add_msg( m_warning, _( "A %1$s %2$s from the %3$s!" ), name().c_str(),
                 has_flag( MF_SWIMS ) || has_flag( MF_AQUATIC ) ? _( "leaps" ) : _( "emerges" ),
                 g->m.tername( pos() ).c_str() );
    } else if( !was_water && will_be_water && g->u.sees( p ) ) {
        add_msg( m_warning, _( "A %1$s %2$s into the %3$s!" ), name().c_str(),
                 has_flag( MF_SWIMS ) || has_flag( MF_AQUATIC ) ? _( "dives" ) : _( "sinks" ),
                 g->m.tername( p ).c_str() );
    }

    setpos( p );
    footsteps( p );
    underwater = will_be_water;
    if( is_hallucination() ) {
        //Hallucinations don't do any of the stuff after this point
        return true;
    }
    // TODO: Make tanks stop taking damage from rubble, because it's just silly
    if( type->size != MS_TINY && on_ground ) {
        if( g->m.has_flag( "SHARP", pos() ) && !one_in( 4 ) ) {
            apply_damage( nullptr, bp_torso, rng( 1, 10 ) );
        }
        if( g->m.has_flag( "ROUGH", pos() ) && one_in( 6 ) ) {
            apply_damage( nullptr, bp_torso, rng( 1, 2 ) );
        }

    }

    if( g->m.has_flag( "UNSTABLE", p ) && on_ground ) {
        add_effect( effect_bouldering, 1, num_bp, true );
    } else if( has_effect( effect_bouldering ) ) {
        remove_effect( effect_bouldering );
    }
    g->m.creature_on_trap( *this );
    if( !will_be_water && ( has_flag( MF_DIGS ) || has_flag( MF_CAN_DIG ) ) ) {
        underwater = g->m.has_flag( "DIGGABLE", pos() );
    }
    // Diggers turn the dirt into dirtmound
    if( digging() ) {
        int factor = 0;
        switch( type->size ) {
            case MS_TINY:
                factor = 100;
                break;
            case MS_SMALL:
                factor = 30;
                break;
            case MS_MEDIUM:
                factor = 6;
                break;
            case MS_LARGE:
                factor = 3;
                break;
            case MS_HUGE:
                factor = 1;
                break;
        }
        if( one_in( factor ) ) {
            g->m.ter_set( pos(), t_dirtmound );
        }
    }
    // Acid trail monsters leave... a trail of acid
    if( has_flag( MF_ACIDTRAIL ) ) {
        g->m.add_field( pos(), fd_acid, 3, 0 );
    }

    if( has_flag( MF_SLUDGETRAIL ) ) {
        for( const tripoint &sludge_p : g->m.points_in_radius( pos(), 1 ) ) {
            const int fstr = 3 - ( abs( sludge_p.x - posx() ) + abs( sludge_p.y - posy() ) );
            if( fstr >= 2 ) {
                g->m.add_field( sludge_p, fd_sludge, fstr, 0 );
            }
        }
    }

    return true;
}
Esempio n. 5
0
/*! \brief Do test particle insertion.
    \copydoc integrator_t (FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                           int nfile, const t_filenm fnm[],
                           const gmx_output_env_t *oenv, gmx_bool bVerbose,
                           int nstglobalcomm,
                           gmx_vsite_t *vsite, gmx_constr_t constr,
                           int stepout,
                           t_inputrec *inputrec,
                           gmx_mtop_t *top_global, t_fcdata *fcd,
                           t_state *state_global,
                           t_mdatoms *mdatoms,
                           t_nrnb *nrnb, gmx_wallcycle_t wcycle,
                           gmx_edsam_t ed,
                           t_forcerec *fr,
                           int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
                           real cpt_period, real max_hours,
                           int imdport,
                           unsigned long Flags,
                           gmx_walltime_accounting_t walltime_accounting)
 */
double do_tpi(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
              int nfile, const t_filenm fnm[],
              const gmx_output_env_t *oenv, gmx_bool bVerbose,
              int gmx_unused nstglobalcomm,
              gmx_vsite_t gmx_unused *vsite, gmx_constr_t gmx_unused constr,
              int gmx_unused stepout,
              t_inputrec *inputrec,
              gmx_mtop_t *top_global, t_fcdata *fcd,
              t_state *state_global,
              t_mdatoms *mdatoms,
              t_nrnb *nrnb, gmx_wallcycle_t wcycle,
              gmx_edsam_t gmx_unused ed,
              t_forcerec *fr,
              int gmx_unused repl_ex_nst, int gmx_unused repl_ex_nex, int gmx_unused repl_ex_seed,
              real gmx_unused cpt_period, real gmx_unused max_hours,
              int gmx_unused imdport,
              unsigned long gmx_unused Flags,
              gmx_walltime_accounting_t walltime_accounting)
{
    gmx_localtop_t *top;
    gmx_groups_t   *groups;
    gmx_enerdata_t *enerd;
    rvec           *f;
    real            lambda, t, temp, beta, drmax, epot;
    double          embU, sum_embU, *sum_UgembU, V, V_all, VembU_all;
    t_trxstatus    *status;
    t_trxframe      rerun_fr;
    gmx_bool        bDispCorr, bCharge, bRFExcl, bNotLastFrame, bStateChanged, bNS;
    tensor          force_vir, shake_vir, vir, pres;
    int             cg_tp, a_tp0, a_tp1, ngid, gid_tp, nener, e;
    rvec           *x_mol;
    rvec            mu_tot, x_init, dx, x_tp;
    int             nnodes, frame;
    gmx_int64_t     frame_step_prev, frame_step;
    gmx_int64_t     nsteps, stepblocksize = 0, step;
    gmx_int64_t     seed;
    int             i;
    FILE           *fp_tpi = NULL;
    char           *ptr, *dump_pdb, **leg, str[STRLEN], str2[STRLEN];
    double          dbl, dump_ener;
    gmx_bool        bCavity;
    int             nat_cavity  = 0, d;
    real           *mass_cavity = NULL, mass_tot;
    int             nbin;
    double          invbinw, *bin, refvolshift, logV, bUlogV;
    real            prescorr, enercorr, dvdlcorr;
    gmx_bool        bEnergyOutOfBounds;
    const char     *tpid_leg[2] = {"direct", "reweighted"};

    /* Since there is no upper limit to the insertion energies,
     * we need to set an upper limit for the distribution output.
     */
    real bU_bin_limit      = 50;
    real bU_logV_bin_limit = bU_bin_limit + 10;

    if (inputrec->cutoff_scheme == ecutsVERLET)
    {
        gmx_fatal(FARGS, "TPI does not work (yet) with the Verlet cut-off scheme");
    }

    nnodes = cr->nnodes;

    top = gmx_mtop_generate_local_top(top_global, inputrec->efep != efepNO);

    groups = &top_global->groups;

    bCavity = (inputrec->eI == eiTPIC);
    if (bCavity)
    {
        ptr = getenv("GMX_TPIC_MASSES");
        if (ptr == NULL)
        {
            nat_cavity = 1;
        }
        else
        {
            /* Read (multiple) masses from env var GMX_TPIC_MASSES,
             * The center of mass of the last atoms is then used for TPIC.
             */
            nat_cavity = 0;
            while (sscanf(ptr, "%20lf%n", &dbl, &i) > 0)
            {
                srenew(mass_cavity, nat_cavity+1);
                mass_cavity[nat_cavity] = dbl;
                fprintf(fplog, "mass[%d] = %f\n",
                        nat_cavity+1, mass_cavity[nat_cavity]);
                nat_cavity++;
                ptr += i;
            }
            if (nat_cavity == 0)
            {
                gmx_fatal(FARGS, "Found %d masses in GMX_TPIC_MASSES", nat_cavity);
            }
        }
    }

    /*
       init_em(fplog,TPI,inputrec,&lambda,nrnb,mu_tot,
       state_global->box,fr,mdatoms,top,cr,nfile,fnm,NULL,NULL);*/
    /* We never need full pbc for TPI */
    fr->ePBC = epbcXYZ;
    /* Determine the temperature for the Boltzmann weighting */
    temp = inputrec->opts.ref_t[0];
    if (fplog)
    {
        for (i = 1; (i < inputrec->opts.ngtc); i++)
        {
            if (inputrec->opts.ref_t[i] != temp)
            {
                fprintf(fplog, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
                fprintf(stderr, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
            }
        }
        fprintf(fplog,
                "\n  The temperature for test particle insertion is %.3f K\n\n",
                temp);
    }
    beta = 1.0/(BOLTZ*temp);

    /* Number of insertions per frame */
    nsteps = inputrec->nsteps;

    /* Use the same neighborlist with more insertions points
     * in a sphere of radius drmax around the initial point
     */
    /* This should be a proper mdp parameter */
    drmax = inputrec->rtpi;

    /* An environment variable can be set to dump all configurations
     * to pdb with an insertion energy <= this value.
     */
    dump_pdb  = getenv("GMX_TPI_DUMP");
    dump_ener = 0;
    if (dump_pdb)
    {
        sscanf(dump_pdb, "%20lf", &dump_ener);
    }

    atoms2md(top_global, inputrec, 0, NULL, top_global->natoms, mdatoms);
    update_mdatoms(mdatoms, inputrec->fepvals->init_lambda);

    snew(enerd, 1);
    init_enerdata(groups->grps[egcENER].nr, inputrec->fepvals->n_lambda, enerd);
    snew(f, top_global->natoms);

    /* Print to log file  */
    walltime_accounting_start(walltime_accounting);
    wallcycle_start(wcycle, ewcRUN);
    print_start(fplog, cr, walltime_accounting, "Test Particle Insertion");

    /* The last charge group is the group to be inserted */
    cg_tp = top->cgs.nr - 1;
    a_tp0 = top->cgs.index[cg_tp];
    a_tp1 = top->cgs.index[cg_tp+1];
    if (debug)
    {
        fprintf(debug, "TPI cg %d, atoms %d-%d\n", cg_tp, a_tp0, a_tp1);
    }

    GMX_RELEASE_ASSERT(inputrec->rcoulomb <= inputrec->rlist && inputrec->rvdw <= inputrec->rlist, "Twin-range interactions are not supported with TPI");

    snew(x_mol, a_tp1-a_tp0);

    bDispCorr = (inputrec->eDispCorr != edispcNO);
    bCharge   = FALSE;
    for (i = a_tp0; i < a_tp1; i++)
    {
        /* Copy the coordinates of the molecule to be insterted */
        copy_rvec(state_global->x[i], x_mol[i-a_tp0]);
        /* Check if we need to print electrostatic energies */
        bCharge |= (mdatoms->chargeA[i] != 0 ||
                    (mdatoms->chargeB && mdatoms->chargeB[i] != 0));
    }
    bRFExcl = (bCharge && EEL_RF(fr->eeltype));

    calc_cgcm(fplog, cg_tp, cg_tp+1, &(top->cgs), state_global->x, fr->cg_cm);
    if (bCavity)
    {
        if (norm(fr->cg_cm[cg_tp]) > 0.5*inputrec->rlist && fplog)
        {
            fprintf(fplog, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
            fprintf(stderr, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
        }
    }
    else
    {
        /* Center the molecule to be inserted at zero */
        for (i = 0; i < a_tp1-a_tp0; i++)
        {
            rvec_dec(x_mol[i], fr->cg_cm[cg_tp]);
        }
    }

    if (fplog)
    {
        fprintf(fplog, "\nWill insert %d atoms %s partial charges\n",
                a_tp1-a_tp0, bCharge ? "with" : "without");

        fprintf(fplog, "\nWill insert %d times in each frame of %s\n",
                (int)nsteps, opt2fn("-rerun", nfile, fnm));
    }

    if (!bCavity)
    {
        if (inputrec->nstlist > 1)
        {
            if (drmax == 0 && a_tp1-a_tp0 == 1)
            {
                gmx_fatal(FARGS, "Re-using the neighborlist %d times for insertions of a single atom in a sphere of radius %f does not make sense", inputrec->nstlist, drmax);
            }
            if (fplog)
            {
                fprintf(fplog, "Will use the same neighborlist for %d insertions in a sphere of radius %f\n", inputrec->nstlist, drmax);
            }
        }
    }
    else
    {
        if (fplog)
        {
            fprintf(fplog, "Will insert randomly in a sphere of radius %f around the center of the cavity\n", drmax);
        }
    }

    ngid   = groups->grps[egcENER].nr;
    gid_tp = GET_CGINFO_GID(fr->cginfo[cg_tp]);
    nener  = 1 + ngid;
    if (bDispCorr)
    {
        nener += 1;
    }
    if (bCharge)
    {
        nener += ngid;
        if (bRFExcl)
        {
            nener += 1;
        }
        if (EEL_FULL(fr->eeltype))
        {
            nener += 1;
        }
    }
    snew(sum_UgembU, nener);

    /* Copy the random seed set by the user */
    seed = inputrec->ld_seed;

    gmx::ThreeFry2x64<16>                rng(seed, gmx::RandomDomain::TestParticleInsertion); // 16 bits internal counter => 2^16 * 2 = 131072 values per stream
    gmx::UniformRealDistribution<real>   dist;

    if (MASTER(cr))
    {
        fp_tpi = xvgropen(opt2fn("-tpi", nfile, fnm),
                          "TPI energies", "Time (ps)",
                          "(kJ mol\\S-1\\N) / (nm\\S3\\N)", oenv);
        xvgr_subtitle(fp_tpi, "f. are averages over one frame", oenv);
        snew(leg, 4+nener);
        e = 0;
        sprintf(str, "-kT log(<Ve\\S-\\betaU\\N>/<V>)");
        leg[e++] = gmx_strdup(str);
        sprintf(str, "f. -kT log<e\\S-\\betaU\\N>");
        leg[e++] = gmx_strdup(str);
        sprintf(str, "f. <e\\S-\\betaU\\N>");
        leg[e++] = gmx_strdup(str);
        sprintf(str, "f. V");
        leg[e++] = gmx_strdup(str);
        sprintf(str, "f. <Ue\\S-\\betaU\\N>");
        leg[e++] = gmx_strdup(str);
        for (i = 0; i < ngid; i++)
        {
            sprintf(str, "f. <U\\sVdW %s\\Ne\\S-\\betaU\\N>",
                    *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
            leg[e++] = gmx_strdup(str);
        }
        if (bDispCorr)
        {
            sprintf(str, "f. <U\\sdisp c\\Ne\\S-\\betaU\\N>");
            leg[e++] = gmx_strdup(str);
        }
        if (bCharge)
        {
            for (i = 0; i < ngid; i++)
            {
                sprintf(str, "f. <U\\sCoul %s\\Ne\\S-\\betaU\\N>",
                        *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
                leg[e++] = gmx_strdup(str);
            }
            if (bRFExcl)
            {
                sprintf(str, "f. <U\\sRF excl\\Ne\\S-\\betaU\\N>");
                leg[e++] = gmx_strdup(str);
            }
            if (EEL_FULL(fr->eeltype))
            {
                sprintf(str, "f. <U\\sCoul recip\\Ne\\S-\\betaU\\N>");
                leg[e++] = gmx_strdup(str);
            }
        }
        xvgr_legend(fp_tpi, 4+nener, (const char**)leg, oenv);
        for (i = 0; i < 4+nener; i++)
        {
            sfree(leg[i]);
        }
        sfree(leg);
    }
    clear_rvec(x_init);
    V_all     = 0;
    VembU_all = 0;

    invbinw = 10;
    nbin    = 10;
    snew(bin, nbin);

    /* Avoid frame step numbers <= -1 */
    frame_step_prev = -1;

    bNotLastFrame = read_first_frame(oenv, &status, opt2fn("-rerun", nfile, fnm),
                                     &rerun_fr, TRX_NEED_X);
    frame = 0;

    if (rerun_fr.natoms - (bCavity ? nat_cavity : 0) !=
        mdatoms->nr - (a_tp1 - a_tp0))
    {
        gmx_fatal(FARGS, "Number of atoms in trajectory (%d)%s "
                  "is not equal the number in the run input file (%d) "
                  "minus the number of atoms to insert (%d)\n",
                  rerun_fr.natoms, bCavity ? " minus one" : "",
                  mdatoms->nr, a_tp1-a_tp0);
    }

    refvolshift = log(det(rerun_fr.box));

    switch (inputrec->eI)
    {
        case eiTPI:
            stepblocksize = inputrec->nstlist;
            break;
        case eiTPIC:
            stepblocksize = 1;
            break;
        default:
            gmx_fatal(FARGS, "Unknown integrator %s", ei_names[inputrec->eI]);
    }

    while (bNotLastFrame)
    {
        frame_step      = rerun_fr.step;
        if (frame_step <= frame_step_prev)
        {
            /* We don't have step number in the trajectory file,
             * or we have constant or decreasing step numbers.
             * Ensure we have increasing step numbers, since we use
             * the step numbers as a counter for random numbers.
             */
            frame_step  = frame_step_prev + 1;
        }
        frame_step_prev = frame_step;

        lambda = rerun_fr.lambda;
        t      = rerun_fr.time;

        sum_embU = 0;
        for (e = 0; e < nener; e++)
        {
            sum_UgembU[e] = 0;
        }

        /* Copy the coordinates from the input trajectory */
        for (i = 0; i < rerun_fr.natoms; i++)
        {
            copy_rvec(rerun_fr.x[i], state_global->x[i]);
        }
        copy_mat(rerun_fr.box, state_global->box);

        V    = det(state_global->box);
        logV = log(V);

        bStateChanged = TRUE;
        bNS           = TRUE;

        step = cr->nodeid*stepblocksize;
        while (step < nsteps)
        {
            /* Restart random engine using the frame and insertion step
             * as counters.
             * Note that we need to draw several random values per iteration,
             * but by using the internal subcounter functionality of ThreeFry2x64
             * we can draw 131072 unique 64-bit values before exhausting
             * the stream. This is a huge margin, and if something still goes
             * wrong you will get an exception when the stream is exhausted.
             */
            rng.restart(frame_step, step);
            dist.reset();  // erase any memory in the distribution

            if (!bCavity)
            {
                /* Random insertion in the whole volume */
                bNS = (step % inputrec->nstlist == 0);
                if (bNS)
                {
                    /* Generate a random position in the box */
                    for (d = 0; d < DIM; d++)
                    {
                        x_init[d] = dist(rng)*state_global->box[d][d];
                    }
                }

                if (inputrec->nstlist == 1)
                {
                    copy_rvec(x_init, x_tp);
                }
                else
                {
                    /* Generate coordinates within |dx|=drmax of x_init */
                    do
                    {
                        for (d = 0; d < DIM; d++)
                        {
                            dx[d] = (2*dist(rng) - 1)*drmax;
                        }
                    }
                    while (norm2(dx) > drmax*drmax);
                    rvec_add(x_init, dx, x_tp);
                }
            }
            else
            {
                /* Random insertion around a cavity location
                 * given by the last coordinate of the trajectory.
                 */
                if (step == 0)
                {
                    if (nat_cavity == 1)
                    {
                        /* Copy the location of the cavity */
                        copy_rvec(rerun_fr.x[rerun_fr.natoms-1], x_init);
                    }
                    else
                    {
                        /* Determine the center of mass of the last molecule */
                        clear_rvec(x_init);
                        mass_tot = 0;
                        for (i = 0; i < nat_cavity; i++)
                        {
                            for (d = 0; d < DIM; d++)
                            {
                                x_init[d] +=
                                    mass_cavity[i]*rerun_fr.x[rerun_fr.natoms-nat_cavity+i][d];
                            }
                            mass_tot += mass_cavity[i];
                        }
                        for (d = 0; d < DIM; d++)
                        {
                            x_init[d] /= mass_tot;
                        }
                    }
                }
                /* Generate coordinates within |dx|=drmax of x_init */
                do
                {
                    for (d = 0; d < DIM; d++)
                    {
                        dx[d] = (2*dist(rng) - 1)*drmax;
                    }
                }
                while (norm2(dx) > drmax*drmax);
                rvec_add(x_init, dx, x_tp);
            }

            if (a_tp1 - a_tp0 == 1)
            {
                /* Insert a single atom, just copy the insertion location */
                copy_rvec(x_tp, state_global->x[a_tp0]);
            }
            else
            {
                /* Copy the coordinates from the top file */
                for (i = a_tp0; i < a_tp1; i++)
                {
                    copy_rvec(x_mol[i-a_tp0], state_global->x[i]);
                }
                /* Rotate the molecule randomly */
                rotate_conf(a_tp1-a_tp0, state_global->x+a_tp0, NULL,
                            2*M_PI*dist(rng),
                            2*M_PI*dist(rng),
                            2*M_PI*dist(rng));
                /* Shift to the insertion location */
                for (i = a_tp0; i < a_tp1; i++)
                {
                    rvec_inc(state_global->x[i], x_tp);
                }
            }

            /* Clear some matrix variables  */
            clear_mat(force_vir);
            clear_mat(shake_vir);
            clear_mat(vir);
            clear_mat(pres);

            /* Set the charge group center of mass of the test particle */
            copy_rvec(x_init, fr->cg_cm[top->cgs.nr-1]);

            /* Calc energy (no forces) on new positions.
             * Since we only need the intermolecular energy
             * and the RF exclusion terms of the inserted molecule occur
             * within a single charge group we can pass NULL for the graph.
             * This also avoids shifts that would move charge groups
             * out of the box. */
            /* Make do_force do a single node force calculation */
            cr->nnodes = 1;
            do_force(fplog, cr, inputrec,
                     step, nrnb, wcycle, top, &top_global->groups,
                     state_global->box, state_global->x, &state_global->hist,
                     f, force_vir, mdatoms, enerd, fcd,
                     state_global->lambda,
                     NULL, fr, NULL, mu_tot, t, NULL, NULL, FALSE,
                     GMX_FORCE_NONBONDED | GMX_FORCE_ENERGY |
                     (bNS ? GMX_FORCE_DYNAMICBOX | GMX_FORCE_NS : 0) |
                     (bStateChanged ? GMX_FORCE_STATECHANGED : 0));
            cr->nnodes    = nnodes;
            bStateChanged = FALSE;
            bNS           = FALSE;

            /* Calculate long range corrections to pressure and energy */
            calc_dispcorr(inputrec, fr, state_global->box,
                          lambda, pres, vir, &prescorr, &enercorr, &dvdlcorr);
            /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */
            enerd->term[F_DISPCORR]  = enercorr;
            enerd->term[F_EPOT]     += enercorr;
            enerd->term[F_PRES]     += prescorr;
            enerd->term[F_DVDL_VDW] += dvdlcorr;

            epot               = enerd->term[F_EPOT];
            bEnergyOutOfBounds = FALSE;

            /* If the compiler doesn't optimize this check away
             * we catch the NAN energies.
             * The epot>GMX_REAL_MAX check catches inf values,
             * which should nicely result in embU=0 through the exp below,
             * but it does not hurt to check anyhow.
             */
            /* Non-bonded Interaction usually diverge at r=0.
             * With tabulated interaction functions the first few entries
             * should be capped in a consistent fashion between
             * repulsion, dispersion and Coulomb to avoid accidental
             * negative values in the total energy.
             * The table generation code in tables.c does this.
             * With user tbales the user should take care of this.
             */
            if (epot != epot || epot > GMX_REAL_MAX)
            {
                bEnergyOutOfBounds = TRUE;
            }
            if (bEnergyOutOfBounds)
            {
                if (debug)
                {
                    fprintf(debug, "\n  time %.3f, step %d: non-finite energy %f, using exp(-bU)=0\n", t, (int)step, epot);
                }
                embU = 0;
            }
            else
            {
                embU      = exp(-beta*epot);
                sum_embU += embU;
                /* Determine the weighted energy contributions of each energy group */
                e                = 0;
                sum_UgembU[e++] += epot*embU;
                if (fr->bBHAM)
                {
                    for (i = 0; i < ngid; i++)
                    {
                        sum_UgembU[e++] +=
                            enerd->grpp.ener[egBHAMSR][GID(i, gid_tp, ngid)]*embU;
                    }
                }
                else
                {
                    for (i = 0; i < ngid; i++)
                    {
                        sum_UgembU[e++] +=
                            enerd->grpp.ener[egLJSR][GID(i, gid_tp, ngid)]*embU;
                    }
                }
                if (bDispCorr)
                {
                    sum_UgembU[e++] += enerd->term[F_DISPCORR]*embU;
                }
                if (bCharge)
                {
                    for (i = 0; i < ngid; i++)
                    {
                        sum_UgembU[e++] += enerd->grpp.ener[egCOULSR][GID(i, gid_tp, ngid)] * embU;
                    }
                    if (bRFExcl)
                    {
                        sum_UgembU[e++] += enerd->term[F_RF_EXCL]*embU;
                    }
                    if (EEL_FULL(fr->eeltype))
                    {
                        sum_UgembU[e++] += enerd->term[F_COUL_RECIP]*embU;
                    }
                }
            }

            if (embU == 0 || beta*epot > bU_bin_limit)
            {
                bin[0]++;
            }
            else
            {
                i = (int)((bU_logV_bin_limit
                           - (beta*epot - logV + refvolshift))*invbinw
                          + 0.5);
                if (i < 0)
                {
                    i = 0;
                }
                if (i >= nbin)
                {
                    realloc_bins(&bin, &nbin, i+10);
                }
                bin[i]++;
            }

            if (debug)
            {
                fprintf(debug, "TPI %7d %12.5e %12.5f %12.5f %12.5f\n",
                        (int)step, epot, x_tp[XX], x_tp[YY], x_tp[ZZ]);
            }

            if (dump_pdb && epot <= dump_ener)
            {
                sprintf(str, "t%g_step%d.pdb", t, (int)step);
                sprintf(str2, "t: %f step %d ener: %f", t, (int)step, epot);
                write_sto_conf_mtop(str, str2, top_global, state_global->x, state_global->v,
                                    inputrec->ePBC, state_global->box);
            }

            step++;
            if ((step/stepblocksize) % cr->nnodes != cr->nodeid)
            {
                /* Skip all steps assigned to the other MPI ranks */
                step += (cr->nnodes - 1)*stepblocksize;
            }
        }

        if (PAR(cr))
        {
            /* When running in parallel sum the energies over the processes */
            gmx_sumd(1,    &sum_embU, cr);
            gmx_sumd(nener, sum_UgembU, cr);
        }

        frame++;
        V_all     += V;
        VembU_all += V*sum_embU/nsteps;

        if (fp_tpi)
        {
            if (bVerbose || frame%10 == 0 || frame < 10)
            {
                fprintf(stderr, "mu %10.3e <mu> %10.3e\n",
                        -log(sum_embU/nsteps)/beta, -log(VembU_all/V_all)/beta);
            }

            fprintf(fp_tpi, "%10.3f %12.5e %12.5e %12.5e %12.5e",
                    t,
                    VembU_all == 0 ? 20/beta : -log(VembU_all/V_all)/beta,
                    sum_embU == 0  ? 20/beta : -log(sum_embU/nsteps)/beta,
                    sum_embU/nsteps, V);
            for (e = 0; e < nener; e++)
            {
                fprintf(fp_tpi, " %12.5e", sum_UgembU[e]/nsteps);
            }
            fprintf(fp_tpi, "\n");
            fflush(fp_tpi);
        }

        bNotLastFrame = read_next_frame(oenv, status, &rerun_fr);
    }   /* End of the loop  */
    walltime_accounting_end(walltime_accounting);

    close_trj(status);

    if (fp_tpi != NULL)
    {
        xvgrclose(fp_tpi);
    }

    if (fplog != NULL)
    {
        fprintf(fplog, "\n");
        fprintf(fplog, "  <V>  = %12.5e nm^3\n", V_all/frame);
        fprintf(fplog, "  <mu> = %12.5e kJ/mol\n", -log(VembU_all/V_all)/beta);
    }

    /* Write the Boltzmann factor histogram */
    if (PAR(cr))
    {
        /* When running in parallel sum the bins over the processes */
        i = nbin;
        global_max(cr, &i);
        realloc_bins(&bin, &nbin, i);
        gmx_sumd(nbin, bin, cr);
    }
    if (MASTER(cr))
    {
        fp_tpi = xvgropen(opt2fn("-tpid", nfile, fnm),
                          "TPI energy distribution",
                          "\\betaU - log(V/<V>)", "count", oenv);
        sprintf(str, "number \\betaU > %g: %9.3e", bU_bin_limit, bin[0]);
        xvgr_subtitle(fp_tpi, str, oenv);
        xvgr_legend(fp_tpi, 2, (const char **)tpid_leg, oenv);
        for (i = nbin-1; i > 0; i--)
        {
            bUlogV = -i/invbinw + bU_logV_bin_limit - refvolshift + log(V_all/frame);
            fprintf(fp_tpi, "%6.2f %10d %12.5e\n",
                    bUlogV,
                    (int)(bin[i]+0.5),
                    bin[i]*exp(-bUlogV)*V_all/VembU_all);
        }
        xvgrclose(fp_tpi);
    }
    sfree(bin);

    sfree(sum_UgembU);

    walltime_accounting_set_nsteps_done(walltime_accounting, frame*inputrec->nsteps);

    return 0;
}
Esempio n. 6
0
body_part Creature::select_body_part(Creature *source, int hit_roll)
{
    // Get size difference (-1,0,1);
    int szdif = source->get_size() - get_size();
    if(szdif < -1) {
        szdif = -1;
    } else if (szdif > 1) {
        szdif = 1;
    }

    add_msg( m_debug, "source size = %d", source->get_size() );
    add_msg( m_debug, "target size = %d", get_size() );
    add_msg( m_debug, "difference = %d", szdif );

    std::map<body_part, double> hit_weights = default_hit_weights[szdif];
    std::map<body_part, double>::iterator iter;

    // If the target is on the ground, even small/tiny creatures may target eyes/head. Also increases chances of larger creatures.
    // Any hit modifiers to locations should go here. (Tags, attack style, etc)
    if(is_on_ground()) {
        hit_weights[bp_eyes] += 10;
        hit_weights[bp_head] += 20;
    }

    //Adjust based on hit roll: Eyes, Head & Torso get higher, while Arms and Legs get lower.
    //This should eventually be replaced with targeted attacks and this being miss chances.
    hit_weights[bp_eyes] = floor(hit_weights[bp_eyes] * std::pow(hit_roll, 1.15) * 10);
    hit_weights[bp_head] = floor(hit_weights[bp_head] * std::pow(hit_roll, 1.15) * 10);
    hit_weights[bp_torso] = floor(hit_weights[bp_torso] * std::pow(hit_roll, 1) * 10);
    hit_weights[bp_arm_l] = floor(hit_weights[bp_arm_l] * std::pow(hit_roll, 0.95) * 10);
    hit_weights[bp_arm_r] = floor(hit_weights[bp_arm_r] * std::pow(hit_roll, 0.95) * 10);
    hit_weights[bp_leg_l] = floor(hit_weights[bp_leg_l] * std::pow(hit_roll, 0.975) * 10);
    hit_weights[bp_leg_r] = floor(hit_weights[bp_leg_r] * std::pow(hit_roll, 0.975) * 10);


    // Debug for seeing weights.
    add_msg( m_debug, "eyes = %f", hit_weights.at( bp_eyes ) );
    add_msg( m_debug, "head = %f", hit_weights.at( bp_head ) );
    add_msg( m_debug, "torso = %f", hit_weights.at( bp_torso ) );
    add_msg( m_debug, "arm_l = %f", hit_weights.at( bp_arm_l ) );
    add_msg( m_debug, "arm_r = %f", hit_weights.at( bp_arm_r ) );
    add_msg( m_debug, "leg_l = %f", hit_weights.at( bp_leg_l ) );
    add_msg( m_debug, "leg_r = %f", hit_weights.at( bp_leg_r ) );

    double totalWeight = 0;
    std::set<std::pair<body_part, double>, weight_compare> adjusted_weights;
    for(iter = hit_weights.begin(); iter != hit_weights.end(); ++iter) {
        totalWeight += iter->second;
        adjusted_weights.insert(*iter);
    }

    body_part selected_part = bp_torso;

    // Blood thirsty monsters can discard body part and go to more damaged
    int part_rolls = 1;
    int repick_chance = 50;
    if (source->has_flag(MF_BLOODTHIRSTY)) {
        part_rolls += 2;
        if (is_player() && g->u.has_trait("ANIMALEMPATH")) {
            part_rolls -= 1;
            repick_chance -= 10;
        }
        if (is_player() && g->u.has_trait("ANIMALDISCORD")) {
            part_rolls += 1;
            repick_chance += 10;
        }
    }
    body_part last_part = selected_part;
    for(int r = 0; r < part_rolls; ++r) {
        double roll = rng_float(1, totalWeight);
        std::set<std::pair<body_part, double>, weight_compare>::iterator adj_iter;
        for(adj_iter = adjusted_weights.begin(); adj_iter != adjusted_weights.end(); ++adj_iter) {
            roll -= adj_iter->second;
            if(roll <= 0) {
                selected_part = adj_iter->first;
                break;
            }
        }

        if (r != 0) {
            hp_part hpart_cur = bodypart_to_hp_part(selected_part);
            hp_part hpart_lst = bodypart_to_hp_part(last_part);
            double ratio_cur = get_hp(hpart_cur) / float(get_hp_max(hpart_cur));
            double ratio_lst = get_hp(hpart_lst) / float(get_hp_max(hpart_lst));
            body_part cur_pick_part = selected_part;
            if(ratio_cur > ratio_lst && repick_chance >= rng(1,100))
                selected_part = last_part;
            add_msg( m_debug, "picked %s from %s(%.2f)/%s(%.2f)",
                        body_part_name(selected_part).c_str(), 
                        body_part_name(cur_pick_part).c_str(), ratio_cur,
                        body_part_name(last_part).c_str(), ratio_lst);
        }
        last_part = selected_part;
    }

    return selected_part;
}
Esempio n. 7
0
bool monster::push_to( const tripoint &p, const int boost, const size_t depth )
{
    if( is_hallucination() ) {
        // Don't let hallucinations push, not even other hallucinations
        return false;
    }

    if( !has_flag( MF_PUSH_MON ) || depth > 2 || has_effect( effect_pushed ) ) {
        return false;
    }

    // TODO: Generalize this to Creature
    monster *const critter = g->critter_at<monster>( p );
    if( critter == nullptr || critter == this || p == pos() ) {
        return false;
    }

    if( !can_move_to( p ) ) {
        return false;
    }

    if( critter->is_hallucination() ) {
        // Kill the hallu, but return false so that the regular move_to is uses instead
        critter->die( nullptr );
        return false;
    }

    // Stability roll of the pushed critter
    const int defend = critter->stability_roll();
    // Stability roll of the pushing zed
    const int attack = stability_roll() + boost;
    if( defend > attack ) {
        return false;
    }

    const int movecost_from = 50 * g->m.move_cost( p );
    const int movecost_attacker = std::max( movecost_from, 200 - 10 * ( attack - defend ) );
    const tripoint dir = p - pos();

    // Mark self as pushed to simplify recursive pushing
    add_effect( effect_pushed, 1 );

    for( size_t i = 0; i < 6; i++ ) {
        const int dx = rng( -1, 1 );
        const int dy = rng( -1, 1 );
        if( dx == 0 && dy == 0 ) {
            continue;
        }

        // Pushing forward is easier than pushing aside
        const int direction_penalty = abs( dx - dir.x ) + abs( dy - dir.y );
        if( direction_penalty > 2 ) {
            continue;
        }

        tripoint dest( p.x + dx, p.y + dy, p.z );

        // Pushing into cars/windows etc. is harder
        const int movecost_penalty = g->m.move_cost( dest ) - 2;
        if( movecost_penalty <= -2 ) {
            // Can't push into unpassable terrain
            continue;
        }

        int roll = attack - ( defend + direction_penalty + movecost_penalty );
        if( roll < 0 ) {
            continue;
        }

        Creature *critter_recur = g->critter_at( dest );
        if( critter_recur == nullptr || critter_recur->is_hallucination() ) {
            // Try to push recursively
            monster *mon_recur = dynamic_cast< monster * >( critter_recur );
            if( mon_recur == nullptr ) {
                continue;
            }

            if( critter->push_to( dest, roll, depth + 1 ) ) {
                // The tile isn't necessarily free, need to check
                if( !g->critter_at( p ) ) {
                    move_to( p );
                }

                moves -= movecost_attacker;
                if( movecost_from > 100 ) {
                    critter->add_effect( effect_downed, movecost_from / 100 + 1 );
                } else {
                    critter->moves -= movecost_from;
                }

                return true;
            } else {
                continue;
            }
        }

        critter_recur = g->critter_at( dest );
        if( critter_recur != nullptr ) {
            if( critter_recur->is_hallucination() ) {
                critter_recur->die( nullptr );
            } else {
                return false;
            }
        }

        critter->setpos( dest );
        move_to( p );
        moves -= movecost_attacker;
        if( movecost_from > 100 ) {
            critter->add_effect( effect_downed, movecost_from / 100 + 1 );
        } else {
            critter->moves -= movecost_from;
        }

        return true;
    }

    // Try to trample over a much weaker zed (or one with worse rolls)
    // Don't allow trampling with boost
    if( boost > 0 || attack < 2 * defend ) {
        return false;
    }

    g->swap_critters( *critter, *this );
    critter->add_effect( effect_stunned, rng( 0, 2 ) );
    // Only print the message when near player or it can get spammy
    if( rl_dist( g->u.pos(), pos() ) < 4 && g->u.sees( *critter ) ) {
        add_msg( m_warning, _( "The %1$s tramples %2$s" ),
                 name().c_str(), critter->disp_name().c_str() );
    }

    moves -= movecost_attacker;
    if( movecost_from > 100 ) {
        critter->add_effect( effect_downed, movecost_from / 100 + 1 );
    } else {
        critter->moves -= movecost_from;
    }

    return true;
}
Esempio n. 8
0
void PhotonShootingTask::Run() {
    // Declare local variables for _PhotonShootingTask_
    MemoryArena arena;
    RNG rng(31 * taskNum);
    vector<Photon> localDirectPhotons, localIndirectPhotons, localCausticPhotons;
    vector<RadiancePhoton> localRadiancePhotons;
    u_int totalPaths = 0;
    bool causticDone = (integrator->nCausticPhotonsWanted == 0);
    bool indirectDone = (integrator->nIndirectPhotonsWanted == 0);
    PermutedHalton halton(6, rng);
    vector<Spectrum> localRpReflectances, localRpTransmittances;
    while (true) {
        // Follow photon paths for a block of samples
        const u_int blockSize = 4096;
        for (u_int i = 0; i < blockSize; ++i) {
            float u[6];
            halton.Sample(++totalPaths, u);
            // Choose light to shoot photon from
            float lightPdf;
            int lightNum = lightDistribution->SampleDiscrete(u[0], &lightPdf);
            const Light *light = scene->lights[lightNum];

            // Generate _photonRay_ from light source and initialize _alpha_
            RayDifferential photonRay;
            float pdf;
            LightSample ls(u[1], u[2], u[3]);
            Normal Nl;
            Spectrum Le = light->Sample_L(scene, ls, u[4], u[5],
                                          &photonRay, &Nl, &pdf);
            if (pdf == 0.f || Le.IsBlack()) continue;
            Spectrum alpha = (AbsDot(Nl, photonRay.d) * Le) / (pdf * lightPdf);
            if (!alpha.IsBlack()) {
                // Follow photon path through scene and record intersections
                PBRT_PHOTON_MAP_STARTED_RAY_PATH(&photonRay, &alpha);
                bool specularPath = true;
                Intersection photonIsect;
                u_int nIntersections = 0;
                while (scene->Intersect(photonRay, &photonIsect)) {
                    ++nIntersections;
                    // Handle photon/surface intersection
                    alpha *= renderer->Transmittance(scene, photonRay, NULL, arena, &rng);
                    BSDF *photonBSDF = photonIsect.GetBSDF(photonRay, arena);
                    BxDFType specularType = BxDFType(BSDF_REFLECTION |
                        BSDF_TRANSMISSION | BSDF_SPECULAR);
                    bool hasNonSpecular = (photonBSDF->NumComponents() >
                        photonBSDF->NumComponents(specularType));
                    Vector wo = -photonRay.d;
                    if (hasNonSpecular) {
                        // Deposit photon at surface
                        Photon photon(photonIsect.dg.p, alpha, wo);
                        bool depositedPhoton = false;
                        if (nIntersections == 1) {
                            PBRT_PHOTON_MAP_DEPOSITED_DIRECT_PHOTON(&photonIsect.dg, &alpha, &wo);
                            depositedPhoton = true;
                            localDirectPhotons.push_back(photon);
                        }
                        else {
                            // Deposit either caustic or indirect photon
                            if (specularPath && !causticDone) {
                                PBRT_PHOTON_MAP_DEPOSITED_CAUSTIC_PHOTON(&photonIsect.dg, &alpha, &wo);
                                depositedPhoton = true;
                                localCausticPhotons.push_back(photon);
                            }
                            else if (!specularPath && !indirectDone) {
                                PBRT_PHOTON_MAP_DEPOSITED_INDIRECT_PHOTON(&photonIsect.dg, &alpha, &wo);
                                depositedPhoton = true;
                                localIndirectPhotons.push_back(photon);
                            }
                        }

                        // Possibly create radiance photon at photon intersection point
                        if (depositedPhoton && integrator->finalGather &&
                            rng.RandomFloat() < .125f) {
                            // Store data for radiance photon
                            Normal n = photonIsect.dg.nn;
                            n = Faceforward(n, -photonRay.d);
                            localRadiancePhotons.push_back(RadiancePhoton(photonIsect.dg.p, n));

                            // Generate random samples for computing reflectance and transmittance
                            const int sqrtRhoSamples = 4;
                            float rhoRSamples1[2*sqrtRhoSamples*sqrtRhoSamples];
                            float rhoRSamples2[2*sqrtRhoSamples*sqrtRhoSamples];
                            StratifiedSample2D(rhoRSamples1, sqrtRhoSamples, sqrtRhoSamples, rng);
                            StratifiedSample2D(rhoRSamples2, sqrtRhoSamples, sqrtRhoSamples, rng);
                            float rhoTSamples1[2*sqrtRhoSamples*sqrtRhoSamples];
                            float rhoTSamples2[2*sqrtRhoSamples*sqrtRhoSamples];
                            StratifiedSample2D(rhoTSamples1, sqrtRhoSamples, sqrtRhoSamples, rng);
                            StratifiedSample2D(rhoTSamples2, sqrtRhoSamples, sqrtRhoSamples, rng);
                            Spectrum rho_r = photonBSDF->rho(sqrtRhoSamples * sqrtRhoSamples,
                                rhoRSamples1, rhoRSamples2, BSDF_ALL_REFLECTION);
                            localRpReflectances.push_back(rho_r);
                            Spectrum rho_t = photonBSDF->rho(sqrtRhoSamples * sqrtRhoSamples,
                                rhoTSamples1, rhoTSamples2, BSDF_ALL_TRANSMISSION);
                            localRpTransmittances.push_back(rho_t);
                        }
                    }
                    if ((int)nIntersections >= integrator->maxPhotonDepth) break;

                    // Sample new photon ray direction
                    Vector wi;
                    float pdf;
                    BxDFType flags;
                    Spectrum fr = photonBSDF->Sample_f(wo, &wi, BSDFSample(rng),
                                                       &pdf, BSDF_ALL, &flags);
                    if (fr.IsBlack() || pdf == 0.f)
                        break;
                    Spectrum anew = alpha * fr *
                        AbsDot(wi, photonBSDF->dgShading.nn) / pdf;

                    // Possibly terminate photon path with Russian roulette
                    float continueProb = min(1.f, anew.y() / alpha.y());
                    if (rng.RandomFloat() > continueProb)
                        break;
                    alpha = anew / continueProb;
                    specularPath &= ((flags & BSDF_SPECULAR) != 0);
                    if (indirectDone && !specularPath) break;
                    photonRay = RayDifferential(photonIsect.dg.p, wi, photonRay,
                                                photonIsect.RayEpsilon);
                }
                PBRT_PHOTON_MAP_FINISHED_RAY_PATH(&photonRay, &alpha);
            }
            arena.FreeAll();
        }

        // Merge local photon data with data in _PhotonIntegrator_
        { MutexLock lock(mutex);

        // Give up if we're not storing enough photons
        if (abortTasks)
            return;
        if (nshot > 500000 &&
            (unsuccessful(integrator->nCausticPhotonsWanted,
                                      causticPhotons.size(), blockSize) ||
             unsuccessful(integrator->nIndirectPhotonsWanted,
                                      indirectPhotons.size(), blockSize))) {
            Error("Unable to store enough photons.  Giving up.\n");
            abortTasks = true;
            return;
        }
        progress.Update(localIndirectPhotons.size() + localCausticPhotons.size());
        nshot += blockSize;

        // Merge direct photons into shared array
        nDirectPaths += blockSize;
        for (u_int i = 0; i < localDirectPhotons.size(); ++i)
            directPhotons.push_back(localDirectPhotons[i]);
        localDirectPhotons.erase(localDirectPhotons.begin(),
                                 localDirectPhotons.end());

        // Merge indirect photons into shared array
        if (!indirectDone) {
            integrator->nIndirectPaths += blockSize;
            for (u_int i = 0; i < localIndirectPhotons.size(); ++i)
                indirectPhotons.push_back(localIndirectPhotons[i]);
            localIndirectPhotons.erase(localIndirectPhotons.begin(),
                                       localIndirectPhotons.end());
            if (indirectPhotons.size() >= integrator->nIndirectPhotonsWanted)
                indirectDone = true;
        }

        // Merge caustic photons into shared array
        if (!causticDone) {
            integrator->nCausticPaths += blockSize;
            for (u_int i = 0; i < localCausticPhotons.size(); ++i)
                causticPhotons.push_back(localCausticPhotons[i]);
            localCausticPhotons.erase(localCausticPhotons.begin(), localCausticPhotons.end());
            if (causticPhotons.size() >= integrator->nCausticPhotonsWanted)
                causticDone = true;
        }

        // Merge radiance photons and reflectances into shared array
        for (u_int i = 0; i < localRadiancePhotons.size(); ++i)
            radiancePhotons.push_back(localRadiancePhotons[i]);
        localRadiancePhotons.erase(localRadiancePhotons.begin(), localRadiancePhotons.end());
        for (u_int i = 0; i < localRpReflectances.size(); ++i)
            rpReflectances.push_back(localRpReflectances[i]);
        localRpReflectances.erase(localRpReflectances.begin(), localRpReflectances.end());
        for (u_int i = 0; i < localRpTransmittances.size(); ++i)
            rpTransmittances.push_back(localRpTransmittances[i]);
        localRpTransmittances.erase(localRpTransmittances.begin(), localRpTransmittances.end());
        }

        // Exit task if enough photons have been found
        if (indirectDone && causticDone)
            break;
    }
}
Esempio n. 9
0
void event::actualize()
{
    switch( type ) {
        case EVENT_HELP:
            debugmsg("Currently disabled while NPC and monster factions are being rewritten.");
        break;

    case EVENT_ROBOT_ATTACK: {
        const auto u_pos = g->u.global_sm_location();
        if (rl_dist(u_pos, map_point) <= 4) {
            const mtype_id& robot_type = one_in( 2 ) ? mon_copbot : mon_riotbot;

            g->u.add_memorial_log( pgettext("memorial_male", "Became wanted by the police!"),
                                    pgettext("memorial_female", "Became wanted by the police!"));
            int robx = (u_pos.x > map_point.x ? 0 - SEEX * 2 : SEEX * 4);
            int roby = (u_pos.y > map_point.y ? 0 - SEEY * 2 : SEEY * 4);
            g->summon_mon(robot_type, tripoint(robx, roby, g->u.posz()));
        }
    } break;

    case EVENT_SPAWN_WYRMS: {
        if (g->get_levz() >= 0) {
            return;
        }
        g->u.add_memorial_log(pgettext("memorial_male", "Drew the attention of more dark wyrms!"),
                                pgettext("memorial_female", "Drew the attention of more dark wyrms!"));
        int num_wyrms = rng(1, 4);
        for (int i = 0; i < num_wyrms; i++) {
            int tries = 0;
            tripoint monp = g->u.pos();
            do {
                monp.x = rng(0, SEEX * MAPSIZE);
                monp.y = rng(0, SEEY * MAPSIZE);
                tries++;
            } while (tries < 10 && !g->is_empty(monp) &&
                    rl_dist(g->u.pos(), monp) <= 2);
            if (tries < 10) {
                g->m.ter_set(monp, t_rock_floor);
                g->summon_mon(mon_dark_wyrm, monp);
            }
        }
        // You could drop the flag, you know.
        if (g->u.has_amount("petrified_eye", 1)) {
            sounds::sound(g->u.pos(), 60, "");
            if (!g->u.is_deaf()) {
                add_msg(_("The eye you're carrying lets out a tortured scream!"));
                g->u.add_morale(MORALE_SCREAM, -15, 0, 300, 5);
            }
        }
        if (!one_in(25)) { // They just keep coming!
            g->events.add( EVENT_SPAWN_WYRMS, calendar::turn + rng( 15_turns, 25_turns ) );
        }
    } break;

    case EVENT_AMIGARA: {
        g->u.add_memorial_log(pgettext("memorial_male", "Angered a group of amigara horrors!"),
                              pgettext("memorial_female", "Angered a group of amigara horrors!"));
        int num_horrors = rng(3, 5);
        int faultx = -1, faulty = -1;
        bool horizontal = false;
        for (int x = 0; x < SEEX * MAPSIZE && faultx == -1; x++) {
            for (int y = 0; y < SEEY * MAPSIZE && faulty == -1; y++) {
                if (g->m.ter(x, y) == t_fault) {
                    faultx = x;
                    faulty = y;
                    horizontal = (g->m.ter(x - 1, y) == t_fault || g->m.ter(x + 1, y) == t_fault);
                }
            }
        }
        for (int i = 0; i < num_horrors; i++) {
            int tries = 0;
            int monx = -1, mony = -1;
            do {
                if (horizontal) {
                    monx = rng(faultx, faultx + 2 * SEEX - 8);
                    for (int n = -1; n <= 1; n++) {
                        if (g->m.ter(monx, faulty + n) == t_rock_floor) {
                            mony = faulty + n;
                        }
                    }
                } else { // Vertical fault
                    mony = rng(faulty, faulty + 2 * SEEY - 8);
                    for (int n = -1; n <= 1; n++) {
                        if (g->m.ter(faultx + n, mony) == t_rock_floor) {
                            monx = faultx + n;
                        }
                    }
                }
                tries++;
            } while ((monx == -1 || mony == -1 || !g->is_empty({monx, mony, g->u.posz()})) &&
                        tries < 10);
            if (tries < 10) {
                g->summon_mon(mon_amigara_horror, tripoint(monx, mony, g->u.posz()));
            }
        }
    } break;

  case EVENT_ROOTS_DIE:
   g->u.add_memorial_log(pgettext("memorial_male", "Destroyed a triffid grove."),
                         pgettext("memorial_female", "Destroyed a triffid grove."));
   for (int x = 0; x < SEEX * MAPSIZE; x++) {
    for (int y = 0; y < SEEY * MAPSIZE; y++) {
     if (g->m.ter(x, y) == t_root_wall && one_in(3))
      g->m.ter_set(x, y, t_underbrush);
    }
   }
   break;

  case EVENT_TEMPLE_OPEN: {
   g->u.add_memorial_log(pgettext("memorial_male", "Opened a strange temple."),
                         pgettext("memorial_female", "Opened a strange temple."));
   bool saw_grate = false;
   for (int x = 0; x < SEEX * MAPSIZE; x++) {
    for (int y = 0; y < SEEY * MAPSIZE; y++) {
     if (g->m.ter(x, y) == t_grate) {
      g->m.ter_set(x, y, t_stairs_down);
      if (!saw_grate && g->u.sees(tripoint(x, y,g->get_levz())))
       saw_grate = true;
     }
    }
   }
   if (saw_grate)
    add_msg(_("The nearby grates open to reveal a staircase!"));
  } break;

  case EVENT_TEMPLE_FLOOD: {
   bool flooded = false;

   ter_id flood_buf[SEEX*MAPSIZE][SEEY*MAPSIZE];
   for (int x = 0; x < SEEX * MAPSIZE; x++) {
    for (int y = 0; y < SEEY * MAPSIZE; y++)
     flood_buf[x][y] = g->m.ter(x, y);
   }
   for (int x = 0; x < SEEX * MAPSIZE; x++) {
    for (int y = 0; y < SEEY * MAPSIZE; y++) {
     if (g->m.ter(x, y) == t_water_sh) {
      bool deepen = false;
      for (int wx = x - 1;  wx <= x + 1 && !deepen; wx++) {
       for (int wy = y - 1;  wy <= y + 1 && !deepen; wy++) {
        if (g->m.ter(wx, wy) == t_water_dp)
         deepen = true;
       }
      }
      if (deepen) {
       flood_buf[x][y] = t_water_dp;
       flooded = true;
      }
     } else if (g->m.ter(x, y) == t_rock_floor) {
      bool flood = false;
      for (int wx = x - 1;  wx <= x + 1 && !flood; wx++) {
       for (int wy = y - 1;  wy <= y + 1 && !flood; wy++) {
        if (g->m.ter(wx, wy) == t_water_dp || g->m.ter(wx, wy) == t_water_sh)
         flood = true;
       }
      }
      if (flood) {
       flood_buf[x][y] = t_water_sh;
       flooded = true;
      }
     }
    }
   }
   if (!flooded)
    return; // We finished flooding the entire chamber!
// Check if we should print a message
   if (flood_buf[g->u.posx()][g->u.posy()] != g->m.ter(g->u.posx(), g->u.posy())) {
    if (flood_buf[g->u.posx()][g->u.posy()] == t_water_sh) {
     add_msg(m_warning, _("Water quickly floods up to your knees."));
     g->u.add_memorial_log(pgettext("memorial_male", "Water level reached knees."),
                           pgettext("memorial_female", "Water level reached knees."));
    } else { // Must be deep water!
     add_msg(m_warning, _("Water fills nearly to the ceiling!"));
     g->u.add_memorial_log(pgettext("memorial_male", "Water level reached the ceiling."),
                           pgettext("memorial_female", "Water level reached the ceiling."));
     g->plswim(g->u.pos());
    }
   }
// flood_buf is filled with correct tiles; now copy them back to g->m
   for (int x = 0; x < SEEX * MAPSIZE; x++) {
    for (int y = 0; y < SEEY * MAPSIZE; y++)
       g->m.ter_set(x, y, flood_buf[x][y]);
   }
   g->events.add( EVENT_TEMPLE_FLOOD, calendar::turn + rng( 2_turns, 3_turns ) );
  } break;

    case EVENT_TEMPLE_SPAWN: {
        static const std::array<mtype_id, 4> temple_monsters = { {
            mon_sewer_snake, mon_dermatik, mon_spider_widow_giant, mon_spider_cellar_giant
        } };
        const mtype_id &montype = random_entry( temple_monsters );
        int tries = 0, x, y;
        do {
            x = rng(g->u.posx() - 5, g->u.posx() + 5);
            y = rng(g->u.posy() - 5, g->u.posy() + 5);
            tries++;
        } while (tries < 20 && !g->is_empty({x, y, g->u.posz()}) &&
                    rl_dist(x, y, g->u.posx(), g->u.posy()) <= 2);
        if (tries < 20) {
            g->summon_mon(montype, tripoint(x, y, g->u.posz()));
        }
    } break;

  default:
   break; // Nothing happens for other events
 }
}
Esempio n. 10
0
// Why put this in a Big Switch?  Why not let bionics have pointers to
// functions, much like monsters and items?
//
// Well, because like diseases, which are also in a Big Switch, bionics don't
// share functions....
void player::activate_bionic(int b, game *g)
{
 bionic bio = my_bionics[b];
 int power_cost = bionics[bio.id].power_cost;
 if (weapon.type->id == itm_bio_claws && bio.id == bio_claws)
  power_cost = 0;
 if (power_level < power_cost) {
  if (my_bionics[b].powered) {
   g->add_msg("Your %s powers down.", bionics[bio.id].name.c_str());
   my_bionics[b].powered = false;
  } else
   g->add_msg("You cannot power your %s", bionics[bio.id].name.c_str());
  return;
 }

 if (my_bionics[b].powered && my_bionics[b].charge > 0) {
// Already-on units just lose a bit of charge
  my_bionics[b].charge--;
 } else {
// Not-on units, or those with zero charge, have to pay the power cost
  if (bionics[bio.id].charge_time > 0) {
   my_bionics[b].powered = true;
   my_bionics[b].charge = bionics[bio.id].charge_time;
  }
  power_level -= power_cost;
 }

 std::string junk;
 std::vector<point> traj;
 std::vector<std::string> good;
 std::vector<std::string> bad;
 WINDOW* w;
 int dirx, diry, t, index;
 InputEvent input;
 unsigned int l;
 item tmp_item;

 switch (bio.id) {
 case bio_painkiller:
  pkill += 6;
  pain -= 2;
  if (pkill > pain)
   pkill = pain;
  break;

 case bio_nanobots:
  healall(4);
  break;

 case bio_resonator:
  g->sound(posx, posy, 30, "VRRRRMP!");
  for (int i = posx - 1; i <= posx + 1; i++) {
   for (int j = posy - 1; j <= posy + 1; j++) {
    g->m.bash(i, j, 40, junk);
    g->m.bash(i, j, 40, junk);	// Multibash effect, so that doors &c will fall
    g->m.bash(i, j, 40, junk);
    if (g->m.is_destructable(i, j) && rng(1, 10) >= 4)
     g->m.ter(i, j) = t_rubble;
   }
  }
  break;

 case bio_time_freeze:
  moves += 100 * power_level;
  power_level = 0;
  g->add_msg("Your speed suddenly increases!");
  if (one_in(3)) {
   g->add_msg("Your muscles tear with the strain.");
   hurt(g, bp_arms, 0, rng(5, 10));
   hurt(g, bp_arms, 1, rng(5, 10));
   hurt(g, bp_legs, 0, rng(7, 12));
   hurt(g, bp_legs, 1, rng(7, 12));
   hurt(g, bp_torso, 0, rng(5, 15));
  }
  if (one_in(5))
   add_disease(DI_TELEGLOW, rng(50, 400), g);
  break;

 case bio_teleport:
  g->teleport();
  add_disease(DI_TELEGLOW, 300, g);
  break;

// TODO: More stuff here (and bio_blood_filter)
 case bio_blood_anal:
  w = newwin(20, 40, 3, 10);
  wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
             LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
  if (has_disease(DI_FUNGUS))
   bad.push_back("Fungal Parasite");
  if (has_disease(DI_DERMATIK))
   bad.push_back("Insect Parasite");
  if (has_disease(DI_POISON))
   bad.push_back("Poison");
  if (radiation > 0)
   bad.push_back("Irradiated");
  if (has_disease(DI_PKILL1))
   good.push_back("Minor Painkiller");
  if (has_disease(DI_PKILL2))
   good.push_back("Moderate Painkiller");
  if (has_disease(DI_PKILL3))
   good.push_back("Heavy Painkiller");
  if (has_disease(DI_PKILL_L))
   good.push_back("Slow-Release Painkiller");
  if (has_disease(DI_DRUNK))
   good.push_back("Alcohol");
  if (has_disease(DI_CIG))
   good.push_back("Nicotine");
  if (has_disease(DI_HIGH))
   good.push_back("Intoxicant: Other");
  if (has_disease(DI_TOOK_PROZAC))
   good.push_back("Prozac");
  if (has_disease(DI_TOOK_FLUMED))
   good.push_back("Antihistamines");
  if (has_disease(DI_ADRENALINE))
   good.push_back("Adrenaline Spike");
  if (good.size() == 0 && bad.size() == 0)
   mvwprintz(w, 1, 1, c_white, "No effects.");
  else {
   for (int line = 1; line < 39 && line <= good.size() + bad.size(); line++) {
    if (line <= bad.size())
     mvwprintz(w, line, 1, c_red, bad[line - 1].c_str());
    else
     mvwprintz(w, line, 1, c_green, good[line - 1 - bad.size()].c_str());
   }
  }
  wrefresh(w);
  refresh();
  getch();
  delwin(w);
  break;

 case bio_blood_filter:
  rem_disease(DI_FUNGUS);
  rem_disease(DI_POISON);
  rem_disease(DI_PKILL1);
  rem_disease(DI_PKILL2);
  rem_disease(DI_PKILL3);
  rem_disease(DI_PKILL_L);
  rem_disease(DI_DRUNK);
  rem_disease(DI_CIG);
  rem_disease(DI_HIGH);
  rem_disease(DI_TOOK_PROZAC);
  rem_disease(DI_TOOK_FLUMED);
  rem_disease(DI_ADRENALINE);
  break;

 case bio_evap:
  if (query_yn("Drink directly? Otherwise you will need a container.")) {
   tmp_item = item(g->itypes[itm_water], 0);
   thirst -= 50;
   if (has_trait(PF_GOURMAND) && thirst < -60) {
     g->add_msg("You can't finish it all!");
     thirst = -60;
   } else if (!has_trait(PF_GOURMAND) && thirst < -20) {
     g->add_msg("You can't finish it all!");
     thirst = -20;
   }
  } else {
   t = g->inv("Choose a container:");
   if (i_at(t).type == 0) {
    g->add_msg("You don't have that item!");
    power_level += bionics[bio_evap].power_cost;
   } else if (!i_at(t).is_container()) {
    g->add_msg("That %s isn't a container!", i_at(t).tname().c_str());
    power_level += bionics[bio_evap].power_cost;
   } else {
    it_container *cont = dynamic_cast<it_container*>(i_at(t).type);
    if (i_at(t).volume_contained() + 1 > cont->contains) {
     g->add_msg("There's no space left in your %s.", i_at(t).tname().c_str());
     power_level += bionics[bio_evap].power_cost;
    } else if (!(cont->flags & con_wtight)) {
     g->add_msg("Your %s isn't watertight!", i_at(t).tname().c_str());
     power_level += bionics[bio_evap].power_cost;
    } else {
     g->add_msg("You pour water into your %s.", i_at(t).tname().c_str());
     i_at(t).put_in(item(g->itypes[itm_water], 0));
    }
   }
  }
  break;

 case bio_lighter:
  g->draw();
  mvprintw(0, 0, "Torch in which direction?");
  input = get_input();
  get_direction(dirx, diry, input);
  if (dirx == -2) {
   g->add_msg("Invalid direction.");
   power_level += bionics[bio_lighter].power_cost;
   return;
  }
  dirx += posx;
  diry += posy;
  if (!g->m.add_field(g, dirx, diry, fd_fire, 1))	// Unsuccessful.
   g->add_msg("You can't light a fire there.");
  break;

 case bio_claws:
  if (weapon.type->id == itm_bio_claws) {
   g->add_msg("You withdraw your claws.");
   weapon = ret_null;
  } else if (weapon.type->id != 0) {
   g->add_msg("Your claws extend, forcing you to drop your %s.",
              weapon.tname().c_str());
   g->m.add_item(posx, posy, weapon);
   weapon = item(g->itypes[itm_bio_claws], 0);
   weapon.invlet = '#';
  } else {
   g->add_msg("Your claws extend!");
   weapon = item(g->itypes[itm_bio_claws], 0);
   weapon.invlet = '#';
  }
  break;

 case bio_blaster:
  tmp_item = weapon;
  weapon = item(g->itypes[itm_bio_blaster], 0);
  weapon.curammo = dynamic_cast<it_ammo*>(g->itypes[itm_bio_fusion]);
  weapon.charges = 1;
  g->refresh_all();
  g->plfire(false);
  weapon = tmp_item;
  break;

 case bio_laser:
  tmp_item = weapon;
  weapon = item(g->itypes[itm_v29], 0);
  weapon.curammo = dynamic_cast<it_ammo*>(g->itypes[itm_laser_pack]);
  weapon.charges = 1;
  g->refresh_all();
  g->plfire(false);
  weapon = tmp_item;
  break;

 case bio_emp:
  g->draw();
  mvprintw(0, 0, "Fire EMP in which direction?");
  input = get_input();
  get_direction(dirx, diry, input);
  if (dirx == -2) {
   g->add_msg("Invalid direction.");
   power_level += bionics[bio_emp].power_cost;
   return;
  }
  dirx += posx;
  diry += posy;
  g->emp_blast(dirx, diry);
  break;

 case bio_hydraulics:
  g->add_msg("Your muscles hiss as hydraulic strength fills them!");
  break;

 case bio_water_extractor:
  for (int i = 0; i < g->m.i_at(posx, posy).size(); i++) {
   item tmp = g->m.i_at(posx, posy)[i];
   if (tmp.type->id == itm_corpse && query_yn("Extract water from the %s",
                                              tmp.tname().c_str())) {
    i = g->m.i_at(posx, posy).size() + 1;	// Loop is finished
    t = g->inv("Choose a container:");
    if (i_at(t).type == 0) {
     g->add_msg("You don't have that item!");
     power_level += bionics[bio_water_extractor].power_cost;
    } else if (!i_at(t).is_container()) {
     g->add_msg("That %s isn't a container!", i_at(t).tname().c_str());
     power_level += bionics[bio_water_extractor].power_cost;
    } else {
     it_container *cont = dynamic_cast<it_container*>(i_at(t).type);
     if (i_at(t).volume_contained() + 1 > cont->contains) {
      g->add_msg("There's no space left in your %s.", i_at(t).tname().c_str());
      power_level += bionics[bio_water_extractor].power_cost;
     } else {
      g->add_msg("You pour water into your %s.", i_at(t).tname().c_str());
      i_at(t).put_in(item(g->itypes[itm_water], 0));
     }
    }
   }
   if (i == g->m.i_at(posx, posy).size() - 1)	// We never chose a corpse
    power_level += bionics[bio_water_extractor].power_cost;
  }
  break;

 case bio_magnet:
  for (int i = posx - 10; i <= posx + 10; i++) {
   for (int j = posy - 10; j <= posy + 10; j++) {
    if (g->m.i_at(i, j).size() > 0) {
     if (g->m.sees(i, j, posx, posy, -1, t))
      traj = line_to(i, j, posx, posy, t);
     else
      traj = line_to(i, j, posx, posy, 0);
    }
    traj.insert(traj.begin(), point(i, j));
    for (int k = 0; k < g->m.i_at(i, j).size(); k++) {
     if (g->m.i_at(i, j)[k].made_of(IRON) || g->m.i_at(i, j)[k].made_of(STEEL)){
      tmp_item = g->m.i_at(i, j)[k];
      g->m.i_rem(i, j, k);
      for (l = 0; l < traj.size(); l++) {
       index = g->mon_at(traj[l].x, traj[l].y);
       if (index != -1) {
        if (g->z[index].hurt(tmp_item.weight() * 2))
         g->kill_mon(index, true);
        g->m.add_item(traj[l].x, traj[l].y, tmp_item);
        l = traj.size() + 1;
       } else if (l > 0 && g->m.move_cost(traj[l].x, traj[l].y) == 0) {
        g->m.bash(traj[l].x, traj[l].y, tmp_item.weight() * 2, junk);
        g->sound(traj[l].x, traj[l].y, 12, junk);
        if (g->m.move_cost(traj[l].x, traj[l].y) == 0) {
         g->m.add_item(traj[l - 1].x, traj[l - 1].y, tmp_item);
         l = traj.size() + 1;
        }
       }
      }
      if (l == traj.size())
       g->m.add_item(posx, posy, tmp_item);
     }
    }
   }
  }
  break;

 case bio_lockpick:
  g->draw();
  mvprintw(0, 0, "Unlock in which direction?");
  input = get_input();
  get_direction(dirx, diry, input);
  if (dirx == -2) {
   g->add_msg("Invalid direction.");
   power_level += bionics[bio_lockpick].power_cost;
   return;
  }
  dirx += posx;
  diry += posy;
  if (g->m.ter(dirx, diry) == t_door_locked) {
   moves -= 40;
   g->add_msg("You unlock the door.");
   g->m.ter(dirx, diry) = t_door_c;
  } else
   g->add_msg("You can't unlock that %s.", g->m.tername(dirx, diry).c_str());
  break;

  // Unused enums added for completeness.
 default:
  break;
 }
}
Esempio n. 11
0
bool player::install_bionics(game *g, it_bionic* type)
{
 if (type == NULL) {
  debugmsg("Tried to install NULL bionic");
  return false;
 }
 std::string bio_name = type->name.substr(5);	// Strip off "CBM: "
 WINDOW* w = newwin(25, 80, 0, 0);

 int pl_skill = int_cur +
   skillLevel("electronics").level() * 4 +
   skillLevel("firstaid").level()    * 3 +
   skillLevel("mechanics").level()   * 2;

 int skint = int(pl_skill / 4);
 int skdec = int((pl_skill * 10) / 4) % 10;

// Header text
 mvwprintz(w, 0,  0, c_white, "Installing bionics:");
 mvwprintz(w, 0, 20, type->color, bio_name.c_str());

// Dividing bars
 for (int i = 0; i < 80; i++) {
  mvwputch(w,  1, i, c_ltgray, LINE_OXOX);
  mvwputch(w, 21, i, c_ltgray, LINE_OXOX);
 }
// Init the list of bionics
 for (int i = 1; i < type->options.size(); i++) {
  bionic_id id = type->options[i];
  mvwprintz(w, i + 2, 0, (has_bionic(id) ? c_ltred : c_ltblue),
            bionics[id].name.c_str());
 }
// Helper text
 mvwprintz(w, 2, 40, c_white,        "Difficulty of this module: %d",
           type->difficulty);
 mvwprintz(w, 3, 40, c_white,        "Your installation skill:   %d.%d",
           skint, skdec);
 mvwprintz(w, 4, 40, c_white,       "Installation requires high intelligence,");
 mvwprintz(w, 5, 40, c_white,       "and skill in electronics, first aid, and");
 mvwprintz(w, 6, 40, c_white,       "mechanics (in that order of importance).");

 int chance_of_success = int((100 * pl_skill) /
                             (pl_skill + 4 * type->difficulty));

 mvwprintz(w, 8, 40, c_white,        "Chance of success:");

 nc_color col_suc;
 if (chance_of_success >= 95)
  col_suc = c_green;
 else if (chance_of_success >= 80)
  col_suc = c_ltgreen;
 else if (chance_of_success >= 60)
  col_suc = c_yellow;
 else if (chance_of_success >= 35)
  col_suc = c_ltred;
 else
  col_suc = c_red;

 mvwprintz(w, 8, 59, col_suc, "%d%%%%", chance_of_success);

 mvwprintz(w, 10, 40, c_white,       "Failure may result in crippling damage,");
 mvwprintz(w, 11, 40, c_white,       "loss of existing bionics, genetic damage");
 mvwprintz(w, 12, 40, c_white,       "or faulty installation.");
 wrefresh(w);

 if (type->id == itm_bionics_battery) {	// No selection list; just confirm
  mvwprintz(w,  2, 0, h_ltblue, "Battery Level +%d", BATTERY_AMOUNT);
  mvwprintz(w, 22, 0, c_ltblue, "\
Installing this bionic will increase your total battery capacity by %d.\n\
Batteries are necessary for most bionics to function.  They also require a\n\
charge mechanism, which must be installed from another CBM.", BATTERY_AMOUNT);
  InputEvent input;
  wrefresh(w);
  do
   input = get_input();
  while (input != Confirm && input != Close);
  if (input == Confirm) {
   practice("electronics", (100 - chance_of_success) * 1.5);
   practice("firstaid", (100 - chance_of_success) * 1.0);
   practice("mechanics", (100 - chance_of_success) * 0.5);
   int success = chance_of_success - rng(1, 100);
   if (success > 0) {
    g->add_msg("Successfully installed batteries.");
    max_power_level += BATTERY_AMOUNT;
   } else
    bionics_install_failure(g, this, success);
   werase(w);
   delwin(w);
   g->refresh_all();
   return true;
  }
  werase(w);
  delwin(w);
  g->refresh_all();
  return false;
 }
Esempio n. 12
0
 CheckReproducibilityBody(std::size_t GrainSize): grainSize(GrainSize) {
     //first generate seeds to check on, and make sure that sequence is reproducible
     ASSERT(SingleCheck<seedsNum>()(0),"Series generated by FastRandom must be reproducible");
     std::generate(seeds,seeds+seedsNum,rng(0));
 }
Esempio n. 13
0
void mission_start::place_npc_software(mission *miss)
{
 npc* dev = g->find_npc(miss->npc_id);
 if (dev == NULL) {
  debugmsg("Couldn't find NPC! %d", miss->npc_id);
  return;
 }
 g->u.i_add( item(itypes["usb_drive"], 0) );
 g->add_msg(_("%s gave you a USB drive."), dev->name.c_str());

 std::string type = "house";

 switch (dev->myclass) {
 case NC_HACKER:
  miss->item_id = "software_hacking";
  break;
 case NC_DOCTOR:
  miss->item_id = "software_medical";
  type = "s_pharm";
  miss->follow_up = MISSION_GET_ZOMBIE_BLOOD_ANAL;
  break;
 case NC_SCIENTIST:
  miss->item_id = "software_math";
  break;
 default:
  miss->item_id = "software_useless";
 }

    int dist = 0;
    point place;
    if (type == "house") {
        int city_id = g->cur_om->closest_city( g->om_location() );
        place = g->cur_om->random_house_in_city(city_id);
    } else {
        place = g->cur_om->find_closest(g->om_location(), type, dist, false);
    }
    miss->target = place;

// Make it seen on our map
 for (int x = place.x - 6; x <= place.x + 6; x++) {
  for (int y = place.y - 6; y <= place.y + 6; y++)
   g->cur_om->seen(x, y, 0) = true;
 }
 tinymap compmap(&(g->traps));
 compmap.load(place.x * 2, place.y * 2, 0, false);
 point comppoint;

    oter_id oter = g->cur_om->ter(place.x, place.y, 0);
    if (oter == "house_north" || oter == "house_east"
            || oter == "house_south" || oter == "house_west") {
        std::vector<point> valid;
        for (int x = 0; x < SEEX * 2; x++) {
            for (int y = 0; y < SEEY * 2; y++) {
                if (compmap.ter(x, y) == t_floor && compmap.furn(x, y) == f_null) {
                    bool okay = false;
                    for (int x2 = x - 1; x2 <= x + 1 && !okay; x2++) {
                        for (int y2 = y - 1; y2 <= y + 1 && !okay; y2++) {
                            if (compmap.furn(x2, y2) == f_bed || compmap.furn(x2, y2) == f_dresser) {
                                okay = true;
                                valid.push_back( point(x, y) );
                            }
                        }
                    }
                }
            }
        }
        if (valid.empty()) {
            comppoint = point( rng(6, SEEX * 2 - 7), rng(6, SEEY * 2 - 7) );
        } else {
            comppoint = valid[rng(0, valid.size() - 1)];
        }
    } else if (oter == "s_pharm_north") {
        bool found = false;
        for (int x = SEEX * 2 - 1; x > 0 && !found; x--) {
            for (int y = SEEY * 2 - 1; y > 0 && !found; y--) {
                if (compmap.ter(x, y) == t_floor) {
                    found = true;
                    comppoint = point(x, y);
                }
            }
        }
    } else if (oter == "s_pharm_east") {
        bool found = false;
        for (int x = 0; x < SEEX * 2 && !found; x++) {
            for (int y = SEEY * 2 - 1; y > 0 && !found; y--) {
                if (compmap.ter(x, y) == t_floor) {
                    found = true;
                    comppoint = point(x, y);
                }
            }
        }
    } else if (oter == "s_pharm_south") {
        bool found = false;
        for (int x = 0; x < SEEX * 2 && !found; x++) {
            for (int y = 0; y < SEEY * 2 && !found; y++) {
                if (compmap.ter(x, y) == t_floor) {
                    found = true;
                    comppoint = point(x, y);
                }
            }
        }
    } else if (oter == "s_pharm_west") {
        bool found = false;
        for (int x = SEEX * 2 - 1; x > 0 && !found; x--) {
            for (int y = 0; y < SEEY * 2 && !found; y++) {
                if (compmap.ter(x, y) == t_floor) {
                    found = true;
                    comppoint = point(x, y);
                }
            }
        }
    }

 compmap.ter_set(comppoint.x, comppoint.y, t_console);
 computer *tmpcomp = compmap.add_computer(comppoint.x, comppoint.y, string_format(_("%s's Terminal"), dev->name.c_str()), 0);
 tmpcomp->mission_id = miss->uid;
 tmpcomp->add_option(_("Download Software"), COMPACT_DOWNLOAD_SOFTWARE, 0);

 compmap.save(g->cur_om, int(g->turn), place.x * 2, place.y * 2, 0);
}
Esempio n. 14
0
/*!
 *  \brief For a given probability "mean" for a single %Benoulli trial,
 *         this method returns the number of trials after which the
 *         first success occurs.
 *
 *  This method performs the \em inverse \em transformation of the
 *  original uniformally distributed random numbers of the interval
 *  (0,1) created by the used pseudo random number generator to
 *  the type of the geometric distribution.
 *
 *  \param mean     the probability for a single %Bernoulli trial
 *  \return the number of trials after which the first success occurs
 *
 *  \author  M. Kreutz
 *  \date    1995-01-01
 *
 *  \par Changes
 *      none
 *
 *  \par Status
 *      stable
 *
 */
long Geometric::operator( )( double mean )
{
    return long( ceil( log( 1 - rng( ) ) / log( 1 - mean ) ) );
}
Esempio n. 15
0
// this function generates clothing for zombies
void mdeath::zombie(game *g, monster *z)
{
    // normal death function first
    mdeath::normal(g, z);

    // skip clothing generation if the zombie was rezzed rather than spawned
    if (z->no_extra_death_drops)
    {
        return;
    }

    // now generate appropriate clothing
    switch(z->type->id)
    {
        case mon_zombie_cop:
            g->m.put_items_from("cop_shoes", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            g->m.put_items_from("cop_torso", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            g->m.put_items_from("cop_pants", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
        break;

        case mon_zombie_swimmer:
            if (one_in(10)) {
              //Wetsuit zombie
              g->m.put_items_from("swimmer_wetsuit", 1, z->posx, z->posy, g->turn, 0, 0, rng(1, 4));
            } else {
              if (!one_in(4)) {
                  g->m.put_items_from("swimmer_head", 1, z->posx, z->posy, g->turn, 0, 0, rng(1, 4));
              }
              if (one_in(3)) {
                  g->m.put_items_from("swimmer_torso", 1, z->posx, z->posy, g->turn, 0, 0, rng(1, 4));
              }
              g->m.put_items_from("swimmer_pants", 1, z->posx, z->posy, g->turn, 0, 0, rng(1, 4));
              if (one_in(4)) {
                  g->m.put_items_from("swimmer_shoes", 1, z->posx, z->posy, g->turn, 0, 0, rng(1, 4));
              }
            }
        break;

        case mon_zombie_scientist:
            g->m.put_items_from("lab_shoes", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            g->m.put_items_from("lab_torso", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            g->m.put_items_from("lab_pants", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
        break;

        case mon_zombie_soldier:
            g->m.put_items_from("cop_shoes", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            g->m.put_items_from("mil_armor_torso", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            g->m.put_items_from("mil_armor_pants", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            if (one_in(4))
            {
                g->m.put_items_from("mil_armor_helmet", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            }
        break;

        case mon_zombie_hulk:
            g->m.spawn_item(z->posx, z->posy, "rag", g->turn, 0, 0, rng(5,10));
            g->m.put_items_from("pants", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            break;

        default:
            g->m.put_items_from("pants", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            g->m.put_items_from("shirts", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            if (one_in(6))
            {
                g->m.put_items_from("jackets", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            }
            if (one_in(15))
            {
                g->m.put_items_from("bags", 1, z->posx, z->posy, g->turn, 0, 0, rng(1,4));
            }
        break;
    }
}
Esempio n. 16
0
// Why put this in a Big Switch?  Why not let bionics have pointers to
// functions, much like monsters and items?
//
// Well, because like diseases, which are also in a Big Switch, bionics don't
// share functions....
void player::activate_bionic(int b)
{
    bionic bio = my_bionics[b];
    int power_cost = bionics[bio.id]->power_cost;
    if ((weapon.type->id == "bio_claws_weapon" && bio.id == "bio_claws_weapon") ||
        (weapon.type->id == "bio_blade_weapon" && bio.id == "bio_blade_weapon")) {
        power_cost = 0;
    }
    if (power_level < power_cost) {
        if (my_bionics[b].powered) {
            add_msg(m_neutral, _("Your %s powers down."), bionics[bio.id]->name.c_str());
            my_bionics[b].powered = false;
        } else {
            add_msg(m_info, _("You cannot power your %s"), bionics[bio.id]->name.c_str());
        }
        return;
    }

    if (my_bionics[b].powered && my_bionics[b].charge > 0) {
        // Already-on units just lose a bit of charge
        my_bionics[b].charge--;
    } else {
        // Not-on units, or those with zero charge, have to pay the power cost
        if (bionics[bio.id]->charge_time > 0) {
            my_bionics[b].powered = true;
            my_bionics[b].charge = bionics[bio.id]->charge_time - 1;
        }
        power_level -= power_cost;
    }

    std::vector<point> traj;
    std::vector<std::string> good;
    std::vector<std::string> bad;
    int dirx, diry;
    item tmp_item;

    if(bio.id == "bio_painkiller") {
        pkill += 6;
        pain -= 2;
        if (pkill > pain) {
            pkill = pain;
        }
    } else if (bio.id == "bio_nanobots") {
        rem_disease("bleed");
        healall(4);
    } else if (bio.id == "bio_night") {
        if (calendar::turn % 5) {
            add_msg(m_neutral, _("Artificial night generator active!"));
        }
    } else if (bio.id == "bio_resonator") {
        g->sound(posx, posy, 30, _("VRRRRMP!"));
        for (int i = posx - 1; i <= posx + 1; i++) {
            for (int j = posy - 1; j <= posy + 1; j++) {
                g->m.bash( i, j, 40 );
                g->m.bash( i, j, 40 ); // Multibash effect, so that doors &c will fall
                g->m.bash( i, j, 40 );
                if (g->m.is_destructable(i, j) && rng(1, 10) >= 4) {
                    g->m.ter_set(i, j, t_rubble);
                }
            }
        }
    } else if (bio.id == "bio_time_freeze") {
        moves += 100 * power_level;
        power_level = 0;
        add_msg(m_good, _("Your speed suddenly increases!"));
        if (one_in(3)) {
            add_msg(m_bad, _("Your muscles tear with the strain."));
            hurt(bp_arms, 0, rng(5, 10));
            hurt(bp_arms, 1, rng(5, 10));
            hurt(bp_legs, 0, rng(7, 12));
            hurt(bp_legs, 1, rng(7, 12));
            hurt(bp_torso, -1, rng(5, 15));
        }
        if (one_in(5)) {
            add_disease("teleglow", rng(50, 400));
        }
    } else if (bio.id == "bio_teleport") {
        g->teleport();
        add_disease("teleglow", 300);
    }
    // TODO: More stuff here (and bio_blood_filter)
    else if(bio.id == "bio_blood_anal") {
        WINDOW *w = newwin(20, 40, 3 + ((TERMY > 25) ? (TERMY - 25) / 2 : 0),
                           10 + ((TERMX > 80) ? (TERMX - 80) / 2 : 0));
        draw_border(w);
        if (has_disease("fungus")) {
            bad.push_back(_("Fungal Parasite"));
        }
        if (has_disease("dermatik")) {
            bad.push_back(_("Insect Parasite"));
        }
        if (has_effect("stung")) {
            bad.push_back(_("Stung"));
        }
        if (has_effect("poison")) {
            bad.push_back(_("Poison"));
        }
        if (radiation > 0) {
            bad.push_back(_("Irradiated"));
        }
        if (has_disease("pkill1")) {
            good.push_back(_("Minor Painkiller"));
        }
        if (has_disease("pkill2")) {
            good.push_back(_("Moderate Painkiller"));
        }
        if (has_disease("pkill3")) {
            good.push_back(_("Heavy Painkiller"));
        }
        if (has_disease("pkill_l")) {
            good.push_back(_("Slow-Release Painkiller"));
        }
        if (has_disease("drunk")) {
            good.push_back(_("Alcohol"));
        }
        if (has_disease("cig")) {
            good.push_back(_("Nicotine"));
        }
        if (has_disease("meth")) {
            good.push_back(_("Methamphetamines"));
        }
        if (has_disease("high")) {
            good.push_back(_("Intoxicant: Other"));
        }
        if (has_disease("weed_high")) {
            good.push_back(_("THC Intoxication"));
        }
        if (has_disease("hallu") || has_disease("visuals")) {
            bad.push_back(_("Magic Mushroom"));
        }
        if (has_disease("iodine")) {
            good.push_back(_("Iodine"));
        }
        if (has_disease("took_xanax")) {
            good.push_back(_("Xanax"));
        }
        if (has_disease("took_prozac")) {
            good.push_back(_("Prozac"));
        }
        if (has_disease("took_flumed")) {
            good.push_back(_("Antihistamines"));
        }
        if (has_disease("adrenaline")) {
            good.push_back(_("Adrenaline Spike"));
        }
        if (has_disease("tapeworm")) {  // This little guy is immune to the blood filter though, as he lives in your bowels.
            good.push_back(_("Intestinal Parasite"));
        }
        if (has_disease("bloodworms")) {
            good.push_back(_("Hemolytic Parasites"));
        }
        if (has_disease("brainworm")) {  // This little guy is immune to the blood filter too, as he lives in your brain.
            good.push_back(_("Intracranial Parasite"));
        }
        if (has_disease("paincysts")) {  // These little guys are immune to the blood filter too, as they live in your muscles.
            good.push_back(_("Intramuscular Parasites"));
        }
        if (has_disease("tetanus")) {  // Tetanus infection.
            good.push_back(_("Clostridium Tetani Infection"));
        }
        if (good.empty() && bad.empty()) {
            mvwprintz(w, 1, 1, c_white, _("No effects."));
        } else {
            for (unsigned line = 1; line < 39 && line <= good.size() + bad.size(); line++) {
                if (line <= bad.size()) {
                    mvwprintz(w, line, 1, c_red, "%s", bad[line - 1].c_str());
                } else {
                    mvwprintz(w, line, 1, c_green, "%s", good[line - 1 - bad.size()].c_str());
                }
            }
        }
        wrefresh(w);
        refresh();
        getch();
        delwin(w);
    } else if(bio.id == "bio_blood_filter") {
        add_msg(m_neutral, _("You activate your blood filtration system."));
        rem_disease("fungus");
        rem_disease("dermatik");
        rem_disease("bloodworms");
        rem_disease("tetanus");
        remove_effect("poison");
        remove_effect("stung");
        rem_disease("pkill1");
        rem_disease("pkill2");
        rem_disease("pkill3");
        rem_disease("pkill_l");
        rem_disease("drunk");
        rem_disease("cig");
        rem_disease("high");
        rem_disease("hallu");
        rem_disease("visuals");
        rem_disease("iodine");
        rem_disease("took_xanax");
        rem_disease("took_prozac");
        rem_disease("took_flumed");
        rem_disease("adrenaline");
        rem_disease("meth");
        pkill = 0;
        stim = 0;
    } else if(bio.id == "bio_evap") {
        item water = item("water_clean", 0);
        if (g->handle_liquid(water, true, true)) {
            moves -= 100;
        } else if (query_yn(_("Drink from your hands?"))) {
            inv.push_back(water);
            consume(inv.position_by_type(water.typeId()));
            moves -= 350;
        } else {
            power_level += bionics["bio_evap"]->power_cost;
        }
    } else if(bio.id == "bio_lighter") {
        if(!choose_adjacent(_("Start a fire where?"), dirx, diry) ||
           (!g->m.add_field(dirx, diry, fd_fire, 1))) {
            add_msg_if_player(m_info, _("You can't light a fire there."));
            power_level += bionics["bio_lighter"]->power_cost;
        }

    }
    if(bio.id == "bio_leukocyte") {
        add_msg(m_neutral, _("You activate your leukocyte breeder system."));
        if (health < 0) {
            health = 0;
        } else {
            health += 5;
        }
    }
    if(bio.id == "bio_geiger") {
        add_msg(m_info, _("Your radiation level: %d"), radiation);
    }
    if(bio.id == "bio_radscrubber") {
        add_msg(m_neutral, _("You activate your radiation scrubber system."));
        if (radiation > 4) {
            radiation -= 5;
        } else {
            radiation = 0;
        }
    }
    if(bio.id == "bio_adrenaline") {
        add_msg(m_neutral, _("You activate your adrenaline pump."));
        if (has_disease("adrenaline")) {
            add_disease("adrenaline", 50);
        } else {
            add_disease("adrenaline", 200);
        }
    } else if(bio.id == "bio_claws") {
        if (weapon.type->id == "bio_claws_weapon") {
            add_msg(m_neutral, _("You withdraw your claws."));
            weapon = ret_null;
        } else if (weapon.has_flag ("NO_UNWIELD")) {
            add_msg(m_info, _("Deactivate your %s first!"),
                       weapon.tname().c_str());
            power_level += bionics[bio.id]->power_cost;
            return;
        } else if(weapon.type->id != "null") {
            add_msg(m_warning, _("Your claws extend, forcing you to drop your %s."),
                       weapon.tname().c_str());
            g->m.add_item_or_charges(posx, posy, weapon);
            weapon = item("bio_claws_weapon", 0);
            weapon.invlet = '#';
        } else {
            add_msg(m_neutral, _("Your claws extend!"));
            weapon = item("bio_claws_weapon", 0);
            weapon.invlet = '#';
        }
    } else if(bio.id == "bio_blade") {
        if (weapon.type->id == "bio_blade_weapon") {
            add_msg(m_neutral, _("You retract your blade."));
            weapon = ret_null;
        } else if (weapon.has_flag ("NO_UNWIELD")) {
            add_msg(m_info, _("Deactivate your %s first!"),
                       weapon.tname().c_str());
            power_level += bionics[bio.id]->power_cost;
            return;
        } else if(weapon.type->id != "null") {
            add_msg(m_warning, _("Your blade extends, forcing you to drop your %s."),
                       weapon.tname().c_str());
            g->m.add_item_or_charges(posx, posy, weapon);
            weapon = item("bio_blade_weapon", 0);
            weapon.invlet = '#';
        } else {
            add_msg(m_neutral, _("You extend your blade!"));
            weapon = item("bio_blade_weapon", 0);
            weapon.invlet = '#';
        }
    } else if(bio.id == "bio_blaster") {
        tmp_item = weapon;
        weapon = item("bio_blaster_gun", 0);
        g->refresh_all();
        g->plfire(false);
        if(weapon.charges == 1) { // not fired
            power_level += bionics[bio.id]->power_cost;
        }
        weapon = tmp_item;
    } else if (bio.id == "bio_laser") {
        tmp_item = weapon;
        weapon = item("bio_laser_gun", 0);
        g->refresh_all();
        g->plfire(false);
        if(weapon.charges == 1) { // not fired
            power_level += bionics[bio.id]->power_cost;
        }
        weapon = tmp_item;
    } else if(bio.id == "bio_chain_lightning") {
        tmp_item = weapon;
        weapon = item("bio_lightning", 0);
        g->refresh_all();
        g->plfire(false);
        if(weapon.charges == 1) { // not fired
            power_level += bionics[bio.id]->power_cost;
        }
        weapon = tmp_item;
    } else if (bio.id == "bio_emp") {
        if(choose_adjacent(_("Create an EMP where?"), dirx, diry)) {
            g->emp_blast(dirx, diry);
        } else {
            power_level += bionics["bio_emp"]->power_cost;
        }
    } else if (bio.id == "bio_hydraulics") {
        add_msg(m_good, _("Your muscles hiss as hydraulic strength fills them!"));
        // Sound of hissing hydraulic muscle! (not quite as loud as a car horn)
        g->sound(posx, posy, 19, _("HISISSS!"));
    } else if (bio.id == "bio_water_extractor") {
        bool extracted = false;
        for (std::vector<item>::iterator it = g->m.i_at(posx,posy).begin();
             it != g->m.i_at(posx, posy).end(); ++it) {
            if (it->type->id == "corpse" ) {
                int avail = 0;
                if ( it->item_vars.find("remaining_water") != it->item_vars.end() ) {
                    avail = atoi ( it->item_vars["remaining_water"].c_str() );
                } else {
                    avail = it->volume() / 2;
                }
                if(avail > 0 && query_yn(_("Extract water from the %s"), it->tname().c_str())) {
                    item water = item("water_clean", 0);
                    if (g->handle_liquid(water, true, true)) {
                        moves -= 100;
                    } else if (query_yn(_("Drink directly from the condensor?"))) {
                        inv.push_back(water);
                        consume(inv.position_by_type(water.typeId()));
                        moves -= 350;
                    }
                    extracted = true;
                    avail--;
                    it->item_vars["remaining_water"] = string_format("%d", avail);
                    break;
                }
            }
        }
        if (!extracted) {
            power_level += bionics["bio_water_extractor"]->power_cost;
        }
    } else if(bio.id == "bio_magnet") {
        for (int i = posx - 10; i <= posx + 10; i++) {
            for (int j = posy - 10; j <= posy + 10; j++) {
                if (g->m.i_at(i, j).size() > 0) {
                    int t; //not sure why map:sees really needs this, but w/e
                    if (g->m.sees(i, j, posx, posy, -1, t)) {
                        traj = line_to(i, j, posx, posy, t);
                    } else {
                        traj = line_to(i, j, posx, posy, 0);
                    }
                }
                traj.insert(traj.begin(), point(i, j));
                for (unsigned k = 0; k < g->m.i_at(i, j).size(); k++) {
                    if (g->m.i_at(i, j)[k].made_of("iron") || g->m.i_at(i, j)[k].made_of("steel")) {
                        tmp_item = g->m.i_at(i, j)[k];
                        g->m.i_rem(i, j, k);
                        std::vector<point>::iterator it;
                        for (it = traj.begin(); it != traj.end(); ++it) {
                            int index = g->mon_at(it->x, it->y);
                            if (index != -1) {
                                if (g->zombie(index).hurt(tmp_item.weight() / 225)) {
                                    g->kill_mon(index, true);
                                }
                                g->m.add_item_or_charges(it->x, it->y, tmp_item);
                                break;
                            } else if (it != traj.begin() && g->m.move_cost(it->x, it->y) == 0) {
                                g->m.bash( it->x, it->y, tmp_item.weight() / 225 );
                                if (g->m.move_cost(it->x, it->y) == 0) {
                                    g->m.add_item_or_charges((it-1)->x, (it-1)->y, tmp_item);
                                    break;
                                }
                            }
                        }
                        if (it == traj.end()) {
                            g->m.add_item_or_charges(posx, posy, tmp_item);
                        }
                    }
                }
            }
        }
    } else if(bio.id == "bio_lockpick") {
        if(!choose_adjacent(_("Activate your bio lockpick where?"), dirx, diry)) {
            power_level += bionics["bio_lockpick"]->power_cost;
            return;
        }
        ter_id type = g->m.ter(dirx, diry);
        if (type  == t_door_locked || type == t_door_locked_alarm || type == t_door_locked_interior ) {
            moves -= 40;
            std::string door_name = rm_prefix(_("<door_name>door"));
            add_msg_if_player(m_neutral, _("With a satisfying click, the lock on the %s opens."),
                                 door_name.c_str());
            g->m.ter_set(dirx, diry, t_door_c);
            // Locked metal doors are the Lab and Bunker entries.  Those need to stay locked.
        } else if(type == t_door_bar_locked) {
            moves -= 40;
            std::string door_name = rm_prefix(_("<door_name>door"));
            add_msg_if_player(m_neutral, _("The %s swings open..."),
                                 door_name.c_str()); //Could better copy the messages from lockpick....
            g->m.ter_set(dirx, diry, t_door_bar_o);
        } else if(type == t_chaingate_l) {
            moves -= 40;
            std::string gate_name = rm_prefix (_("<door_name>gate"));
            add_msg_if_player(m_neutral, _("With a satisfying click, the lock on the %s opens."),
                                 gate_name.c_str());
            g->m.ter_set(dirx, diry, t_chaingate_c);
        } else if(type == t_door_c) {
            add_msg(m_info, _("That door isn't locked."));
        } else {
            add_msg_if_player(m_neutral, _("You can't unlock that %s."),
                              g->m.tername(dirx, diry).c_str());
        }
    } else if(bio.id == "bio_flashbang") {
        add_msg_if_player(m_neutral, _("You activate your integrated flashbang generator!"));
        g->flashbang(posx, posy, true);
    } else if(bio.id == "bio_shockwave") {
        g->shockwave(posx, posy, 3, 4, 2, 8, true);
        add_msg_if_player(m_neutral, _("You unleash a powerful shockwave!"));
    } else if(bio.id == "bio_ups"){
        add_msg_if_player(m_neutral, _("Your internal UPS powers on."));
    }
}
Esempio n. 17
0
void mdeath::normal(game *g, monster *z)
{
 if (g->u_see(z)) {
  g->add_msg(_("The %s dies!"), z->name().c_str());
 }
 if(z->type->difficulty >= 15) {
   g->u.add_memorial_log(_("Killed a %s."), z->name().c_str());
 }
 if (z->made_of("flesh") && z->has_flag(MF_WARM)) {
   g->m.add_field(g, z->posx, z->posy, fd_blood, 1);
 }

    int gib_amount = 0;
    bool leave_corpse = false;
    int corpse_damage = 0;
// determine how much of a mess is left, for flesh and veggy creatures
    if (z->made_of("flesh") || z->made_of("veggy") || z->made_of("hflesh"))
    {
        if (z->hp >= 0 - 2 * z->type->hp) // less than 2x monster hp overkill, leave corpse
        {
            leave_corpse = true;
            corpse_damage = 0;
        }
        if (z->hp >= 0 - 2 * z->type->hp - 20 && z->hp < 0 - 2 * z->type->hp) // corpse with damage 1
        {
            leave_corpse = true;
            corpse_damage = 1;
            gib_amount = rng(1,3);
        }
        if (z->hp >= 0 - 2 * z->type->hp - 40 && z->hp < 0 - 2 * z->type->hp - 20) // corpse with damage 2
        {
            leave_corpse = true;
            corpse_damage = 2;
            gib_amount = rng(2,5);
        }
        if (z->hp >= 0 - 2 * z->type->hp - 60 && z->hp < 0 - 2 * z->type->hp - 40) // corpse with damage 3
        {
            leave_corpse = true;
            corpse_damage = 3;
            gib_amount = rng(3,9);
        }
        if (z->hp >= 0 - 2 * z->type->hp - 80 && z->hp < 0 - 2 * z->type->hp - 60) // corpse with damage 4
        {
            leave_corpse = true;
            corpse_damage = 4;
            gib_amount = rng(4,12);
        }
        if (z->hp <= 0 - 2 * z->type->hp - 80) // no corpse if MS_TINY or MS_SMALL, gib_amount fields only
        {
            if (z->type->size == MS_MEDIUM || z->type->size == MS_LARGE || z->type->size == MS_HUGE)
            {
                leave_corpse = true;
                corpse_damage = 4;
            }
            else
            {
                leave_corpse = false;
            }
            gib_amount = rng(5,15);
        }
    }

    // leave a corpse, if any
    if (leave_corpse)
    {
        item tmp;
        tmp.make_corpse(g->itypes["corpse"], z->type, g->turn);
        tmp.damage = corpse_damage;
        g->m.add_item_or_charges(z->posx, z->posy, tmp);
    }

    // leave gibs
    for (int i = 0; i < gib_amount; i++)
    {
        const int rand_posx = z->posx + rng(1,5) - 3;
        const int rand_posy = z->posy + rng(1,5) - 3;
        const int rand_density = rng(1, 3);

        if (z->made_of("flesh") || z->made_of("hflesh"))
        {
            g->m.add_field(g, rand_posx, rand_posy, fd_gibs_flesh, rand_density);
        }
        else if (z->made_of("veggy"))
        {
            g->m.add_field(g, rand_posx, rand_posy, fd_gibs_veggy, rand_density);
        }
    }
}
Esempio n. 18
0
bool player::uninstall_bionic(bionic_id b_id)
{
    // malfunctioning bionics don't have associated items and get a difficulty of 12
    int difficulty = 12;
    if( item_controller->has_template(b_id) > 0) {
        const it_bionic *type = dynamic_cast<it_bionic *> (item_controller->find_template(b_id));
        difficulty = type->difficulty;
    }

    if (!has_bionic(b_id)) {
        popup(_("You don't have this bionic installed."));
        return false;
    }
    if (!(inv.has_items_with_quality("CUT", 1, 1) && has_amount("1st_aid", 1))) {
        popup(_("Removing bionics requires a cutting tool and a first aid kit."));
        return false;
    }
    
    if ( b_id == "bio_blaster" ) {
        popup(_("Removing your Fusion Blaster Arm would leave you with a useless stump."));
        return false;
    }

    // removal of bionics adds +2 difficulty over installation
    int chance_of_success = bionic_manip_cos(int_cur,
                            skillLevel("electronics"),
                            skillLevel("firstaid"),
                            skillLevel("mechanics"),
                            difficulty + 2);

    if (!query_yn(_("WARNING: %i percent chance of SEVERE bodily damage! Remove anyway?"),
                  100 - chance_of_success)) {
        return false;
    }

    use_charges("1st_aid", 1);

    practice( "electronics", int((100 - chance_of_success) * 1.5) );
    practice( "firstaid", int((100 - chance_of_success) * 1.0) );
    practice( "mechanics", int((100 - chance_of_success) * 0.5) );

    int success = chance_of_success - rng(1, 100);

    if (success > 0) {
        add_memorial_log(pgettext("memorial_male", "Removed bionic: %s."),
                         pgettext("memorial_female", "Removed bionic: %s."),
                         bionics[b_id]->name.c_str());
        // until bionics can be flagged as non-removable
        add_msg(m_neutral, _("You jiggle your parts back into their familiar places."));
        add_msg(m_good, _("Successfully removed %s."), bionics[b_id]->name.c_str());
        remove_bionic(b_id);
        g->m.spawn_item(posx, posy, "burnt_out_bionic", 1);
    } else {
        add_memorial_log(pgettext("memorial_male", "Removed bionic: %s."),
                         pgettext("memorial_female", "Removed bionic: %s."),
                         bionics[b_id]->name.c_str());
        bionics_uninstall_failure(this);
    }
    g->refresh_all();
    return true;
}
Esempio n. 19
0
/**
 * Attempts to harm a creature with a projectile.
 *
 * @param source Pointer to the creature who shot the projectile.
 * @param missed_by Deviation of the projectile.
 * @param proj Reference to the projectile hitting the creature.
 * @param dealt_dam A reference storing the damage dealt.
 * @return 0 signals that the projectile should stop,
 *         1 signals that the projectile should not stop (i.e. dodged, passed through).
 */
int Creature::deal_projectile_attack(Creature *source, double missed_by,
                                     const projectile &proj, dealt_damage_instance &dealt_dam)
{
    bool u_see_this = g->u_see(this);
    body_part bp_hit;

    // do 10,speed because speed could potentially be > 10000
    if (dodge_roll() >= dice(10, proj.speed)) {
        if (is_player())
            add_msg(_("You dodge %s projectile!"),
                    source->disp_name(true).c_str());
        else if (u_see_this)
            add_msg(_("%s dodges %s projectile."),
                    disp_name().c_str(), source->disp_name(true).c_str());
        return 1;
    }

    // Bounce applies whether it does damage or not.
    if (proj.proj_effects.count("BOUNCE")) {
        add_effect("bounced", 1);
    }

    double hit_value = missed_by + rng_float(-0.5, 0.5);
    // headshots considered elsewhere
    if (hit_value <= 0.4) {
        bp_hit = bp_torso;
    } else if (one_in(4)) {
        if( one_in(2)) {
            bp_hit = bp_leg_l;
        } else {
            bp_hit = bp_leg_r;
        }
    } else {
        if( one_in(2)) {
            bp_hit = bp_arm_l;
        } else {
            bp_hit = bp_arm_r;
        }
    }

    double monster_speed_penalty = std::max(double(get_speed()) / 80., 1.0);
    double goodhit = missed_by / monster_speed_penalty;
    double damage_mult = 1.0;

    std::string message = "";
    game_message_type gmtSCTcolor = m_neutral;

    if (goodhit <= .1) {
        message = _("Headshot!");
        source->add_msg_if_player(m_good, message.c_str());
        gmtSCTcolor = m_headshot;
        damage_mult *= rng_float(2.45, 3.35);
        bp_hit = bp_head; // headshot hits the head, of course
    } else if (goodhit <= .2) {
        message = _("Critical!");
        source->add_msg_if_player(m_good, message.c_str());
        gmtSCTcolor = m_critical;
        damage_mult *= rng_float(1.75, 2.3);
    } else if (goodhit <= .4) {
        message = _("Good hit!");
        source->add_msg_if_player(m_good, message.c_str());
        gmtSCTcolor = m_good;
        damage_mult *= rng_float(1, 1.5);
    } else if (goodhit <= .6) {
        damage_mult *= rng_float(0.5, 1);
    } else if (goodhit <= .8) {
        message = _("Grazing hit.");
        source->add_msg_if_player(m_good, message.c_str());
        gmtSCTcolor = m_grazing;
        damage_mult *= rng_float(0, .25);
    } else {
        damage_mult *= 0;
    }

    // copy it, since we're mutating
    damage_instance impact = proj.impact;
    if( item(proj.ammo->id, 0).has_flag("NOGIB") ) {
        impact.add_effect("NOGIB");
    }
    impact.mult_damage(damage_mult);

    dealt_dam = deal_damage(source, bp_hit, impact);
    dealt_dam.bp_hit = bp_hit;

    // Apply ammo effects to target.
    const std::string target_material = get_material();
    if (proj.proj_effects.count("FLAME")) {
        if (0 == target_material.compare("veggy") || 0 == target_material.compare("cotton") ||
            0 == target_material.compare("wool") || 0 == target_material.compare("paper") ||
            0 == target_material.compare("wood" ) ) {
            add_effect("onfire", rng(8, 20));
        } else if (0 == target_material.compare("flesh") || 0 == target_material.compare("iflesh") ) {
            add_effect("onfire", rng(5, 10));
        }
    } else if (proj.proj_effects.count("INCENDIARY") ) {
        if (0 == target_material.compare("veggy") || 0 == target_material.compare("cotton") ||
            0 == target_material.compare("wool") || 0 == target_material.compare("paper") ||
            0 == target_material.compare("wood") ) {
            add_effect("onfire", rng(2, 6));
        } else if ( (0 == target_material.compare("flesh") || 0 == target_material.compare("iflesh") ) &&
                    one_in(4) ) {
            add_effect("onfire", rng(1, 4));
        }
    } else if (proj.proj_effects.count("IGNITE")) {
        if (0 == target_material.compare("veggy") || 0 == target_material.compare("cotton") ||
            0 == target_material.compare("wool") || 0 == target_material.compare("paper") ||
            0 == target_material.compare("wood") ) {
            add_effect("onfire", rng(6, 6));
        } else if (0 == target_material.compare("flesh") || 0 == target_material.compare("iflesh") ) {
            add_effect("onfire", rng(10, 10));
        }
    }
    int stun_strength = 0;
    if (proj.proj_effects.count("BEANBAG")) {
        stun_strength = 4;
    }
    if(proj.proj_effects.count("WHIP")) {
        stun_strength = rng(4, 10);
    }
    if (proj.proj_effects.count("LARGE_BEANBAG")) {
        stun_strength = 16;
    }
    if( stun_strength > 0 ) {
        switch( get_size() ) {
        case MS_TINY:
            stun_strength *= 4;
            break;
        case MS_SMALL:
            stun_strength *= 2;
            break;
        case MS_MEDIUM:
        default:
            break;
        case MS_LARGE:
            stun_strength /= 2;
            break;
        case MS_HUGE:
            stun_strength /= 4;
            break;
        }
        add_effect( "stunned", rng(stun_strength / 2, stun_strength) );
    }

    if(u_see_this) {
        if (damage_mult == 0) {
            if(source != NULL) {
                add_msg(source->is_player() ? _("You miss!") : _("The shot misses!"));
            }
        } else if (dealt_dam.total_damage() == 0) {
            add_msg(_("The shot reflects off %s %s!"), disp_name(true).c_str(),
                    skin_name().c_str());
        } else if (source != NULL) {
            if (source->is_player()) {
                //player hits monster ranged
                nc_color color;
                std::string health_bar = "";
                get_HP_Bar(dealt_dam.total_damage(), this->get_hp_max(), color, health_bar, true);

                SCT.add(this->xpos(),
                        this->ypos(),
                        direction_from(0, 0, this->xpos() - source->xpos(), this->ypos() - source->ypos()),
                        health_bar, m_good,
                        message, gmtSCTcolor);

                if (this->get_hp() > 0) {
                    get_HP_Bar(this->get_hp(), this->get_hp_max(), color, health_bar, true);

                    SCT.add(this->xpos(),
                            this->ypos(),
                            direction_from(0, 0, this->xpos() - source->xpos(), this->ypos() - source->ypos()),
                            health_bar, m_good,
                            //~ “hit points”, used in scrolling combat text
                            _("hp"), m_neutral,
                            "hp");
                } else {
                    SCT.removeCreatureHP();
                }

                add_msg(m_good, _("You hit the %s for %d damage."),
                        disp_name().c_str(), dealt_dam.total_damage());

            } else if(this->is_player()) {
                //monster hits player ranged
                //~ Hit message. 1$s is bodypart name in accusative. 2$d is damage value.
                add_msg_if_player(m_bad, _( "You were hit in the %1$s for %2$d damage." ),
                                  body_part_name_accusative(bp_hit).c_str( ),
                                  dealt_dam.total_damage());
            } else if( u_see_this ) {
                add_msg(_("%s shoots %s."),
                        source->disp_name().c_str(), disp_name().c_str());
            }
        }
    }
    if (this->is_dead_state()) {
        this->die(source);
    }
    return 0;
}
Esempio n. 20
0
void bionics_install_failure(player *u, it_bionic *type, int success)
{
    // "success" should be passed in as a negative integer representing how far off we
    // were for a successful install.  We use this to determine consequences for failing.
    success = abs(success);

    // it would be better for code reuse just to pass in skill as an argument from install_bionic
    // pl_skill should be calculated the same as in install_bionics
    int pl_skill = u->int_cur * 4 +
                   u->skillLevel("electronics") * 4 +
                   u->skillLevel("firstaid")    * 3 +
                   u->skillLevel("mechanics")   * 1;

    // for failure_level calculation, shift skill down to a float between ~0.4 - 30
    float adjusted_skill = float (pl_skill) - std::min( float (40),
                           float (pl_skill) - float (pl_skill) / float (10.0));

    // failure level is decided by how far off the character was from a successful install, and
    // this is scaled up or down by the ratio of difficulty/skill.  At high skill levels (or low
    // difficulties), only minor consequences occur.  At low skill levels, severe consequences
    // are more likely.
    int failure_level = int(sqrt(success * 4.0 * type->difficulty / float (adjusted_skill)));
    int fail_type = (failure_level > 5 ? 5 : failure_level);

    if (fail_type <= 0) {
        add_msg(m_neutral, _("The installation fails without incident."));
        return;
    }

    switch (rng(1, 5)) {
    case 1:
        add_msg(m_neutral, _("You flub the installation."));
        break;
    case 2:
        add_msg(m_neutral, _("You mess up the installation."));
        break;
    case 3:
        add_msg(m_neutral, _("The installation fails."));
        break;
    case 4:
        add_msg(m_neutral, _("The installation is a failure."));
        break;
    case 5:
        add_msg(m_neutral, _("You screw up the installation."));
        break;
    }

    if (fail_type == 3 && u->num_bionics() == 0) {
        fail_type = 2;    // If we have no bionics, take damage instead of losing some
    }

    switch (fail_type) {

    case 1:
        if (!(u->has_trait("NOPAIN"))) {
            add_msg(m_bad, _("It really hurts!"));
            u->mod_pain( rng(failure_level * 3, failure_level * 6) );
        }
        break;

    case 2:
        add_msg(m_bad, _("Your body is damaged!"));
        u->hurtall(rng(failure_level, failure_level * 2));
        break;

    case 3:
        if (u->num_bionics() <= failure_level) {
            add_msg(m_bad, _("All of your existing bionics are lost!"));
        } else {
            add_msg(m_bad, _("Some of your existing bionics are lost!"));
        }
        for (int i = 0; i < failure_level && u->remove_random_bionic(); i++) {
            ;
        }
        break;

    case 4:
        add_msg(m_mixed, _("You do damage to your genetics, causing mutation!"));
        while (failure_level > 0) {
            u->mutate();
            failure_level -= rng(1, failure_level + 2);
        }
        break;

    case 5: {
        add_msg(m_bad, _("The installation is faulty!"));
        std::vector<bionic_id> valid;
        for (std::vector<std::string>::iterator it = faulty_bionics.begin() ; it != faulty_bionics.end();
             ++it) {
            if (!u->has_bionic(*it)) {
                valid.push_back(*it);
            }
        }
        if (valid.empty()) { // We've got all the bad bionics!
            if (u->max_power_level > 0) {
                int old_power = u->max_power_level;
                add_msg(m_bad, _("You lose power capacity!"));
                u->max_power_level = rng(0, u->max_power_level - 1);
                g->u.add_memorial_log(pgettext("memorial_male", "Lost %d units of power capacity."),
                                      pgettext("memorial_female", "Lost %d units of power capacity."),
                                      old_power - u->max_power_level);
            }
            // TODO: What if we can't lose power capacity?  No penalty?
        } else {
            int index = rng(0, valid.size() - 1);
            u->add_bionic(valid[index]);
            u->add_memorial_log(pgettext("memorial_male", "Installed bad bionic: %s."),
                                pgettext("memorial_female", "Installed bad bionic: %s."),
                                bionics[valid[index]]->name.c_str());
        }
    }
    break;
    }
}
Esempio n. 21
0
void monster::plan( const mfactions &factions )
{
    // Bots are more intelligent than most living stuff
    bool smart_planning = has_flag( MF_PRIORITIZE_TARGETS );
    Creature *target = nullptr;
    // 8.6f is rating for tank drone 60 tiles away, moose 16 or boomer 33
    float dist = !smart_planning ? 1000 : 8.6f;
    bool fleeing = false;
    bool docile = friendly != 0 && has_effect( effect_docile );
    bool angers_hostile_weak = type->anger.find( MTRIG_HOSTILE_WEAK ) != type->anger.end();
    int angers_hostile_near =
        ( type->anger.find( MTRIG_HOSTILE_CLOSE ) != type->anger.end() ) ? 5 : 0;
    int fears_hostile_near = ( type->fear.find( MTRIG_HOSTILE_CLOSE ) != type->fear.end() ) ? 5 : 0;
    bool group_morale = has_flag( MF_GROUP_MORALE ) && morale < type->morale;
    bool swarms = has_flag( MF_SWARMS );
    auto mood = attitude();

    // If we can see the player, move toward them or flee, simpleminded animals are too dumb to follow the player.
    if( friendly == 0 && sees( g->u ) && !has_flag( MF_PET_WONT_FOLLOW ) ) {
        dist = rate_target( g->u, dist, smart_planning );
        fleeing = fleeing || is_fleeing( g->u );
        target = &g->u;
        if( dist <= 5 ) {
            anger += angers_hostile_near;
            morale -= fears_hostile_near;
        }
    } else if( friendly != 0 && !docile ) {
        // Target unfriendly monsters, only if we aren't interacting with the player.
        for( monster &tmp : g->all_monsters() ) {
            if( tmp.friendly == 0 ) {
                float rating = rate_target( tmp, dist, smart_planning );
                if( rating < dist ) {
                    target = &tmp;
                    dist = rating;
                }
            }
        }
    }

    if( docile ) {
        if( friendly != 0 && target != nullptr ) {
            set_dest( target->pos() );
        }

        return;
    }

    for( npc &who : g->all_npcs() ) {
        auto faction_att = faction.obj().attitude( who.get_monster_faction() );
        if( faction_att == MFA_NEUTRAL || faction_att == MFA_FRIENDLY ) {
            continue;
        }

        float rating = rate_target( who, dist, smart_planning );
        bool fleeing_from = is_fleeing( who );
        // Switch targets if closer and hostile or scarier than current target
        if( ( rating < dist && fleeing ) ||
            ( rating < dist && attitude( &who ) == MATT_ATTACK ) ||
            ( !fleeing && fleeing_from ) ) {
            target = &who;
            dist = rating;
        }
        fleeing = fleeing || fleeing_from;
        if( rating <= 5 ) {
            anger += angers_hostile_near;
            morale -= fears_hostile_near;
        }
    }

    fleeing = fleeing || ( mood == MATT_FLEE );
    if( friendly == 0 ) {
        for( const auto &fac : factions ) {
            auto faction_att = faction.obj().attitude( fac.first );
            if( faction_att == MFA_NEUTRAL || faction_att == MFA_FRIENDLY ) {
                continue;
            }

            for( monster *const mon_ptr : fac.second ) {
                monster &mon = *mon_ptr;
                float rating = rate_target( mon, dist, smart_planning );
                if( rating < dist ) {
                    target = &mon;
                    dist = rating;
                }
                if( rating <= 5 ) {
                    anger += angers_hostile_near;
                    morale -= fears_hostile_near;
                }
            }
        }
    }

    // Friendly monsters here
    // Avoid for hordes of same-faction stuff or it could get expensive
    const auto actual_faction = friendly == 0 ? faction : mfaction_str_id( "player" );
    auto const &myfaction_iter = factions.find( actual_faction );
    if( myfaction_iter == factions.end() ) {
        DebugLog( D_ERROR, D_GAME ) << disp_name() << " tried to find faction "
                                    << actual_faction.id().str()
                                    << " which wasn't loaded in game::monmove";
        swarms = false;
        group_morale = false;
    }
    swarms = swarms && target == nullptr; // Only swarm if we have no target
    if( group_morale || swarms ) {
        for( monster *const mon_ptr : myfaction_iter->second ) {
            monster &mon = *mon_ptr;
            float rating = rate_target( mon, dist, smart_planning );
            if( group_morale && rating <= 10 ) {
                morale += 10 - rating;
            }
            if( swarms ) {
                if( rating < 5 ) { // Too crowded here
                    wander_pos.x = posx() * rng( 1, 3 ) - mon.posx();
                    wander_pos.y = posy() * rng( 1, 3 ) - mon.posy();
                    wandf = 2;
                    target = nullptr;
                    // Swarm to the furthest ally you can see
                } else if( rating < INT_MAX && rating > dist && wandf <= 0 ) {
                    target = &mon;
                    dist = rating;
                }
            }
        }
    }

    if( target != nullptr ) {

        tripoint dest = target->pos();
        auto att_to_target = attitude_to( *target );
        if( att_to_target == Attitude::A_HOSTILE && !fleeing ) {
            set_dest( dest );
        } else if( fleeing ) {
            set_dest( tripoint( posx() * 2 - dest.x, posy() * 2 - dest.y, posz() ) );
        }
        if( angers_hostile_weak && att_to_target != Attitude::A_FRIENDLY ) {
            int hp_per = target->hp_percentage();
            if( hp_per <= 70 ) {
                anger += 10 - int( hp_per / 10 );
            }
        }
    } else if( friendly > 0 && one_in( 3 ) ) {
        // Grow restless with no targets
        friendly--;
    } else if( friendly < 0 && sees( g->u ) ) {
        if( rl_dist( pos(), g->u.pos() ) > 2 ) {
            set_dest( g->u.pos() );
        } else {
            unset_dest();
        }
    }
}
Esempio n. 22
0
	uint64_t randint() {
		return rng();
	}
Esempio n. 23
0
void trapfunc::sinkhole(int x, int y)
{
    (void)x; (void)y; // unused
 g->add_msg(_("You step into a sinkhole, and start to sink down!"));
 g->u.add_memorial_log(pgettext("memorial_male", "Stepped into a sinkhole."),
                       pgettext("memorial_female", "Stepped into a sinkhole."));
 if (g->u.has_amount("grapnel", 1) &&
     query_yn(_("There is a sinkhole here. Throw your grappling hook out to try to catch something?"))) {
  int throwroll = rng(g->u.skillLevel("throw"),
                      g->u.skillLevel("throw") + g->u.str_cur + g->u.dex_cur);
  if (throwroll >= 6) {
   g->add_msg(_("The grappling hook catches something!"));
   if (rng(g->u.skillLevel("unarmed"),
           g->u.skillLevel("unarmed") + g->u.str_cur) > 4) {
// Determine safe places for the character to get pulled to
    std::vector<point> safe;
    for (int i = g->u.posx - 1; i <= g->u.posx + 1; i++) {
     for (int j = g->u.posy - 1; j <= g->u.posy + 1; j++) {
      if (g->m.move_cost(i, j) > 0 && g->m.tr_at(i, j) != tr_pit)
       safe.push_back(point(i, j));
     }
    }
    if (safe.empty()) {
     g->add_msg(_("There's nowhere to pull yourself to, and you sink!"));
     g->u.use_amount("grapnel", 1);
     g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "grapnel");
     g->m.ter_set(g->u.posx, g->u.posy, t_hole);
     g->vertical_move(-1, true);
    } else {
     g->add_msg(_("You pull yourself to safety!  The sinkhole collapses."));
     int index = rng(0, safe.size() - 1);
     g->m.ter_set(g->u.posx, g->u.posy, t_hole);
     g->u.posx = safe[index].x;
     g->u.posy = safe[index].y;
     g->update_map(g->u.posx, g->u.posy);
    }
   } else {
    g->add_msg(_("You're not strong enough to pull yourself out..."));
    g->u.moves -= 100;
    g->u.use_amount("grapnel", 1);
    g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "grapnel");
    g->m.ter_set(g->u.posx, g->u.posy, t_hole);
    g->vertical_move(-1, true);
   }
  } else {
   g->add_msg(_("Your throw misses completely, and you sink!"));
   if (one_in((g->u.str_cur + g->u.dex_cur) / 3)) {
    g->u.use_amount("grapnel", 1);
    g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "grapnel");
   }
   g->m.ter_set(g->u.posx, g->u.posy, t_hole);
   g->vertical_move(-1, true);
  }
 } else if (g->u.has_amount("rope_30", 1) &&
     query_yn(_("There is a sinkhole here. Throw your rope out to try to catch something?"))) {
  int throwroll = rng(g->u.skillLevel("throw"),
                      g->u.skillLevel("throw") + g->u.str_cur + g->u.dex_cur);
  if (throwroll >= 12) {
   g->add_msg(_("The rope catches something!"));
   if (rng(g->u.skillLevel("unarmed"),
           g->u.skillLevel("unarmed") + g->u.str_cur) > 6) {
// Determine safe places for the character to get pulled to
    std::vector<point> safe;
    for (int i = g->u.posx - 1; i <= g->u.posx + 1; i++) {
     for (int j = g->u.posy - 1; j <= g->u.posy + 1; j++) {
      if (g->m.move_cost(i, j) > 0 && g->m.tr_at(i, j) != tr_pit)
       safe.push_back(point(i, j));
     }
    }
    if (safe.empty()) {
     g->add_msg(_("There's nowhere to pull yourself to, and you sink!"));
     g->u.use_amount("rope_30", 1);
     g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "rope_30");
     g->m.ter_set(g->u.posx, g->u.posy, t_hole);
     g->vertical_move(-1, true);
    } else {
     g->add_msg(_("You pull yourself to safety!  The sinkhole collapses."));
     int index = rng(0, safe.size() - 1);
     g->m.ter_set(g->u.posx, g->u.posy, t_hole);
     g->u.posx = safe[index].x;
     g->u.posy = safe[index].y;
     g->update_map(g->u.posx, g->u.posy);
    }
   } else {
    g->add_msg(_("You're not strong enough to pull yourself out..."));
    g->u.moves -= 100;
    g->u.use_amount("rope_30", 1);
    g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "rope_30");
    g->m.ter_set(g->u.posx, g->u.posy, t_hole);
    g->vertical_move(-1, true);
   }
  } else {
   g->add_msg(_("Your throw misses completely, and you sink!"));
   if (one_in((g->u.str_cur + g->u.dex_cur) / 3)) {
    g->u.use_amount("rope_30", 1);
    g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "rope_30");
   }
   g->m.ter_set(g->u.posx, g->u.posy, t_hole);
   g->vertical_move(-1, true);
  }
 } else {
  g->add_msg(_("You sink into the sinkhole!"));
  g->m.ter_set(g->u.posx, g->u.posy, t_hole);
  g->vertical_move(-1, true);
 }
}
Esempio n. 24
0
void monster::die(game *g)
{
 if (!dead)
  dead = true;
// Drop goodies
 int total_chance = 0, total_it_chance, cur_chance, selected_location,
     selected_item;
 bool animal_done = false;
 std::vector<items_location_and_chance> it = g->monitems[type->id];
 std::vector<itype_id> mapit;
 if (type->item_chance != 0 && it.size() == 0)
  debugmsg("Type %s has item_chance %d but no items assigned!",
           type->name.c_str(), type->item_chance);
 else {
  for (int i = 0; i < it.size(); i++)
   total_chance += it[i].chance;

  while (rng(0, 99) < abs(type->item_chance) && !animal_done) {
   cur_chance = rng(1, total_chance);
   selected_location = -1;
   while (cur_chance > 0) {
    selected_location++;
    cur_chance -= it[selected_location].chance;
   }
   total_it_chance = 0;
   mapit = g->mapitems[it[selected_location].loc];
   for (int i = 0; i < mapit.size(); i++)
    total_it_chance += g->itypes[mapit[i]]->rarity;
   cur_chance = rng(1, total_it_chance);
   selected_item = -1;
   while (cur_chance > 0) {
    selected_item++;
    cur_chance -= g->itypes[mapit[selected_item]]->rarity;
   }
   g->m.spawn_item(posx, posy, g->itypes[mapit[selected_item]], 0);
   if (type->item_chance < 0)
    animal_done = true;	// Only drop ONE item.
  }
 } // Done dropping items

// If we're a queen, make nearby groups of our type start to die out
 if (has_flag(MF_QUEEN)) {
// Do it for overmap above/below too
  for(int z = 0; z >= -1; --z) {
   std::vector<mongroup*> groups = g->cur_om.monsters_at(g->levx, g->levy, z);
   for (int i = 0; i < groups.size(); i++) {
   if (MonsterGroupManager::IsMonsterInGroup(groups[i]->type, mon_id(type->id)))
    groups[i]->dying = true;
   }
  }
 }
// If we're a mission monster, update the mission
 if (mission_id != -1) {
  mission_type *misstype = g->find_mission_type(mission_id);
  if (misstype->goal == MGOAL_FIND_MONSTER)
   g->fail_mission(mission_id);
  if (misstype->goal == MGOAL_KILL_MONSTER)
   g->mission_step_complete(mission_id, 1);
 }
// Also, perform our death function
 mdeath md;
 (md.*type->dies)(g, this);
// If our species fears seeing one of our own die, process that
 int anger_adjust = 0, morale_adjust = 0;
 for (int i = 0; i < type->anger.size(); i++) {
  if (type->anger[i] == MTRIG_FRIEND_DIED)
   anger_adjust += 15;
 }
 for (int i = 0; i < type->placate.size(); i++) {
  if (type->placate[i] == MTRIG_FRIEND_DIED)
   anger_adjust -= 15;
 }
 for (int i = 0; i < type->fear.size(); i++) {
  if (type->fear[i] == MTRIG_FRIEND_DIED)
   morale_adjust -= 15;
 }
 if (anger_adjust != 0 && morale_adjust != 0) {
  int light = g->light_level();
  for (int i = 0; i < g->z.size(); i++) {
   int t = 0;
   if (g->m.sees(g->z[i].posx, g->z[i].posy, posx, posy, light, t)) {
    g->z[i].morale += morale_adjust;
    g->z[i].anger += anger_adjust;
   }
  }
 }
}
Esempio n. 25
0
void defense_game::init_map(game *g)
{
 for (int x = 0; x < OMAPX; x++) {
  for (int y = 0; y < OMAPY; y++) {
   g->cur_om.ter(x, y, 0) = ot_field;
   g->cur_om.seen(x, y, 0) = true;
  }
 }

 g->cur_om.save();
 g->levx = 100;
 g->levy = 100;
 g->levz = 0;
 g->u.posx = SEEX;
 g->u.posy = SEEY;

 switch (location) {

 case DEFLOC_HOSPITAL:
  for (int x = 49; x <= 51; x++) {
   for (int y = 49; y <= 51; y++)
    g->cur_om.ter(x, y, 0) = ot_hospital;
  }
  g->cur_om.ter(50, 49, 0) = ot_hospital_entrance;
  break;

 case DEFLOC_MALL:
  for (int x = 49; x <= 51; x++) {
   for (int y = 49; y <= 51; y++)
    g->cur_om.ter(x, y, 0) = ot_megastore;
  }
  g->cur_om.ter(50, 49, 0) = ot_megastore_entrance;
  break;

 case DEFLOC_BAR:
  g->cur_om.ter(50, 50, 0) = ot_bar_north;
  break;

 case DEFLOC_MANSION:
  for (int x = 49; x <= 51; x++) {
   for (int y = 49; y <= 51; y++)
    g->cur_om.ter(x, y, 0) = ot_mansion;
  }
  g->cur_om.ter(50, 49, 0) = ot_mansion_entrance;
  break;
 }
// Init the map
 int old_percent = 0;
 for (int i = 0; i <= MAPSIZE * 2; i += 2) {
  for (int j = 0; j <= MAPSIZE * 2; j += 2) {
   int mx = g->levx - MAPSIZE + i, my = g->levy - MAPSIZE + j;
   int percent = 100 * ((j / 2 + MAPSIZE * (i / 2))) /
                       ((MAPSIZE) * (MAPSIZE + 1));
   if (percent >= old_percent + 1) {
    popup_nowait("Please wait as the map generates [%s%d%]",
                 (percent < 10 ? " " : ""), percent);
    old_percent = percent;
   }
// Round down to the nearest even number
   mx -= mx % 2;
   my -= my % 2;
   tinymap tm(&g->itypes, &g->mapitems, &g->traps);
   tm.generate(g, &(g->cur_om), mx, my, 0, int(g->turn));
   tm.clear_spawns();
   tm.clear_traps();
   tm.save(&g->cur_om, int(g->turn), mx, my, 0);
  }
 }

 g->m.load(g, g->levx, g->levy, g->levz, true);

 g->update_map(g->u.posx, g->u.posy);
 monster generator(g->mtypes[mon_generator], g->u.posx + 1, g->u.posy + 1);
// Find a valid spot to spawn the generator
 std::vector<point> valid;
 for (int x = g->u.posx - 1; x <= g->u.posx + 1; x++) {
  for (int y = g->u.posy - 1; y <= g->u.posy + 1; y++) {
   if (generator.can_move_to(g->m, x, y) && g->is_empty(x, y))
    valid.push_back( point(x, y) );
  }
 }
 if (!valid.empty()) {
  point p = valid[rng(0, valid.size() - 1)];
  generator.spawn(p.x, p.y);
 }
 generator.friendly = -1;
 g->z.push_back(generator);
}
Esempio n. 26
0
void monster::make_friendly()
{
 plans.clear();
 friendly = rng(5, 30) + rng(0, 20);
}
Esempio n. 27
0
void mission_start::place_caravan_ambush(mission *miss)
{
 point site = target_om_ter_random("field", 1, miss, false);
 tinymap bay;
 bay.load(site.x * 2, site.y * 2, g->get_levz(), false);
 bay.add_vehicle("cube_van", SEEX, SEEY, 0);
 bay.add_vehicle("quad_bike", SEEX+6, SEEY-5, 270, 500, -1, true);
 bay.add_vehicle("motorcycle", SEEX-2, SEEY-9, 315, 500, -1, true);
 bay.add_vehicle("motorcycle", SEEX-5, SEEY-5, 90, 500, -1, true);
 bay.draw_square_ter(t_grass, SEEX-6, SEEY-9, SEEX+6, SEEY+3);
 bay.draw_square_ter(t_dirt, SEEX-4, SEEY-7, SEEX+3, SEEY+1);
 bay.furn_set(SEEX, SEEY-4, f_ash);
 bay.spawn_item(SEEX-1, SEEY-3, "rock");
 bay.spawn_item(SEEX, SEEY-3, "rock");
 bay.spawn_item(SEEX+1, SEEY-3, "rock");
 bay.spawn_item(SEEX-1, SEEY-4, "rock");
 bay.spawn_item(SEEX+1, SEEY-4, "rock");
 bay.spawn_item(SEEX-1, SEEY-5, "rock");
 bay.spawn_item(SEEX, SEEY-5, "rock");
 bay.spawn_item(SEEX+1, SEEY-5, "rock");
 bay.trap_set(SEEX+3, SEEY-5, tr_rollmat);
 bay.trap_set(SEEX, SEEY-7, tr_rollmat);
 bay.trap_set(SEEX-3, SEEY-4, tr_fur_rollmat);
 bay.spawn_item(SEEX+rng(-6,6), SEEY+rng(-9,3), "can_beans");
 bay.spawn_item(SEEX+rng(-6,6), SEEY+rng(-9,3), "beer");
 bay.spawn_item(SEEX+rng(-6,6), SEEY+rng(-9,3), "beer");
 bay.spawn_item(SEEX+rng(-6,6), SEEY+rng(-9,3), "bottle_glass");
 bay.spawn_item(SEEX+rng(-6,6), SEEY+rng(-9,3), "bottle_glass");
 bay.spawn_item(SEEX+rng(-6,6), SEEY+rng(-9,3), "heroin");
 bay.place_items("dresser", 75, SEEX-3, SEEY, SEEX-2, SEEY+2, true, 0 );
 bay.place_items("softdrugs", 50, SEEX-3, SEEY, SEEX-2, SEEY+2, true, 0 );
 bay.place_items("camping", 75, SEEX-3, SEEY, SEEX-2, SEEY+2, true, 0 );
 bay.spawn_item(SEEX+1, SEEY+4, "9mm_casing",1,1,0,0,true);
 bay.spawn_item(SEEX+rng(-2,3), SEEY+rng(3,6), "9mm_casing",1,1,0,0,true);
 bay.spawn_item(SEEX+rng(-2,3), SEEY+rng(3,6), "9mm_casing",1,1,0,0,true);
 bay.spawn_item(SEEX+rng(-2,3), SEEY+rng(3,6), "9mm_casing",1,1,0,0,true);
 bay.add_corpse(SEEX+1, SEEY+7);
 bay.add_corpse(SEEX, SEEY+8);
 bay.add_field(SEEX, SEEY+7,fd_blood,1);
 bay.add_field(SEEX+2, SEEY+7,fd_blood,1);
 bay.add_field(SEEX-1, SEEY+8,fd_blood,1);
 bay.add_field(SEEX+1, SEEY+8,fd_blood,1);
 bay.add_field(SEEX+2, SEEY+8,fd_blood,1);
 bay.add_field(SEEX+1, SEEY+9,fd_blood,1);
 bay.add_field(SEEX, SEEY+9,fd_blood,1);
 bay.place_npc(SEEX+3,SEEY-5, "bandit");
 bay.place_npc(SEEX, SEEY-7, "thug");
 miss->target_npc_id = bay.place_npc(SEEX-3, SEEY-4, "bandit");
 bay.save();
}
Esempio n. 28
0
//////////////////////// Sector
Sector::Sector(int x, int y, int z)
{
	unsigned long _init[4] = { x, y, z, UNIVERSE_SEED };
	sx = x; sy = y; sz = z;
	MTRand rng(_init, 4);
	MTRand rand(UNIVERSE_SEED);

	GetCustomSystems();

	/* Always place random systems outside the core custom-only region */
	if ((x < -CUSTOM_ONLY_RADIUS) || (x > CUSTOM_ONLY_RADIUS-1) ||
	    (y < -CUSTOM_ONLY_RADIUS) || (y > CUSTOM_ONLY_RADIUS-1) ||
	    (z < -CUSTOM_ONLY_RADIUS) || (z > CUSTOM_ONLY_RADIUS-1)) {
		int numSystems = (rng.Int32(4,20) * Galaxy::GetSectorDensity(x, y, z)) >> 8;

		for (int i=0; i<numSystems; i++) {
			System s;
			switch (rng.Int32(15)) {
				case 0:
					s.numStars = 4; break;
				case 1: case 2:
					s.numStars = 3; break;
				case 3: case 4: case 5: case 6:
					s.numStars = 2; break;
				default:
					s.numStars = 1; break;
			}

			s.p.x = rng.Double(SIZE);
			s.p.y = rng.Double(SIZE);
			s.p.z = rng.Double(SIZE);
			s.seed = 0;
			s.customSys = 0;
			
			double spec = rng.Double(1000000.0);
			// frequencies from wikipedia
			/*if (spec < 100) { // should be 1 but that is boring
				s.starType[0] = SBody::TYPE_STAR_O;
			} else if (spec < 1300) {
				s.starType[0] = SBody::TYPE_STAR_B;
			} else if (spec < 7300) {
				s.starType[0] = SBody::TYPE_STAR_A;
			} else if (spec < 37300) {
				s.starType[0] = SBody::TYPE_STAR_F;
			} else if (spec < 113300) {
				s.starType[0] = SBody::TYPE_STAR_G;
			} else if (spec < 234300) {
				s.starType[0] = SBody::TYPE_STAR_K;
			} else if (spec < 250000) {
				s.starType[0] = SBody::TYPE_WHITE_DWARF;
			} else if (spec < 900000) {
				s.starType[0] = SBody::TYPE_STAR_M;
			} else {
				s.starType[0] = SBody::TYPE_BROWN_DWARF;
			}*/
			//if ((sx > 50) || (sx < -50) ||
			//	(sy > 50) || (sy < -50))

			// Frequencies are low enough that we probably don't need this anymore.
			if (isqrt(1+sx*sx+sy*sy) > 10) 
			{
				if (spec < 1) { 
					s.starType[0] = SBody::TYPE_STAR_IM_BH;  // These frequencies are made up
				} else if (spec < 3) {
					s.starType[0] = SBody::TYPE_STAR_S_BH; 
				} else if (spec < 5) {
					s.starType[0] = SBody::TYPE_STAR_O_WF; 
				} else if (spec < 8) {
					s.starType[0] = SBody::TYPE_STAR_B_WF; 
				} else if (spec < 12) {
					s.starType[0] = SBody::TYPE_STAR_M_WF; 
				} else if (spec < 15) {
					s.starType[0] = SBody::TYPE_STAR_K_HYPER_GIANT; 
				} else if (spec < 18) {
					s.starType[0] = SBody::TYPE_STAR_G_HYPER_GIANT;
				} else if (spec < 23) {
					s.starType[0] = SBody::TYPE_STAR_O_HYPER_GIANT; 
				} else if (spec < 28) {
					s.starType[0] = SBody::TYPE_STAR_A_HYPER_GIANT;
				} else if (spec < 33) {
					s.starType[0] = SBody::TYPE_STAR_F_HYPER_GIANT;
				} else if (spec < 41) {
					s.starType[0] = SBody::TYPE_STAR_B_HYPER_GIANT; 
				} else if (spec < 48) {
					s.starType[0] = SBody::TYPE_STAR_M_HYPER_GIANT; 
				} else if (spec < 58) {
					s.starType[0] = SBody::TYPE_STAR_K_SUPER_GIANT; 
				} else if (spec < 68) {
					s.starType[0] = SBody::TYPE_STAR_G_SUPER_GIANT;
				} else if (spec < 78) {
					s.starType[0] = SBody::TYPE_STAR_O_SUPER_GIANT; 
				} else if (spec < 88) {
					s.starType[0] = SBody::TYPE_STAR_A_SUPER_GIANT;
				} else if (spec < 98) {
					s.starType[0] = SBody::TYPE_STAR_F_SUPER_GIANT;
				} else if (spec < 108) {
					s.starType[0] = SBody::TYPE_STAR_B_SUPER_GIANT; 
				} else if (spec < 158) {
					s.starType[0] = SBody::TYPE_STAR_M_SUPER_GIANT; 
				} else if (spec < 208) {
					s.starType[0] = SBody::TYPE_STAR_K_GIANT; 
				} else if (spec < 250) {
					s.starType[0] = SBody::TYPE_STAR_G_GIANT;
				} else if (spec < 300) {
					s.starType[0] = SBody::TYPE_STAR_O_GIANT; 
				} else if (spec < 350) {
					s.starType[0] = SBody::TYPE_STAR_A_GIANT;
				} else if (spec < 400) {
					s.starType[0] = SBody::TYPE_STAR_F_GIANT;
				} else if (spec < 500) {
					s.starType[0] = SBody::TYPE_STAR_B_GIANT; 
				} else if (spec < 700) {
					s.starType[0] = SBody::TYPE_STAR_M_GIANT; 
				} else if (spec < 800) {
					s.starType[0] = SBody::TYPE_STAR_O;  // should be 1 but that is boring
				} else if (spec < 2000) { // spec < 1300 / 20500
					s.starType[0] = SBody::TYPE_STAR_B;  
				} else if (spec < 8000) { // spec < 7300
					s.starType[0] = SBody::TYPE_STAR_A;  
				} else if (spec < 37300) { // spec < 37300
					s.starType[0] = SBody::TYPE_STAR_F;  
				} else if (spec < 113300) { // spec < 113300
					s.starType[0] = SBody::TYPE_STAR_G;  
				} else if (spec < 234300) { // spec < 234300
					s.starType[0] = SBody::TYPE_STAR_K;  
				} else if (spec < 250000) { // spec < 250000
					s.starType[0] = SBody::TYPE_WHITE_DWARF;
				} else if (spec < 900000) {  //spec < 900000
					s.starType[0] = SBody::TYPE_STAR_M;
				} else {
					s.starType[0] = SBody::TYPE_BROWN_DWARF;
				}
			} else {
				if (spec < 100) { // should be 1 but that is boring
					s.starType[0] = SBody::TYPE_STAR_O;
				} else if (spec < 1300) {
					s.starType[0] = SBody::TYPE_STAR_B;
				} else if (spec < 7300) {
					s.starType[0] = SBody::TYPE_STAR_A;
				} else if (spec < 37300) {
					s.starType[0] = SBody::TYPE_STAR_F;
				} else if (spec < 113300) {
					s.starType[0] = SBody::TYPE_STAR_G;
				} else if (spec < 234300) {
					s.starType[0] = SBody::TYPE_STAR_K;
				} else if (spec < 250000) {
					s.starType[0] = SBody::TYPE_WHITE_DWARF;
				} else if (spec < 900000) {
					s.starType[0] = SBody::TYPE_STAR_M;
				} else {
					s.starType[0] = SBody::TYPE_BROWN_DWARF;
				}
			}
			//printf("%d: %d%\n", sx, sy);

			if (s.numStars > 1) {
				s.starType[1] = SBody::BodyType(rng.Int32(SBody::TYPE_STAR_MIN, s.starType[0]));
				if (s.numStars > 2) {
					s.starType[2] = SBody::BodyType(rng.Int32(SBody::TYPE_STAR_MIN, s.starType[0]));
					s.starType[3] = SBody::BodyType(rng.Int32(SBody::TYPE_STAR_MIN, s.starType[2]));
				}
			}

			if ((s.starType[0] <= SBody::TYPE_STAR_A) && (rng.Int32(10)==0)) {
				// make primary a giant. never more than one giant in a system
				// while 
				if (isqrt(1+sx*sx+sy*sy) > 10)
				{			
					if (rand.Int32(0,1000) >= 999) {
						s.starType[0] = SBody::TYPE_STAR_B_HYPER_GIANT;
					} else if (rand.Int32(0,1000) >= 998) {
						s.starType[0] = SBody::TYPE_STAR_O_HYPER_GIANT;
					} else if (rand.Int32(0,1000) >= 997) {
						s.starType[0] = SBody::TYPE_STAR_K_HYPER_GIANT;
					} else if (rand.Int32(0,1000) >= 995) {
						s.starType[0] = SBody::TYPE_STAR_B_SUPER_GIANT;
					} else if (rand.Int32(0,1000) >= 993) {
						s.starType[0] = SBody::TYPE_STAR_O_SUPER_GIANT;
					} else if (rand.Int32(0,1000) >= 990) {
						s.starType[0] = SBody::TYPE_STAR_K_SUPER_GIANT;
					} else if (rand.Int32(0,1000) >= 985) {
						s.starType[0] = SBody::TYPE_STAR_B_GIANT;
					} else if (rand.Int32(0,1000) >= 980) {
						s.starType[0] = SBody::TYPE_STAR_O_GIANT;
					} else if (rand.Int32(0,1000) >= 975) {
						s.starType[0] = SBody::TYPE_STAR_K_GIANT;
					} else if (rand.Int32(0,1000) >= 950) {
						s.starType[0] = SBody::TYPE_STAR_M_HYPER_GIANT;
					} else if (rand.Int32(0,1000) >= 875) {
						s.starType[0] = SBody::TYPE_STAR_M_SUPER_GIANT;
					} else {
						s.starType[0] = SBody::TYPE_STAR_M_GIANT;
					} 
				} else if (isqrt(1+sx*sx+sy*sy) > 5) s.starType[0] = SBody::TYPE_STAR_M_GIANT;
				else s.starType[0] = SBody::TYPE_STAR_M;

				//printf("%d: %d%\n", sx, sy);
			}

			s.name = GenName(s, rng);
			//printf("%s: \n", s.name.c_str());

			m_systems.push_back(s);
		}
	}
Esempio n. 29
0
static void
test_for_replica_exchange(FILE                 *fplog,
                          const gmx_multisim_t *ms,
                          struct gmx_repl_ex   *re,
                          const gmx_enerdata_t *enerd,
                          real                  vol,
                          int64_t               step,
                          real                  time)
{
    int                                  m, i, j, a, b, ap, bp, i0, i1, tmp;
    real                                 delta = 0;
    gmx_bool                             bPrint, bMultiEx;
    gmx_bool                            *bEx      = re->bEx;
    real                                *prob     = re->prob;
    int                                 *pind     = re->destinations; /* permuted index */
    gmx_bool                             bEpot    = FALSE;
    gmx_bool                             bDLambda = FALSE;
    gmx_bool                             bVol     = FALSE;
    gmx::ThreeFry2x64<64>                rng(re->seed, gmx::RandomDomain::ReplicaExchange);
    gmx::UniformRealDistribution<real>   uniformRealDist;
    gmx::UniformIntDistribution<int>     uniformNreplDist(0, re->nrepl-1);

    bMultiEx = (re->nex > 1);  /* multiple exchanges at each state */
    fprintf(fplog, "Replica exchange at step %" PRId64 " time %.5f\n", step, time);

    if (re->bNPT)
    {
        for (i = 0; i < re->nrepl; i++)
        {
            re->Vol[i] = 0;
        }
        bVol               = TRUE;
        re->Vol[re->repl]  = vol;
    }
    if ((re->type == ereTEMP || re->type == ereTL))
    {
        for (i = 0; i < re->nrepl; i++)
        {
            re->Epot[i] = 0;
        }
        bEpot              = TRUE;
        re->Epot[re->repl] = enerd->term[F_EPOT];
        /* temperatures of different states*/
        for (i = 0; i < re->nrepl; i++)
        {
            re->beta[i] = 1.0/(re->q[ereTEMP][i]*BOLTZ);
        }
    }
    else
    {
        for (i = 0; i < re->nrepl; i++)
        {
            re->beta[i] = 1.0/(re->temp*BOLTZ);  /* we have a single temperature */
        }
    }
    if (re->type == ereLAMBDA || re->type == ereTL)
    {
        bDLambda = TRUE;
        /* lambda differences. */
        /* de[i][j] is the energy of the jth simulation in the ith Hamiltonian
           minus the energy of the jth simulation in the jth Hamiltonian */
        for (i = 0; i < re->nrepl; i++)
        {
            for (j = 0; j < re->nrepl; j++)
            {
                re->de[i][j] = 0;
            }
        }
        for (i = 0; i < re->nrepl; i++)
        {
            re->de[i][re->repl] = (enerd->enerpart_lambda[static_cast<int>(re->q[ereLAMBDA][i])+1]-enerd->enerpart_lambda[0]);
        }
    }

    /* now actually do the communication */
    if (bVol)
    {
        gmx_sum_sim(re->nrepl, re->Vol, ms);
    }
    if (bEpot)
    {
        gmx_sum_sim(re->nrepl, re->Epot, ms);
    }
    if (bDLambda)
    {
        for (i = 0; i < re->nrepl; i++)
        {
            gmx_sum_sim(re->nrepl, re->de[i], ms);
        }
    }

    /* make a duplicate set of indices for shuffling */
    for (i = 0; i < re->nrepl; i++)
    {
        pind[i] = re->ind[i];
    }

    rng.restart( step, 0 );

    if (bMultiEx)
    {
        /* multiple random switch exchange */
        int nself = 0;


        for (i = 0; i < re->nex + nself; i++)
        {
            // For now this is superfluous, but just in case we ever add more
            // calls in different branches it is safer to always reset the distribution.
            uniformNreplDist.reset();

            /* randomly select a pair  */
            /* in theory, could reduce this by identifying only which switches had a nonneglibible
               probability of occurring (log p > -100) and only operate on those switches */
            /* find out which state it is from, and what label that state currently has. Likely
               more work that useful. */
            i0 = uniformNreplDist(rng);
            i1 = uniformNreplDist(rng);
            if (i0 == i1)
            {
                nself++;
                continue;  /* self-exchange, back up and do it again */
            }

            a  = re->ind[i0]; /* what are the indices of these states? */
            b  = re->ind[i1];
            ap = pind[i0];
            bp = pind[i1];

            bPrint = FALSE; /* too noisy */
            /* calculate the energy difference */
            /* if the code changes to flip the STATES, rather than the configurations,
               use the commented version of the code */
            /* delta = calc_delta(fplog,bPrint,re,a,b,ap,bp); */
            delta = calc_delta(fplog, bPrint, re, ap, bp, a, b);

            /* we actually only use the first space in the prob and bEx array,
               since there are actually many switches between pairs. */

            if (delta <= 0)
            {
                /* accepted */
                prob[0] = 1;
                bEx[0]  = TRUE;
            }
            else
            {
                if (delta > c_probabilityCutoff)
                {
                    prob[0] = 0;
                }
                else
                {
                    prob[0] = exp(-delta);
                }
                // roll a number to determine if accepted. For now it is superfluous to
                // reset, but just in case we ever add more calls in different branches
                // it is safer to always reset the distribution.
                uniformRealDist.reset();
                bEx[0] = uniformRealDist(rng) < prob[0];
            }
            re->prob_sum[0] += prob[0];

            if (bEx[0])
            {
                /* swap the states */
                tmp      = pind[i0];
                pind[i0] = pind[i1];
                pind[i1] = tmp;
            }
        }
        re->nattempt[0]++;  /* keep track of total permutation trials here */
        print_allswitchind(fplog, re->nrepl, pind, re->allswaps, re->tmpswap);
    }
    else
    {
        /* standard nearest neighbor replica exchange */

        m = (step / re->nst) % 2;
        for (i = 1; i < re->nrepl; i++)
        {
            a = re->ind[i-1];
            b = re->ind[i];

            bPrint = (re->repl == a || re->repl == b);
            if (i % 2 == m)
            {
                delta = calc_delta(fplog, bPrint, re, a, b, a, b);
                if (delta <= 0)
                {
                    /* accepted */
                    prob[i] = 1;
                    bEx[i]  = TRUE;
                }
                else
                {
                    if (delta > c_probabilityCutoff)
                    {
                        prob[i] = 0;
                    }
                    else
                    {
                        prob[i] = exp(-delta);
                    }
                    // roll a number to determine if accepted. For now it is superfluous to
                    // reset, but just in case we ever add more calls in different branches
                    // it is safer to always reset the distribution.
                    uniformRealDist.reset();
                    bEx[i] = uniformRealDist(rng) < prob[i];
                }
                re->prob_sum[i] += prob[i];

                if (bEx[i])
                {
                    /* swap these two */
                    tmp       = pind[i-1];
                    pind[i-1] = pind[i];
                    pind[i]   = tmp;
                    re->nexchange[i]++;  /* statistics for back compatibility */
                }
            }
            else
            {
                prob[i] = -1;
                bEx[i]  = FALSE;
            }
        }
        /* print some statistics */
        print_ind(fplog, "ex", re->nrepl, re->ind, bEx);
        print_prob(fplog, "pr", re->nrepl, prob);
        fprintf(fplog, "\n");
        re->nattempt[m]++;
    }

    /* record which moves were made and accepted */
    for (i = 0; i < re->nrepl; i++)
    {
        re->nmoves[re->ind[i]][pind[i]] += 1;
        re->nmoves[pind[i]][re->ind[i]] += 1;
    }
    fflush(fplog); /* make sure we can see what the last exchange was */
}
Esempio n. 30
0
      void go() override
         {
         std::unique_ptr<Botan::Private_Key> key(Botan::PKCS8::load_key(get_arg("key"), rng(), get_arg("key-pass")));

         if(!key)
            {
            throw CLI_Error("Failed to load key from " + get_arg("key"));
            }

         Botan::X509_Cert_Options opts;

         opts.common_name  = get_arg("CN");
         opts.country      = get_arg("country");
         opts.organization = get_arg("organization");
         opts.email        = get_arg("email");
         opts.set_padding_scheme(get_arg_or("emsa", "EMSA4"));

         Botan::PKCS10_Request req = Botan::X509::create_cert_req(opts, *key, get_arg("hash"), rng());

         output() << req.PEM_encode();
         }