def produce(_id): batch = 2 * config['batchEconomy'] colony = cp.query(payload="\ SELECT goods, storage, industry, population, untilJoins\ FROM massive\ WHERE _id == '"+_id+"'")['results'][0] # produce_goods goodsPerPop = float(colony['untilJoins']['habitability']) - float(colony['population']) * config['popDAR'] goodsTotal = batch * float(colony['population']) * goodsPerPop colony['storage']['goods'][colony['goods']] += int(goodsTotal) # produce_materials materialsPerInd = float(colony['untilJoins']['richness']) - float(colony['industry']) * config['indDAR'] materialsTotal = batch * float(colony['industry']) * materialsPerInd colony['storage']['solids'] += int(materialsTotal * float(colony['untilJoins']['materials'][0])) colony['storage']['metals'] += int(materialsTotal * float(colony['untilJoins']['materials'][1])) colony['storage']['isotopes'] += int(materialsTotal * float(colony['untilJoins']['materials'][2])) r = cp.query(payload="\ UPDATE massive['" + _id + "']\ SET storage.goods['"+colony['goods']+"'] = "+str(colony['storage']['goods'][colony['goods']])+",\ storage['solids'] = "+str(colony['storage']['solids'])+",\ storage['metals'] = "+str(colony['storage']['metals'])+",\ storage['isotopes'] = "+str(colony['storage']['isotopes'])+"\ ")['results'][0]['_id'] return 'economy: produce at ' + r
def disband(_id): r = cp.query(payload="SELECT *\ FROM massive\ WHERE object == 'colony' && faction == '" + _id + "'\ LIMIT 0, 0") if int(r['hits']) == 0: r = cp.query(payload="DELETE massive['" + _id + "']")['results'][0]['_id'] return 'factions: disband faction ' + _id else: return 'factions: keep faction ' + _id
def upkeep(_id): batch = 2 * config['batchEconomy'] colony = cp.query(payload="\ SELECT goods, storage, industry, population, untilJoins\ FROM massive\ WHERE _id == '"+_id+"'")['results'][0] # upkeep_population size = colony['population'] for key, amount in colony['storage']['goods'].items(): if size == 0: break if colony['storage']['goods'][key] >= batch and random.random() >= config['popForeignGoods']: colony['storage']['goods'][key] -= batch size -= 1 if colony['storage']['goods'][colony['goods']] >= size * config['popLocalPenalty'] * batch: colony['storage']['goods'][colony['goods']] -= size * config['popLocalPenalty'] * batch else: colony['population'] -= 1 colony['storage']['goods'][colony['goods']] += config['popDowngradeRefund'] * config['popUpgradeGoods'] colony['storage']['solids'] += config['popDowngradeRefund'] * config['popUpgradeSolids'] # upkeep_industry size = colony['industry'] for key, amount in colony['storage']['goods'].items(): if size == 0: break if colony['storage']['goods'][key] >= batch and random.random() >= config['indForeignGoods']: colony['storage']['goods'][key] -= batch size -= 1 if colony['storage']['solids'] >= size * config['indLocalPenalty'] * batch: colony['storage']['solids'] -= size * config['indLocalPenalty'] * batch else: colony['industry'] -= 1 colony['storage']['goods'][colony['goods']] += config['indDowngradeRefund'] * config['indUpgradeGoods'] colony['storage']['solids'] += config['indDowngradeRefund'] * config['indUpgradeSolids'] r = cp.query(payload="\ UPDATE massive['" + _id + "']\ SET storage['goods'] = "+json.dumps(colony['storage']['goods'])+",\ storage['solids'] = "+str(int(colony['storage']['solids']))+",\ storage['metals'] = "+str(int(colony['storage']['metals']))+",\ storage['isotopes'] = "+str(int(colony['storage']['isotopes']))+",\ population = "+str(int(colony['population']))+",\ industy = "+str(int(colony['industry']))+"\ ")['results'][0]['_id'] return 'economy: upkeep at ' + r
import utils tick = 0 # lock to serialize console output while True: # Reload stuff ############################################################ start = time.time() with open('config.json') as data_file: config = json.loads(jsmin(data_file.read())) # Get tick try: tick = cp.query(payload="SELECT COUNT() FROM massive WHERE object == 'tick' GROUP BY object LIMIT 0, 1")["results"][0]["COUNT()"] except KeyError or TypeError: tick = 0 # Respawn workers utils.spawn_workers(config['num_worker_threads'], tick, config, utils.q) # Update universe, create or age systems, stars, planets utils.q.put('universe') # Check planets to spawn new Faction with Colony utils.q.put('factions') # Production and upkeep utils.q.put('economy')
def main(tick, config, q): # Disband 'empty' factions with no colonies def disband(_id): r = cp.query(payload="SELECT *\ FROM massive\ WHERE object == 'colony' && faction == '" + _id + "'\ LIMIT 0, 0") if int(r['hits']) == 0: r = cp.query(payload="DELETE massive['" + _id + "']")['results'][0]['_id'] return 'factions: disband faction ' + _id else: return 'factions: keep faction ' + _id if tick%config['cleanFactions'] == 0: factions = cp.query(payload="\ SELECT _id\ FROM massive\ WHERE object == 'faction'\ LIMIT 0,9999") if 'results' in factions: for faction in factions['results']: utils.queue(disband, faction['_id']) # Abandon depopulation colonies def abandon(_id): r = cp.query(payload="\ UPDATE massive['" + _id + "']\ SET faction = null")['results'][0]['_id'] return 'factions: abandon colony ' + r colonies = cp.query(payload="\ SELECT _id, faction\ FROM massive\ WHERE object == 'colony' && population == 0 && faction") if 'results' in colonies: for colony in colonies['results']: utils.queue(abandon,colony['_id']) # Spawn new factions with initial colony count = int(cp.query(payload="SELECT * FROM massive WHERE object == 'faction' LIMIT 0, 0")['hits']) want = int(utils.dist_skewedLeft(config['factions'])) if want > count: planet = cp.query(payload="\ SELECT _id, size, habitability, richness, materials\ FROM massive\ WHERE\ object == 'planet' &&\ type != 'Gas' &&\ system_coords.radius < "+str(int(config['optimalDistance'][0]*config['optimalDistance'][1]))+" &&\ system_coords.radius > "+str(int(config['optimalDistance'][0]/config['optimalDistance'][1]))+"\ ORDER BY Math.abs("+str(config['optimalDistance'][0])+" - system_coords.radius) * Math.random()\ LIMIT 0, 1" )["results"][0] occupied = cp.query(payload="\ SELECT SUM(population+industry) as size\ FROM massive\ WHERE object == 'colony' && anchor == '"+planet['_id']+"'\ GROUP BY anchor") if int(occupied['hits']) == 0 or (planet['size'] >= occupied['results'][0]['size'] + 2): utils.queue(cp.put, payload={ 'object': 'faction', 'pref': { # 0 prefers first, 1 prefers last, 0.5 is indifferent. 'population_industry': utils.dist_flat(config['population_industry']), 'pacific_militaristic': utils.dist_flat(config['pacific_militaristic']), 'defence_attack': utils.dist_flat(config['defence_attack']), 'growth_expand': utils.dist_flat(config['growth_expand']), }}, params='[faction'+str(tick)+']', msg='factions: spawn faction '+str(tick) ) utils.queue(cp.put, payload={ 'object': 'colony', 'faction': 'faction'+str(tick), 'anchor': planet['_id'], 'goods': re.search("(\w*)p", planet['_id']).group(1), 'untilJoins': { 'habitability': planet['habitability'], 'richness': planet['richness'], 'materials': planet['materials'], }, 'population': 1, 'industry': 1, 'storage': { 'goods': { re.search("(\w*)p", planet['_id']).group(1): 100, }, 'solids': 100, # Upkeep for industry 'metals': 0, # For structure of skips 'isotopes': 0, # For guns of ships 'ammo': 0 # For guns to shoot }}, msg='factions: spawn colony' ) return 'done'
def abandon(_id): r = cp.query(payload="\ UPDATE massive['" + _id + "']\ SET faction = null")['results'][0]['_id'] return 'factions: abandon colony ' + r
def main(tick, config, q): # How many systems are there? count = int(cp.query(payload="SELECT * FROM massive WHERE object == 'system' LIMIT 0, 0")["hits"]) # How many we want? want = int(utils.dist_skewedLeft(config['systems'])) if want == count: pass elif want >= count: # Generate up to X more systems per tick pre = '[t' + str(tick) for system in range(0, min(config['systemsVolatility'], want - count)): urly = 'y' + str(system) stars = [] for star in range(0, int(utils.dist_skewedLeft(config['stars']))): urls = urly + 's' + str(star) coordss = rndCoords(config['starDistance'], config['zFlatness']) planets = [] for planet in range(0, int(utils.dist_skewedLeft(config['planets']))): urlp = urls + 'p' + str(planet) coordsp = rndCoords(config['planetDistance'], config['zFlatness'], coordss) moons = [] for moon in range(0, int(utils.dist_skewedLeft(config['moons']))): urlm = urlp + 'm' + str(moon) utils.queue(cp.put, payload={ "object": "moon", "system_coords": rndCoords(config['moonDistance'], config['zFlatness'], coordsp), 'type': ['Gas', 'Ice', 'Rock', 'Iron', 'Mix'][utils.choose_weighted(config['moonType'])], 'size': round(utils.dist_skewedLeft(config['moonSize']), 0), 'habitability': round(utils.dist_skewedLeft(config['moonHabitability']), 1), 'richness': round(utils.dist_skewedLeft(config['moonRichness']), 1), 'materials': rndMaterials(config['moonWeightSolidsOther'], config['moonWeightMetalsIsotopes']), }, params=pre+urlm+"]", msg=' Moon ' + pre+urlm+"]" ) utils.queue(cp.put, payload={ "object": "planet", "system_coords": rndCoords(config['planetDistance'], config['zFlatness']), 'type': ['Gas', 'Ice', 'Rock', 'Iron', 'Mix'][utils.choose_weighted(config['planetType'])], 'size': round(utils.dist_skewedLeft(config['planetSize']), 0), 'habitability': round(utils.dist_skewedLeft(config['planetHabitability']), 1), 'richness': round(utils.dist_skewedLeft(config['planetRichness']), 1), 'materials': rndMaterials(config['planetWeightSolidsOther'], config['planetWeightMetalsIsotopes']), }, params=pre+urlp+"]", msg=' Planet ' + pre+urlp+"]" ) utils.queue(cp.put, payload={ "id": star, "object": "star", "system_coords": rndCoords(config['starDistance'], config['zFlatness']), }, params=pre+urls+"]", msg=' Star ' + pre+urls+"]" ) utils.queue(cp.put, payload={ "object": "system", "universe_coords": { "x": random.randrange(config['x'][0],config['x'][1]), "y": random.randrange(config['y'][0],config['y'][1]), "z": random.randrange(config['z'][0],config['z'][1]), },}, params=pre+urly+"]", msg='System ' + pre+urly+"]" ) elif want <= count: pass # TODO destroy systems return "done"
def main(tick, config, q): # On average, per tick: # Colony produce (10 * (habitability-population/10)) local goods per population # Colony produce (10 * richness * weight) every material per industry # Colony upkeeps 1 unique exotic good or 4 local goods per population # Colony upkeeps 1 unique exotic good or 4 solids per industry def produce(_id): batch = 2 * config['batchEconomy'] colony = cp.query(payload="\ SELECT goods, storage, industry, population, untilJoins\ FROM massive\ WHERE _id == '"+_id+"'")['results'][0] # produce_goods goodsPerPop = float(colony['untilJoins']['habitability']) - float(colony['population']) * config['popDAR'] goodsTotal = batch * float(colony['population']) * goodsPerPop colony['storage']['goods'][colony['goods']] += int(goodsTotal) # produce_materials materialsPerInd = float(colony['untilJoins']['richness']) - float(colony['industry']) * config['indDAR'] materialsTotal = batch * float(colony['industry']) * materialsPerInd colony['storage']['solids'] += int(materialsTotal * float(colony['untilJoins']['materials'][0])) colony['storage']['metals'] += int(materialsTotal * float(colony['untilJoins']['materials'][1])) colony['storage']['isotopes'] += int(materialsTotal * float(colony['untilJoins']['materials'][2])) r = cp.query(payload="\ UPDATE massive['" + _id + "']\ SET storage.goods['"+colony['goods']+"'] = "+str(colony['storage']['goods'][colony['goods']])+",\ storage['solids'] = "+str(colony['storage']['solids'])+",\ storage['metals'] = "+str(colony['storage']['metals'])+",\ storage['isotopes'] = "+str(colony['storage']['isotopes'])+"\ ")['results'][0]['_id'] return 'economy: produce at ' + r def upkeep(_id): batch = 2 * config['batchEconomy'] colony = cp.query(payload="\ SELECT goods, storage, industry, population, untilJoins\ FROM massive\ WHERE _id == '"+_id+"'")['results'][0] # upkeep_population size = colony['population'] for key, amount in colony['storage']['goods'].items(): if size == 0: break if colony['storage']['goods'][key] >= batch and random.random() >= config['popForeignGoods']: colony['storage']['goods'][key] -= batch size -= 1 if colony['storage']['goods'][colony['goods']] >= size * config['popLocalPenalty'] * batch: colony['storage']['goods'][colony['goods']] -= size * config['popLocalPenalty'] * batch else: colony['population'] -= 1 colony['storage']['goods'][colony['goods']] += config['popDowngradeRefund'] * config['popUpgradeGoods'] colony['storage']['solids'] += config['popDowngradeRefund'] * config['popUpgradeSolids'] # upkeep_industry size = colony['industry'] for key, amount in colony['storage']['goods'].items(): if size == 0: break if colony['storage']['goods'][key] >= batch and random.random() >= config['indForeignGoods']: colony['storage']['goods'][key] -= batch size -= 1 if colony['storage']['solids'] >= size * config['indLocalPenalty'] * batch: colony['storage']['solids'] -= size * config['indLocalPenalty'] * batch else: colony['industry'] -= 1 colony['storage']['goods'][colony['goods']] += config['indDowngradeRefund'] * config['indUpgradeGoods'] colony['storage']['solids'] += config['indDowngradeRefund'] * config['indUpgradeSolids'] r = cp.query(payload="\ UPDATE massive['" + _id + "']\ SET storage['goods'] = "+json.dumps(colony['storage']['goods'])+",\ storage['solids'] = "+str(int(colony['storage']['solids']))+",\ storage['metals'] = "+str(int(colony['storage']['metals']))+",\ storage['isotopes'] = "+str(int(colony['storage']['isotopes']))+",\ population = "+str(int(colony['population']))+",\ industy = "+str(int(colony['industry']))+"\ ")['results'][0]['_id'] return 'economy: upkeep at ' + r # Whom production or upkeep should happen this tick? r = cp.query(payload="\ SELECT _id FROM massive\ WHERE object == 'colony' && faction && population > 0 && Math.random()<"+str(1/config['batchEconomy'])+"\ LIMIT 0, 999999") if int(r['hits']) > 0: # Iterate through colonies for lucky in r['results']: if random.random() < 0.5: utils.queue(produce, lucky['_id']) else: utils.queue(upkeep, lucky['_id']) return 'done'
#!/usr/bin/python3.4 from pprintpp import pprint as pp import cp # Manual query below pp(cp.query(payload="SELECT GROUP_KEY() as distance, COUNT() FROM massive WHERE type == 'planet' GROUP BY Math.floor(distance/50)*50 ORDER BY distance ASC LIMIT 0,10"))