diff --git a/nullptr/api.py b/nullptr/api.py index 41f124d..4859e8f 100644 --- a/nullptr/api.py +++ b/nullptr/api.py @@ -324,8 +324,8 @@ class Api: 'shipSymbol': dship.symbol } data = self.request('post', f'my/ships/{sship.symbol}/transfer', data) - sship.log(f'transferred {amt} {typ} to {dship}') - dship.log(f'received {amt} {typ} from {sship}') + sship.log(f'tra {amt} {typ} to {dship}') + dship.log(f'rec {amt} {typ} from {sship}', 10) if 'cargo' in data: sship.update(data) dship.put_cargo(typ, amt) diff --git a/nullptr/central_command.py b/nullptr/central_command.py index 285d338..84148d3 100644 --- a/nullptr/central_command.py +++ b/nullptr/central_command.py @@ -6,7 +6,7 @@ from random import choice, randrange from time import sleep from threading import Thread from nullptr.atlas_builder import AtlasBuilder -from nullptr.analyzer import Analyzer +from nullptr.analyzer import Analyzer, Point class CentralCommandError(Exception): pass @@ -112,13 +112,20 @@ class CentralCommand: if s in self.missions: m = self.missions[s] - def find_gas(self, s): - system = s.location.system + def find_gas(self, system): m = [w for w in self.store.all_members(system, 'Waypoint') if w.type == 'GAS_GIANT'] if len(m)==0: raise CentralCommandError('no gas giant found') return m[0] - + + def find_metal(self, system): + m = [w for w in self.store.all_members(system, Waypoint) if 'COMMON_METAL_DEPOSITS' in w.traits] + if len(m) == 0: + return None + origin = Point(0,0) + m = sorted(m, key=lambda w: w.distance(origin)) + return m[0] + def assign_mission(self, s): if s.role == 'trader': self.assign_trade(s) @@ -128,18 +135,34 @@ class CentralCommand: self.assign_siphon(s) elif s.role == 'hauler': self.assign_hauler(s) - + elif s.role == 'surveyor': + self.assign_survey(s) + + def assign_survey(self, s): + if s.crew is None: + raise CentralCommandError('ship has no crew') + w = s.crew.site + self.init_mission(s, 'survey') + self.smipa(s, 'site', w) + + def assign_hauler(self, s): - w = self.find_gas(s) - m = self.analyzer.best_sell_market(s.location.system, 'HYDROCARBON') - resources = list(m.prices.keys()) + if s.crew is None: + raise CentralCommandError('ship has no crew') + w = s.crew.site + resources = s.crew.resources + resource = choice(resources) + m = self.analyzer.best_sell_market(s.location.system, resource) + s.log(f'assigning haul mission from {w} to {m}') self.init_mission(s, 'haul') self.smipa(s, 'site', w) self.smipa(s, 'dest', m) self.smipa(s, 'resources', resources) def assign_siphon(self, s): - w = self.find_gas(s) + if s.crew is None: + raise CentralCommandError('ship has no crew') + w = s.crew.site self.init_mission(s, 'siphon') self.smipa(s, 'site', w) @@ -149,7 +172,7 @@ class CentralCommand: m = self.analyzer.solve_tsp(m) hops = [w.symbol for w in m] start_hop = randrange(0, len(hops)) - print(f'Assigning {s} to probe {len(hops)} starting at {hops[start_hop]}') + s.log(f'Assigning {s} to probe {len(hops)} starting at {hops[start_hop]}') self.init_mission(s, 'probe') self.smipa(s, 'hops', hops) self.smipa(s, 'next-hop', start_hop) @@ -161,7 +184,7 @@ class CentralCommand: self.init_mission(s,'idle') self.smipa(s, 'seconds', 600) return - print(f'assigning {s} to deliver {t.resource} from {t.source} to {t.dest} at a margin of {t.margin}') + s.log(f'assigning {s} to deliver {t.resource} from {t.source} to {t.dest} at a margin of {t.margin}') self.init_mission(s, 'trade') self.smipa(s, 'site', t.source) self.smipa(s, 'dest', t.dest) @@ -196,3 +219,18 @@ class CentralCommand: def stop_mission(self, s): if s in self.missions: del self.missions[s] + + def create_default_crews(self): + system = self.api.agent.headquarters.system + gas_w = self.find_gas(system) + metal_w = self.find_metal(system) + metal = self.store.get('Crew', 'METAL', create=True) + metal.site = metal_w + metal.resources = ['COPPER_ORE','IRON_ORE'] + gas = self.store.get('Crew', 'GAS', create=True) + gas.site = gas_w + gas.resources = ['HYDROCARBON','LIQUID_HYDROGEN','LIQUID_NITROGEN'] + return [gas, metal] + + + \ No newline at end of file diff --git a/nullptr/commander.py b/nullptr/commander.py index ea38cf5..3e1e993 100644 --- a/nullptr/commander.py +++ b/nullptr/commander.py @@ -56,8 +56,8 @@ class Commander(CommandLine): self.centcom.run_interactive() def do_log(self, level): - if not self.has_ship(): return - self.ship._log_level = int(level) + ship = self.has_ship() + ship._log_level = int(level) ######## Resolvers ######### def ask_obj(self, typ, prompt): @@ -71,9 +71,9 @@ class Commander(CommandLine): def has_ship(self): if self.ship is not None: - return True + return self.ship else: - print('set a ship') + raise CommandError('set a ship') def select_agent(self): agents = self.store.all(Agent) @@ -96,8 +96,8 @@ class Commander(CommandLine): if type(system_str) == System: return system_str if system_str == '': - if not self.has_ship(): return - system = self.ship.location.system + ship = self.has_ship() + system = ship.location.system else: system = self.store.get(System, system_str) return system @@ -106,12 +106,12 @@ class Commander(CommandLine): if type(w) == Waypoint: return w if w == '': - if not self.has_ship(): return - return self.ship.location + ship = self.has_ship() + return ship.location p = w.split('-') if len(p) == 1: - if not self.has_ship(): return - s = self.ship.location.system + ship = self.has_ship() + s = ship.location.system w = f'{s}-{w}' r = self.store.get(Waypoint, w) if r is None: @@ -203,8 +203,8 @@ class Commander(CommandLine): def do_waypoints(self, system_str=''): loc = None if system_str == '': - if not self.has_ship(): return - loc = self.ship.location + ship = self.has_ship() + loc = ship.location system = loc.system else: system = self.store.get(System, system_str) @@ -224,8 +224,8 @@ class Commander(CommandLine): print(f'{wname:4} {typ} {traits}') def do_members(self): - if not self.has_ship(): return - system = self.ship.location.system + ship = self.has_ship() + system = ship.location.system pprint(list(self.store.all_members(system))) def do_wp(self, s=''): @@ -245,8 +245,8 @@ class Commander(CommandLine): def do_jumps(self, waypoint_str=None): if waypoint_str is None: - if not self.has_ship(): return - waypoint = self.ship.location + ship = self.has_ship() + waypoint = ship.location else: waypoint = self.store.get(Waypoint, waypoint_str.upper()) r = self.api.jumps(waypoint) @@ -266,49 +266,49 @@ class Commander(CommandLine): ######## Commerce ######### def do_refuel(self, source='market'): - if not self.has_ship(): return + ship = self.has_ship() from_cargo = source != 'market' - r = self.api.refuel(self.ship, from_cargo=from_cargo) + r = self.api.refuel(ship, from_cargo=from_cargo) pprint(r) def do_cargo(self): - if not self.has_ship(): return - print(f'== Cargo {self.ship.cargo_units}/{self.ship.cargo_capacity} ==') - for c, units in self.ship.cargo.items(): + ship = self.has_ship() + print(f'== Cargo {ship.cargo_units}/{ship.cargo_capacity} ==') + for c, units in ship.cargo.items(): print(f'{units:4d} {c}') def do_buy(self, resource, amt=None): - if not self.has_ship(): return + ship = self.has_ship() if amt is None: - amt = self.ship.cargo_capacity - self.ship.cargo_units - self.api.buy(self.ship, resource.upper(), amt) + amt = ship.cargo_capacity - ship.cargo_units + self.api.buy(ship, resource.upper(), amt) self.do_cargo() def do_sell(self, resource, amt=None): - if not self.has_ship(): return - self.api.sell(self.ship, resource.upper(), amt) + ship = self.has_ship() + self.api.sell(ship, resource.upper(), amt) self.do_cargo() def do_dump(self, resource): - if not self.has_ship(): return - self.api.jettison(self.ship, resource.upper()) + ship = self.has_ship() + self.api.jettison(ship, resource.upper()) self.do_cargo() def do_transfer(self, resource, dship, amount=None): - if not self.has_ship(): return + ship = self.has_ship() resource = resource.upper() - avail = self.ship.get_cargo(resource) + avail = ship.get_cargo(resource) if amount is None: amount = avail amount = int(amount) if avail < amount: raise CommandError('resource not in cargo') dship = self.resolve_ship(dship) - self.api.transfer(self.ship, dship, resource, amount) + self.api.transfer(ship, dship, resource, amount) def do_purchase(self, ship_type): - if not self.has_ship(): return - location = self.ship.location + ship = self.has_ship() + location = ship.location ship_type = ship_type.upper() if not ship_type.startswith('SHIP'): ship_type = 'SHIP_' + ship_type @@ -317,23 +317,23 @@ class Commander(CommandLine): ######## Mining ######### def do_siphon(self): - if not self.has_ship(): return - data = self.api.siphon(self.ship) + ship = self.has_ship() + data = self.api.siphon(ship) def do_survey(self): - if not self.has_ship(): return - r = self.api.survey(self.ship) + ship = self.has_ship() + r = self.api.survey(ship) pprint(r) def do_surveys(self): pprint(list(self.store.all('Survey'))) def do_extract(self, survey_str=''): - if not self.has_ship(): return + ship = self.has_ship() survey = None if survey_str != '': survey = self.resolve('Survey', survey_str) - result = self.api.extract(self.ship, survey) + result = self.api.extract(ship, survey) symbol = mg(result,'extraction.yield.symbol') units = mg(result,'extraction.yield.units') @@ -346,39 +346,51 @@ class Commander(CommandLine): pprint(self.ship.mission_state) def do_role(self, role): - roles = [None, 'trader', 'probe', 'siphon', 'hauler'] - if not self.has_ship(): return + roles = [None, 'trader', 'probe', 'siphon', 'hauler', 'surveyor', 'miner'] + ship = self.has_ship() if role == 'none': role = None if role not in roles: print(f'role {role} not found. Choose from {roles}') return - self.ship.role = role + ship.role = role def do_mission(self, arg=''): - if not self.has_ship(): return + ship = self.has_ship() if arg: - self.centcom.init_mission(self.ship, arg) + self.centcom.init_mission(ship, arg) self.print_mission() def do_mrestart(self, status='init'): - if not self.has_ship(): return - self.centcom.restart_mission(self.ship, status) + ship = self.has_ship() + self.centcom.restart_mission(ship, status) self.print_mission() def do_mstep(self): - if not self.has_ship(): return - self.centcom.single_step(self.ship) + ship = self.has_ship() + self.centcom.single_step(ship) self.print_mission() def do_mreset(self): - if not self.has_ship(): return - self.ship.mission_state = {} + ship = self.has_ship() + ship.mission_state = {} def do_mset(self, nm, val): - if not self.has_ship(): return - self.centcom.set_mission_param(self.ship, nm, val) + ship = self.has_ship() + self.centcom.set_mission_param(ship, nm, val) + def do_crew(self, arg): + ship = self.has_ship() + crew = self.resolve('Crew', arg) + ship.crew = crew + pprint(ship) + + ######## Crews ######### + def do_create_crews(self): + crews = self.centcom.create_default_crews() + for c in crews: + print(f'{c.symbol:15s} {c.site}') + ######## Contracts ######### def active_contract(self): for c in self.store.all('Contract'): @@ -393,8 +405,8 @@ class Commander(CommandLine): pprint(r) def do_negotiate(self): - if not self.has_ship(): return - r = self.api.negotiate(self.ship) + ship = self.has_ship() + r = self.api.negotiate(ship) pprint(r) def do_accept(self, c): @@ -403,118 +415,59 @@ class Commander(CommandLine): pprint(r) def do_deliver(self): - if not self.has_ship(): return - site = self.ship.location + ship = self.has_ship() + site = ship.location contract = self.active_contract() delivery = contract.unfinished_delivery() if delivery is None: raise CommandError('no delivery') resource = delivery['trade_symbol'] - self.api.deliver(self.ship, resource, contract) + self.api.deliver(ship, resource, contract) pprint(contract) def do_fulfill(self): contract = self.active_contract() self.api.fulfill(contract) - ######## Automissions ######### - def do_cmine(self): - if not self.has_ship(): return - site = self.ship.location - contract = self.active_contract() - delivery = contract.unfinished_delivery() - if delivery is None: - raise CommandError('no delivery') - resource = delivery['trade_symbol'] - destination = delivery['destination'] - self.centcom.init_mission(self.ship, 'mine') - self.centcom.set_mission_param(self.ship, 'site', site) - self.centcom.set_mission_param(self.ship, 'resource', resource) - self.centcom.set_mission_param(self.ship, 'dest', destination) - self.centcom.set_mission_param(self.ship, 'contract', contract) - self.print_mission() - - def do_chaul(self): - if not self.has_ship(): return - if len(self.ship.cargo) > 0: - raise CommandError('please dump cargo first') - contract = self.active_contract() - delivery = contract.unfinished_delivery() - if delivery is None: - raise CommandError('no delivery') - resource = delivery['trade_symbol'] - destination = delivery['destination'] - m = self.analyzer.find_closest_markets(resource, 'buy', destination) - if len(m) == 0: - m = self.analyzer.find_closest_markets(resource, 'exchange', destination) - if len(m) == 0: - print('no market found') - return - _, m, _, _ = m[0] - site = self.store.get(Waypoint, m.symbol) - self.centcom.init_mission(self.ship, 'trade') - self.centcom.set_mission_param(self.ship, 'site', site) - self.centcom.set_mission_param(self.ship, 'resource', resource) - self.centcom.set_mission_param(self.ship, 'dest', destination) - self.centcom.set_mission_param(self.ship, 'contract', contract) - self.print_mission() - - def do_cprobe(self): - if not self.has_ship(): return - contract = self.active_contract() - delivery = contract.unfinished_delivery() - if delivery is None: - raise CommandError('no delivery') - resource = delivery['trade_symbol'] - destination = delivery['destination'] - m = self.analyzer.find_closest_markets(resource, 'buy,exchange', destination) - if len(m) == 0: - print('no market found') - return - markets = [ mkt[1] for mkt in m] - markets = self.analyzer.solve_tsp(markets) - self.centcom.init_mission(self.ship, 'probe') - self.centcom.set_mission_param(self.ship, 'hops', markets) - self.print_mission() - ######## Travel ######### def do_travel(self, dest): + ship = self.has_ship() dest = self.resolve('Waypoint', dest) - self.centcom.init_mission(self.ship, 'travel') - self.centcom.set_mission_param(self.ship, 'dest', dest) + self.centcom.init_mission(ship, 'travel') + self.centcom.set_mission_param(ship, 'dest', dest) self.print_mission() def do_go(self, arg): - if not self.has_ship(): return - system = self.ship.location.system + ship = self.has_ship() + system = ship.location.system symbol = f'{system}-{arg}' dest = self.resolve('Waypoint', symbol) - self.api.navigate(self.ship, dest) - pprint(self.ship) + self.api.navigate(ship, dest) + pprint(ship) def do_dock(self): - if not self.has_ship(): return - self.api.dock(self.ship) - pprint(self.ship) + ship = self.has_ship() + self.api.dock(ship) + pprint(ship) def do_orbit(self): - if not self.has_ship(): return - self.api.orbit(self.ship) - pprint(self.ship) + ship = self.has_ship() + self.api.orbit(ship) + pprint(ship) def do_speed(self, speed): - if not self.has_ship(): return + ship = self.has_ship() speed = speed.upper() speeds = ['DRIFT', 'STEALTH','CRUISE','BURN'] if speed not in speeds: print('please choose from:', speeds) - self.api.flight_mode(self.ship, speed) + self.api.flight_mode(ship, speed) def do_jump(self, waypoint_str): - if not self.has_ship(): return + ship = self.has_ship() w = self.resolve('Waypoint', waypoint_str) - self.api.jump(self.ship, w) - pprint(self.ship) + self.api.jump(ship, w) + pprint(ship) ######## Analysis ######### def do_server(self): @@ -563,8 +516,8 @@ class Commander(CommandLine): print('Dirty: ', obj in self.store.dirty_objects) def do_query(self, resource): - if not self.has_ship(): return - location = self.ship.location + ship = self.has_ship() + location = ship.location resource = resource.upper() print('Found markets:') for typ, m, d, plen in self.analyzer.find_closest_markets(resource, 'buy,exchange',location): @@ -574,14 +527,14 @@ class Commander(CommandLine): print(m, typ[0], f'{plen-1:3} hops {price}') def do_findtrade(self): - if not self.has_ship(): return - system = self.ship.location.system + ship = self.has_ship() + system = ship.location.system t = self.analyzer.find_trade(system) pprint(t) def do_prices(self, resource=None): - if not self.has_ship(): return - system = self.ship.location.system + ship = self.has_ship() + system = ship.location.system prices = self.analyzer.prices(system) if resource is not None: prices = {resource: prices[resource.upper()]} @@ -592,7 +545,7 @@ class Commander(CommandLine): print(f"{m['wp'].symbol:12s} {m['category']} {m['volume']:5d} {m['buy']:5d} {m['sell']:5d}") def do_path(self, waypoint_str): - if not self.has_ship(): return + ship = self.has_ship() w = self.resolve('Waypoint', waypoint_str) - p = self.analyzer.find_nav_path(self.ship.location, w, self.ship.fuel_capacity) + p = self.analyzer.find_nav_path(ship.location, w, ship.fuel_capacity) pprint(p) diff --git a/nullptr/missions/base.py b/nullptr/missions/base.py index 0d82e74..aab52c2 100644 --- a/nullptr/missions/base.py +++ b/nullptr/missions/base.py @@ -111,7 +111,7 @@ class Mission: } def step_done(self): - self.ship.log(f'mission finished with balance {self.balance()}', 3) + self.ship.log(f'mission {type(self).__name__} finished with balance {self.balance()}', 3) def is_waiting(self): if self.next_step > time() or self.ship.cooldown > time() or self.ship.arrival > time(): diff --git a/nullptr/missions/mine.py b/nullptr/missions/mine.py index 6ebcce9..e41e1cc 100644 --- a/nullptr/missions/mine.py +++ b/nullptr/missions/mine.py @@ -9,39 +9,23 @@ class MiningMission(BaseMission): def params(cls): return { 'site': MissionParam(Waypoint, True), - 'resource': MissionParam(str, True), - 'dest': MissionParam(Waypoint, True), - 'delivery': MissionParam(str, True, 'deliver'), - 'contract': MissionParam(Contract, False) + 'resources': MissionParam(list, True) } - + p def start_state(self): return 'travel-to' def steps(self): return { - **self.travel_steps('to', 'site', 'orbit1'), - 'orbit1': (self.step_orbit, 'extract'), - 'extract': (self.step_extract, { - 'done': 'dock', - 'more': 'extract' - }), - 'dock': (self.step_dock, 'sell'), - 'sell': (self.step_sell, { - 'more': 'sell', - 'done': 'orbit2', - }), - 'orbit2': (self.step_orbit, 'jettison'), - 'jettison': (self.step_dispose, { - 'more': 'jettison', - 'done': 'extract', - 'full': 'travel-back' - }), - **self.travel_steps('back', 'dest', 'unload'), - 'unload': (self.step_unload, { - 'done': 'travel-to', - 'more': 'unload' - }), + **self.travel_steps('to', 'site', 'extract'), + 'extract': (self.step_extract, { + 'more': 'extract', + 'full': 'unload' + }), + 'unload': (self.step_unload, { + 'more': 'unload', + 'done': 'done' + }) } def get_survey(self): diff --git a/nullptr/missions/siphon.py b/nullptr/missions/siphon.py index b587af2..3587517 100644 --- a/nullptr/missions/siphon.py +++ b/nullptr/missions/siphon.py @@ -41,7 +41,8 @@ class SiphonMission(BaseMission): else: space = h.cargo_space() amt = min(space, amt) - self.api.transfer(self.ship, h, r, amt) + if amt > 0: + self.api.transfer(self.ship, h, r, amt) return 'more' def steps(self): diff --git a/nullptr/missions/survey.py b/nullptr/missions/survey.py index 2a41458..98b74b4 100644 --- a/nullptr/missions/survey.py +++ b/nullptr/missions/survey.py @@ -1,11 +1,19 @@ from nullptr.missions.base import BaseMission, MissionParam +from nullptr.models.waypoint import Waypoint class SurveyMission(BaseMission): def start_state(self): - return 'survey' + return 'travel-to' + @classmethod + def params(cls): + return { + 'site': MissionParam(Waypoint, True), + } + def steps(self): return { + **self.travel_steps('to', 'site', 'survey'), 'survey': (self.step_survey, 'survey') } diff --git a/nullptr/models/__init__.py b/nullptr/models/__init__.py index d768312..dc62957 100644 --- a/nullptr/models/__init__.py +++ b/nullptr/models/__init__.py @@ -9,5 +9,6 @@ from nullptr.models.ship import Ship from nullptr.models.contract import Contract from nullptr.models.survey import Survey from nullptr.models.atlas import Atlas +from nullptr.models.crew import Crew -__all__ = [ 'Waypoint', 'Sector', 'Ship', 'Survey', 'System', 'Agent', 'Marketplace', 'Jumpgate', 'Contract', 'Base', 'Atlas' ] +__all__ = [ 'Waypoint', 'Sector', 'Ship', 'Survey', 'System', 'Agent', 'Marketplace', 'Jumpgate', 'Contract', 'Base', 'Atlas', 'Crew' ] diff --git a/nullptr/models/agent.py b/nullptr/models/agent.py index 63dec10..e0e6636 100644 --- a/nullptr/models/agent.py +++ b/nullptr/models/agent.py @@ -1,12 +1,16 @@ from .base import Base +from nullptr.models.waypoint import Waypoint class Agent(Base): def define(self): self.token: str = None self.credits: int = 0 - + self.headquarters: Waypoint = None + def update(self, d): self.seta('credits', d) + getter = self.store.getter(Waypoint, create=True) + self.seta('headquarters', d, interp=getter) @classmethod def ext(self): diff --git a/nullptr/models/crew.py b/nullptr/models/crew.py new file mode 100644 index 0000000..05df918 --- /dev/null +++ b/nullptr/models/crew.py @@ -0,0 +1,16 @@ +from .base import Base + +class Crew(Base): + @classmethod + def ext(self): + return 'crw' + + def define(self): + self.site = None + self.resources = [] + + def f(self, detail=1): + r = super().f(detail) + if detail >2: + r += f'\nSite: {self.site}' + return r diff --git a/nullptr/models/ship.py b/nullptr/models/ship.py index 1fdf2c6..a7fafb9 100644 --- a/nullptr/models/ship.py +++ b/nullptr/models/ship.py @@ -19,6 +19,7 @@ class Ship(Base): self.mission:str = None self.mission_status:str = 'init' self.role = None + self.crew = None self.frame = '' self.speed = "CRUISE" self._log_file = None @@ -29,11 +30,12 @@ class Ship(Base): fn = os.path.join(self.store.data_dir, f'{self.symbol}.{self.ext()}.log') self._log_file = open(fn, 'a') ts = strftime('%Y%m%d %H%M%S') + sts = strftime('%H%M%S') m = m.strip() self._log_file.write(f'{ts} {m}\n') self._log_file.flush() if l <= self._log_level: - print(f'{self} {ts} {m}') + print(f'{self} {sts} {m}') @classmethod def ext(self): @@ -139,6 +141,9 @@ class Ship(Base): role = self.role if role is None: role = 'none' + crew = 'none' + if self.crew is not None: + crew = self.crew.symbol mstatus = self.mission_status if mstatus == 'error': mstatus = mstatus.upper() @@ -160,7 +165,7 @@ class Ship(Base): r += f' [C: {cooldown}]' else: r = f'== {self.symbol} {self.frame} ==\n' - r += f'Role: {role}\n' + r += f'Role: {crew} / {role}\n' r += f'Mission: {self.mission} ({mstatus})\n' for k, v in self.mission_state.items(): if type(v) == list: diff --git a/nullptr/models/waypoint.py b/nullptr/models/waypoint.py index 5b3ef0f..169b7ac 100644 --- a/nullptr/models/waypoint.py +++ b/nullptr/models/waypoint.py @@ -47,15 +47,15 @@ class Waypoint(Base): traits.append('MARKET') - if self.type == 'ASTEROID': - if 'COMMON_METAL_DEPOSITS' in self.traits: - traits.append('METAL') - if 'PRECIOUS_METAL_DEPOSITS' in self.traits: - traits.append('GOLD') - if 'MINERAL_DEPOSITS' in self.traits: - traits.append('MINS') - if 'STRIPPED' in self.traits: - traits.append('STRIPPED') + + if 'COMMON_METAL_DEPOSITS' in self.traits: + traits.append('METAL') + if 'PRECIOUS_METAL_DEPOSITS' in self.traits: + traits.append('GOLD') + if 'MINERAL_DEPOSITS' in self.traits: + traits.append('MINS') + if 'STRIPPED' in self.traits: + traits.append('STRIPPED') return traits def f(self, detail=1):