class Game: x_offset = 20 y_offset = 250 width = 639 height = 480 # TODO: Organize/Standardize hardcoded pixel locations def __init__(self): print 'Starting a new game' self.coordinates = (0, 0) self.location = GameLocation(self.x_offset, self.y_offset, self.width, self.height) self.vision = Vision(self.location) self.controller = Controller(self.x_offset, self.y_offset) self.phone = Phone() self._build_buttons() self._reset_food() self._build_customers() self._build_recipes() self.mat = GameObject('Mat', (199, 380)) def play(self): print 'Getting past menus' self._start() while True: self._deal_with_unhappy_customers() self._prepare_customer_orders() sleep(6) self._clear_tables() if self._is_level_complete(): self.advance_level() def _reset_food(self): self._build_food() self._build_sake() def _start(self): self._focus() self.controller.click_on(self.sound_button) self.controller.click_on(self.play_button) self.controller.click_menu(self.continue_button) self.controller.click_menu(self.skip_button) self.controller.click_menu(self.continue_button) def _deal_with_unhappy_customers(self): unhappy_customers = self._find_unhappy_customers() if len(unhappy_customers) == 0: print 'Everyone looks happy' for customer in unhappy_customers: print customer.name + ' is unhappy.' self._serve_sake(customer) def _get_customer_orders(self): print 'Gathering customer orders' orders = map( lambda customer: self.vision.analyze(customer.order_box()), self.customers) # Reverse order to reduce last customer wait time orders.reverse() return orders def _prepare_customer_orders(self): for code in self.get_customer_orders: results = filter(lambda recipe: recipe.with_code(code), self.recipes) if results: self._prepare_recipe(results[0]) def _clear_tables(self): print 'Clearing tables' for customer in self.customers: self.controller.click_on(customer.plate) def _is_level_complete(self): return self.advanceButton.isPresent( self.vision.analyze(self.advanceButton.boundingBox)) def _advance_level(self): print 'Level complete' sleep(15) print 'Advancing to next level' # There are 2 continue buttons to start the next level for _ in xrange(2): self.controller.click_on(self.advanceButton) sleep(1) self.reset_food() def _focus(self): self.controller.click_on(self) def _build_buttons(self): self.sound_button = Button('Sound', (302, 372), boundingBox=(499, 717, 768, 772)) self.play_button = Button('Play', (311, 206), boundingBox=(448, 342, 825, 477)) self.continue_button = Button('Continue', (317, 393)) self.skip_button = Button('Skip', (579, 455)) self.advanceButton = Button('Advance', boundingBox=(348, 714, 931, 797), colorSum=49559) def _build_food(self): # This list is getting long...perhaps there are other classes hiding here # name, type, location, order_button location, unavailable_pixel, starting_quantity self.rice = Food('Rice', 'Base', (88, 338), (516, 276), (118, 83, 85, 255), quantity=10) self.shrimp = Food('Shrimp', 'Topping', (41, 330), (461, 210), quantity=5) self.nori = Food('Nori', 'Topping', (40, 393), (464, 269), quantity=10) self.roe = Food('Roe', 'Topping', (101, 388), (551, 275), quantity=10) self.salmon = Food('Salmon', 'Topping', (41, 453), (468, 331), quantity=5) self.unagi = Food('Unagi', 'Topping', (103, 442), (548, 211), quantity=5) def _build_sake(self): self.sake = [] locations = [(430, 370), (415, 342)] for location in locations: self.sake.append( Food('Sake', 'Sake', location, (516, 273), (160, 160, 160, 255), quantity=1)) def _build_customers(self): self.customers = [] for position in xrange(6): plate = self._build_plate(position) order = self._build_order(position) happiness = self._build_happiness(position) self.customers.append( Customer('Customer ' + str(position), plate, order, happiness)) def _build_plate(self, position): plate_coordinates = [85, 189, 280, 387, 484, 581] plate_location = (plate_coordinates[position], 204) plate = GameObject('Plate', plate_location) return plate def _build_order(self, position): order_coordinates = [51, 253, 455, 657, 859, 1061] order_width = 121 order_y = 122 order_height = 29 order_box = (order_coordinates[position], order_y, order_coordinates[position] + order_width, order_y + order_height) order = GameObject('Order Bubble', boundingBox=order_box) return order def _build_happiness(self, position): happiness_coordinates = [100, 302, 504, 706, 908, 1110] happiness_width = 11 happiness_y = 216 happiness_height = 7 happiness_box = (happiness_coordinates[position], happiness_y, happiness_coordinates[position] + happiness_width, happiness_y + happiness_height) happiness = GameObject('Happiness Indicator', boundingBox=happiness_box, colorSum=548) return happiness def _build_recipes(self): self.cali_roll = Recipe('California Roll', [self.nori, self.rice, self.roe], 4989) self.gunkan = Recipe('Gunkan', [self.nori, self.rice, self.roe, self.roe], 4352) self.onigiri = Recipe('Onigiri', [self.rice, self.rice, self.nori], 4345) self.salmon_roll = Recipe( 'Salmon Roll', [self.rice, self.nori, self.salmon, self.salmon], 4320) self.shrimp_sushi = Recipe( 'Shrimp Sushi', [self.rice, self.nori, self.shrimp, self.shrimp], 4767) self.unagi_sushi = Recipe( 'Unagi Sushi', [self.rice, self.nori, self.unagi, self.unagi], 4568) self.recipes = [ self.cali_roll, self.gunkan, self.onigiri, self.salmon_roll, self.shrimp_sushi, self.unagi_sushi ] def _prepare_recipe(self, recipe): if recipe.any_ingredient_missing(): return print 'Preparing ' + recipe.name for ingredient in recipe.ingredients: self.controller.click_on(ingredient) ingredient.consume() self._roll_mat() for ingredient in recipe.low_ingredient_list(): self.restock(ingredient) def _roll_mat(self): self.controller.click_on(self.mat) sleep(1.5) def _restock(self, food, attempt=0): self.controller.click_menu(self.phone) self.controller.click_menu(self.phone.menuFor(food)) # TODO: Clean this mess up location = tuple(map(lambda x: x * 2, food.order_location())) pixel = self.vision.screenGrab().getpixel(location) print str( food.quantity) + ' ' + food.name + ' remaining. Trying to restock' if food.available_for_order(pixel): print food.name + ' is available...Ordering' self.controller.click_menu(food.order_button) self.controller.click_menu(self.phone.orderButton) food.update_quantity() else: print food.name + ' is unavailable...Hanging up' self.controller.click_menu(self.phone.hangUpButton) print 'Waiting for income...' sleep(3) if attempt < 3: self._restock(food, attempt + 1) def _find_unhappy_customers(self): unhappy_customers = [] for customer in self.customers: if customer.is_unhappy( self.vision.analyze(customer.happiness_meter_location())): unhappy_customers.append(customer) return unhappy_customers def _serve_sake(self, customer): servable_sake = filter(lambda sake: sake.sold_out() is False, self.sake) if len(servable_sake) > 0: sake = servable_sake[0] print "Let's get " + customer.name + " drunk" self.controller.click_on(sake) self.controller.drag_to(customer.plate) self.controller.click_on(customer.plate) sake.consume()