From eb53739618ec727168d732e26b66d2c9ea73a843 Mon Sep 17 00:00:00 2001 From: empathicqubit Date: Fri, 7 May 2021 03:35:13 -0400 Subject: [PATCH] Fix bitness of velocity. Added target scan function. Currently broken. --- config.lua | 2 +- game.lua | 74 ++++++++++++++++++++++++++-- state-test.lua | 5 +- tools/status-overlay.lua | 103 +++++++++++++++++++-------------------- util.lua | 12 +++++ 5 files changed, 135 insertions(+), 61 deletions(-) diff --git a/config.lua b/config.lua index a115928..a41f3bf 100644 --- a/config.lua +++ b/config.lua @@ -41,7 +41,7 @@ _M.StartPowerup = 0 _M.NeatConfig = { DisableSound = true, -Threads = 1, +Threads = 7, --Filename = "DP1.state", SaveFile = _M.Filename .. ".pool", diff --git a/game.lua b/game.lua index f17fca4..a80b86f 100644 --- a/game.lua +++ b/game.lua @@ -196,6 +196,66 @@ function _M.findPreferredExit() end) end +--- Starting from a specified point in the area, weave back and forth until we reach +--- fall to the bottom. Return all points where we hit the floor on the way down. +---@param startX integer x coordinate of the starting point +---@param startY integer y coordinate of the starting point +---@return table table A list of all the points that we collided with a platform +function _M.rollFromTarget(startX, startY) + local areaWidth = _M.getAreaWidth() + local areaHeight = _M.getAreaHeight() + local increment = mem.size.tile + local direction = increment + local terminus = areaWidth + -- If we're on the right half, move left + -- If we're on the left half, move right + if startX > areaWidth / 2 then + direction = -direction + terminus = 0 + end + + local collisions = {} + local currentY = startY + local currentX = startX + while currentY < areaHeight - increment do + -- Drop down until we collide with the floor + while currentY < areaHeight - increment and _M.getAbsoluteTile(currentX, currentY) ~= 1 do + currentY = currentY + increment + print(string.format("currentx: %d, currenty: %d, areaheight: %d, direction: %d, ", currentX, currentY, areaHeight, direction)) + end + + -- Break if we've hit the bottom + if currentY > areaHeight - increment then + break + end + -- Track the collision + table.insert(collisions, { + x = currentX, + y = currentY, + }) + -- Move in the direction until we reach a gap or the edge of the area + while currentY < areaHeight - increment do + currentX = currentX + direction + print(string.format("currentx: %d, currenty: %d, areaheight: %d, direction: %d, ", currentX, currentY, areaHeight, direction)) + -- Switch directions if we're out of bounds + if direction < 0 and currentX < terminus + increment or direction > 0 and currentX > terminus - increment then + direction = -direction + elseif _M.getAbsoluteTile(currentX, currentY) ~= 1 then + -- Check to make sure there isn't a floor immediately underneath. + -- If there is we're probably on an incline. + if _M.getAbsoluteTile(currentX, currentY + increment) == 1 then + currentY = currentY + increment + else + break + end + end + end + end + + print(util.table_to_string(collisions)) + return collisions +end + function _M.getGoalHit() local sprites = _M.getSprites() for i=1,#sprites,1 do @@ -345,9 +405,9 @@ function _M.tileIsSolid(x, y, tileVal, tileOffset) return true end -function _M.getTile(dx, dy) - local tileX = math.floor((_M.partyX + dx * mem.size.tile) / mem.size.tile) * mem.size.tile - local tileY = math.floor((_M.partyY + dy * mem.size.tile) / mem.size.tile) * mem.size.tile +function _M.getAbsoluteTile(x, y) + local tileX = math.floor(x / mem.size.tile) * mem.size.tile + local tileY = math.floor(y / mem.size.tile) * mem.size.tile local offset = _M.tileOffsetCalculation(tileX, tileY, _M.vertical) @@ -360,6 +420,10 @@ function _M.getTile(dx, dy) return 1 end +function _M.getTile(dx, dy) + return _M.getAbsoluteTile(_M.partyX + dx * mem.size.tile, _M.partyY + dy * mem.size.tile) +end + function _M.getCurrentArea() return memory.readword(mem.addr.currentAreaNumber) end @@ -403,8 +467,8 @@ function _M.getSprite(idx) -- 0x4000 0: Right facing 1: Flipped -- 0x1000 0: Alive 1: Dying style = util.regionToWord(spriteData, offsets.style), - velocityX = util.regionToWord(spriteData, offsets.velocityX), - velocityY = util.regionToWord(spriteData, offsets.velocityY), + velocityX = util.regionToSWord(spriteData, offsets.velocityX), + velocityY = util.regionToSWord(spriteData, offsets.velocityY), motion = util.regionToWord(spriteData, offsets.motion), x = x, y = y, diff --git a/state-test.lua b/state-test.lua index 57d17bc..a5240e5 100644 --- a/state-test.lua +++ b/state-test.lua @@ -9,4 +9,7 @@ end) set_timer_timeout(1) local game = dofile(base.."/game.lua")(Promise) local util = dofile(base.."/util.lua")(Promise) -local serpent = dofile(base.."/serpent.lua") \ No newline at end of file +local serpent = dofile(base.."/serpent.lua") + +game.registerHandlers() +game.getPositions() diff --git a/tools/status-overlay.lua b/tools/status-overlay.lua index 3914859..98ab950 100644 --- a/tools/status-overlay.lua +++ b/tools/status-overlay.lua @@ -132,44 +132,43 @@ function on_input (subframe) end end -local function get_sprite(base_addr) +local function get_sprite(baseAddr) + local spriteData = memory.readregion(baseAddr, mem.size.sprite) local offsets = mem.offset.sprite - local cameraX = memory.readword(mem.addr.cameraX) - 256 - local cameraY = memory.readword(mem.addr.cameraY) - 256 - local x = memory.readword(base_addr + offsets.x) - local y = memory.readword(base_addr + offsets.y) + local x = util.regionToWord(spriteData, offsets.x) + local y = util.regionToWord(spriteData, offsets.y) return { - base_addr = string.format("%04x", base_addr), - screenX = x - 256 - cameraX, - screenY = y - 256 - cameraY - mem.size.tile / 3, - control = memory.readword(base_addr + offsets.control), - draworder = memory.readword(base_addr + 0x02), + base_addr = string.format("%04x", baseAddr), + screenX = x - game.cameraX, + screenY = y - game.cameraY - mem.size.tile / 3, + control = util.regionToWord(spriteData, offsets.control), + draworder = util.regionToWord(spriteData, 0x02), x = x, y = y, - jumpHeight = memory.readword(base_addr + offsets.jumpHeight), - style = memory.readword(base_addr + offsets.style), - currentframe = memory.readword(base_addr + 0x18), - nextframe = memory.readword(base_addr + 0x1a), - state = memory.readword(base_addr + 0x1e), - velocityX = memory.readsword(base_addr + offsets.velocityX), - velocityY = memory.readsword(base_addr + offsets.velocityY), - velomaxx = memory.readsword(base_addr + 0x26), - velomaxy = memory.readsword(base_addr + 0x2a), - motion = memory.readword(base_addr + offsets.motion), - attr = memory.readword(base_addr + 0x30), - animnum = memory.readword(base_addr + 0x36), - remainingframe = memory.readword(base_addr + 0x38), - animcontrol = memory.readword(base_addr + 0x3a), - animreadpos = memory.readword(base_addr + 0x3c), - animcontrol2 = memory.readword(base_addr + 0x3e), - animformat = memory.readword(base_addr + 0x40), - damage1 = memory.readword(base_addr + 0x44), - damage2 = memory.readword(base_addr + 0x46), - damage3 = memory.readword(base_addr + 0x48), - damage4 = memory.readword(base_addr + 0x4a), - damage5 = memory.readword(base_addr + 0x4c), - damage6 = memory.readword(base_addr + 0x4e), - spriteparam = memory.readword(base_addr + 0x58), + jumpHeight = util.regionToWord(spriteData, offsets.jumpHeight), + style = util.regionToWord(spriteData, offsets.style), + currentframe = util.regionToWord(spriteData, 0x18), + nextframe = util.regionToWord(spriteData, 0x1a), + state = util.regionToWord(spriteData, 0x1e), + velocityX = util.regionToSWord(spriteData, offsets.velocityX), + velocityY = util.regionToSWord(spriteData, offsets.velocityY), + velomaxx = util.regionToSWord(spriteData, 0x26), + velomaxy = util.regionToSWord(spriteData, 0x2a), + motion = util.regionToWord(spriteData, offsets.motion), + attr = util.regionToWord(spriteData, 0x30), + animnum = util.regionToWord(spriteData, 0x36), + remainingframe = util.regionToWord(spriteData, 0x38), + animcontrol = util.regionToWord(spriteData, 0x3a), + animreadpos = util.regionToWord(spriteData, 0x3c), + animcontrol2 = util.regionToWord(spriteData, 0x3e), + animformat = util.regionToWord(spriteData, 0x40), + damage1 = util.regionToWord(spriteData, 0x44), + damage2 = util.regionToWord(spriteData, 0x46), + damage3 = util.regionToWord(spriteData, 0x48), + damage4 = util.regionToWord(spriteData, 0x4a), + damage5 = util.regionToWord(spriteData, 0x4c), + damage6 = util.regionToWord(spriteData, 0x4e), + spriteparam = util.regionToWord(spriteData, 0x58), } end @@ -233,6 +232,8 @@ Sprite Details: return end + game.getPositions() + local toggles = "" if pokemon then @@ -256,17 +257,11 @@ Sprite Details: "Up" } - local cameraX = memory.readword(mem.addr.cameraX) - 256 - local cameraY = memory.readword(mem.addr.cameraY) - 256 local cameraDir = memory.readbyte(CAMERA_MODE) local direction = directions[cameraDir+1] - local vertical = memory.readword(mem.addr.tileCollisionMathPointer) == mem.addr.verticalPointer - - local partyX = memory.readword(mem.addr.partyX) - local partyY = memory.readword(mem.addr.partyY) - local partyTileOffset = game.tileOffsetCalculation(partyX, partyY, vertical) + local partyTileOffset = game.tileOffsetCalculation(game.partyX, game.partyY, game.vertical) local stats = string.format([[ %s camera %d,%d @@ -275,11 +270,11 @@ Tile offset: %04x Main area: %04x Current area: %04x %s -]], direction, cameraX, cameraY, vertical, partyTileOffset, memory.readword(mem.addr.mainAreaNumber), memory.readword(mem.addr.currentAreaNumber), util.table_to_string(game.getInputs()):gsub("[\\{\\},\n\"]", ""):gsub("-1", "X"):gsub("0", "."):gsub("1", "O"):gsub("(.............)", "%1\n")) +]], direction, game.cameraX, game.cameraY, game.vertical, partyTileOffset, memory.readword(mem.addr.mainAreaNumber), memory.readword(mem.addr.currentAreaNumber), util.table_to_string(game.getInputs()):gsub("[\\{\\},\n\"]", ""):gsub("-1", "X"):gsub("0", "."):gsub("1", "O"):gsub("(.............)", "%1\n")) text(guiWidth - 125, guiHeight - 200, stats) - text((partyX - 256 - cameraX) * 2, (partyY - 256 - cameraY) * 2 + 20, "Party") + text((game.partyX - game.cameraX) * 2, (game.partyY - game.cameraY) * 2 + 20, "Party") local sprites = {} for idx = 0,22,1 do @@ -312,20 +307,20 @@ Current area: %04x ::continue:: end - if rulers and cameraX >= 0 then + if rulers and game.cameraX >= 0 then local halfWidth = math.floor(guiWidth / 2) local halfHeight = math.floor(guiHeight / 2) - local cameraTileX = math.floor(cameraX / mem.size.tile) + local cameraTileX = math.floor(game.cameraX / mem.size.tile) gui.line(0, halfHeight, guiWidth, halfHeight, BG_COLOR) for i = cameraTileX, cameraTileX + guiWidth / mem.size.tile / 2,1 do - text((i * mem.size.tile - cameraX) * 2, halfHeight, tostring(i), FG_COLOR, BG_COLOR) + text((i * mem.size.tile - game.cameraX) * 2, halfHeight, tostring(i), FG_COLOR, BG_COLOR) end - local cameraTileY = math.floor(cameraY / mem.size.tile) + local cameraTileY = math.floor(game.cameraY / mem.size.tile) gui.line(halfWidth, 0, halfWidth, guiHeight, BG_COLOR) for i = cameraTileY, cameraTileY + guiHeight / mem.size.tile / 2,1 do - text(halfWidth, (i * mem.size.tile - cameraY) * 2, tostring(i), FG_COLOR, BG_COLOR) + text(halfWidth, (i * mem.size.tile - game.cameraY) * 2, tostring(i), FG_COLOR, BG_COLOR) end end @@ -333,10 +328,10 @@ Current area: %04x for x = -TILE_RADIUS, TILE_RADIUS, 1 do for y = -TILE_RADIUS, TILE_RADIUS, 1 do - local tileX = math.floor((partyX + x * mem.size.tile) / mem.size.tile) * mem.size.tile - local tileY = math.floor((partyY + y * mem.size.tile) / mem.size.tile) * mem.size.tile + local tileX = math.floor((game.partyX + x * mem.size.tile) / mem.size.tile) * mem.size.tile + local tileY = math.floor((game.partyY + y * mem.size.tile) / mem.size.tile) * mem.size.tile - local offset = game.tileOffsetCalculation(tileX, tileY, vertical) + local offset = game.tileOffsetCalculation(tileX, tileY, game.vertical) local tile = memory.readword(tilePtr + offset) @@ -344,8 +339,8 @@ Current area: %04x goto continue end - local screenX = (tileX - 256 - cameraX) * 2 - local screenY = (tileY - 256 - cameraY) * 2 + local screenX = (tileX - 256 - game.cameraX) * 2 + local screenY = (tileY - 256 - game.cameraY) * 2 if screenX < 0 or screenX > guiWidth or screenY < 0 or screenY > guiHeight then --goto continue @@ -357,7 +352,7 @@ Current area: %04x end end - if cameraX >= 0 then + if game.cameraX >= 0 then local oam = memory2.OAM:readregion(0x00, 0x220) for idx=0,0x200/4-1,1 do diff --git a/util.lua b/util.lua index 92ecc9c..8fd9fb3 100644 --- a/util.lua +++ b/util.lua @@ -275,6 +275,18 @@ function _M.regionToWord(region, offset) return bit.compose(region[offset], region[offset + 1]) end +function _M.regionToSWord(region, offset) + local unsigned = _M.regionToWord(region, offset) + local base = bit.band(unsigned, 0x7fff) + local sign = bit.lrshift(unsigned, 15) + -- There is a more mathematical way to do this but whatever + if sign == 1 then + return base-0x8000 + else + return base + end +end + return function(promise) Promise = promise return _M