<commit_before>/*

    Copyright <NAME> and <NAME>, 2011, 2012
    
    This file is part of Lasercake.

    Lasercake is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Lasercake is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "specific_object_types.hpp"

#include "data_structures/bbox_collision_detector_iteration.hpp"

namespace /* anonymous */ {

typedef non_normalized_rational<polygon_int_type> rational;
typedef std::pair<bool, rational> bool_and_rational;


struct beam_first_contact_finder {
  beam_first_contact_finder(world const& w, line_segment beam, object_or_tile_identifier ignore):w_(w),beam_(beam) {ignores_.insert(ignore);}
  typedef boost::optional<rational> result_type;
  result_type min_cost(bounding_box const& bbox) const {
    const bool_and_rational result = shape(bbox).first_intersection(beam_);
    return result.first ? result_type(result.second) : result_type();
  }
  result_type cost(object_or_tile_identifier id, world_collision_detector::bounding_box const&) const {
    if(ignores_.find(id) != ignores_.end()) return result_type();
    const bool_and_rational result = w_.get_detail_shape_of_object_or_tile(id).first_intersection(beam_);
    return result.first ? result_type(result.second) : result_type();
  }
private:
  world const& w_;
  line_segment beam_;
  unordered_set<object_or_tile_identifier> ignores_;
};

void fire_standard_laser(world& w, object_identifier my_id, vector3<fine_scalar> location, vector3<fine_scalar> facing) {
  facing = facing * tile_width * 2 / facing.magnitude_within_32_bits();
  const line_segment beam(location, location + facing * 50);
  beam_first_contact_finder finder(w, beam, my_id);
  if(auto hit = w.get_things_exposed_to_collision().find_least(finder)) {
    const object_or_tile_identifier hit_object = hit->object;
    const rational best_intercept_point = hit->cost;
    // TODO do I have to worry about overflow?
    w.add_laser_sfx(location, facing * 50 * best_intercept_point.numerator / best_intercept_point.denominator);
    if(tile_location const* locp = hit_object.get_tile_location()) {
      if (locp->stuff_at().contents() == ROCK) {
        w.replace_substance(*locp, ROCK, RUBBLE);
      }
    }
  }
  else {
    w.add_laser_sfx(location, facing * 50);
  }
}

const int robot_max_carrying_capacity = 4;<commit_msg>re-add overflow protection hack<commit_after>/*

    Copyright <NAME> and <NAME>, 2011, 2012
    
    This file is part of Lasercake.

    Lasercake is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Lasercake is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "specific_object_types.hpp"

#include "data_structures/bbox_collision_detector_iteration.hpp"

namespace /* anonymous */ {

typedef non_normalized_rational<polygon_int_type> rational;
typedef std::pair<bool, rational> bool_and_rational;


struct beam_first_contact_finder {
  beam_first_contact_finder(world const& w, line_segment beam, object_or_tile_identifier ignore):w_(w),beam_(beam) {ignores_.insert(ignore);}
  typedef boost::optional<rational> result_type;
  static const uint64_t too_large = (1ULL << 32) - 1;
  bool bbox_is_too_large(world_collision_detector::bounding_box const& bbox) const {
    return (bbox.size_minus_one(X) >= too_large || bbox.size_minus_one(Y) >= too_large || bbox.size_minus_one(Z) >= too_large);
  }
  result_type min_cost(world_collision_detector::bounding_box const& bbox) const {
    // hack - avoid overflow - don't try to filter out too-large regions
    if(bbox_is_too_large(bbox)) return rational(0);
    const bool_and_rational result = shape(bbox).first_intersection(beam_);
    return result.first ? result_type(result.second) : result_type();
  }
  result_type cost(object_or_tile_identifier id, world_collision_detector::bounding_box const& bbox) const {
    // hack - avoid overflow - effect: incredibly large objects can't be hit by lasers
    if(bbox_is_too_large(bbox)) return result_type();
    if(ignores_.find(id) != ignores_.end()) return result_type();
    const bool_and_rational result = w_.get_detail_shape_of_object_or_tile(id).first_intersection(beam_);
    return result.first ? result_type(result.second) : result_type();
  }
private:
  world const& w_;
  line_segment beam_;
  unordered_set<object_or_tile_identifier> ignores_;
};

void fire_standard_laser(world& w, object_identifier my_id, vector3<fine_scalar> location, vector3<fine_scalar> facing) {
  facing = facing * tile_width * 2 / facing.magnitude_within_32_bits();
  const line_segment beam(location, location + facing * 50);
  beam_first_contact_finder finder(w, beam, my_id);
  if(auto hit = w.get_things_exposed_to_collision().find_least(finder)) {
    const object_or_tile_identifier hit_object = hit->object;
    const rational best_intercept_point = hit->cost;
    // TODO do I have to worry about overflow?
    w.add_laser_sfx(location, facing * 50 * best_intercept_point.numerator / best_intercept_point.denominator);
    if(tile_location const* locp = hit_object.get_tile_location()) {
      if (locp->stuff_at().contents() == ROCK) {
        w.replace_substance(*locp, ROCK, RUBBLE);
      }
    }
  }
  else {
    w.add_laser_sfx(location, facing * 50);
  }
}

const int robot_max_carrying_capacity = 4;
{'fraction_non_alphanumeric': 0.09095253265371138, 'fraction_numerical': 0.007805033450143358, 'mean_word_length': 4.6875, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4998864', 'n_tokens_mistral': 2043, 'n_tokens_neox': 1936, 'n_words': 530}