Created
September 13, 2011 20:03
-
-
Save arturaz/1214959 to your computer and use it in GitHub Desktop.
Ruby side
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| lambda do | |
| jar_path = File.join(ROOT_DIR, 'vendor', 'SpaceMule', 'dist', 'SpaceMule.jar') | |
| # Win32 requires us to manually require all the jars before requiring | |
| # main jar. | |
| Dir[File.dirname(jar_path) + "/lib/*.jar"].each { |jar| require jar } | |
| require jar_path | |
| # Scala <-> Ruby interoperability. | |
| class Object | |
| def to_scala | |
| case self | |
| when Hash | |
| scala_hash = Java::scala.collection.immutable.HashMap.new | |
| each do |key, value| | |
| scala_hash = scala_hash.updated(key.to_scala, value.to_scala) | |
| end | |
| scala_hash | |
| when Set | |
| scala_set = Java::scala.collection.immutable.HashSet.new | |
| each { |item| scala_set = scala_set.send(:"$plus", item.to_scala) } | |
| scala_set | |
| when Array | |
| scala_array = Java::scala.collection.mutable.ArrayBuffer.new | |
| each { |value| scala_array.send(:"$plus$eq", value.to_scala) } | |
| scala_array.to_indexed_seq | |
| when Symbol | |
| to_s | |
| else | |
| self | |
| end | |
| end | |
| def from_scala | |
| case self | |
| when Java::scala.collection.Map, Java::scala.collection.immutable.Map, | |
| Java::scala.collection.mutable.Map | |
| ruby_hash = {} | |
| foreach { |tuple| ruby_hash[tuple._1.from_scala] = tuple._2.from_scala } | |
| ruby_hash | |
| when Java::scala.collection.Set, Java::scala.collection.immutable.Set, | |
| Java::scala.collection.mutable.Set | |
| ruby_set = Set.new | |
| foreach { |item| ruby_set.add item.from_scala } | |
| ruby_set | |
| when Java::scala.collection.Seq | |
| ruby_array = [] | |
| foreach { |item| ruby_array.push item.from_scala } | |
| ruby_array | |
| else | |
| self | |
| end | |
| end | |
| end | |
| module Kernel | |
| def Some(value); Java::scala.Some.new(value); end | |
| None = Java::scala.None | |
| end | |
| end.call | |
| # Heavy work mule written in Scala. | |
| class SpaceMule | |
| include Singleton | |
| # Scala constants | |
| SmModules = Java::spacemule.modules | |
| Pmg = SmModules.pmg | |
| Coords = Pmg.classes.geom.Coords | |
| Pf = SmModules.pathfinder | |
| PfO = Pf.objects | |
| # Finds traveling path from _source_ to _target_ and returns path. | |
| # | |
| # _source_ is object that responds to Location#route_attrs. | |
| # _target_ is object that responds to Location#route_attrs. | |
| # _through_ is +SsObject::Jumpgate+. | |
| # _avoid_npc_ is +Boolean+ if we should try to avoid NPC units in | |
| # solar systems. | |
| # | |
| # Returns Array of PmO.ServerLocation: | |
| # id: Int, | |
| # kind: Location.Kind, | |
| # coords: Option[Coords], | |
| # timeMultiplier: Double | |
| # | |
| def find_path(source, target, avoid_npc=true) | |
| avoidable_points = [] | |
| source_solar_system = source.solar_system | |
| sm_source_solar_system = None | |
| if source_solar_system | |
| sm_source_solar_system = to_pf_solar_system(source_solar_system) | |
| if avoid_npc | |
| avoidable_points += source_solar_system.npc_unit_locations.map do | |
| |solar_system_point| | |
| PfO.SolarSystemPoint.new( | |
| sm_source_solar_system, | |
| Coords.new(solar_system_point.x, solar_system_point.y) | |
| ) | |
| end | |
| end | |
| end | |
| target_solar_system = target.solar_system | |
| sm_target_solar_system = None | |
| if target_solar_system | |
| sm_target_solar_system = to_pf_solar_system(target_solar_system) | |
| if avoid_npc && source_solar_system != target_solar_system | |
| avoidable_points += target_solar_system.npc_unit_locations.map do | |
| |solar_system_point| | |
| PfO.SolarSystemPoint.new( | |
| sm_target_solar_system, | |
| Coords.new(solar_system_point.x, solar_system_point.y) | |
| ) | |
| end | |
| end | |
| end | |
| # Add avoidable points if we have something to avoid. | |
| sm_avoidable_points = avoidable_points.blank? \ | |
| ? None : Some(avoidable_points.to_scala) | |
| sm_source_jumpgates = Set.new.to_scala | |
| sm_target_jumpgates = Set.new.to_scala | |
| sm_source_ss_galaxy_coords = None | |
| sm_target_ss_galaxy_coords = None | |
| if source_solar_system && target.is_a?(GalaxyPoint) | |
| # SS -> Galaxy hop, only source JGs needed. | |
| sm_source_jumpgates = jumpgates_for(sm_source_solar_system) | |
| sm_source_ss_galaxy_coords = | |
| Some(jump_coords(target.id, target, source_solar_system)) | |
| elsif source.is_a?(GalaxyPoint) && target_solar_system | |
| # Galaxy -> SS hop, only target JGs needed | |
| sm_target_jumpgates = jumpgates_for(sm_target_solar_system) | |
| sm_target_ss_galaxy_coords = | |
| Some(jump_coords(source.id, source, target_solar_system)) | |
| elsif source_solar_system && target_solar_system && ( | |
| source_solar_system.id != target_solar_system.id | |
| ) | |
| # Different SS -> SS hop, we need all jumpgates | |
| sm_source_jumpgates = jumpgates_for(sm_source_solar_system) | |
| sm_target_jumpgates = jumpgates_for(sm_target_solar_system) | |
| sm_source_ss_galaxy_coords = Some(jump_coords( | |
| target_solar_system.galaxy_id, target_solar_system, | |
| source_solar_system | |
| )) | |
| sm_target_ss_galaxy_coords = Some(jump_coords( | |
| source_solar_system.galaxy_id, source_solar_system, | |
| target_solar_system | |
| )) | |
| else | |
| # No jumpgates needed. | |
| end | |
| sm_source = to_pf_locatable(source, sm_source_solar_system) | |
| sm_target = to_pf_locatable(target, sm_target_solar_system) | |
| PfO.Finder.find( | |
| sm_source, sm_source_jumpgates, sm_source_solar_system, | |
| sm_source_ss_galaxy_coords, | |
| sm_target, sm_target_jumpgates, sm_target_solar_system, | |
| sm_target_ss_galaxy_coords, | |
| sm_avoidable_points | |
| ).from_scala | |
| end | |
| protected | |
| # Converts Ruby +SolarSystem+ to SpaceMule +SolarSystem+ used in pathfinder. | |
| def to_pf_solar_system(solar_system) | |
| PfO.SolarSystem.new( | |
| solar_system.id, | |
| solar_system.x.nil? || solar_system.y.nil? \ | |
| ? None \ | |
| : Some(Coords.new(solar_system.x, solar_system.y)), | |
| solar_system.galaxy_id | |
| ) | |
| end | |
| # Converts Ruby +Location+ to SpaceMule pathfinders +Locatable+. | |
| # _sm_solar_system_ is used if _location_ is in solar system. | |
| def to_pf_locatable(location, sm_solar_system) | |
| coords = Coords.new(location.x, location.y) | |
| case location | |
| when GalaxyPoint | |
| PfO.GalaxyPoint.new(location.id, coords, 1.0) | |
| when SolarSystemPoint | |
| PfO.SolarSystemPoint.new(sm_solar_system, coords) | |
| when SsObject | |
| PfO.Planet.new(location.id, sm_solar_system, coords) | |
| else | |
| raise ArgumentError.new( | |
| "Cannot convert #{location.inspect} to pathfinder Locatable!" | |
| ) | |
| end | |
| end | |
| # Checks if _solar_system_ is a battleground. If so - links entry/exit | |
| # point to closest wormhole in the galaxy. | |
| # | |
| # Otherwise travels as expected. | |
| def jump_coords(galaxy_id, wormhole_proximity_point, solar_system) | |
| if solar_system.main_battleground? | |
| wormhole = Galaxy.closest_wormhole(galaxy_id, | |
| wormhole_proximity_point.x, wormhole_proximity_point.y) | |
| Coords.new(wormhole.x, wormhole.y) | |
| else | |
| Coords.new(solar_system.x, solar_system.y) | |
| end | |
| end | |
| # Given PmO.SolarSystem returns Set of +PmO.SolarSystemPoint+s. | |
| def jumpgates_for(sm_solar_system) | |
| points = SsObject::Jumpgate.where(:solar_system_id => sm_solar_system.id). | |
| all.map do |jumpgate| | |
| PfO.SolarSystemPoint.new( | |
| sm_solar_system, | |
| Coords.new(jumpgate.x, jumpgate.y) | |
| ) | |
| end | |
| Set.new(points).to_scala | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment