Created
October 11, 2012 22:18
-
-
Save Muon/3875892 to your computer and use it in GitHub Desktop.
Achron economy model
This file contains 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
"""A high-level simulation of Achron's economy.""" | |
from __future__ import division | |
# Simulation time parameters | |
ticks_per_second = 18 | |
simulation_length = 5 * 60 | |
t = simulation_length * ticks_per_second | |
# RP constants | |
# EXPb | |
rp_cost = 100 | |
lc_per_load = 10 | |
ticks_per_load = 178 | |
morph_time = 9 * ticks_per_second # EXPb v1.2.0 | |
# morph_time = 4 * ticks_per_second # EXPb v1.1.0 | |
# Achron v1.2.0.1 | |
# rp_cost = 50 | |
# lc_per_load = 8 | |
# ticks_per_load = 284 | |
# morph_time = 3 * ticks_per_second | |
# Map-dependent constants | |
distance_to_crates = 5 # Fudge factor for moving to starting resource patch | |
# Common constants | |
start_lc = 300 | |
deploy_time = 24 # Time needed for RP to start collecting after being built | |
rp_width = 3 # Width of an RP, needed for biped start time fudge factor | |
# Biped constants | |
biped_move_rate = 10 # ticks/cell | |
biped_build_time = 20 * ticks_per_second # Time needed for biped RP to be built | |
# Grekim constants | |
octo_cost = 45 | |
pharo_cost = 95 | |
pharo_birth_time = 162 | |
octo_birth_time = 288 # ticks | |
octo_move_rate = 6 # ticks/cell | |
grekim_rp_horiz_move_rate = 14 # ticks/cell | |
grekim_rp_vert_move_rate = 4 # ticks/height level | |
grekim_initial_rp_travel_time = 12 * ticks_per_second - deploy_time # distance_to_crates * grekim_rp_horiz_move_rate + grekim_rp_vert_move_rate * 2 | |
# Fudge factors for Octo movement from duo to crate | |
octo_move_time = octo_move_rate * distance_to_crates | |
# octo_move_time = 0 # Walking duo, so travel time is negligible | |
initial_progen_energy = 20 | |
progen_regeneration = 108 # ticks/unit regenerated | |
octo_progen_cost = 3 # Progen energy consumed to birth an octo | |
progen_toggle_time = 90 # ticks; time needed to enter progen mode | |
morph_cost = rp_cost - octo_cost | |
grekim_build_time = morph_time + deploy_time + octo_move_time | |
def compute_new_lc(t, lc, rps, build_time): | |
"""Computes new LC value. Species-agnostic.""" | |
for time_built_at in rps: | |
time_since_build_issued = t - time_built_at | |
if build_time > time_since_build_issued: | |
continue | |
time_active = time_since_build_issued - build_time | |
if time_active > 0 and (time_active % ticks_per_load) == 0: | |
lc += lc_per_load | |
return lc | |
def count_active_rps(t, rps, build_time): | |
"""Counts active RPs. Species-agnostic.""" | |
active_rps = 0 | |
for time_built_at in rps: | |
time_since_build_issued = t - time_built_at | |
if build_time > time_since_build_issued: | |
continue | |
time_active = time_since_build_issued - build_time | |
if time_active > 0: | |
active_rps += 1 | |
return active_rps | |
def biped(): | |
lc = start_lc | |
first_rp = distance_to_crates * biped_move_rate | |
rps = [first_rp, first_rp + biped_move_rate * rp_width, first_rp + biped_move_rate * rp_width * 2] # times at which RPs were built | |
for i in range(0, rps[0]): | |
yield [0, lc] | |
lc -= rp_cost | |
for i in range(rps[0], rps[1]): | |
yield [0, lc] | |
lc -= rp_cost | |
for i in range(rps[1], rps[2]): | |
yield [0, lc] | |
lc -= rp_cost | |
start_time = rps[2] | |
for i in range(start_time, t): | |
assert lc >= 0 | |
lc = compute_new_lc(i, lc, rps, biped_build_time + deploy_time) | |
if lc >= rp_cost: | |
rps.append(i) | |
lc -= rp_cost | |
yield [count_active_rps(i, rps, biped_build_time), lc] | |
def _grekim_mature_octos(t, octo_buildstart): | |
new_octos = 0 | |
new_buildstart = [] | |
for octo in octo_buildstart: | |
if t - octo >= octo_birth_time: | |
new_octos += 1 | |
else: | |
new_buildstart.append(octo) | |
octo_buildstart[:] = new_buildstart | |
return new_octos | |
def _grekim_morph_octos(t, lc, octos, rps): | |
while octos > 0 and lc >= morph_cost: | |
rps.append(t) | |
octos -= 1 | |
lc -= morph_cost | |
return lc, octos | |
def _grekim_predict_future(start, duration, lc, octos, rps, octo_buildstart): | |
rps = rps[:] | |
octo_buildstart = octo_buildstart[:] | |
for i in range(start, start + duration + 1): | |
lc = compute_new_lc(i, lc, rps, grekim_build_time) | |
lc, octos = _grekim_morph_octos(i, lc, octos, rps) | |
octos += _grekim_mature_octos(i, octo_buildstart) | |
return lc, octos | |
def grekim(): | |
lc = start_lc - pharo_cost | |
octo_buildstart = [] # times at which octos were built | |
octos = 0 | |
progen_energy = initial_progen_energy | |
rps = [grekim_initial_rp_travel_time - grekim_build_time] # times at which RPs were built | |
for i in range(0, grekim_initial_rp_travel_time + deploy_time): | |
yield [0, lc] | |
start_time = pharo_birth_time + progen_toggle_time | |
for i in range(grekim_initial_rp_travel_time + deploy_time, start_time): | |
yield [1, lc] | |
for i in range(start_time, t): | |
if (i % progen_regeneration) == 0: | |
progen_energy = min(initial_progen_energy, progen_energy + 1) | |
assert 0 <= progen_energy <= initial_progen_energy | |
assert lc >= 0 | |
lc = compute_new_lc(i, lc, rps, grekim_build_time) | |
lc, octos = _grekim_morph_octos(i, lc, octos, rps) | |
while lc >= octo_cost and progen_energy >= octo_progen_cost: | |
future_lc, future_octos = _grekim_predict_future( | |
i, octo_birth_time, lc - octo_cost, octos, rps, octo_buildstart) | |
if future_lc >= morph_cost * (future_octos + 1): | |
octo_buildstart.append(i) | |
progen_energy -= octo_progen_cost | |
lc -= octo_cost | |
else: | |
break | |
octos += _grekim_mature_octos(i, octo_buildstart) | |
yield [count_active_rps(i, rps, grekim_build_time), lc] | |
from matplotlib import dates | |
import matplotlib.pyplot as plt | |
from datetime import datetime | |
def prettify_rp_data(data_iterable): | |
"""Takes model iterable and returns distinct RP counts with times. | |
Returns two lists (times, rp_counts). | |
""" | |
rp_counts = [] | |
times = [] | |
prev_rp_count = None | |
for i, (rp_count, lc) in enumerate(data_iterable): | |
if rp_count != prev_rp_count: | |
rp_counts.append(rp_count) | |
times.append(datetime.fromtimestamp(i / ticks_per_second)) | |
prev_rp_count = rp_count | |
return times, rp_counts | |
def prettify_lc_data(data_iterable): | |
"""Takes model iterable and returns distinct LC counts with times. | |
Returns two lists (times, lc_counts). | |
""" | |
lc_counts = [] | |
times = [] | |
prev_lc = None | |
for i, (rp_count, lc) in enumerate(data_iterable): | |
if lc != prev_lc: | |
lc_counts.append(lc) | |
times.append(datetime.fromtimestamp(i / ticks_per_second)) | |
prev_lc = lc | |
return times, lc_counts | |
biped_data = list(biped()) | |
grekim_data = list(grekim()) | |
# Plot RPs/time graph | |
biped_times, biped_rps = prettify_rp_data(biped_data) | |
grekim_times, grekim_rps = prettify_rp_data(grekim_data) | |
plt.figure(1) | |
plt.subplot(211) | |
axes = plt.gca() | |
axes.xaxis.set_major_formatter(dates.DateFormatter('%M:%S')) | |
axes.set_xlabel("Time") | |
axes.set_ylabel("Number of RPs") | |
axes.set_axisbelow(True) | |
plt.xlim([datetime.fromtimestamp(0), datetime.fromtimestamp(simulation_length)]) | |
plt.step(biped_times, biped_rps, 'b.-', where="post", label="Biped RPs") | |
plt.step(grekim_times, grekim_rps, 'g.-', where="post", label="Grekim RPs") | |
plt.grid(True, which="major", linestyle="-") | |
plt.grid(True, which="minor", color="b", linestyle="--") | |
plt.legend(loc=2, prop={'size':10}) | |
# Plot LC/time graph | |
biped_times, biped_lc = prettify_lc_data(biped_data) | |
grekim_times, grekim_lc = prettify_lc_data(grekim_data) | |
plt.subplot(212) | |
axes = plt.gca() | |
axes.xaxis.set_major_formatter(dates.DateFormatter('%M:%S')) | |
axes.set_xlabel("Time") | |
axes.set_ylabel("Amount of LC") | |
axes.set_axisbelow(True) | |
plt.xlim([datetime.fromtimestamp(0), datetime.fromtimestamp(simulation_length)]) | |
plt.step(biped_times, biped_lc, 'b-', where="post", label="Biped LC") | |
plt.step(grekim_times, grekim_lc, 'g-', where="post", label="Grekim LC") | |
plt.grid(True, which="major", linestyle="-") | |
plt.grid(True, which="minor", color="b", linestyle="--") | |
plt.legend(loc=2, prop={'size':10}) | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment