Do both players get to grab the bonuses or is it only the first one who gets it? You could try to have a score competition of sorts, though that'd be pretty subtle since the players can't get in each others' way all that much.
Generally, if it doesn't cost you time or entertainment, it's worth grabbing everything.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
I think I should try to grab them all, unless it looks quite a bit more interesting if I do something else at the time which would prevent me from getting those bonuses.
In particular, I'm thinking about the two bonuses at the end of the first level. I would like to keep the two players flying into each others' space even while digging through the regenerating gunk. I'm not sure if I can dig upwards or downwards, but if I can't work my way vertically at all, I may sacrifice getting one or both bonuses for the sake of dancing around with both players together entertainingly.
Although, I could still try and dance a bit on opposite sides so I can still get both those bonuses... I'll try to work it out when I get to that point. For now, there's the rest of the stage I have to get through.
Mainly, I'm posting to confirm I did not forget this project.
Secondly, I've only added around 13 seconds over my last WIP so far. Just a report on how much I've done so far. I'm moving, but slowly...
I'm probably going to spoil a part of my plans here, but here's what I'm thinking for a particular part of the first level:
At those red vines, I won't shoot them all. I see some letters in there that I don't want to shoot. All I would be doing is get rid of all the extra vines so that these letters don't have any extras hanging off them! I might even end up doing a bit of TASvertisement through these vines! (In truth, I'm playing around with the idea of writing Wii on there.)
That is mostly what I have planned for those vines. I don't want my plans to come off as bad after I put in the effort to write on those vines. And though the surprise is somewhat ruined by my explaining something I foresee, I don't actually want to end up making something awful when all that is needed to prevent it is asking here.
On a side note, in the process of making that plan, I snapped a few screenshots and made a GIF file. Any suggestions on where to upload the picture?
I get my next WIP ready, and I can't even connect to Microstorage now. I did refer to this thread and I'm still having problems. It seems as though it's completely down for the time being. (EDIT: The problems are gone now.)
EDIT: Temporary link removed. I'm using Microstorage again. By the way, while I only added a few frames, I did make some adjustments to my run. Basically, I got rid of my biggest regrets, and hopefully is more entertaining. I still think my TASing style changed.
ImageShack seems like a convenient site for pictures. I might use it after taking a little more time to decide where to put my picture.
Wow. This was really smooth.
Dude.. Keep up the pace. I hope you release a longer WIP, or just finish the TAS tomorrow. I want to watch the full length during the weekend.
Hey, Microstorage is available again! Since it's up again, I put my edited run up there, and edited my previous post. There isn't much progress to view in the run, but I got rid of my biggest regrets:
Frames 1820~2170 got a makeover, where I no longer spell a barely legible FATRAT in there. It's mostly illegible! In its place, I dance around instead.
Frames 3440~3680 just wasn't daring enough. Now there's a little more action and a lot closer shave for Red.
Then at the end, 10 new frames, testing things out in the short term before deciding to go back and fix my previous problems. I suppose these 10 frames are enough to foreshadow Red's fate, huh?
I should recognize when progress is going too darn slow. Might help somewhat if I knew how to go about using lua scripts or some way of multi-track rerecording, but right now, at the pace I'm working, the project may as well be dead.
Still, that's not to say nothing happened during all this time. I stopped several moments before getting that last blue one, since I don't feel as though I'm up to continuing for a little while.
One thing I discovered, after blasting away most of the other durable blue stuff, is that I can fire at a rate higher than 30 Hz. If you have one on-screen bullet, and fire at the same time it hits an enemy and disappears, you can hold down B for one more frame and fire off another shot. I can effectively fire at 40 Hz this way. Although fairly moot when it comes to speed in an auto-scroller, it would have given me a little more time to dance around later.
Largely, though, I'm just announcing that the project is virtually in hibernation. May as well throw in what I've got before I forget completely.
Yo! I'm back to working on this run!
It looks like my EVO run is put on hold now. And I'm swinging back to this run. Well, at least I'm still trying something.
Joined: 7/19/2006
Posts: 21
Location: San Francisco
Wicked run, I love it.
I seem to recall that after Live Force is cleared it restarts at a higher difficulty. For instance, the arms shoot little fire balls. Is there a code to start at this higher difficulty level? If not an argument could be made for a save-state start.
Also, it could be a very flawed memory of mine, (perhaps I am getting this confused with Tyrian) but I seem to recall the the big yellow claws/hooks/thorns in the middle of level one are killable. I have a vague memory of concentrating a lot of laser fire with options while playing two player with my little brother and killing one of them.
It does. Things are faster, and things that don't normally shoot start taking pot-shots at you. Beat the game again, and things get even faster. I am not aware of any in-game code that starts at a higher difficulty, so the only way I can instantly get there is by altering the game or using a save-state, neither of which are accepted at TASVideos to my knowledge. I am not aware of exceptions.
I don't remember ever destroying them. In my run, I actually do fire a shot at one of them while my ships are "impaled" on them in an attempt to make a sound effect. Using memory watch, the HP did not go down.
The memory locations I was looking at were 0x0506 and earlier for the enemy HP. Not that it matters for this particular case, since it's so fun watching my ships play with the hit-detection and act like they're stabbed. I am not aiming for a 100% kills run, either.
After frame 8400, I'm testing out Force. But I suggest starting at 8000, since that's where I stopped the last WIP.
It's fun! Imagine the sort of tricks on your eyes I can play with it! After the movie ends, you get to see what Force normally looks like. But we don't want plain, boring Force, do we?
That big, bunch of nothing happening at the end is... Well, I just haven't figured out what to fill it with, yet. I'm sure I can give that fireball a mind of its own though, rather than keep that "I'm blowing up" pattern continuously.
I'm thinking about this run again...
Because I want to catch all secrets, I thought I'd craft up a lua script whose only job is to paste an "x" where there are things. I took a look at Dromiceius's code (the one made to help with enjoying my Magician run), and decided to work off of that to create something simple.
... So I treat some variables as an array of one element. It works, and I'm a tad worried about experimenting too much. The loop overwrites the variable before using it anyway. ... Okay, so I don't even rename the variables. I'm sure there's lots of stuff to make fun of.
--Salamander (J), places an x where stuff exists, no questions asked.
local ex, ey, eh = {}, {}, {}
function readword(a, b)
return memory.readbyte(a) + (memory.readbyte(b or a+1)*256)
end
while true do
for i=0, 15 do
ex[0]=memory.readbyte(0x035f+i)
ey[0]=memory.readbyte(0x033a+i)
eh[0]=memory.readbyte(0x042b+i) -- If non-zero, it probably exists.
if ex[0] > 0 and ex[0] < 248 and ey[0] > 0 and ey[0] < 223 and eh[0] > 0 then
gui.text(ex[0],ey[0],"x")
end
end
FCEU.frameadvance()
end
I suppose this is my first lua script... Perhaps a breakthrough for me.
Some oddly placed "x"s show up. Some have something to do with the transforming terrain, but sure enough...
... There's one at the top part, where the point bonus is described. The "x" shows up right there, alright, and flying there does give 5000 points. The bottom area has no such bonus, in case you're curious.
I missed this bonus in my run. At least this game appears very friendly to input editing. As long as you match up the exact position, sub-position, and power-ups, things should be fine, unless some enemies are seeking the other player instead. Besides, there are some "lazy" parts that should be fixed up anyway. Notably, the two claws right after that missed secret.
But first, I really should complete the input all the way through the first stage. I'm still wishing I had multi-track recording, but I'll run with one player and manually edit in the other player...
As I said, I am thinking about this run again. I'm just frustrated at how hours/days of work only pays off with 30 or so seconds of game time. It's as though everything here demands high precision the entire time... With two players. Worse yet, I may have to redo that last piece. I hated thinking about that fact while trying it out, because it means I spent hours (Yes, I mean hours) on that last bit of regenerating gunk, only to throw it away.
I don't mean to spoil the mood. It's a fair bit of precision carving I've been doing, and hopefully it will prove to be entertaining. Few would know just how to direct the regenerating gunk just right...
I put in subtitles pointing out things I want to change...
1st message: The GO I wanted to display is... Almost invisible. I'll likely try dancing differently at that spot.
2nd message: I miss the bonus like I say in the subtitle. Predict what the change will be!
3rd message: You know, I was lazy here. I really could have played with those claws, but no... I think I should change that.
4th message: Latest addition. I wasted a LOT of time after this subtitle shows up, like entire seconds, just to prove what sort of design I can make.
Well, okay. As an auto-scroller, I can't actually "waste" any time other than lag, but I could easily have danced using those seconds I wasted. And in a TAS, don't we need perfection?
I would like help. I'm not sure what sort of help I need, but without any of it... Compare the times between my last post and this one. I've been spending a fair amount of that time only to produce a small piece. Projected completion time based off that is at least years. I don't want that. Besides that, take a look at the rerecord count.
Again, I'm not sure what sort of help I need. Maybe a script that lets me know what directions I can take without blowing up on the terrain would be a start. I don't have many useful addresses, but if you need me to find something, I'll go look.
If not, I'll just temporarily abandon this project in favor of creating a few short clips of what I envision what this run should be. At least everything up to those parts wouldn't matter, as long as I have the power-ups I need.
We can do multi-track recording with Lua, but it's a bit crude. Basically, the script loads p1's inputs into memory, and then feeds them back into the emulator as you record player 2's inputs. You'll want to back up your movie before trying this.
It's lazy of me not to test it better, but I'm pretty sure it works. You'll need to modify the script to point to a copy of your WIP. Also note that it starts paused.
Script
...Waitaminute, didn't the windows build of FCEUX already have this feature?
Can't say I've succeeded at discovering tile or collision data in RAM before, though it would be indispensable for some bots I've been meaning to write. I've already got my own set of memory search functions, so I may conjure up a custom function to detect the memory structure(s) we're interested in. That should be interesting, if not altogether useful.
Other than that, I'm not sure what sorts of problems you're facing in your recording. I could write a random input bot to traverse the level without being killed- which would be boring, and useless for TASing- or possibly something more apropos of some specific challenge, if you have any ideas.
I'm not aware of this. I've looked through a few things, but never saw anything about it. Since I apparently can't find this, I probably would need to be pointed exactly to where it is.
Some terrain in Salamander isn't a constant, apparently. You can shoot some terrain, others just grows in, and there's plenty of constant terrain about.
In any case, I went into the Hex Editor just now and eyeballed some curious looking addresses. In the PPU Memory, I'm curious about 0x2080 and a few hundred locations after it... Very curious. Curiosity went up a bit more when I spot things changing a bit more rapidly while my ships were digging through the various terrain. Like, zeroes were popping up as some terrain got shot into pure blackness. There aren't many of those zeroes in parts where there are no black tiles.
Things got extremely curious when I overwrote a few values in those places. Like, the terrain suddenly changes. At a particular spot on the screen. Just to make sure, I piloted a ship at the spot that transformed. Clearly, by setting it to 0x00, I didn't remove the collision, merely the graphical tile used at the spot. Might be useful, but...
I took one more look. Another curious spot is, in the NES Memory, locations 0x6000 to 0x61E9. I think this is our collision detection. Each tile is packed in two-bit chunks. It does not "scroll" with the screen. Here's what I observe:
00 - Open space
01 - Solid wall
10 - Destructible (1 HP)
11 - Destructible (2 HP)
At least, that's basically what I think... May be worth screwing around with this to confirm whether or not I'm right...
Yes, I eyeballed this just looking in the Hex Editor. Which makes confirming this all the more important, as we can't openly trust intuition straight up.
Er, what is PPU Memory and how is it different from NES Memory? I'm guessing primarily graphical stuff happens in the PPU Memory...?
Ah. All I remember is that it was in some version of FCEU. Odd that it wouldn't be ported, but oh well. If you try the script, let me know how it goes.
Well, I overwrote the entire 0x6000 0x61E9 region with zeroes, and couldn't hit the terrain anywhere in the level, including the brain at the end. Setting it to 1 would logically make every 4th tile deadly, and sure enough, I can keep the ship in a tiny invisible column of safety before being crushed against the side of the screen. Your findings seem to be correct.
for i = 0, 100 do FCEU.frameadvance() end --avoid messing up the boot sequence
while true do
for i = 0, 0x1e9 do
memory.writebyte(0x6000+i, 1)
memory.writebyte(0x2080+i, i) --lol.
end
FCEU.frameadvance()
end
The PPU is the Picture Processing Unit. It's just a separate chip to offload graphics processing.
The next piece of fun coding to do is to multiply each byte by 2, OR it with the original value, and AND it with 0xAA every frame. All terrain should be shot away with one shot, while the open space remains open... Theoretically. But putting in destructible terrain where there shouldn't be any... How will the game react? Probably normally, just with more destructive bullets than you thought possible.
There seems to be some spots within the range 6000 to 61E9 that aren't used. Or at least, not by the terrain. It also seems to switch between two sets of addresses, both within the range I specify. 0x6028 to 0x60EF, and 0x6128 to 0x61EF. On the other hand... There's the top-down view. That needs more width. In which case, it uses a larger range from 0x6000 to 0x60EF and 0x6100 to 0x61EF.
We might want these, too. You know, just in case we want to draw our boxes:
0x0043 - Stage sub-position
0x0044 - Stage position
0x0045 - Stage position * 256
0x0041 - 0 = side view 1 = top-down view ... I think...
0x035C - 1P X-pos 0x0064 - 1P subX
0x0337 - 1P Y-pos 0x0062 - 1P subY
0x035D - 2P X-pos 0x0065 - 2P subX
0x0338 - 2P Y-pos 0x0063 - 2P subY
0x0070 - 1P speed Each speed up is +1/4 pixel/frame
0x0071 - 2P speed At 0 speed, movement at 5/4 px/fr
Alright, so we have the arrays for the terrain, which we merely need to look at for a bit in order to align things correctly. We have the stage position. We might be able to draw neat little boxes that are accurately placed. I think we have side/top view states so we don't mix up the boxes. And if ever you want to mess around with the players, my intuition says that knowing their positions and speed are mandatory.
On a side note, I decided to skip ahead a little and pick up three Options to see what I can do with 'em. It's amazing how much you can do with 10 onscreen bullets at a time, and a bit easier than I thought it would be. I have a habit of spoiling things... In any case, this is a moment that I'm glad for editing in the input with a text editor.
LMAO. Yeah, it does pretty much what you'd expect. Works on those things that grow out of the walls, too.
Well, 0x6000 -> 0x6028 have no apparent effect, while 0x6029 -> 0x6064 are the top row, so that all makes sense. I assume that second bank of addresses is related to paging in upcoming terrain, since the entire first level would have to be stored in about 0x1300 bytes, while 0x6028 to 0x60EF is only 0xC7. I haven't watched the regions, though. FCEUX is beginning to misbehave.
I imagine that the brain boss is also affected by the terrain transformation. For once, you might be able to shoot down pieces of the silly boss before it becomes "vulnerable". Though, now that I think about it, I recall in the USA version, Life Force that the second boss's central region does not have any hit-detection at all. The "arms" are still painful, but it's like it failed to load up the collision data for the terrain or something. The JPN version, Salamander has it properly loaded.
I might be wrong about the top-down scrollers taking up 0x6100 to 0x61EF. That array appears to be unused in those stages.
As far as I can tell:
0x6028 to 0x60EF and 0x6128 to 0x61EF for side-scrollers.
0x6000 to 0x60EF for top-down scrollers.
I think this little chat did help. I feel much more optimistic about things now. It'll certainly make things easier when I don't feel things are going nowhere. All that work ahead of me? Not so intimidating now. Might change once I start on it again, but I feel fine now.
I'm starting to get deeper into lua scripting. I have successfully created an array of dots that scroll along with the screen. Problem is, the dots have no significance, and will utterly fail to look good in stages 2, 4, and 6. Point is, I'm farther in lua scripts than before. I'll try creating a script that dots out where the terrain is. I'd like the practice.
It's a really fun language for the most part, not to mention useful for general purposes.
If you don't already have them, you'll want the manual and the emulua doc handy. I also recommend Programming in Lua. Chapters 1-5, 7 and 11 are pretty much all you need to get started.
--Salamander (J), draws a single green pixel where there exists a wall.
--FatRatKnight
local sp, temp, addr, nx, ny = {}, {}, {}, {}, {}
function getwall(x, y) -- Expects input by tile, not by pixel
-- Function reads the target address. Silly numbers are clipped to within range.
addr = 0x6000
nx = x%64
ny = y%30
if nx > 31 then -- horizontal scroll uses two different arrays
nx = nx - 32
addr = addr + 0x100
end
return AND( 3 * 4^(nx%4) , memory.readbyte(addr + math.floor( nx/4 ) + ny*8) )/4^(nx%4)
-- Bitmask Calculate Address Location rightshift
end
while true do
for x=0, 31 do
for y=0, 24 do
if memory.readbyte(0x0041) == 0 then -- horizontal scrolling
sp = memory.readbyte(0x0044) + memory.readbyte(0x0045)*256
if getwall(math.floor((sp+4)/8) + x , y+4) ~= 0 then
temp = 7 - (( sp + 4 ) % 8)
gui.drawpixel(x*8+temp, y*8+4, "green")
end
elseif memory.readbyte(0x0041) == 1 then -- vertical scrolling
sp = memory.readbyte(0x0044) + memory.readbyte(0x0045)*240
if getwall( x , y - math.floor((sp+4)/8) ) ~= 0 then
temp = ( sp + 4 ) % 8
gui.drawpixel(x*8+4, y*8+temp, "green")
end
end -- if; horizontal/vertical scrolling
end -- y-loop
end -- x-loop
FCEU.frameadvance()
end
I believe this will dot up all walls successfully, until bosses show up and start scrolling around themselves. Some dots are hard to see, but at least we can recognize walls and where they are. I'm pretty sure the getwall function I made should work perfectly in other things besides drawing dots, though it lets the caller handle the stage position stuff.
Though, I got a surprise when the vertical scrolling segments has address 0x0044 go to 239 instead of 255. However, I spotted that and... Yep. Those dots aren't sliding out of their spots now.
Where's my shift operators and the ability to put single statements over multiple lines? Yeah, I'm just more used to C code. Lua feels... Unclean, somehow. But as is said in some places, it's not too hard to transition to lua if you know some programming. Then again, there's probably a few things that aren't "optimal" coding with my lack of experience in lua. Especially the variables.
I haven't experimented or searched enough to understand if it's possible to stuff local variables that only the function itself can see, or if it can affect whatever variables passed to it from the caller's point of view. It... Works, and is therefore passable, but it certainly screams for improvement.
Drawing boxes shouldn't be hard to implement, hopefully. Checking player's position to see if it would overlap with a wall would be a neat trick to do.
Lua does scope locality with the "local" keyword. You don't have to declare everything at the top like you do in C. More importantly, declaring "sp = {}" makes sp an object of type table rather than a scalar variable. You can delete that "local sp, temp..." line altogether. Also, using 'local' when instantiating a variable is good practice.
There are, in fact, no bitwise operators. Lua itself doesn't even have AND, OR, etc. DeHackEd added those to Snes9x himself, and it wouldn't be difficult to add shift functions.
You can use semicolons to put multiple statements on one line... possibly with some caveats.
As for the "smell" of the code, most of the script is bit-twiddling, which is necessarily going to be ugly, so I don't see any possible refactorings.
If you've found where the game stores hitbox coordinates, a call to gui.drawbox() is all you need, IIRC.
It's simple enough to shift stuff around with 2^n, multiplying or dividing for whatever the case may be. Just a few more characters I have to type. I can understand why there are no bitwise operators for lua alone, since it doesn't use things like integers, preferring to instead exclusively use double precision floating point.
It seems to be a language less for things that needs to work with individual bits and more for just working with numbers in general. Unfortunately, manipulating bits is often a concern when dealing with quite a few games, which makes me think lua isn't the ideal language, but the bitwise functions that were added is proof enough that we can change the language a bit to fit our needs.
But I was thinking about putting a single statement over multiple lines! That's certainly has some difference from putting multiple statements in a single line.
Hmm... Haven't found the hitboxes. As far as terrain is considered, your ship is an infinitely small point, checking only its location to see if it overlaps with the terrain. Something clunky like a box? Nope. Which is how I'm able to fit in some tight spots, and thus draw such neat designs in my WIP. The game does use actual boxes when concerning enemies.
But different size hitboxes must exist. There are tiny bullets, decent-sized enemies, and those huge fangs. Therefore, there should be a spot in memory which tells us how big they are. The player ships also seem to have their own hitbox, but again, those particular boxes are definitely ignored on terrain.
I was thinking about drawing 8x8 squares where there are solid wall tiles. An improvement over hard-to-see pixels. But that's a fairly trivial change. That's kind of what I'm talking about when I was thinking about boxes. Definitely trivial.