Esempio n. 1
0
def price_of_item(name):
    np = NeoPage(base_url='https://items.jellyneo.net')
    path = '/search/'
    np.get(path, f'name={name}', 'name_type=3')
    results = re_jn_item.findall(np.content)
    for item_id, name, price_updated, price in results:
        print(f'Price of {name} ({item_id}) is {price}')
Esempio n. 2
0
def clean_shop_till():
    log = open(SALES_LOG_FILE, 'a')
    np = NeoPage()

    np.get('/market.phtml', 'type=sales')
    referer = np.referer
    if 'Nobody has bought anything' in np.content:
        print('No new sales.')
    else:
        tbl = re.search(
            '''<table align=center width=530 cellpadding=3 cellspacing=0>(.*?)</table>''',
            np.content)[1]
        rows = util.table_to_tuples(tbl)
        total_sales = 0
        for date, item, buyer, price in rows[1:-1]:
            price = util.amt(price)
            print(f'{date}: {buyer} bought {item} for {price} NP')
            log.write(f'{date},{buyer},{item},{price}\n')
            total_sales += price

        print(f'Total sales cleared: {total_sales} NP')
        print(f'Saved to {SALES_LOG_FILE}. Clearing history.')
        np.post('/market.phtml', 'type=sales', 'clearhistory=true')

    np.set_referer(referer)
    np.get('/market.phtml', 'type=till')
    amt = util.amt(
        re.search(r'''You currently have <b>(.*?)</b> in your till.''',
                  np.content)[1])
    if amt:
        print(f'Withdrawing {amt} NP from shop till.')
        np.post('/process_market.phtml', 'type=withdraw', f'amount={amt}')
    else:
        print(f'Shop till is empty.')
Esempio n. 3
0
def gen_restock_list(cat):
    np = NeoPage(base_url='https://items.jellyneo.net')
    path = '/search/'
    args = []
    args.append(f'cat[]={cat}')

    args.append('min_rarity=1')
    args.append('max_rarity=100')
    args.append('status=1')

    args.append('sort=5')
    args.append('sort_dir=desc')

    start = 0
    while True:
        np.get(path, *args, f'start={start}')
        time.sleep(min(60, random.expovariate(30)) + 60)
        last_page = not re.search(r'<li class="arrow"><a href=".*?">&raquo;</a>', np.content)
        referer = np.referer
        results = re_jn_item.findall(np.content)
        for item_id, name, price_updated, price in results:
            if price == 'Inflation Notice':
                np.set_referer(referer)
                np.get(f'/item/{item_id}')
                time.sleep(min(60, random.expovariate(30)) + 60)
                price = re.search('<div class="price-row">(.*?) NP', np.content)[1]
            try:
                price = lib.amt(price)
            except (ValueError, TypeError, IndexError):
                # safe assumption that unpriceable items are at least 10M NP?
                price = 10000001
            print(f'\'{name}\': {price},')
        start += 50
        if last_page: break
Esempio n. 4
0
def purchase(item, image=None, budget=None, quantity=1, **kwargs):
    # Buys a quantity of items from user shops, sticking within a budget.
    # Returns actual amount spent, or None if not successful.
    market = next(iter(item_db.get_market(item, image, **kwargs).values()))

    true_cost = 0
    qty_left = quantity
    buy_nps = []
    for price, stock, link in market:
        np2 = NeoPage()
        np2.get(link)
        buy_link, image, item, in_stock, cost = shop_item_re.search(
            np2.content).groups()
        in_stock = util.amt(in_stock)
        cost = util.amt(cost)
        if cost <= price:
            to_buy = min(in_stock, qty_left)
            true_cost += cost * to_buy
            qty_left -= to_buy
            buy_nps.append((np2, buy_link, to_buy))
            if qty_left <= 0:
                break

    if budget != None and true_cost > budget:
        return None

    ensure_np(true_cost)
    for np2, buy_link, to_buy in buy_nps:
        referer = np2.referer
        for _ in range(to_buy):
            print(f'Buying {item} from {buy_link}')
            np2.set_referer(referer)
            np2.get(f'/{buy_link}')

    return true_cost
Esempio n. 5
0
def jhudora_quest():
    np = NeoPage(save_pages=True)
    np.get(path)

    if 'I Accept!' in np.content:
        # TODO: Search your SDB, gallery, shop, and Neohome Superstore for item as well.
        user = os.environ['NP_USER']
        np.post(path_process, 'type=accept', f'username={user}')
        m = re.search(
            r"<br>Where is my <b>(.*?)</b>\?<p><img src='http://images.neopets.com/items/(.*?)'.*?>",
            np.content)
        item = m[1]
        image = m[2]
        print(f'Jhudora asked for {item} ({image})')
        cost = inventory.purchase(item, image=image)
        print(f'Bought it for {cost} NP.')
        np.set_referer_path(path)
        np.post(path_process, 'type=finished')
        if 'You have completed' in np.content:
            print(f'Quest shouuuuld be completed?')
        else:
            print(f"Quest doesn't seem to have completed")
    elif 'I am not ready' in np.content:
        print("Too early for Jhudora's Quest.")
    else:
        print("Jhudora's quest: Error!")
Esempio n. 6
0
def price_of_item(name):
    np = NeoPage(base_url='https://items.jellyneo.net')
    path = '/search/'
    np.get(path, f'name={name}', 'name_type=3')
    results = re_jn_item.findall(np.content)
    for item_id, name, price_updated, price in results:
        print(f'Price of {name} ({item_id}) is {price}')
Esempio n. 7
0
def purchase(item, image=None, budget=None, quantity=1, **kwargs):
    # Buys a quantity of items from user shops, sticking within a budget.
    # Returns actual amount spent, or None if not successful.
    market = next(iter(item_db.get_market(item, image, **kwargs).values()))

    true_cost = 0
    qty_left = quantity
    buy_nps = []
    for price, stock, link in market:
        np2 = NeoPage()
        np2.get(link)
        buy_link, image, item, in_stock, cost = shop_item_re.search(np2.content).groups()
        in_stock = util.amt(in_stock)
        cost = util.amt(cost)
        if cost <= price:
            to_buy = min(in_stock, qty_left)
            true_cost += cost * to_buy
            qty_left -= to_buy
            buy_nps.append((np2, buy_link, to_buy))
            if qty_left <= 0:
                break

    if budget != None and true_cost > budget:
        return None
    
    ensure_np(true_cost)
    for np2, buy_link, to_buy in buy_nps:
        referer = np2.referer
        for _ in range(to_buy):
            print(f'Buying {item} from {buy_link}')
            np2.set_referer(referer)
            np2.get(f'/{buy_link}')

    return true_cost
Esempio n. 8
0
def clean_shop_till():
    log = open(SALES_LOG_FILE, 'a')
    np = NeoPage()

    np.get('/market.phtml', 'type=sales')
    referer = np.referer
    if 'Nobody has bought anything' in np.content:
        print('No new sales.')
    else:
        tbl = re.search('''<table align=center width=530 cellpadding=3 cellspacing=0>(.*?)</table>''', np.content)[1]
        rows = util.table_to_tuples(tbl)
        total_sales = 0
        for date, item, buyer, price in rows[1:-1]:
            price = util.amt(price)
            print(f'{date}: {buyer} bought {item} for {price} NP')
            log.write(f'{date},{buyer},{item},{price}\n')
            total_sales += price

        print(f'Total sales cleared: {total_sales} NP')
        print(f'Saved to {SALES_LOG_FILE}. Clearing history.')
        np.post('/market.phtml', 'type=sales', 'clearhistory=true')

    np.set_referer(referer)
    np.get('/market.phtml', 'type=till')
    amt = util.amt(re.search(r'''You currently have <b>(.*?)</b> in your till.''', np.content)[1])
    if amt:
        print(f'Withdrawing {amt} NP from shop till.')
        np.post('/process_market.phtml', 'type=withdraw', f'amount={amt}')
    else:
        print(f'Shop till is empty.')
Esempio n. 9
0
def scorchy_slots():
    np = NeoPage()
    np.get(path)
    _ref_ck = np.search(r"<input type='hidden' name='_ref_ck' value='(.*?)'>")[1]
    np.post(path, f'_ref_ck={_ref_ck}', 'play=yes')

    while True:
Esempio n. 10
0
def set_shop_prices():
    np = NeoPage()

    g.items_stocked.clear()
    lim = 30
    ub_count = 0
    total_prices = 0
    while True:
        np.get('/market.phtml', 'order_by=id', 'type=your', f'lim={lim}')
        has_next = "<input type='submit' name='subbynext' value='Next 30'>" in np.content
        args = []
        args.append('type=update_prices')
        args.append('order_by=')
        args.append('view=')
        results = shop_item_re.findall(np.content)
        changed = False
        for (name, image, stock, category, obj_id_key, obj_id_val,
             old_cost_key, old_price, cost_key, desc,
             back_to_inv_key) in results:
            stock = int(stock)
            old_price = int(old_price)
            obj_id_val = int(obj_id_val)
            args.append(f'{obj_id_key}={obj_id_val}')
            args.append(f'{old_cost_key}={old_price}')

            g.items_stocked[obj_id_val] = stock

            my_price = old_price
            try:
                true_price = item_db.get_price(name,
                                               image,
                                               max_laxness=4,
                                               max_age=timedelta(days=7))
                if true_price == None:
                    pass
                elif type(true_price) == dict:
                    print(f'Warning: {name} has multiple forms: {true_price}')
                elif true_price >= 1000000:
                    ub_count += 1
                    print(f'Warning: {name} is unbuyable')
                    my_price = 0
                else:
                    my_price = true_price - 1
            except item_db.ShopWizardBannedException:
                pass
            if my_price != old_price:
                print(f'Setting {name} from {old_price} to {my_price} NP')
                changed = True
            total_prices += my_price
            args.append(f'{cost_key}={my_price}')
            args.append(f'{back_to_inv_key}=0')
        args.append('obj_name=')
        if changed:
            np.post('/process_market.phtml', *args)
        lim += 30
        if not has_next:
            break
    print(
        f'Shop has {total_prices} NP worth of items for sale ({ub_count} unbuyable)'
    )
Esempio n. 11
0
def dl_fc_history(start, end):
    os.makedirs('food_club', exist_ok=True)
    nfc = NeoPage(base_url='http://neofoodclub.fr')
    for cur_round in range(start, end + 1):
        print(f'Grabbing round {cur_round} from neofoodclub')
        nfc.get(f'/rounds/{cur_round}.json')
        nfc.save_to_file(f'food_club/{cur_round}.json')
        time.sleep(2.0)
Esempio n. 12
0
def dl_fc_history(start, end):
    os.makedirs('food_club', exist_ok=True)
    nfc = NeoPage(base_url='http://neofoodclub.fr')
    for cur_round in range(start, end+1):
        print(f'Grabbing round {cur_round} from neofoodclub')
        nfc.get(f'/rounds/{cur_round}.json')
        nfc.save_to_file(f'food_club/{cur_round}.json')
        time.sleep(2.0)
Esempio n. 13
0
def apple_bobbing():
    np = NeoPage(path)
    if np.contains('Give it a shot!'):
        np.get(path, bobbing=1)
        message = np.search("<div id='bob_middle'>(.*?)</div>")[1].strip()
        message = strip_tags(message)
        print(message)
    elif np.contains('blind underneath this hat'):
        print('Already apple bobbed today.')
    else:
        print("Couldn't find apple bobbing.")
Esempio n. 14
0
def set_shop_prices():
    np = NeoPage()

    g.items_stocked.clear()
    lim = 30
    ub_count = 0
    total_prices = 0
    while True:
        np.get('/market.phtml', 'order_by=id', 'type=your', f'lim={lim}')
        has_next = "<input type='submit' name='subbynext' value='Next 30'>" in np.content
        args = []
        args.append('type=update_prices')
        args.append('order_by=')
        args.append('view=')
        results = shop_item_re.findall(np.content)
        changed = False
        for (name, image, stock, category, obj_id_key, obj_id_val, old_cost_key,
                old_price, cost_key, desc, back_to_inv_key) in results:
            stock = int(stock)
            old_price = int(old_price)
            obj_id_val = int(obj_id_val)
            args.append(f'{obj_id_key}={obj_id_val}')
            args.append(f'{old_cost_key}={old_price}')

            g.items_stocked[obj_id_val] = stock

            my_price = old_price
            try:
                true_price = item_db.get_price(name, image, max_laxness=4, max_age=timedelta(days=7))
                if true_price == None:
                    pass
                elif type(true_price) == dict:
                    print(f'Warning: {name} has multiple forms: {true_price}')
                elif true_price >= 1000000:
                    ub_count += 1
                    print(f'Warning: {name} is unbuyable')
                    my_price = 0
                else:
                    my_price = true_price - 1
            except item_db.ShopWizardBannedException:
                pass
            if my_price != old_price:
                print(f'Setting {name} from {old_price} to {my_price} NP')
                changed = True
            total_prices += my_price
            args.append(f'{cost_key}={my_price}')
            args.append(f'{back_to_inv_key}=0')
        args.append('obj_name=')
        if changed:
            np.post('/process_market.phtml', *args)
        lim += 30
        if not has_next:
            break
    print(f'Shop has {total_prices} NP worth of items for sale ({ub_count} unbuyable)')
Esempio n. 15
0
def apple_bobbing():
    np = NeoPage(path)
    if np.contains('Give it a shot!'):
        np.get(path, bobbing=1)
        message = np.search("<div id='bob_middle'>(.*?)</div>")[1].strip()
        message = strip_tags(message)
        print(message)
    elif np.contains('blind underneath this hat'):
        print('Already apple bobbed today.')
    else:
        print("Couldn't find apple bobbing.")
Esempio n. 16
0
def list_items():
    np = NeoPage()
    np.get('/inventory.phtml')
    items = np.findall(r'\n<td class=.*?>.*?</td>')
    for item in items:
        attr = re.search(r'<td class="(.*?)"><a href="javascript:;" onclick="openwin\((\d+)\);"><img src="http://images.neopets.com/items/(.*?)" width="80" height="80" title="(.*?)" alt="(.*?)" border="0" class="(.*?)"></a><br>(.*?)(<hr noshade size="1" color="#DEDEDE"><span class="attr medText">(.*?)</span>)?</td>', item, flags=re.DOTALL)
        item_id = attr[2]
        item_image = attr[3]
        item_desc = attr[4]
        item_name = attr[7]
        item_db.update_item(item_name, image=item_image, desc=item_desc)
Esempio n. 17
0
def expellibox():
    np = NeoPage(base_url=base_url)
    np.get(path)
    rand = random.randint(1, 99999)
    np.post(f'/games/giveaway/process_giveaway.phtml?r=rand', 'onData=[type Function]')
    log = open('expellibox.log', 'a')
    result = parse_qs(np.content)
    success = result['success']
    prize_id = result['prize_id']
    msg = result['msg']
    print(rand, result)
    log.write(f'{rand},{result}\n')
Esempio n. 18
0
def expellibox():
    np = NeoPage(base_url=base_url)
    np.get(path)
    rand = random.randint(1, 99999)
    np.post(f'/games/giveaway/process_giveaway.phtml?r=rand',
            'onData=[type Function]')
    log = open('expellibox.log', 'a')
    result = parse_qs(np.content)
    success = result['success']
    prize_id = result['prize_id']
    msg = result['msg']
    print(rand, result)
    log.write(f'{rand},{result}\n')
Esempio n. 19
0
def ensure_np(amount):
    # Withdraws from the bank to get up at least [amount] NP.
    np = NeoPage()
    np.get('/bank.phtml')
    if np.contains('Collect Interest ('):
        bank_interest.bank_interest()
    nps = np.current_np()
    if nps >= amount: return
    need = amount - nps
    denom = 10**max(len(str(need)), len(str(amount)))
    need = (need // denom + 1) * denom
    np.post('/process_bank.phtml', 'type=withdraw', f'amount={need}')
    print(f'Withdrawing {need} NP')
Esempio n. 20
0
def ensure_np(amount):
    # Withdraws from the bank to get up at least [amount] NP.
    np = NeoPage()
    np.get('/bank.phtml')
    if np.contains('Collect Interest ('):
        bank_interest.bank_interest()
    nps = np.current_np()
    if nps >= amount: return
    need = amount - nps
    denom = 10**max(len(str(need)), len(str(amount)))
    need = (need // denom + 1) * denom
    np.post('/process_bank.phtml', 'type=withdraw', f'amount={need}')
    print(f'Withdrawing {need} NP')
Esempio n. 21
0
def list_items():
    np = NeoPage()
    np.get('/inventory.phtml')
    items = np.findall(r'\n<td class=.*?>.*?</td>')
    for item in items:
        attr = re.search(
            r'<td class="(.*?)"><a href="javascript:;" onclick="openwin\((\d+)\);"><img src="http://images.neopets.com/items/(.*?)" width="80" height="80" title="(.*?)" alt="(.*?)" border="0" class="(.*?)"></a><br>(.*?)(<hr noshade size="1" color="#DEDEDE"><span class="attr medText">(.*?)</span>)?</td>',
            item,
            flags=re.DOTALL)
        item_id = attr[2]
        item_image = attr[3]
        item_desc = attr[4]
        item_name = attr[7]
        item_db.update_item(item_name, image=item_image, desc=item_desc)
Esempio n. 22
0
def withdraw_sdb(item):
    # Withdraws item from SDB.
    np = NeoPage()
    np.get('/safetydeposit.phtml', f'obj_name={item}', 'category=')
    items = re.findall(r'''<td align="center"><img src="http://images.neopets.com/items/(.*?)" height="80" width="80" alt="" border="1"></td>\n<td align="left"><b>(.*?)<br><span class="medText"></span></b></td>\n<td width="350" align="left"><i>(.*?)</i></td>\n<td align="left"><b>(.*?)</b></td>\n<td align="center"><b>(.*?)</b></td>\n<td align="center" nowrap>\n.*<input type='text' name='back_to_inv\[(.*?)\]' size=3 value='0' data-total_count='(.*?)' class='remove_safety_deposit' data-remove_val='n' ><br>\n.*<a href="javascript:onClick=passPin\((.*?),(.*?),'(.*?)','(.*?)'\);" class="medText">Remove One</a></td>
</tr>''', np.content)
    for img, name, desc, cat, quant, _, _, offset, obj_info_id, obj_name, category in items:
        print(f'Have {quant}x {name}')
        if name == item:
            np.get('/process_safetydeposit.phtml', f'offset={offset}', f'remove_one_object={obj_info_id}', f'obj_name={obj_name}', f'category={category}', 'pin=')
            print('Took one.')
            break
    else:
        print(f'No {item} in SDB.')
Esempio n. 23
0
def stats():
    np = NeoPage()
    np.get(path)
    tbl = np.search(r'<table align=center cellpadding=3 cellspacing=0 border=0>(.*?)</table>')[0]
    rows = util.table_to_tuples(tbl)

    freqs = {i: 0 for i in range(1, 31)}
    for date, prize, winners, share, matches_needed, numbers in rows[1:]:
        nums = map(int, numbers.split(','))
        for n in nums:
            freqs[n] += 1

    for n, freq in sorted(freqs.items()):
        print(f'{n}, {freq}')
Esempio n. 24
0
def food_club_old():
    np = NeoPage(path)
    np.get(path, 'type=bet')
    arenas = np.findall(r"<script language='javascript'>(.*?)</script>")
    for i, arena in enumerate(arenas[:5]):
        pirates = arena.strip().splitlines()
        pirate_odds = []
        for pirate in pirates:
            tokens = pirate.split()
            pirate_id = int(tokens[0].split('[')[1][:-1])
            odds = int(tokens[2][:-1])
            pirate_odds.append((pirate_id, odds))
        print(f'Arena {i}: {pirate_odds}')
        ar = sum(1 / x for _, x in pirate_odds)
        print(ar)
Esempio n. 25
0
def ensure_np(amount):
    # Withdraws from the bank to get up at least [amount] NP.
    np = NeoPage()
    np.get('/bank.phtml')
    if np.contains('Collect Interest ('):
        bank_interest.bank_interest()
    nps = np.search(
        r'''<a id='npanchor' href="/inventory.phtml">(.*?)</a>''')[1]
    nps = int(nps.replace(',', ''))
    if nps >= amount: return
    need = amount - nps
    denom = 10**max(len(str(need)), len(str(amount)))
    need = (need // denom + 1) * denom
    np.post('/process_bank.phtml', 'type=withdraw', f'amount={need}')
    print(f'Withdrawing {need} NP')
Esempio n. 26
0
def quickstock(exclude=[]):
    # First list items to add them to the item db
    np = NeoPage()
    list_items()
    np.get('/quickstock.phtml')
    items = np.findall(r'''<TD align="left">(.*?)</TD><INPUT type="hidden"  name="id_arr\[(.*?)\]" value="(\d+?)">''')
    args = []
    args.append('buyitem=0')
    for name, idx, item_id in items:
        args.append(f'id_arr[{idx}]={item_id}')
        if name in exclude: continue
        policy = item_policy[name]
        if policy:
            args.append(f'radio_arr[{idx}]={policy}')
    np.post('/process_quickstock.phtml', *args)
Esempio n. 27
0
def food_club_old():
    np = NeoPage(path)
    np.get(path, 'type=bet')
    arenas = np.findall(r"<script language='javascript'>(.*?)</script>")
    for i,arena in enumerate(arenas[:5]):
        pirates = arena.strip().splitlines()
        pirate_odds = []
        for pirate in pirates:
            tokens = pirate.split()
            pirate_id = int(tokens[0].split('[')[1][:-1])
            odds = int(tokens[2][:-1])
            pirate_odds.append((pirate_id, odds))
        print(f'Arena {i}: {pirate_odds}')
        ar = sum(1/x for _,x in pirate_odds)
        print(ar)
Esempio n. 28
0
def deposit_all_items(exclude=[]):
    # First list items to add them to the item db
    np = NeoPage()
    list_items()
    np.get('/quickstock.phtml')
    items = np.findall(
        r'''<TD align="left">(.*?)</TD><INPUT type="hidden"  name="id_arr\[(.*?)\]" value="(\d+?)">'''
    )
    args = []
    args.append('buyitem=0')
    for name, idx, item_id in items:
        args.append(f'id_arr[{idx}]={item_id}')
        if name not in exclude:
            args.append(f'radio_arr[{idx}]=deposit')
    np.post('/process_quickstock.phtml', *args)
Esempio n. 29
0
def withdraw_sdb(item):
    # Withdraws item from SDB.
    np = NeoPage()
    np.get('/safetydeposit.phtml', f'obj_name={item}', 'category=')
    items = re.findall(
        r'''<td align="center"><img src="http://images.neopets.com/items/(.*?)" height="80" width="80" alt="" border="1"></td>\n<td align="left"><b>(.*?)<br><span class="medText"></span></b></td>\n<td width="350" align="left"><i>(.*?)</i></td>\n<td align="left"><b>(.*?)</b></td>\n<td align="center"><b>(.*?)</b></td>\n<td align="center" nowrap>\n.*<input type='text' name='back_to_inv\[(.*?)\]' size=3 value='0' data-total_count='(.*?)' class='remove_safety_deposit' data-remove_val='n' ><br>\n.*<a href="javascript:onClick=passPin\((.*?),(.*?),'(.*?)','(.*?)'\);" class="medText">Remove One</a></td>
</tr>''', np.content)
    for img, name, desc, cat, quant, _, _, offset, obj_info_id, obj_name, category in items:
        print(f'Have {quant}x {name}')
        if name == item:
            np.get('/process_safetydeposit.phtml', f'offset={offset}',
                   f'remove_one_object={obj_info_id}', f'obj_name={obj_name}',
                   f'category={category}', 'pin=')
            print('Took one.')
            break
    else:
        print(f'No {item} in SDB.')
Esempio n. 30
0
def list_items():
    np = NeoPage()
    np.get('/inventory.phtml')
    items = np.findall(r'\n<td class=.*?>.*?</td>')
    for item in items:
        attr = re.search(
            r'<td class="(.*?)"><a href="javascript:;" onclick="openwin\((\d+)\);"><img src="http://images.neopets.com/items/(.*?)" width="80" height="80" title="(.*?)" alt="(.*?)" border="0" class="(.*?)"></a><br>(.*?)(<hr noshade size="1" color="#DEDEDE"><span class="attr medText">(.*?)</span>)?</td>',
            item)
        item_id = attr[2]
        item_image = attr[3]
        item_desc = attr[4]
        item_name = attr[7]

        item_db.query(
            '''
        INSERT INTO items (name,image,desc,last_updated)
        VALUES (?,?,?,datetime('now'))
        ON CONFLICT (name,image) DO UPDATE SET desc=?, last_updated=datetime('now')
        ''', item_name, item_image, item_desc, item_desc)
Esempio n. 31
0
def lottery():
    numbers_left = {n:4 for n in numbers}
    tickets = []
    for _ in range(n_tickets):
        min_left = min(numbers_left.values())
        population = [k for k, v in numbers_left.items() if v > min_left]
        #population = numbers
        if len(population) < N:
            population = [k for k, v in numbers_left.items() if v >= min_left]
        ticket = tuple(sorted(random.sample(population, N)))
        tickets.append(ticket)
    print(tickets)
    print(evaluate(tickets))

    np = NeoPage()
    np.get(path)
    ref = np.referer
    for ticket in tickets:
        np.set_referer(ref)
        np.post(path_process, *[f'{x}={n}' for x, n in zip('one two three four five six'.split(), ticket)])
Esempio n. 32
0
def faerieland_jobs(jobs_to_do):
    np = NeoPage()
    np.get(path, 'type=jobs', 'voucher=basic')
    start = 0
    jobs_by_profit = []
    try:
        while jobs_to_do > 0:
            jobs = job_re.findall(np.content)
            has_more_pages = bool(re.search('<A HREF="employment.phtml.*?">Next 10</A>', np.content))
            for image, job_link, count, name, prize in jobs:
                count = int(count)
                prize = util.amt(prize)
                revenue = prize * 1.25
                if revenue < MIN_PROFIT:
                    print(f'Skipping {name} (can only make {revenue})')
                    continue

                price = item_db.get_price(name, image)
                profit = revenue - count * price
                print(f'Can profit by about {profit} NP: Buy {count}x {name} ({price} NP each), turn in for {revenue}')
                bisect.insort(jobs_by_profit, (profit, name, count, job_link))
                if profit < MIN_PROFIT:
                    continue
                print('Taking the job!')
                
                true_cost = inventory.purchase(name, image=image, budget=revenue - MIN_PROFIT, quantity=count)
                if not true_cost:
                    print(f'Failed to acquire all the items within budget')
                    continue

                # Do the job!
                np.get(f'/faerieland/employ/{job_link}')
                if 'Good job! You got all the items' in np.content:
                    prize = re.search(r'You have been paid <b>(.*?) Neopoints</b>.', np.content)[1]
                    prize = util.amt(prize)
                    print(f'Turned in {count}x {name} for {prize} NP. (Profit: {prize - true_cost})')
                elif 'You got the job!' in np.content:
                    print(f'Job was not completed before applying? TODO')
                    print(np.last_file_path)
                    return
                else:
                    print(f'Error applying for job. TODO')
                    print(np.last_file_path)
                    return
                jobs_to_do -= 1
                if jobs_to_do <= 0:
                    return

            if has_more_pages:
                start += 10
                np.get(path, 'type=jobs', 'voucher=basic', f'start={start}')
            else:
                break
    except item_db.ShopWizardBannedException:
        return

    print(jobs_by_profit)
    print('Did not find enough appropriate jobs.')
Esempio n. 33
0
def jhudora_quest():
    np = NeoPage(save_pages=True)
    np.get(path)

    if 'I Accept!' in np.content:
        # TODO: Search your SDB, gallery, shop, and Neohome Superstore for item as well.
        user = os.environ['NP_USER']
        np.post(path_process, 'type=accept', f'username={user}')
        m = re.search(r"<br>Where is my <b>(.*?)</b>\?<p><img src='http://images.neopets.com/items/(.*?)'.*?>", np.content)
        item = m[1]
        image = m[2]
        print(f'Jhudora asked for {item} ({image})')
        cost = inventory.purchase(item, image=image)
        print(f'Bought it for {cost} NP.')
        np.set_referer_path(path)
        np.post(path_process, 'type=finished')
        if 'You have completed' in np.content:
            print(f'Quest shouuuuld be completed?')
        else:
            print(f"Quest doesn't seem to have completed")
    elif 'I am not ready' in np.content:
        print("Too early for Jhudora's Quest.")
    else:
        print("Jhudora's quest: Error!")
Esempio n. 34
0
def gen_restock_list(cat):
    np = NeoPage(base_url='https://items.jellyneo.net')
    path = '/search/'
    args = []
    args.append(f'cat[]={cat}')

    args.append('min_rarity=1')
    args.append('max_rarity=100')
    args.append('status=1')

    args.append('sort=5')
    args.append('sort_dir=desc')

    start = 0
    while True:
        np.get(path, *args, f'start={start}')
        time.sleep(min(60, random.expovariate(30)) + 60)
        last_page = not re.search(
            r'<li class="arrow"><a href=".*?">&raquo;</a>', np.content)
        referer = np.referer
        results = re_jn_item.findall(np.content)
        for item_id, name, price_updated, price in results:
            if price == 'Inflation Notice':
                np.set_referer(referer)
                np.get(f'/item/{item_id}')
                time.sleep(min(60, random.expovariate(30)) + 60)
                price = re.search('<div class="price-row">(.*?) NP',
                                  np.content)[1]
            try:
                price = lib.amt(price)
            except (ValueError, TypeError, IndexError):
                # safe assumption that unpriceable items are at least 10M NP?
                price = 10000001
            print(f'\'{name}\': {price},')
        start += 50
        if last_page: break
Esempio n. 35
0
def shapeshifter(timeout=10 * 60):
    np = NeoPage()
    np.get(path_index)
    starting_np = np.current_np()
    if np.contains('Continue Game!'):
        np.get(path_game)
    elif np.contains('Start Game!'):
        np.post(path_process, f'type=init')

    # Just in case we won but left it in the completed state
    if np.contains('You Won!') or np.contains('You Lost!'):
        np.post(path_process + '?type=init')

    tbl = np.search(r'''<table border=1 bordercolor='gray'>(.*?)</table>''')[1]
    imgs = re.findall(
        r'''<img src='(.*?)' border=0 name='i_'>(<br><b><small>GOAL</small></b></td>)?''',
        tbl)
    imgs = imgs[:-1]
    N = len(imgs)
    goal_idx = next(i for i, (_, goal) in enumerate(imgs) if goal)
    to_idx = {img: i for i, (img, _) in enumerate(imgs)}

    tbl = np.search(
        r'''<table align=center cellpadding=0 cellspacing=0 border=0>(.*?)</table>'''
    )[1]
    goal_grid = []
    for row in re.findall(r'''<tr>(.*?)</tr>''', tbl, flags=re.DOTALL):
        imgs = re.findall(r'''<img src='(.*?)' .*?>''', row)
        goal_row = [to_idx[img] for img in imgs]
        goal_grid.append(goal_row)

    tbl = np.search(
        r'''<center><b><big>ACTIVE SHAPE</big></b><p>(.*?)</table>\n''')[1]
    shape_grids = []
    for shape_info in re.findall(r'''<table.*?>(.*?)</table>''', tbl):
        grid = []
        for row_info in re.findall(r'''<tr>(.*?)</tr>''', shape_info):
            tiles = re.findall(r'''<td.*?>(.*?)</td>''', row_info)
            grid.append(
                [int('square.gif' in tile_info) for tile_info in tiles])
        shape_grids.append(grid)

    # Compute kvho difficulty.
    R = len(goal_grid)
    C = len(goal_grid[0])
    min_shifts_needed = R * C * (N - 1) - sum(map(sum, goal_grid))
    shifts_available = sum(
        sum(sum(rows) for rows in grid) for grid in shape_grids)
    num_overshifts = shifts_available - min_shifts_needed
    num_flips = num_overshifts // N
    print(f'Puzzle permits {num_flips} flips ({num_overshifts} overshifts)')

    kvho_input = make_kvho_input(goal_grid, shape_grids, goal_idx)

    print(f'Waiting for kvho.')
    start_time = datetime.now()

    positions = []
    try:
        proc = subprocess.run(['c/ss'],
                              input=kvho_input,
                              encoding='utf-8',
                              capture_output=True,
                              timeout=timeout)
        for line in proc.stdout.splitlines():
            if 'x' in line and '=' in line:
                x = list(
                    map(
                        int,
                        line.replace('x', ' ').replace('=',
                                                       ' ').strip().split()))
                for c, r, _ in zip(x[::3], x[1::3], x[2::3]):
                    positions.append((r, c))
        print(f'Solution found in {datetime.now() - start_time}: {positions}')
    except subprocess.TimeoutExpired:
        print(
            f'Solution not found in time. Throwing this puzzle to get a new one.'
        )
        for _ in shape_grids:
            positions.append((0, 0))

    for i, (shape, (r, c)) in enumerate(zip(shape_grids, positions)):
        print(f'\rPlacing piece {i+1}/{len(positions)}', end='')
        np.set_referer_path(path_game)
        np.get(path_process, 'type=action', f'posx={c}', f'posy={r}')
        time.sleep(0.5)
    print()

    if np.contains('You Won!'):
        np.set_referer_path(path_game)
        np.post(path_process + '?type=init')
        ending_np = np.current_np()
        print(f'Done level, earned {ending_np - starting_np} NP')
        return 1
    elif np.contains('reached your max neopoints'):
        print('Done for today.')
        return 2
    else:
        print('Did not solve level??')
        return 0
Esempio n. 36
0
def battledome(forever=False):
    np = NeoPage(path)
    np.get(path_arena)
    neopoints_left = True
    prizes_left = True
    while prizes_left or forever:
        battle_id = None
        if np.contains('battleid:'):
            print('Battledome: Already in fight.')
            battle_id = np.search(r"battleid:'(\d+)',")[1]
        else:
            print('Battledome: Starting fight.')
            np.post(path_start_fight, 'type=2', f'pet={PET_NAME}',
                    f'npcId={npc_id}', f'toughness={toughness}')
            battle = json.loads(np.content)
            if not battle['success']:
                print('Battledome: Error.')
                return
            battle_id = battle['battle']['id']
        time.sleep(2)
        np.set_referer_path(path)
        np.get(path_arena)
        ts = int(time.time() * 1000)
        for step in itertools.count():
            intro = 1 if step == 0 else 0
            np.set_referer_path(path_arena)
            np.post(path_arena_ajax, f'battleid={battle_id}', f'step={step}',
                    f'intro={intro}', 'status=1')
            resp = json.loads(np.content)
            abils = resp['p1']['abils']
            chosen_abil = ''
            for abil in ['21', '2', '14', '17', '1']:
                if abil in abils and not abils[abil]['hasCooldown']:
                    chosen_abil = abil
                    break
            items = re.findall(
                r'<li><img.*?id="(\d+)".*?title="(.*?)".*?/></li>',
                resp['p1']['items'])
            item1id = items[0][0]
            item2id = items[1][0]
            opts = []
            opts.append(f'p1s=')
            opts.append(f'eq1={item1id}')
            opts.append(f'eq2={item2id}')
            opts.append(f'p1a={chosen_abil}')
            opts.append(f'chat=')
            opts.append('action=attack')
            opts.append(f'ts={ts}')
            opts.append(f'battleid={battle_id}')
            opts.append(f'step={step}')
            opts.append(f'intro=0')
            opts.append('status=1')
            print(
                f'Battledome: Attacking with {items[0][1]} and {items[1][1]}')
            np.set_referer_path(path_arena)
            np.post(path_arena_ajax, *opts)
            resp = json.loads(np.content)
            if resp['battle']['prizes'] or 'prize_messages' in resp['battle']:
                prizes = ', '.join(
                    x['name'] for x in resp['battle']['prizes']) or "nothing"
                print(f'Battledome: Won {prizes}')
                if 'prize_messages' in resp['battle']:
                    prize_messages = resp['battle']['prize_messages']
                    if any('reached the item limit' in m
                           for m in prize_messages):
                        prizes_left = False
                    if any('reached the NP limit' in m
                           for m in prize_messages):
                        neopoints_left = False
                    print(f'Battledome: {prize_messages}')
                break
            # TODO: Detect defeat.
            elif step > 5:
                print(
                    f'Battledome: Took more than 5 steps. Something went wrong.'
                )
Esempio n. 37
0
def faerieland_jobs(jobs_to_do):
    np = NeoPage()
    np.get(path, 'type=jobs', 'voucher=basic')
    start = 0
    jobs_by_profit = []
    try:
        while jobs_to_do > 0:
            jobs = job_re.findall(np.content)
            has_more_pages = bool(
                re.search('<A HREF="employment.phtml.*?">Next 10</A>',
                          np.content))
            for image, job_link, count, name, prize in jobs:
                count = int(count)
                prize = util.amt(prize)
                revenue = prize * 1.25
                if revenue < MIN_PROFIT:
                    print(f'Skipping {name} (can only make {revenue})')
                    continue

                price = item_db.get_price(name, image)
                profit = revenue - count * price
                print(
                    f'Can profit by about {profit} NP: Buy {count}x {name} ({price} NP each), turn in for {revenue}'
                )
                bisect.insort(jobs_by_profit, (profit, name, count, job_link))
                if profit < MIN_PROFIT:
                    continue
                print('Taking the job!')

                true_cost = inventory.purchase(name,
                                               image=image,
                                               budget=revenue - MIN_PROFIT,
                                               quantity=count)
                if not true_cost:
                    print(f'Failed to acquire all the items within budget')
                    continue

                # Do the job!
                np.get(f'/faerieland/employ/{job_link}')
                if 'Good job! You got all the items' in np.content:
                    prize = re.search(
                        r'You have been paid <b>(.*?) Neopoints</b>.',
                        np.content)[1]
                    prize = util.amt(prize)
                    print(
                        f'Turned in {count}x {name} for {prize} NP. (Profit: {prize - true_cost})'
                    )
                elif 'You got the job!' in np.content:
                    print(f'Job was not completed before applying? TODO')
                    print(np.last_file_path)
                    return
                else:
                    print(f'Error applying for job. TODO')
                    print(np.last_file_path)
                    return
                jobs_to_do -= 1
                if jobs_to_do <= 0:
                    return

            if has_more_pages:
                start += 10
                np.get(path, 'type=jobs', 'voucher=basic', f'start={start}')
            else:
                break
    except item_db.ShopWizardBannedException:
        return

    print(jobs_by_profit)
    print('Did not find enough appropriate jobs.')
Esempio n. 38
0
def food_club():
    np = NeoPage()
    np.get(path, 'type=bet')
    if np.contains('All betting gates are now closed!'):
        print(f"Dangit, we're late.")
        return
    maxbet = util.amt(re.search(r'You can only place up to <b>(.*?)</b> NeoPoints per bet', np.content)[1])
    print(f'Max bet is {maxbet}')

    # We compute the current round number because it seems there's no way to
    # find it explicitly unless you actually make a bet.
    day = int(re.search(r'Next match: <b>.*?</b> the <b>(\d+).*?</b> at <b>02:00 PM NST</b>', np.content)[1])
    date = neotime.now_nst().replace(day=day, hour=14, minute=0, second=0)
    epoch = datetime(2018, 10, 7, 14, 0, 0)
    from_epoch = round((date - epoch) / timedelta(days=1))
    cur_round = 7093 + from_epoch
    print(f'Food Club round {cur_round}')

    dl_fc_history(cur_round - 1, cur_round)
    table = stats()
    rnd = get_rounds(table[table['round'] == cur_round])[0]

    for i, arena in enumerate(arena_names):
        participants = ', '.join(pirate_names[p.pirate] for p in rnd.pirates[i])
        print(f'{arena} Arena: {participants}')

    bets = maxter_strategy(rnd, 1000000 / maxbet)
    total_bet_amt = 0
    total_exp_win = 0
    TER = 0
    for exp_win, spend, bet in bets:
        if exp_win < 1.0:
            print('Not making -EV bet: {bet}')
            continue
        bet_amt = round(spend * maxbet)
        print(f'Bet {bet_amt} NP on {bet}. EV: {exp_win * bet_amt:.1f} NP')
        opts = []
        total_odds = 1
        for i, (ps, b) in enumerate(zip(rnd.pirates, bet)):
            if b == None:
                continue
            ps[b].pirate
            opts.append(f'winner{i+1}={ps[b].pirate}')
            opts.append(f'matches[]={i+1}')
            total_odds *= ps[b].closing_odds
        opts.append(f'bet_amount={bet_amt}')
        opts.append(f'total_odds={total_odds}')
        opts.append(f'winnings={bet_amt * total_odds}')
        opts.append('type=bet')
        np.post('/pirates/process_foodclub.phtml', *opts)
        total_bet_amt += bet_amt
        total_exp_win += bet_amt * exp_win
        TER += exp_win

    print(f'Made {total_bet_amt} NP of bets. Expect to win {total_exp_win:.1f} NP. (TER {TER:.2f}; ROI {total_exp_win / total_bet_amt:.3f})')

    np.get('/pirates/foodclub.phtml', 'type=collect')
    if np.contains("<input type='submit' value='Collect Your Winnings!'>"):
        tbl = np.search(r"<table border='0' .*?>(.*?)</table>")[1]
        tuples = util.table_to_tuples(tbl)
        earliest_rnd = int(tuples[2][0])
        total_winnings = tuples[-1][-1]
        print(f'Note: We have {total_winnings} winnings dating from round {earliest_rnd}.')
        if cur_round - earliest_rnd >= 7:
            print(f'Should collect winnings before they vanish!')
Esempio n. 39
0
def food_club():
    np = NeoPage()
    np.get(path, 'type=bet')
    if np.contains('All betting gates are now closed!'):
        print(f"Dangit, we're late.")
        return
    maxbet = util.amt(
        re.search(r'You can only place up to <b>(.*?)</b> NeoPoints per bet',
                  np.content)[1])
    print(f'Max bet is {maxbet}')

    # We compute the current round number because it seems there's no way to
    # find it explicitly unless you actually make a bet.
    day = int(
        re.search(
            r'Next match: <b>.*?</b> the <b>(\d+).*?</b> at <b>02:00 PM NST</b>',
            np.content)[1])
    date = neotime.now_nst().replace(day=day, hour=14, minute=0, second=0)
    epoch = datetime(2018, 10, 7, 14, 0, 0)
    from_epoch = round((date - epoch) / timedelta(days=1))
    cur_round = 7093 + from_epoch
    print(f'Food Club round {cur_round}')

    dl_fc_history(cur_round - 1, cur_round)
    table = stats()
    rnd = get_rounds(table[table['round'] == cur_round])[0]

    for i, arena in enumerate(arena_names):
        participants = ', '.join(pirate_names[p.pirate]
                                 for p in rnd.pirates[i])
        print(f'{arena} Arena: {participants}')

    bets = maxter_strategy(rnd, 1000000 / maxbet)
    total_bet_amt = 0
    total_exp_win = 0
    TER = 0
    for exp_win, spend, bet in bets:
        if exp_win < 1.0:
            print('Not making -EV bet: {bet}')
            continue
        bet_amt = round(spend * maxbet)
        print(f'Bet {bet_amt} NP on {bet}. EV: {exp_win * bet_amt:.1f} NP')
        opts = []
        total_odds = 1
        for i, (ps, b) in enumerate(zip(rnd.pirates, bet)):
            if b == None:
                continue
            ps[b].pirate
            opts.append(f'winner{i+1}={ps[b].pirate}')
            opts.append(f'matches[]={i+1}')
            total_odds *= ps[b].closing_odds
        opts.append(f'bet_amount={bet_amt}')
        opts.append(f'total_odds={total_odds}')
        opts.append(f'winnings={bet_amt * total_odds}')
        opts.append('type=bet')
        np.post('/pirates/process_foodclub.phtml', *opts)
        total_bet_amt += bet_amt
        total_exp_win += bet_amt * exp_win
        TER += exp_win

    print(
        f'Made {total_bet_amt} NP of bets. Expect to win {total_exp_win:.1f} NP. (TER {TER:.2f}; ROI {total_exp_win / total_bet_amt:.3f})'
    )

    np.get('/pirates/foodclub.phtml', 'type=collect')
    if np.contains("<input type='submit' value='Collect Your Winnings!'>"):
        tbl = np.search(r"<table border='0' .*?>(.*?)</table>")[1]
        tuples = util.table_to_tuples(tbl)
        earliest_rnd = int(tuples[2][0])
        total_winnings = tuples[-1][-1]
        print(
            f'Note: We have {total_winnings} winnings dating from round {earliest_rnd}.'
        )
        if cur_round - earliest_rnd >= 7:
            print(f'Should collect winnings before they vanish!')
Esempio n. 40
0
def update_prices(item_name, laxness=1):
    char_groups = 'an0 bo1 cp2 dq3 er4 fs5 gt6 hu7 iv8 jw9 kx_ ly mz'.split()
    c2g = dict(sum(([(c, i) for c in cs] for i, cs in enumerate(char_groups)), []))
    markets = defaultdict(dict)
    ub_count = 0
    search_count = 0

    np = NeoPage('/market.phtml?type=wizard')
    opts = []
    opts.append('type=process_wizard')
    opts.append('feedset=0')
    opts.append(f'shopwizard={item_name}')
    opts.append('table=shop')
    opts.append('criteria=exact')
    opts.append('min_price=0')
    opts.append('max_price=999999')

    # Repeatedly search the shop wizard, collecting all results seen.
    while not markets or any(len(market_data) < len(char_groups) - laxness for market_data in markets.values()):
        print(f'\r({sum(len(md) for md in markets.values())}/{len(markets) * len(char_groups)}) ', end='')
        np.post('/market.phtml', *opts)
        tbl = np.search(r'<table width="600".*?>(.*?)</table>')
        if not tbl:
            if np.contains('Whoa there, too many'):
                print('Shop wizard banned.')
                raise ShopWizardBannedException
            ub_count += 1
            if ub_count >= 5: break
            continue
        tbl = tbl[1]
        rows = lib.table_to_tuples(tbl, raw=True)[1:]
        search_count += 1
        if search_count >= 50: break
        market_data = []
        obj_info_id = None
        for owner, item, stock, price in rows:
            result = re.search(r'<a href="(.*?)"><b>(.*?)</b></a>', owner)
            link = result[1]
            owner = result[2]
            result = re.search(r'/browseshop.phtml\?owner=(.*?)&buy_obj_info_id=(.*?)&buy_cost_neopoints=(\d+)', link)
            obj_info_id = int(result[2])
            price = lib.amt(lib.strip_tags(price))
            stock = lib.amt(stock)
            market_data.append((price, stock, link))
        g = c2g[lib.strip_tags(rows[0][0])[0]]
        markets[obj_info_id][g] = market_data

    level2_by_item = {}
    # Consolidate results for each item into a quote.

    if markets:
        for obj_info_id, market_data in markets.items():
            # TODO: Check suspiciously cheap prices to see if owners are frozen.
            level2 = sorted(sum(market_data.values(), []))
            level2_by_item[obj_info_id] = level2
            # The price of an item for our purposes is the price of the 2nd
            # cheapest item in the market.
            cur_amt = 0
            cur_price = UNBUYABLE_PRICE
            for price, stock, link in level2:
                cur_price = price
                cur_amt += stock
                if cur_amt >= 2:
                    break
            print(f'The price of {item_name} (id {obj_info_id}) is {cur_price} NP.')
            cur_amt = 0
            for price, stock, link in level2:
                cur_amt += stock
                if cur_amt >= 30:
                    break
            c = conn.cursor()
            c.execute('''
            SELECT name FROM items WHERE obj_info_id=?
            ''', (obj_info_id,))
            result = c.fetchone()
            if not result or result[0][0] != item_name:
                for market_data in level2:
                    # Visit the shop and populate a bunch of fields
                    np.get(market_data[2])
                    res = np.search(r'''<A href=".*?" onClick=".*?"><img src="http://images.neopets.com/items/(.*?)" .*? title="(.*?)" border="1"></a> <br> <b>(.*?)</b>''')
                    if not res:
                        print(f'{market_data[2]} is froze?')
                        continue
                    image = res[1]
                    desc = res[2]
                    name = res[3]
                    c.execute('''
                    INSERT INTO items (name, image, desc, obj_info_id, last_updated)
                    VALUES (?, ?, ?, ?, datetime('now'))
                    ON CONFLICT (name, image)
                    DO UPDATE SET desc=?, obj_info_id=?, last_updated=datetime('now')
                    ''', (name, image, desc, obj_info_id, desc, obj_info_id))
                    print(f'The object id of {name} is {obj_info_id}')
                    break
                else:
                    print('Unable to find legit seller for {obj_info_id}. Will not store it in itemdb.')
                    continue
            c.execute('''
            UPDATE items SET price=?, price_last_updated=datetime('now') WHERE obj_info_id=?
            ''', (cur_price, obj_info_id))
    else:
        print(f'It seems {item_name} is unbuyable.')
        # Item could not be found; assume it's unbuyable.
        # We use a cheap price estimate of 1,000,001 NP.
        # TODO: Items inserted in this way will have a wonky image property.
        c = conn.cursor()
        c.execute('''
        INSERT INTO items (name, image, last_updated, price, price_last_updated)
        VALUES (?, NULL, datetime('now'), 1000001, datetime('now'))
        ON CONFLICT (name, image)
        DO UPDATE SET last_updated=datetime('now'), price=1000001, price_last_updated=datetime('now')
        ''', (item_name,))

    conn.commit()
    return level2_by_item
Esempio n. 41
0
def fetch(verbose=False):
    log = open('fetch.log', 'a')
    np = NeoPage()
    # TODO: Figure out how to continue on from existing game.
    np.get(path, 'deletegame=1')

    # Start new game.
    UNKNOWN_COST = random.choice([1,2,3,4,5])

    diffs = re.findall(r'<A HREF="maze.phtml\?create=1&diff=(\d+)">', np.content)
    diff = '4' if '4' in diffs else '3'
    np.get(path, 'create=1', f'diff={diff}')
    maze_size = maze_sizes[diff]

    goal_item_img, goal_item = re.search(r'<IMG SRC="http://images.neopets.com/games/maze/(item_.*?)" WIDTH="80" HEIGHT="80"><br><b>(.*?)</b>', np.content).group(1, 2)
    print(f'Asked to find {goal_item} (img: {goal_item_img})')
    np.post(path)

    # State for a single game.
    maze = {}
    x_start = 0
    y_start = 0
    x_cur = x_start
    y_cur = y_start
    x_lower = -maze_size + 1
    x_upper = maze_size - 1
    y_lower = -maze_size + 1
    y_upper = maze_size - 1
    xy_item = None
    xy_exit = None

    while True:
        # Check end conditions.
        if np.contains('Success! You fetched the item and reached the exit!'):
            prize = util.amt(re.search(r'You have been awarded <b>(.*?)</b> for your efforts!', np.content)[1])
            print(f'Won! Got {prize} NP')
            if np.contains('You have achieved a streak'):
                streak, cumul = re.search(r'You have achieved a streak of <b>(.*?)</b> victories, for a running total of <b>(.*?)</b> points', np.content).group(1, 2)
                print(f'Streak is {streak}, total score {cumul}')

                # Don't get too high of a score!
                if int(cumul) > 0:
                    np.get(path, 'deletegame=1')
                    np.get(path, 'create=1', 'diff=1')
            else:
                streak = 1
                cumul = prize
            log.write(f'{diff},{UNKNOWN_COST},1,{prize},{streak},{cumul}\n')
            return (prize, streak, cumul)
        elif np.contains("Your master is very displeased!"):
            print(f'Ran out of time! :(')
            log.write(f'{diff},{UNKNOWN_COST},0,0,0,0\n')
            return

        moves_remaining = int(re.search(r'Moves Remaining: <b>(.*?)</b>', np.content)[1].split()[0])

        # Update knowledge.
        tbl = re.search(r'<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="400">(.*?)</TABLE>', np.content, flags=re.DOTALL)[1]
        tiles = re.findall(r'<TD BACKGROUND="http://images.neopets.com/games/maze/(.*?).gif" WIDTH="80" HEIGHT="80".*?>(.*?)</TD>', tbl)

        for jitter_x, jitter_y in [(0, 0), (1, 0), (-1, 0), (0, 1), (0, -1)]:
            tiles_iter = iter(tiles)
            good = True
            for dy in range(-2, 3):
                for dx in range(-2, 3):
                    img, content = next(tiles_iter)
                    x = x_cur + jitter_x + dx
                    y = y_cur + jitter_y + dy
                    if (x, y) in maze and maze[x, y] != img_to_dirs[img]:
                        good = False
            if good:
                x_cur += jitter_x
                y_cur += jitter_y
                break

        tiles_iter = iter(tiles)
        for dy in range(-2, 3):
            for dx in range(-2, 3):
                img, content = next(tiles_iter)
                x = x_cur + dx
                y = y_cur + dy

                dirs = img_to_dirs[img]
                maze[x, y] = dirs

                if 'http://images.neopets.com/games/maze/item_' in content:
                    xy_item = (x, y)

                # Update knowledge of bounds
                if dirs == 0:
                    if dx == 0:
                        if dy < 0:
                            y_lower = max(y_lower, y_cur + dy + 1)
                            y_upper = y_lower + maze_size - 1
                        elif dy > 0:
                            y_upper = min(y_upper, y_cur + dy - 1)
                            y_lower = y_upper - maze_size + 1
                    if dy == 0:
                        if dx < 0:
                            x_lower = max(x_lower, x_cur + dx + 1)
                            x_upper = x_lower + maze_size - 1
                        elif dx > 0:
                            x_upper = min(x_upper, x_cur + dx - 1)
                            x_lower = x_upper - maze_size + 1

                # Path leading out of bounds indicates an exit
                if x_lower <= x <= x_upper and y_lower <= y <= y_upper:
                    for d in DIRS:
                        ddx, ddy = dir_to_delta[d]
                        if dirs & d and not (x_lower <= x + ddx <= x_upper and y_lower <= y + ddy <= y_upper):
                            xy_exit = (x, y)

        # Compute the goals.
        got_item = not np.contains('Searching for:')
        goals = []
        if got_item:
            # Find the exit!!
            if xy_exit:
                goals = [xy_exit]
            else:
                # All points on any side opposite the side you started on.
                candidates = []
                if x_lower == 0: candidates.extend((x_upper, y) for y in range(y_lower, y_upper + 1))
                if x_upper == 0: candidates.extend((x_lower, y) for y in range(y_lower, y_upper + 1))
                if y_lower == 0: candidates.extend((x, y_upper) for x in range(x_lower, x_upper + 1))
                if y_upper == 0: candidates.extend((x, y_lower) for x in range(x_lower, x_upper + 1))
                # ... that has not been a confirmed dud
                goals = []
                for x, y in candidates:
                    good = False
                    for d in DIRS:
                        dx, dy = dir_to_delta[d]
                        if not (x_lower <= x + dx <= x_upper and y_lower <= y + dy <= y_upper) and (maze.get((x, y), -1) & d) and (maze.get((x + dx, y + dy), -1) & opp_dir[d]):
                            good = True
                            break
                    if good:
                        goals.append((x, y))
        else:
            if xy_item:
                goals = [xy_item]
            else:
                # Possibilities for item location.
                padding = maze_size // 2 - 1
                goals = [(x, y)
                        for x in range(x_lower + padding, x_upper - padding + 1)
                        for y in range(y_lower + padding, y_upper - padding + 1)
                        if (x, y) not in maze]

        # Dijkstra's to figure out how to best reach a goal.
        # Distance is (# ? tiles, # known steps).
        prevs = {}
        Q = [(0, (x_cur, y_cur), None)]
        reached_goal = None
        while Q:
            c, (x, y), prev = heapq.heappop(Q)
            if (x, y) in prevs: continue
            if (x, y) not in maze and not (x_lower <= x <= x_upper and y_lower <= y <= y_upper): continue
            prevs[x, y] = prev
            if (x, y) in goals:
                reached_goal = (x, y)
                break
            dirs = maze.get((x, y), -1)
            c_ = c + (UNKNOWN_COST if dirs == -1 else 1)
            for d in DIRS:
                dx, dy = dir_to_delta[d]
                dirs_ = maze.get((x + dx, y + dy), -1)
                if dirs & d and dirs_ & opp_dir[d]:
                    heapq.heappush(Q, (c_, (x + dx, y + dy), (x, y)))

        if not reached_goal:
            print(f'Ended up in a bad aimless state.')
            log.write(f'{diff},{UNKNOWN_COST},0,0,0,0,ERROR\n')
            return
        
        # Backtrace route to find which direction to walk in.
        cur = reached_goal
        route = []
        while cur:
            route.append(cur)
            cur = prevs[cur]
        route = route[::-1]

        x_nxt, y_nxt = route[1]
        dxdy = (x_nxt - x_cur, y_nxt - y_cur)
        movedir = None
        if dxdy == (-1, 0): movedir = 2
        elif dxdy == (1, 0): movedir = 3
        elif dxdy == (0, -1): movedir = 0
        elif dxdy == (0, 1): movedir = 1

        # Print the maze.
        movechar = "↑↓←→"[movedir]
        if verbose:
            coords = list(maze.keys()) + goals
            min_x = max(x_lower - 2, min(xs(coords)))
            max_x = min(x_upper + 2, max(xs(coords)))
            min_y = max(y_lower - 2, min(ys(coords)))
            max_y = min(y_upper + 2, max(ys(coords)))
            for y in range(min_y - 1, max_y + 2):
                for x in range(min_x - 1, max_x + 2):
                    c = dirs_to_unicode[maze.get((x, y), -1)]
                    if (x, y) == (x_cur, y_cur):
                        c = '@'
                    if (x, y) in goals:
                        c = C_YELLOW + c + C_ENDC
                    elif (x, y) in route:
                        c = (C_GREEN if got_item else C_RED) + c + C_ENDC
                    elif abs(x - x_cur) <= 2 and abs(y - y_cur) <= 2:
                        c = C_CYAN + c + C_ENDC
                    if c == '?':
                        c = C_GREY + c + C_ENDC
                    print(c, end='')
                print()
            print(f'Moves left: {moves_remaining}')
            print(f'Min distance to goal: {len(route)}')
            print(f'Moving {movechar}')
            print()
        else:
            print(f'\r[{moves_remaining} {movechar}] ', end='')

        if len(route) > moves_remaining:
            print(f'No hope of winning. Giving up.')
            log.write(f'{diff},{UNKNOWN_COST},0,0,0,0\n')
            return

        s = re.search(r'<AREA SHAPE="poly" COORDS="57,57,57,0,91,0,91,57" HREF="maze.phtml\?action=move&movedir=0&s=(\d+)"', np.content)[1]
        np.get(path, 'action=move', f'movedir={movedir}', f's={s}')
        x_cur, y_cur = x_nxt, y_nxt
Esempio n. 42
0
def shapeshifter(timeout=10*60):
    np = NeoPage()
    np.get(path_index)
    starting_np = np.current_np()
    if np.contains('Continue Game!'):
        np.get(path_game)
    elif np.contains('Start Game!'):
        np.post(path_process, f'type=init')

    # Just in case we won but left it in the completed state
    if np.contains('You Won!') or np.contains('You Lost!'):
        np.post(path_process + '?type=init')

    tbl = np.search(r'''<table border=1 bordercolor='gray'>(.*?)</table>''')[1]
    imgs = re.findall(r'''<img src='(.*?)' border=0 name='i_'>(<br><b><small>GOAL</small></b></td>)?''', tbl)
    imgs = imgs[:-1]
    N = len(imgs)
    goal_idx = next(i for i, (_, goal) in enumerate(imgs) if goal)
    to_idx = {img: i for i, (img, _) in enumerate(imgs)}

    tbl = np.search(r'''<table align=center cellpadding=0 cellspacing=0 border=0>(.*?)</table>''')[1]
    goal_grid = []
    for row in re.findall(r'''<tr>(.*?)</tr>''', tbl, flags=re.DOTALL):
        imgs = re.findall(r'''<img src='(.*?)' .*?>''', row)
        goal_row = [to_idx[img] for img in imgs]
        goal_grid.append(goal_row)

    tbl = np.search(r'''<center><b><big>ACTIVE SHAPE</big></b><p>(.*?)</table>\n''')[1]
    shape_grids = []
    for shape_info in re.findall(r'''<table.*?>(.*?)</table>''', tbl):
        grid = []
        for row_info in re.findall(r'''<tr>(.*?)</tr>''', shape_info):
            tiles = re.findall(r'''<td.*?>(.*?)</td>''', row_info)
            grid.append([int('square.gif' in tile_info) for tile_info in tiles])
        shape_grids.append(grid)

    # Compute kvho difficulty.
    R = len(goal_grid)
    C = len(goal_grid[0])
    min_shifts_needed = R * C * (N - 1) - sum(map(sum, goal_grid))
    shifts_available = sum(sum(sum(rows) for rows in grid) for grid in shape_grids)
    num_overshifts = shifts_available - min_shifts_needed
    num_flips = num_overshifts // N
    print(f'Puzzle permits {num_flips} flips ({num_overshifts} overshifts)')

    kvho_input = make_kvho_input(goal_grid, shape_grids, goal_idx)

    print(f'Waiting for kvho.')
    start_time = datetime.now()

    positions = []
    try:
        proc = subprocess.run(['c/ss'], input=kvho_input, encoding='utf-8', capture_output=True, timeout=timeout)
        for line in proc.stdout.splitlines():
            if 'x' in line and '=' in line:
                x = list(map(int, line.replace('x', ' ').replace('=', ' ').strip().split()))
                for c, r, _ in zip(x[::3], x[1::3], x[2::3]):
                    positions.append((r, c))
        print(f'Solution found in {datetime.now() - start_time}: {positions}')
    except subprocess.TimeoutExpired:
        print(f'Solution not found in time. Throwing this puzzle to get a new one.')
        for _ in shape_grids:
            positions.append((0, 0))

    for i, (shape, (r, c)) in enumerate(zip(shape_grids, positions)):
        print(f'\rPlacing piece {i+1}/{len(positions)}', end='')
        np.set_referer_path(path_game)
        np.get(path_process, 'type=action', f'posx={c}', f'posy={r}')
        time.sleep(0.5)
    print()

    if np.contains('You Won!'):
        np.set_referer_path(path_game)
        np.post(path_process + '?type=init')
        ending_np = np.current_np()
        print(f'Done level, earned {ending_np - starting_np} NP')
        return 1
    elif np.contains('reached your max neopoints'):
        print('Done for today.')
        return 2
    else:
        print('Did not solve level??')
        return 0