
今天在社区看到 V 友分享了 Paperclips 这个文本游戏网站,粗玩了一下就冲动写了一个外挂,能够实现:
欢迎增加新功能,这个游戏属于越玩越好玩。
// 配置对象 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() 查看价格统计');