# Fill out the information between the lines #---------------------------------------------------------------------------------------- # prices at which your buildings will buy externally produced commodities imports = {'food':250, 'water':220, 'energy':110, 'exotic matter':500, 'nebula gas':150, 'animal embryos':50} # prices at which excess production will be sold by your buildings, if commodity isn't listed here, any excess is assumed to be dumped into space exports = {'drugs':15000, 'droid modules':8000} # Specify end building type/number. Generally you can't have equal profits in a sector that # mixes two different industries. Specify one building type to get equal profit for all # buildings in the industry. If you specify several end-level building types, you'll get equal # profit for supporting buildings, but unequal profits for end-level buildings. end_buildings = {'droid ass complex':1, 'battleweapon factory':1, 'weapon factory':1} # level of your buildings level = 6 # per-ton profit for traders doing upkeep (only for internally produced resources) upkeep_profit = 150 # specifies how profit is divided between buildings 1/1/1/2 means illegal buildings get twice # as much profit as all others low_level_building_share = 1. mid_level_building_share = 1. high_level_building_share = 1. illegal_building_share = 1 # -------------------------------------------------------------------------------------- from math import ceil import sys # initialize upkeep/production data # building names building_names = 'fuel collector','gas collector','space farm','energy well','chemical lab','asteroid mine','radiation collector','medical lab','brewerie','plastic facility','smelting facility','slave camp','optics research center','electronics facility','recycletron','clod generator','nebula plant','drug station','dark dome','weapon factory','battleweapon factory','robot factory','droid ass complex','leech nursery','military outpost','trade outpost' low_level_buildings = ['fuel collector','gas collector','space farm','energy well','chemical lab','asteroid mine','radiation collector','nebula plant'] mid_level_buildings = ['medical lab','brewerie','plastic facility','smelting facility','optics research center','electronics facility','recycletron','clod generator'] high_level_buildings = ['weapon factory','battleweapon factory','robot factory','droid ass complex','leech nursery'] illegal_buildings = ['slave camp','drug station','dark dome'] # initialize profit factors profit_factors = {} for b in building_names: if b in low_level_buildings: profit_factors[b] = low_level_building_share elif b in mid_level_buildings: profit_factors[b] = mid_level_building_share elif b in high_level_buildings: profit_factors[b] = high_level_building_share elif b in illegal_buildings: profit_factors[b] = illegal_building_share commodity_names = 'food','energy','water','animal embryos','ore','metal','electronics','robots','heavy plastics','weapons','medicines','nebula gas','chemical supplies','gem stones','optical components','liqour','hydrogen fuel','exotic matter','radioactive cells','droid modules','bio waste','slaves','drugs','nutrient clods','battleweapon parts','leech baby','body parts' # increased profit for these buildings, because of additional factors (reputation loss, high construction cost, XP requirements) # increased profit for trading with these commodities, ie dangerous route, or infrequent runs trading_factors = {'exotic matter':2} upkeep_s = """ ,Food,,2,,1,1,1,1,2,2,2,2,3,1,1,,,2,3,,1,1,2,1,2,,,125,,,,100,150 ,Energy,4,2,4,,3,1,3,2,2,2,2,1,3,4,3,4,,1,1,2,2,2,3,6,5,,,375,,375,125,250 ,Water,,2,,1,1,1,1,2,2,2,2,3,1,1,,,2,3,,1,1,2,1,10,,,93.75,,125,,,100 ,Animal Embryos,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,Ore,,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,, ,Metal,,,,,,,,,,,,,,3,,,,,,,3,1,,,,,,,,,, ,Electronics,,,,,,,,,,,,,,,,,,,,3,3,4,,,,,,,,,, ,Robots,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,, ,Heavy Plastics,,,,,,,,,,,,,,2,,,,,,3,,,,,,,,,,,, ,Weapons,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,Medicines,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,, ,Nebula Gas,,,,,,,,7,,3,,,,,,,,,,,,,,,,,,,,,, ,Chemical Supplies,1,,,,,,,,4,3,,,,,1,4,,,,,,,,,,,,,,,, ,Gem Stones,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,25,,, ,Optical Components,,,,,,,,,,,,,,,,,,,,3,4,2,,,,,,,,,, ,Liqour,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,, ,Hydrogen Fuel,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,, ,Exotic Matter,,,,,,,,,,,,,,,,,3,3,,,,,,,,,,,,,, ,Radioactive Cells,,,,,,,,,,,,,,,,,,,,,,,3,6,,,,,,,, ,Droid Modules,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,Bio Waste,,,,,,,,,,,,,,,5,18,,,,,,,,,,,,,,,, ,Slaves,,,,,,,,,,,,,,,,,,3,2,,,,,,,,,,,,, ,Drugs,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,Nutrient Clods,,,,,,,,,,,,,,,,,,,,,,,,40,,,,,,,, ,Battleweapon Parts,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,Leech Baby,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, """ production_s = """ ,Food,,,8,,,,,,,,,,,,7,,,,,,,,,,,,,250,,,, ,Energy,,,,6,,,,,,,,,,,,,35,,,,,,,,,,187.5,,,,, ,Water,,,2,,,,,,,,,,,,5,,,,,,,,,,,,,312.5,,500,, ,Animal Embryos,,,,,,,,,,,,,,,,,,,,,,,,,,,62.5,31.25,,31.25,50,62.5 ,Ore,,,,,,9,,,,,,,,,,,,,,,,,,,,,,,,,,75 ,Metal,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,25 ,Electronics,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,, ,Robots,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,, ,Heavy Plastics,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,, ,Weapons,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, ,Medicines,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,, ,Nebula Gas,,20,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,250, ,Chemical Supplies,,,,,9,,,,,,,,,,,,,,,,,,,,,,,,,,25, ,Gem Stones,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,, ,Optical Components,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,, ,Liqour,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,, ,Hydrogen Fuel,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,Exotic Matter,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,Radioactive Cells,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,, ,Droid Modules,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,, ,Bio Waste,,,1,,,,,,,,,,,,,,,,4,,,,,3,,,,,,,, ,Slaves,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,6.25,,, ,Drugs,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,, ,Nutrient Clods,,,,,,,,,,,,,,,,5,,,,,,,,,,,,,,,, ,Battleweapon Parts,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,, ,Leech Baby,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,, ,Body Parts,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,, """ # parses amounts, ignores planets, starbases def parseit(s): d = {} for line in s.split('\n'): line = line.strip() if not line: continue toks = line.split(',') prod = toks[1].lower() toks = toks[2:] for (i, building) in enumerate(building_names): tok = toks[i] if 'planet' in building or 'starbase' in building: continue d.setdefault(building, {}) if not tok: continue amount = float(tok) d[building][prod]=amount return d upkeep_dict = parseit(upkeep_s) production_dict = parseit(production_s) def upkeep(b): result = {} d = upkeep_dict[b] for commodity in d: result[commodity] = int(round(d[commodity]*(1+(level-1)*.5))) return result def production(b): result = {} d = production_dict[b] for commodity in d: result[commodity] = int(round(d[commodity]*(1+(level-1)*.5))) return result def get_profits(buy_prices, sell_prices): p = {} for b in building_names: in_credits = 0 out_credits = 0 unable_to_determine = False if not b in buildings: continue for (com, am) in upkeep(b).items(): if com not in buy_prices: unable_to_determine = True break out_credits+=buy_prices[com]*am for (com, am) in production(b).items(): if com not in sell_prices: unable_to_determine = True break in_credits+=sell_prices[com]*am*consumed[com]/produced[com] if not unable_to_determine: p[b] = in_credits-out_credits return p # initialize starting requirements balance = dict([(c, 0) for c in commodity_names]) produced = dict([(c, 0.) for c in commodity_names]) # keeps track of total resource produced consumed = dict([(c, 0.) for c in commodity_names]) # keeps track of total resource consumed buildings = [] # Set initial needs, from the list of buildings for bname,num_buildings in end_buildings.items(): for commodity,amount in production(bname).items(): balance[commodity]+=amount*num_buildings produced[commodity]+=amount*num_buildings for commodity,amount in upkeep(bname).items(): balance[commodity]=-amount*num_buildings consumed[commodity]+=amount*num_buildings buildings.extend([bname]*num_buildings) upkeep_done = False counter = 0 upkeep_transferred = 0 # create support buildings while not upkeep_done: changed = False for commodity,amount in balance.items(): if amount>=0 or commodity in imports: continue for b in building_names: p = production(b) u = upkeep(b) if commodity in p: num_buildings = int(ceil(float(abs(amount))/p[commodity])) buildings.extend([b]*num_buildings) for commodity2,am in p.items(): balance[commodity2] += am*num_buildings produced[commodity2] += am*num_buildings for commodity2,am in u.items(): balance[commodity2] -= am*num_buildings consumed[commodity2] += am*num_buildings changed = True break if not changed: print 'Couldnt find source for %s'%(commodity,) sys.exit() break upkeep_done = True for commodity,amount in balance.items(): if commodity not in imports and amount<0: upkeep_done = False break # calculate total upkeep to transfer (not including imports,exports) for b in buildings: for (com, amount) in upkeep(b).items(): if com in imports: continue upkeep_transferred+=amount # Assume that every produced item that's in exports if "consumed" for com, am in produced.items(): if com in exports: consumed[com]+=am # get credit balance credits = 0 import_transferred = 0 print 'Target buildings' for b,am in end_buildings.items(): print '%25s %d' %(b, am) print 'Total Buildings' b_dict = {} for b in buildings: b_dict[b] = b_dict.get(b, 0)+1 for (b, amt) in b_dict.items(): print '%25s %d' %(b, amt) print 'Exports' for com,amount in balance.items(): if amount>0: credits+=amount*exports.get(com, 0) if not com in exports: s = 'Excess' else: s = '' print '%25s %6d %s'%(com, amount, s) print 'Imports' for com,amount in balance.items(): if amount<0: credits-=abs(amount)*imports[com] import_transferred+=abs(amount) print '%25s %6d'%(com, abs(amount)) owner_profit = credits-upkeep_transferred*upkeep_profit # calculate desired building profits profits = {} profit_denom = 0. for b in buildings: profit_denom+=profit_factors.get(b, 1) for b in buildings: profits[b] = owner_profit*profit_factors.get(b, 1)/profit_denom #print '%20s %d'%(b, profits[b]) # calculate prices buy_prices = dict(imports) sell_prices = dict(exports) counter = 0 while counter<100: # find a building with no incoming edges (all buying commodities have prices) for b in buildings: buy_determined = True sell_determined = True for com in upkeep(b): if not com in buy_prices: buy_determined = False break for com in production(b): if not com in sell_prices: sell_determined = False if buy_determined and not sell_determined: out_credits = 0 in_credits = 0 for (com, amount) in upkeep(b).items(): out_credits+=buy_prices[com]*amount in_credits = profits[b]+out_credits tons_produced = 0 # adjust for inefficiencies (pretend that produce only as many tons as are consumed) for (com, amount) in production(b).items(): tons_produced+=amount*consumed[com]/produced[com] if consumed[com] == 0: print 'Warning, commodity %s isnt consumed....did you specify it as an export?'%(com,) if tons_produced>0: price_per_ton = in_credits/tons_produced else: price_per_ton = -1 for com in production(b): sell_prices[com] = price_per_ton buy_prices[com] = price_per_ton+upkeep_profit break counter+=1 print 'Profits:' for (building, profit) in get_profits(buy_prices, sell_prices).items(): print '%25s %6d'%(building, profit) print 'Prices:' for com in commodity_names: if com not in buy_prices and com not in sell_prices: continue print '%20s %5d %5d'%(com, buy_prices.get(com, -1), sell_prices.get(com, -1)) print print 'Upkeep tons to transfer per cycle: %d' %(upkeep_transferred,) print 'Upkeep tons to import per cycle: %d' %(import_transferred,) print 'Total upkeep trader profit: %d' %(upkeep_transferred*upkeep_profit,) print 'Per building owner profit: %d' %(owner_profit/len(building),) #print 'Profit per building: %d'% (owner_profit/len(buildings),) print '-'*30