IST
Joined: 8/26/2008
Posts: 103
Cave Story is being ported to the Wii with additional content, so eventually a TAS for it will happen. :D
Senior Moderator
Joined: 8/4/2005
Posts: 5770
Location: Away
This is about third (1, 2) topic for this game, if I'm not missing anything. Isn't it the time we merge them already? OmnipotentEntity: Be optimistic.
Warp wrote:
Edit: I think I understand now: It's my avatar, isn't it? It makes me look angry.
upthorn
He/Him
Emulator Coder, Active player (388)
Joined: 3/24/2006
Posts: 1802
moozooh wrote:
This is about third (1, 2) topic for this game, if I'm not missing anything. Isn't it the time we merge them already?
I don't know. The first two are definitely worth merging, but this topic is different. It started out not a "hey, you should know about this game" but as more of a "let's plan a TAS!" And at this point it is more of a "windows game wishlist".
How fleeting are all human passions compared with the massive continuity of ducks.
Emulator Coder, Skilled player (1300)
Joined: 12/21/2004
Posts: 2687
Iji is pretty cool too. There's a nice trailer for it here. It's kind of underwhelming at first, but it really escalates. About Cave Story, I've been wondering, what exactly would an any% run get? The machinegun is obvious, that thing has tons of potential to save time especially in a speedrun/TAS setting. I'm not sure about the missiles... they're quite strong when powered up but they might not make up the time overall compared to skipping the missiles (and sword spamming instead). Similarly, health pickups could save time, but they take long enough to get (and enough enemies do damage you can survive with only 3 HP) that it might be faster to ignore them all.
Senior Moderator
Joined: 8/4/2005
Posts: 5770
Location: Away
I keep thinking that Snake is the only non-mandatory weapon that actually saves any time. As for health upgrades, they're probably only worth it if they're directly on your way. Taking each of them takes what, 5 seconds? No way a meager increase in HP is going to save that much every time.
Warp wrote:
Edit: I think I understand now: It's my avatar, isn't it? It makes me look angry.
Emulator Coder, Skilled player (1300)
Joined: 12/21/2004
Posts: 2687
I really doubt Snake could save more time overall than the machinegun, which allows at least the following timesavers: - Flying before getting the booster, so you can take much more direct routes and/or bypass waiting in several places - Falling extra-fast - Higher-precision control over jumps - Faster horizontal travel through water in some places (by not touching the ground) - Trajectory changes with the booster that are otherwise impossible (for faster and more fluid movement) - A water current track-changing shortcut or two - Two shortcuts through otherwise one-way air currents (that I can remember) The Snake is more out of the way as well, and being able to shoot through walls only helps in a select few places that I know of. Even if it saves a lot of time in those places I don't think it compares.
Senior Moderator
Joined: 8/4/2005
Posts: 5770
Location: Away
Wait, doesn't machinegun prevent the best ending? Or am I confusing something?
Warp wrote:
Edit: I think I understand now: It's my avatar, isn't it? It makes me look angry.
Emulator Coder, Skilled player (1300)
Joined: 12/21/2004
Posts: 2687
moozooh wrote:
Wait, doesn't machinegun prevent the best ending?
Nope, you can beat Ballos while in possession of the machinegun.
Joined: 7/2/2007
Posts: 3960
You have four options for one of your weapon slots: * Polar Star (starting weapon, sucks) * Machinegun (lets you fly, first available replacement) * Snake (necessary for maximum-speed runs through Hell, otherwise dubious) * Spur (last available replacement, chargeable for more dakka) However, they have no bearing on the ending you get. To get to Hell, you have to skip Booster and save Curly; skipping Booster is in fact quite easy if you have the machinegun, and saving Curly doesn't require anything special. As for the missiles, when upgraded they have the best damage output of any weapon, bar none. And given that several of the later bosses have invincibility periods (c.f. Undead Core, Ballos (in ball form when jumping, practically you can't get more than one shot in)), you'll want to be dealing as much damage as possible when they are vulnerable. So I think it's worth grabbing one missile pack so you can upgrade them, then grabbing the megapack in Hell. For Undead Core, you can fire off the 5 missiles you'll have, then reload off all the little enemies. Though, for this hypothetical TAS, it'd be worth comparing the upgrading missiles to the level 2 Sword, which has some pretty fantastic damage potential if you get in the enemy's face.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Player (67)
Joined: 3/11/2004
Posts: 1058
Location: Reykjaví­k, Ísland
In my experience when I was making a semi-crappy speedrun (which has since been bested by someone else), I determined that the missles, and in fact all non-essential guns, are just a waste of time. You can annihilate anything with level 1 sword extremely fast. You can't fire another sword until the current one is gone, but if you are "inside" the boss, or close enough, it'll hit instantly and your firing rate is only determined by the rate at which you can press the button. Boss = very dead. In fact, in a TAS, you'll probably be wasting bosses in less than a second using the sword. Also, if you don't have missles, no missle pickups appear, so you gain more xp and life.
Lex
Joined: 6/25/2007
Posts: 732
Location: Vancouver, British Columbia, Canada
If Cave Story was reverse-engineered and had TAS features added, could it be accepted alongside the emulators as a viable TAS platform, even though it's one which only plays one game? My argument for this would be that it'd be an executable just like snes9x or fceux with reproducible input video playback. This assumes it would meet all the requirements listed on http://tasvideos.org/EmulatorResources/Requirements.html (excepting those disputed by Nach in the comment). I guess the main problem here would be gaining legal rights etc.
upthorn
He/Him
Emulator Coder, Active player (388)
Joined: 3/24/2006
Posts: 1802
I think this would be a very bad paradigm to set. It would be much better to work on a more general TASing solution for PC games. And, indeed, there are already multiple projects underway to accomplish this.
How fleeting are all human passions compared with the massive continuity of ducks.
Lex
Joined: 6/25/2007
Posts: 732
Location: Vancouver, British Columbia, Canada
What projects? I've only heard of the deterministic JPC project in the other thread, and that was really cloudy.
upthorn
He/Him
Emulator Coder, Active player (388)
Joined: 3/24/2006
Posts: 1802
Well, the Universal TAS VM project, of course, and this one which has been in the works since spring but I just announced today.
How fleeting are all human passions compared with the massive continuity of ducks.
Joined: 5/2/2009
Posts: 656
upthorn wrote:
Well, the Universal TAS VM project, of course, and this one which has been in the works since spring but I just announced today.
Most of the "Hourglass"' demo is Cave Story's Egg Corridor. Is there an actual TAS in the works, for demonstrate the project?
My first language is not English, so please excuse myself if I write something wrong. I'll do my best do write as cleary as I can, so cope with me here =) (ノಥ益ಥ)ノ
Active player (308)
Joined: 2/28/2006
Posts: 2275
Location: Milky Way -> Earth -> Brazil
nitsuja wrote:
Iji is pretty cool too. There's a nice trailer for it here. It's kind of underwhelming at first, but it really escalates.
Dude, that crap really needs to escalate a lot. I played it for a few minutes and I didn't know if I laughed at it or cursed you for making it available to me... hehehe It's some sort of a mix of Metroid Zero Mission and Alien 3, but with I-wish-I-was-vectorial bad graphics. Plus, it wouldn't be a bad enough game if it accepted controllers or had running ability...
"Genuine self-esteem, however, consists not of causeless feelings, but of certain knowledge about yourself. It rests on the conviction that you — by your choices, effort and actions — have made yourself into the kind of person able to deal with reality. It is the conviction — based on the evidence of your own volitional functioning — that you are fundamentally able to succeed in life and, therefore, are deserving of that success." - Onkar Ghate
Bisqwit wrote:
Drama, too long, didn't read, lol.
Joined: 7/2/2007
Posts: 3960
Mostly you play Iji for the writing. The actual gameplay is competent, but it is pretty slow.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Emulator Coder, Skilled player (1300)
Joined: 12/21/2004
Posts: 2687
It gets quite chaotic, just not anywhere near the start. It takes way more than a few minutes for that to happen (unless you're seriously speedrunning it). The graphics are pretty bad though. I've convinced myself not to care when a game has bad graphics, although I still wonder why in the world someone wouldn't put more effort into that aspect of their game.
Joined: 7/2/2007
Posts: 3960
Generally they put as much effort as they can into the graphics, and what determines how good it looks from there is skill. Videogame graphics are not easy to make! I played Iji after watching DeceasedCrab's Let's Play of it. My first runthrough was pacifist on the normal difficulty setting, and I think I might have died...twice? Of course, I had to abort many more times due to accidentally killing enemies...generally by kicking a turret head into them. Stupid turrets.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
juef
He/Him
Player (131)
Joined: 1/29/2007
Posts: 205
Location: Québec, Canada
I just heard the WiiWare version is out! Anybody has tried it yet?
Player (36)
Joined: 9/11/2004
Posts: 2623
I have it running on Dolphin right now. :O
Build a man a fire, warm him for a day, Set a man on fire, warm him for the rest of his life.
Player (36)
Joined: 9/11/2004
Posts: 2623
That being said, recording is not working at all.
Build a man a fire, warm him for a day, Set a man on fire, warm him for the rest of his life.
Joined: 1/3/2010
Posts: 16
upthorn wrote:
I Wanna Be The Guy
I tried that.. Well not a real tas, but a script.. It uses pixel-color detection to know where the guy is at each given time. I made this video as proof that it's possible, however it would take a lot of work; which it's not worth to me.. http://www.youtube.com/watch?v=G98KqfYVqP4 The code for this simple vid was:
program IWBTG;
const
  frm = 20;
  chk = 10;
  dbg = true;
  
procedure pressKey(id : Integer);
begin
  KeyDown(id);
  wait(frm);
  KeyUp(id);
end;

procedure waitUntilColor(x, y, color : Integer);
begin
  status('Scanning');
  repeat
    wait(chk);
  until (getColor(x, y) = color);
  status('Waiting');
end;

function GetCurrentTime : String;
var
  t, h, m, s : Integer;
begin
  t := getTimeRunning();
  h := t / 3600000;
  m := t / 60000 - h * 60;
  s := t / 1000 - m * 60;
  t := t - s * 1000;
  Result := '(' + IntToStr(h) + ':' + IntToStr(m) + ':' + IntToStr(s) + ',' +
            IntToStr(t) + ') ';
end;

procedure report(text : String);
begin
  AddToReport(GetCurrentTime + text);
  writeln('---');
end;

procedure debug(text : String);
begin
  if dbg then
    writeln(GetCurrentTime + text);
end;

procedure walkTo(x, y, id : Integer);
begin
  status('Scanning');
  KeyDown(id);
  waitUntilColor(x, y, 8);
  KeyUp(id);
  status('Waiting');
end;

procedure setup;
begin
  disguise('IWBTG Completer - By CX');
  clearDebug();
  clearReport();
  ChangeReportWidth(300);
  activateClient();
end;

procedure menu;
begin
  report('Navigating menu');
  pressKey(113);
  debug('F2 - New game');
  waitUntilColor(593, 422, 12437049);
  pressKey(16);
  debug('Shift - Skip Intro');
  waitUntilColor(526, 166, 65931);
  pressKey(16);
  debug('Shift - Start');
  waitUntilColor(416, 475, 9868950);
  pressKey(39);
  debug('Right - Second save');
  waitUntilColor(393, 477, 10066329);
  pressKey(16);
  wait(frm);
  debug('Shift - Select save');
  waitUntilColor(355, 209, 26294);
  pressKey(40);
  debug('Down - New Game');
  waitUntilColor(332, 240, 16777215);
  pressKey(39);
  debug('Right - Very Hard');
  waitUntilColor(443, 258, 6731519);
  pressKey(39);
  debug('Right - Impossible');
  waitUntilColor(389, 265, 11993014);
  pressKey(16);
  debug('Shift - Select');
end;

procedure part1;
begin
  report('Started gameplay');
  debug('Wait - touching ground');
  waitUntilColor(168, 89, 8);
  KeyDown(39);
  KeyDown(16);
  debug('Jump right - upper path');
  wait(300);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - upper path');
  report('Cherry valley');
  wait(200);
  KeyUp(16);
  waitUntilColor(240, 570, 8);
  KeyUp(39);
  debug('Wait - falling cherry');
  wait(260);              // tw
  debug('Right');
  walkTo(357, 570, 39);
  wait(frm);
  debug('Left - falling cherries');
  walkTo(333, 570, 37);
  debug('Wait - falling cherries');
  wait(200);          // tw
  debug('Right');
  walkTo(466, 570, 39);
  debug('Wait - falling cherries');
  wait(240);          // tw
  debug('Right');
  walkTo(670, 570, 39);
  wait(frm);
  KeyDown(37);
  debug('Left - falling cherry');
  wait(2 * frm);
  KeyUp(37);
  debug('Wait - falling cherry');
  wait(200);          // tw
  wait(frm);
  KeyDown(39);
  KeyDown(16);
  debug('Jump right - onto steps');
  waitUntilColor(750, 506, 8);
  KeyUp(39);
  keyUp(16);
  debug('Left - positioning for jump');
  walkTo(732, 506, 37);
  KeyDown(16);
  debug('Jump - try to get cherry');
  waitUntilColor(734, 400, 8);
  KeyUp(16);
  KeyDown(39);
  debug('Right - lure cherry');
  wait(frm);
  KeyUp(39);
  KeyDown(16);
  debug('Double jump wait - levitating cherry');
  wait(200);          // tw
  KeyDown(39);
  debug('Right - on 1st platform');
  waitUntilColor(733, 354, 8);
  KeyUp(16);
  KeyUp(39);
  wait(frm);
  waitUntilColor(739, 379, 1973790);
  KeyDown(37);
  KeyDown(16);
  debug('Jump left - on 2nd platform');
  wait(frm);
  KeyUp(16);
  waitUntilColor(660, 346, 8);
  KeyUp(37);
  debug('Wait - cherry');
  wait(140);           // tw
  KeyDown(37);
  KeyDown(16);
  debug('Jump left - on 3rd platform');
  wait(frm);
  KeyUp(16);
  waitUntilColor(545, 313, 8);
  KeyUp(37);
  wait(frm);
  KeyDown(37);
  KeyDown(16);
  wait(600);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - on 5th platform (skipping 4th)');
  waitUntilColor(325, 314, 8);
  KeyUp(16);
  waitUntilColor(292, 313, 8);
  KeyDown(16);
  debug('Jump - final ledge');
  wait(600);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump');
  waitUntilColor(70, 378, 8);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Jump - cloud screen');
  wait(400);
  KeyUp(16);
  report('Cloud room');
  waitUntilColor(766, 314, 8);
  wait(280);
  KeyDown(16);
  debug('Jump - 1st cloud');
  wait(200);
  KeyUp(16);
  waitUntilColor(593, 320, 8);
  KeyDown(16);
  debug('Jump - 2nd cloud');
  wait(400);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - 2nd cloud');
  wait(200);
  KeyUp(16);
  wait(600);
  KeyUp(37);
  wait(200);
  KeyDown(37);
  wait(50);
  KeyDown(16);
  debug('Jump left - 3rd cloud');
  wait(500);         // tw
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - 3rd cloud');
  wait(350);           // tw
  KeyUp(16);
  KeyUp(37);
  debug('Wait - hammer time');
  waitUntilColor(265, 265, 8);
  KeyDown(39);
  debug('Right - falling off');
  wait(120);
  KeyUp(39);
  wait(frm);
  KeyDown(37);
  debug('Left - 4th cloud');
  wait(520);
  KeyDown(16);
  debug('Double jump - 4th cloud');
  wait(200);
  KeyUp(16);
  wait(800);
  KeyUp(37);
  KeyDown(16);
  debug('Jump - ledge');
  wait(400);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - ledge');
  wait(350);
  KeyUp(16);
  KeyDown(39);
  debug('Right - ledge');
  wait(60);              // tw
  KeyUp(39);
  waitUntilColor(70, 250, 8);
  KeyDown(37);
  KeyDown(16);
  debug('Jump left - safety');
  wait(400);
  KeyUp(16);
  report('Invisible block room');
  waitUntilColor(745, 218, 8);
  KeyDown(16);
  debug('Jump - 1st block');
  wait(600);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - 1nd block');
  wait(200);
  KeyUp(16);
  waitUntilColor(515, 250, 8);
  KeyDown(16);
  debug('Jump - 2nd block');
  wait(600);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - 2nd block');
  wait(400);
  KeyUp(16);
  waitUntilColor(290, 250, 8);
  KeyDown(16);
  debug('Jump - ledge');
  wait(600);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - ledge');
  wait(400);
  KeyUp(16);
  wait(1000);
  report('Above the city');
  waitUntilColor(640, 250, 8);
  KeyDown(16);
  debug('Jump - 1st block');
  wait(200);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - 1st block');
  wait(50);
  KeyUp(16);
  waitUntilColor(482, 282, 8);
  KeyDown(16);
  debug('Jump - 2nd block');
  wait(600);
  KeyUp(16);
  waitUntilColor(355, 282, 8);
  KeyDown(16);
  debug('Jump - 3rd block');
  wait(500);
  KeyUp(16);
  waitUntilColor(255, 218, 8);
  KeyDown(16);
  debug('Jump - 4rd block');
  wait(200);
  KeyUp(16);
  waitUntilColor(166, 186, 8);
  KeyDown(16);
  debug('Jump - 5rd block');
  wait(400);
  KeyUp(16);
  waitUntilColor(80, 121, 8);
  KeyUp(37);
  wait(frm);
  KeyDown(39);
  waitUntilColor(90, 122, 8);
  KeyDown(16);
  debug('Jump - 6th block');
  wait(600);
  KeyUp(16);
  //waitUntilColor(180, 56, 8);        // This needs to be fixed
  wait(100);                           // and this be removed
  KeyDown(16);
  debug('Jump - game over room');
  wait(400);
  KeyUp(16);
  report('Game over room');
  wait(frm);
  KeyDown(16);
  debug('Double jump - game over room');
  wait(400);
  KeyUp(16);
  waitUntilColor(336, 540, 9422847);
  KeyDown(16);
  debug('Jump - item grab');
  wait(500);
  KeyUp(16);
  waitUntilColor(4, 287, 3300019);
  report('Invisible block room');
  waitUntilColor(91, 249, 8);
  KeyDown(16);
  debug('Jump - 1st block');
  wait(600);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - 1st block');
  wait(200);
  KeyUp(16);
  waitUntilColor(318, 249, 8);
  KeyDown(16);
  debug('Jump - 2nd block');
  wait(600);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - 2nd block');
  wait(400);
  KeyUp(16);
  waitUntilColor(543, 249, 8);
  KeyDown(16);
  debug('Jump - ledge');
  wait(620);
  KeyUp(16);
  wait(frm);
  KeyDown(16);
  debug('Double jump - ledge');
  wait(600);
  KeyUp(16);
  //waitUntilColor(542, 249, 8);

end;

begin
  setup;
  menu;
  //pressKey(82);
  part1;
end.
Emulator Coder, Skilled player (1300)
Joined: 12/21/2004
Posts: 2687
By the way, I don't know if this will work for everyone, but here's a RAM Watch file that might help for a Cave Story TAS:
0
9
00000	0049E66C	d	s	0	X velocity
00001	0049E670	d	s	0	Y velocity
00002	0049E654	d	u	0	X pos
00003	0049E658	d	s	0	Y pos
00004	0049E664	d	s	0	X cam offset
00005	0049E660	w	s	0	Y cam offset
00006	0049E6B0	w	h	0	flags
00007	0049E6CC	w	s	0	health
00008	0049E1EC	d	u	0	framecounter
You should be able to save those into a .wch file and open it in the RAM Watch window in Hourglass. Watching the X velocity value, it seems that the character has a continuously oscillating speed when on the ground that locks to something in the air (like in SNES Mario games, I think), which can probably be abused by always jumping at good speed values to go slightly faster than normal.
Personman
Other
Joined: 4/20/2008
Posts: 465
How did you go about finding these memory locations? I would love to be able to monitor x and y positions in Ninja Senki, but I have no idea how to go about finding the right memory locations. Hourglass doesn't have a way to report everything that changed from one frame to another, does it? And if it did, it seems likely that it would be many more addresses than in say an NES game, due to being written in a high-level language with things like garbage collection going on...
A warb degombs the brangy. Your gitch zanks and leils the warb.