"Buttercup GO!" Player

Skills used:

  • Python
  • Selenium Web Driver

This program automatically plays a web-browser game called "ButterCup GO!" Every part of the game is an HTML element, so we can target all the text, buttons, obstacles, and characters in the game.

The bot tracks the height of the incoming obstacle and moves the character up or down to get through it. Once that obstacle reaches an x position of 600px, it switches its focus to the second obstacle and adjusts the character's height accordingly.

When the bot loses, it submits the score and replays the game. Performance generally differs depending on which web browser is used by the code. I currently have Firefox as the default browser.

Code:
                    
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import *
from selenium.webdriver.common.by import By

service = Service("./msedgedriver.exe")
driver = webdriver.Edge(service=service)
driver.get("https://buttercup.rocks/")


def get_window(even_obs):
    top = ""
    bottom = ""
    path = '//*[@id="__next"]/div/div[5]/div[4]/div[3]' if even_obs else '//*[@id="__next"]/div/div[5]/div[5]/div[3]'
    window = driver.find_element(By.XPATH, f'{path}').get_attribute('style')
    top_finished = False
    for letter in window:
        if letter.isdigit():
            if top_finished:
                bottom += letter
            else:
                top += letter
        elif letter == ";":
            top_finished = True
    top = int(top)
    bottom = int(bottom)
    return [top, bottom]

def get_buttercup():
    y_axis = ""
    window = driver.find_element(By.XPATH, '//*[@id="__next"]/div/div[5]/div[6]').get_attribute('style')
    x_finished = False
    for letter in window:
        if letter.isdigit() or letter == ".":
            if x_finished:
                y_axis += letter
        elif letter == ",":
            x_finished = True
        elif x_finished and letter == ")":
            break
    return float(y_axis)

def track_obstacles(even_obs):
    x_axis = ""
    path = '//*[@id="__next"]/div/div[5]/div[4]' if even_obs else '//*[@id="__next"]/div/div[5]/div[5]'
    position = driver.find_element(By.XPATH, f'{path}').get_attribute('style')
    w_finished = False
    for letter in position:
        if letter.isdigit() or letter == ".":
            if w_finished:
                x_axis += letter
        elif letter == ";":
            w_finished = True
        elif w_finished and letter == "p":
            break
    if x_axis == "":
        x_axis = "0"

    return float(x_axis)


while True:
    time.sleep(2)
    driver.find_element(By.CSS_SELECTOR, "div button").click()
    time.sleep(2)
    driver.find_element(By.CSS_SELECTOR, 'body').click()
    on_even_obstacle = False

    while driver.find_element(By.CSS_SELECTOR, ".styles_deadMessage__kW9am").get_attribute("style") == "display: none;":
        current_obstacle = track_obstacles(on_even_obstacle)
        print(current_obstacle)
        if current_obstacle > 600:
            on_even_obstacle = not on_even_obstacle
            current_obstacle = track_obstacles(on_even_obstacle)
        obstacle_height = get_window(on_even_obstacle)
        buttercup_y = get_buttercup()
        if obstacle_height[1] + 200 + 90.25 >= buttercup_y - 62.03:
            driver.find_element(By.CSS_SELECTOR, 'body').click()

    time.sleep(1)
    initials = driver.find_element(By.CSS_SELECTOR, ".styles_input__3823I")
    initials.send_keys("gee")
    driver.find_element(By.CSS_SELECTOR, ".styles_submitButton__2B0Uc button").click()
    time.sleep(1)
    driver.find_element(By.CSS_SELECTOR, ".styles_backButtonCt__1SJax button").click()