Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Cookie Clicker Simulator
- """
- #http://www.codeskulptor.org/#user43_ULjUFtSgFkDefdl_12.py
- import simpleplot
- import math
- #import user43_G4PJLsAMW3DL8ai_22 as simpletest
- # Used to increase the timeout, if necessary
- import codeskulptor
- codeskulptor.set_timeout(20)
- import poc_clicker_provided as provided
- # Constants
- SIM_TIME = 10000000000.0
- class ClickerState:
- """
- Simple class to keep track of the game state.
- """
- def __init__(self):
- self._cps = 1.0
- self._cookies = 0.0
- self._net_cookies = 0.0
- self._time = 0.0
- self._history = [(0.0, None, 0.0, 0.0)]
- def __str__(self):
- """
- Return human readable state
- """
- return str(self._cookies) + " cookies out of <" + str(self._net_cookies/(SIM_TIME*100000)) + "> million available at time " + str(self._time)
- def get_cookies(self):
- """
- Return current number of cookies
- (not total number of cookies)
- Should return a float
- """
- return self._cookies
- def get_net_cookies(self):
- """
- Return total number of cookies
- Should return a float
- """
- return self._net_cookies
- def get_cps(self):
- """
- Get current CPS
- Should return a float
- """
- return self._cps
- def get_time(self):
- """
- Get current time
- Should return a float
- """
- return self._time
- def get_history(self):
- """
- Return history list
- History list should be a list of tuples of the form:
- (time, item, cost of item, total cookies)
- For example: [(0.0, None, 0.0, 0.0)]
- Should return a copy of any internal data structures,
- so that they will not be modified outside of the class.
- """
- return list(self._history)
- def time_until(self, cookies):
- """
- Return time until you have the given number of cookies
- (could be 0.0 if you already have enough cookies)
- Should return a float with no fractional part
- """
- if self._cookies > cookies:
- return 0.0
- else:
- return math.ceil(float(cookies-self._cookies)/self._cps)
- def wait(self, time):
- """
- Wait for given amount of time and update state
- Should do nothing if time <= 0.0
- """
- if time <= 0:
- return
- else:
- self._cookies += time*self._cps
- self._net_cookies += time*self._cps
- self._time += time
- return
- def buy_item(self, item_name, cost, additional_cps):
- """
- Buy an item and update state
- Should do nothing if you cannot afford the item
- """
- if self._cookies < cost:
- return
- else:
- self._cookies -= cost
- self._cps += additional_cps
- self._history.append((self._time, item_name, cost, self._net_cookies))
- return
- def simulate_clicker(build_info, duration, strategy):
- """
- Function to run a Cookie Clicker game for the given
- duration with the given strategy. Returns a ClickerState
- object corresponding to the final state of the game.
- """
- #initialize locals
- local_build_info = build_info.clone()
- clicker = ClickerState()
- debug_log = []
- debug = False
- #main logic
- while clicker.get_time() < duration:
- next_purchase = strategy(clicker.get_cookies(), clicker.get_cps(),
- clicker.get_history(), duration - clicker.get_time(),
- local_build_info)
- #check for break conditions
- #i.e. strategy doesn't return next purchase OR insufficient time/funds
- if not next_purchase:
- debug_log.append("Strategy declined purchasing item")
- break
- time_until_purchase = clicker.time_until(local_build_info.get_cost(next_purchase))
- if time_until_purchase + clicker.get_time() > duration:
- debug_log.append(("Cannot afford another ", next_purchase))
- break
- #buy next item
- clicker.wait(time_until_purchase)
- clicker.buy_item(next_purchase, local_build_info.get_cost(next_purchase),
- local_build_info.get_cps(next_purchase))
- debug_log.append(("Buying ", next_purchase, " under strat ", strategy))
- debug_log.append(clicker.get_history())
- local_build_info.update_item(next_purchase)
- #use up remaining time
- time_remainder = duration - clicker.get_time()
- debug_log.append((time_remainder, " time left over"))
- clicker.wait(time_remainder)
- #buy items at end-time
- next_purchase = strategy(clicker.get_cookies(), clicker.get_cps(),
- clicker.get_history(), 0.0, local_build_info)
- debug_log.append(("Next purchase: ", next_purchase))
- while next_purchase:
- if clicker.get_cookies() > local_build_info.get_cost(next_purchase):
- clicker.buy_item(next_purchase, local_build_info.get_cost(next_purchase),
- local_build_info.get_cps(next_purchase))
- local_build_info.update_item(next_purchase)
- next_purchase = strategy(clicker.get_cookies(), clicker.get_cps(),
- clicker.get_history(), 0.0, local_build_info)
- else:
- break
- #debugging
- if debug:
- for statement in debug_log:
- print statement
- #end
- return clicker
- def strategy_cursor_broken(cookies, cps, history, time_left, build_info):
- """
- Always pick Cursor!
- Note that this simplistic (and broken) strategy does not properly
- check whether it can actually buy a Cursor in the time left. Your
- simulate_clicker function must be able to deal with such broken
- strategies. Further, your strategy functions must correctly check
- if you can buy the item in the time left and return None if you
- can't.
- """
- return "Cursor"
- def strategy_none(cookies, cps, history, time_left, build_info):
- """
- Always return None
- This is a pointless strategy that will never buy anything, but
- that you can use to help debug your simulate_clicker function.
- """
- return None
- def strategy_cheap(cookies, cps, history, time_left, build_info):
- """
- Always buy the cheapest item you can afford in the time left.
- """
- cookies += cps*time_left
- items = build_info.build_items()
- costs_items = []
- for item in items:
- costs_items.append((build_info.get_cost(item), item))
- costs_items.sort()
- for cost_item in costs_items:
- if cookies >= cost_item[0]:
- return cost_item[1]
- return None
- def strategy_expensive(cookies, cps, history, time_left, build_info):
- """
- Always buy the most expensive item you can afford in the time left.
- """
- cookies += cps*time_left
- items = build_info.build_items()
- costs_items = []
- for item in items:
- costs_items.append((build_info.get_cost(item), item))
- costs_items.sort(reverse=True)
- for cost_item in costs_items:
- if cookies >= cost_item[0]:
- return cost_item[1]
- return None
- def strategy_best(cookies, cps, history, time_left, build_info):
- """
- The best strategy that you are able to implement.
- Returns object you can afford with highest cps to cost ratio.
- """
- cookies += cps*time_left
- items = build_info.build_items()
- costfactors_items = []
- for item in items:
- costfactors_items.append((build_info.get_cps(item)/build_info.get_cost(item),
- item))
- costfactors_items.sort(reverse=True)
- for costfactor_item in costfactors_items:
- if cookies >= build_info.get_cost(costfactor_item[1]):
- return costfactor_item[1]
- return None
- def run_strategy(strategy_name, time, strategy):
- """
- Run a simulation for the given time with one strategy.
- """
- state = simulate_clicker(provided.BuildInfo(), time, strategy)
- print strategy_name, ":", state
- # Plot total cookies over time
- # Uncomment out the lines below to see a plot of total cookies vs. time
- # Be sure to allow popups, if you do want to see it
- history = state.get_history()
- history = [(item[0], item[3]) for item in history]
- simpleplot.plot_lines(strategy_name, 1000, 400, 'Time', 'Total Cookies', [history], True)
- def run():
- """
- Run the simulator.
- """
- #Add calls to run_strategy to run additional strategies
- run_strategy("Cheap", SIM_TIME, strategy_cheap)
- run_strategy("Expensive", SIM_TIME, strategy_expensive)
- run_strategy("Best", SIM_TIME, strategy_best)
- #run_strategy("Cursor Broken", SIM_TIME, strategy_cursor_broken)
- return
- run()
- ##Simpletest Debugging
- #simpletest.run_suite_ClickerState(ClickerState)
- #simpletest.run_suite_cheap_simulation(simulate_clicker, strategy_cheap)
- #simpletest.run_suite_none_simulation(simulate_clicker, strategy_none)
Advertisement
Add Comment
Please, Sign In to add comment