From 330cf035faf5ad009e4357fbde900ff6f22ed3d4 Mon Sep 17 00:00:00 2001 From: empathicqubit Date: Wed, 7 Apr 2021 17:30:46 -0400 Subject: [PATCH] Fix bump logic --- README.md | 5 ++-- game.lua | 77 +++++++++++++++++++++++++++++++++++++------------- neat-donk.lua | 10 ++++++- spritelist.lua | 1 + 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 4078c04..781a377 100644 --- a/README.md +++ b/README.md @@ -47,5 +47,6 @@ If you want a better idea of what's going on with the tile and sprite calculatio ## TODO -* Incur penalty for non-hazardous enemy collisions to encourage neutralizing Klobber -* Make enemies neutral when held? (Klobber, Click-Clack, etc.) +[x] Incur penalty for non-hazardous enemy collisions to encourage neutralizing Klobber +[ ] Make enemies neutral when held? (Klobber, Click-Clack, etc.) +[ ] Multiple nets to handle different contexts s/a clicking map items diff --git a/game.lua b/game.lua index a63d0c7..1dcc780 100644 --- a/game.lua +++ b/game.lua @@ -10,25 +10,27 @@ local _M = {} spritelist.InitSpriteList() spritelist.InitExtSpriteList() -KREMCOINS = 0x7e08cc -TILE_SIZE = 32 -ENEMY_SIZE = 64 -TILE_COLLISION_MATH_POINTER = 0x7e17b2 -SPRITE_BASE = 0x7e0de2 -VERTICAL_POINTER = 0xc414 -TILEDATA_POINTER = 0x7e0098 -HAVE_BOTH = 0x7e08c2 -CAMERA_X = 0x7e17ba -CAMERA_Y = 0x7e17c0 -LEAD_CHAR = 0x7e08a4 -PARTY_X = 0x7e0a2a -PARTY_Y = 0x7e0a2c -SOLID_LESS_THAN = 0x7e00a0 -KONG_LETTERS = 0x7e0902 -MATH_LIVES = 0x7e08be -DISPLAY_LIVES = 0x7e0c0 -MAIN_AREA_NUMBER = 0x7e08a8 -CURRENT_AREA_NUMBER = 0x7e08c8 +local KREMCOINS = 0x7e08cc +local TILE_SIZE = 32 +local ENEMY_SIZE = 64 +local TILE_COLLISION_MATH_POINTER = 0x7e17b2 +local SPRITE_BASE = 0x7e0de2 +local SPRITE_SIZE = 94 +local SPRITE_DYING = 0x1000 +local VERTICAL_POINTER = 0xc414 +local TILEDATA_POINTER = 0x7e0098 +local HAVE_BOTH = 0x7e08c2 +local CAMERA_X = 0x7e17ba +local CAMERA_Y = 0x7e17c0 +local LEAD_CHAR = 0x7e08a4 +local PARTY_X = 0x7e0a2a +local PARTY_Y = 0x7e0a2c +local SOLID_LESS_THAN = 0x7e00a0 +local KONG_LETTERS = 0x7e0902 +local MATH_LIVES = 0x7e08be +local DISPLAY_LIVES = 0x7e0c0 +local MAIN_AREA_NUMBER = 0x7e08a8 +local CURRENT_AREA_NUMBER = 0x7e08c8 function _M.getPositions() leader = memory.readword(LEAD_CHAR) @@ -241,7 +243,7 @@ function _M.getJumpHeight() end function _M.getSprite(idx) - local base_addr = idx * 94 + SPRITE_BASE + local base_addr = idx * SPRITE_SIZE + SPRITE_BASE local control = memory.readword(base_addr) @@ -256,6 +258,10 @@ function _M.getSprite(idx) screenX = x - 256 - cameraX - 256, screenY = y - 256 - cameraY - 256, jumpHeight = memory.readword(base_addr + 0x0e), + -- style bits + -- 0x4000 0: Right facing 1: Flipped + -- 0x1000 0: Alive 1: Dying + style = memory.readword(base_addr + 0x12), velocityX = memory.readsword(base_addr + 0x20), velocityY = memory.readsword(base_addr + 0x24), x = x, @@ -408,6 +414,34 @@ function _M.onceMapLoaded(handler) table.insert(mapLoadedQueue, handler) end +local emptyHitQueue = {} +function _M.onEmptyHit(handler) + emptyHitQueue = {} + table.insert(emptyHitQueue, handler) +end + +function processEmptyHit(addr, val) + local idx = math.floor((bit.band(addr, 0xffff) - bit.band(SPRITE_BASE, 0xffff)) / SPRITE_SIZE) + local pow = _M.getSprite(idx) + if pow == nil or + pow.control ~= 0x0238 then + return + end + + local sprites = _M.getSprites() + for i=1,#sprites,1 do + local sprite = sprites[i] + if bit.band(sprite.style, SPRITE_DYING) ~= 0 and + sprite.good == -1 then + return + end + end + + for i=#emptyHitQueue,1,-1 do + emptyHitQueue[i]() + end +end + function processAreaLoad() for i=#areaLoadedQueue,1,-1 do table.remove(areaLoadedQueue, i)() @@ -423,6 +457,9 @@ end function _M.registerHandlers() memory2.BUS:registerwrite(0xb517b2, processAreaLoad) memory2.WRAM:registerread(0x06b1, processMapLoad) + for i=2,22,1 do + memory2.WRAM:registerwrite(bit.band(SPRITE_BASE + SPRITE_SIZE * i, 0xffff), processEmptyHit) + end end return _M diff --git a/neat-donk.lua b/neat-donk.lua index c848df4..8884a3c 100644 --- a/neat-donk.lua +++ b/neat-donk.lua @@ -19,6 +19,7 @@ netPicture = nil runInitialized = {} frameAdvanced = {} timeout = 0 +bumps = 0 saveLoadFile = config.NeatConfig.SaveFile statusLine = nil @@ -666,6 +667,11 @@ function on_timer() game.onceMapLoaded(function() timeout = -100000 end) + bumps = 0 + -- Penalize player for collisions that do not result in enemy deaths + game.onEmptyHit(function() + bumps = bumps + 1 + end) game.clearJoypad() startKong = game.getKong() startBananas = game.getBananas() @@ -970,6 +976,7 @@ function mainLoop (species, genome) end local hitPenalty = partyHitCounter * 100 + local bumpPenalty = bumps * 100 local powerUpBonus = powerUpCounter * 100 local most = 0 @@ -985,7 +992,7 @@ function mainLoop (species, genome) most = most - pool.currentFrame / 2 end - local fitness = bananaCoinsFitness - hitPenalty + powerUpBonus + most + game.getJumpHeight() / 100 + local fitness = bananaCoinsFitness - bumpPenalty - hitPenalty + powerUpBonus + most + game.getJumpHeight() / 100 local lives = game.getLives() @@ -1364,6 +1371,7 @@ function displayForm() gui.text(5, 95, "Krem: " .. (game.getKremCoins() - startKrem)) gui.text(130, 65, "Coins: " .. (game.getCoins() - startCoins)) gui.text(130, 80, "Lives: " .. game.getLives()) + gui.text(130, 95, "Bumps: " .. bumps) gui.text(230, 65, "Damage: " .. partyHitCounter) gui.text(230, 80, "PowerUp: " .. powerUpCounter) gui.text(320, 65, string.format("Current Area: %04x", currentArea)) diff --git a/spritelist.lua b/spritelist.lua index 8f42f30..31bacbb 100644 --- a/spritelist.lua +++ b/spritelist.lua @@ -5,6 +5,7 @@ _M.Sprites = {} -- Make sure this list is sorted before initialization. _M.NeutralSprites = { 0x0020, -- Krow egg fragments + 0x0060, -- Barrel fragments 0x0064, -- Barrel fragments -- Our heroes