V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
zungmou
V2EX  ›  分享创造

Paperclips 游戏自动低价买矿 + 自动营销

  •  
  •   zungmou · 27 天前 · 1092 次点击

    今天在社区看到 V 友分享了 Paperclips 这个文本游戏网站,粗玩了一下就冲动写了一个外挂,能够实现:

    1. 在资源低于指定额度下,一旦矿价出现近期最低价格则不断买入直到达到额度。
    2. 一旦利润达到营销费用则自动点击营销按钮。

    欢迎增加新功能,这个游戏属于越玩越好玩。

    // 配置对象
    const CONFIG = {
        WIRE_MAX: 100000,
        PRICE_HISTORY_LENGTH: 100,  // 存储最近 100 个价格
        PRICE_PREMIUM: 0,           // 在最低价基础上加的溢价
        INTERVAL: 500,
        STOP_ON_PROJECT: true
    };
    
    // 环形缓冲区实现(高效存储历史数据)
    class PriceRingBuffer {
        constructor(size) {
            this.size = size;
            this.buffer = new Array(size);
            this.index = 0;
            this.count = 0;
        }
        
        push(price) {
            if (typeof price === 'number' && price > 0) {
                this.buffer[this.index] = price;
                this.index = (this.index + 1) % this.size;
                this.count = Math.min(this.count + 1, this.size);
            }
        }
        
        getMin() {
            if (this.count === 0) return 15; // 默认值
            let min = Infinity;
            for (let i = 0; i < this.count; i++) {
                min = Math.min(min, this.buffer[i]);
            }
            return min;
        }
        
        getStats() {
            return {
                min: this.getMin(),
                count: this.count,
                ready: this.count >= 10 // 至少收集 10 个数据点才启用动态定价
            };
        }
    }
    
    // 初始化价格追踪器
    const wirePriceHistory = new PriceRingBuffer(CONFIG.PRICE_HISTORY_LENGTH);
    
    // 缓存 DOM 元素
    const elements = {
        wire: document.querySelector('#wire'),
        wireCost: document.querySelector('#wireCost'),
        btnBuyWire: document.querySelector('#btnBuyWire'),
        btnExpandMarketing: document.querySelector('#btnExpandMarketing'),
        btnMakePaperclip: document.querySelector('#btnMakePaperclip'),
        projectList: document.querySelector('#projectList'),
        processors: document.querySelector('#processors'),
        memory: document.querySelector('#memory'),
        btnAddProc: document.querySelector('#btnAddProc'),
        btnAddMem: document.querySelector('#btnAddMem')
    };
    
    // 安全解析数字(处理各种格式)
    function parseGameNumber(element) {
        if (!element) return 0;
        const text = element.innerText || element.textContent || '';
        // 移除逗号、货币符号、单位文字
        const cleaned = text.replace(/[,$\s]/g, '').replace(/spool/i, '');
        const num = parseFloat(cleaned);
        return isNaN(num) ? 0 : num;
    }
    
    // 安全点击
    function safeClick(button) {
        if (button && !button.disabled && button.offsetParent !== null) {
            button.click();
            return true;
        }
        return false;
    }
    
    // 获取动态价格阈值
    function getDynamicPriceThreshold() {
        const currentPrice = parseGameNumber(elements.wireCost);
        if (currentPrice > 0) {
            wirePriceHistory.push(currentPrice);
        }
        
        const stats = wirePriceHistory.getStats();
        
        // 数据不足时使用保守策略
        if (!stats.ready) {
            return 15;
        }
        
        // 动态阈值 = 历史最低价 + 溢价
        // 随着游戏进行,价格会上涨,这个策略会自动适应
        return stats.min + CONFIG.PRICE_PREMIUM;
    }
    
    // 核心自动化逻辑
    function runAI() {
        // 1. 制造回形针(最高优先级)
        safeClick(elements.btnMakePaperclip);
    
        // 2. 购买线材(动态定价策略)
        const wireStock = parseGameNumber(elements.wire);
        const wirePrice = parseGameNumber(elements.wireCost);
        const priceThreshold = getDynamicPriceThreshold();
        
        if (wirePrice <= priceThreshold && wireStock < CONFIG.WIRE_MAX) {
            safeClick(elements.btnBuyWire);
        }
    
        // 3. 扩展营销
        safeClick(elements.btnExpandMarketing);
    
        // 4. 自动购买 AutoClippers (前期核心)
        const btnBuyAutoclipper = document.querySelector('#btnBuyAutoclipper');
        safeClick(btnBuyAutoclipper);
    
        // 5. 平衡升级 Processors 和 Memory
        const procCount = parseGameNumber(elements.processors);
        const memCount = parseGameNumber(elements.memory);
        if (memCount < procCount * 2) {
            safeClick(elements.btnAddMem);
        } else {
            safeClick(elements.btnAddProc);
        }
    
        // 6. 项目完成检测
        if (CONFIG.STOP_ON_PROJECT && elements.projectList?.innerText.includes('Complete')) {
            console.log(`已制造 ${parseGameNumber(document.querySelector('#clips'))} 个回形针`);
            console.log('检测到项目完成,停止自动化');
            clearInterval(autowire_int);
        }
    }
    
    // 启动自动化
    const autowire_int = setInterval(runAI, CONFIG.INTERVAL);
    
    // 控制台工具函数
    window.stopAutowire = () => clearInterval(autowire_int);
    window.getPriceStats = () => wirePriceHistory.getStats();
    
    console.log('回形针自动化已启动');
    console.log('命令:stopAutowire() 停止自动化');
    console.log('命令:getPriceStats() 查看价格统计');
    
    目前尚无回复
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   2965 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 12:38 · PVG 20:38 · LAX 04:38 · JFK 07:38
    ♥ Do have faith in what you're doing.