Hat Dash White Hat 명예의 전당 및 리더 보드 새로 고침
며칠 전, 나는 사람들이 Hat Dash에서 속임수를 쓰지 못하도록 방지 (또는 적어도 더 어렵게 만드는) 방법을 찾는 데 도움 을 요청 했습니다. 지금까지 도움을 주신 모든 사용자에게 한마디 부탁드립니다 . Hat Dash 리더 보드 하단 에있는 새로운 White Hat 명예의 전당 에서 확인할 수 있습니다 . 이러한 각 사용자는 이후에 해결 된 (클라이언트, 서버 또는 둘 다에서) 게임 보호의 약점을 드러 냈습니다. 이 모든 사용자는 현상금 보상과 함께 특별한 새 모자 (유니콘의 수호자)도 받게됩니다.

게시물이 작성된 이후, 나는 클라이언트와 서버 모두에 대한 변경 사항을 특징으로하는 Hat Dash의 부정 행위 방지 제어 및 휴리스틱의 새 버전을 출시했습니다. 모든 것이 100 % 안전하지 않습니다. 그것이 어떻게 만들어 졌는지 알면, 나는 확실히 가짜 점수를 얻는 방법을 고안 할 수 있습니다 (그리고 여러분 중 일부는 그렇게 할 것이라고 확신합니다). 그러나 현재 매우 공격적인 사용자 자동 금지 메커니즘이 있기 때문에 무언가를 속이기 시작하면 금지되기가 매우 쉽습니다 . 따라서 경고 emptor . 이제 금지 상태를 확인할 수도 있습니다 .
즉, 새로운 시스템으로 속일 수있는 경우 (속임수 = 불법 점수를 리더 보드에 올릴 수 있고이를 수행 한 방법에 대해보고 할 수있는 경우, 불법 = 게임을 플레이하거나 다른 수단을 통해 API에 액세스 할 수 있음) 공간 / 위쪽 화살표 / 탭을 사용하여 게임을 플레이하는 것보다) 모자 / 현상금 / 호프를 얻고 싶다면 아래 또는 원래 게시물에 자유롭게 게시하십시오 (12 월 30 일까지 게시 된 답변 만 고려됩니다. ,상은 내 재량입니다).
이미 금지 된 상태에서 시스템을 이길 수 있는지 확인하려는 경우, Hat Dash는 이제 각 게임이 끝난 후 콘솔에 한 줄을 인쇄 [Date] | Is Game Suspect | (true/false)
하여 게임에서 무언가가 잡혔는 지 알려줍니다 (참고 : 모든 의심스러운 게임은 자동 금지로 이어질 것입니다).
치트 방지 시스템이 업그레이드되면서 전체 통계 목록이 더 이상 사용되지 않습니다. 이제 리더 보드 하단에 있습니다. 순위표의 맨 위에는 새로운 전체 통계 (2020-12-22) 섹션 (더 나은 이름을 생각할 수 있다면 알려주세요)이 있으며, 여기에는 오늘부터의 점수 만 포함됩니다.
확률이 당신에게 유리하고 행복한 점프가 되길 바랍니다.
(아, 그리고 새 비밀 모자를 얻고 싶지만 흰색 모자 사기꾼이되고 싶지 않다면 계속 지켜봐주세요… )
업데이트 : 최종 White Hat Hall of Fame 라인업이 설정되었습니다. 참여해 주셔서 감사합니다!
답변
채팅에서 나는 더 이상 속임수를 쓰지 않겠다고 말 했지만이 방법을 시도하는 것을 막을 수 없었고 효과가 있었다.
setInterval(function() {
Runner.instance_.horizon.obstacles[0].collisionBoxes = [];
},200);
200ms마다 충돌 상자를 비우고 유니콘이 통과합니다. 하지만 점프 횟수를 확인한다고 생각했기 때문에 필요 없어도 장애물이 보일 때마다 점프했습니다.

추신 : 내 일을 마치면 당신은 나를 영원히 금지 할 수 있습니다.
규칙을 지키지 않고 시스템을 이기고 높은 점수를 얻을 수있는 방법을 찾았습니다. 순위표에서 차단되어 점수를받을 수 없었지만 브라우저 콘솔 메시지는 게임이 의심되지 않았다는 것을 확인합니다.
나는 자바 스크립트에 익숙하지 않기 때문에 아마도 내가하는 일을하는 가장 좋은 방법은 아닐 것입니다.하지만 그것이 작동하기 때문에 올바른 방법을 찾는 데 시간을 낭비하지 않을 것입니다.
기본적으로 게임을 시작하고 장애물에 부딪쳐 야합니다. 게임이 끝나면 다음을 입력하십시오.
Runner.instance_.horizon.obstacles[0].typeConfig.yPos = 1337
브라우저 콘솔로. 그런 다음 다시 시작하여 다른 장애물에 부딪 히고 동일한 코드를 콘솔에 입력하십시오. 장애물이 더 이상 발생하지 않을 때까지 반복합니다 (잘 작동하면이 작업을 세 번 수행해야하고 잠시 후 세 번째 장애물이 오기 때문에 넘어지지 않도록 실제 장애물을 피하는 것처럼 점프해야합니다. 치트 방지 시스템). 이제 장애물없이 게임을 플레이 할 수 있지만 치트 방지 시스템을 속이기 위해서는 실제로 장애물을 피하는 것처럼 계속 점프하고 더킹해야합니다. 피곤해질 때까지 계속 진행 한 다음 다른 탭으로 전환하여 게임을 종료하십시오.
내부 : 세 가지 유형의 장애물 CACTUS_SMALL
, CACTUS_LARGE
및 PTERODACTYL
(배열에 정의되어 있음 s.types
)이 있습니다. 장애물에 부딪히면 특정 장애물 유형의 참조가 저장 Runner.instance_.horizon.obstacles[0]
되므로 특정 장애물 유형 yPos
을 거대한 것으로 변경합니다 . 이 유형의 장애물은 이제 캔버스 외부에 배치되어 볼 수없고 더 중요한 것은 부딪 힐 수 없다는 것입니다. 제가 말했듯이, 저는 자바 스크립트에 익숙하지 않아서 s.types
콘솔에서 직접 편집하는 방법을 알아낼 수 없었습니다 (이 경우 yPos
세 가지 유형을 한 번에 모두 변경할 수 있음 ). 가능하다면 자유롭게 이 게시물을 수정하거나 아래에 댓글을 달아주세요.

Is Game Suspect = false
게임은 여전히 JavaScript를 통해 자동 재생 될 수있는 것으로 보입니다.
먼저,이 스크립트를 완전히 작성하지 않았습니다. ( 원본 출처 ) 유니콘이 회피하도록 수정하고 점프 높이를 조정했습니다.
그것은 지속적으로 약 1500에서 2000+의 점수를 얻었습니다 (유니콘이 우연히 넘어지기 전에).
다른 방법으로 속임수를 쓰다가 실수로 금지당했습니다 (아래 스크립트를 사용했기 때문이 아닐 것 같습니다). 나는 내가 금지 된 이유에 대한 이론을 가지고 totalJumps
있습니다.
내가 금지되기 전에 아래 스크립트를 사용하여 얻은 내 최고 점수 중 하나입니다 .

const autoPlayLoop = function() {
const JUMP_SPEED = 750;
const DISTANCE_BEFORE_JUMP = 112;
const instance = window.Runner.instance_;
const tRex = instance.tRex;
if (tRex.jumping) {
requestAnimationFrame(autoPlayLoop);
return;
}
const tRexPos = tRex.xPos;
const obstacles = instance.horizon.obstacles;
const nextObstacle = obstacles.find(o => o.xPos > tRexPos);
if (nextObstacle && (nextObstacle.xPos - tRexPos) <= DISTANCE_BEFORE_JUMP) {
if (nextObstacle.yPos < 80) {
tRex.setDuck(true);
} else {
tRex.startJump(JUMP_SPEED)
}
}
requestAnimationFrame(autoPlayLoop);
}
requestAnimationFrame(autoPlayLoop);
순위표 상단에는 새로운 전체 통계 (2020-12-22부터) 섹션이 있습니다 (더 나은 이름을 생각할 수 있다면 알려주세요).
나는 그들이 게임 홀에서 그것을 어떻게 불렀는지 생각하고 있었는데
역대 최고 점수
과
일일 최고 점수
좋은 것
Panda가 이미 언급 했으므로 여기 에서 가져온 다른 접근 방식을 사용하여 게임을 자동화하려고 했으며 원래는 T-Rex 실행 게임을 플레이하려고했습니다.
코드는 Panda가 게시 한 것보다 훨씬 간단합니다. 이것이 나를 금지 한 것인지는 모르겠지만 여기에 참조 용으로 사용한 수정 버전이 있습니다.
(function loop() {
var rand = Math.round(Math.random() * (3)) + 3;
setTimeout(function() {
try{
DoAction()
}
catch(e){
}
loop();
}, rand);
}());
function DoAction(){
if (Runner.instance_.horizon.obstacles.length > 0){ // if obsticles exist
if (Runner.instance_.horizon.obstacles[0].xPos < Runner.instance_.currentSpeed * 20 - Runner.instance_.horizon.obstacles[0].width/3 && Runner.instance_.horizon.obstacles[0].yPos > 75){
keyUp(40);
keyDown(38);
}
else if (Runner.instance_.horizon.obstacles[0].xPos < Runner.instance_.currentSpeed * 20 - Runner.instance_.horizon.obstacles[0].width && Runner.instance_.horizon.obstacles[0].yPos > 75){
keyDown(40);
}
}
}
내가 현재 게임에서 금지되어 있으므로 첫 번째 해킹 테스트 단계 이후에 구현 된 게임 변수에 대한 직접 액세스에 대한 확인이 있거나 점프의 규칙 성이 휴리스틱을 유발했습니다. 이것이 내가 코드를 변경 한 이유이기도하다. 그래서 루프는 점프가 더 "인간적"처럼 보이도록하는 임의의 지연을 가지게되지만, 이것이 내부 치트 방지를 방해하기에 충분한 지 테스트 할 수 없다. 안타깝게도 저는 금지를 받기 전에 그것에 대해 생각하지 않았습니다.
네트워크 탭이보고 한 내용에 따르면 게임은 세 가지 유형의 요청을 수행하는 것으로 보입니다.
- https://winterbash2020.stackexchange.com/hat-dash/start: 게임이 시작되었다는 신호입니다. 타임 스탬프 포함
- https://winterbash2020.stackexchange.com/hat-dash/cp: 이상한 것. 기간과 "점프 합계"가 포함 된 메시지입니다. 현재 나는 이것이 언제 호출되는지 이해하지 못했지만 클라이언트 측 치트 방지 시스템의 일부일 수 있습니다. 하지만 치트없이 플레이 할 때에도 이것이 호출되는 것을 알았 기 때문에 확실하지 않습니다.
- https://winterbash2020.stackexchange.com/hat-dash/end: 게임 종료시 호출되며 기간 등과 같은 예상 정보를 포함합니다. 또한 "총 점프"변수를 다시 참조합니다. 이상하게도 게임이 이전 점수를 참조한 것처럼 "역사 키"목록도 포함되어 있습니다.
원래는 "totaljump"가 치트 방지와 관련이있을 가능성이 가장 높은 것으로 보였지만 그 다음이 히스토리 배열이었습니다.
업데이트 : 나는 애초에 봇 때문에 금지되었다는 것을 의심하기 시작했습니다. 나는 그것이 적어도 기술적 으로 부정 행위와 관련이없는 다른 서버 측 휴리스틱과 관련이 있어야한다고 생각하고 있습니다 (단지 테스트로 트리거 될 수 있음). 내가 가진 몇 가지 무작위 아이디어 :
- 실제로 점수를 제출하지 않고 테스트를 수행하기 위해 로그 오프되도록 비공개 브라우저 창에서 플레이를 시도했습니다 .... 동일한 IP 결과를 가진 클라이언트가 기록되지 않은 상태와 기록 된 상태 모두가 트리거가 될 수 있습니다.
- Firefox의 두 가지 버전, 표준 및 개발자를 사용합니다. 호기심으로 저는 개발자를 사용하여 "모바일 모드"에서 게임을 플레이하여 누군가가보고 한 기능 (낮은 삼각형이 사라짐)이 사실인지 확인하고 동작을 T-Rex Chrome 게임과 비교했습니다. 일부 사용자는 "사용자 에이전트 문자열을 너무 많이 전환"하여 금지 된 것으로보고되었습니다.
- API가 플레이어 점수 기록을 추적하는 것처럼 보이기 때문에 누군가가 갑자기 트리거가 될 수있는 스킬과 호환되지 않는 점수를 얻는 경우 "스킬"을 기반으로 추론을 수행하려고합니다. 상당히 이상하게 보입니다-만약 그렇다면 많은 세계 점수가 즉각적인 금지를 초래했을 것이라고 가정했을 것입니다 (btw, 속도 변화로 인해 약 20k 최대에서 게임을 할 수 없게 될 것임을 고려하면 btw , 왜 이것이 아닌가? 나는 인간이 100k에 도달 할 수 있을지 의심 스럽다).
즉, 이것은 원래 게임의 치트가 Hat-Dash 버전에서도 실행되는 원래 T-Rex 실행과 논리가 여전히 충분히 유사한 지 확인하기위한 테스트 일뿐입니다 (누군가가 이미 시도하고 시연 한 게시하다). 지금은 여유 시간이 많지 않으므로 알아 둘만한 정보가 더 있으면 나중에 다시보고하겠습니다.
추신 : 누군가이 라인이 무엇을해야하는지 궁금해하는 경우 ...
if (Runner.instance_.horizon.obstacles[0].xPos < Runner.instance_.currentSpeed * 20 - Runner.instance_.horizon.obstacles[0].width && Runner.instance_.horizon.obstacles[0].yPos > 75){
keyDown(40);
}
이것은이 게임이 때때로 가지고있는 "불가능한"점프 문제를 해결하기위한 매우 원시적 인 시도입니다. Magish가 알아 차린 것처럼 유니콘은 이전 장애물에 너무 가까운 장애물을 뛰어 넘을 수있을만큼 빠르게 떨어지지 않습니다. 이 경우 아래로 누르면 유니콘이 더 빨리 떨어집니다.
최근에 Playwright 브라우저 자동화 라이브러리를 사용하여 많은 작업을 수행하고 있습니다. 해머 만 있으면 ... 이것이 속임수에 좋은 방법이라고 말하는 것이 아닙니다. 게임 자체를 전혀 건드리지 않고 할 수 있습니다.
내 원래 아이디어는 Playwright를 사용하여 페이지를로드하고 게임을 시작한 다음 분석을 위해 스크린 샷을 반복적으로 캡처하도록하는 것이 었습니다. 이것은 최대한의 스텔스를 위해 누르는 공간 외에 브라우저 환경 내에서 아무것도 만질 필요가 없음을 의미합니다. 이것은 효과가 있었지만 Chromium에 스크린 샷 (전체 페이지의 크기를 조정 함)을 찍고 버퍼에로드 한 다음 처리하는 데 150ms 정도가 걸렸는데 이는 너무 느려서 내가 염두에 둔 매우 간단한 논리를 사용하여 훌륭한 점수를 얻었습니다. 나는 속임수를 썼다.
그래서 저는 클라이언트 브라우저에 toDataURL()
게임의 <canvas>
요소 를 호출 하고 이미지 데이터를 다시 가져 오도록 요청했습니다 . 이것은 10-15ms 정도의 대기 시간을 달성 할 수 있습니다. 나는 반복적으로 게임 이미지를 캡처하고 장애물 (흰색이 아닌 픽셀, 컴퓨터 비전, 그렇지 않음)에 대한 작은 감지 사각형을 봅니다. 발견하면 스페이스 바를 누릅니다. 이것은 특별히 영리하지는 않지만 (나는 아래쪽 화살표를 사용하지 않으며, 고속에서는 우리가 공중에있는 동안 점프를 시도하기 때문에 실패 할 수 있습니다), 게임은 자동화되어 있습니다. 운이 좋을 때까지 플레이합니다.
이 프로세스는 두 개의 상수로 제어됩니다. 거기에 XCROP
장애물을 검출 할 때 미리보고 얼마나 멀리 사전에 : 검출 영역을 결정합니다. 잘못 설정하면 너무 일찍 또는 늦게 점프합니다. 그리고 SPEED_FACTOR
더 빠른 속도를 조정하기 위해 게임이 진행됨에 따라 xcrop을 선형 적으로 증가시키는, (속도가 선형 적으로 증가합니까? 확인하지 않았습니다). 이러한 상수는 스크립트가 실행되는 환경에 매우 민감합니다. 자동화를 게임과 동기화하려고 시도하지 않으며 SCALE_FACTOR
이미지 캡처 / 처리 루프를 실행하는 데 걸리는 시간에 전적으로 의존합니다. console.log()
테스트에서 진술을 추가 / 제거하는 것만으로도 충분했습니다. 따라서 이러한 값은 시스템에서 작동하지 않을 수 있습니다. 그러나 적절하게 조정하면 (다른 값으로 많은 게임을 플레이하여 자동화 할 수 있음) 일일 순위표에 적합한 점수를 쉽게 얻을 수 있습니다.
이것은 특히 탐지를 피하려고하지 않습니다. 물체가 탐지되고 게임을 계속할 때 초인적 인내력을 가지고있을 때 초인적 인 속도로 반복적으로 스페이스 바를 스팸으로 처리합니다. 그리고 흰색이 아닌 경우 33px 너비의 직사각형을 보는 탐지 로직 픽셀은 거의 영리하지 않지만 항상 "Is Game Suspect = false"를 인쇄하는 것처럼 보입니다.
const Jimp = require('jimp');
const {chromium} = require('playwright');
(async () => {
const XCROP = 122
const SPEED_FACTOR = 0.008
const browser = await chromium.launch({
headless: false
})
const context = await browser.newContext()
const page = await context.newPage()
// pipe the browser console to our console so we can see the "Is Game Suspect" message
page.on('console', msg => console.log(msg.text()))
const playGame = async (xcrop, speedFactor) => {
await page.goto('https://winterbash2020.stackexchange.com/run-with-the-hats')
const container = await page.waitForSelector('.runner-container')
// start the game
await container.click()
await container.press(' ')
await page.waitForTimeout(500)
const canvas = await page.$('canvas') let weLost = false for (let count=0; !weLost; count++) { // check if we lost and return our score if we did if (await page.$('.js-personal-stats > div')) {
weLost = true
const scoreElems = await page.$$('.js-personal-stats strong')
const score = parseInt(await scoreElems[2].innerText())
return score
}
// ask the game's <canvas> for its image data as a data url and stuff it in a buffer
const dataURL = await page.evaluate((elem) => {
return elem.toDataURL()
}, canvas)
const buffer = Buffer.from(dataURL.substr(22), 'base64')
// parse the image data and crop out a small rectangle from it with 1-bit color depth for analysis
const img = await Jimp.read(buffer)
let foundPixel = false
img
.crop(xcrop + (speedFactor * count), 100, 33, 20)
.posterize(2)
// look though the image data for any non-white pixels, which indicates we found an object
// the image is in RGBA format, so we can skip bits
for (let i = img.bitmap.data.length - 1; i >= 0; i -= 4) {
if (img.bitmap.data[i] != 0) {
foundPixel = true
break
}
}
// if we detected an object, press space to jump
if (foundPixel) {
await container.press(' ')
console.log(xcrop + (speedFactor * count), speedFactor, speedFactor * count)
}
}
}
const playMultipleGames = async (tries, ...args) => {
const results = []
for (let i=0; i<tries; i++) {
const score = await playGame.apply(null, args)
results.push(score)
}
console.log(results, args)
}
console.log(await playMultipleGames(20, XCROP, SPEED_FACTOR))
await page.close()
await context.close()
await browser.close()
})().catch((ex) => {
console.error(ex);
process.exit(1)
});
대부분의 테스트를 로그 아웃했지만 일부 최종 테스트를 위해 스크립트에 로그인 단계를 추가했습니다 (잠시 후 로그인 양식에서 보안 문자를 트리거하기 시작 했으므로 적어도 작동합니다). 이제 나를 차단할 수 있습니다.
Panda의 답변 에서 자동 재생 스크립트를 수정하고 , 많은 구현 세부 사항을 교체하고, SPArcheon의 답변 (점프 거리 계산) 에서 일부 공식을 사용하고 , Tuqay의 답변 (장애물 충돌 상자 재설정) 에서 가져온 사기 코드를 삽입했습니다 . 또한 클라이언트 측 치트 감지를 피하기 위해 게임 속도를 줄이려고 시도하며 실제로 잘 작동합니다.
이번에는 리소스 재정의를 해제 했으므로 SE 파일이 조작되지 않습니다. 확장 프로그램이없는 바닐라 Google 크롬이면 충분합니다.
나는 sockpuppet (내 기본 계정이 금지됨)에서 두 개의 점수를 제출했지만 여전히 금지되지 않았습니다. 아래 스크린 샷을 참조하십시오. 그러나 최고 점수는 아직 순위표에 나타나지 않았습니다.
추신 : Google Chrome 또는 Microsoft Edge (새로운 Chromium 기반)에서 실행되는 JavaScript를 편집하고 디버깅하는 데 Microsoft Visual Studio Code를 권장합니다.
const keySpace = {
key: " ",
keyCode: 32,
code: "Space",
which: 32,
shiftKey: false,
ctrlKey: false,
metaKey: false,
isDown: false,
},
keyDown = {
key: "down",
keyCode: 40,
code: "Down",
which: 40,
shiftKey: false,
ctrlKey: false,
metaKey: false,
isDown: false,
};
const createKeyEvent = function (keyObj, duration) {
if (!keyObj.isDown) {
document.dispatchEvent(new KeyboardEvent("keydown", keyObj));
keyObj.isDown = true;
}
setTimeout(() => {
if (keyObj.isDown) {
document.dispatchEvent(new KeyboardEvent("keyup", keyObj));
keyObj.isDown = false;
}
}, duration)
;
};
const autoPlayLoop = function () {
const instance = Runner.instance_;
const speed = instance.currentSpeed;
if (speed > instance.config.MAX_SPEED) {
instance.currentSpeed = instance.config.MAX_SPEED - 0.1;
}
const tRex = instance.tRex;
// if (tRex.jumping) {
// requestAnimationFrame(autoPlayLoop);
// return;
// }
const tRexPos = tRex.xPos;
const obstacles = instance.horizon.obstacles;
const prevObstacle = obstacles.find((o) => o.xPos <= tRexPos);
const nextObstacle = obstacles.find((o) => o.xPos > tRexPos);
if (tRex.jumping) {
if (prevObstacle) {
createKeyEvent(keyDown, 200);
}
} else if (nextObstacle) {
nextObstacle.collisionBoxes = [];
const DISTANCE_BEFORE_JUMP = 20 * speed - nextObstacle.width / 3;
if (nextObstacle.xPos - tRexPos <= DISTANCE_BEFORE_JUMP) {
if (nextObstacle.yPos < 80) {
// dodge instead of jump
createKeyEvent(keyDown, 300);
} else {
if (speed >= 18) {
createKeyEvent(keySpace, 30);
//setTimeout(() => createKeyEvent(keyDown, 300), 150);
} else {
createKeyEvent(keySpace, 30);
}
//tRex.startJump(JUMP_SPEED);
}
}
}
requestAnimationFrame(autoPlayLoop);
};
requestAnimationFrame(autoPlayLoop);
게임을 시작하고 다른 해킹을 시도하기에는 너무 게으른 사람들을위한 해결책이 있습니다.
(async () => {
var score = 4000;
var seconds = 200;
var jumps = 400;
Runner.gameStarted();
Runner.setCurrentScore(score);
await new Promise(resolve => setTimeout(resolve, seconds * 1000));
Runner.gameEnded(Runner.instance_.startedAt, jumps);
})();
교체 score
, seconds
그리고 jumps
그에 따라. 리더 보드 에서 다른 사람의 합법적 인 점수를 보는 것이 도움이 될 것 입니다.
내 이전 답변에서 수정되었습니다 . jumpCount
새로운 부정 행위 방지 기능과 함께 서버로 전송되기 때문에 추가되었습니다 .
업데이트 된 자동 금지 시스템은 중력, 낙하 속도, 초기 점프 속도, 현재 속도 및 장애물 수에 대한 잘못된 값을 확인합니다. 이러한 값을 수정하지 않았기 때문에 게임이 진행됨에 따라 현재 속도가 증가하기 때문에 현재 속도 만 걱정하면되었습니다. 자동 금지 시스템이 작동하지 않도록하기 위해 현재 속도가 25 미만일 때마다 y 축에서 충돌 상자를 위로 이동했습니다. 다음은 제가 사용한 코드입니다.
setInterval(function() {
var yPosition = 1000;
function shiftCollisionBoxes(obstacles, yPosition) {
if (obstacles && yPosition >= 0) {
for (var i = 0; i < obstacles.length; i++){
for (var j = 0; j < obstacles[i].collisionBoxes.length; j++){
obstacles[i].collisionBoxes[j].y = yPosition;
}
}
}
}
if (Runner.instance_.currentSpeed < 25) {
shiftCollisionBoxes(Runner.instance_.horizon.obstacles, yPosition);
shiftCollisionBoxes(Runner.instance_.obstacles, yPosition);
}
},200);


나는 잘하겠다고 맹세했다 . 나는 언제 언급하는 것을 잊었다 고 생각한다. 나는이 솔루션이 이미 충돌 상자와 y 축 위치를 엉망으로 만든 다른 솔루션이 100 % 고유하지 않다는 것을 알고 있습니다. 그러나이 솔루션은 충돌 상자의 존재를 확인하는 것만으로는 충분하지 않음을 보여줍니다. 코드는 충돌 상자의 위치가 변경되지 않았는지 확인해야합니다. 이 솔루션은 또한 업데이트 된 자동 차단 시스템의 호출을 명시 적으로 방지합니다. 내가 명예의 전당에 들어갈 수 있다면이 모자는 내 흰색 밴과 잘 어울릴 것입니다. 모두 즐거운 휴일 보내세요!
Number
기능 을 편집하여 점수를 변경할 수 있습니다 . 대체 될 때 코드는 Firefox의 예쁘게 인쇄 된 코드의 1168 행에있는 점수 문자열을 숫자로 변환하려고 시도하고 대신 사용자 지정 함수를 실행합니다. 이 코드를 JavaScript 콘솔에 붙여 넣으십시오.
function Number(n) {
return 1000000;
}